diff --git a/.github/workflows/dockerpublish.yml b/.github/workflows/dockerpublish.yml new file mode 100644 index 0000000..21b91b8 --- /dev/null +++ b/.github/workflows/dockerpublish.yml @@ -0,0 +1,41 @@ +name: Publish to Docker Registry Manual +on: + workflow_dispatch: + +jobs: + build_docker_and_publish: + runs-on: ubuntu-latest + steps: + + - name: Clone repository + uses: actions/checkout@v2 + + - name: Read version from release.json + uses: notiz-dev/github-action-json-property@release + id: xteve_version + with: + path: 'release.json' + prop_path: 'version' + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + with: + image: tonistiigi/binfmt:latest + platforms: arm64,arm + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: . + platforms: linux/amd64,linux/arm64,linux/arm/v7 + push: true + tags: ${{ secrets.DOCKER_USERNAME }}/xteve:latest,${{ secrets.DOCKER_USERNAME }}/xteve:${{ steps.xteve_version.outputs.prop }} \ No newline at end of file diff --git a/.github/workflows/xTeVe_release.yml b/.github/workflows/xTeVe_release.yml new file mode 100644 index 0000000..4de1b55 --- /dev/null +++ b/.github/workflows/xTeVe_release.yml @@ -0,0 +1,86 @@ +name: xTeVe release manual +on: + workflow_dispatch: + release: + types: [created] + +permissions: + contents: read + +jobs: + build_xteve_and_publish: + permissions: + contents: write + name: build_xteve + runs-on: ubuntu-latest + strategy: + matrix: + # build and publish in parallel: linux/386, linux/amd64, linux/arm64, windows/386, windows/amd64, darwin/amd64, darwin/arm64 + goos: [linux, windows, darwin] + goarch: ["386", amd64, arm64] + exclude: + - goarch: "386" + goos: darwin + - goarch: arm64 + goos: windows + steps: + - uses: actions/checkout@v3 + + - name: Read version from release.json + uses: notiz-dev/github-action-json-property@release + id: xteve_version + with: + path: 'release.json' + prop_path: 'version' + + - name: Set BUILD_TIME env + run: echo BUILD_TIME=$(date -u +%Y%m%d-%H%M) >> ${GITHUB_ENV} + + - uses: wangyoucao577/go-release-action@v1.30 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + goos: ${{ matrix.goos }} + goarch: ${{ matrix.goarch }} + overwrite: true + extra_files: LICENSE README.md + release_tag: v${{steps.xteve_version.outputs.prop}} + binary_name: xteve + build_flags: -v + ldflags: -X "main.appVersion=${{ steps.xteve_version.outputs.prop }}" -X "main.buildTime=${{ env.BUILD_TIME }}" -X main.gitCommit=${{ github.sha }} -X main.gitRef=${{ github.ref }} + + build_docker_and_publish: + runs-on: ubuntu-latest + steps: + + - name: Clone repository + uses: actions/checkout@v2 + + - name: Read version from release.json + uses: notiz-dev/github-action-json-property@release + id: xteve_version + with: + path: 'release.json' + prop_path: 'version' + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + with: + image: tonistiigi/binfmt:latest + platforms: arm64,arm + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: . + platforms: linux/amd64,linux/arm64,linux/arm/v7 + push: true + tags: ${{ secrets.DOCKER_USERNAME }}/xteve:latest,${{ secrets.DOCKER_USERNAME }}/xteve:${{ steps.xteve_version.outputs.prop }} diff --git a/.gitignore b/.gitignore index 8d7b0a2..65132d9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,12 @@ .DS_Store -demo -dev -compiler -files -update_xteve*.sh xteve xteve.exe -de.json \ No newline at end of file +de.json +parts/ +prime/ +stage/ +xteve*.snap +html/js/ +/.idea/* +.xteve/ +__debug_bin diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d5177f9 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceRoot}", + "env": {}, + "args": [] + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..ce848a7 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,51 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Update Version", + "type": "shell", + "command": "./update_version.sh", + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "type": "typescript", + "tsconfig": "ts/tsconfig.json", + "problemMatcher": [ + "$tsc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "label": "tsc build" + }, + { + "label": "Build webUI", + "type": "shell", + "command": "test -f './xteve' && ./xteve -buildwebui", + "presentation": { + "reveal": "always", + "panel": "new" + }, + "dependsOn": [ + "Update Version", + "tsc build" + ] + }, + { + "label": "Build xTeVe", + "type": "shell", + "command": "go build xteve.go", + "group": { + "kind": "build", + "isDefault": true + }, + "dependsOn": [ + "Build webUI" + ] + } + ] +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..be7b016 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,95 @@ +# First stage. Building a binary +# ----------------------------------------------------------------------------- + +# Base image for builder is debian 11 with golang 1.18+ pre-installed +FROM --platform=$BUILDPLATFORM golang:bullseye AS builder + +# Download the source code +# Uncomment the below line to force git pull (no cache) +#ADD "https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h" skipcache +RUN git clone https://github.com/SenexCrenshaw/xTeVe.git /src +WORKDIR /src + +ARG TARGETOS TARGETARCH +# Install dependencies +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go mod download + +# Compile +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build xteve.go + +# Second stage. Creating an image +# ----------------------------------------------------------------------------- +FROM alpine:latest + +ARG BUILD_DATE +ARG VCS_REF +ARG XTEVE_PORT=34400 +ARG XTEVE_VERSION=2.5.1 + +LABEL org.opencontainers.image.created="{$BUILD_DATE}" \ + org.opencontainers.image.url="https://hub.docker.com/r/SenexCrenshaw/xteve/" \ + org.opencontainers.image.source="https://github.com/SenexCrenshaw/xTeVe" \ + org.opencontainers.image.version="{$XTEVE_VERSION}" \ + org.opencontainers.image.revision="{$VCS_REF}" \ + org.opencontainers.image.vendor="SenexCrenshaw" \ + org.opencontainers.image.title="xTeVe" \ + org.opencontainers.image.description="Dockerized fork of xTeVe by SenexCrenshaw" \ + org.opencontainers.image.authors="SenexCrenshaw SenexCrenshaw@gmail.com" + +ENV XTEVE_BIN=/home/xteve/bin +ENV XTEVE_CONF=/home/xteve/conf +ENV XTEVE_HOME=/home/xteve +ENV XTEVE_TEMP=/tmp/xteve + +# Add binary to PATH +ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$XTEVE_BIN + +# Set working directory +WORKDIR $XTEVE_HOME + +# Update package lists +RUN apk update +RUN apk upgrade + +# Install CA certificates +RUN apk add --no-cache ca-certificates +RUN apk add curl + +# Timezone (TZ) +RUN apk update && apk add --no-cache tzdata +ENV TZ=America/New_York +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# Add ffmpeg and vlc +RUN apk add ffmpeg +RUN apk add vlc + +# Creat bin dir +RUN mkdir $XTEVE_BIN + +# Copy built binary from builder image +COPY --from=builder [ "/src/xteve", "${XTEVE_BIN}/" ] + +# Set binary permissions +RUN chmod +rx $XTEVE_BIN/xteve + +# Create XML cache directory +RUN mkdir $XTEVE_HOME/cache + +# Create working directories for xTeVe +RUN mkdir $XTEVE_CONF +RUN chmod a+rwX $XTEVE_CONF +RUN mkdir $XTEVE_TEMP +RUN chmod a+rwX $XTEVE_TEMP + +RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2 + +# Configure container volume mappings +VOLUME $XTEVE_CONF +VOLUME $XTEVE_TEMP + +# Expose Port +EXPOSE 34400 + +# Run the xTeVe executable +ENTRYPOINT ${XTEVE_BIN}/xteve -port=${XTEVE_PORT} -config=${XTEVE_CONF} diff --git a/LICENSE b/LICENSE index 622e181..d250dac 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ MIT License Copyright (c) 2019 marmei@xteve-project +Copyright (c) 2022 senexcrenshaw Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README-DEV.md b/README-DEV.md deleted file mode 100644 index 4882217..0000000 --- a/README-DEV.md +++ /dev/null @@ -1 +0,0 @@ -# Information for the developers will come soon \ No newline at end of file diff --git a/README.md b/README.md index 51dec72..d496684 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,38 @@
- xTeVe + xTeVe

# xTeVe -## M3U Proxy for Plex DVR and Emby Live TV. -Documentation for setup and configuration is [here](https://github.com/xteve-project/xTeVe-Documentation/blob/master/en/configuration.md). +## M3U Proxy and EPG aggregator for Plex DVR and Emby Live TV -#### Donation -* **Bitcoin:** 1c1iCe4CJPfNUXtqxKBbW2Qd2EtqRPWme -![Bitcoin](html/img/BC-QR.jpg "Bitcoin - xTeVe") +### This is a fork of , all credit goes to the original author -## Requirements -### Plex -* Plex Media Server (1.11.1.4730 or newer) -* Plex Client with DVR support -* Plex Pass +Documentation for setup and configuration is [here](https://github.com/xteve-project/xTeVe-Documentation/blob/main/en/configuration.md). -### Emby -* Emby Server (3.5.3.0 or newer) -* Emby Client with Live-TV support -* Emby Premiere - ---- +--- ## Features -#### Files +### Files + * Merge external M3U files -* Merge external XMLTV files +* Merge external XMLTV files (EPG aggregation) * Automatic M3U and XMLTV update * M3U and XMLTV export #### Channel management + * Filtering streams +* Teleguide timeshift * Channel mapping * Channel order * Channel logos * Channel categories #### Streaming + * Buffer with HLS / M3U8 support * Re-streaming * Number of tuners adjustable @@ -48,112 +40,233 @@ Documentation for setup and configuration is [here](https://github.com/xteve-pro --- -## Downloads v2 | 64 Bit only -#### 64 Bit Intel / AMD +## Downloads -* [Windows](https://github.com/xteve-project/xTeVe-Downloads/blob/master/xteve_windows_amd64.zip?raw=true) -* [OS X](https://github.com/xteve-project/xTeVe-Downloads/blob/master/xteve_darwin_amd64.zip?raw=true) -* [Linux](https://github.com/xteve-project/xTeVe-Downloads/blob/master/xteve_linux_amd64.zip?raw=true) -* [FreeBSD](https://github.com/xteve-project/xTeVe-Downloads/blob/master/xteve_freebsd_amd64.zip?raw=true) +* See [releases page](https://github.com/senexcrenshaw/xTeVe/releases) -#### 64 Bit ARM -* [Linux](https://github.com/xteve-project/xTeVe-Downloads/blob/master/xteve_linux_arm64.zip?raw=true) +--- + +## TLS mode + +This mode can be enabled by ticking the checkbox in `Settings -> General`. -#### Recommended Docker Image (Linux 64 Bit) -Thanks to @alturismo and @LeeD for creating the Docker Images. +Unless the server's certificate and it's private key already exists in xTeVe config directory, xTeVe will generate a self-signed automatically. -**Created by alturismo:** -[xTeVe](https://hub.docker.com/r/alturismo/xteve) -[xTeVe / Guide2go](https://hub.docker.com/r/alturismo/xteve_guide2go) -[xTeVe / Guide2go / owi2plex](https://hub.docker.com/r/alturismo/xteve_g2g_owi) +Self-signed certificate will only allow TLS mode to start up but not to actually establish a secure connections. +For truly working HTTPS, you should [generate](https://gist.github.com/fntlnz/cf14feb5a46b2eda428e000157447309) a certificate by yourself and **also** add the CA certificate to the client-side certificate storage (where the web browser, Plex etc. is). -Including: -- Guide2go: XMLTV grabber for Schedules Direct -- owi2plex: XMLTV file grabber for Enigma receivers +Certificate and it's private key should be placed in xTeVe config directory like so: + +```text +/home/username/.xteve/certificates/xteve.crt +/home/username/.xteve/certificates/xteve.key +``` -**Created by LeeD:** -[xTeVe / Guide2go / Zap2XML](https://hub.docker.com/r/dnsforge/xteve) +If the certificate is signed by a certificate authority (CA), it should be the concatenation of the server's certificate, any intermediates, and the CA's certificate. -Including: -- Guide2go: XMLTV grabber for Schedules Direct -- Zap2XML: Perl based zap2it XMLTV grabber -- Bash: A Unix / Linux shell -- Crond: Daemon to execute scheduled commands -- Perl: Programming language +This will also enable copy to clipboad by clicking the green links at the header. (DVR IP,M3U URL,XEPG URL) --- +## Docker + +Supported OS/ARCH: + +* linux/amd64 +* linux/arm64 +* linux/arm/v7 + +### Get an image + +Pull from dockerhub: + +```sh +docker pull senexcrenshaw/xteve:latest +``` + +**OR** build your own image based on Dockerfile from this repository: + +```sh +git clone https://github.com/SenexCrenshaw/xTeVe.git +cd xTeVe +docker build --tag senexcrenshaw/xteve . +``` + +### Create a container + +```sh +docker create \ + --tty \ + --publish 34400:34400 \ + --name xteve \ + senexcrenshaw/xteve +``` + +With the specific timezone, ip and port: + +```sh +docker create \ + --tty \ + --env TZ=Europe/Amsterdam \ + --env XTEVE_PORT=12345 \ + --publish 192.168.88.218:12345:12345 \ + --name xteve \ + senexcrenshaw/xteve +``` + +### Start a container + +```sh +docker start xteve +``` + +#### Attach to a started container + +```sh +docker attach xteve +``` + +To detach from a container, press `Ctrl + C`. + +#### Access web UI + +Open `http(s)://:/web/` in browser, for example: +`http://192.168.88.218:34400/web/` + +#### Stop a running container + +```sh +docker stop xteve +``` + +--- + ## Build from source code [Go / Golang] -#### Requirements -* [Go](https://golang.org) (go1.16.2 or newer) +### Requirements + +* [Go](https://golang.org) (go1.18 or newer) + +### Dependencies -#### Dependencies +* [avfs](https://github.com/avfs/avfs) * [go-ssdp](https://github.com/koron/go-ssdp) -* [websocket](https://github.com/gorilla/websocket) +* [lo](https://github.com/samber/lo) * [osext](https://github.com/kardianos/osext) +* [testify](https://github.com/stretchr/testify) +* [websocket](https://github.com/gorilla/websocket) -#### Build -1. Download source code -2. Install dependencies +### Build + +#### 1. Download source code + +```sh +git clone https://github.com/senexcrenshaw/xTeVe.git ``` -go get github.com/koron/go-ssdp + +#### 2. Install dependencies + +```sh +go mod tidy +``` + +Or + +```sh +go get github.com/avfs/avfs@latest go get github.com/gorilla/websocket go get github.com/kardianos/osext +go get github.com/koron/go-ssdp +go get github.com/samber/lo +go get github.com/stretchr/testify ``` -3. Build xTeVe + +#### 3. Update dependencies (optional) + +```sh +go get -u ./... +``` + +#### 5. Update web files (optional) + +If TypeScript files were changed, run: + +```sh +tsc -p ./ts/tsconfig.json ``` + +Then, to embed updated JavaScript files into the source code (src/webUI.go), run it in development mode at least once: + +```sh go build xteve.go +xteve -dev +``` + +:exclamation: To not to get CreateFile error, do not forget to switch your binary to "regular" mode after runnning with `-dev` flag: + +`xteve -branch main` or `xteve -branch beta` + +#### 4. Build xTeVe + +```sh +go build xteve.go +``` + +Or use convenient cross-compile tool. To build binaries for every OS / architecture pair into `./xteve-build/` folder: + +```sh +go get github.com/mitchellh/gox +go install github.com/mitchellh/gox +gox -output="./xteve-build/{{.Dir}}_{{.OS}}_{{.Arch}}" ./ ``` --- -## Fork without pull request :mega: +## Forks + When creating a fork, the xTeVe GitHub account must be changed from the source code or the update function disabled. -Future updates of the xteve-project would update your fork. :wink: xteve.go - Line: 29 -```Go -var GitHub = GitHubStruct{Branch: "master", User: "xteve-project", Repo: "xTeVe-Downloads", Update: true} -/* - Branch: GitHub Branch - User: GitHub Username - Repo: GitHub Repository - Update: Automatic updates from the GitHub repository [true|false] -*/ +```go +var GitHub = GitHubStruct{Branch: "main", User: "senexcrenshaw", Repo: "xTeVe", Update: true} +// Branch: GitHub Branch +// User: GitHub Username +// Repo: GitHub Repository +// Update: Automatic updates from the GitHub repository [true|false] ``` - - diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..4fd0fe3 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +2.5.1 \ No newline at end of file diff --git a/changelog-beta.md b/changelog-beta.md deleted file mode 100644 index dae577c..0000000 --- a/changelog-beta.md +++ /dev/null @@ -1,88 +0,0 @@ -#### 2.1.1.0116-beta -If no user agent is specified, the default FFmpeg or VLC user agent is used. - -#### 2.1.1.0115-beta -```diff -+ GZIP compression for xteve.xml file. (http://xteve.ip:34400/xmltv/xteve.xml.gz) -- Removed protocol setting for reverse proxy. HTTPS can also be configured in the proxy, where it makes more sense. -``` - -#### 2.1.0.0106-beta -```diff -+ User-Agent is now also used by VLC and FFmpeg. -``` - -#### 2.1.0.0105-beta -```diff -+ Fixed wrong buffer value in log -+ New setting: URL protocol for M3U and XML file -+ Add xml tag premiere to xteve.xml -``` - -#### 2.1.0.0101-beta -```diff -+ Reverse proxy fix -``` - -#### 2.0.3.0042-beta -**Version 2.0.3.0042 changes the settings.json.** -Settings from the current beta can not be used for the current master version 2.0.3 -- New default options for VLC and FFmpeg -- VLC and FFmpeg log entries in the xTeVe log -- Less CPU load with VLC and FFmpeg - -#### 2.0.3.0035-beta -```diff -+ FFmpeg support -+ VLC support -``` -**Version 2.0.3.0035 changes the settings.json.** -Settings from the current beta can not be used for the current master version 2.0.3 - -#### 2.0.2.0024-beta -```diff -+ Improved monitoring of the buffer process -+ Update the XEPG database a bit faster -``` - -##### Fixes -- Error message if filter rule is missing -- Channels are lost when saving again (Mapping) -- Plex log, invalid source: IPTV - -#### 2.0.1.0012-beta -```diff -+ Add support for "video/m2ts" video streams (Pull request #14) -``` -#### 2.0.1.0011-beta -```diff -+ Original group title is shown in the Mapping Editor -``` -##### Fixes -- incorrect original-air-date - -#### 2.0.1.0010-beta -```diff -+ Set timestamp to -``` - -#### 2.0.0.0008-beta -##### Fixes -- Pull request #6 [Error in http/https detection] window.location.protocol return "https:", not "https://" - -#### 2.0.0.0007-beta -```diff -+ Buffer HLS: Add VOD tag from M3U8 -+ CLI: Add new arguments [-restore] -+ CLI: Add new arguments [-info] -``` -##### Fixes -- Missing images with caching for localhost URL - - -#### 2.0.0.0001-beta -```diff -+ Wizard: Add HTML input placeholder (M3U, XMLTV) -+ Wizard: Alert by empty value (M3U, XMLTV) -+ Image caching: Ignore invalid image URLs -``` \ No newline at end of file diff --git a/cmd/xteve-inactive/main.go b/cmd/xteve-inactive/main.go new file mode 100644 index 0000000..324a828 --- /dev/null +++ b/cmd/xteve-inactive/main.go @@ -0,0 +1,68 @@ +package main + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "net/http" + "os" + "strconv" + + xteve "xteve/src" +) + +var port = flag.String("port", "", ": Server port [34400] (default: 34400)") +var host = flag.String("host", "", ": Server host (default: localhost)") + +func main() { + flag.Parse() + + portNum := 34400 + if port != nil && *port != "" { + var err error + portNum, err = strconv.Atoi(*port) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable parse port: %v\n", err) + os.Exit(-1) + } + } + + hostname := "localhost" + if host != nil && *host != "" { + hostname = *host + } + + requestBody, err := json.Marshal(&xteve.APIRequestStruct{ + Cmd: "status", + }) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to marshall request: %v\n", err) + os.Exit(-1) + } + + resp, err := http.Post(fmt.Sprintf("http://%s:%d/api/", hostname, portNum), "application/json", bytes.NewBuffer(requestBody)) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to get API: %v\n", err) + os.Exit(-1) + } + + defer resp.Body.Close() + + respStr, err := ioutil.ReadAll(resp.Body) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable read response: %v\n", err) + os.Exit(-1) + } + + var apiresp xteve.APIResponseStruct + err = json.Unmarshal(respStr, &apiresp) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable parse response: %v\n", err) + fmt.Fprintf(os.Stderr, "%s\n", respStr) + os.Exit(-1) + } + + os.Exit(int(apiresp.TunerActive)) +} diff --git a/cmd/xteve-status/main.go b/cmd/xteve-status/main.go new file mode 100644 index 0000000..9e4f012 --- /dev/null +++ b/cmd/xteve-status/main.go @@ -0,0 +1,83 @@ +package main + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "net/http" + "os" + "strconv" + + xteve "xteve/src" +) + +var port = flag.String("port", "", ": Server port [34400] (default: 34400)") +var host = flag.String("host", "", ": Server host (default: localhost)") + +func main() { + flag.Parse() + + portNum := 34400 + if port != nil && *port != "" { + var err error + portNum, err = strconv.Atoi(*port) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable parse port: %v\n", err) + os.Exit(-1) + } + } + + hostname := "localhost" + if host != nil && *host != "" { + hostname = *host + } + + requestBody, err := json.Marshal(&xteve.APIRequestStruct{ + Cmd: "status", + }) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to marshall request: %v\n", err) + os.Exit(-1) + } + + resp, err := http.Post(fmt.Sprintf("http://%s:%d/api/", hostname, portNum), "application/json", bytes.NewBuffer(requestBody)) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to get API: %v\n", err) + os.Exit(-1) + } + + defer resp.Body.Close() + + respStr, err := ioutil.ReadAll(resp.Body) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable read response: %v\n", err) + os.Exit(-1) + } + + var apiresp xteve.APIResponseStruct + err = json.Unmarshal(respStr, &apiresp) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable parse response: %v\n", err) + fmt.Fprintf(os.Stderr, "%s\n", respStr) + os.Exit(-1) + } + + fmt.Printf("xTeVe status:\n") + fmt.Printf("EPG Source: %v\n", apiresp.EpgSource) + fmt.Printf("Error: %v\n", apiresp.Error) + fmt.Printf("Status: %v\n", apiresp.Status) + fmt.Printf("Streams Active: %v\n", apiresp.StreamsActive) + fmt.Printf("Streams Total: %v\n", apiresp.StreamsAll) + fmt.Printf("Streams XEPG: %v\n", apiresp.StreamsXepg) + fmt.Printf("Tuners Active: %v\n", apiresp.TunerActive) + fmt.Printf("Tuners Available: %v\n", apiresp.TunerAll) + fmt.Printf("URL for DVR: %v\n", apiresp.URLDvr) + fmt.Printf("URL for M3U: %v\n", apiresp.URLM3U) + fmt.Printf("URL for XEPG: %v\n", apiresp.URLXepg) + fmt.Printf("API Version: %v\n", apiresp.VersionAPI) + fmt.Printf("xTeVe Version: %v\n", apiresp.VersionXteve) + + os.Exit(0) +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..934445f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +version: "2.1" +services: + xteve: + image: senexcrenshaw/xteve:latest + container_name: xteve + environment: + - TZ=America/New_York + volumes: + - /opt/configs/xteve/config:/home/xteve/conf + - /tmp/xteve:/tmp/xteve:rw + ports: + - 34400:34400 + restart: unless-stopped diff --git a/go.mod b/go.mod index 3ae8132..1e66c9b 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,22 @@ module xteve -go 1.16 +go 1.19 require ( - github.com/gorilla/websocket v1.4.2 // indirect - github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect - github.com/koron/go-ssdp v0.0.2 // indirect + github.com/gorilla/websocket v1.5.0 + github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 + github.com/koron/go-ssdp v0.0.3 + github.com/samber/lo v1.27.0 + github.com/stretchr/testify v1.8.0 +) + +require github.com/avfs/avfs v0.30.0 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect + golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect + golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 55714e3..b51943a 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,46 @@ -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/avfs/avfs v0.30.0 h1:rrcJMJNdqXj8bsVNEXItbA4Oj1NxOE1/h+YtJ3ah2z8= +github.com/avfs/avfs v0.30.0/go.mod h1:CSGcc8vnwdripDtbXQ6hzmKazmnJFZ7m2ObyomzneEg= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= -github.com/koron/go-ssdp v0.0.2 h1:fL3wAoyT6hXHQlORyXUW4Q23kkQpJRgEAYcZB5BR71o= -github.com/koron/go-ssdp v0.0.2/go.mod h1:XoLfkAiA2KeZsYh4DbHxD7h3nR2AZNqVQOa+LJuqPYs= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA= -golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8= +github.com/koron/go-ssdp v0.0.3/go.mod h1:b2MxI6yh02pKrsyNoQUsk4+YNikaGhe4894J+Q5lDvA= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/samber/lo v1.20.0 h1:20FtphdORvp4yxklurzZv2HX+g+0urEMQziODC5bV70= +github.com/samber/lo v1.20.0/go.mod h1:2I7tgIv8Q1SG2xEIkRq0F2i2zgxVpnyPOP0d3Gj2r+A= +github.com/samber/lo v1.27.0 h1:GOyDWxsblvqYobqsmUuMddPa2/mMzkKyojlXol4+LaQ= +github.com/samber/lo v1.27.0/go.mod h1:it33p9UtPMS7z72fP4gw/EIfQB2eI8ke7GR2wc6+Rhg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= +golang.org/x/exp v0.0.0-20220428152302-39d4317da171 h1:TfdoLivD44QwvssI9Sv1xwa5DcL5XQr4au4sZ2F2NV4= +golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= +golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 h1:fqTvyMIIj+HRzMmnzr9NtpHP6uVpvB5fkHcgPDC4nu8= +golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/html/configuration.html b/html/configuration.html index c8bea21..0475b9c 100644 --- a/html/configuration.html +++ b/html/configuration.html @@ -1,58 +1,60 @@ - - - - - xTeVe - - - - - - - - - - - -
-
-
- - -
- - - - - - - - - - - - - - - - - - - - -
Version: OS: 
UUID: Arch: 
Streams: DVR: 
- -
-

Configuration

-
-

-
- -
- -
- + + + + + + xTeVe + + + + + + + + + + + +
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + +
Version: OS: 
UUID: Arch: 
Streams: DVR: 
+ +
+

Configuration

+
+

+
+ +
+ +
+ + \ No newline at end of file diff --git a/html/create-first-user.html b/html/create-first-user.html index 86fb1d2..32aad09 100644 --- a/html/create-first-user.html +++ b/html/create-first-user.html @@ -1,47 +1,49 @@ - - - - - xTeVe - - - - - - - - - - -
- -
-

{{.account.headline}}

-
- -

- -
- -
- -
{{.account.username.title}}:
- -
{{.account.password.title}}:
- -
{{.account.confirm.title}}:
- - -
- -
- - - - -
- + + + + + + xTeVe + + + + + + + + + + +
+ +
+

{{.account.headline}}

+
+ +

+ +
+ +
+ +
{{.account.username.title}}:
+ +
{{.account.password.title}}:
+ +
{{.account.confirm.title}}:
+ + +
+ +
+ + + + +
+ + \ No newline at end of file diff --git a/html/css/base.css b/html/css/base.css index 8fb9390..3d25d85 100644 --- a/html/css/base.css +++ b/html/css/base.css @@ -3,7 +3,7 @@ -moz-appearance: none; -ms-appearance: none; font-family: "Arial", sans-serif; - letter-spacing: 2px; + letter-spacing: 2px; } /* @@ -17,32 +17,35 @@ height: 12px; } - + ::-webkit-scrollbar-track { - -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); + box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); border-radius: 5px; - + } - + ::-webkit-scrollbar-thumb { border-radius: 5px; - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0,0.6); + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.6); + box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.6); background-color: #444; } ::-webkit-scrollbar-thumb:hover { - background: #333; + background: #333; } -::-webkit-scrollbar-corner { - background: transparent; +::-webkit-scrollbar-corner { + background: transparent; } a { color: #00E6FF; } -html, body { +html, +body { color: #fff; margin: 0px auto; height: 100%; @@ -91,11 +94,11 @@ pre { color: #ddd; letter-spacing: 1px; white-space: pre-wrap; - font-family: monospace; - font-size: 12px; - font-style: normal; - font-variant: normal; - line-height: 1.6em; + font-family: monospace; + font-size: 12px; + font-style: normal; + font-variant: normal; + line-height: 1.6em; } label { @@ -124,7 +127,7 @@ select { outline: none; color: #fff; padding: 9px 10px; - display:block; + display: block; background-color: #333; font-size: 14px; margin: 5px 0px 5px 0px; @@ -142,7 +145,8 @@ input { font-size: 14px; } -input[type=button], input[type=submit] { +input[type=button], +input[type=submit] { cursor: pointer; background-color: #000; margin: 10px 10px; @@ -154,8 +158,8 @@ input[type=button], input[type=submit] { color: #fff; } -input[type=button]:focus { - outline: none; +input[type=button]:focus { + outline: none; } input[type=button]:hover { @@ -163,12 +167,14 @@ input[type=button]:hover { color: #000; } -input[type=button]:hover.delete { +input[type=button]:hover.delete { background-color: red; color: #fff; } -input[type=text], input[type=search], input[type=password] { +input[type=text], +input[type=search], +input[type=password] { color: #fff; width: -webkit-calc(100% - 0px); width: -moz-calc(100% - 0px); @@ -215,23 +221,24 @@ input[type="checkbox"]:checked:before { input[type=button].cancel { - + background-color: transparent; border-color: red; } -input[type=button].save{ +input[type=button].save { background-color: #111; float: right; } -input[type=button].black, input[type=submit].black{ +input[type=button].black, +input[type=submit].black { background-color: #000; border-color: #000; } -input[type=button].center{ +input[type=button].center { margin-right: auto; margin-left: auto; background-color: #000; @@ -302,27 +309,22 @@ input[type=button].center{ margin-bottom: 30px; } -.block { - -} - .none { display: none; } - .notVisible { height: 0px; display: none; opacity: 0; border-bottom: #000 solid 0px; - + } .visible { opacity: 1; display: block; - border-bottom: #444 solid 1px; + border-bottom: #444 solid 1px; padding: 10px; } @@ -338,10 +340,6 @@ input[type=button].center{ background-color: #00E6FF; } -.menu-notActive { - -} - #branch { display: table; margin: auto; @@ -380,7 +378,11 @@ input[type=button].center{ color: magenta; } -.News, .Movie, .Series, .Sports, .Kids { +.News, +.Movie, +.Series, +.Sports, +.Kids { border-left: solid 2px } @@ -410,7 +412,7 @@ input[type=button].center{ top: 0px; z-index: 10000; position: absolute; - background-color: rgba(0,0,0, 0.8); + background-color: rgba(0, 0, 0, 0.8); margin: auto; width: 100%; height: 100%; @@ -434,15 +436,25 @@ input[type=button].center{ right: 0; bottom: 0; left: 0; - + } @-webkit-keyframes spin { - 0% { -webkit-transform: rotate(0deg); } - 100% { -webkit-transform: rotate(360deg); } + 0% { + -webkit-transform: rotate(0deg); + } + + 100% { + -webkit-transform: rotate(360deg); + } } @keyframes spin { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } -} + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} \ No newline at end of file diff --git a/html/css/screen.css b/html/css/screen.css index 793e1b5..db16a88 100644 --- a/html/css/screen.css +++ b/html/css/screen.css @@ -42,7 +42,7 @@ nav p { height: 100px; background: url("../img/logo_w_600x200.png"); background-repeat: no-repeat; - background-position: center; + background-position: center; background-size: 100%; } @@ -57,14 +57,14 @@ nav p { height: -moz-calc(100% - 130px); height: calc(100% - 130px); */ - + min-height: -webkit-calc(100% - 120px); min-height: -moz-calc(100% - 120px); min-height: calc(100% - 120px); - - + + box-shadow: 0px 5px 5px #222; - + } #uiSetting { @@ -72,13 +72,14 @@ nav p { margin-right: 25px; } -#box input[type=text], #box input[type=password] { +#box input[type=text], +#box input[type=password] { width: -webkit-calc(100% - 20px); width: -moz-calc(100% - 20px); width: calc(100% - 20px); } -#box input[type=submit]{ +#box input[type=submit] { margin: 50px auto; } @@ -122,22 +123,17 @@ nav p { float: right; } -#settings-footer { - -} - - /* Wizard*/ #box { background-color: #444; min-height: 400px; - + display: flex; flex-direction: column; justify-content: space-between; } -#box p{ +#box p { padding: 10px 0px; } @@ -167,13 +163,16 @@ nav p { /* --- */ -#clientInfo, #activeStreams, #inactiveStreams { +#clientInfo, +#activeStreams, +#inactiveStreams { font-family: monospace; display: block; font-size: 9px; background-color: #111; color: #00E6FF; - border-bottom: solid 0px;; + border-bottom: solid 0px; + ; padding: 0px; letter-spacing: 1px; overflow-x: hidden; @@ -188,9 +187,9 @@ nav p { max-height: 150px; background-color: #111; color: white; - display:flex; - justify-content:center; - align-items:center; + display: flex; + justify-content: center; + align-items: center; } #openStreams { @@ -203,24 +202,26 @@ nav p { bottom: 0px; background: url("../img/touch.png"); background-color: #111; - - background-position: bottom right; + + background-position: bottom right; } #allStreams { width: 100%; height: 100%; - padding: 2px; + padding: 2px; } -#activeStreams, #inactiveStreams { +#activeStreams, +#inactiveStreams { overflow-y: scroll; width: 50%; max-height: 100px; float: left; } -#activeStreams .tdKey, #inactiveStreams .tdKey { +#activeStreams .tdKey, +#inactiveStreams .tdKey { width: 75px; } @@ -231,21 +232,36 @@ nav p { color: red; } -#clientInfo .tdVal, #logInfo .tdVal, #activeStreams .tdVal, #inactiveStreams .tdVal, #mappingInfo .tdVal{ +#clientInfo .tdVal, +#logInfo .tdVal, +#activeStreams .tdVal, +#inactiveStreams .tdVal, +#mappingInfo .tdVal { color: #aaa; white-space: inherit; } +#clientInfo .tdValLink, +#logInfo .tdValLink, +#activeStreams .tdValLink, +#inactiveStreams .tdValLink, +#mappingInfo .tdValLink { + color: lime; + white-space: inherit; +} + #box-wrapper { display: inline-block; width: 100%; - + overflow-y: scroll; } -#content_table, #mapping-detail-table, #content_table { +#content_table, +#mapping-detail-table, +#content_table { display: table; - + border-collapse: collapse; overflow-y: scroll; width: 100%; @@ -282,7 +298,7 @@ tbody { max-width: 30px; } -#content_table tr{ +#content_table tr { border-left: solid 3px 444; border-bottom: solid 1px #333; cursor: pointer; @@ -297,7 +313,7 @@ tbody { padding: 0px 2px; } -#content_table input[type=text]{ +#content_table input[type=text] { width: 80%; min-width: 35px; max-width: 60px; @@ -307,7 +323,7 @@ tbody { text-align: left; } -#content_table input[type=checkbox]{ +#content_table input[type=checkbox] { max-width: 25px; margin: auto; } @@ -321,20 +337,16 @@ tbody { display: none; } -.noBulk { - -} - -#content_table tr.activeEPG{ +#content_table tr.activeEPG { border-left: solid 3px lawngreen; } -#content_table tr.notActiveEPG{ +#content_table tr.notActiveEPG { border-left: solid 3px red; } -#logScreen p{ +#logScreen p { white-space: pre; font-size: 10px; /* @@ -342,11 +354,11 @@ tbody { font-family: "Arial", sans-serif; */ letter-spacing: 1px; - font-family: monospace; - font-size: 12px; - font-style: normal; - font-variant: normal; - line-height: 1.6em; + font-family: monospace; + font-size: 12px; + font-style: normal; + font-variant: normal; + line-height: 1.6em; } #popup { @@ -356,18 +368,22 @@ tbody { width: 100%; z-index: 100; height: 100%; + overflow: scroll; } -#mapping-detail, #user-detail, #file-detail, #popup-custom { +#mapping-detail, +#user-detail, +#file-detail, +#popup-custom { box-shadow: 0px 5px 40px #000; margin-top: 20px; margin-left: auto; margin-right: auto; - - max-width: 600px; + + max-width: 800px; background-color: #222; padding: 10px; - overflow:auto; + overflow: auto; } #popup-custom h3 { @@ -388,14 +404,18 @@ tbody { margin-right: auto; } -#popup-custom input[type=text], #popup-custom input[type=password], #mapping-detail input[type=text], #content_settings input[type=text], #content_settings input[type=password]{ +#popup-custom input[type=text], +#popup-custom input[type=password], +#mapping-detail input[type=text], +#content_settings input[type=text], +#content_settings input[type=password] { border: solid 1px; border-color: transparent; background-color: #333; text-align: left; width: -webkit-calc(100% - 20px); - width: -moz-calc(100% - 20px); - width: calc(100% - 20px); + width: -moz-calc(100% - 20px); + width: calc(100% - 20px); } #popup-custom input[type=text].notAvailable { @@ -404,34 +424,46 @@ tbody { cursor: not-allowed; } -#mapping-detail-table, #user-detail-table { +#popup-custom input[type=text]:disabled { + color: #666; + cursor: not-allowed; +} + +#mapping-detail-table, +#user-detail-table { display: inline-table; width: 100%; } -#popup-custom table, #content_settings table { +#popup-custom table, +#content_settings table { display: inline-table; table-layout: fixed; width: 100%; } -#mapping-detail-table td, #user-detail-table td { +#mapping-detail-table td, +#user-detail-table td { padding: 10px 0px; } -#mapping-detail-table td.left, #user-detail-table td.left, #popup-custom td.left { +#mapping-detail-table td.left, +#user-detail-table td.left, +#popup-custom td.left { width: 38%; } -.interaction, #interaction { +.interaction, +#interaction { margin-top: 20px; display: inline-flex; float: right; } -.interaction input[type=button], .interaction input[type=submit] { +.interaction input[type=button], +.interaction input[type=submit] { background-color: #000; min-width: 100px; margin: 0px 10px; @@ -444,7 +476,7 @@ tbody { right: 0px; height: 100%; width: 250px; - + background-color: #222; box-shadow: 0px 0px 20px #000; } @@ -473,7 +505,7 @@ tbody { } -@media only screen and (min-width: 620px){ +@media only screen and (min-width: 620px) { body { width: 100%; background-color: #444; @@ -495,7 +527,7 @@ tbody { height: 100px; background: url("../img/logo_w_600x200.png"); background-repeat: no-repeat; - + background-size: 300px 100px; } @@ -536,7 +568,4 @@ tbody { flex-direction: column; } - #settings, #settings-footer { - - } -} +} \ No newline at end of file diff --git a/html/favicon.ico b/html/favicon.ico new file mode 100644 index 0000000..2b97fa3 Binary files /dev/null and b/html/favicon.ico differ diff --git a/html/img/BC-QR.jpg b/html/img/BC-QR.jpg deleted file mode 100644 index 25d79aa..0000000 Binary files a/html/img/BC-QR.jpg and /dev/null differ diff --git a/html/index.html b/html/index.html index 59eed18..60e64d2 100644 --- a/html/index.html +++ b/html/index.html @@ -1,35 +1,34 @@ - - - - - xTeVe - - - - - - - - - - - - - -
-
-
+ - + + + + xTeVe + + + + + + + + + + + + + +
+
+
+ + -
+
- - + + -
- - - \ No newline at end of file diff --git a/html/js/authentication.js b/html/js/authentication.js deleted file mode 100644 index 581700b..0000000 --- a/html/js/authentication.js +++ /dev/null @@ -1,42 +0,0 @@ -function createFirstAccount(elm) { - var err = false; - var div = document.getElementById(elm); - console.log(div); - - var form = document.getElementById('authentication'); - - const username = document.getElementById('username'); - const password = document.getElementById('password'); - const confirm = document.getElementById('confirm'); - - var inputs = div.getElementsByTagName('INPUT') - console.log(confirm); - - switch(confirm) { - case null: break; - - default: - for (var i = 0; i < inputs.length; i++) { - if (inputs[i].value.length == 0) { - inputs[i].style.borderColor = 'red'; - err = true - } - } - - switch(err) { - case true: return; break; - case false: - if (password.value != confirm.value) { - confirm.style.borderColor = 'red'; - return; - } - break; - } - } - - - - - form.submit(); - return; -} \ No newline at end of file diff --git a/html/js/authentication_ts.js b/html/js/authentication_ts.js deleted file mode 100644 index f708119..0000000 --- a/html/js/authentication_ts.js +++ /dev/null @@ -1,32 +0,0 @@ -function login() { - var err = false; - var data = new Object(); - var div = document.getElementById("content"); - var form = document.getElementById("authentication"); - var inputs = div.getElementsByTagName("INPUT"); - console.log(inputs); - for (var i = inputs.length - 1; i >= 0; i--) { - var key = inputs[i].name; - var value = inputs[i].value; - if (value.length == 0) { - inputs[i].style.borderColor = "red"; - err = true; - } - data[key] = value; - } - if (err == true) { - data = new Object(); - return; - } - if (data.hasOwnProperty("confirm")) { - if (data["confirm"] != data["password"]) { - alert("sdafsd"); - document.getElementById('password').style.borderColor = "red"; - document.getElementById('confirm').style.borderColor = "red"; - document.getElementById("err").innerHTML = "{{.account.failed}}"; - return; - } - } - console.log(data); - form.submit(); -} diff --git a/html/js/base.js b/html/js/base.js deleted file mode 100644 index ebc2f66..0000000 --- a/html/js/base.js +++ /dev/null @@ -1,331 +0,0 @@ -var config = new Object(); -var menu = new Object(); -var subMenu = new Object(); -var activeStreams = new Object(); -var xEPG = new Object(); -var users = new Object(); -var log = new Object(); -var undo = new Object(); -var webSockets = true; -var closeLog, version, activeMenu; -var columnToSort = 0 - - -if (window.WebSocket === undefined) { - alert("Your browser does not support WebSockets"); - webSockets = false; -} - -function pageReady() { - var data = new Object(); - data["cmd"] = "getServerConfig"; - xTeVe(data); - //showLoadingScreen(false); - - var resizeHandle = document.getElementById("openStreams"); - var box = document.getElementById("myStreamsBox"); - resizeHandle.addEventListener("mousedown", initialiseResize, false); - - function initialiseResize(e) { - window.addEventListener("mousemove", startResizing, false); - window.addEventListener("mouseup", stopResizing, false); - } - - function startResizing(e) { - box.style.height = (e.clientY - box.offsetTop) + "px"; - - var elm = document.getElementById("allStreams"); - if (e.clientY > 120) { - elm.className = "visible"; - } else { - elm.className = "notVisible"; - } - - calculateWrapperHeight(); - - } - function stopResizing(e) { - window.removeEventListener('mousemove', startResizing, false); - window.removeEventListener('mouseup', stopResizing, false); - calculateWrapperHeight(); - } - - window.addEventListener("resize", function(){ - calculateWrapperHeight(); - }, true); -} - - -function getObjKeys(obj) { - var keys = new Array(); - - for (var i in obj) { - if (obj.hasOwnProperty(i)) { - keys.push(i); - } - } - - return keys; -} - - -function createElement(item) { - //console.log(item); - var element = document.createElement(item["_element"]); - if (item.hasOwnProperty("_text")) { - //element.innerHTML = "

" + item["_text"] + "

"; - element.innerHTML = item["_text"]; - } - - var keys = getObjKeys(item); - for (var i = 0; i < keys.length; i++) { - if (keys[i].charAt(0) != "_") { - //console.log(keys[i], item[keys[i]]); - element.setAttribute(keys[i], item[keys[i]]); - } - } - - //console.log(element); - return element; -} - -function modifyOption(id, options, values) { - var select = document.getElementById(id); - select.innerHTML = ""; - - for (var i = 0; i < options.length; i++) { - - var element = document.createElement("OPTION") - - element.value = values[i]; - element.innerHTML = options[i]; - - document.getElementById(id).appendChild(element); - - } - -} - - -function startWebSocket() { - if (webSockets == false) { - return; - } - - //ws.send('{"cmd": "getServerConfig1"}'); - -} - -function checkErr(obj) { - //alert(obj["err"]) - //screenLog(obj["err"], "error") - console.log(obj); - var newObj = new Object(); - var newErr = new Object(); - newErr["key"] = "Error"; - newErr["value"] = obj["err"]; - newErr["type"] = "error"; - - newObj[0] = newErr - showLog(newObj); - return -} - -function screenLog(msg, msgType, show) { - return - clearTimeout(closeLog) - var div = document.getElementById("screenLog"); - var newMsg = new Object(); - - newMsg["_element"] = "P"; - - switch(msgType) { - case "error": newMsg["class"] = "errorMsg"; break; - case "warning": newMsg["class"] = "warningMsg"; break; - //default: newMsg["class"] = "infoMsg" - } - - newMsg["_text"] = msg; - - div.appendChild(createElement(newMsg)); - - div.scrollTop = div.scrollHeight; - - if (show == false) { - return; - } - - div.className = "" - closeLog = setTimeout(closeScreenLog, 10000); -} - - -function closeScreenLog() { - var div = document.getElementById("screenLog"); - div.className = "screenLogHidden" -} - -function showScreenLog() { - clearTimeout(closeLog) - var div = document.getElementById("screenLog"); - var currentClass = div.className; - div.className = "screenLogHidden" - - switch(currentClass) { - case "screenLogHidden": div.className = ""; break; - case "": div.className = "screenLogHidden"; break; - } -} - -function showLoadingScreen(elm) { - var div = document.getElementById("loading"); - switch(elm) { - case true: div.className = "block"; break; - case false: div.className = "none"; break; - - /* - case true: div.style.display = "block"; break; - case false: div.style.display = "none"; break; - */ - } -} - -function createClintInfo(obj) { - //console.log(obj); - var keys = getObjKeys(obj); - for (var i = 0; i < keys.length; i++) { - if(document.getElementById(keys[i])){ - document.getElementById(keys[i]).innerHTML = obj[keys[i]]; - } - } - //document.getElementById("clientInfo").className = "visible"; -} - -function showElement(elmID, type) { - switch(type) { - case true: cssClass = "block"; break; - case false: cssClass = "none"; break; - } - - document.getElementById(elmID).className = cssClass; -} - -function showPopUpElement(elm) { - var allElements = new Array("deleteUserDetail", "mapping-detail", "user-detail", "file-detail"); - - for (var i = 0; i < allElements.length; i++) { - showElement(allElements[i], false) - } - - showElement(elm, true) - - setTimeout(function(){ - showElement("popup", true); - }, 10); -} - - // body... - -function showStreams(force) { - - var elmBox = document.getElementById("myStreamsBox"); - var elm = document.getElementById("allStreams"); - //console.log(elm); - show = elm.className; - - switch(force) { - case true: show = "notVisible"; break; - case false: show = "visible"; break; - } - - switch(show) { - case "notVisible": - elm.className = "visible"; - elmBox.style.height = "100px"; - break; - - default: - elm.className = "notVisible"; - elmBox.style.height = "20px"; - break; - } - - var show = elm.style.display; { - //console.log(elm.style.display); - } - - calculateWrapperHeight(); -} - -function xteveBackup() { - console.log("xteveBackup"); - var data = new Object(); - data["cmd"] = "xteveBackup"; - - xTeVe(data); -} - -function xteveRestore(elm) { - var restore = document.createElement("INPUT"); - restore.setAttribute("type", "file"); - restore.setAttribute("class", "notVisible"); - restore.setAttribute("name", ""); - restore.id = "upload"; - - document.body.appendChild(restore); - restore.click(); - - restore.onchange = function() { - var filename = restore.files[0].name - //console.log(restore.srcElement.files[0]); - var check = confirm("File: " + filename + "\nAll data will be replaced with those from the backup.\nShould the files be restored?"); - if (check == true) { - var reader = new FileReader(); - var file = document.querySelector('input[type=file]').files[0]; - if (file) { - reader.readAsDataURL(file); - reader.onload = function() { - console.log(reader.result); - var data = new Object(); - data["cmd"] = "xteveRestore" - data["base64"] = reader.result - - xTeVe(data); - return - }; - } else { - alert("File could not be loaded") - } - } - }; -} - -function getBase64(file) { - var reader = new FileReader(); - reader.readAsDataURL(file); - reader.onload = function() { - console.log(reader.result); - }; - reader.onerror = function(error) { - console.log('Error: ', error); - }; -} - -function logout() { - document.cookie.split(';').forEach(function(c) { - document.cookie = c.trim().split('=')[0] + '=;' + 'expires=Thu, 01 Jan 1970 00:00:00 UTC;'; - }); - location.reload(); -} - -function getCookie(name) { - var value = "; " + document.cookie; - var parts = value.split("; " + name + "="); - if (parts.length == 2) return parts.pop().split(";").shift(); -} - -function setCookie(token) { - //console.log(token); - document.cookie = "Token=" + token -} - diff --git a/html/js/base_ts.js b/html/js/base_ts.js deleted file mode 100644 index 17ea2ac..0000000 --- a/html/js/base_ts.js +++ /dev/null @@ -1,481 +0,0 @@ -var SERVER = new Object(); -var BULK_EDIT = false; -var COLUMN_TO_SORT; -var SEARCH_MAPPING = new Object(); -var UNDO = new Object(); -var SERVER_CONNECTION = false; -var WS_AVAILABLE = false; -// Menü -var menuItems = new Array(); -menuItems.push(new MainMenuItem("playlist", "{{.mainMenu.item.playlist}}", "m3u.png", "{{.mainMenu.headline.playlist}}")); -//menuItems.push(new MainMenuItem("pmsID", "{{.mainMenu.item.pmsID}}", "number.png", "{{.mainMenu.headline.pmsID}}")) -menuItems.push(new MainMenuItem("filter", "{{.mainMenu.item.filter}}", "filter.png", "{{.mainMenu.headline.filter}}")); -menuItems.push(new MainMenuItem("xmltv", "{{.mainMenu.item.xmltv}}", "xmltv.png", "{{.mainMenu.headline.xmltv}}")); -menuItems.push(new MainMenuItem("mapping", "{{.mainMenu.item.mapping}}", "mapping.png", "{{.mainMenu.headline.mapping}}")); -menuItems.push(new MainMenuItem("users", "{{.mainMenu.item.users}}", "users.png", "{{.mainMenu.headline.users}}")); -menuItems.push(new MainMenuItem("settings", "{{.mainMenu.item.settings}}", "settings.png", "{{.mainMenu.headline.settings}}")); -menuItems.push(new MainMenuItem("log", "{{.mainMenu.item.log}}", "log.png", "{{.mainMenu.headline.log}}")); -menuItems.push(new MainMenuItem("logout", "{{.mainMenu.item.logout}}", "logout.png", "{{.mainMenu.headline.logout}}")); -// Kategorien für die Einstellungen -var settingsCategory = new Array(); -settingsCategory.push(new SettingsCategoryItem("{{.settings.category.general}}", "xteveAutoUpdate,tuner,epgSource,api")); -settingsCategory.push(new SettingsCategoryItem("{{.settings.category.files}}", "update,files.update,temp.path,cache.images,xepg.replace.missing.images")); -settingsCategory.push(new SettingsCategoryItem("{{.settings.category.streaming}}", "buffer,udpxy,buffer.size.kb,buffer.timeout,user.agent,ffmpeg.path,ffmpeg.options,vlc.path,vlc.options")); -settingsCategory.push(new SettingsCategoryItem("{{.settings.category.backup}}", "backup.path,backup.keep")); -settingsCategory.push(new SettingsCategoryItem("{{.settings.category.authentication}}", "authentication.web,authentication.pms,authentication.m3u,authentication.xml,authentication.api")); -function showPopUpElement(elm) { - var allElements = new Array("popup-custom"); - for (var i = 0; i < allElements.length; i++) { - showElement(allElements[i], false); - } - showElement(elm, true); - setTimeout(function () { - showElement("popup", true); - }, 10); - return; -} -function showElement(elmID, type) { - var cssClass; - switch (type) { - case true: - cssClass = "block"; - break; - case false: - cssClass = "none"; - break; - } - document.getElementById(elmID).className = cssClass; -} -function changeButtonAction(element, buttonID, attribute) { - var value = element.options[element.selectedIndex].value; - document.getElementById(buttonID).setAttribute(attribute, value); -} -function getLocalData(dataType, id) { - var data = new Object(); - switch (dataType) { - case "m3u": - data = SERVER["settings"]["files"][dataType][id]; - break; - case "hdhr": - data = SERVER["settings"]["files"][dataType][id]; - break; - case "filter": - case "custom-filter": - case "group-title": - if (id == -1) { - data["active"] = true; - data["caseSensitive"] = false; - data["description"] = ""; - data["exclude"] = ""; - data["filter"] = ""; - data["include"] = ""; - data["name"] = ""; - data["type"] = "group-title"; - SERVER["settings"]["filter"][id] = data; - } - data = SERVER["settings"]["filter"][id]; - break; - case "xmltv": - data = SERVER["settings"]["files"][dataType][id]; - break; - case "users": - data = SERVER["users"][id]["data"]; - break; - case "mapping": - data = SERVER["xepg"]["epgMapping"][id]; - break; - case "m3uGroups": - data = SERVER["data"]["playlist"]["m3u"]["groups"]; - break; - } - return data; -} -function getObjKeys(obj) { - var keys = new Array(); - for (var i in obj) { - if (obj.hasOwnProperty(i)) { - keys.push(i); - } - } - return keys; -} -function getAllSelectedChannels() { - var channels = new Array(); - if (BULK_EDIT == false) { - return channels; - } - var trs = document.getElementById("content_table").getElementsByTagName("TR"); - for (var i = 1; i < trs.length; i++) { - if (trs[i].style.display != "none") { - if (trs[i].firstChild.firstChild.checked == true) { - channels.push(trs[i].id); - } - } - } - return channels; -} -function selectAllChannels() { - var bulk = false; - var trs = document.getElementById("content_table").getElementsByTagName("TR"); - if (trs[0].firstChild.firstChild.checked == true) { - bulk = true; - } - for (var i = 1; i < trs.length; i++) { - if (trs[i].style.display != "none") { - switch (bulk) { - case true: - trs[i].firstChild.firstChild.checked = true; - break; - case false: - trs[i].firstChild.firstChild.checked = false; - break; - } - } - } - return; -} -function bulkEdit() { - BULK_EDIT = !BULK_EDIT; - var className; - var rows = document.getElementsByClassName("bulk"); - switch (BULK_EDIT) { - case true: - className = "bulk showBulk"; - break; - case false: - className = "bulk hideBulk"; - break; - } - for (var i = 0; i < rows.length; i++) { - rows[i].className = className; - rows[i].checked = false; - } - return; -} -function sortTable(column) { - //console.log(columm); - if (column == COLUMN_TO_SORT) { - return; - } - var table = document.getElementById("content_table"); - var tableHead = table.getElementsByTagName("TR")[0]; - var tableItems = tableHead.getElementsByTagName("TD"); - var sortObj = new Object(); - var x, xValue; - var tableHeader; - var sortByString = false; - if (column > 0 && COLUMN_TO_SORT > 0) { - tableItems[COLUMN_TO_SORT].className = "pointer"; - tableItems[column].className = "sortThis"; - } - COLUMN_TO_SORT = column; - var rows = table.rows; - if (rows[1] != undefined) { - tableHeader = rows[0]; - x = rows[1].getElementsByTagName("TD")[column]; - for (i = 1; i < rows.length; i++) { - x = rows[i].getElementsByTagName("TD")[column]; - switch (x.childNodes[0].tagName.toLowerCase()) { - case "input": - xValue = x.getElementsByTagName("INPUT")[0].value.toLowerCase(); - break; - case "p": - xValue = x.getElementsByTagName("P")[0].innerText.toLowerCase(); - break; - default: console.log(x.childNodes[0].tagName); - } - if (xValue == "" || xValue == NaN) { - xValue = i; - sortObj[i] = rows[i]; - } - else { - switch (isNaN(xValue)) { - case false: - xValue = parseFloat(xValue); - sortObj[xValue] = rows[i]; - break; - case true: - sortByString = true; - sortObj[xValue.toLowerCase() + i] = rows[i]; - break; - } - } - } - while (table.firstChild) { - table.removeChild(table.firstChild); - } - var sortValues = getObjKeys(sortObj); - if (sortByString == true) { - sortValues.sort(); - console.log(sortValues); - } - else { - function sortFloat(a, b) { - return a - b; - } - sortValues.sort(sortFloat); - } - table.appendChild(tableHeader); - for (var i = 0; i < sortValues.length; i++) { - table.appendChild(sortObj[sortValues[i]]); - } - } - return; -} -function createSearchObj() { - SEARCH_MAPPING = new Object(); - var data = SERVER["xepg"]["epgMapping"]; - var channels = getObjKeys(data); - var channelKeys = ["x-active", "x-channelID", "x-name", "_file.m3u.name", "x-group-title", "x-xmltv-file"]; - channels.forEach(function (id) { - channelKeys.forEach(function (key) { - if (key == "x-active") { - switch (data[id][key]) { - case true: - SEARCH_MAPPING[id] = "online "; - break; - case false: - SEARCH_MAPPING[id] = "offline "; - break; - } - } - else { - if (key == "x-xmltv-file") { - var xmltvFile = getValueFromProviderFile(data[id][key], "xmltv", "name"); - if (xmltvFile != undefined) { - SEARCH_MAPPING[id] = SEARCH_MAPPING[id] + xmltvFile + " "; - } - } - else { - SEARCH_MAPPING[id] = SEARCH_MAPPING[id] + data[id][key] + " "; - } - } - }); - }); - return; -} -function searchInMapping() { - var searchValue = document.getElementById("searchMapping").value; - var trs = document.getElementById("content_table").getElementsByTagName("TR"); - for (var i = 1; i < trs.length; ++i) { - var id = trs[i].getAttribute("id"); - var element = SEARCH_MAPPING[id]; - switch (element.toLowerCase().includes(searchValue.toLowerCase())) { - case true: - document.getElementById(id).style.display = ""; - break; - case false: - document.getElementById(id).style.display = "none"; - break; - } - } - return; -} -function calculateWrapperHeight() { - if (document.getElementById("box-wrapper")) { - var elm = document.getElementById("box-wrapper"); - var divs = new Array("myStreamsBox", "clientInfo", "content"); - var elementsHeight = 0 - elm.offsetHeight; - for (var i = 0; i < divs.length; i++) { - elementsHeight = elementsHeight + document.getElementById(divs[i]).offsetHeight; - } - elm.style.height = window.innerHeight - elementsHeight + "px"; - } - return; -} -function changeChannelNumber(element) { - var dbID = element.parentNode.parentNode.id; - var newNumber = parseFloat(element.value); - var channelNumbers = []; - var data = SERVER["xepg"]["epgMapping"]; - var channels = getObjKeys(data); - if (isNaN(newNumber)) { - alert("{{.alert.invalidChannelNumber}}"); - return; - } - channels.forEach(function (id) { - var channelNumber = parseFloat(data[id]["x-channelID"]); - channelNumbers.push(channelNumber); - }); - for (var i = 0; i < channelNumbers.length; i++) { - if (channelNumbers.indexOf(newNumber) == -1) { - break; - } - if (Math.floor(newNumber) == newNumber) { - newNumber = newNumber + 1; - } - else { - newNumber = newNumber + 0.1; - newNumber.toFixed(1); - newNumber = Math.round(newNumber * 10) / 10; - } - } - data[dbID]["x-channelID"] = newNumber.toString(); - element.value = newNumber; - console.log(data[dbID]["x-channelID"]); - if (COLUMN_TO_SORT == 1) { - COLUMN_TO_SORT = -1; - sortTable(1); - } - return; -} -function backup() { - var data = new Object(); - console.log("Backup data"); - var cmd = "xteveBackup"; - console.log("SEND TO SERVER"); - console.log(data); - var server = new Server(cmd); - server.request(data); - return; -} -function toggleChannelStatus(id) { - var element; - var status; - if (document.getElementById("active")) { - var checkbox = document.getElementById("active"); - status = (checkbox).checked; - } - var ids = getAllSelectedChannels(); - if (ids.length == 0) { - ids.push(id); - } - ids.forEach(function (id) { - var channel = SERVER["xepg"]["epgMapping"][id]; - channel["x-active"] = status; - switch (channel["x-active"]) { - case true: - if (channel["x-xmltv-file"] == "-" || channel["x-mapping"] == "-") { - if (BULK_EDIT == false) { - alert(channel["x-name"] + ": Missing XMLTV file / channel"); - checkbox.checked = false; - } - channel["x-active"] = false; - } - break; - case false: - // code... - break; - } - if (channel["x-active"] == false) { - document.getElementById(id).className = "notActiveEPG"; - } - else { - document.getElementById(id).className = "activeEPG"; - } - }); -} -function restore() { - if (document.getElementById('upload')) { - document.getElementById('upload').remove(); - } - var restore = document.createElement("INPUT"); - restore.setAttribute("type", "file"); - restore.setAttribute("class", "notVisible"); - restore.setAttribute("name", ""); - restore.id = "upload"; - document.body.appendChild(restore); - restore.click(); - restore.onchange = function () { - var filename = restore.files[0].name; - var check = confirm("File: " + filename + "\n{{.confirm.restore}}"); - if (check == true) { - var reader = new FileReader(); - var file = document.querySelector('input[type=file]').files[0]; - if (file) { - reader.readAsDataURL(file); - reader.onload = function () { - console.log(reader.result); - var data = new Object(); - var cmd = "xteveRestore"; - data["base64"] = reader.result; - var server = new Server(cmd); - server.request(data); - }; - } - else { - alert("File could not be loaded"); - } - restore.remove(); - return; - } - }; - return; -} -function uploadLogo() { - if (document.getElementById('upload')) { - document.getElementById('upload').remove(); - } - var upload = document.createElement("INPUT"); - upload.setAttribute("type", "file"); - upload.setAttribute("class", "notVisible"); - upload.setAttribute("name", ""); - upload.id = "upload"; - document.body.appendChild(upload); - upload.click(); - upload.onblur = function () { - alert(); - }; - upload.onchange = function () { - var filename = upload.files[0].name; - var reader = new FileReader(); - var file = document.querySelector('input[type=file]').files[0]; - if (file) { - reader.readAsDataURL(file); - reader.onload = function () { - console.log(reader.result); - var data = new Object(); - var cmd = "uploadLogo"; - data["base64"] = reader.result; - data["filename"] = file.name; - var server = new Server(cmd); - server.request(data); - var updateLogo = document.getElementById('update-icon'); - updateLogo.checked = false; - updateLogo.className = "changed"; - }; - } - else { - alert("File could not be loaded"); - } - upload.remove(); - return; - }; -} -function checkUndo(key) { - switch (key) { - case "epgMapping": - if (UNDO.hasOwnProperty(key)) { - SERVER["xepg"][key] = JSON.parse(JSON.stringify(UNDO[key])); - } - else { - UNDO[key] = JSON.parse(JSON.stringify(SERVER["xepg"][key])); - } - break; - default: - break; - } - return; -} -function sortSelect(elem) { - var tmpAry = []; - var selectedValue = elem[elem.selectedIndex].value; - for (var i = 0; i < elem.options.length; i++) - tmpAry.push(elem.options[i]); - tmpAry.sort(function (a, b) { return (a.text < b.text) ? -1 : 1; }); - while (elem.options.length > 0) - elem.options[0] = null; - var newSelectedIndex = 0; - for (var i = 0; i < tmpAry.length; i++) { - elem.options[i] = tmpAry[i]; - if (elem.options[i].value == selectedValue) - newSelectedIndex = i; - } - elem.selectedIndex = newSelectedIndex; // Set new selected index after sorting - return; -} -function updateLog() { - console.log("TOKEN"); - var server = new Server("updateLog"); - server.request(new Object()); -} diff --git a/html/js/classes_ts.js b/html/js/classes_ts.js deleted file mode 100644 index 80c168b..0000000 --- a/html/js/classes_ts.js +++ /dev/null @@ -1,40 +0,0 @@ -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var MainMenu = /** @class */ (function () { - function MainMenu() { - this.DocumentID = "main-menu"; - this.HTMLTag = "LI"; - } - MainMenu.prototype.create = function () { - console.log(this.DocumentID); - }; - return MainMenu; -}()); -var MainMenuItem = /** @class */ (function (_super) { - __extends(MainMenuItem, _super); - function MainMenuItem() { - return _super !== null && _super.apply(this, arguments) || this; - } - MainMenuItem.prototype.create2 = function () { - var element = document.createElement(this.HTMLTag); - element.innerText = this.Value; - console.log(element); - }; - return MainMenuItem; -}(MainMenu)); -function pageReady() { - var item = new MainMenuItem(); - item.Value = "Test"; - item.create2(); -} diff --git a/html/js/configuaration.js b/html/js/configuaration.js deleted file mode 100644 index 0b1105b..0000000 --- a/html/js/configuaration.js +++ /dev/null @@ -1,294 +0,0 @@ -var configMenu = new Object(); -var wizard = new Array("key", "tuner", "epgSource", "m3u", "complete"); -var activeWizard; -var dvrIP - -var configMenu_tuner = new Object(); -configMenu_tuner["_element"] = "SELECT"; -configMenu_tuner["_menuType"] = "singleInput"; -configMenu_tuner["_configKey"] = "tuner"; -configMenu_tuner["_label"] = "Available tuners"; -configMenu_tuner["name"] = "tuner"; -configMenu_tuner["id"] = "Tuner"; -configMenu_tuner["placeholder"] = "Tuner"; -configMenu_tuner["_usage"] = "This setting is only used by Plex and Emby.
The number of concurrent streams allowed by the IPTV provider." - - -var optionValues = new Array(); -for (var i = 1; i <= 100; i++) { - optionValues.push(i) -} -configMenu_tuner["_optionValues"] = optionValues; - -var configMenu_epg = new Object(); -configMenu_epg["_element"] = "SELECT"; -configMenu_epg["_menuType"] = "singleInput"; -configMenu_epg["_configKey"] = "epgSource"; -configMenu_epg["_label"] = "Selection of the EPG source"; -configMenu_epg["name"] = "epgSource"; -configMenu_epg["id"] = "EPG source"; -configMenu_epg["placeholder"] = "EPG source"; -configMenu_epg["_optionValues"] = new Array("PMS", "XEPG"); -configMenu_epg["_usage"] = "PMS: Use EPG data from Plex or Emby
XEPG: Use of external EPG data (XMLTV)
Several XMLTV sources possible
Allows editing and order channels
M3U / XMLTV export (HTTP link for IPTV apps)" - -var configMenu_m3u = new Object(); -configMenu_m3u["_element"] = "INPUT"; -configMenu_m3u["_menuType"] = "inputArray"; -configMenu_m3u["_configKey"] = "file"; -configMenu_m3u["_label"] = "M3U File: local or remote"; -configMenu_m3u["name"] = "file"; -configMenu_m3u["id"] = "m3u"; -configMenu_m3u["type"] = "text"; -configMenu_m3u["placeholder"] = "M3U File"; -configMenu_m3u["_usage"] = "Remote playlist: http://your.provider.com/file.m3u
Local playlist: /path/to/file.m3u" - - -configMenu_m3u["value"] = "http://websrv.local:8080/kabel.m3u"; - -var configMenu_complete = new Object(); -configMenu_complete["_element"] = "H2"; -configMenu_complete["_menuType"] = "inputArray"; -configMenu_complete["_configKey"] = "file"; -configMenu_complete["_text"] = "xTeVe was successfully set up"; -configMenu_complete["name"] = "complete"; -configMenu_complete["id"] = "complete"; -configMenu_complete["type"] = "text"; -configMenu_complete["class"] = "center"; - -configMenu["tuner"] = configMenu_tuner; -configMenu["epgSource"] = configMenu_epg; -configMenu["m3u"] = configMenu_m3u; -configMenu["complete"] = configMenu_complete; - -function readyForConfiguration() { - var data = new Object(); - data["cmd"] = "getServerConfig"; - xTeVe(data); - showLoadingScreen(false); -} - -function createConfiguration(elm) { - - activeWizard = elm; - var item = configMenu[elm]; - - var div = document.getElementById("content"); - div.innerHTML = ""; - div.setAttribute("data-configKey", item["_configKey"]); - div.setAttribute("data-menuType", item["_menuType"]); - - switch(item.hasOwnProperty("_label")) { - case true: - var newItem = new Object(); - newItem["_element"] = "LABEL"; - newItem["_text"] = item["_label"]; - newItem["for"] = item["id"]; - div.appendChild(createElement(newItem)); - break - } - - switch(item["_element"]) { - case "SELECT": - div.appendChild(createElement(item)); - var selectElement = div.getElementsByTagName("SELECT")[0]; - var values = item["_optionValues"]; - for (var i = 0; i < values.length; i++) { - var newEntry = new Object; - newEntry["_element"] = "OPTION"; - newEntry["_text"] = item["id"] + ": " + values[i]; - newEntry["value"] = values[i]; - selectElement.appendChild(createElement(newEntry)); - } - //return - break; - - default: - div.appendChild(createElement(item)); - break; - - - } - //alert() - - switch(item.hasOwnProperty("_usage")) { - case true: - var usageItem = new Object(); - usageItem["_element"] = "PRE" - usageItem["_text"] = item["_usage"]; - div.appendChild(createElement(usageItem)); - } - - if (activeWizard == "complete") { - document.getElementById("next").value = "Finished" - //document.getElementById("next").setAttribute("onclick", "javascript: location.reload();") - } - - //div.appendChild(createElement(item)); -} - -function saveData() { - - var div = document.getElementById("content"); - var inputs = div.getElementsByTagName("INPUT"); - var selects = div.getElementsByTagName("SELECT"); - var value; - var data = new Object(); - var valueArr = new Array(); - var newData = false; - - if (activeWizard == "complete") { - data["cmd"] = "wizardCompleted"; - showLoadingScreen(true) - xTeVe(data); - return - } - - for (var i = 0; i < inputs.length; i++) { - var menuType = inputs[i].parentElement.getAttribute("data-menutype"); - if (inputs[i].value != undefined && inputs[i].value != "" ) { - newData = true; - - console.log(inputs[i].id) - switch(inputs[i].id) { - case "m3u": - var newPlaylist = new Object(); - newPlaylist["file.source"] = inputs[i].value; - //newPlaylist["name"] = inputs[i].value; - newPlaylist["type"] = "m3u"; - newPlaylist["new"] = true; - - data["files"] = new Object(); - data["files"]["m3u"] = new Object(); - data["files"]["m3u"]["-"] = newPlaylist; - - data["cmd"] = "saveFilesM3U"; - xTeVe(data) - return - } - /* - switch(menuType) { - case "singleInput": - data[inputs[i].name] = inputs[i].value; break; - case "inputArray": - valueArr.push(inputs[i].value); - data[inputs[i].name] = valueArr; break - - } - */ - } else { - inputs[i].style.borderBottomColor = "red"; - return; - } - } - - - for (var i = 0; i < selects.length; i++) { - var value = selects[i].options[selects[i].selectedIndex].value; - if (isNaN(value) == false) { - value = parseInt(value); - data[selects[i].name] = value; - newData = true; - break; - } - data[selects[i].name] = value; - newData = true; - } - - - //console.log(data, newData); - if (newData == true) { - config = data - data["cmd"] = "saveConfig"; - xTeVe(data); - } -} - -function xTeVe(data) { - - if (webSockets == false) { - alert("Your browser does not support WebSockets"); - return; - } - - if (activeWizard == "m3u" || activeWizard == "epgSource") { - showLoadingScreen(true); - } - - var protocolWS - switch(window.location.protocol) { - case "http:": protocolWS = "ws://"; break; - case "https:": protocolWS = "wss://"; break; - } - - var ws = new WebSocket(protocolWS + window.location.hostname + ":" + window.location.port + "/data/" + "?Token=" + getCookie("Token")); - - ws.onopen = function() { - ws.send(JSON.stringify(data)); - } - - ws.onmessage = function (e) { - - var response = JSON.parse(e.data); - - if (response.hasOwnProperty("clientInfo")) { - createClintInfo(response["clientInfo"]); - } - - if (response.hasOwnProperty("status")) { - if (response["status"] == false) { - document.getElementById("headline").style.borderColor = "red"; - showErr(response["err"]); - showLoadingScreen(false) - return - } else { - document.getElementById("err").innerHTML = ""; - document.getElementById("headline").style.borderColor = "lawngreen"; - } - - dvrIP = response["DVR"] - switch(response["configurationWizard"]) { - case true: - if (activeWizard == undefined) { - activeWizard = wizard[0] - } - var n = wizard.indexOf(activeWizard); - n++; - activeWizard = wizard[n] - - if (activeWizard == undefined) { - data["cmd"] = "wizardCompleted"; - xTeVe(data) - } else { - //console.log(activeWizard); - createConfiguration(activeWizard); - } - - break; - } - - switch(response["reload"]) { - - - case true: - - setTimeout(function(){ - location.reload(); - }, 100); - - //location.reload(); - - break; - - } - - - } - - setTimeout(function(){ showLoadingScreen(false); }, 300); - } - -} - -function showErr(elm) { - document.getElementById("err").innerHTML = elm; -} \ No newline at end of file diff --git a/html/js/configuration_ts.js b/html/js/configuration_ts.js deleted file mode 100644 index 8aa4ee3..0000000 --- a/html/js/configuration_ts.js +++ /dev/null @@ -1,147 +0,0 @@ -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var WizardCategory = /** @class */ (function () { - function WizardCategory() { - this.DocumentID = "content"; - } - WizardCategory.prototype.createCategoryHeadline = function (value) { - var element = document.createElement("H4"); - element.innerHTML = value; - return element; - }; - return WizardCategory; -}()); -var WizardItem = /** @class */ (function (_super) { - __extends(WizardItem, _super); - function WizardItem(key, headline) { - var _this = _super.call(this) || this; - _this.headline = headline; - _this.key = key; - return _this; - } - WizardItem.prototype.createWizard = function () { - var headline = this.createCategoryHeadline(this.headline); - var key = this.key; - var content = new PopupContent(); - var description; - var doc = document.getElementById(this.DocumentID); - doc.innerHTML = ""; - doc.appendChild(headline); - switch (key) { - case "tuner": - var text = new Array(); - var values = new Array(); - for (var i = 1; i <= 100; i++) { - text.push(i); - values.push(i); - } - var select = content.createSelect(text, values, "1", key); - select.setAttribute("class", "wizard"); - select.id = key; - doc.appendChild(select); - description = "{{.wizard.tuner.description}}"; - break; - case "epgSource": - var text = ["PMS", "XEPG"]; - var values = ["PMS", "XEPG"]; - var select = content.createSelect(text, values, "XEPG", key); - select.setAttribute("class", "wizard"); - select.id = key; - doc.appendChild(select); - description = "{{.wizard.epgSource.description}}"; - break; - case "m3u": - var input = content.createInput("text", key, ""); - input.setAttribute("placeholder", "{{.wizard.m3u.placeholder}}"); - input.setAttribute("class", "wizard"); - input.id = key; - doc.appendChild(input); - description = "{{.wizard.m3u.description}}"; - break; - case "xmltv": - var input = content.createInput("text", key, ""); - input.setAttribute("placeholder", "{{.wizard.xmltv.placeholder}}"); - input.setAttribute("class", "wizard"); - input.id = key; - doc.appendChild(input); - description = "{{.wizard.xmltv.description}}"; - break; - default: - console.log(key); - break; - } - var pre = document.createElement("PRE"); - pre.innerHTML = description; - doc.appendChild(pre); - console.log(headline, key); - }; - return WizardItem; -}(WizardCategory)); -function readyForConfiguration(wizard) { - var server = new Server("getServerConfig"); - server.request(new Object()); - showElement("loading", false); - configurationWizard[wizard].createWizard(); -} -function saveWizard() { - var cmd = "saveWizard"; - var div = document.getElementById("content"); - var config = div.getElementsByClassName("wizard"); - var wizard = new Object(); - for (var i = 0; i < config.length; i++) { - var name; - var value; - switch (config[i].tagName) { - case "SELECT": - name = config[i].name; - value = config[i].value; - // Wenn der Wert eine Zahl ist, wird dieser als Zahl gespeichert - if (isNaN(value)) { - wizard[name] = value; - } - else { - wizard[name] = parseInt(value); - } - break; - case "INPUT": - switch (config[i].type) { - case "text": - name = config[i].name; - value = config[i].value; - if (value.length == 0) { - var msg = name.toUpperCase() + ": " + "{{.alert.missingInput}}"; - alert(msg); - return; - } - wizard[name] = value; - break; - } - break; - default: - // code... - break; - } - } - var data = new Object(); - data["wizard"] = wizard; - var server = new Server(cmd); - server.request(data); - console.log(data); -} -// Wizard -var configurationWizard = new Array(); -configurationWizard.push(new WizardItem("tuner", "{{.wizard.tuner.title}}")); -configurationWizard.push(new WizardItem("epgSource", "{{.wizard.epgSource.title}}")); -configurationWizard.push(new WizardItem("m3u", "{{.wizard.m3u.title}}")); -configurationWizard.push(new WizardItem("xmltv", "{{.wizard.xmltv.title}}")); diff --git a/html/js/data.js b/html/js/data.js deleted file mode 100644 index 688733a..0000000 --- a/html/js/data.js +++ /dev/null @@ -1,329 +0,0 @@ -function showConfig(obj) { - config = obj; - //setMenuItem(); - createMenu(); - //document.getElementById("page").className = ""; -} - -showMyStreams - -function showMyStreams(allStreamsObj) { - - var streamTypeKeys = getObjKeys(allStreamsObj) - - for (var s = 0; s < streamTypeKeys.length; s++) { - var streamType = streamTypeKeys[s]; - var obj = new Object(); - obj = allStreamsObj[streamType]; - switch(streamType) { - case "activeStreams": activeStreams = obj; break; - } - - document.getElementById(streamType).innerHTML = ""; - - var streamsObj = new Object(); - var streamsNames = new Array(); - - var keys = getObjKeys(obj) - - // Create Object (streamsObj) for the streams and sort by name (streamsNames) - for (var i = 0; i < keys.length; i++) { - var name = obj[keys[i]]["name"]; - var tmp = new Object(); - var streamKey = getObjKeys(obj[keys[i]]); - - for (var j = 0; j < streamKey.length; j++) { - tmp[streamKey[j]] = obj[keys[i]][streamKey[j]]; - } - - streamsObj[name] = tmp; - streamsNames.push(name) - } - - streamsNames.sort(); - - // Create Table for activeStreams - var table = document.getElementById(streamType); - - for (var i = 0; i < streamsNames.length; i++) { - var newEntry = new Object(); - newEntry["_element"] = "TR"; - table.appendChild(createElement(newEntry)); - var line = table.lastChild; - - var tmp = streamsObj[streamsNames[i]] - var keys = getObjKeys(tmp) - - var newKey = new Object() - newKey["_element"] = "TD"; - //newKey["_text"] = streamsNames[i]; - switch(streamType) { - case "activeStreams": newKey["_text"] = "Channel (+):"; break; - case "inactiveStreams": newKey["_text"] = "Channel (-):"; break; - } - - newKey["class"] = "tdKey"; - console.log(); - - - var newVal = new Object() - newVal["_element"] = "TD"; - newVal["_text"] = streamsNames[i]; - newVal["class"] = "tdVal"; - //newVal["_text"] = value; - - line.appendChild(createElement(newKey)); - line.appendChild(createElement(newVal)); - - } - - } - - return -} - -function showActiveStreams(obj) { - document.getElementById("activeStreams").innerHTML = ""; - activeStreams = obj; - var streamsObj = new Object(); - var streamsNames = new Array(); - - var keys = getObjKeys(obj) - - // Create Object (streamsObj) for the streams and sort by name (streamsNames) - for (var i = 0; i < keys.length; i++) { - var name = obj[keys[i]]["name"]; - var tmp = new Object(); - var streamKey = getObjKeys(obj[keys[i]]); - - for (var j = 0; j < streamKey.length; j++) { - tmp[streamKey[j]] = obj[keys[i]][streamKey[j]]; - } - - streamsObj[name] = tmp; - streamsNames.push(name) - } - - streamsNames.sort(); - - // Create Table for activeStreams - var table = document.getElementById("activeStreams"); - - for (var i = 0; i < streamsNames.length; i++) { - var newEntry = new Object(); - newEntry["_element"] = "TR"; - table.appendChild(createElement(newEntry)); - var line = table.lastChild; - - var tmp = streamsObj[streamsNames[i]] - var keys = getObjKeys(tmp) - - var newKey = new Object() - newKey["_element"] = "TD"; - //newKey["_text"] = streamsNames[i]; - newKey["_text"] = "Channel:"; - newKey["class"] = "tdKey"; - console.log(); - - - var newVal = new Object() - newVal["_element"] = "TD"; - newVal["_text"] = streamsNames[i]; - newVal["class"] = "tdVal"; - //newVal["_text"] = value; - - line.appendChild(createElement(newKey)); - line.appendChild(createElement(newVal)); - - } - -} - -function parseLogs(obj) { - log = obj - var keys = getObjKeys(obj) - - var msgType; - for (var i = 0; i < keys.length; i++) { - switch(keys[i]) { - case "warnings": msgType = "warningMsg"; break; - case "errors": msgType = "errorMsg"; break; - } - - switch(obj[keys[i]]) { - case 0: msgType = "tdVal"; break; - default: break; - } - - if(document.getElementById(keys[i])){ - document.getElementById(keys[i]).className = msgType; - } - - - } - return -} - - -function cancelData(element) { - createMenu(); -} - -function saveData(element) { - var data = new Object(); - var div = element.parentNode.parentNode; - var inputs = div.getElementsByTagName("INPUT"); - - var configKey = div.getAttribute("data-configkey"); - var menuType = div.getAttribute("data-menutype"); - var value; - var valueArr = new Array(); - - for (var i = 0; i < inputs.length; i++) { - if (inputs[i].type == "text" && inputs[i].value != undefined && inputs[i].value != "" ) { - console.log(inputs[i].value, menuType) - switch(menuType) { - case "inputArray": valueArr.push(inputs[i].value); break; - case "singleInput": value = inputs[i].value; break; - } - } - } - - switch(menuType) { - case "inputArray": data[configKey] = valueArr; break; - case "singleInput": - if (isNaN(value) == false) { - value = parseInt(value); - data[configKey] = value; - break; - } - - if (value == undefined) { - data["delete"] = configKey; - } else { - data[configKey] = value - } - - break; - } - - data["cmd"] = "saveConfig"; - console.log(data); - xTeVe(data) -} - -function xTeVe(data) { - if (webSockets == false) { - alert("Your browser does not support WebSockets"); - return; - } else { - if (data["cmd"] != "getLog") { - showLoadingScreen(true) - } - } - delete undo["epgMapping"]; - - var protocolWS - switch(window.location.protocol) { - case "http:": protocolWS = "ws://"; break; - case "https:": protocolWS = "wss://"; break; - } - - - var ws = new WebSocket(protocolWS + window.location.hostname + ":" + window.location.port + "/data/" + "?Token=" + getCookie("Token")); - ws.onopen = function() { - console.log(data) - ws.send(JSON.stringify(data)); - } - - ws.onmessage = function (e) { - var response = JSON.parse(e.data); - console.log(response); - - if (response.hasOwnProperty("clientInfo")) { - createClintInfo(response["clientInfo"]); - } - - if (response.hasOwnProperty("log")) { - createClintInfo(response["log"]); - } - - if (response.hasOwnProperty("status")) { - if (response["status"] == false) { - alert(response["err"]) - if(response.hasOwnProperty("reload")) { - location.reload(); - } - //checkErr(response) - console.log(response); - updateXteveStatus(response); - setTimeout(function(){ showLoadingScreen(false); }, 300); - - return - } - - updateXteveStatus(response) - - //console.log(data["cmd"]); - switch(data["cmd"]) { - case "saveUserData": createMenu(); break; - case "saveNewUser": createMenu(); break; - case "saveFilesXMLTV": //createMenu(); break; - case "saveFilesM3U": //createMenu(); return; break; - case "saveConfig": - data = new Object(); - data["cmd"] = "checkToken"; - xTeVe(data); - break; - - case "emptyLog": writeLogInDiv(); break; - case "getLog": return; break; - } - - - } - - if (config["files"] == undefined || config["files"].length == 0) { - createMenu(); - document.getElementById(10).click() - } - - setTimeout(function(){ showLoadingScreen(false); }, 0); - } - -} - -function updateXteveStatus(response) { - var keys = getObjKeys(response); - //console.log(keys); - - for (var i = 0; i < keys.length; i++) { - switch(keys[i]) { - case "alert": alert(response[keys[i]]); break; - case "config": showConfig(response[keys[i]]); break; - case "log": parseLogs(response[keys[i]]); break; - case "myStreams": showMyStreams(response[keys[i]]); break; - case "xEPG": xEPG = response[keys[i]]; break; - case "users": users = response[keys[i]]; break; - case "token": document.cookie = "Token=" + response[keys[i]]; break; - case "reload": location.reload(); break; - case "openLink": window.location = response["openLink"]; break; - //case "version": version = response[keys[i]]; break; - } - } -} - -function getValueFromProviderFile(xXmltvFile, fileType, key) { - - var fileID = xXmltvFile.substring(0, xXmltvFile.lastIndexOf('.')) - - if (config["files"][fileType].hasOwnProperty(fileID) == true) { - var data = config["files"][fileType][fileID]; - return data[key] - } - -} - - - - diff --git a/html/js/files.js b/html/js/files.js deleted file mode 100644 index a8b63f2..0000000 --- a/html/js/files.js +++ /dev/null @@ -1,379 +0,0 @@ -function openFiles(elm, fileType) { - //document.getElementById("settings").innerHTML = "Test"; - - columnToSort = 0; - var newDiv = document.getElementById("settings"); - - var newEntry = new Object(); - newEntry["_element"] = "HR"; - newDiv.appendChild(createElement(newEntry)); - - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "button"; - newEntry["class"] = "button"; - newEntry["value"] = "New"; - newEntry["onclick"] = 'fileDetail("-", "' + fileType + '")'; - newDiv.appendChild(createElement(newEntry)); - - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "button"; - newEntry["class"] = "button"; - newEntry["value"] = "Update"; - newEntry["onclick"] = "fileDetail(0)"; - //newDiv.appendChild(createElement(newEntry)); - - var div = document.getElementById("settings"); - - // Build table - var newTable = new Object(); - newTable["_element"] = "TABLE"; - newTable["id"] = "id_mapping"; - newTable["class"] = "table-mapping"; - div.appendChild(createElement(newTable)); - - setTimeout(function(){ - createFilesTable(fileType); - }, 10); - -} - -function createFilesTable(fileType) { - var table = document.getElementById("id_mapping"); - var availableFileTypes = new Array(); - - table.innerHTML = ""; - var newTR = new Object(); - newTR["_element"] = "TR"; - newTR["class"] = "table-mapping-header"; - table.appendChild(createElement(newTR)); - - var tr = table.lastChild; - - switch(fileType) { - case "xmltv": - availableFileTypes = new Array("xmltv"); - var trHeadlines = new Array("Guide", "Last Update", "Availability %", "Channels", "Programs") - var compatibilityKeys = new Array("xmltv.channels", "xmltv.programs") - break; - - case "m3u": - availableFileTypes = new Array("m3u", "hdhr"); - var trHeadlines = new Array("Playlist", "Last Update", "Availability %", "Type", "Streams", "group-title %", "tvg-id %", "Unique ID %"); - var compatibilityKeys = new Array("streams", "group.title", "tvg.id", "stream.id"); - break; - } - - for (var i = 0; i < trHeadlines.length; i++) { - var newTD = new Object(); - newTD["_element"] = "TD"; - newTD["_text"] = trHeadlines[i]; - tr.appendChild(createElement(newTD)); - } - - for (var i = 0; i < availableFileTypes.length; i++) { - - var fileType = availableFileTypes[i] - - var data = config["files"][fileType]; - - var allFiles = getObjKeys(data) - - for (var f = 0; f < allFiles.length; f++) { - var elm = data[allFiles[f]]; - var table = document.getElementById("id_mapping"); - var fileID = elm["id.provider"]; - var name = elm["name"]; - var lastUpdate = elm["last.update"]; - var availability = elm["provider.availability"]; - var type = elm["type"].toUpperCase(); - var compatibility = elm["compatibility"]; - - // Create TR - var newTR = new Object(); - newTR["_element"] = "TR"; - newTR["class"] = ""; - newTR["id"] = fileID; - newTR["onclick"] = 'javascript: fileDetail("' + fileID + '","' + fileType + '");'; - table.appendChild(createElement(newTR)); - - var tr = table.lastChild; - - // Create file name TD - var newTD = new Object(); - newTD["_element"] = "P"; - newTD["_text"] = name; - createNewTD(newTD, tr); - - // Create last update TD - var newTD = new Object(); - newTD["_element"] = "P"; - newTD["_text"] = lastUpdate; - createNewTD(newTD, tr); - - // Create availability TD - var newTD = new Object(); - newTD["_element"] = "P"; - newTD["_text"] = availability; - createNewTD(newTD, tr); - - if (fileType == "m3u" || fileType == "hdhr") { - - // Create Type TD - var newTD = new Object(); - newTD["_element"] = "P"; - newTD["_text"] = type; - createNewTD(newTD, tr); - - } - - // Create all compatibility TDs - - for (var j = 0; j < compatibilityKeys.length; j++) { - var newTD = new Object(); - newTD["_element"] = "P"; - newTD["_text"] = compatibility[compatibilityKeys[j]]; - createNewTD(newTD, tr); - } - - } - - } - - - sortTable(0) - - // usage Info - var div = document.getElementById("settings"); - switch(menu[activeMenu.id].hasOwnProperty("_usage")) { - case true: - var usageItem = new Object(); - usageItem["_element"] = "PRE" - usageItem["_text"] = menu[activeMenu.id]["_usage"]; - - var newHR = new Object(); - newHR["_element"] = "HR" - div.appendChild(createElement(newHR)); - div.appendChild(createElement(usageItem)); - break; - } - - calculateWrapperHeight(); - return; -} - - -function fileDetail(fileID, fileType) { - - optionsText = new Array("M3U", "HDHomeRun - [Experimental]") - optionsValue = new Array("m3u", "hdhr") - - switch (fileType) { - - case "m3u": - document.getElementById("name").setAttribute("placeholder", "Playlist name"); - document.getElementById("description").setAttribute("placeholder", "Description of this playlist"); - document.getElementById("file-detail-headline").innerHTML = "M3U Playlist"; - document.getElementById("file-path").innerHTML = "M3U File:"; - document.getElementById("file.source").setAttribute("placeholder", "Local or remote"); - break; - - case "hdhr": - document.getElementById("name").setAttribute("placeholder", "HDHomeRun name"); - document.getElementById("description").setAttribute("placeholder", "Description of this HDHomeRun tuner"); - document.getElementById("file-detail-headline").innerHTML = "HDHomeRun"; - document.getElementById("file-path").innerHTML = "HDHomeRun IP:"; - document.getElementById("file.source").setAttribute("placeholder", "IP address and port of the tuner (192.168.1.10:5004)"); - break; - - case "xmltv": - document.getElementById("name").setAttribute("placeholder", "XMLTV name"); - document.getElementById("description").setAttribute("placeholder", "Description of this XMLTV file"); - document.getElementById("file-detail-headline").innerHTML = "XMLTV File"; - document.getElementById("file-path").innerHTML = "XMLTV File:"; - document.getElementById("file.source").setAttribute("placeholder", "Local or remote"); - - optionsText = new Array("XMLTV") - optionsValue = new Array("xmltv") - break; - } - - modifyOption("type", optionsText, optionsValue) - - showPopUpElement('file-detail'); - - document.getElementById("saveFileDetail").setAttribute("onclick", 'javascript: saveFileDetail("' + fileID + '","' + fileType + '", false)'); - document.getElementById("updateFileDetail").setAttribute("onclick", 'javascript: updateFile("' + fileID + '","' + fileType + '", false)'); - document.getElementById("deleteFileDetail").setAttribute("onclick", 'javascript: saveFileDetail("' + fileID + '","' + fileType + '", true)'); - - var data = new Object(); - - switch(fileID) { - - case "-": // New file - data["name"] = ""; - data["description"] = ""; - data["file.source"] = ""; - data["type"] = fileType; - - document.getElementById("deleteFileDetail").className = "delete"; - document.getElementById("type").setAttribute("onchange", "changeFileType(this);") - document.getElementById("type").setAttribute("data-id", fileID) - - showElement("deleteFileDetail", false); - showElement("updateFileDetail", false); - - if (fileType == "xmltv") { - showElement("type", false); - showElement("file-type", false); - } else { - showElement("type", true); - showElement("file-type", true); - } - - break; - - default: - data = config["files"][fileType][fileID]; - document.getElementById("deleteFileDetail").className = "delete"; - - showElement("updateFileDetail", true); - showElement("type", false); - showElement("file-type", false); - - break; - - } - - var keys = getObjKeys(data); - - for (var i = 0; i < keys.length; i++) { - - if(document.getElementById(keys[i])){ - document.getElementById(keys[i]).value = data[keys[i]]; - } - - - } - -} - -function changeFileType(elm) { - - var fileID = elm.getAttribute("data-id"); - var fileType = elm.options[elm.selectedIndex].value; - - fileDetail(fileID, fileType) - -} - - -function saveFileDetail(fileID, fileType, deleteFile) { - - if (fileID == undefined) { - alert("ID is missing!!!"); - return - } - - var inputs = document.getElementById("file-detail").getElementsByTagName("INPUT"); - var selects = document.getElementById("file-detail").getElementsByTagName("SELECT"); - var newFileData = new Object(); - var data = new Object(); - - for (var i = 0; i < inputs.length; i++) { - switch(inputs[i].type) { - case "text": newFileData[inputs[i].name] = inputs[i].value; break; - } - } - - for (var i = 0; i < selects.length; i++) { - newFileData[selects[i].id] = selects[i].options[selects[i].selectedIndex].value; - } - - if (deleteFile == true) { - switch(fileType) { - case "m3u": var alertText = "Delete this playlist?"; break; - case "hdhr": var alertText = "Delete this HDHomeRun tuner?"; break; - case "xmltv": var alertText = "Delete this XMLTV file?"; break; - } - - if (confirm(alertText)) { - newFileData["delete"] = true - data = buildFilesObj(fileType, fileID, newFileData); - console.log(data); - - } else { - showElement("popup", false); - return - - } - - } else { - - switch(config["files"][fileType].hasOwnProperty(fileID)) { - - case true: - data = config["files"][fileType][fileID]; - if (data["file.source"] != newFileData["file.source"]) { - data["update"] = true - } else { - data["updatePlaylistName"] = true; - } - break; - - case false: - newFileData["new"] = true; - data = buildFilesObj(fileType, fileID, newFileData); - break - - } - - } - - switch(fileType) { - - case "m3u": data["cmd"] = "saveFilesM3U"; break; - case "hdhr": data["cmd"] = "saveFilesHDHR"; break; - case "xmltv": data["cmd"] = "saveFilesXMLTV"; break; - - } - //console.log(data); - xTeVe(data); - return -} - -function updateFile(fileID, fileType, allFiles) { - - switch(config["files"][fileType].hasOwnProperty(fileID)) { - - case true: - - var data = new Object(); - var data = buildFilesObj(fileType, fileID, config["files"][fileType][fileID]) - data["new"] = true - - switch(fileType) { - - case "m3u": data["cmd"] = "updateFileM3U"; break; - case "hdhr": data["cmd"] = "updateFileHDHR"; break; - case "xmltv": data["cmd"] = "updateFileXMLTV"; break; - - } - - xTeVe(data); - - break; - } - -} - -function buildFilesObj(fileType, fileID, obj) { - - var data = new Object(); - data["files"] = new Object(); - data["files"][fileType] = new Object(); - data["files"][fileType][fileID] = obj - return data - -} \ No newline at end of file diff --git a/html/js/log.js b/html/js/log.js deleted file mode 100644 index 378d42f..0000000 --- a/html/js/log.js +++ /dev/null @@ -1,114 +0,0 @@ -var logInterval - - -function updateLog() { - var data = new Object(); - data["cmd"] = "getLog"; - xTeVe(data); - writeLogInDiv(); - return -} - -function writeLogInDiv() { - var logs = log["log"]; - var div = document.getElementById("settings").lastChild.lastChild; - div.innerHTML = ""; - - var max = 50; - - - for (var i = 0; i < logs.length; i++) { - var newEntry = new Object(); - newEntry["_element"] = "P"; - - if (logs[i].includes("ERROR")) { -// case "warnings": msgType = "warningMsg"; break; - newEntry["class"] = "errorMsg"; - } - - if (logs[i].includes("WARNING")) { -// case "warnings": msgType = "warningMsg"; break; - newEntry["class"] = "warningMsg"; - } - - newEntry["_text"] = logs[i]; - - div.appendChild(createElement(newEntry)); - } - - calculateWrapperHeight(); - var scrollDiv = document.getElementById("box-wrapper"); - scrollDiv.scrollTop = scrollDiv.scrollHeight; -} - -function showLog(obj) { - //logInterval = setInterval(updateLog, 5000); - - var logs = log["log"]; - - var div = document.getElementById("settings"); - - var newEntry = new Object(); - newEntry["_element"] = "HR"; - div.appendChild(createElement(newEntry)); - //div = div.lastChild; - - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "button"; - newEntry["class"] = "button"; - newEntry["value"] = "Empty Log"; - newEntry["onclick"] = "emptyLog()"; - div.appendChild(createElement(newEntry)); - - var newEntry = new Object(); - newEntry["_element"] = "code"; - newEntry["_text"] = "Update Log: "; - div.appendChild(createElement(newEntry)); - - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "checkbox"; - //newEntry["checked"] = "checkbox"; - newEntry["onclick"] = "logUpdates(this)"; - div.appendChild(createElement(newEntry)); - - var newEntry = new Object(); - newEntry["_element"] = "HR"; - div.appendChild(createElement(newEntry)); - - - - - - var newWrapper = new Object(); - newWrapper["_element"] = "DIV"; - newWrapper["id"] = "box-wrapper"; - div.appendChild(createElement(newWrapper)); - div = div.lastChild; - - var newPre = new Object(); - newPre["_element"] = "PRE"; - newPre["id"] = "logScreen"; - div.appendChild(createElement(newPre)); - - div = div.lastChild; - - writeLogInDiv() - return -} - -function emptyLog() { - var data = new Object(); - data["cmd"] = "emptyLog"; - xTeVe(data); - return -} - -function logUpdates(elm) { - switch(elm.checked) { - case false: clearInterval(logInterval); break; - case true: logInterval = setInterval(updateLog, 5000); break; - - } -} \ No newline at end of file diff --git a/html/js/logs_ts.js b/html/js/logs_ts.js deleted file mode 100644 index ab2f812..0000000 --- a/html/js/logs_ts.js +++ /dev/null @@ -1,42 +0,0 @@ -var Log = /** @class */ (function () { - function Log() { - } - Log.prototype.createLog = function (entry) { - var element = document.createElement("PRE"); - if (entry.indexOf("WARNING") != -1) { - element.className = "warningMsg"; - } - if (entry.indexOf("ERROR") != -1) { - element.className = "errorMsg"; - } - if (entry.indexOf("DEBUG") != -1) { - element.className = "debugMsg"; - } - element.innerHTML = entry; - return element; - }; - return Log; -}()); -function showLogs(bottom) { - var log = new Log(); - var logs = SERVER["log"]["log"]; - var div = document.getElementById("content_log"); - div.innerHTML = ""; - var keys = getObjKeys(logs); - keys.forEach(function (logID) { - var entry = log.createLog(logs[logID]); - div.append(entry); - }); - setTimeout(function () { - if (bottom == true) { - var wrapper = document.getElementById("box-wrapper"); - wrapper.scrollTop = wrapper.scrollHeight; - } - }, 10); -} -function resetLogs() { - var cmd = "resetLogs"; - var data = new Object(); - var server = new Server(cmd); - server.request(data); -} diff --git a/html/js/mapping-editor.js b/html/js/mapping-editor.js deleted file mode 100644 index 471dfe3..0000000 --- a/html/js/mapping-editor.js +++ /dev/null @@ -1,1466 +0,0 @@ -var mappingError = false; -var bulk = false; -var bulkEditAll = false; -var selectObj = new Object(); -var searchObj = new Object(); - -var bulkIDs = new Array(); -var bulkChangeObj = new Object(); - -function checkUndo(key, elm) { - var tmp = new Object(); - tmp = elm - console.log("--"); - if (undo.hasOwnProperty("epgMapping")) { - xEPG["epgMapping"] = JSON.parse(JSON.stringify(undo["epgMapping"]));; - } else { - undo["epgMapping"] = JSON.parse(JSON.stringify(elm)); - } -} - -//var plexCategories = new Array("-", "Action sports", "Action", "Adults only", "Adventure", "Aerobics", "Animals", "Animated", "Anime", "Anthology", "Archery", "Art", "Arts/crafts", "Auction", "Auto racing", "Auto", "Aviation", "Awards", "Ballet", "Baseball", "Basketball", "Bicycle racing", "Bicycle", "Billiards", "Biography", "Boat racing", "Boat", "Bowling", "Boxing", "Bus./financial", "Children", "Collectibles", "Comedy drama", "Comedy", "Community", "Computers", "Consumer", "Cooking", "Crime drama", "Crime", "Dance", "Dark comedy", "Debate", "Diving", "Docudrama", "Documentary", "Drama", "Educational", "Entertainment", "Environment", "Equestrian", "Erotic", "Event", "Fantasy", "Fashion", "Feature Film", "Fishing", "Football", "Game show", "Gaming", "Gay/lesbian", "Golf", "Handball", "Health", "Historical drama", "History", "Hockey", "Holiday", "Home improvement", "Horror", "Horse", "House/garden", "How-to", "Interview", "Intl soccer", "Law", "Martial arts", "Medical", "Military", "Miniseries", "Mixed martial arts", "Motorcycle racing", "Motorcycle", "Motorsports", "Mountain biking", "Music", "Musical comedy", "Musical", "Mystery", "Nature", "News", "Newsmagazine", "Olympics", "Opera", "Outdoors", "Parade", "Paranormal", "Parenting", "Performing arts", "Playoff sports", "Poker", "Politics", "Pro wrestling", "Public affairs", "Reality", "Religious", "Rodeo", "Roller derby", "Romance", "Romantic comedy", "Rugby", "Running", "Sailing", "Science fiction", "Science", "Self improvement", "Series", "Shooting", "Shopping", "Short Film", "Sitcom", "Skiing", "Snooker", "Soap", "Soccer", "Special", "Sports", "sports", "Sports event", "Sports non-event", "Sports talk", "Standup", "Surfing", "Suspense", "TV Movie", "Talk", "Technology", "Tennis", "Theater", "Thriller", "Track/field", "Travel", "Triathlon", "Variety", "Volleyball", "War", "Watersports", "Weather", "Western", "Wrestling", "Yacht racing", "movie", "series", "sports", "tvshow"); -var plexCategoriesValues = new Array("-", "Kids", "News", "Movie", "Series", "Sports") -var plexCategoriesOption = new Array("-", "Kids (Emby only)", "News", "Movie", "Series", "Sports") - - -function openMappingEditor(elm) { - var columnToSort = 1 - - checkUndo("epgMapping", xEPG["epgMapping"]) - - var newDiv = document.getElementById("settings"); - - var newEntry = new Object(); - newEntry["_element"] = "HR"; - newDiv.appendChild(createElement(newEntry)); - - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "button"; - newEntry["class"] = "button"; - newEntry["value"] = "Save"; - newEntry["onclick"] = "saveXEPG()"; - newDiv.appendChild(createElement(newEntry)); - - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "button"; - newEntry["class"] = "button"; - newEntry["value"] = "Bulk Edit"; - newEntry["onclick"] = "bulkEdit()"; - newDiv.appendChild(createElement(newEntry)); - - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "button"; - newEntry["class"] = "button"; - newEntry["value"] = "Show XEPG"; - newEntry["onclick"] = "showXEPG()"; - newDiv.appendChild(createElement(newEntry)); - - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["class"] = "search"; - newEntry["id"] = "searchMapping"; - newEntry["type"] = "search"; - newEntry["placeholder"] = "Search"; - newEntry["onchange"] = "searchInMapping()"; - newDiv.appendChild(createElement(newEntry)); - - var div = document.getElementById("settings"); - //screenLog("Duplicate ID", "error", true) - - - // Build table - - var newWrapper = new Object(); - newWrapper["_element"] = "DIV"; - newWrapper["id"] = "box-wrapper"; - div.appendChild(createElement(newWrapper)); - - - var newTable = new Object(); - newTable["_element"] = "TABLE"; - newTable["id"] = "id_mapping"; - newTable["class"] = "table-mapping"; - div.lastChild.appendChild(createElement(newTable)); - showLoadingScreen(true); - - setTimeout(function(){ - createMappingTable(); - }, 10); - -} - -function createSearchObj() { - searchObj = new Object(); - var IDs = getObjKeys(xEPG["epgMapping"]) - for (var i = IDs.length - 1; i >= 0; i--) { - var item = xEPG["epgMapping"][IDs[i]]; - var searchID = item["x-epg"]; - var searchValue = ""; - searchValue = searchValue + item["x-channelID"] + " "; - searchValue = searchValue + item["x-category"] + " "; - searchValue = searchValue + item["x-name"] + " "; - searchValue = searchValue + item["x-group-title"] + " "; - searchValue = searchValue + item["x-xmltv-file"] + " "; - searchValue = searchValue + item["_file.m3u.name"] + " "; - - switch(item["x-active"]) { - case true: searchValue = searchValue + "online"; break; - case false: searchValue = searchValue + "offline"; break; - } - - searchObj[searchValue] = searchID; - - } -} - - -function calculateWrapperHeight() { - - if (document.getElementById("box-wrapper")){ - - var elm = document.getElementById("box-wrapper"); - - var divs = new Array("myStreamsBox", "clientInfo", "settings"); - var elementsHeight = 0 - elm.offsetHeight; - for (var i = 0; i < divs.length; i++) { - elementsHeight = elementsHeight + document.getElementById(divs[i]).offsetHeight; - } - - elm.style.height = window.innerHeight - elementsHeight + "px"; - - } - - if (document.getElementById("menu-wrapper")){ - - var elm = document.getElementById("menu-wrapper"); - - var offest = document.getElementById("settings").offsetHeight + document.getElementById("myStreamsBox").offsetHeight + document.getElementById("clientInfo").offsetHeight; - - if (window.innerHeight > offest) { - elm.style.height = window.innerHeight + "px" - } else { - elm.style.height = offest + "px" - } - - - } - - -} - -function createMappingTable() { - columnToSort = 1; - createSearchObj(); - - // Create table (Header) - var table = document.getElementById("id_mapping"); - table.innerHTML = ""; - var newTR = new Object(); - newTR["_element"] = "TR"; - newTR["class"] = "table-mapping-header"; - table.appendChild(createElement(newTR)); - - var tr = document.getElementById("id_mapping").lastChild; - var trHeadlines = new Array("Bulk", "Ch. No.", "Logo", "Channel Name", "Playlist", "Group Title", "XMLTV File", "XMLTV ID") - - for (var i = 0; i < trHeadlines.length; i++) { - var newTD = new Object(); - - newTD["_element"] = "TD"; - newTD["_text"] = trHeadlines[i]; - - - - var width = ""; - switch(trHeadlines[i]) { - - case "Bulk": - - maxWidth = "32px"; - minWidth = "32px"; - - // Create bulk TD - var newCheckbox = new Object(); - newCheckbox["_element"] = "INPUT"; - newCheckbox["type"] = "checkbox"; - newCheckbox["class"] = "bulk hideBulk"; - newCheckbox["onmouseout"] = "javascript: this.blur()" - newCheckbox["onclick"] = "javascript: bulkEditAllChannels()" - - - //newTD.appendChild(createElement(newCheckbox)); - - break; - - case "Ch. No.": - maxWidth = "80px"; - minWidth = "70px"; - newTD["onclick"] = "javscript: sortTable(" + i + ");"; - newTD["class"] = "pointer"; - break; - - case "Logo": maxWidth = "120px"; minWidth = "60px"; break; - - case "Channel Name": - maxWidth = "50%"; - minWidth = "200px"; - newTD["onclick"] = "javscript: sortTable(" + i + ");"; - newTD["class"] = "pointer"; - break; - - case "Playlist": - maxWidth = "150px"; - minWidth = "100px"; - newTD["onclick"] = "javscript: sortTable(" + i + ");"; - newTD["class"] = "pointer"; - break; - - case "Group Title": - maxWidth = "150px"; - minWidth = "100px"; - newTD["onclick"] = "javscript: sortTable(" + i + ");"; - newTD["class"] = "pointer"; - break; - - case "XMLTV File": - maxWidth = "150px"; - minWidth = "100px"; - //newTD["onclick"] = "javscript: sortTable(" + i + ");"; - newTD["class"] = ""; - break; - - - case "XMLTV ID": maxWidth = "150px"; minWidth = "100px"; break; - - default: - newTD["class"] = ""; - break; - } - - tr.appendChild(createElement(newTD)); - if (trHeadlines[i] == "Bulk") { - tr.lastChild.innerHTML = ""; - tr.lastChild.appendChild(createElement(newCheckbox)); - - } - - var elm = tr.lastChild; - elm.style.width = maxWidth; - elm.style.maxWidth = maxWidth; - elm.style.minWidth = minWidth; - - } - calculateWrapperHeight(); - var IDs = getObjKeys(xEPG["epgMapping"]) - - var allXmltvFiles = getObjKeys(xEPG["xmltvMap"]); - - if (allXmltvFiles == 0) { - showLoadingScreen(false); - return; - } - - // Sort IDs - var posObj = new Object(); - for (var i = 0; i < IDs.length; i++) { - var item = xEPG["epgMapping"][IDs[i]]; - var pos - switch(isNaN(xEPG["epgMapping"][IDs[i]]["x-channelID"])) { - case false: pos = parseFloat(xEPG["epgMapping"][IDs[i]]["x-channelID"]) ; break; - } - posObj[pos] = item; - } - posFloat = getObjKeys(posObj) - function sortFloat(a,b) { return a - b; } - posFloat.sort(sortFloat) - - //console.log(posFloat); - - // --- - - if (IDs.length > 200) { - setTimeout(function(){ - showLoadingScreen(true); - }, 1); - - } - - - // table for int channel ID's - for (var i = 0; i < posFloat.length; i++) { - - var table = document.getElementById("id_mapping"); - var item = posObj[posFloat[i]]; - //var item = xEPG["epgMapping"][IDs[i]]; - //console.log(item); - var newTR = new Object(); - newTR["_element"] = "TR"; - newTR["class"] = ""; - newTR["id"] = item["x-epg"]; - newTR["oncontextmenu"] = 'javascript: switchChannelStatus("' + item["x-epg"] + '"); return false;'; - table.appendChild(createElement(newTR)); - - var tr = document.getElementById("id_mapping").lastChild; - - // Create bulk TD - var newTD = new Object(); - newTD["_element"] = "INPUT"; - newTD["type"] = "checkbox"; - newTD["class"] = "bulk hideBulk"; - newTD["onmouseout"] = "javascript: this.blur()" - - createNewTD(newTD, tr); - - - // Create ID TD - var newTD = new Object(); - newTD["_element"] = "INPUT"; - newTD["type"] = "text" - newTD["class"] = "w40px"; - newTD["value"] = item["x-channelID"]; - newTD["onfocusout"] = "javascript: arrangeTable(this);" - createNewTD(newTD, tr); - - // Create IMG TD - var newTD = new Object(); - newTD["_element"] = "IMG"; - newTD["onclick"] = 'javascript: mappingDetail("' + item["x-epg"] + '");'; - if (item["tvg-logo"] != undefined) { - newTD["src"] = item["tvg-logo"]; - } else { - item["tvg-logo"] = ""; - newTD["src"] = ""; - } - createNewTD(newTD, tr); - tr.lastChild.setAttribute("onclick", 'javascript: mappingDetail("' + item["x-epg"] + '");') - - // Create P TD (channel name) - var newTD = new Object(); - newTD["_element"] = "P"; - newTD["_text"] = item["x-name"]; - newTD["class"] = item["x-category"]; - - createNewTD(newTD, tr); - tr.lastChild.setAttribute("onclick", 'javascript: mappingDetail("' + item["x-epg"] + '");') - tr.lastChild.lastChild.style.padding = "5px 10px"; - - // Create P TD (Playlist Name) - var newTD = new Object(); - newTD["_element"] = "P"; - newTD["_text"] = item["_file.m3u.name"]; - newTD["class"] = item["tableEllipsis"]; - - createNewTD(newTD, tr); - tr.lastChild.setAttribute("onclick", 'javascript: mappingDetail("' + item["x-epg"] + '");') - - // Create P TD (Group Title) - var newTD = new Object(); - newTD["_element"] = "P"; - newTD["_text"] = item["x-group-title"]; - newTD["class"] = item["tableEllipsis"]; - - createNewTD(newTD, tr); - tr.lastChild.setAttribute("onclick", 'javascript: mappingDetail("' + item["x-epg"] + '");') - - - // Create P TD (XMLTV file) - var newTD = new Object(); - newTD["_element"] = "P"; - newTD["class"] = "tableEllipsis"; - newTD["_text"] = "-" - - if (allXmltvFiles.indexOf(item["x-xmltv-file"]) != -1) { - var xXmltvFile = item["x-xmltv-file"]; - switch(xXmltvFile) { - case "-": newTD["_text"] = xXmltvFile; break; - case "xTeVe Dummy": newTD["_text"] = xXmltvFile; break; - default: newTD["_text"] = getValueFromProviderFile(xXmltvFile, "xmltv", "name"); break; - - } - //console.log(newTD); - - //newTD["_text"] = item["x-xmltv-file"]; - } else { - //newTD["_text"] = "-" - } - createNewTD(newTD, tr); - tr.lastChild.setAttribute("onclick", 'javascript: mappingDetail("' + item["x-epg"] + '");') - - // Creatr P TD (XMLTV channel ID) - newTD["_element"] = "P"; - newTD["class"] = "tableEllipsis"; - - if (item["x-mapping"] != undefined) { - newTD["_text"] = item["x-mapping"]; - } - - createNewTD(newTD, tr); - tr.lastChild.setAttribute("onclick", 'javascript: mappingDetail("' + item["x-epg"] + '");') - - - var xXmltvFile = item["x-xmltv-file"]; - var xMapping = item["x-mapping"]; - var tvgID = item["tvg-id"]; - - //console.log(item["x-epg"]); - //console.log(item); - - if (item["x-active"] == true) { - tr.className = "activeEPG"; - } else { - tr.className = "notActiveEPG"; - } - - } - - sortTable(1); - - setTimeout(function(){ - showLoadingScreen(false); - }, 5); -} - -function searchInMapping(elm) { - - var search = document.getElementById("searchMapping").value; - var values = getObjKeys(searchObj) - - for (var i = values.length - 1; i >= 0; i--) { - var id = searchObj[values[i]]; - var bool = values[i].toLowerCase().includes(search.toLowerCase()); - switch(bool) { - case true: document.getElementById(id).style.display = ""; break; - case false: document.getElementById(id).style.display = "none"; break; - } - } - -} - -function mappingDetail(xepg) { - - bulkIDs = new Array(); - var activeElement = document.activeElement; - // If input id, return - if (activeElement.tagName == "INPUT") { - return - } - - if (bulk == true) { - var elm = document.getElementsByClassName("bulk"); - for (var i = 1; i < elm.length; i++) { - if (elm[i].checked == true) { - var id = elm[i].parentElement.parentElement.id; - bulkIDs.push(id) - } - - } - - if (bulkIDs.length == 0) { - showElement('popup', false) - alert("No channels selected for editing") - return - } - - xepg = bulkIDs[0] - } - - - createSearchObj(); - - showPopUpElement('mapping-detail'); - - var thisChannel = xEPG["epgMapping"][xepg]; - //console.log(thisChannel); - var xXmltvFile = thisChannel["x-xmltv-file"]; - var xMapping = thisChannel["x-mapping"]; - var xCategory = thisChannel["x-category"]; - - if (xXmltvFile == undefined) { - thisChannel["x-xmltv-file"] = "-"; - xXmltvFile = "-"; - } - - if (xMapping == undefined) { - thisChannel["x-mapping"] = "-"; - xMapping = "-"; - } - - /* - console.log("ID:", xepg); - console.log("XMLTV File:", xXmltvFile); - console.log("Mapping:", xMapping); - */ - - var keys = getObjKeys(thisChannel); - for (var i = 0; i < keys.length; i++) { - if(document.getElementById(keys[i])){ - var td = document.getElementById(keys[i]) - } else { - var td = undefined; - } - - var newItem = new Object(); - var values, text = new Array(); - switch(keys[i]) { - case "x-xmltv-file": - var fileIDs = getObjKeys(xEPG["xmltvMap"]); - var value = new Array("-"); - var text = new Array("-"); - - for (var j = fileIDs.length - 1; j >= 0; j--) { - if (fileIDs[j] != "xTeVe Dummy") { - value.push(getValueFromProviderFile(fileIDs[j], "xmltv", "file.xteve")) - text.push(getValueFromProviderFile(fileIDs[j], "xmltv", "name")) - } else { - value.push(fileIDs[j]) - text.push(fileIDs[j]) - } - - } - - newItem["_element"] = "SELECT"; - newItem["_optionValues"] = value; - newItem["_optionText"] = text - newItem["value"] = xXmltvFile; - newItem["onchange"] = 'javascript: changeXmltvFile("' + xepg + '",this);'; - - break; - - case "x-mapping": - - var values = getObjKeys(xEPG["xmltvMap"][xXmltvFile]); - - for (var j = 0; j < values.length; j++) { - - if (xEPG["xmltvMap"][xXmltvFile][values[j]].hasOwnProperty('display-name') == true) { - var displayName = xEPG["xmltvMap"][xXmltvFile][values[j]]["display-name"]; - } else { - var displayName = "-" - } - - //text[j] = values[j] + " (" + displayName + ")"; - text[j] = displayName + " (" + values[j] + ")"; - } - - text.unshift("-"); - values.unshift("-"); - newItem["_element"] = "SELECT"; - newItem["_optionValues"] = values; - newItem["_optionText"] = text - newItem["value"] = xMapping; - newItem["onchange"] = 'javascript: mappingChannel("' + xepg + '",this);'; - break; - - case "x-category": - //var values = plexCategoriesValues - newItem["_element"] = "SELECT"; - newItem["_optionValues"] = plexCategoriesValues; - newItem["_optionText"] = plexCategoriesOption; - newItem["value"] = xCategory; - newItem["onchange"] = 'saveCategory("' + xepg + '")'; - break; - - case "tvg-logo": - document.getElementById("channel-logo").setAttribute("src", thisChannel["tvg-logo"]); - newItem["_element"] = "INPUT"; - newItem["type"] = "text"; - newItem["value"] = thisChannel["tvg-logo"]; - newItem["onfocusout"] = 'saveChannelLogo("' + xepg + '")'; - newItem["placeholder"] = 'Image URL'; - break; - - case "x-update-channel-icon": - newItem["_element"] = "INPUT"; - newItem["type"] = "checkbox"; - switch(JSON.parse(thisChannel["x-update-channel-icon"])) { - case true: newItem["checked"] = thisChannel["x-update-channel-icon"]; - break - } - newItem["onchange"] = 'saveChannelIconUpdate("' + xepg + '")'; - break; - - case "x-name": - newItem["_element"] = "INPUT"; - newItem["type"] = "text"; - newItem["value"] = thisChannel["x-name"]; - newItem["onfocusout"] = 'saveChannelName("' + xepg + '")'; - newItem["placeholder"] = 'Channel Name'; - break; - - case "x-update-channel-name": - if (thisChannel.hasOwnProperty("_uuid.key") == true) { - newItem["_element"] = "INPUT"; - newItem["type"] = "checkbox"; - switch(JSON.parse(thisChannel["x-update-channel-name"])) { - case true: newItem["checked"] = thisChannel["x-update-channel-name"]; - break - } - newItem["onchange"] = 'saveChannelNameUpdate("' + xepg + '")'; - showElement("streamHasCUID", true) - - break; - } else { - //streamHasCUID - showElement("streamHasCUID", false) - break; - } - - case "x-active": - newItem["_element"] = "INPUT"; - newItem["type"] = "checkbox"; - switch(JSON.parse(thisChannel["x-active"])) { - case true: newItem["checked"] = thisChannel["x-active"]; - break - } - newItem["onchange"] = 'saveChannelStatus("' + xepg + '")'; - break; - - case "x-group-title": - newItem["_element"] = "INPUT"; - newItem["type"] = "text"; - newItem["value"] = thisChannel["x-group-title"]; - newItem["onfocusout"] = 'saveGroupTitle("' + xepg + '")'; - newItem["placeholder"] = 'Group Title'; - break; - - default: - newItem["_element"] = "P"; - newItem["_text"] = thisChannel[keys[i]]; - break; - - } - - if (td != undefined) { - td.innerHTML = ""; - var element = createNewElement(newItem) - //console.log(element); - td.appendChild(element); - } - - } - - if (bulk == true) { - - var elm = document.getElementsByClassName("noBulk"); - for (var i = 0; i < elm.length; i++) { - elm[i].lastChild.setAttribute("readonly", true) - elm[i].lastChild.style.borderColor = "red"; - } - - xepg = bulkIDs[0] - } - - sortSelect(document.getElementById("x-xmltv-file").lastChild); - sortSelect(document.getElementById("x-mapping").lastChild); - -} - -function sortSelect(elem) { - - var tmpAry = []; - // Retain selected value before sorting - var selectedValue = elem[elem.selectedIndex].value; - // Grab all existing entries - for (var i=0;i 0) elem.options[0] = null; - // Restore sorted elements - var newSelectedIndex = 0; - for (var i=0;i 0 && xMapping != "-" && xMapping.length > 0) { - if (xEPG["xmltvMap"][xXmltvFile][xMapping].hasOwnProperty("icon")) { - var logoURL = xEPG["xmltvMap"][xXmltvFile][xMapping]["icon"]; - thisChannel["tvg-logo"] = logoURL; - document.getElementById(xepg).childNodes[2].lastChild.setAttribute("src", logoURL); - document.getElementById("channel-logo").setAttribute("src", logoURL); - } else { - alert("No logo URL in the XMLTV file available") - } - - } - - /* - if (xEPG["xmltvMap"][xXmltvFile][xMapping]["icon"] != undefined) { - - - } - */ - - } -} - -function saveChannelLogo(xepg) { - if (bulk == false) { - var thisChannel = xEPG["epgMapping"][xepg]; - thisChannel["tvg-logo"] = document.getElementById("tvg-logo").lastChild.value; - document.getElementById(xepg).childNodes[2].lastChild.setAttribute("src", thisChannel["tvg-logo"]); - mappingDetail(xepg); - return - } - - if (bulk == true) { - var key = "tvg-logo"; - var value = document.getElementById("tvg-logo").lastChild.value; - saveBulk(key, value); - - mappingDetail(xepg); - return - } -} - -function saveChannelIconUpdate(xepg) { - - var key = "x-update-channel-icon"; - var value = JSON.parse(document.getElementById("x-update-channel-icon").lastChild.checked); - if (bulk == false) { - var thisChannel = xEPG["epgMapping"][xepg]; - thisChannel[key] = value - updateChannelLogo(xepg) - - mappingDetail(xepg); - searchInMapping(); - return - } - - if (bulk == true) { - saveBulk(key, value); - mappingDetail(xepg); - return - } - -} - -function saveChannelName(xepg) { - if (bulk == false) { - var thisChannel = xEPG["epgMapping"][xepg]; - thisChannel["x-name"] = document.getElementById("x-name").lastChild.value; - document.getElementById(xepg).childNodes[3].lastChild.innerHTML = thisChannel["x-name"]; - mappingDetail(xepg); - searchInMapping(); - } - -} - -function saveChannelNameUpdate(xepg) { - var key = "x-update-channel-name"; - var value = JSON.parse(document.getElementById("x-update-channel-name").lastChild.checked); - - if (bulk == false) { - var thisChannel = xEPG["epgMapping"][xepg]; - thisChannel[key] = value - mappingDetail(xepg); - searchInMapping(); - return - } - - if (bulk == true) { - saveBulk(key, value); - mappingDetail(xepg); - return - } - -} - -function saveChannelStatus(xepg) { - var thisChannel = xEPG["epgMapping"][xepg]; - var xXmltvFile = thisChannel["x-xmltv-file"]; - - var key = "x-active"; - var value = JSON.parse(document.getElementById("x-active").lastChild.checked); - - if (xEPG["xmltvMap"].hasOwnProperty(xXmltvFile) == true) { - if (thisChannel["x-mapping"] != "-" && thisChannel["x-mapping"] != undefined) { - thisChannel["x-active"] = !thisChannel["x-active"]; - var tr = document.getElementById(xepg); - switch(thisChannel["x-active"]) { - case true: tr.className = "activeEPG"; break; - case false: tr.className = "notActiveEPG"; break; - } - - } else { - var err = "XMLTV Channel is not selected" - alert(err) - value = false - } - - } else { - if (value == true) { - var err = "XMLTV File is not selecte" - alert(err) - value = false - } - } - - - - if (bulk == false) { - var thisChannel = xEPG["epgMapping"][xepg]; - thisChannel[key] = value - mappingDetail(xepg); - searchInMapping(); - - var tr = document.getElementById(xepg); - switch(thisChannel["x-active"]) { - case true: tr.className = "activeEPG"; break; - case false: tr.className = "notActiveEPG"; break; - } - - return - } - - if (bulk == true) { - saveBulk(key, value); - mappingDetail(xepg); - return - } - -} - -function saveGroupTitle(xepg) { - var key = "x-group-title"; - var value = document.getElementById("x-group-title").lastChild.value; - - if (bulk == false) { - var thisChannel = xEPG["epgMapping"][xepg]; - document.getElementById(xepg).childNodes[5].lastChild.innerHTML = value; - thisChannel[key] = value; - mappingDetail(xepg); - searchInMapping(); - } - - if (bulk == true) { - saveBulk(key, value); - mappingDetail(xepg); - return - } - -} - -function saveCategory(xepg) { - var key = "x-category"; - var value = document.getElementById("x-category").lastChild.value; - - if (bulk == false) { - var thisChannel = xEPG["epgMapping"][xepg]; - thisChannel[key] = value - document.getElementById(xepg).childNodes[3].lastChild.className = value - mappingDetail(xepg); - searchInMapping(); - } - - if (bulk == true) { - saveBulk(key, value); - mappingDetail(xepg); - return - } - -} - -function arrangeTable(elm) { - var tr = elm.parentElement.parentElement; - var newPosition = elm.value; - var x_channelID = tr.id; - - switch(isNaN(newPosition)) { - case true: - alert("Ch. No. must be a number"); - mappingError = true; - break; - } - - - //var item = xEPG["epgMapping"][id]; - var keys = getObjKeys(xEPG["epgMapping"]) - for (var i = 0; i < keys.length; i++) { - var item = xEPG["epgMapping"][keys[i]]; - if (item["x-epg"] == x_channelID) { - - // Check if position exist - var oldPosition = item["x-channelID"]; - - if (oldPosition != newPosition) { - - console.log(newPosition, newPosition.length); - if (newPosition.length == 0) { - mappingError = true - newPosition = oldPosition; - - } - - if (mappingError == true) { - elm.value = oldPosition; - return; - } - - for (var j = keys.length - 1; j >= 0; j--) { - var channel = xEPG["epgMapping"][keys[j]]; - if (keys[j] != x_channelID) { - if (newPosition == channel["x-channelID"]) { // If position exist, set next free position. - newPosition++; - elm.value = newPosition; - arrangeTable(elm); - return; - /* - var newError = new Object(); - newError["err"] = "Duplicate ID"; - checkErr(newError); - sortTable(); - mappingError = true; - document.getElementById(x_channelID).getElementsByTagName("INPUT")[0].focus(); - return; - */ - } - } - } - - } - - //console.log(oldPosition, newPosition); - if (keys[i] == x_channelID && oldPosition != newPosition) { - item["x-channelID"] = newPosition; - } - - document.getElementById("logInfo").className = "notVisible"; - if (columnToSort == 1) { - sortTable(columnToSort); - } - mappingError = false; - - } - } -} - -function changeXmltvFile(xepg, elm) { - - var thisChannel = xEPG["epgMapping"][xepg]; - - var xXmltvFile = elm.value; - var channelID = thisChannel["tvg-id"]; - thisChannel["x-xmltv-file"] = xXmltvFile; - - if (bulk == false) { - - setTimeout(function(){ - - var xMapping = "-" - - // Automap - if (xXmltvFile != "-") { - if (xEPG["xmltvMap"][xXmltvFile].hasOwnProperty(channelID) == true) { - thisChannel["x-mapping"] = channelID; - xMapping = channelID - } else { - thisChannel["x-mapping"] = xMapping - } - } else { - thisChannel["x-mapping"] = xMapping - - } - - var tr = document.getElementById(xepg); - - if (xMapping == "-") { - thisChannel["x-active"] = false; - tr.className = "notActiveEPG" - } else { - thisChannel["x-active"] = true; - tr.className = "activeEPG" - } - - // Show data in table - var td = tr.getElementsByTagName("TD"); - var dataFile = td[td.length - 2].lastChild; - switch(xXmltvFile) { - case "-": dataFile.innerHTML = xXmltvFile; break; - case "xTeVe Dummy": dataFile.innerHTML = xXmltvFile; break; - default: dataFile.innerHTML = getValueFromProviderFile(xXmltvFile, "xmltv", "name"); break; - } - - //xXmltvFile.replace(/^.*[\\\/]/, ''); - - var dataXmltvID = td[td.length - 1].lastChild; - dataXmltvID.innerHTML = xMapping; - - mappingDetail(xepg); - - }, 10); - } - - if (bulk == true) { - var key = "x-xmltv-file" - var value = xXmltvFile - saveBulk(key, value); - - var key = "x-mapping" - var value = "-" - saveBulk(key, value); - mappingDetail(xepg); - return - } - - return -} - -function mappingChannel(xepg, elm) { - var thisChannel = xEPG["epgMapping"][xepg]; - //var xMapping = elm.value; - var xMapping = elm.options[elm.selectedIndex].value - - if (bulk == false) { - - thisChannel["x-mapping"] = xMapping; - - var tr = document.getElementById(xepg); - - if (xMapping == "-") { - thisChannel["x-active"] = false; - tr.className = "notActiveEPG" - } else { - thisChannel["x-active"] = true; - tr.className = "activeEPG" - } - - // Show data in table - var td = tr.getElementsByTagName("TD"); - var dataXmltvID = td[td.length - 1].lastChild; - dataXmltvID.innerHTML = xMapping; - //console.log(td[td.length - 1]); - //console.log(xMapping, elm); - - createSearchObj(); - searchInMapping(); - updateChannelLogo(xepg) - mappingDetail(xepg); - return - } - - if (bulk == true) { - - var key = "x-mapping" - var value = xMapping - saveBulk(key, value); - - mappingDetail(xepg); - return - } - - return -} - - -function createNewTD(newItem, elm) { - var newTD = new Object(); - newTD["_element"] = "TD"; - - elm.appendChild(createElement(newTD)); - var td = elm.lastChild; - - switch(newItem["_element"]) { - case "SELECT": - td.appendChild(createElement(newItem)); - var td = elm.lastChild.lastChild; - var values = newItem["_optionValues"]; - for (var i = 0; i < values.length; i++) { - //console.log(item); - var newEntry = new Object; - newEntry["_element"] = "OPTION"; - newEntry["_text"] = values[i]; - newEntry["value"] = values[i]; - td.appendChild(createElement(newEntry)); - } - td.value = newItem["value"]; - - break; - - default: - - td.appendChild(createElement(newItem)); - break; - } - -} - -function saveXEPG() { - if (mappingError == true) { - alert("Data could not be saved, errors in the XEPG data."); - return; - } - showLoadingScreen(true); - - var data = new Object(); - data["epgMapping"] = xEPG["epgMapping"]; - data["cmd"] = "saveEpgMapping"; - //console.log(data); - xTeVe(data); -} - -function bulkEdit() { - bulk = !bulk; - var className; - - var elm = document.getElementsByClassName("bulk"); - - switch(bulk) { - case true: - className = "bulk showBulk"; - break; - - case false: - className = "bulk hideBulk"; - bulkEditAll = false; - break; - } - - for (var i = 0; i < elm.length; i++) { - elm[i].className = className; - elm[i].checked = false; - } - -} - -function bulkEditAllChannels() { - - var allTR = document.getElementById("id_mapping").getElementsByTagName("TR"); - - for (var i = 1; i < allTR.length; i++) { - if (allTR[i].style.display != "none") { - switch(bulkEditAll) { - case false: allTR[i].firstChild.firstChild.checked = true; break; - case true: allTR[i].firstChild.firstChild.checked = false; break; - } - - } - - } - - bulkEditAll = !bulkEditAll; -} - -function sortTable(columm) { - //console.log(columm); - if (columm == columnToSort) { - //return; - } - - var table = document.getElementById("id_mapping"); - var tableHead = table.getElementsByTagName("TR")[0]; - var tableItems = tableHead.getElementsByTagName("TD"); - - var sortObj = new Object(); - var x, xValue; - var tableHeader - var sortByString = false - - if (columm > 0 && columnToSort > 0) { - tableItems[columnToSort].className = "pointer"; - tableItems[columm].className = "sortThis"; - } - - columnToSort = columm; - - var rows = table.rows; - - if (rows[1] != undefined) { - tableHeader = rows[0] - - x = rows[1].getElementsByTagName("TD")[columm]; - - for (i = 1; i < rows.length; i++) { - - x = rows[i].getElementsByTagName("TD")[columm]; - - switch(x.childNodes[0].tagName.toLowerCase()) { - case "input": - xValue = x.getElementsByTagName("INPUT")[0].value.toLowerCase(); - break; - - case "p": - xValue = x.getElementsByTagName("P")[0].innerText.toLowerCase(); - break; - - default: console.log(x.childNodes[0].tagName); - } - - if (xValue == "" || xValue == NaN) { - xValue = i - sortObj[i] = rows[i]; - - } else { - - switch(isNaN(xValue)) { - case false: - - xValue = parseFloat(xValue); - sortObj[xValue] = rows[i] - break; - - case true: - - sortByString = true - sortObj[xValue.toLowerCase() + i] = rows[i] - break; - - } - - } - - } - - while (table.firstChild) { - table.removeChild(table.firstChild); - } - - var sortValues = getObjKeys(sortObj) - if (sortByString == true) { - sortValues.sort() - } else { - function sortFloat(a, b) { - return a - b; - } - sortValues.sort(sortFloat); - } - - table.appendChild(tableHeader) - - for (var i = 0; i < sortValues.length; i++) { - - table.appendChild(sortObj[sortValues[i]]) - - } - - } - -} - - -function sortTable_old(columm) { - showLoadingScreen(true); - - setTimeout(function(){ - - var table, rows, switching, i, x, y, shouldSwitch; - table = document.getElementById("id_mapping"); - - var tableHead = table.getElementsByTagName("TR")[0]; - var tableItems = tableHead.getElementsByTagName("TD"); - - if (columm > 0) { - tableItems[columnToSort].className = "pointer"; - tableItems[columm].className = "sortThis"; - } - - columnToSort = columm; - - /* - for (var i = 0; i < tableItems.length; i++) { - if (tableItems[i].className != undefined) { - tableItems[i].className = "pointer" - } - - } - */ - - - - console.log(tableItems); - - switching = true; - while (switching) { - switching = false; - rows = table.rows; - for (i = 1; i < (rows.length - 1); i++) { - shouldSwitch = false; - - x = rows[i].getElementsByTagName("TD")[columm]; - y = rows[i + 1].getElementsByTagName("TD")[columm]; - - switch(x.childNodes[0].tagName.toLowerCase()) { - case "input": - xValue = x.getElementsByTagName("INPUT")[0].value.toLowerCase(); - yValue = y.getElementsByTagName("INPUT")[0].value.toLowerCase(); - break; - - case "p": - xValue = x.getElementsByTagName("P")[0].innerText.toLowerCase(); - yValue = y.getElementsByTagName("P")[0].innerText.toLowerCase(); - break; - - default: console.log(x.childNodes[0].tagName); - } - - - switch(isNaN(xValue)) { - case false: xValue = parseFloat(xValue) ; break; - } - - switch(isNaN(yValue)) { - case false: yValue = parseFloat(yValue) ; break; - } - - - if (xValue > yValue) { - shouldSwitch = true; - break; - } - - } - if (shouldSwitch) { - rows[i].parentNode.insertBefore(rows[i + 1], rows[i]); - switching = true; - } - } - createSearchObj() - - showLoadingScreen(false); - }, 20); - -} - -function showXEPG() { - var url = location.protocol + "//" + location.hostname + ":" + location.port + "/xmltv/xteve.xml" - var win = window.open(url, '_blank'); - win.focus(); -} \ No newline at end of file diff --git a/html/js/menu.js b/html/js/menu.js deleted file mode 100644 index 962e921..0000000 --- a/html/js/menu.js +++ /dev/null @@ -1,754 +0,0 @@ - -function setMenuItem() { - - menu = new Object(); - subMenu = new Object(); - - var menu_m3u = new Object(); - menu_m3u["_menuType"] = "inputArray"; - menu_m3u["_element"] = "LI"; - menu_m3u["_configKey"] = "files.m3u"; - menu_m3u["_text"] = "Playlist"; - menu_m3u["_icon"] = "img/m3u.png"; - menu_m3u["_headline"] = "Playlists: Local or remote"; - menu_m3u["_usage"] = "Info
Availability: File availability in percent
Streams: Number of streams in the file.
group-title: Streams that are assigned to a group. Simplifies filtering streams
tvg-id: This ID is used for automatic mapping, must match with the channel ID in the XMLTV file.
Unique ID: Streams with a unique ID to identify them. Allows channel name changes in the M3U without losing the XMLTV mapping (PPV / live events).

Usage M3U:
Remote playlist: http://your.iptv.provider.com/file.m3u
Local playlist: /path/to/file.m3u

Usage HDHomeRun:
IP: 192.168.1.10:5004
" - menu_m3u["name"] = "file"; - menu_m3u["id"] = "file"; - menu_m3u["value"] = menu_m3u["name"]; - menu_m3u["placeholder"] = "Playlist: local or remote"; - menu_m3u["onclick"] = "javascript: toggleMenu(this);"; - menu_m3u["class"] = "menu-notActive"; - - - var menu_filter = new Object(); - menu_filter["_menuType"] = "inputArray"; - menu_filter["_element"] = "LI"; - menu_filter["_configKey"] = "filter"; - menu_filter["_text"] = "Filter"; - menu_filter["_icon"] = "img/filter.png"; - menu_filter["_headline"] = "Filter by M3U parameters, e.g. group-title"; - menu_filter["_usage"] = "Usage:
Sport - All sports channels
Sport {HD} - All HD sports channels
Sport {HD} !{ES,DE} - All HD sports channels, but no Spanish and German

To filter the streams of a HDHomeRun, the playlist name can be entered:
My tuner {HD}" - //menu_filter["_usage"] = "Usage:
All sports channels: Sport
All HD sports channels: Sport {HD}
All HD sports channels, but no Spanish and German: Sport {HD} !{ES,DE}" - menu_filter["name"] = "filter"; - menu_filter["id"] = "M3U"; - menu_filter["value"] = menu_filter["name"]; - menu_filter["placeholder"] = "Filter streams: Sport"; - menu_filter["onclick"] = "javascript: toggleMenu(this);"; - menu_filter["class"] = "menu-notActive"; - - var menu_id = new Object(); - menu_id["_menuType"] = "inputArray"; - menu_id["_element"] = "LI"; - menu_id["_configKey"] = "id"; - menu_id["_text"] = "PMS ID"; - menu_id["_icon"] = "img/number.png"; - menu_id["_headline"] = "Setup PMS guide number"; - menu_id["_usage"] = 'Some playlists have unique channel IDs.
Enter the keyword of the ID. The channel assignment in PMS will change as a result.

e.g. channelID
#EXTINF:0 type="stream" channelId="81", My Streaming Channel HD

Only enter here if you know what you are doing!' - menu_id["name"] = "id"; - menu_id["id"] = "id"; - menu_id["value"] = menu_id["name"]; - menu_id["placeholder"] = "Unique ID from the M3U file"; - menu_id["onclick"] = "javascript: toggleMenu(this);"; - menu_id["class"] = "menu-notActive"; - - - var menu_xmltv = new Object(); - menu_xmltv["_menuType"] = "inputArray"; - menu_xmltv["_element"] = "LI"; - menu_xmltv["_configKey"] = "files.xmltv"; - menu_xmltv["_text"] = "XMLTV"; - menu_xmltv["_icon"] = "img/xmltv.png"; - menu_xmltv["_headline"] = "XMLTV files: Local or remote"; - menu_xmltv["_usage"] = "Info:
Availability: File availability in percent
Channels: Number of channels in the file
Programs: Number of EPG data

Usage:
Remote XMLTV file: http://your.epg.provider.com/guide.xml
Local XMLTV file: /path/to/guide.xml" - menu_xmltv["name"] = "xmltv"; - menu_xmltv["id"] = "xmltv"; - menu_xmltv["value"] = menu_xmltv["name"]; - menu_xmltv["placeholder"] = "XMLTV File: local or remote"; - menu_xmltv["onclick"] = "javascript: toggleMenu(this);"; - menu_xmltv["class"] = "menu-notActive"; - - menu_mapping = new Object(); - menu_mapping["_element"] = "LI"; - menu_mapping["_text"] = "Mapping"; - menu_mapping["_icon"] = "img/mapping.png"; - menu_mapping["_configKey"] = "mapping"; - menu_mapping["_headline"] = "XMLTV assignment and sorting of channels"; - menu_mapping["id"] = "mapping"; - menu_mapping["onclick"] = "javascript: toggleMenu(this);"; - menu_mapping["class"] = "menu-notActive phone"; - - menu_users = new Object(); - menu_users["_element"] = "LI"; - menu_users["_text"] = "Users"; - menu_users["_icon"] = "img/users.png"; - menu_users["_configKey"] = "users"; - menu_users["_headline"] = "Administration of users and permissions"; - menu_users["id"] = "users"; - menu_users["onclick"] = "javascript: toggleMenu(this);"; - menu_users["class"] = "menu-notActive"; - menu_users["_usage"] = "Authorization groups:
WEB: Users can log in to the web interface
PMS: Programs like Plex can access the channel list. Login via DVR IP: username:password@xteve.ip:port
M3U: Allows clients to download the M3U playlist.
XML: Allows clients to download the XMLTV file.
API: Allows clients to use the API interface.

!!! For PMS authentication, only the following special characters are valid: !$()=.,-:;

The individual authentication groups can be activated / deactivated in the settings menu." - - menu_settings = new Object(); - menu_settings["_element"] = "LI"; - menu_settings["_text"] = "Settings"; - menu_settings["_icon"] = "img/settings.png"; - menu_settings["_configKey"] = "settings"; - menu_settings["_headline"] = "Settings"; - menu_settings["_subMenu"] = "701,702,703,704,705,706,707,708,799,710,711,712,713,714"; - menu_settings["id"] = "settings"; - menu_settings["onclick"] = "javascript: toggleMenu(this);"; - menu_settings["class"] = "menu-notActive"; - - menu_log = new Object(); - menu_log["_element"] = "LI"; - menu_log["_text"] = "Log"; - menu_log["_icon"] = "img/log.png"; - menu_log["_headline"] = "Log"; - menu_log["_configKey"] = "log"; - menu_log["id"] = "log"; - menu_log["onclick"] = "javascript: toggleMenu(this);"; - menu_log["class"] = "menu-notActive"; - - menu_logout = new Object(); - menu_logout["_element"] = "LI"; - menu_logout["_text"] = "Logout"; - menu_logout["_icon"] = "img/logout.png"; - menu_logout["id"] = "logout"; - menu_logout["onclick"] = "javascript: logout();"; - menu_logout["class"] = "menu-notActive"; - - var menu_schedule = new Object(); - menu_schedule["_menuType"] = "inputArray"; - menu_schedule["_element"] = "LI"; - menu_schedule["_configKey"] = "update"; - menu_schedule["_text"] = "Schedule"; - menu_schedule["_icon"] = "img/schedule.png"; - menu_schedule["_headline"] = "Schedule for updating M3U, XMLTV files and creating a local backup"; - menu_schedule["_usage"] = "Usage:
0815 = 8:15 am
1930 = 7:30 pm" - menu_schedule["name"] = "update"; - menu_schedule["id"] = "update"; - menu_schedule["value"] = menu_id["name"]; - menu_schedule["placeholder"]= "time of day (24-hour clock)"; - menu_schedule["onclick"] = "javascript: toggleMenu(this);"; - menu_schedule["class"] = "menu-notActive"; - - var menu_filesUpdate = new Object(); - menu_filesUpdate["_element"] = "LI"; - menu_filesUpdate["_menuType"] = "checkbox"; - menu_filesUpdate["_configKey"] = "files.update"; - menu_filesUpdate["_label"] = "Update the provider files at system startup"; - menu_filesUpdate["_headline"] = "Update the provider files at system startup"; - menu_filesUpdate["_usage"] = "Playlists and XMLTV files are updated by xTeVe at system startup." - menu_filesUpdate["name"] = "files.update"; - menu_filesUpdate["id"] = "files.update"; - menu_filesUpdate["value"] = menu_filesUpdate["name"]; - menu_filesUpdate["onclick"] = "javascript: toggleMenu(this);"; - menu_filesUpdate["class"] = "menu-notActive"; - - var menu_tuner = new Object(); - menu_tuner["_element"] = "LI"; - menu_tuner["_menuType"] = "select"; - menu_tuner["_configKey"] = "tuner"; - menu_tuner["_label"] = "Available tuners"; - menu_tuner["_text"] = "Tuner"; - menu_tuner["_icon"] = "img/tuner.png"; - menu_tuner["_headline"] = "Number of tuners"; - menu_tuner["_usage"] = "This setting is only used by Plex and Emby.
The number of concurrent streams allowed by the IPTV provider.
After a change, xTeVe must be delete in the PMS DVR settings and set up again." - menu_tuner["name"] = "tuner"; - menu_tuner["id"] = "tuner"; - menu_tuner["value"] = menu_tuner["name"]; - menu_tuner["placeholder"] = "Number of tuners"; - menu_tuner["onclick"] = "javascript: toggleMenu(this);"; - menu_tuner["class"] = "menu-notActive"; - - var optionValues = new Array(); - for (var i = 1; i <= 100; i++) { - optionValues.push(i) - } - menu_tuner["_optionValues"] = optionValues; - - var menu_epg = new Object(); - menu_epg["_element"] = "LI"; - menu_epg["_menuType"] = "select"; - menu_epg["_configKey"] = "epgSource"; - menu_epg["_label"] = "Selection of the EPG source"; - menu_epg["_text"] = "EPG source"; - menu_epg["_headline"] = "Selection of the EPG source"; - menu_epg["_usage"] = "PMS: Use EPG data from Plex or Emby.
XEPG: Use of external EPG data (XMLTV).
Several XMLTV sources possible.
Allows editing and order channels.
M3U / XMLTV export (HTTP link for IPTV apps)." - menu_epg["name"] = "epgSource"; - menu_epg["id"] = "epgSource"; - menu_epg["value"] = menu_epg["name"]; - menu_epg["placeholder"] = "EPG source"; - menu_epg["onclick"] = "javascript: toggleMenu(this);"; - menu_epg["class"] = "menu-notActive"; - menu_epg["_optionValues"] = new Array("PMS", "XEPG"); - - var menu_xepg = new Object(); - menu_xepg["_element"] = "LI"; - menu_xepg["_menuType"] = "checkbox"; - menu_xepg["_configKey"] = "xteveAutoUpdate"; - menu_xepg["_label"] = "Automatic update of xTeVe"; - menu_xepg["_headline"] = "Automatic update of xTeVe"; - menu_xepg["_usage"] = "If a new version of xTeVe is available, it will be automatically installed." - menu_xepg["name"] = "xteveAutoUpdate"; - menu_xepg["id"] = "xteveAutoUpdate"; - menu_xepg["value"] = menu_xepg["name"]; - menu_xepg["onclick"] = "javascript: toggleMenu(this);"; - menu_xepg["class"] = "menu-notActive"; - - var menu_autoBackupPath = new Object(); - menu_autoBackupPath["_element"] = "LI"; - menu_autoBackupPath["_menuType"] = "singleInput"; - menu_autoBackupPath["_configKey"] = "backup.path"; - menu_autoBackupPath["_label"] = "Location for automatic backups"; - menu_autoBackupPath["_headline"] = "Location for automatic backups"; - menu_autoBackupPath["_usage"] = "Before any update of the provider data by the schedule, xTeVe creates a backup. The path for the automatic backups can be changed. xTeVe requires write permission for this folder." - menu_autoBackupPath["name"] = "backup.path"; - menu_autoBackupPath["id"] = "backup.path"; - menu_autoBackupPath["value"] = menu_autoBackupPath["name"]; - menu_autoBackupPath["onclick"] = "javascript: toggleMenu(this);"; - menu_autoBackupPath["class"] = "menu-notActive"; - - var menu_autoBackupKeep = new Object(); - menu_autoBackupKeep["_element"] = "LI"; - menu_autoBackupKeep["_menuType"] = "select"; - menu_autoBackupKeep["_configKey"] = "backup.keep"; - menu_autoBackupKeep["_text"] = "Keep"; - menu_autoBackupKeep["_label"] = "Number of backups to keep"; - menu_autoBackupKeep["_headline"] = "Number of backups to keep"; - menu_autoBackupKeep["_usage"] = "" - menu_autoBackupKeep["name"] = "backup.keep"; - menu_autoBackupKeep["id"] = "backup.keep"; - menu_autoBackupKeep["value"] = menu_autoBackupKeep["name"]; - menu_autoBackupKeep["onclick"] = "javascript: toggleMenu(this);"; - menu_autoBackupKeep["class"] = "menu-notActive"; - - var optionValues = new Array(5, 10, 20, 30, 40, 50); - menu_autoBackupKeep["_optionValues"] = optionValues; - - - var menu_buffer = new Object(); - menu_buffer["_element"] = "LI"; - menu_buffer["_menuType"] = "checkbox"; - menu_buffer["_configKey"] = "buffer"; - menu_buffer["_label"] = "Stream buffering [Experimental]"; - menu_buffer["_headline"] = "Stream buffering [Experimental]"; - menu_buffer["_usage"] = "With activated buffer, streams can be played and recorded more fluently.
The stream is passed from xTeVe to Plex / Emby" - menu_buffer["name"] = "buffer"; - menu_buffer["id"] = "buffer"; - menu_buffer["value"] = menu_buffer["name"]; - menu_buffer["onclick"] = "javascript: toggleMenu(this);"; - menu_buffer["class"] = "menu-notActive"; - - var menu_api = new Object(); - menu_api["_element"] = "LI"; - menu_api["_menuType"] = "checkbox"; - menu_api["_configKey"] = "api"; - menu_api["_label"] = "API interface"; - menu_api["_headline"] = "API interface"; - menu_api["_usage"] = 'Via API interface it is possible to send commands to xTeVe. API documentation is available here ' - //menu_api["_usage"] = 'Via API interface it is possible to send commands to xTeVe. API documentation is available here ' - menu_api["name"] = "api"; - menu_api["id"] = "api"; - menu_api["value"] = menu_api["name"]; - menu_api["onclick"] = "javascript: toggleMenu(this);"; - menu_api["class"] = "menu-notActive"; - - var menu_authenticationWeb = new Object(); - menu_authenticationWeb["_element"] = "LI"; - menu_authenticationWeb["_menuType"] = "checkbox"; - menu_authenticationWeb["_configKey"] = "authentication.web"; - menu_authenticationWeb["_label"] = "User authentication"; - menu_authenticationWeb["_headline"] = "User authentication"; - menu_authenticationWeb["_usage"] = "Access to xTeVe requires authentication." - menu_authenticationWeb["name"] = "authentication.web"; - menu_authenticationWeb["id"] = "authentication.web"; - menu_authenticationWeb["value"] = menu_authenticationWeb["name"]; - menu_authenticationWeb["onclick"] = "javascript: toggleMenu(this);"; - menu_authenticationWeb["class"] = "menu-notActive"; - - var menu_authenticationPms = new Object(); - menu_authenticationPms["_element"] = "LI"; - menu_authenticationPms["_menuType"] = "checkbox"; - menu_authenticationPms["_configKey"] = "authentication.pms"; - menu_authenticationPms["_label"] = "Plex authentication."; - menu_authenticationPms["_headline"] = "Plex authentication."; - menu_authenticationPms["_usage"] = "Plex requests are only possible with authentication.
Warning!!! After activating this function xTeVe must be delete in the PMS DVR settings and set up again." - menu_authenticationPms["name"] = "authentication.pms"; - menu_authenticationPms["id"] = "authentication.pms"; - menu_authenticationPms["value"] = menu_authenticationPms["name"]; - menu_authenticationPms["onclick"] = "javascript: toggleMenu(this);"; - menu_authenticationPms["class"] = "menu-notActive"; - - var menu_authenticationM3u = new Object(); - menu_authenticationM3u["_element"] = "LI"; - menu_authenticationM3u["_menuType"] = "checkbox"; - menu_authenticationM3u["_configKey"] = "authentication.m3u"; - menu_authenticationM3u["_label"] = "M3U authentication."; - menu_authenticationM3u["_headline"] = "M3U authentication."; - menu_authenticationM3u["_usage"] = "Downloading the M3U file via an HTTP request is only possible with authentication." - menu_authenticationM3u["name"] = "authentication.m3u"; - menu_authenticationM3u["id"] = "authentication.m3u"; - menu_authenticationM3u["value"] = menu_authenticationM3u["name"]; - menu_authenticationM3u["onclick"] = "javascript: toggleMenu(this);"; - menu_authenticationM3u["class"] = "menu-notActive"; - - - var menu_authenticationXml = new Object(); - menu_authenticationXml["_element"] = "LI"; - menu_authenticationXml["_menuType"] = "checkbox"; - menu_authenticationXml["_configKey"] = "authentication.xml"; - menu_authenticationXml["_label"] = "XEPG authentication"; - menu_authenticationXml["_headline"] = "XEPG authentication"; - menu_authenticationXml["_usage"] = "Downloading the XEPG (XMLTV) file via an HTTP request is only possible with authentication." - menu_authenticationXml["name"] = "authentication.xml"; - menu_authenticationXml["id"] = "authentication.xml"; - menu_authenticationXml["value"] = menu_authenticationXml["name"]; - menu_authenticationXml["onclick"] = "javascript: toggleMenu(this);"; - menu_authenticationXml["class"] = "menu-notActive"; - - var menu_authenticationApi = new Object(); - menu_authenticationApi["_element"] = "LI"; - menu_authenticationApi["_menuType"] = "checkbox"; - menu_authenticationApi["_configKey"] = "authentication.api"; - menu_authenticationApi["_label"] = "API authentication"; - menu_authenticationApi["_headline"] = "API authentication"; - menu_authenticationApi["_usage"] = "Access to the API interface is only possible with authentication." - menu_authenticationApi["name"] = "authentication.api"; - menu_authenticationApi["id"] = "authentication.api"; - menu_authenticationApi["value"] = menu_authenticationApi["name"]; - menu_authenticationApi["onclick"] = "javascript: toggleMenu(this);"; - menu_authenticationApi["class"] = "menu-notActive"; - - - // Main menu - menu[10] = menu_m3u; - - switch(config["epgSource"]) { - case "PMS": - menu[20] = menu_id; - break; - - case "XMLTV": - menu[40] = menu_xmltv; - break; - - case "XEPG": - menu[40] = menu_xmltv; - menu[50] = menu_mapping; - break; - } - - menu[30] = menu_filter; - - if (config["authentication.web"] == true) { - menu[60] = menu_users; - } - - menu[70] = menu_settings; - menu[80] = menu_log; - if (config["authentication.web"] == true) { - menu[100] = menu_logout; - } - - - // Sub-Menu - - subMenu[701] = menu_schedule; - subMenu[702] = menu_filesUpdate; - subMenu[703] = menu_tuner; - subMenu[704] = menu_epg; - subMenu[705] = menu_xepg; - subMenu[706] = menu_autoBackupPath; - subMenu[707] = menu_autoBackupKeep; - subMenu[708] = menu_buffer; - - subMenu[710] = menu_authenticationWeb; - - if (config["authentication.web"] == true) { - subMenu[711] = menu_authenticationPms; - subMenu[712] = menu_authenticationM3u; - subMenu[713] = menu_authenticationXml; - subMenu[714] = menu_authenticationApi; - } - - subMenu[799] = menu_api; - - - - return -} - -function createMenu() { - - showElement("popup", false); - - //console.log(config); - setMenuItem(); - var menuItems = getObjKeys(menu) - var nav = document.getElementsByTagName("NAV")[0]; - nav.innerHTML = ""; - var newItem = new Object(); - - for (var i = 0; i < menuItems.length; i++) { - - - var newItem = menu[menuItems[i]]; - newItem["id"] = menuItems[i]; - - - switch(newItem.hasOwnProperty("_icon")) { - case true: - var itemText = newItem["_text"]; - delete newItem["_text"] - nav.appendChild(createElement(newItem)); - newItem["_text"] = itemText; - var newIcon = new Object(); - newIcon["_element"] = "IMG"; - newIcon["src"] = newItem["_icon"]; - - var currentElement = document.getElementById(menuItems[i]); - currentElement.appendChild(createElement(newIcon)); - - - var text = new Object(); - text["_element"] = "P" - text["_text"] = itemText; - text["class"] = "nav-text" - currentElement.appendChild(createElement(text)); - break; - - default: - nav.appendChild(createElement(newIcon)); - break; - } - - } - if (activeMenu != undefined) { - //console.log(activeMenu); - toggleMenu(activeMenu); - } - - return -} - -function toggleMenu(elm) { - //showStreams(false); - clearInterval(logInterval) - activeMenu = elm; - var item = menu[elm.id] - var div = document.getElementById("settings"); - div.innerHTML = ""; - - // Set Headline - var headline = new Object(); - headline["_element"] = "H4"; - headline["_text"] = item["_headline"]; - div.appendChild(createElement(headline)); - - // Sub-Menu - if (item.hasOwnProperty("_subMenu") == true) { - openSubMenu(item); - return - } - - // Mapping, Users, Log, Files - switch(item["_configKey"]) { - case "mapping": openMappingEditor(item); return; break; - case "users": openUsers(item); return; break; - case "log": showLog(item); return; break; - case "files.m3u": openFiles(item, "m3u"); return; break; - case "files.xmltv": openFiles(item, "xmltv"); return; break; - - case "filter": showStreams(true); break; - } - - - - var newHR = new Object(); - newHR["_element"] = "HR" - div.appendChild(createElement(newHR)); - - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "button"; - //newEntry["class"] = "save"; - newEntry["value"] = "Save"; - newEntry["onclick"] = "saveData2('settings')" - div.appendChild(createElement(newEntry)); - - - var newWrapper = new Object(); - newWrapper["_element"] = "DIV"; - newWrapper["id"] = "box-wrapper"; - div.appendChild(createElement(newWrapper)); - - div = div.lastChild; - - div.appendChild(createMenuItem(item)) - - // usage Info - switch(menu[activeMenu.id].hasOwnProperty("_usage")) { - case true: - var usageItem = new Object(); - usageItem["_element"] = "PRE" - usageItem["_text"] = menu[activeMenu.id]["_usage"]; - div.appendChild(createElement(usageItem)); - } - - calculateWrapperHeight(); - -} - -function createMenuItem(item) { - var element = document.createElement("DIV"); - switch(item["_menuType"]) { - case "inputArray": - if (config.hasOwnProperty(item["_configKey"]) == true) { - var value = config[item["_configKey"]]; - } else { - var value = new Array(); - } - - for (var i = 0; i < value.length; i++) { - var newEntry = new Object(); - newEntry = item - delete newEntry["onclick"]; - newEntry["_element"] = "INPUT"; - newEntry["value"] = value[i]; - newEntry["type"] = "search"; - newEntry["data-menutype"] = item["_menuType"]; - newEntry["data-menukey"] = item["_configKey"]; - element.appendChild(createElement(newEntry)); - - } - // New entry for array - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "search"; - newEntry["name"] = item["name"]; - newEntry["placeholder"] = item["placeholder"]; - newEntry["value"] = ""; - newEntry["data-menutype"] = item["_menuType"]; - newEntry["data-menukey"] = item["_configKey"]; - element.appendChild(createElement(newEntry)); - break; - - case "singleInput": - var value = config[item["_configKey"]]; - if (value == undefined) { - value = ""; - } - var newEntry = new Object(); - newEntry = item; - delete newEntry["onclick"]; - newEntry["_element"] = "INPUT"; - newEntry["value"] = value; - newEntry["type"] = "search"; - newEntry["data-menutype"] = item["_menuType"]; - newEntry["data-menukey"] = item["_configKey"]; - element.appendChild(createElement(newEntry)); - break; - - case "checkbox": - var value = config[item["_configKey"]]; - if (value == undefined) { - value = false; - } - var newEntry = new Object(); - newEntry = item; - delete newEntry["onclick"]; - newEntry["_element"] = "INPUT"; - newEntry["value"] = value; - newEntry["type"] = "checkbox"; - newEntry["data-menutype"] = item["_menuType"]; - newEntry["data-menukey"] = item["_configKey"]; - element.appendChild(createElement(newEntry)); - element.getElementsByTagName("INPUT")[0].checked = value; - break; - - case "select": - var value = config[item["_configKey"]]; - var newEntry = new Object(); - newEntry = item; - delete newEntry["onclick"] - newEntry["_element"] = "SELECT"; - element.appendChild(createElement(newEntry)); - var selectElement = element.getElementsByTagName("SELECT")[0]; - var values = item["_optionValues"]; - for (var i = 0; i < values.length; i++) { - var newEntry = new Object; - newEntry["_element"] = "OPTION"; - newEntry["_text"] = item["_text"] + ": " + values[i]; - newEntry["value"] = values[i]; - selectElement.appendChild(createElement(newEntry)); - } - selectElement.value = value; - break; - - } - return element; -} - -function openSubMenu(item) { - var entrys = item["_subMenu"].split(","); - var div = document.getElementById("settings"); - - var newHR = new Object(); - newHR["_element"] = "HR" - div.appendChild(createElement(newHR)); - - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "button"; - //newEntry["class"] = "save"; - newEntry["value"] = "Save"; - newEntry["onclick"] = "saveData2('settings')" - div.appendChild(createElement(newEntry)); - - if (item["_configKey"] == "settings") { - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "button"; - //newEntry["class"] = "save"; - newEntry["value"] = "Backup"; - newEntry["onclick"] = "xteveBackup()" - div.appendChild(createElement(newEntry)); - } - - if (item["_configKey"] == "settings") { - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "button"; - //newEntry["class"] = "save"; - newEntry["value"] = "Restore"; - newEntry["onclick"] = "xteveRestore(this)" - div.appendChild(createElement(newEntry)); - } - - - var newWrapper = new Object(); - newWrapper["_element"] = "DIV"; - newWrapper["id"] = "box-wrapper"; - div.appendChild(createElement(newWrapper)); - - div = div.lastChild; - - - for (var i = 0; i < entrys.length; i++) { - var item = subMenu[entrys[i]]; - if (item == undefined) { - break; - } - - var container = new Object(); - container["_element"] = "DIV"; - div.appendChild(createElement(container)); - - var divContainer = div.lastChild; - - var headline = new Object(); - headline["_element"] = "H5"; - headline["_text"] = item["_headline"]; - divContainer.appendChild(createElement(headline)); - - divContainer.appendChild(createMenuItem(item)) - - switch(item.hasOwnProperty("_usage")) { - case true: - var usageItem = new Object(); - usageItem["_element"] = "PRE" - usageItem["_text"] = item["_usage"]; - divContainer.appendChild(createElement(usageItem)); - } - - var hr = new Object(); - hr["_element"] = "HR"; - divContainer.appendChild(createElement(hr)); - - } - - calculateWrapperHeight(); - return -} - -function saveData2(elm) { - var div = document.getElementById(elm); - var inputs = div.getElementsByTagName("INPUT"); - var selects = div.getElementsByTagName("SELECT"); - var value, configKey; - var data = new Object(); - var valueArr = new Array(); - var newData = false; - - for (var i = 0; i < inputs.length; i++) { - if (inputs[i].type != "button") { - var menuType = inputs[i].getAttribute("data-menutype"); - - //console.log(menuType); - switch(menuType) { - case "singleInput": - value = inputs[i].value; - if (value == "" || value == undefined) { - data = new Object(); - data["delete"] = inputs[i].name - newData = true; - } else { - newData = true; - data[inputs[i].name] = value; - console.log(data); - } - break; - case "inputArray": - value = inputs[i].value; - if (value != "" && value != undefined) { - newData = true; - valueArr.push(value) - data[inputs[i].name] = valueArr; - configKey = inputs[i].name; - } - - break; - - case "checkbox": - value = inputs[i].checked - data[inputs[i].name] = value; - } - - } - - } - - - // Delete config key - if (valueArr.length == 0 && newData == false) { - newData = true; - data = new Object(); - data["delete"] = configKey; - } - - - for (var i = 0; i < selects.length; i++) { - var value = selects[i].options[selects[i].selectedIndex].value; - switch(isNaN(value)) { - case false: value = parseInt(value); break; - } - - data[selects[i].name] = value; - newData = true; - } - - //console.log(data, newData); - - if (newData == true) { - data["cmd"] = "saveConfig"; - if (!data.hasOwnProperty('filter')) { - data["filter"] = config["filter"] - } - var settings = new Object(); - settings["cmd"] = data["cmd"]; - settings["settings"] = data; - console.log(settings); - xTeVe(settings); - } -} diff --git a/html/js/menu_ts.js b/html/js/menu_ts.js deleted file mode 100644 index 8cb5a78..0000000 --- a/html/js/menu_ts.js +++ /dev/null @@ -1,1757 +0,0 @@ -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var MainMenu = /** @class */ (function () { - function MainMenu() { - this.DocumentID = "main-menu"; - this.HTMLTag = "LI"; - this.ImagePath = "img/"; - } - MainMenu.prototype.createIMG = function (src) { - var element = document.createElement("IMG"); - element.setAttribute("src", this.ImagePath + src); - return element; - }; - MainMenu.prototype.createValue = function (value) { - var element = document.createElement("P"); - element.innerHTML = value; - return element; - }; - return MainMenu; -}()); -var MainMenuItem = /** @class */ (function (_super) { - __extends(MainMenuItem, _super); - function MainMenuItem(menuKey, value, image, headline) { - var _this = _super.call(this) || this; - _this.menuKey = menuKey; - _this.value = value; - _this.imgSrc = image; - _this.headline = headline; - return _this; - } - MainMenuItem.prototype.createItem = function () { - var item = document.createElement("LI"); - item.setAttribute("onclick", "javascript: openThisMenu(this)"); - item.setAttribute("id", this.id); - var img = this.createIMG(this.imgSrc); - var value = this.createValue(this.value); - item.appendChild(img); - item.appendChild(value); - var doc = document.getElementById(this.DocumentID); - doc.appendChild(item); - switch (this.menuKey) { - case "playlist": - this.tableHeader = ["{{.playlist.table.playlist}}", "{{.playlist.table.tuner}}", "{{.playlist.table.lastUpdate}}", "{{.playlist.table.availability}} %", "{{.playlist.table.type}}", "{{.playlist.table.streams}}", "{{.playlist.table.groupTitle}} %", "{{.playlist.table.tvgID}} %", "{{.playlist.table.uniqueID}} %"]; - break; - case "xmltv": - this.tableHeader = ["{{.xmltv.table.guide}}", "{{.xmltv.table.lastUpdate}}", "{{.xmltv.table.availability}} %", "{{.xmltv.table.channels}}", "{{.xmltv.table.programs}}"]; - break; - case "filter": - this.tableHeader = ["{{.filter.table.name}}", "{{.filter.table.type}}", "{{.filter.table.filter}}"]; - break; - case "users": - this.tableHeader = ["{{.users.table.username}}", "{{.users.table.password}}", "{{.users.table.web}}", "{{.users.table.pms}}", "{{.users.table.m3u}}", "{{.users.table.xml}}", "{{.users.table.api}}"]; - break; - case "mapping": - this.tableHeader = ["BULK", "{{.mapping.table.chNo}}", "{{.mapping.table.logo}}", "{{.mapping.table.channelName}}", "{{.mapping.table.playlist}}", "{{.mapping.table.groupTitle}}", "{{.mapping.table.xmltvFile}}", "{{.mapping.table.xmltvID}}"]; - break; - } - //console.log(this.menuKey, this.tableHeader); - }; - return MainMenuItem; -}(MainMenu)); -var Content = /** @class */ (function () { - function Content() { - this.DocumentID = "content"; - this.TableID = "content_table"; - this.headerClass = "content_table_header"; - this.interactionID = "content-interaction"; - } - Content.prototype.createHeadline = function (value) { - var element = document.createElement("H3"); - element.innerHTML = value; - return element; - }; - Content.prototype.createHR = function () { - var element = document.createElement("HR"); - return element; - }; - Content.prototype.createInteraction = function () { - var element = document.createElement("DIV"); - element.setAttribute("id", this.interactionID); - return element; - }; - Content.prototype.createDIV = function () { - var element = document.createElement("DIV"); - element.id = this.DivID; - return element; - }; - Content.prototype.createTABLE = function () { - var element = document.createElement("TABLE"); - element.id = this.TableID; - return element; - }; - Content.prototype.createTableRow = function () { - var element = document.createElement("TR"); - element.className = this.headerClass; - return element; - }; - Content.prototype.createTableContent = function (menuKey) { - var data = new Object(); - var rows = new Array(); - switch (menuKey) { - case "playlist": - var fileTypes = new Array("m3u", "hdhr"); - fileTypes.forEach(function (fileType) { - data = SERVER["settings"]["files"][fileType]; - var keys = getObjKeys(data); - keys.forEach(function (key) { - var tr = document.createElement("TR"); - tr.id = key; - tr.setAttribute('onclick', 'javascript: openPopUp("' + fileType + '", this)'); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["name"]; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - if (SERVER["settings"]["buffer"] != "-") { - cell.value = data[key]["tuner"]; - } - else { - cell.value = "-"; - } - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["last.update"]; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["provider.availability"]; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["type"].toUpperCase(); - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["compatibility"]["streams"]; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["compatibility"]["group.title"]; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["compatibility"]["tvg.id"]; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["compatibility"]["stream.id"]; - tr.appendChild(cell.createCell()); - rows.push(tr); - }); - }); - break; - case "filter": - delete SERVER["settings"]["filter"][-1]; - data = SERVER["settings"]["filter"]; - var keys = getObjKeys(data); - keys.forEach(function (key) { - var tr = document.createElement("TR"); - tr.id = key; - tr.setAttribute('onclick', 'javascript: openPopUp("' + data[key]["type"] + '", this)'); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["name"]; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - switch (data[key]["type"]) { - case "custom-filter": - cell.value = "{{.filter.custom}}"; - break; - case "group-title": - cell.value = "{{.filter.group}}"; - break; - default: - break; - } - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["filter"]; - tr.appendChild(cell.createCell()); - rows.push(tr); - }); - break; - case "xmltv": - var fileTypes = new Array("xmltv"); - fileTypes.forEach(function (fileType) { - data = SERVER["settings"]["files"][fileType]; - var keys = getObjKeys(data); - keys.forEach(function (key) { - var tr = document.createElement("TR"); - tr.id = key; - tr.setAttribute('onclick', 'javascript: openPopUp("' + fileType + '", this)'); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["name"]; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["last.update"]; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["provider.availability"]; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["compatibility"]["xmltv.channels"]; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["compatibility"]["xmltv.programs"]; - tr.appendChild(cell.createCell()); - rows.push(tr); - }); - }); - break; - case "users": - var fileTypes = new Array("users"); - fileTypes.forEach(function (fileType) { - data = SERVER[fileType]; - var keys = getObjKeys(data); - keys.forEach(function (key) { - var tr = document.createElement("TR"); - tr.id = key; - tr.setAttribute('onclick', 'javascript: openPopUp("' + fileType + '", this)'); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["data"]["username"]; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = "******"; - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - if (data[key]["data"]["authentication.web"] == true) { - cell.value = "✓"; - } - else { - cell.value = "-"; - } - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - if (data[key]["data"]["authentication.pms"] == true) { - cell.value = "✓"; - } - else { - cell.value = "-"; - } - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - if (data[key]["data"]["authentication.m3u"] == true) { - cell.value = "✓"; - } - else { - cell.value = "-"; - } - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - if (data[key]["data"]["authentication.xml"] == true) { - cell.value = "✓"; - } - else { - cell.value = "-"; - } - tr.appendChild(cell.createCell()); - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - if (data[key]["data"]["authentication.api"] == true) { - cell.value = "✓"; - } - else { - cell.value = "-"; - } - tr.appendChild(cell.createCell()); - rows.push(tr); - }); - }); - break; - case "mapping": - BULK_EDIT = false; - createSearchObj(); - checkUndo("epgMapping"); - console.log("MAPPING"); - data = SERVER["xepg"]["epgMapping"]; - var keys = getObjKeys(data); - keys.forEach(function (key) { - var tr = document.createElement("TR"); - tr.id = key; - //tr.setAttribute('oncontextmenu', 'javascript: rightClick(this)') - switch (data[key]["x-active"]) { - case true: - tr.className = "activeEPG"; - break; - case false: - tr.className = "notActiveEPG"; - break; - } - // Bulk - var cell = new Cell(); - cell.child = true; - cell.childType = "BULK"; - cell.value = false; - tr.appendChild(cell.createCell()); - // Kanalnummer - var cell = new Cell(); - cell.child = true; - cell.childType = "INPUTCHANNEL"; - cell.value = data[key]["x-channelID"]; - //td.setAttribute('onclick', 'javascript: changeChannelNumber("' + key + '", this)') - tr.appendChild(cell.createCell()); - // Logo - var cell = new Cell(); - cell.child = true; - cell.childType = "IMG"; - cell.imageURL = data[key]["tvg-logo"]; - var td = cell.createCell(); - td.setAttribute('onclick', 'javascript: openPopUp("mapping", this)'); - td.id = key; - tr.appendChild(td); - // Kanalname - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.className = data[key]["x-category"]; - cell.value = data[key]["x-name"]; - var td = cell.createCell(); - td.setAttribute('onclick', 'javascript: openPopUp("mapping", this)'); - td.id = key; - tr.appendChild(td); - // Playlist - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - //cell.value = data[key]["_file.m3u.name"] - cell.value = getValueFromProviderFile(data[key]["_file.m3u.id"], "m3u", "name"); - var td = cell.createCell(); - td.setAttribute('onclick', 'javascript: openPopUp("mapping", this)'); - td.id = key; - tr.appendChild(td); - // Gruppe (group-title) - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = data[key]["x-group-title"]; - var td = cell.createCell(); - td.setAttribute('onclick', 'javascript: openPopUp("mapping", this)'); - td.id = key; - tr.appendChild(td); - // XMLTV Datei - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - if (data[key]["x-xmltv-file"] != "-") { - cell.value = getValueFromProviderFile(data[key]["x-xmltv-file"], "xmltv", "name"); - } - else { - cell.value = data[key]["x-xmltv-file"]; - } - var td = cell.createCell(); - td.setAttribute('onclick', 'javascript: openPopUp("mapping", this)'); - td.id = key; - tr.appendChild(td); - // XMLTV Kanal - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - //var value = str.substring(1, 4); - var value = data[key]["x-mapping"]; - if (value.length > 20) { - value = data[key]["x-mapping"].substring(0, 20) + "..."; - } - cell.value = value; - var td = cell.createCell(); - td.setAttribute('onclick', 'javascript: openPopUp("mapping", this)'); - td.id = key; - tr.appendChild(td); - rows.push(tr); - }); - break; - case "settings": - alert(); - break; - default: - console.log("Table content (menuKey):", menuKey); - break; - } - return rows; - }; - return Content; -}()); -var Cell = /** @class */ (function () { - function Cell() { - } - Cell.prototype.createCell = function () { - var td = document.createElement("TD"); - if (this.child == true) { - var element; - switch (this.childType) { - case "P": - element = document.createElement(this.childType); - element.innerHTML = this.value; - element.className = this.className; - break; - case "INPUT": - element = document.createElement(this.childType); - element.value = this.value; - element.type = "text"; - break; - case "INPUTCHANNEL": - element = document.createElement("INPUT"); - element.setAttribute("onchange", "javscript: changeChannelNumber(this)"); - element.value = this.value; - element.type = "text"; - break; - case "BULK": - element = document.createElement("INPUT"); - element.checked = this.value; - element.type = "checkbox"; - element.className = "bulk hideBulk"; - break; - case "BULK_HEAD": - element = document.createElement("INPUT"); - element.checked = this.value; - element.type = "checkbox"; - element.className = "bulk hideBulk"; - element.setAttribute("onclick", "javascript: selectAllChannels()"); - break; - case "IMG": - element = document.createElement(this.childType); - element.setAttribute("src", this.imageURL); - if (this.imageURL != "") { - element.setAttribute("onerror", "javascript: this.onerror=null;this.src=''"); - //onerror="this.onerror=null;this.src='missing.gif';" - } - } - td.appendChild(element); - } - else { - td.innerHTML = this.value; - } - if (this.onclick == true) { - td.setAttribute("onclick", this.onclickFunktion); - td.className = "pointer"; - } - if (this.tdClassName != undefined) { - td.className = this.tdClassName; - } - return td; - }; - return Cell; -}()); -var ShowContent = /** @class */ (function (_super) { - __extends(ShowContent, _super); - function ShowContent(menuID) { - var _this = _super.call(this) || this; - _this.menuID = menuID; - return _this; - } - ShowContent.prototype.createInput = function (type, name, value) { - var input = document.createElement("INPUT"); - input.setAttribute("type", type); - input.setAttribute("name", name); - input.setAttribute("value", value); - return input; - }; - ShowContent.prototype.show = function () { - COLUMN_TO_SORT = -1; - // Alten Inhalt löschen - var doc = document.getElementById(this.DocumentID); - doc.innerHTML = ""; - showPreview(false); - // Überschrift - var headline = menuItems[this.menuID].headline; - var menuKey = menuItems[this.menuID].menuKey; - var h = this.createHeadline(headline); - doc.appendChild(h); - var hr = this.createHR(); - doc.appendChild(hr); - // Interaktion - var div = this.createInteraction(); - doc.appendChild(div); - var interaction = document.getElementById(this.interactionID); - switch (menuKey) { - case "playlist": - var input = this.createInput("button", menuKey, "{{.button.new}}"); - input.setAttribute("id", "-"); - input.setAttribute("onclick", 'javascript: openPopUp("playlist")'); - interaction.appendChild(input); - break; - case "filter": - var input = this.createInput("button", menuKey, "{{.button.new}}"); - input.setAttribute("id", -1); - input.setAttribute("onclick", 'javascript: openPopUp("filter", this)'); - interaction.appendChild(input); - break; - case "xmltv": - var input = this.createInput("button", menuKey, "{{.button.new}}"); - input.setAttribute("id", "xmltv"); - input.setAttribute("onclick", 'javascript: openPopUp("xmltv")'); - interaction.appendChild(input); - break; - case "users": - var input = this.createInput("button", menuKey, "{{.button.new}}"); - input.setAttribute("id", "users"); - input.setAttribute("onclick", 'javascript: openPopUp("users")'); - interaction.appendChild(input); - break; - case "mapping": - showElement("loading", true); - var input = this.createInput("button", menuKey, "{{.button.save}}"); - input.setAttribute("onclick", 'javascript: savePopupData("mapping", "", "")'); - interaction.appendChild(input); - var input = this.createInput("button", menuKey, "{{.button.bulkEdit}}"); - input.setAttribute("onclick", 'javascript: bulkEdit()'); - interaction.appendChild(input); - var input = this.createInput("search", "search", ""); - input.setAttribute("id", "searchMapping"); - input.setAttribute("placeholder", "{{.button.search}}"); - input.className = "search"; - input.setAttribute("onchange", 'javascript: searchInMapping()'); - interaction.appendChild(input); - break; - case "settings": - var input = this.createInput("button", menuKey, "{{.button.save}}"); - input.setAttribute("onclick", 'javascript: saveSettings();'); - interaction.appendChild(input); - var input = this.createInput("button", menuKey, "{{.button.backup}}"); - input.setAttribute("onclick", 'javascript: backup();'); - interaction.appendChild(input); - var input = this.createInput("button", menuKey, "{{.button.restore}}"); - input.setAttribute("onclick", 'javascript: restore();'); - interaction.appendChild(input); - var wrapper = document.createElement("DIV"); - wrapper.setAttribute("id", "box-wrapper"); - doc.appendChild(wrapper); - this.DivID = "content_settings"; - var settings = this.createDIV(); - wrapper.appendChild(settings); - showSettings(); - return; - break; - case "log": - var input = this.createInput("button", menuKey, "{{.button.resetLogs}}"); - input.setAttribute("onclick", 'javascript: resetLogs();'); - interaction.appendChild(input); - var wrapper = document.createElement("DIV"); - wrapper.setAttribute("id", "box-wrapper"); - doc.appendChild(wrapper); - this.DivID = "content_log"; - var logs = this.createDIV(); - wrapper.appendChild(logs); - showLogs(true); - return; - break; - case "logout": - location.reload(); - document.cookie = "Token= ; expires = Thu, 01 Jan 1970 00:00:00 GMT"; - break; - default: - console.log("Show content (menuKey):", menuKey); - break; - } - // Tabelle erstellen (falls benötigt) - var tableHeader = menuItems[this.menuID].tableHeader; - if (tableHeader.length > 0) { - var wrapper = document.createElement("DIV"); - doc.appendChild(wrapper); - wrapper.setAttribute("id", "box-wrapper"); - var table = this.createTABLE(); - wrapper.appendChild(table); - var header = this.createTableRow(); - table.appendChild(header); - // Kopfzeile der Tablle - tableHeader.forEach(function (element) { - var cell = new Cell(); - cell.child = true; - cell.childType = "P"; - cell.value = element; - if (element == "BULK") { - cell.childType = "BULK_HEAD"; - cell.value = false; - } - if (menuKey == "mapping") { - if (element == "{{.mapping.table.chNo}}") { - cell.onclick = true; - cell.onclickFunktion = "javascript: sortTable(1);"; - cell.tdClassName = "sortThis"; - } - if (element == "{{.mapping.table.channelName}}") { - cell.onclick = true; - cell.onclickFunktion = "javascript: sortTable(3);"; - } - if (element == "{{.mapping.table.playlist}}") { - cell.onclick = true; - cell.onclickFunktion = "javascript: sortTable(4);"; - } - if (element == "{{.mapping.table.groupTitle}}") { - cell.onclick = true; - cell.onclickFunktion = "javascript: sortTable(5);"; - } - } - header.appendChild(cell.createCell()); - }); - table.appendChild(header); - // Inhalt der Tabelle - var rows = this.createTableContent(menuKey); - rows.forEach(function (tr) { - table.appendChild(tr); - }); - } - switch (menuKey) { - case "mapping": - sortTable(1); - break; - case "filter": - showPreview(true); - sortTable(0); - break; - default: - COLUMN_TO_SORT = -1; - sortTable(0); - break; - } - showElement("loading", false); - }; - return ShowContent; -}(Content)); -function PageReady() { - var server = new Server("getServerConfig"); - server.request(new Object()); - window.addEventListener("resize", function () { - calculateWrapperHeight(); - }, true); - setInterval(function () { - updateLog(); - }, 10000); - return; -} -function createLayout() { - // Client Info - var obj = SERVER["clientInfo"]; - var keys = getObjKeys(obj); - for (var i = 0; i < keys.length; i++) { - if (document.getElementById(keys[i])) { - document.getElementById(keys[i]).innerHTML = obj[keys[i]]; - } - } - if (!document.getElementById("main-menu")) { - return; - } - // Menü erstellen - document.getElementById("main-menu").innerHTML = ""; - for (var i_1 = 0; i_1 < menuItems.length; i_1++) { - menuItems[i_1].id = i_1; - switch (menuItems[i_1]["menuKey"]) { - case "users": - case "logout": - if (SERVER["settings"]["authentication.web"] == true) { - menuItems[i_1].createItem(); - } - break; - case "mapping": - case "xmltv": - if (SERVER["clientInfo"]["epgSource"] == "XEPG") { - menuItems[i_1].createItem(); - } - break; - default: - menuItems[i_1].createItem(); - break; - } - } - return; -} -function openThisMenu(element) { - var id = element.id; - var content = new ShowContent(id); - content.show(); - calculateWrapperHeight(); - return; -} -var PopupWindow = /** @class */ (function () { - function PopupWindow() { - this.DocumentID = "popup-custom"; - this.InteractionID = "interaction"; - this.doc = document.getElementById(this.DocumentID); - } - PopupWindow.prototype.createTitle = function (title) { - var td = document.createElement("TD"); - td.className = "left"; - td.innerHTML = title + ":"; - return td; - }; - PopupWindow.prototype.createContent = function (element) { - var td = document.createElement("TD"); - td.appendChild(element); - return td; - }; - PopupWindow.prototype.createInteraction = function () { - var div = document.createElement("div"); - div.setAttribute("id", "popup-interaction"); - div.className = "interaction"; - this.doc.appendChild(div); - }; - return PopupWindow; -}()); -var PopupContent = /** @class */ (function (_super) { - __extends(PopupContent, _super); - function PopupContent() { - var _this = _super !== null && _super.apply(this, arguments) || this; - _this.table = document.createElement("TABLE"); - return _this; - } - PopupContent.prototype.createHeadline = function (headline) { - this.doc.innerHTML = ""; - var element = document.createElement("H3"); - element.innerHTML = headline.toUpperCase(); - this.doc.appendChild(element); - // Tabelle erstellen - this.table = document.createElement("TABLE"); - this.doc.appendChild(this.table); - }; - PopupContent.prototype.appendRow = function (title, element) { - var tr = document.createElement("TR"); - // Bezeichnung - if (title.length != 0) { - tr.appendChild(this.createTitle(title)); - } - // Content - tr.appendChild(this.createContent(element)); - this.table.appendChild(tr); - }; - PopupContent.prototype.createInput = function (type, name, value) { - var input = document.createElement("INPUT"); - if (value == undefined) { - value = ""; - } - input.setAttribute("type", type); - input.setAttribute("name", name); - input.setAttribute("value", value); - return input; - }; - PopupContent.prototype.createCheckbox = function (name) { - var input = document.createElement("INPUT"); - input.setAttribute("type", "checkbox"); - input.setAttribute("name", name); - return input; - }; - PopupContent.prototype.createSelect = function (text, values, set, dbKey) { - var select = document.createElement("SELECT"); - select.setAttribute("name", dbKey); - for (var i = 0; i < text.length; i++) { - var option = document.createElement("OPTION"); - option.setAttribute("value", values[i]); - option.innerText = text[i]; - select.appendChild(option); - } - if (set != "") { - select.value = set; - } - if (set == undefined) { - select.value = values[0]; - } - return select; - }; - PopupContent.prototype.selectOption = function (select, value) { - //select.selectedOptions = value - var s = select; - s.options[s.selectedIndex].value = value; - return select; - }; - PopupContent.prototype.description = function (value) { - var tr = document.createElement("TR"); - var td = document.createElement("TD"); - var span = document.createElement("PRE"); - span.innerHTML = value; - tr.appendChild(td); - tr.appendChild(this.createContent(span)); - this.table.appendChild(tr); - }; - // Interaktion - PopupContent.prototype.addInteraction = function (element) { - var interaction = document.getElementById("popup-interaction"); - interaction.appendChild(element); - }; - return PopupContent; -}(PopupWindow)); -function openPopUp(dataType, element) { - var data = new Object(); - var id; - switch (element) { - case undefined: - switch (dataType) { - case "group-title": - if (id == undefined) { - id = -1; - } - data = getLocalData("filter", id); - data["type"] = "group-title"; - break; - case "custom-filter": - if (id == undefined) { - id = -1; - } - data = getLocalData("filter", id); - data["type"] = "custom-filter"; - break; - default: - data["id.provider"] = "-"; - data["type"] = dataType; - id = "-"; - break; - } - break; - default: - id = element.id; - data = getLocalData(dataType, id); - break; - } - var content = new PopupContent(); - switch (dataType) { - case "playlist": - content.createHeadline("{{.playlist.playlistType.title}}"); - // Type - var text = ["M3U", "HDHomeRun"]; - var values = ["javascript: openPopUp('m3u')", "javascript: openPopUp('hdhr')"]; - var select = content.createSelect(text, values, "", "type"); - select.setAttribute("id", "type"); - select.setAttribute("onchange", 'javascript: changeButtonAction(this, "next", "onclick")'); // changeButtonAction - content.appendRow("{{.playlist.type.title}}", select); - // Interaktion - content.createInteraction(); - // Abbrechen - var input = content.createInput("button", "cancel", "{{.button.cancel}}"); - input.setAttribute("onclick", 'javascript: showElement("popup", false);'); - content.addInteraction(input); - // Weiter - var input = content.createInput("button", "next", "{{.button.next}}"); - input.setAttribute("onclick", 'javascript: openPopUp("m3u")'); - input.setAttribute("id", 'next'); - content.addInteraction(input); - break; - case "m3u": - content.createHeadline(dataType); - // Name - var dbKey = "name"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.playlist.name.placeholder}}"); - content.appendRow("{{.playlist.name.title}}", input); - // Beschreibung - var dbKey = "description"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.playlist.description.placeholder}}"); - content.appendRow("{{.playlist.description.title}}", input); - // URL - var dbKey = "file.source"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.playlist.fileM3U.placeholder}}"); - content.appendRow("{{.playlist.fileM3U.title}}", input); - // Tuner - if (SERVER["settings"]["buffer"] != "-") { - var text = new Array(); - var values = new Array(); - for (var i = 1; i <= 100; i++) { - text.push(i.toString()); - values.push(i.toString()); - } - var dbKey = "tuner"; - var select = content.createSelect(text, values, data[dbKey], dbKey); - select.setAttribute("onfocus", "javascript: return;"); - content.appendRow("{{.playlist.tuner.title}}", select); - } - else { - var dbKey = "tuner"; - if (data[dbKey] == undefined) { - data[dbKey] = 1; - } - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("readonly", "true"); - input.className = "notAvailable"; - content.appendRow("{{.playlist.tuner.title}}", input); - } - content.description("{{.playlist.tuner.description}}"); - // Interaktion - content.createInteraction(); - // Löschen - if (data["id.provider"] != "-") { - var input = content.createInput("button", "delete", "{{.button.delete}}"); - input.className = "delete"; - input.setAttribute('onclick', 'javascript: savePopupData("m3u", "' + id + '", true, 0)'); - content.addInteraction(input); - } - else { - var input = content.createInput("button", "back", "{{.button.back}}"); - input.setAttribute("onclick", 'javascript: openPopUp("playlist")'); - content.addInteraction(input); - } - // Abbrechen - var input = content.createInput("button", "cancel", "{{.button.cancel}}"); - input.setAttribute("onclick", 'javascript: showElement("popup", false);'); - content.addInteraction(input); - // Aktualisieren - if (data["id.provider"] != "-") { - var input = content.createInput("button", "update", "{{.button.update}}"); - input.setAttribute('onclick', 'javascript: savePopupData("m3u", "' + id + '", false, 1)'); - content.addInteraction(input); - } - // Speichern - var input = content.createInput("button", "save", "{{.button.save}}"); - input.setAttribute('onclick', 'javascript: savePopupData("m3u", "' + id + '", false, 0)'); - content.addInteraction(input); - break; - case "hdhr": - content.createHeadline(dataType); - // Name - var dbKey = "name"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.playlist.name.placeholder}}"); - content.appendRow("{{.playlist.name.title}}", input); - // Beschreibung - var dbKey = "description"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.playlist.description.placeholder}}"); - content.appendRow("{{.playlist.description.placeholder}}", input); - // URL - var dbKey = "file.source"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.playlist.fileHDHR.placeholder}}"); - content.appendRow("{{.playlist.fileHDHR.title}}", input); - // Tuner - if (SERVER["settings"]["buffer"] != "-") { - var text = new Array(); - var values = new Array(); - for (var i = 1; i <= 100; i++) { - text.push(i.toString()); - values.push(i.toString()); - } - var dbKey = "tuner"; - var select = content.createSelect(text, values, data[dbKey], dbKey); - select.setAttribute("onfocus", "javascript: return;"); - content.appendRow("{{.playlist.tuner.title}}", select); - } - else { - var dbKey = "tuner"; - if (data[dbKey] == undefined) { - data[dbKey] = 1; - } - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("readonly", "true"); - input.className = "notAvailable"; - content.appendRow("{{.playlist.tuner.title}}", input); - } - content.description("{{.playlist.tuner.description}}"); - // Interaktion - content.createInteraction(); - // Löschen - if (data["id.provider"] != "-") { - var input = content.createInput("button", "delete", "{{.button.delete}}"); - input.setAttribute('onclick', 'javascript: savePopupData("hdhr", "' + id + '", true, 0)'); - input.className = "delete"; - content.addInteraction(input); - } - else { - var input = content.createInput("button", "back", "{{.button.back}}"); - input.setAttribute("onclick", 'javascript: openPopUp("playlist")'); - content.addInteraction(input); - } - // Abbrechen - var input = content.createInput("button", "cancel", "{{.button.cancel}}"); - input.setAttribute("onclick", 'javascript: showElement("popup", false);'); - content.addInteraction(input); - // Aktualisieren - if (data["id.provider"] != "-") { - var input = content.createInput("button", "update", "{{.button.update}}"); - input.setAttribute('onclick', 'javascript: savePopupData("hdhr", "' + id + '", false, 1)'); - content.addInteraction(input); - } - // Speichern - var input = content.createInput("button", "save", "{{.button.save}}"); - input.setAttribute('onclick', 'javascript: savePopupData("hdhr", "' + id + '", false, 0)'); - content.addInteraction(input); - break; - case "filter": - content.createHeadline(dataType); - // Type - var dbKey = "type"; - var text = ["M3U: " + "{{.filter.type.groupTitle}}", "xTeVe: " + "{{.filter.type.customFilter}}"]; - var values = ["javascript: openPopUp('group-title')", "javascript: openPopUp('custom-filter')"]; - var select = content.createSelect(text, values, "javascript: openPopUp('group-title')", dbKey); - select.setAttribute("id", id); - select.setAttribute("onchange", 'javascript: changeButtonAction(this, "next", "onclick");'); // changeButtonAction - content.appendRow("{{.filter.type.title}}", select); - // Interaktion - content.createInteraction(); - // Abbrechen - var input = content.createInput("button", "cancel", "{{.button.cancel}}"); - input.setAttribute("onclick", 'javascript: showElement("popup", false);'); - content.addInteraction(input); - // Weiter - var input = content.createInput("button", "next", "{{.button.next}}"); - input.setAttribute("onclick", 'javascript: openPopUp("group-title")'); - input.setAttribute("id", 'next'); - content.addInteraction(input); - break; - case "custom-filter": - case "group-title": - switch (dataType) { - case "custom-filter": - content.createHeadline("{{.filter.custom}}"); - break; - case "group-title": - content.createHeadline("{{.filter.group}}"); - break; - } - // Name - var dbKey = "name"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.filter.name.placeholder}}"); - content.appendRow("{{.filter.name.title}}", input); - // Beschreibung - var dbKey = "description"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.filter.description.placeholder}}"); - content.appendRow("{{.filter.description.title}}", input); - // Typ - var dbKey = "type"; - var input = content.createInput("hidden", dbKey, data[dbKey]); - content.appendRow("", input); - var filterType = data[dbKey]; - switch (filterType) { - case "custom-filter": - // Groß- Kleinschreibung beachten - var dbKey = "caseSensitive"; - var input = content.createCheckbox(dbKey); - input.checked = data[dbKey]; - content.appendRow("{{.filter.caseSensitive.title}}", input); - // Filterregel (Benutzerdefiniert) - var dbKey = "filter"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.filter.filterRule.placeholder}}"); - content.appendRow("{{.filter.filterRule.title}}", input); - break; - case "group-title": - //alert(dbKey + " " + filterType) - // Filter basierend auf den Gruppen in der M3U - var dbKey = "filter"; - var groupsM3U = getLocalData("m3uGroups", ""); - var text = groupsM3U["text"]; - var values = groupsM3U["value"]; - var select = content.createSelect(text, values, data[dbKey], dbKey); - select.setAttribute("onchange", "javascript: this.className = 'changed'"); - content.appendRow("{{.filter.filterGroup.title}}", select); - content.description("{{.filter.filterGroup.description}}"); - // Groß- Kleinschreibung beachten - var dbKey = "caseSensitive"; - var input = content.createCheckbox(dbKey); - input.checked = data[dbKey]; - content.appendRow("{{.filter.caseSensitive.title}}", input); - var dbKey = "include"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.filter.include.placeholder}}"); - content.appendRow("{{.filter.include.title}}", input); - content.description("{{.filter.include.description}}"); - var dbKey = "exclude"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.filter.exclude.placeholder}}"); - content.appendRow("{{.filter.exclude.title}}", input); - content.description("{{.filter.exclude.description}}"); - break; - default: - break; - } - // Interaktion - content.createInteraction(); - // Löschen - var input = content.createInput("button", "delete", "{{.button.delete}}"); - input.setAttribute('onclick', 'javascript: savePopupData("filter", "' + id + '", true, 0)'); - input.className = "delete"; - content.addInteraction(input); - // Abbrechen - var input = content.createInput("button", "cancel", "{{.button.cancel}}"); - input.setAttribute("onclick", 'javascript: showElement("popup", false);'); - content.addInteraction(input); - // Speichern - var input = content.createInput("button", "save", "{{.button.save}}"); - input.setAttribute('onclick', 'javascript: savePopupData("filter", "' + id + '", false, 0)'); - content.addInteraction(input); - break; - case "xmltv": - content.createHeadline(dataType); - // Name - var dbKey = "name"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.xmltv.name.placeholder}}"); - content.appendRow("{{.xmltv.name.title}}", input); - // Beschreibung - var dbKey = "description"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.xmltv.description.placeholder}}"); - content.appendRow("{{.xmltv.description.title}}", input); - // URL - var dbKey = "file.source"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.xmltv.fileXMLTV.placeholder}}"); - content.appendRow("{{.xmltv.fileXMLTV.title}}", input); - // Interaktion - content.createInteraction(); - // Löschen - if (data["id.provider"] != "-") { - var input = content.createInput("button", "delete", "{{.button.delete}}"); - input.setAttribute('onclick', 'javascript: savePopupData("xmltv", "' + id + '", true, 0)'); - input.className = "delete"; - content.addInteraction(input); - } - // Abbrechen - var input = content.createInput("button", "cancel", "{{.button.cancel}}"); - input.setAttribute("onclick", 'javascript: showElement("popup", false);'); - content.addInteraction(input); - // Aktualisieren - if (data["id.provider"] != "-") { - var input = content.createInput("button", "update", "{{.button.update}}"); - input.setAttribute('onclick', 'javascript: savePopupData("xmltv", "' + id + '", false, 1)'); - content.addInteraction(input); - } - // Speichern - var input = content.createInput("button", "save", "{{.button.save}}"); - input.setAttribute('onclick', 'javascript: savePopupData("xmltv", "' + id + '", false, 0)'); - content.addInteraction(input); - break; - case "users": - content.createHeadline("{{.mainMenu.item.users}}"); - // Benutzername - var dbKey = "username"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.users.username.placeholder}}"); - content.appendRow("{{.users.username.title}}", input); - // Neues Passwort - var dbKey = "password"; - var input = content.createInput("password", dbKey, ""); - input.setAttribute("placeholder", "{{.users.password.placeholder}}"); - content.appendRow("{{.users.password.title}}", input); - // Bestätigung - var dbKey = "confirm"; - var input = content.createInput("password", dbKey, ""); - input.setAttribute("placeholder", "{{.users.confirm.placeholder}}"); - content.appendRow("{{.users.confirm.title}}", input); - // Berechtigung WEB - var dbKey = "authentication.web"; - var input = content.createCheckbox(dbKey); - input.checked = data[dbKey]; - if (data["defaultUser"] == true) { - input.setAttribute("onclick", "javascript: return false"); - } - content.appendRow("{{.users.web.title}}", input); - // Berechtigung PMS - var dbKey = "authentication.pms"; - var input = content.createCheckbox(dbKey); - input.checked = data[dbKey]; - content.appendRow("{{.users.pms.title}}", input); - // Berechtigung M3U - var dbKey = "authentication.m3u"; - var input = content.createCheckbox(dbKey); - input.checked = data[dbKey]; - content.appendRow("{{.users.m3u.title}}", input); - // Berechtigung XML - var dbKey = "authentication.xml"; - var input = content.createCheckbox(dbKey); - input.checked = data[dbKey]; - content.appendRow("{{.users.xml.title}}", input); - // Berechtigung API - var dbKey = "authentication.api"; - var input = content.createCheckbox(dbKey); - input.checked = data[dbKey]; - content.appendRow("{{.users.api.title}}", input); - // Interaktion - content.createInteraction(); - // Löschen - if (data["defaultUser"] != true && id != "-") { - var input = content.createInput("button", "delete", "{{.button.delete}}"); - input.className = "delete"; - input.setAttribute('onclick', 'javascript: savePopupData("' + dataType + '", "' + id + '", true, 0)'); - content.addInteraction(input); - } - // Abbrechen - var input = content.createInput("button", "cancel", "{{.button.cancel}}"); - input.setAttribute("onclick", 'javascript: showElement("popup", false);'); - content.addInteraction(input); - // Speichern - var input = content.createInput("button", "save", "{{.button.save}}"); - input.setAttribute("onclick", 'javascript: savePopupData("' + dataType + '", "' + id + '", "false");'); - content.addInteraction(input); - break; - case "mapping": - content.createHeadline("{{.mainMenu.item.mapping}}"); - // Aktiv - var dbKey = "x-active"; - var input = content.createCheckbox(dbKey); - input.checked = data[dbKey]; - input.id = "active"; - //input.setAttribute("onchange", "javascript: this.className = 'changed'") - input.setAttribute("onchange", "javascript: toggleChannelStatus('" + id + "', this)"); - content.appendRow("{{.mapping.active.title}}", input); - // Kanalname - var dbKey = "x-name"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - if (BULK_EDIT == true) { - input.style.border = "solid 1px red"; - input.setAttribute("readonly", "true"); - } - content.appendRow("{{.mapping.channelName.title}}", input); - content.description(data["name"]); - // Beschreibung - var dbKey = "x-description"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("placeholder", "{{.mapping.description.placeholder}}"); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - content.appendRow("{{.mapping.description.title}}", input); - // Aktualisierung des Kanalnamens - if (data.hasOwnProperty("_uuid.key")) { - if (data["_uuid.key"] != "") { - var dbKey = "x-update-channel-name"; - var input = content.createCheckbox(dbKey); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - input.checked = data[dbKey]; - content.appendRow("{{.mapping.updateChannelName.title}}", input); - } - } - // Logo URL (Kanal) - var dbKey = "tvg-logo"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - input.setAttribute("id", "channel-icon"); - content.appendRow("{{.mapping.channelLogo.title}}", input); - // Aktualisierung des Kanallogos - var dbKey = "x-update-channel-icon"; - var input = content.createCheckbox(dbKey); - input.checked = data[dbKey]; - input.setAttribute("id", "update-icon"); - input.setAttribute("onchange", "javascript: this.className = 'changed'; changeChannelLogo('" + id + "');"); - content.appendRow("{{.mapping.updateChannelLogo.title}}", input); - // Erweitern der EPG Kategorie - var dbKey = "x-category"; - var text = ["-", "Kids (Emby only)", "News", "Movie", "Series", "Sports"]; - var values = ["", "Kids", "News", "Movie", "Series", "Sports"]; - var select = content.createSelect(text, values, data[dbKey], dbKey); - select.setAttribute("onchange", "javascript: this.className = 'changed'"); - content.appendRow("{{.mapping.epgCategory.title}}", select); - // M3U Gruppentitel - var dbKey = "x-group-title"; - var input = content.createInput("text", dbKey, data[dbKey]); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - content.appendRow("{{.mapping.m3uGroupTitle.title}}", input); - if (data["group-title"] != undefined) { - content.description(data["group-title"]); - } - // XMLTV Datei - var dbKey = "x-xmltv-file"; - var xmlFile = data[dbKey]; - var xmltv = new XMLTVFile(); - var select = xmltv.getFiles(data[dbKey]); - select.setAttribute("name", dbKey); - select.setAttribute("id", "popup-xmltv"); - select.setAttribute("onchange", "javascript: this.className = 'changed'; setXmltvChannel('" + id + "',this);"); - content.appendRow("{{.mapping.xmltvFile.title}}", select); - var file = data[dbKey]; - // XMLTV Mapping - var dbKey = "x-mapping"; - var xmltv = new XMLTVFile(); - var select = xmltv.getPrograms(file, data[dbKey]); - select.setAttribute("name", dbKey); - select.setAttribute("id", "popup-mapping"); - select.setAttribute("onchange", "javascript: this.className = 'changed'; checkXmltvChannel('" + id + "',this,'" + xmlFile + "');"); - sortSelect(select); - content.appendRow("{{.mapping.xmltvChannel.title}}", select); - // Interaktion - content.createInteraction(); - // Logo hochladen - var input = content.createInput("button", "cancel", "{{.button.uploadLogo}}"); - input.setAttribute("onclick", 'javascript: uploadLogo();'); - content.addInteraction(input); - // Abbrechen - var input = content.createInput("button", "cancel", "{{.button.cancel}}"); - input.setAttribute("onclick", 'javascript: showElement("popup", false);'); - content.addInteraction(input); - // Fertig - var ids = new Array(); - ids = getAllSelectedChannels(); - if (ids.length == 0) { - ids.push(id); - } - var input = content.createInput("button", "save", "{{.button.done}}"); - input.setAttribute("onclick", 'javascript: donePopupData("' + dataType + '", "' + ids + '", "false");'); - content.addInteraction(input); - break; - default: - break; - } - showPopUpElement('popup-custom'); -} -var XMLTVFile = /** @class */ (function () { - function XMLTVFile() { - } - XMLTVFile.prototype.getFiles = function (set) { - var fileIDs = getObjKeys(SERVER["xepg"]["xmltvMap"]); - var values = new Array("-"); - var text = new Array("-"); - for (var i = 0; i < fileIDs.length; i++) { - if (fileIDs[i] != "xTeVe Dummy") { - values.push(getValueFromProviderFile(fileIDs[i], "xmltv", "file.xteve")); - text.push(getValueFromProviderFile(fileIDs[i], "xmltv", "name")); - } - else { - values.push(fileIDs[i]); - text.push(fileIDs[i]); - } - } - var select = document.createElement("SELECT"); - for (var i = 0; i < text.length; i++) { - var option = document.createElement("OPTION"); - option.setAttribute("value", values[i]); - option.innerText = text[i]; - select.appendChild(option); - } - if (set != "") { - select.value = set; - } - return select; - }; - XMLTVFile.prototype.getPrograms = function (file, set) { - //var fileIDs:string[] = getObjKeys(SERVER["xepg"]["xmltvMap"]) - var values = getObjKeys(SERVER["xepg"]["xmltvMap"][file]); - var text = new Array(); - var displayName; - for (var i = 0; i < values.length; i++) { - if (SERVER["xepg"]["xmltvMap"][file][values[i]].hasOwnProperty('display-name') == true) { - displayName = SERVER["xepg"]["xmltvMap"][file][values[i]]["display-name"]; - } - else { - displayName = "-"; - } - text[i] = displayName + " (" + values[i] + ")"; - } - text.unshift("-"); - values.unshift("-"); - var select = document.createElement("SELECT"); - for (var i = 0; i < text.length; i++) { - var option = document.createElement("OPTION"); - option.setAttribute("value", values[i]); - option.innerText = text[i]; - select.appendChild(option); - } - if (set != "") { - select.value = set; - } - if (select.value != set) { - select.value = "-"; - } - return select; - }; - return XMLTVFile; -}()); -function getValueFromProviderFile(file, fileType, key) { - if (file == "xTeVe Dummy") { - return file; - } - var fileID; - var indicator = file.charAt(0); - switch (indicator) { - case "M": - fileType = "m3u"; - fileID = file; - break; - case "H": - fileType = "hdhr"; - fileID = file; - break; - case "X": - fileType = "xmltv"; - fileID = file.substring(0, file.lastIndexOf('.')); - break; - } - if (SERVER["settings"]["files"][fileType].hasOwnProperty(fileID) == true) { - var data = SERVER["settings"]["files"][fileType][fileID]; - return data[key]; - } - return; -} -function setXmltvChannel(id, element) { - var xmltv = new XMLTVFile(); - var xmlFile = element.value; - var tvgId = SERVER["xepg"]["epgMapping"][id]["tvg-id"]; - var td = document.getElementById("popup-mapping").parentElement; - td.innerHTML = ""; - var select = xmltv.getPrograms(element.value, tvgId); - select.setAttribute("name", "x-mapping"); - select.setAttribute("id", "popup-mapping"); - select.setAttribute("onchange", "javascript: this.className = 'changed'; checkXmltvChannel('" + id + "',this,'" + xmlFile + "');"); - select.className = "changed"; - sortSelect(select); - td.appendChild(select); - checkXmltvChannel(id, select, xmlFile); -} -function checkXmltvChannel(id, element, xmlFile) { - var value = element.value; - var bool; - var checkbox = document.getElementById('active'); - var channel = SERVER["xepg"]["epgMapping"][id]; - var updateLogo; - if (value == "-") { - bool = false; - } - else { - bool = true; - } - checkbox.checked = bool; - checkbox.className = "changed"; - console.log(xmlFile); - // Kanallogo aktualisieren - /* - updateLogo = (document.getElementById("update-icon") as HTMLInputElement).checked - console.log(updateLogo); - */ - if (xmlFile != "xTeVe Dummy" && bool == true) { - //(document.getElementById("update-icon") as HTMLInputElement).checked = true; - //(document.getElementById("update-icon") as HTMLInputElement).className = "changed"; - console.log("ID", id); - changeChannelLogo(id); - return; - } - if (xmlFile == "xTeVe Dummy") { - document.getElementById("update-icon").checked = false; - document.getElementById("update-icon").className = "changed"; - } - return; -} -function changeChannelLogo(id) { - var updateLogo; - var channel = SERVER["xepg"]["epgMapping"][id]; - var f = document.getElementById("popup-xmltv"); - var xmltvFile = f.options[f.selectedIndex].value; - var m = document.getElementById("popup-mapping"); - var xMapping = m.options[m.selectedIndex].value; - var xmltvLogo = SERVER["xepg"]["xmltvMap"][xmltvFile][xMapping]["icon"]; - updateLogo = document.getElementById("update-icon").checked; - if (updateLogo == true && xmltvFile != "xTeVe Dummy") { - if (SERVER["xepg"]["xmltvMap"][xmltvFile].hasOwnProperty(xMapping)) { - var logo = xmltvLogo; - } - else { - logo = channel["tvg-logo"]; - } - var logoInput = document.getElementById("channel-icon"); - logoInput.value = logo; - if (BULK_EDIT == false) { - logoInput.className = "changed"; - } - } -} -function savePopupData(dataType, id, remove, option) { - if (dataType == "mapping") { - var data = new Object(); - console.log("Save mapping data"); - cmd = "saveEpgMapping"; - data["epgMapping"] = SERVER["xepg"]["epgMapping"]; - console.log("SEND TO SERVER"); - var server = new Server(cmd); - server.request(data); - delete UNDO["epgMapping"]; - return; - } - console.log("Save popup data"); - var div = document.getElementById("popup-custom"); - var inputs = div.getElementsByTagName("TABLE")[0].getElementsByTagName("INPUT"); - var selects = div.getElementsByTagName("TABLE")[0].getElementsByTagName("SELECT"); - var input = new Object(); - var confirmMsg; - for (var i = 0; i < selects.length; i++) { - var name; - name = selects[i].name; - var value = selects[i].value; - switch (name) { - case "tuner": - input[name] = parseInt(value); - break; - default: - input[name] = value; - break; - } - } - for (var i = 0; i < inputs.length; i++) { - switch (inputs[i].type) { - case "checkbox": - name = inputs[i].name; - input[name] = inputs[i].checked; - break; - case "text": - case "hidden": - case "password": - name = inputs[i].name; - switch (name) { - case "tuner": - input[name] = parseInt(inputs[i].value); - break; - default: - input[name] = inputs[i].value; - break; - } - break; - } - } - var data = new Object(); - var cmd; - if (remove == true) { - input["delete"] = true; - } - switch (dataType) { - case "users": - confirmMsg = "Delete this user?"; - if (id == "-") { - cmd = "saveNewUser"; - data["userData"] = input; - } - else { - cmd = "saveUserData"; - var d = new Object(); - d[id] = input; - data["userData"] = d; - } - break; - case "m3u": - confirmMsg = "Delete this playlist?"; - switch (option) { - // Popup: Save - case 0: - cmd = "saveFilesM3U"; - break; - // Popup: Update - case 1: - cmd = "updateFileM3U"; - break; - } - data["files"] = new Object; - data["files"][dataType] = new Object; - data["files"][dataType][id] = input; - break; - case "hdhr": - confirmMsg = "Delete this HDHomeRun tuner?"; - switch (option) { - // Popup: Save - case 0: - cmd = "saveFilesHDHR"; - break; - // Popup: Update - case 1: - cmd = "updateFileHDHR"; - break; - } - data["files"] = new Object; - data["files"][dataType] = new Object; - data["files"][dataType][id] = input; - break; - case "xmltv": - confirmMsg = "Delete this XMLTV file?"; - switch (option) { - // Popup: Save - case 0: - cmd = "saveFilesXMLTV"; - break; - // Popup: Update - case 1: - cmd = "updateFileXMLTV"; - break; - } - data["files"] = new Object; - data["files"][dataType] = new Object; - data["files"][dataType][id] = input; - break; - case "filter": - confirmMsg = "Delete this filter?"; - cmd = "saveFilter"; - data["filter"] = new Object; - data["filter"][id] = input; - break; - default: - console.log(dataType, id); - return; - break; - } - if (remove == true) { - if (!confirm(confirmMsg)) { - showElement("popup", false); - return; - } - } - console.log("SEND TO SERVER"); - console.log(data); - var server = new Server(cmd); - server.request(data); -} -function donePopupData(dataType, idsStr) { - var ids = idsStr.split(','); - var div = document.getElementById("popup-custom"); - var inputs = div.getElementsByClassName("changed"); - ids.forEach(function (id) { - var input = new Object(); - input = SERVER["xepg"]["epgMapping"][id]; - console.log(input); - for (var i = 0; i < inputs.length; i++) { - var name; - var value; - switch (inputs[i].tagName) { - case "INPUT": - switch (inputs[i].type) { - case "checkbox": - name = inputs[i].name; - value = inputs[i].checked; - input[name] = value; - break; - case "text": - name = inputs[i].name; - value = inputs[i].value; - input[name] = value; - break; - } - break; - case "SELECT": - name = inputs[i].name; - value = inputs[i].value; - input[name] = value; - break; - } - switch (name) { - case "tvg-logo": - //(document.getElementById(id).childNodes[2].firstChild as HTMLElement).setAttribute("src", value) - break; - case "x-name": - document.getElementById(id).childNodes[3].firstChild.innerHTML = value; - break; - case "x-category": - document.getElementById(id).childNodes[3].firstChild.className = value; - break; - case "x-group-title": - document.getElementById(id).childNodes[5].firstChild.innerHTML = value; - break; - case "x-xmltv-file": - if (value != "xTeVe Dummy" && value != "-") { - value = getValueFromProviderFile(value, "xmltv", "name"); - } - if (value == "-") { - input["x-active"] = false; - } - document.getElementById(id).childNodes[6].firstChild.innerHTML = value; - break; - case "x-mapping": - if (value == "-") { - input["x-active"] = false; - } - document.getElementById(id).childNodes[7].firstChild.innerHTML = value; - break; - default: - } - createSearchObj(); - searchInMapping(); - } - if (input["x-active"] == false) { - document.getElementById(id).className = "notActiveEPG"; - } - else { - document.getElementById(id).className = "activeEPG"; - } - console.log(input["tvg-logo"]); - document.getElementById(id).childNodes[2].firstChild.setAttribute("src", input["tvg-logo"]); - }); - showElement("popup", false); - return; -} -function showPreview(element) { - var div = document.getElementById("myStreamsBox"); - switch (element) { - case false: - div.className = "notVisible"; - return; - break; - } - var streams = ["activeStreams", "inactiveStreams"]; - streams.forEach(function (preview) { - var table = document.getElementById(preview); - table.innerHTML = ""; - var obj = SERVER["data"]["StreamPreviewUI"][preview]; - obj.forEach(function (channel) { - var tr = document.createElement("TR"); - var tdKey = document.createElement("TD"); - var tdVal = document.createElement("TD"); - tdKey.className = "tdKey"; - tdVal.className = "tdVal"; - switch (preview) { - case "activeStreams": - tdKey.innerText = "Channel: (+)"; - break; - case "inactiveStreams": - tdKey.innerText = "Channel: (-)"; - break; - } - tdVal.innerText = channel; - tr.appendChild(tdKey); - tr.appendChild(tdVal); - table.appendChild(tr); - }); - }); - showElement("loading", false); - div.className = "visible"; - return; -} diff --git a/html/js/network_ts.js b/html/js/network_ts.js deleted file mode 100644 index 916e819..0000000 --- a/html/js/network_ts.js +++ /dev/null @@ -1,105 +0,0 @@ -var Server = /** @class */ (function () { - function Server(cmd) { - this.cmd = cmd; - } - Server.prototype.request = function (data) { - if (SERVER_CONNECTION == true) { - return; - } - SERVER_CONNECTION = true; - console.log(data); - if (this.cmd != "updateLog") { - showElement("loading", true); - UNDO = new Object(); - } - switch (window.location.protocol) { - case "http:": - this.protocol = "ws://"; - break; - case "https:": - this.protocol = "wss://"; - break; - } - var url = this.protocol + window.location.hostname + ":" + window.location.port + "/data/" + "?Token=" + getCookie("Token"); - data["cmd"] = this.cmd; - var ws = new WebSocket(url); - ws.onopen = function () { - WS_AVAILABLE = true; - console.log("REQUEST (JS):"); - console.log(data); - console.log("REQUEST: (JSON)"); - console.log(JSON.stringify(data)); - this.send(JSON.stringify(data)); - }; - ws.onerror = function (e) { - console.log("No websocket connection to xTeVe could be established. Check your network configuration."); - SERVER_CONNECTION = false; - if (WS_AVAILABLE == false) { - alert("No websocket connection to xTeVe could be established. Check your network configuration."); - } - }; - ws.onmessage = function (e) { - SERVER_CONNECTION = false; - showElement("loading", false); - console.log("RESPONSE:"); - var response = JSON.parse(e.data); - console.log(response); - if (response.hasOwnProperty("token")) { - document.cookie = "Token=" + response["token"]; - } - if (response["status"] == false) { - alert(response["err"]); - if (response.hasOwnProperty("reload")) { - location.reload(); - } - return; - } - if (response.hasOwnProperty("logoURL")) { - var div = document.getElementById("channel-icon"); - div.value = response["logoURL"]; - div.className = "changed"; - return; - } - switch (data["cmd"]) { - case "updateLog": - SERVER["log"] = response["log"]; - if (document.getElementById("content_log")) { - showLogs(false); - } - return; - break; - default: - SERVER = new Object(); - SERVER = response; - break; - } - if (response.hasOwnProperty("openMenu")) { - var menu = document.getElementById(response["openMenu"]); - menu.click(); - showElement("popup", false); - } - if (response.hasOwnProperty("openLink")) { - window.location = response["openLink"]; - } - if (response.hasOwnProperty("alert")) { - alert(response["alert"]); - } - if (response.hasOwnProperty("reload")) { - location.reload(); - } - if (response.hasOwnProperty("wizard")) { - createLayout(); - configurationWizard[response["wizard"]].createWizard(); - return; - } - createLayout(); - }; - }; - return Server; -}()); -function getCookie(name) { - var value = "; " + document.cookie; - var parts = value.split("; " + name + "="); - if (parts.length == 2) - return parts.pop().split(";").shift(); -} diff --git a/html/js/settings_ts.js b/html/js/settings_ts.js deleted file mode 100644 index f0f1fdb..0000000 --- a/html/js/settings_ts.js +++ /dev/null @@ -1,513 +0,0 @@ -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var SettingsCategory = /** @class */ (function () { - function SettingsCategory() { - this.DocumentID = "content_settings"; - } - SettingsCategory.prototype.createCategoryHeadline = function (value) { - var element = document.createElement("H4"); - element.innerHTML = value; - return element; - }; - SettingsCategory.prototype.createHR = function () { - var element = document.createElement("HR"); - return element; - }; - SettingsCategory.prototype.createSettings = function (settingsKey) { - var setting = document.createElement("TR"); - var content = new PopupContent(); - var data = SERVER["settings"][settingsKey]; - switch (settingsKey) { - // Texteingaben - case "update": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.update.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createInput("text", "update", data.toString()); - input.setAttribute("placeholder", "{{.settings.update.placeholder}}"); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "backup.path": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.backupPath.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createInput("text", "backup.path", data); - input.setAttribute("placeholder", "{{.settings.backupPath.placeholder}}"); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "temp.path": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.tempPath.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createInput("text", "temp.path", data); - input.setAttribute("placeholder", "{{.settings.tmpPath.placeholder}}"); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "user.agent": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.userAgent.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createInput("text", "user.agent", data); - input.setAttribute("placeholder", "{{.settings.userAgent.placeholder}}"); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "buffer.timeout": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.bufferTimeout.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createInput("text", "buffer.timeout", data); - input.setAttribute("placeholder", "{{.settings.bufferTimeout.placeholder}}"); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "ffmpeg.path": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.ffmpegPath.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createInput("text", "ffmpeg.path", data); - input.setAttribute("placeholder", "{{.settings.ffmpegPath.placeholder}}"); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "ffmpeg.options": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.ffmpegOptions.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createInput("text", "ffmpeg.options", data); - input.setAttribute("placeholder", "{{.settings.ffmpegOptions.placeholder}}"); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "vlc.path": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.vlcPath.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createInput("text", "vlc.path", data); - input.setAttribute("placeholder", "{{.settings.vlcPath.placeholder}}"); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "vlc.options": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.vlcOptions.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createInput("text", "vlc.options", data); - input.setAttribute("placeholder", "{{.settings.vlcOptions.placeholder}}"); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - // Checkboxen - case "authentication.web": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.authenticationWEB.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createCheckbox(settingsKey); - input.checked = data; - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "authentication.pms": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.authenticationPMS.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createCheckbox(settingsKey); - input.checked = data; - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "authentication.m3u": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.authenticationM3U.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createCheckbox(settingsKey); - input.checked = data; - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "authentication.xml": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.authenticationXML.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createCheckbox(settingsKey); - input.checked = data; - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "authentication.api": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.authenticationAPI.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createCheckbox(settingsKey); - input.checked = data; - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "files.update": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.filesUpdate.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createCheckbox(settingsKey); - input.checked = data; - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "cache.images": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.cacheImages.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createCheckbox(settingsKey); - input.checked = data; - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "xepg.replace.missing.images": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.replaceEmptyImages.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createCheckbox(settingsKey); - input.checked = data; - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "xteveAutoUpdate": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.xteveAutoUpdate.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createCheckbox(settingsKey); - input.checked = data; - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "api": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.api.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createCheckbox(settingsKey); - input.checked = data; - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - // Select - case "tuner": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.tuner.title}}" + ":"; - var tdRight = document.createElement("TD"); - var text = new Array(); - var values = new Array(); - for (var i = 1; i <= 100; i++) { - text.push(i); - values.push(i); - } - var select = content.createSelect(text, values, data, settingsKey); - select.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(select); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "epgSource": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.epgSource.title}}" + ":"; - var tdRight = document.createElement("TD"); - var text = ["PMS", "XEPG"]; - var values = ["PMS", "XEPG"]; - var select = content.createSelect(text, values, data, settingsKey); - select.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(select); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "backup.keep": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.backupKeep.title}}" + ":"; - var tdRight = document.createElement("TD"); - var text = ["5", "10", "20", "30", "40", "50"]; - var values = ["5", "10", "20", "30", "40", "50"]; - var select = content.createSelect(text, values, data, settingsKey); - select.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(select); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "buffer.size.kb": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.bufferSize.title}}" + ":"; - var tdRight = document.createElement("TD"); - var text = ["0.5 MB", "1 MB", "2 MB", "3 MB", "4 MB", "5 MB", "6 MB", "7 MB", "8 MB"]; - var values = ["512", "1024", "2048", "3072", "4096", "5120", "6144", "7168", "8192"]; - var select = content.createSelect(text, values, data, settingsKey); - select.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(select); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "buffer": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.streamBuffering.title}}" + ":"; - var tdRight = document.createElement("TD"); - var text = ["{{.settings.streamBuffering.info_false}}", "xTeVe: ({{.settings.streamBuffering.info_xteve}})", "FFmpeg: ({{.settings.streamBuffering.info_ffmpeg}})", "VLC: ({{.settings.streamBuffering.info_vlc}})"]; - var values = ["-", "xteve", "ffmpeg", "vlc"]; - var select = content.createSelect(text, values, data, settingsKey); - select.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(select); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - case "udpxy": - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = "{{.settings.udpxy.title}}" + ":"; - var tdRight = document.createElement("TD"); - var input = content.createInput("text", "udpxy", data); - input.setAttribute("placeholder", "{{.settings.udpxy.placeholder}}"); - input.setAttribute("onchange", "javascript: this.className = 'changed'"); - tdRight.appendChild(input); - setting.appendChild(tdLeft); - setting.appendChild(tdRight); - break; - } - return setting; - }; - SettingsCategory.prototype.createDescription = function (settingsKey) { - var description = document.createElement("TR"); - var text; - switch (settingsKey) { - case "authentication.web": - text = "{{.settings.authenticationWEB.description}}"; - break; - case "authentication.m3u": - text = "{{.settings.authenticationM3U.description}}"; - break; - case "authentication.pms": - text = "{{.settings.authenticationPMS.description}}"; - break; - case "authentication.xml": - text = "{{.settings.authenticationXML.description}}"; - break; - case "authentication.api": - if (SERVER["settings"]["authentication.web"] == true) { - text = "{{.settings.authenticationAPI.description}}"; - } - break; - case "xteveAutoUpdate": - text = "{{.settings.xteveAutoUpdate.description}}"; - break; - case "backup.keep": - text = "{{.settings.backupKeep.description}}"; - break; - case "backup.path": - text = "{{.settings.backupPath.description}}"; - break; - case "temp.path": - text = "{{.settings.tempPath.description}}"; - break; - case "buffer": - text = "{{.settings.streamBuffering.description}}"; - break; - case "buffer.size.kb": - text = "{{.settings.bufferSize.description}}"; - break; - case "buffer.timeout": - text = "{{.settings.bufferTimeout.description}}"; - break; - case "user.agent": - text = "{{.settings.userAgent.description}}"; - break; - case "ffmpeg.path": - text = "{{.settings.ffmpegPath.description}}"; - break; - case "ffmpeg.options": - text = "{{.settings.ffmpegOptions.description}}"; - break; - case "vlc.path": - text = "{{.settings.vlcPath.description}}"; - break; - case "vlc.options": - text = "{{.settings.vlcOptions.description}}"; - break; - case "epgSource": - text = "{{.settings.epgSource.description}}"; - break; - case "tuner": - text = "{{.settings.tuner.description}}"; - break; - case "update": - text = "{{.settings.update.description}}"; - break; - case "api": - text = "{{.settings.api.description}}"; - break; - case "files.update": - text = "{{.settings.filesUpdate.description}}"; - break; - case "cache.images": - text = "{{.settings.cacheImages.description}}"; - break; - case "xepg.replace.missing.images": - text = "{{.settings.replaceEmptyImages.description}}"; - break; - case "udpxy": - text = "{{.settings.udpxy.description}}"; - break; - default: - text = ""; - break; - } - var tdLeft = document.createElement("TD"); - tdLeft.innerHTML = ""; - var tdRight = document.createElement("TD"); - var pre = document.createElement("PRE"); - pre.innerHTML = text; - tdRight.appendChild(pre); - description.appendChild(tdLeft); - description.appendChild(tdRight); - return description; - }; - return SettingsCategory; -}()); -var SettingsCategoryItem = /** @class */ (function (_super) { - __extends(SettingsCategoryItem, _super); - function SettingsCategoryItem(headline, settingsKeys) { - var _this = _super.call(this) || this; - _this.headline = headline; - _this.settingsKeys = settingsKeys; - return _this; - } - SettingsCategoryItem.prototype.createCategory = function () { - var _this = this; - var headline = this.createCategoryHeadline(this.headline); - var settingsKeys = this.settingsKeys; - var doc = document.getElementById(this.DocumentID); - doc.appendChild(headline); - // Tabelle für die Kategorie erstellen - var table = document.createElement("TABLE"); - var keys = settingsKeys.split(","); - keys.forEach(function (settingsKey) { - switch (settingsKey) { - case "authentication.pms": - case "authentication.m3u": - case "authentication.xml": - case "authentication.api": - if (SERVER["settings"]["authentication.web"] == false) { - break; - } - default: - var item = _this.createSettings(settingsKey); - var description = _this.createDescription(settingsKey); - table.appendChild(item); - table.appendChild(description); - break; - } - }); - doc.appendChild(table); - doc.appendChild(this.createHR()); - }; - return SettingsCategoryItem; -}(SettingsCategory)); -function showSettings() { - console.log("SETTINGS"); - for (var i = 0; i < settingsCategory.length; i++) { - settingsCategory[i].createCategory(); - } -} -function saveSettings() { - console.log("Save Settings"); - var cmd = "saveSettings"; - var div = document.getElementById("content_settings"); - var settings = div.getElementsByClassName("changed"); - var newSettings = new Object(); - for (var i = 0; i < settings.length; i++) { - var name; - var value; - switch (settings[i].tagName) { - case "INPUT": - switch (settings[i].type) { - case "checkbox": - name = settings[i].name; - value = settings[i].checked; - newSettings[name] = value; - break; - case "text": - name = settings[i].name; - value = settings[i].value; - switch (name) { - case "update": - value = value.split(","); - value = value.filter(function (e) { return e; }); - break; - case "buffer.timeout": - value = parseFloat(value); - } - newSettings[name] = value; - break; - } - break; - case "SELECT": - name = settings[i].name; - value = settings[i].value; - // Wenn der Wert eine Zahl ist, wird dieser als Zahl gespeichert - if (isNaN(value)) { - newSettings[name] = value; - } - else { - newSettings[name] = parseInt(value); - } - break; - } - } - var data = new Object(); - data["settings"] = newSettings; - var server = new Server(cmd); - server.request(data); -} diff --git a/html/js/users.js b/html/js/users.js deleted file mode 100644 index 8cf9414..0000000 --- a/html/js/users.js +++ /dev/null @@ -1,341 +0,0 @@ -function openUsers(elm) { - colomnSort = 0; - - var newDiv = document.getElementById("settings"); - - var newEntry = new Object(); - newEntry["_element"] = "HR"; - newDiv.appendChild(createElement(newEntry)); - - var newEntry = new Object(); - newEntry["_element"] = "INPUT"; - newEntry["type"] = "button"; - newEntry["class"] = "button"; - newEntry["value"] = "New"; - newEntry["onclick"] = "userDetail(0)"; - newDiv.appendChild(createElement(newEntry)); - - var div = document.getElementById("settings"); - - // Build table - var newTable = new Object(); - newTable["_element"] = "TABLE"; - newTable["id"] = "id_mapping"; - newTable["class"] = "table-mapping"; - div.appendChild(createElement(newTable)); - - setTimeout(function(){ - createUsersTable(); - }, 10); -} - -function createUsersTable() { - var table = document.getElementById("id_mapping"); - table.innerHTML = ""; - var newTR = new Object(); - newTR["_element"] = "TR"; - newTR["class"] = "table-mapping-header"; - table.appendChild(createElement(newTR)); - - var tr = table.lastChild; - var trHeadlines = new Array("Username", "Password", "WEB", "PMS", "M3U", "XML", "API") - - for (var i = 0; i < trHeadlines.length; i++) { - var newTD = new Object(); - newTD["_element"] = "TD"; - newTD["_text"] = trHeadlines[i]; - tr.appendChild(createElement(newTD)); - } - - - // Sort users - var userIds = getObjKeys(users); - - var userObj = new Object(); - - for (var i = 0; i < userIds.length; i++) { - var username = users[userIds[i]]["data"]["username"]; - userObj[username] = userIds[i]; - } - - var allUsers = getObjKeys(userObj); - allUsers.sort(); - // -- - - for (var i = 0; i < allUsers.length; i++) { - var table = document.getElementById("id_mapping"); - var userID = userObj[allUsers[i]]; - var username = allUsers[i]; - var item = users[userID]["data"]; - - // Create TR - var newTR = new Object(); - newTR["_element"] = "TR"; - newTR["class"] = ""; - newTR["id"] = userID; - newTR["onclick"] = 'javascript: userDetail("' + userID + '");'; - table.appendChild(createElement(newTR)); - - var tr = table.lastChild; - - // Create username TD - var newTD = new Object(); - newTD["_element"] = "P"; - newTD["_text"] = username; - createNewTD(newTD, tr); - - // Create password TD - var newTD = new Object(); - newTD["_element"] = "P"; - newTD["_text"] = "....."; - createNewTD(newTD, tr); - - // Create web access - var newTD = new Object(); - newTD["_element"] = "P"; - switch(item["authentication.web"]){ - case true: newTD["_text"] = "✓"; break; - default: newTD["_text"] = "-"; break; - } - createNewTD(newTD, tr); - - // Create PMS access - var newTD = new Object(); - newTD["_element"] = "P"; - switch(item["authentication.pms"]){ - case true: newTD["_text"] = "✓"; break; - default: newTD["_text"] = "-"; break; - } - createNewTD(newTD, tr); - - // Create M3U access - var newTD = new Object(); - newTD["_element"] = "P"; - switch(item["authentication.m3u"]){ - case true: newTD["_text"] = "✓"; break; - default: newTD["_text"] = "-"; break; - } - createNewTD(newTD, tr); - - // Create XMLTV access - var newTD = new Object(); - newTD["_element"] = "P"; - switch(item["authentication.xml"]){ - case true: newTD["_text"] = "✓"; break; - default: newTD["_text"] = "-"; break; - } - createNewTD(newTD, tr); - - // Create API access - var newTD = new Object(); - newTD["_element"] = "P"; - - switch(item["authentication.api"]){ - case true: newTD["_text"] = "✓"; break; - default: newTD["_text"] = "-"; break; - } - createNewTD(newTD, tr); - - } - - // usage Info - var div = document.getElementById("settings"); - switch(menu[activeMenu.id].hasOwnProperty("_usage")) { - case true: - var usageItem = new Object(); - usageItem["_element"] = "PRE" - usageItem["_text"] = menu[activeMenu.id]["_usage"]; - - var newHR = new Object(); - newHR["_element"] = "HR" - div.appendChild(createElement(newHR)); - div.appendChild(createElement(usageItem)); - } - - sortTable(0); -} - -function userDetail(userID) { - showPopUpElement('user-detail'); - setTimeout(function(){ - showElement("popup", true); - }, 10); - var defaultUser; - - document.getElementById("saveUserDetail").setAttribute("onclick", 'javascript: saveUserDetail("' + userID + '", false)'); - document.getElementById("deleteUserDetail").setAttribute("onclick", 'javascript: saveUserDetail("' + userID + '", true)'); - - var data = new Object(); - - switch(userID) { - case 0: // New User - data["username"] = ""; - data["authentication.web"] = false; - data["authentication.pms"] = true; - data["authentication.xml"] = true; - data["authentication.m3u"] = false; - data["authentication.api"] = false; - data["defaultUser"] = false; - setTimeout(function(){ - showElement("deleteUserDetail", false) - }, 1); - - break; - - default: - data = users[userID]["data"]; - showElement("deleteUserDetail", true) - document.getElementById("deleteUserDetail").className = "delete"; - - break - } - - - var username = data["username"]; - data["password"] = ""; - data["confirm"] = ""; - - var keys = getObjKeys(data); - defaultUser = data["defaultUser"]; - if (data.hasOwnProperty("defaultUser")) { - defaultUser = JSON.parse(data["defaultUser"]); - } - - for (var i = 0; i < keys.length; i++) { - - if(document.getElementById(keys[i])){ - var td = document.getElementById(keys[i]) - } else { - var td = undefined; - } - - var newItem = new Object(); - - newItem["_element"] = "INPUT"; - - newItem["value"] = data[keys[i]]; - newItem["name"] = keys[i]; - - - - - - switch(keys[i].indexOf("authentication")) { - case -1: - if (keys[i] == "password" || keys[i] == "confirm") { - newItem["type"] = "password"; - } else { - newItem["type"] = "text"; - } - break; - - default: - newItem["type"] = "checkbox"; - - if (keys[i] == "authentication.web" && defaultUser == true) { - newItem["onclick"] = "return false"; - } - - if (data[keys[i]] == true) { - newItem["checked"] = data[keys[i]]; - } - - break; - } - - switch(keys[i]) { - case "defaultUser": - //if (data[keys[i]] == true) { - newItem["type"] = "hidden"; - //} - } - - - if (td != undefined) { - td.innerHTML = ""; - var element = createNewElement(newItem) - //console.log(element); - td.appendChild(element); - } - - - } - - - if (defaultUser == true) { - showElement("deleteUserDetail", false) - } else { - showElement("deleteUserDetail", true) - document.getElementById("deleteUserDetail").className = "delete"; - } - -} - -function saveUserDetail(userID, deleteUser) { - - var inputs = document.getElementById("user-detail-table").getElementsByTagName("INPUT"); - - var newUserData = new Object(); - for (var i = 0; i < inputs.length; i++) { - switch(inputs[i].type) { - case "checkbox": newUserData[inputs[i].name] = inputs[i].checked; break; - default: newUserData[inputs[i].name] = inputs[i].value; break; - } - - if (inputs["username"].value.length == 0) { - inputs["username"].style.border = "solid 1px red"; - return; - } - - switch(userID) { - case "0": - if (inputs["password"].value.length == 0) { - console.log(inputs["password"].value.length); - inputs["password"].style.border = "solid 1px red"; - return - } - break; - } - - if (inputs["password"].value.length > 0) { - if (inputs["password"].value != inputs["confirm"].value) { - inputs["password"].style.border = "solid 1px red"; - inputs["confirm"].style.border = "solid 1px red"; - return; - } - } - - } - - var data = new Object(); - - switch(userID) { - case "0": - //data = newUserData - data["userData"] = newUserData - data["cmd"] = "saveNewUser"; break; - - default: - var thisUser = new Object(); - - if (deleteUser == true) { - if (confirm('Delete the selected user?')) { - data["deleteUser"] = true; - } else { - showElement("popup", false); - return - } - } - - thisUser[userID] = newUserData; - - data["userData"] = thisUser; - data["cmd"] = "saveUserData"; break; - } - - xTeVe(data); - //createUsersTable() - showElement("popup", false); -} - - diff --git a/html/lang/en.json b/html/lang/en.json index 73c3d14..1a4756a 100644 --- a/html/lang/en.json +++ b/html/lang/en.json @@ -1,8 +1,6 @@ { - "mainMenu": - { - "item": - { + "mainMenu": { + "item": { "playlist": "Playlist", "pmsID": "PMS ID", "filter": "Filter", @@ -13,8 +11,7 @@ "log": "Log", "logout": "Logout" }, - "headline": - { + "headline": { "playlist": "Local or remote playlists", "filter": "Filter playlist", "xmltv": "Local or remote XMLTV files", @@ -25,18 +22,15 @@ "logout": "Logout" } }, - "confirm": - { + "confirm": { "restore": "All data will be replaced with those from the backup. Should the files be restored?" }, - "alert": - { + "alert": { "fileLoadingError": "File couldn't be loaded", "invalidChannelNumber": "Invalid channel number", "missingInput": "Missing input" }, - "button": - { + "button": { "back": "Back", "backup": "Backup", "bulkEdit": "Bulk Edit", @@ -54,70 +48,68 @@ "resetLogs": "Reset Logs", "uploadLogo": "Upload Logo" }, - "filter": - { - "table": - { + "filter": { + "table": { + "startingChannel": "Starting Ch. No.", "name": "Filter Name", "type": "Filter Type", "filter": "Filter" }, "custom": "Custom", - "group": "Group", - "name": - { + "group": "M3U Group", + "name": { "title": "Filter Name", "placeholder": "Filter name", "description": "" }, - "description": - { + "description": { "title": "Description", "placeholder": "Description", "description": "" }, - "type": - { + "type": { "title": "Type", "groupTitle": "Group Title", "customFilter": "Custom Filter" }, - "caseSensitive": - { + "caseSensitive": { "title": "Case Sensitive", "placeholder": "", "description": "" }, - "filterRule": - { + "filterRule": { "title": "Filter Rule", "placeholder": "Sport {HD} !{ES,IT}", "description": "" }, - "filterGroup": - { + "filterGroup": { "title": "Group Title", "placeholder": "", "description": "Select a M3U group. (Counter)
Changing the group title in the M3U invalidates the filter." }, - "include": - { + "include": { "title": "Include", "placeholder": "FHD,UHD", "description": "Channel name must include.
(Comma separated) Comma means or" }, - "exclude": - { + "exclude": { "title": "Exclude", "placeholder": "ES,IT", "description": "Channel name must not contain.
(Comma separated) Comma means or" + }, + "preserveMapping": { + "title": "Preserve Existing M3U
Channel Numbers", + "palceholder": "", + "description": "Preserve existing M3U playlist channel numbers?" + }, + "startingChannel": { + "title": "Starting Channel Number", + "placeholder": "", + "description": "" } - }, - "playlist": - { - "table": - { + "playlist": { + "table": { "playlist": "Playlist", "tuner": "Tuner", "lastUpdate": "Last Update", @@ -128,155 +120,151 @@ "tvgID": "tvg-id", "uniqueID": "Unique ID" }, - "playlistType": - { + "playlistType": { "title": "Playlist type", "placeholder": "", "description": "" }, - "type": - { + "type": { "title": "Type", "placeholder": "", "description": "" }, - "name": - { + "name": { "title": "Name", "placeholder": "Playlist name", "description": "" }, - "description": - { + "description": { "title": "Description", "placeholder": "Description", "description": "" }, - "fileM3U": - { + "fileM3U": { "title": "M3U File", "placeholder": "File path or URL of the M3U", "description": "" }, - "fileHDHR": - { + "fileHDHR": { "title": "HDHomeRun IP", "placeholder": "IP address and port (192.168.1.10:5004)", "description": "" }, - "tuner": - { + "tuner": { "title": "Tuner / Streams", "placeholder": "", "description": "Number of parallel connections that can be established to the provider.
Only available with activated buffer.
New settings will only be applied after quitting all streams." } }, - "xmltv": - { - "table": - { + "xmltv": { + "table": { "guide": "Guide", "lastUpdate": "Last Update", "availability": "Availability", "channels": "Channels", "programs": "Programs" }, - "name": - { + "name": { "title": "Name", "placeholder": "Guide name", "description": "" }, - "description": - { + "description": { "title": "Description", "placeholder": "Description", "description": "" }, - "fileXMLTV": - { + "fileXMLTV": { "title": "XMLTV File", "placeholder": "File path or URL of the XMLTV", "description": "" } }, - "mapping": - { - "table": - { + "mapping": { + "table": { "chNo": "Ch. No.", "logo": "Logo", "channelName": "Channel Name", + "updateChannelNameRegex": "Upd. Rx.", "playlist": "Playlist", "groupTitle": "Group Title", "xmltvFile": "XMLTV File", - "xmltvID": "XMLTV ID" + "xmltvID": "XMLTV ID", + "timeshift": "Timeshift" }, - "active": - { + "active": { "title": "Active", "placeholder": "", "description": "" }, - "channelName": - { + "channelName": { "title": "Channel Name", "placeholder": "", "description": "" }, - "description": - { + "description": { "title": "Channel Description", "placeholder": "Used by the Dummy as an XML description", "description": "" }, - "updateChannelName": - { + "updateChannelName": { "title": "Update Channel Name", "placeholder": "", "description": "" }, - "channelLogo": - { + "updateChannelNameRegex": { + "title": "Channel name update regex", + "placeholder": "For example ^PPV[ \\\\-_]?1.*", + "description": "On update, if any new channel name matches this regex, rename current channel to the first matching name" + }, + "updateChannelNameByGroupRegex": { + "title": "Only by group regex", + "placeholder": "", + "description": "Rename this channel only if current user-defined group matches this regex" + }, + "updateChannelGroup": { + "title": "Update Channel Group", + "placeholder": "", + "description": "If checked, use group from the database" + }, + "channelLogo": { "title": "Logo URL", "placeholder": "", "description": "" }, - "updateChannelLogo": - { - "title": "Update Channel Logo", + "updateChannelLogo": { + "title": "Use logo from M3U", "placeholder": "", "description": "" }, - "epgCategory": - { + "epgCategory": { "title": "EPG Category", "placeholder": "", "description": "" }, - "m3uGroupTitle": - { + "m3uGroupTitle": { "title": "Group Title (xteve.m3u)", "placeholder": "", "description": "" }, - "xmltvFile": - { + "xmltvFile": { "title": "XMLTV File", "placeholder": "", "description": "" }, - "xmltvChannel": - { + "xmltvChannel": { "title": "XMLTV Channel", "placeholder": "", "description": "" + }, + "timeshift": { + "title": "Timeshift", + "placeholder": "0", + "description": "" } }, - "users": - { - "table": - { + "users": { + "table": { "username": "Username", "password": "Password", "web": "WEB", @@ -285,262 +273,247 @@ "xml": "XML", "api": "API" }, - "username": - { + "username": { "title": "Username", "placeholder": "Username", "description": "" }, - "password": - { + "password": { "title": "Password", "placeholder": "Password", "description": "" }, - "confirm": - { + "confirm": { "title": "Confirm", "placeholder": "Password confirm", "description": "" }, - "web": - { + "web": { "title": "Web Access", "placeholder": "", "description": "" }, - "pms": - { + "pms": { "title": "PMS Access", "placeholder": "", "description": "" }, - "m3u": - { + "m3u": { "title": "M3U Access", "placeholder": "", "description": "" }, - "xml": - { + "xml": { "title": "XML Access", "placeholder": "", "description": "" }, - "api": - { + "api": { "title": "API Access", "placeholder": "", "description": "" } }, - "settings": - { - "category": - { + "settings": { + "category": { "general": "General", + "mapping": "Mapping", "files": "Files", "streaming": "Streaming", "backup": "Backup", "authentication": "Authentication" }, - "update": - { + "update": { "title": "Schedule for updating (Playlist, XMLTV, Backup)", "placeholder": "0000,1000,2000", "description": "Time in 24 hour format (0800 = 8:00 am). More times can be entered comma separated. Leave this field empty if no updates are to be carried out." }, - "api": - { + "api": { "title": "API Interface", "description": "Via API interface it is possible to send commands to xTeVe. API documentation is here" }, - "epgSource": - { + "clearXMLTVCache": { + "title": "Clear XMLTV cache", + "description": "If checked, do not keep XMLTV cache in memory.
Significally reduces RAM usage in idle mode,
but significally slowing down every subsequent update in XEPG database." + }, + "defaultMissingEPG": { + "title": "Fill Missing EPG Data", + "description": "When there is no matching EPG data for channel,
autofill with xTeVe dummy EPG data?" + }, + "enableMappedChannels": { + "title": "Enable mapped channels", + "description": "Automatically enable channels with assigned EPG data" + }, + "disallowURLDuplicates": { + "title": "Disallow URL duplicates", + "description": "If checked, do not add a new channel from playlist if channel with such URL already exists" + }, + "epgSource": { "title": "EPG Source", "description": "PMS:
- Use EPG data from Plex or Emby

XEPG:
- Use of one or more XMLTV files
- Channel management
- M3U / XMLTV export (HTTP link for IPTV apps)" }, - "tuner": - { + "tuner": { "title": "Number of Tuners", "description": "Number of parallel connections that can be established to the provider.
Available for: Plex, Emby (HDHR), M3U (with active buffer).
After a change, xTeVe must be delete in the Plex / Emby DVR settings and set up again." }, - "filesUpdate": - { + "hostIP": { + "title": "Host IP", + "description": "IP address xTeVe will use to form M3U and XMLTV files" + }, + "hostName": { + "title": "Host Name Override", + "description": "Hostname xTeVe will use to form M3U and XMLTV files. This will override Host IP if set" + }, + "tlsMode": { + "title": "TLS (HTTPS) mode", + "description": "Changes web server protocol to HTTPS.
For details, see https://github.com/SenexCrenshaw/xTeVe#tls-mode" + }, + "filesUpdate": { "title": "Updates all files at startup", "description": "Updates all playlists, tuner and XMLTV files at startup." }, - "cacheImages": - { + "cacheImages": { "title": "Image Caching", "description": "All images from the XMLTV file are cached, allowing faster rendering of the grid in the client.
Downloading the images may take a while and will be done in the background." }, - "replaceEmptyImages": - { + "replaceEmptyImages": { "title": "Replace missing program images", "description": "If the poster in the XMLTV program is missing, the channel logo will be used." }, - "xteveAutoUpdate": - { + "xteveAutoUpdate": { "title": "Automatic update of xTeVe", "description": "If a new version of xTeVe is available, it will be automatically installed. The updates are downloaded from GitHub." }, - "streamBuffering": - { + "streamBuffering": { "title": "Stream Buffer", "description": "Functions of the buffer:
- The stream is passed from xTeVe, FFmpeg or VLC to Plex, Emby or M3U Player
- Small jerking of the streams can be compensated
- HLS / M3U8 support
- RTP / RTPS support (only FFmpeg or VLC)
- Re-streaming
- Separate tuner limit for each playlist", "info_false": "No Buffer (Client connects to the streaming server)", "info_xteve": "xTeVe connects to the streaming server", "info_ffmpeg": "FFmpeg connects to the streaming server", "info_vlc": "VLC connects to the streaming server" - }, - "udpxy": - { + "udpxy": { "title": "UDPxy address", "description": "The address of your UDPxy server. If set, and the channel URLs in the m3u is multicast, xTeVe will rewrite it so that it is accessed via the UDPxy service.", "placeholder": "host:port" }, - "ffmpegPath": - { + "ffmpegPath": { "title": "FFmpeg Binary Path", "description": "Path to FFmpeg binary.", "placeholder": "/path/to/ffmpeg" }, - "ffmpegOptions": - { + "ffmpegOptions": { "title": "FFmpeg Options", "description": "FFmpeg options.
Only change if you know what you are doing.
Leave blank to set default settings.", "placeholder": "Leave blank to set default settings" }, - "vlcPath": - { + "vlcPath": { "title": "VLC / CVLC Binary Path", "description": "Path to VLC / CVLC binary.", "placeholder": "/path/to/cvlc" }, - "vlcOptions": - { + "vlcOptions": { "title": "VLC / CVLC Options", "description": "VLC / CVLC options.
Only change if you know what you are doing.
Leave blank to set default settings.", "placeholder": "Leave blank to set default settings" }, - "bufferSize": - { + "bufferSize": { "title": "Buffer Size", "description": "Buffer size in MB.
M3U8: If the TS segment smaller then the buffer size, the file size of the segment is used." }, - "bufferTimeout": - { + "storeBufferInRAM": { + "title": "Store buffer in RAM", + "description": "If checked, write buffer to RAM instead of writing to disk" + }, + "bufferTimeout": { "title": "Timeout for new client connections", "description": "The xTeVe buffer waits until new client connections are established. Helpful for fast channel switching. Value in milliseconds.", "placeholder": "100" }, - "userAgent": - { + "userAgent": { "title": "User Agent", "description": "User Agent for HTTP requests. For every HTTP connection, this value is used for the user agent. Should only be changed if xTeVe is blocked.", "placeholder": "xTeVe" }, - "backupPath": - { + "backupPath": { "title": "Location for automatic backups", "placeholder": "/mnt/data/backup/xteve/", "description": "Before any update of the provider data by the schedule, xTeVe creates a backup. The path for the automatic backups can be changed. xTeVe requires write permission for this folder." }, - "tempPath": - { + "tempPath": { "title": "Location for the temporary files", "placeholder": "/tmp/xteve/", "description": "Location for the buffer files." }, - "backupKeep": - { + "backupKeep": { "title": "Number of backups to keep", "description": "Number of backups to keep. Older backups are automatically deleted." }, - "authenticationWEB": - { + "authenticationWEB": { "title": "WEB Authentication", "description": "Access to the web interface only possible with credentials." }, - "authenticationPMS": - { + "authenticationPMS": { "title": "PMS Authentication", "description": "Plex requests are only possible with authentication.
Warning!!! After activating this function xTeVe must be delete in the PMS DVR settings and set up again." }, - "authenticationM3U": - { + "authenticationM3U": { "title": "M3U Authentication", "description": "Downloading the xteve.m3u file via an HTTP request is only possible with authentication." }, - "authenticationXML": - { + "authenticationXML": { "title": "XML Authentication", "description": "Downloading the xteve.xml file via an HTTP request is only possible with authentication" }, - "authenticationAPI": - { + "authenticationAPI": { "title": "API Authentication", "description": "Access to the API interface is only possible with authentication." } }, - "wizard": - { - "epgSource": - { + "wizard": { + "epgSource": { "title": "EPG Source", "description": "PMS:
- Use EPG data from Plex or Emby

XEPG:
- Use of one or more XMLTV files
- Channel management
- M3U / XMLTV export (HTTP link for IPTV apps)" }, - "tuner": - { + "tuner": { "title": "Number of tuners", "description": "Number of parallel connections that can be established to the provider.
Available for: Plex, Emby (HDHR), M3U (with active buffer).
After a change, xTeVe must be delete in the Plex / Emby DVR settings and set up again." }, - "m3u": - { + "m3u": { "title": "M3U Playlist", "placeholder": "File path or URL of the M3U", "description": "Local or remote playlists" }, - "xmltv": - { + "xmltv": { "title": "XMLTV File", "placeholder": "File path or URL of the XMLTV", "description": "Local or remote XMLTV file" } }, - "login": - { + "login": { "failed": "User authentication failed", "headline": "Login", - "username": - { + "username": { "title": "Username", "placeholder": "Username" }, - "password": - { + "password": { "title": "Password", "placeholder": "Password" } }, - "account": - { + "account": { "failed": "Password does not match", "headline": "Create user account", - "username": - { + "username": { "title": "Username", "placeholder": "Username" }, - "password": - { + "password": { "title": "Password", "placeholder": "Password" }, - "confirm": - { + "confirm": { "title": "Confirm", "placeholder": "Confirm" } diff --git a/html/login.html b/html/login.html index a3e7042..9c1521f 100644 --- a/html/login.html +++ b/html/login.html @@ -1,46 +1,47 @@ - - - - - xTeVe - - - - - + - - - + + + + xTeVe + + + + + -
+ -
-

{{.login.headline}}

-
+ -

{{.authenticationErr}}

+
-
+
+

{{.login.headline}}

+
-
+

{{.authenticationErr}}

-
{{.login.username.title}}:
- -
{{.login.password.title}}:
- +
- +
-
+
{{.login.username.title}}:
+ +
{{.login.password.title}}:
+ - - -
+ + +
+ + + +
+ + - - \ No newline at end of file diff --git a/html/maintenance.html b/html/maintenance.html index b1ba141..c55f54d 100644 --- a/html/maintenance.html +++ b/html/maintenance.html @@ -1,30 +1,32 @@ - - - - - xTeVe - - - - - - - - -
- -
-

Maintenance

-
- -
- xTeVe is updating the database, please try again later. -
- - - -
- - + + + + + + xTeVe + + + + + + + + +
+ +
+

Maintenance

+
+ +
+ xTeVe is updating the database, please try again later. +
+ + + +
+ + + \ No newline at end of file diff --git a/release.json b/release.json new file mode 100644 index 0000000..79426e8 --- /dev/null +++ b/release.json @@ -0,0 +1,4 @@ +{ + "version": "2.5.1", + "go_version": "1.19.0" +} diff --git a/snap/hooks/pre-refresh b/snap/hooks/pre-refresh new file mode 100755 index 0000000..bd6da56 --- /dev/null +++ b/snap/hooks/pre-refresh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -ex + +# Check to see if the service is running +SERVICE_STATUS=`snapctl services xteve.xteve | tail -1 | cut -d " " -f 5` +if [ "$SERVICE_STATUS" != "active" ]; then + exit 0 +fi + +# Check to see if it is doing anything +exec $SNAP/bin/xteve-inactive -port 8080 diff --git a/snap/local/scripts/restart-if-inactive b/snap/local/scripts/restart-if-inactive new file mode 100755 index 0000000..ee8d4f4 --- /dev/null +++ b/snap/local/scripts/restart-if-inactive @@ -0,0 +1,3 @@ +#!/bin/sh + +${SNAP}/bin/xteve-inactive -port 8080 && snapctl restart xteve.xteve diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml new file mode 100644 index 0000000..8e07259 --- /dev/null +++ b/snap/snapcraft.yaml @@ -0,0 +1,62 @@ +name: xteve +base: core22 +summary: M3U Proxy for Plex DVR and Emby Live TV. +adopt-info: xteve +description: | + xTeVe emulates a DVR tuner for Plex and Emby. It takes an M3U files and + emulates a network tuner that can be discovered by those services. Provides + multiple tuners and caching proxy of streams. Can also take XMLTV files an + handle them internally for program guides. + +grade: stable +confinement: strict + +parts: + xteve: + plugin: go + source: . + build-snaps: + - go + override-stage: | + snapcraftctl stage + snapcraftctl set-version `$SNAPCRAFT_STAGE/bin/xteve -version` + snap-scripts: + plugin: dump + source: snap/local/scripts + organize: + '*': bin/ +# vlc: +# plugin: nil +# stage-packages: [ "vlc-bin" ] + ffmpeg: + plugin: nil + stage-packages: [ "ffmpeg" ] + +apps: + xteve: + daemon: simple + command: bin/xteve -port 8080 -config $SNAP_COMMON/config -no-updates -debug 3 + environment: + LD_LIBRARY_PATH: ${LD_LIBRARY_PATH}:${SNAP}/usr/lib:${SNAP}/usr/lib/${SNAP_LAUNCHER_ARCH_TRIPLET}/pulseaudio/ + plugs: + - network + - network-bind +# restart: +# daemon: oneshot +# command: bin/restart-if-inactive +# timer: 00:10-23:10/24 +# plugs: +# - network + inactive: + command: bin/xteve-inactive -port 8080 + plugs: + - network + status: + command: bin/xteve-status -port 8080 + plugs: + - network + +hooks: + pre-refresh: + plugs: + - network diff --git a/src/authentication.go b/src/authentication.go index 1b15876..aae2e31 100644 --- a/src/authentication.go +++ b/src/authentication.go @@ -63,7 +63,7 @@ func createFirstUserForAuthentication(username, password string) (token string, func tokenAuthentication(token string) (newToken string, err error) { - if System.ConfigurationWizard == true { + if System.ConfigurationWizard { return } @@ -74,7 +74,7 @@ func tokenAuthentication(token string) (newToken string, err error) { func basicAuth(r *http.Request, level string) (username string, err error) { - err = errors.New("User authentication failed") + err = errors.New("user authentication failed") auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2) @@ -109,7 +109,7 @@ func urlAuth(r *http.Request, requestType string) (err error) { case "m3u": level = "authentication.m3u" - if Settings.AuthenticationM3U == true { + if Settings.AuthenticationM3U { token, err = authentication.UserAuthentication(username, password) if err != nil { return @@ -119,7 +119,7 @@ func urlAuth(r *http.Request, requestType string) (err error) { case "xml": level = "authentication.xml" - if Settings.AuthenticationXML == true { + if Settings.AuthenticationXML { token, err = authentication.UserAuthentication(username, password) if err != nil { return @@ -150,19 +150,19 @@ func checkAuthorizationLevel(token, level string) (err error) { if v, ok := userData[level].(bool); ok { - if v == false { - err = errors.New("No authorization") + if !v { + err = errors.New("no authorization") } } else { userData[level] = false - err = authentication.WriteUserData(userID, userData) - err = errors.New("No authorization") + authentication.WriteUserData(userID, userData) + //err = errors.New("No authorization") } } else { - err = authentication.WriteUserData(userID, userData) - err = errors.New("No authorization") + authentication.WriteUserData(userID, userData) + //err = errors.New("No authorization") } return diff --git a/src/backup.go b/src/backup.go index 437fbcb..4899fa1 100644 --- a/src/backup.go +++ b/src/backup.go @@ -1,274 +1,285 @@ package src import ( - b64 "encoding/base64" - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" + b64 "encoding/base64" + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" ) func xTeVeAutoBackup() (err error) { - var archiv = "xteve_auto_backup_" + time.Now().Format("20060102_1504") + ".zip" - var target string - var sourceFiles = make([]string, 0) - var oldBackupFiles = make([]string, 0) - var debug string + var archive = "xteve_auto_backup_" + time.Now().Format("20060102_1504") + ".zip" + var target string + var sourceFiles = make([]string, 0) + var oldBackupFiles = make([]string, 0) + var debug string - if len(Settings.BackupPath) > 0 { - System.Folder.Backup = Settings.BackupPath - } + if len(Settings.BackupPath) > 0 { + System.Folder.Backup = Settings.BackupPath + } - showInfo("Backup Path:" + System.Folder.Backup) + showInfo("Backup Path:" + System.Folder.Backup) - err = checkFolder(System.Folder.Backup) - if err != nil { - ShowError(err, 1070) - return - } + err = checkFolder(System.Folder.Backup) + if err != nil { + ShowError(err, 1070) + return + } - // Alte Backups löschen - files, err := ioutil.ReadDir(System.Folder.Backup) + // Delete Old Backups + files, err := ioutil.ReadDir(System.Folder.Backup) - if err == nil { + if err == nil { - for _, file := range files { + for _, file := range files { - if filepath.Ext(file.Name()) == ".zip" && strings.Contains(file.Name(), "xteve_auto_backup") { - oldBackupFiles = append(oldBackupFiles, file.Name()) - } + if filepath.Ext(file.Name()) == ".zip" && strings.Contains(file.Name(), "xteve_auto_backup") { + oldBackupFiles = append(oldBackupFiles, file.Name()) + } - } + } - // Alle Backups löschen - var end int - switch Settings.BackupKeep { - case 0: - end = 0 - default: - end = Settings.BackupKeep - 1 - } + // Delete All Backups + var end int + switch Settings.BackupKeep { + case 0: + end = 0 + default: + end = Settings.BackupKeep - 1 + } - for i := 0; i < len(oldBackupFiles)-end; i++ { + for i := 0; i < len(oldBackupFiles)-end; i++ { - os.RemoveAll(System.Folder.Backup + oldBackupFiles[i]) - debug = fmt.Sprintf("Delete backup file:%s", oldBackupFiles[i]) - showDebug(debug, 1) + os.RemoveAll(System.Folder.Backup + oldBackupFiles[i]) + debug = fmt.Sprintf("Delete backup file:%s", oldBackupFiles[i]) + showDebug(debug, 1) - } + } - if Settings.BackupKeep == 0 { - return - } + if Settings.BackupKeep == 0 { + return + } - } else { + } else { - return + return - } + } - // Backup erstellen - if err == nil { + // Create a Backup + if err == nil { - target = System.Folder.Backup + archiv + target = System.Folder.Backup + archive - for _, i := range SystemFiles { - sourceFiles = append(sourceFiles, System.Folder.Config+i) - } + for _, i := range SystemFiles { + sourceFiles = append(sourceFiles, System.Folder.Config+i) + } - sourceFiles = append(sourceFiles, System.Folder.ImagesUpload) + sourceFiles = append(sourceFiles, System.Folder.ImagesUpload) + if Settings.TLSMode { + sourceFiles = append(sourceFiles, System.Folder.Certificates) + } - err = zipFiles(sourceFiles, target) + err = zipFiles(sourceFiles, target) - if err == nil { + if err == nil { - debug = fmt.Sprintf("Create backup file:%s", target) - showDebug(debug, 1) + debug = fmt.Sprintf("Create backup file:%s", target) + showDebug(debug, 1) - showInfo("Backup file:" + target) + showInfo("Backup file:" + target) - } + } - } + } - return + return } -func xteveBackup() (archiv string, err error) { +func xteveBackup() (archive string, err error) { - err = checkFolder(System.Folder.Temp) - if err != nil { - return - } + err = checkFolder(System.Folder.Temp) + if err != nil { + return + } - archiv = "xteve_backup_" + time.Now().Format("20060102_1504") + ".zip" + archive = "xteve_backup_" + time.Now().Format("20060102_1504") + ".zip" - var target = System.Folder.Temp + archiv - var sourceFiles = make([]string, 0) + var target = System.Folder.Temp + archive + var sourceFiles = make([]string, 0) - for _, i := range SystemFiles { - sourceFiles = append(sourceFiles, System.Folder.Config+i) - } + for _, i := range SystemFiles { + sourceFiles = append(sourceFiles, System.Folder.Config+i) + } - sourceFiles = append(sourceFiles, System.Folder.Data) + sourceFiles = append(sourceFiles, System.Folder.Data) + if Settings.TLSMode { + sourceFiles = append(sourceFiles, System.Folder.Certificates) + } - err = zipFiles(sourceFiles, target) - if err != nil { - ShowError(err, 0) - return - } + err = zipFiles(sourceFiles, target) + if err != nil { + ShowError(err, 0) + return + } - return + return } func xteveRestore(archive string) (newWebURL string, err error) { - var newPort, oldPort, backupVersion, tmpRestore string + var newPort, oldPort, backupVersion, tmpRestore string - tmpRestore = System.Folder.Temp + "restore" + string(os.PathSeparator) + tmpRestore = System.Folder.Temp + "restore" + string(os.PathSeparator) - err = checkFolder(tmpRestore) - if err != nil { - return - } + defer os.RemoveAll(tmpRestore) + defer os.Remove(archive) - // Zip Archiv in tmp entpacken - err = extractZIP(archive, tmpRestore) - if err != nil { - return - } + err = checkFolder(tmpRestore) + if err != nil { + return + } - // Neue Config laden um den Port und die Version zu überprüfen - newConfig, err := loadJSONFileToMap(tmpRestore + "settings.json") - if err != nil { - ShowError(err, 0) - return - } + // Unpack the ZIP Archive in tmp + err = extractZIP(archive, tmpRestore) + if err != nil { + return + } - backupVersion = newConfig["version"].(string) - if backupVersion < System.Compatibility { - err = errors.New(getErrMsg(1013)) - return - } + // Load a new Config to check the Port and Version + newConfig, err := loadJSONFileToMap(tmpRestore + "settings.json") + if err != nil { + ShowError(err, 0) + return + } - // Zip Archiv in den Config Ordner entpacken - err = extractZIP(archive, System.Folder.Config) - if err != nil { - return - } + backupVersion = newConfig["version"].(string) + if backupVersion < System.Compatibility { + err = errors.New(getErrMsg(1013)) + return + } - // Neue Config laden um den Port und die Version zu überprüfen - newConfig, err = loadJSONFileToMap(System.Folder.Config + "settings.json") - if err != nil { - ShowError(err, 0) - return - } + if err = removeChildItems(getPlatformPath(System.Folder.Config)); err != nil { + ShowError(err, 1073) + } - newPort = newConfig["port"].(string) - oldPort = Settings.Port + // Extract the ZIP Archive into the Config Folder + err = extractZIP(archive, System.Folder.Config) + if err != nil { + return + } - if newPort == oldPort { + // Load a new Config to check the Port and Version + newConfig, err = loadJSONFileToMap(System.Folder.Config + "settings.json") + if err != nil { + ShowError(err, 0) + return + } - if err != nil { - ShowError(err, 0) - } + newPort = newConfig["port"].(string) + oldPort = Settings.Port - loadSettings() + if newPort == oldPort { - err := Init() - if err != nil { - ShowError(err, 0) - return "", err - } + if err != nil { + ShowError(err, 0) + } - err = StartSystem(true) - if err != nil { - ShowError(err, 0) - return "", err - } + loadSettings() - return "", err - } + err := Init() + if err != nil { + ShowError(err, 0) + return "", err + } - var url = System.URLBase + "/web/" - newWebURL = strings.Replace(url, ":"+oldPort, ":"+newPort, 1) + err = StartSystem(true) + if err != nil { + ShowError(err, 0) + return "", err + } - os.RemoveAll(tmpRestore) + return "", err + } - return + var url = System.URLBase + "/web/" + newWebURL = strings.Replace(url, ":"+oldPort, ":"+newPort, 1) + + return } func xteveRestoreFromWeb(input string) (newWebURL string, err error) { - // Base64 Json String in base64 umwandeln - b64data := input[strings.IndexByte(input, ',')+1:] + // Convert base64 JSON string to base64 + b64data := input[strings.IndexByte(input, ',')+1:] - // Base64 in bytes umwandeln und speichern - sDec, err := b64.StdEncoding.DecodeString(b64data) + // Convert Base64 into bytes and save + sDec, err := b64.StdEncoding.DecodeString(b64data) - if err != nil { - return - } + if err != nil { + return + } - var archive = System.Folder.Temp + "restore.zip" + var archive = System.Folder.Temp + "restore.zip" - err = writeByteToFile(archive, sDec) - if err != nil { - return - } + err = writeByteToFile(archive, sDec) + if err != nil { + return + } - newWebURL, err = xteveRestore(archive) + newWebURL, err = xteveRestore(archive) - return + return } -// XteveRestoreFromCLI : Wiederherstellung über die Kommandozeile +// XteveRestoreFromCLI : Recovery from the Command Line func XteveRestoreFromCLI(archive string) (err error) { - var confirm string + var confirm string - println() - showInfo(fmt.Sprintf("Version:%s Build: %s", System.Version, System.Build)) - showInfo(fmt.Sprintf("Backup File:%s", archive)) - showInfo(fmt.Sprintf("System Folder:%s", getPlatformPath(System.Folder.Config))) - println() + println() + showInfo(fmt.Sprintf("Version:%s Build: %s", System.Version, System.Build)) + showInfo(fmt.Sprintf("Backup File:%s", archive)) + showInfo(fmt.Sprintf("System Folder:%s", getPlatformPath(System.Folder.Config))) + println() - fmt.Print("All data will be replaced with those from the backup. Should the files be restored? [yes|no]:") + fmt.Print("All data will be replaced with those from the backup. Should the files be restored? [yes|no]:") - fmt.Scanln(&confirm) + fmt.Scanln(&confirm) - switch strings.ToLower(confirm) { + switch strings.ToLower(confirm) { - case "yes": - break + case "yes": + break - case "no": - return + case "no": + return - default: - fmt.Println("Invalid input") - return + default: + fmt.Println("Invalid input") + return - } + } - if len(System.Folder.Config) > 0 { + if len(System.Folder.Config) > 0 { - err = checkFilePermission(System.Folder.Config) - if err != nil { - return - } + err = checkFilePermission(System.Folder.Config) + if err != nil { + return + } - _, err = xteveRestore(archive) - if err != nil { - return - } + _, err = xteveRestore(archive) + if err != nil { + return + } - showHighlight(fmt.Sprintf("Restor:Backup was successfully restored. %s can now be started normally", System.Name)) + showHighlight(fmt.Sprintf("Restor:Backup was successfully restored. %s can now be started normally", System.Name)) - } - return + } + return } diff --git a/src/buffer.go b/src/buffer.go index 7af38e7..66fe6a1 100644 --- a/src/buffer.go +++ b/src/buffer.go @@ -1,7 +1,7 @@ package src /* - Tuner-Limit Bild als Video rendern [ffmpeg] + Render Tuner Stream-Limit image as Video [ffmpeg] -loop 1 -i stream-limit.jpg -c:v libx264 -t 1 -pix_fmt yuv420p -vf scale=1920:1080 stream-limit.ts */ @@ -21,6 +21,10 @@ import ( "strconv" "strings" "time" + + "github.com/avfs/avfs/vfs/memfs" + "github.com/avfs/avfs/vfs/osfs" + "github.com/samber/lo" ) func createStreamID(stream map[int]ThisStream) (streamID int) { @@ -59,17 +63,17 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon //w.Header().Set("Connection", "keep-alive") w.Header().Set("Connection", "close") - // Überprüfen ob die Playlist schon verwendet wird + // Check whether the Playlist is already in use if p, ok := BufferInformation.Load(playlistID); !ok { var playlistType string - // Playlist wird noch nicht verwendet, Default-Werte für die Playlist erstellen + // Playlist is not yet used, create Default Values for the Playlist playlist.Folder = System.Folder.Temp + playlistID + string(os.PathSeparator) playlist.PlaylistID = playlistID playlist.Streams = make(map[int]ThisStream) playlist.Clients = make(map[int]ThisClient) - err := checkFolder(playlist.Folder) + err := checkVFSFolder(playlist.Folder, bufferVFS) if err != nil { ShowError(err, 000) httpStatusError(w, r, 404) @@ -90,7 +94,7 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon playlist.PlaylistName = getProviderParameter(playlist.PlaylistID, playlistType, "name") - // Default-Werte für den Stream erstellen + // Create Default Values for the Stream streamID = createStreamID(playlist.Streams) client.Connection = 1 @@ -105,8 +109,8 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon } else { - // Playlist wird bereits zum streamen verwendet - // Überprüfen ob die URL bereit von einem anderen Client gestreamt wird. + // Playlist is already being used for streaming + // Check if the URL is already being streamed by another Client playlist = p.(Playlist) @@ -145,18 +149,17 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon } - // Neuer Stream bei einer bereits aktiven Playlist - if newStream == true { + // New Stream for an already active Playlist + if newStream { - // Prüfen ob die Playlist noch einen weiteren Stream erlaubt (Tuner) + // Check whether the Playlist allows another Stream (Tuner) if len(playlist.Streams) >= playlist.Tuner { showInfo(fmt.Sprintf("Streaming Status:Playlist: %s - No new connections available. Tuner = %d", playlist.PlaylistName, playlist.Tuner)) if value, ok := webUI["html/video/stream-limit.ts"]; ok { - var content string - content = GetHTMLString(value.(string)) + var content string = GetHTMLString(value.(string)) w.WriteHeader(200) w.Header().Set("Content-type", "video/mpeg") @@ -174,8 +177,8 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon return } - // Playlist erlaubt einen weiterern Stream (Das Limit des Tuners ist noch nicht erreicht) - // Default-Werte für den Stream erstellen + // Playlist allows another Stream (The Tuner limit has not yet been reached) + // Create Default Values for the Stream stream = ThisStream{} client = ThisClient{} @@ -195,10 +198,10 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon } - // Überprüfen ob der Stream breits von einem anderen Client abgespielt wird - if playlist.Streams[streamID].Status == false && newStream == true { + // Check whether the Stream is already being played by another Client + if !playlist.Streams[streamID].Status && newStream { - // Neuer Buffer wird benötigt + // New buffer is required stream = playlist.Streams[streamID] stream.MD5 = getMD5(streamingURL) stream.Folder = playlist.Folder + stream.MD5 + string(os.PathSeparator) @@ -230,7 +233,7 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon w.WriteHeader(200) - for { // Loop 1: Warten bis das erste Segment durch den Buffer heruntergeladen wurde + for { // Loop 1: Wait until the first Segment has been downloaded by the Buffer if p, ok := BufferInformation.Load(playlistID); ok { @@ -238,7 +241,7 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon if stream, ok := playlist.Streams[streamID]; ok { - if stream.Status == false { + if !stream.Status { timeOut++ @@ -260,16 +263,17 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon var oldSegments []string - for { // Loop 2: Temporäre Datein sind vorhanden, Daten können zum Client gesendet werden + for { // Loop 2: Temporary files are available, Data can be sent to the Client - // HTTP Clientverbindung überwachen + // Monitor HTTP Client connection - cn, ok := w.(http.CloseNotifier) + //cn, ok := w.(http.CloseNotifier) + ctx := r.Context() if ok { select { - case <-cn.CloseNotify(): + case <-ctx.Done(): // cn.CloseNotify(): killClientConnection(streamID, playlistID, false) return @@ -293,17 +297,17 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon } - if _, err := os.Stat(stream.Folder); os.IsNotExist(err) { + if _, err := bufferVFS.Stat(stream.Folder); fsIsNotExistErr(err) { killClientConnection(streamID, playlistID, false) return } - var tmpFiles = getTmpFiles(&stream) + var tmpFiles = getBufTmpFiles(&stream) //fmt.Println("Buffer Loop:", stream.Connection) for _, f := range tmpFiles { - if _, err := os.Stat(stream.Folder); os.IsNotExist(err) { + if _, err := bufferVFS.Stat(stream.Folder); fsIsNotExistErr(err) { killClientConnection(streamID, playlistID, false) return } @@ -312,7 +316,13 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon var fileName = stream.Folder + f - file, err := os.Open(fileName) + file, err := bufferVFS.Open(fileName) + if err != nil { + debug = fmt.Sprintf("Buffer Open (%s)", fileName) + showDebug(debug, 2) + return + } + defer file.Close() if err == nil { @@ -330,7 +340,7 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon file.Seek(0, 0) - if streaming == false { + if !streaming { contentType := http.DetectContentType(buffer) _ = contentType @@ -365,12 +375,14 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon } - var n = indexOfString(f, oldSegments) + var n = lo.IndexOf(oldSegments, f) if n > 20 { var fileToRemove = stream.Folder + oldSegments[0] - os.RemoveAll(getPlatformFile(fileToRemove)) + if err = bufferVFS.RemoveAll(getPlatformFile(fileToRemove)); err != nil { + ShowError(err, 4007) + } oldSegments = append(oldSegments[:0], oldSegments[0+1:]...) } @@ -385,31 +397,31 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon time.Sleep(time.Duration(100) * time.Millisecond) } - } // Ende Loop 2 + } // End of Loop 2 } else { - // Stream nicht vorhanden + // Stream not available killClientConnection(streamID, stream.PlaylistID, false) showInfo(fmt.Sprintf("Streaming Status:Playlist: %s - Tuner: %d / %d", playlist.PlaylistName, len(playlist.Streams), playlist.Tuner)) return } - } // Ende BufferInformation + } // End of Buffer Information - } // Ende Loop 1 + } // End of Loop 1 } -func getTmpFiles(stream *ThisStream) (tmpFiles []string) { +func getBufTmpFiles(stream *ThisStream) (tmpFiles []string) { var tmpFolder = stream.Folder var fileIDs []float64 - if _, err := os.Stat(tmpFolder); !os.IsNotExist(err) { + if _, err := bufferVFS.Stat(tmpFolder); !fsIsNotExistErr(err) { - files, err := ioutil.ReadDir(getPlatformPath(tmpFolder)) + files, err := bufferVFS.ReadDir(getPlatformPath(tmpFolder)) if err != nil { ShowError(err, 000) return @@ -435,7 +447,7 @@ func getTmpFiles(stream *ThisStream) (tmpFiles []string) { var fileName = fmt.Sprintf("%d.ts", int64(file)) - if indexOfString(fileName, stream.OldSegments) == -1 { + if lo.IndexOf(stream.OldSegments, fileName) == -1 { tmpFiles = append(tmpFiles, fileName) stream.OldSegments = append(stream.OldSegments, fileName) } @@ -458,7 +470,7 @@ func killClientConnection(streamID int, playlistID string, force bool) { var playlist = p.(Playlist) - if force == true { + if force { delete(playlist.Streams, streamID) showInfo(fmt.Sprintf("Streaming Status:Playlist: %s - Tuner: %d / %d", playlist.PlaylistName, len(playlist.Streams), playlist.Tuner)) return @@ -511,7 +523,9 @@ func clientConnection(stream ThisStream) (status bool) { debug = fmt.Sprintf("Remove tmp folder:%s", stream.Folder) showDebug(debug, 1) - os.RemoveAll(stream.Folder) + if err := bufferVFS.RemoveAll(stream.Folder); err != nil { + ShowError(err, 4005) + } if p, ok := BufferInformation.Load(stream.PlaylistID); ok { @@ -547,7 +561,7 @@ func connectToStreamingServer(streamID int, playlistID string) { var m3u8Segments []string var bandwidth BandwidthCalculation var networkBandwidth = Settings.M3U8AdaptiveBandwidthMBPS * 1e+6 - // Größe des Buffers + // Size of the Buffer var bufferSize = Settings.BufferSize var buffer = make([]byte, 1024*bufferSize*2) @@ -592,16 +606,18 @@ func connectToStreamingServer(streamID int, playlistID string) { } - os.RemoveAll(getPlatformPath(tmpFolder)) + if err := bufferVFS.RemoveAll(getPlatformPath(tmpFolder)); err != nil { + ShowError(err, 4005) + } - err := checkFolder(tmpFolder) + err := checkVFSFolder(tmpFolder, bufferVFS) if err != nil { ShowError(err, 0) addErrorToStream(err) return } - // M3U8 Segmente + // M3U8 Segments InitBuffer: defaultSegment() @@ -614,9 +630,9 @@ func connectToStreamingServer(streamID int, playlistID string) { var stream ThisStream = playlist.Streams[streamID] - if stream.Status == false { + if !stream.Status { - if strings.Index(stream.URL, ".m3u8") != -1 { + if strings.Contains(stream.URL, ".m3u8") { showInfo("Streaming Type:" + "[HLS / M3U8]") } else { showInfo("Streaming Type:" + "[TS]") @@ -634,7 +650,7 @@ func connectToStreamingServer(streamID int, playlistID string) { for { - if clientConnection(stream) == false { + if !clientConnection(stream) { return } @@ -653,10 +669,10 @@ func connectToStreamingServer(streamID int, playlistID string) { debug = fmt.Sprintf("Connection to:%s", currentURL) showDebug(debug, 2) - // Sprung für Redirect (301 <---> 308) + // Jump for redirect (301 <---> 308) Redirect: - req, err := http.NewRequest("GET", currentURL, nil) + req, _ := http.NewRequest("GET", currentURL, nil) req.Header.Set("User-Agent", Settings.UserAgent) req.Header.Set("Connection", "close") //req.Header.Set("Range", "bytes=0-") @@ -678,7 +694,7 @@ func connectToStreamingServer(streamID int, playlistID string) { if resp == nil { - err = errors.New("No response from streaming server") + err = errors.New("no response from streaming server") fmt.Println("Current URL:", currentURL) ShowError(err, 0) @@ -709,7 +725,7 @@ func connectToStreamingServer(streamID int, playlistID string) { } else { - err = errors.New("Streaming server") + err = errors.New("streaming server") ShowError(err, 4002) addErrorToStream(err) @@ -730,13 +746,11 @@ func connectToStreamingServer(streamID int, playlistID string) { } - defer resp.Body.Close() - } defer resp.Body.Close() - // HTTP Status überprüfen, bei Fehlern wird der Stream beendet + // Check HTTP Status, in case of errors the stream is terminated var contentType = resp.Header.Get("Content-Type") var httpStatusCode = resp.StatusCode var httpStatusInfo = fmt.Sprintf("HTTP Response Status [%d] %s", httpStatusCode, http.StatusText(resp.StatusCode)) @@ -763,8 +777,8 @@ func connectToStreamingServer(streamID int, playlistID string) { return } - // Informationen über den Streamingserver auslesen - if stream.Status == false { + // Read out information about the streaming server + if !stream.Status { if len(stream.URLStreamingServer) == 0 { @@ -797,7 +811,7 @@ func connectToStreamingServer(streamID int, playlistID string) { } - // Content Type bereinigen + // Clean up Content Type if len(contentType) > 0 { var ct = strings.SplitN(contentType, ";", 2) contentType = strings.ToLower(ct[0]) @@ -828,7 +842,7 @@ func connectToStreamingServer(streamID int, playlistID string) { var fileSize int - // Größe des Buffers + // Size of the Buffer buffer = make([]byte, 1024*bufferSize*2) var tmpFileSize = 1024 * bufferSize * 1 @@ -840,12 +854,12 @@ func connectToStreamingServer(streamID int, playlistID string) { var tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment) - if clientConnection(stream) == false { + if !clientConnection(stream) { resp.Body.Close() return } - bufferFile, err := os.Create(tmpFile) + bufferFile, err := bufferVFS.Create(tmpFile) if err != nil { addErrorToStream(err) @@ -865,7 +879,7 @@ func connectToStreamingServer(streamID int, playlistID string) { } timeOut = 0 - // Buffer mit Daten vom Server füllen + // Fill the Buffer with data from the Server n, err := resp.Body.Read(buffer) if err != nil && err != io.EOF { @@ -892,20 +906,19 @@ func connectToStreamingServer(streamID int, playlistID string) { fileSize = fileSize + n - if clientConnection(stream) == false { + if !clientConnection(stream) { resp.Body.Close() bufferFile.Close() - err = os.RemoveAll(stream.Folder) - if err != nil { + if err = bufferVFS.RemoveAll(stream.Folder); err != nil { ShowError(err, 4005) } return } - // Buffer auf die Festplatte speichern + // Save the buffer to the Hard Disk if fileSize >= tmpFileSize/2 || n == 0 { Lock.Lock() @@ -934,20 +947,19 @@ func connectToStreamingServer(streamID int, playlistID string) { tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment) - if clientConnection(stream) == false { + if !clientConnection(stream) { bufferFile.Close() resp.Body.Close() - err = os.RemoveAll(stream.Folder) - if err != nil { + if err = bufferVFS.RemoveAll(stream.Folder); err != nil { ShowError(err, 4005) } return } - bufferFile, err = os.Create(tmpFile) + bufferFile, err = bufferVFS.Create(tmpFile) if err != nil { addErrorToStream(err) resp.Body.Close() @@ -969,10 +981,10 @@ func connectToStreamingServer(streamID int, playlistID string) { //-- - // Umbekanntes Format + // Unknown Format default: showInfo("Content Type:" + resp.Header.Get("Content-Type")) - err = errors.New("Streaming error") + err = errors.New("streaming error") ShowError(err, 4003) addErrorToStream(err) @@ -982,8 +994,8 @@ func connectToStreamingServer(streamID int, playlistID string) { s++ - // Wartezeit für den Download das nächste Segments berechnen - if stream.HLS == true { + // Calculate the waiting time for the Download of the next Segment + if stream.HLS { var sleep float64 @@ -1008,7 +1020,7 @@ func connectToStreamingServer(streamID int, playlistID string) { _ = i time.Sleep(time.Duration(100) * time.Millisecond) - if _, err := os.Stat(stream.Folder); os.IsNotExist(err) { + if _, err := bufferVFS.Stat(stream.Folder); fsIsNotExistErr(err) { break } @@ -1024,9 +1036,9 @@ func connectToStreamingServer(streamID int, playlistID string) { resp.Body.Close() - } // Ende for loop + } // End for loop - } // Ende BufferInformation + } // End of BufferInformation } @@ -1125,7 +1137,7 @@ func parseM3U8(stream *ThisStream) (err error) { var parseURL = func(line string, segment *Segment) { - // Prüfen ob die Adresse eine gültige URL ist (http://... oder /path/to/stream) + // Check if the address is a valid URL (http://... or /path/to/stream) _, err := url.ParseRequestURI(line) if err == nil { @@ -1133,33 +1145,32 @@ func parseM3U8(stream *ThisStream) (err error) { u, _ := url.Parse(line) if len(u.Host) == 0 { - // Adresse enthällt nicht die Domain, Redirect wird der Adresse hinzugefügt + // Check whether the domain is included in the address segment.URL = stream.URLStreamingServer + line } else { - // Domain in der Adresse enthalten + // Domain included in the address segment.URL = line } } else { - // keine URL, sondern ein Dateipfad (media/file-01.ts) + // not URL, but a file path (media/file-01.ts) var serverURLPath = strings.Replace(stream.M3U8URL, path.Base(stream.M3U8URL), line, -1) segment.URL = serverURLPath } - return } if strings.Contains(stream.Body, "#EXTM3U") { var lines = strings.Split(strings.Replace(stream.Body, "\r\n", "\n", -1), "\n") - if stream.DynamicBandwidth == false { + if !stream.DynamicBandwidth { stream.DynamicStream = make(map[int]DynamicStream) } - // Parameter parsen + // Parse Parameters for i, line := range lines { _ = i @@ -1177,8 +1188,8 @@ func parseM3U8(stream *ThisStream) (err error) { } - // M3U8 enthällt mehrere Links zu weiteren M3U8 Wiedergabelisten (Bandbreitenoption) - if segment.Info == true && len(line) > 0 && line[0:1] != "#" { + // M3U8 contains several links to additional M3U8 Playlists (Bandwidth option) + if segment.Info && len(line) > 0 && line[0:1] != "#" { var dynamicStream DynamicStream @@ -1195,7 +1206,7 @@ func parseM3U8(stream *ThisStream) (err error) { } - // Segment mit TS Stream + // Segment with TS Stream if segment.Duration > 0 && line[0:1] != "#" { parseURL(line, &segment) @@ -1222,7 +1233,7 @@ func parseM3U8(stream *ThisStream) (err error) { noNewSegment = true - if stream.Status == false { + if !stream.Status { if len(m3u8Segments) >= 2 { m3u8Segments = m3u8Segments[0 : len(m3u8Segments)-1] @@ -1234,12 +1245,12 @@ func parseM3U8(stream *ThisStream) (err error) { segment = s - if stream.Status == false { + if !stream.Status { noNewSegment = false stream.LastSequence = segment.Sequence - // Stream ist vom Typ VOD. Es muss das erste Segment der M3U8 Playlist verwendet werden. + // Stream is of type VOD. The first segment of the M3U8 playlist must be used. if strings.ToUpper(segment.PlaylistType) == "VOD" { break } @@ -1260,9 +1271,9 @@ func parseM3U8(stream *ThisStream) (err error) { } - if noNewSegment == false { + if !noNewSegment { - if stream.DynamicBandwidth == true { + if stream.DynamicBandwidth { switchBandwidth(stream) } else { stream.Segment = append(stream.Segment, segment) @@ -1270,7 +1281,7 @@ func parseM3U8(stream *ThisStream) (err error) { } - if noNewSegment == true { + if noNewSegment { var sleep = lastSegmentDuration * 0.5 @@ -1279,7 +1290,7 @@ func parseM3U8(stream *ThisStream) (err error) { _ = i time.Sleep(time.Duration(100) * time.Millisecond) - if _, err := os.Stat(stream.Folder); os.IsNotExist(err) { + if _, err := bufferVFS.Stat(stream.Folder); fsIsNotExistErr(err) { break } @@ -1341,7 +1352,7 @@ func switchBandwidth(stream *ThisStream) (err error) { return } -// Buffer mit FFMPEG +// Buffer with FFMPEG func thirdPartyBuffer(streamID int, playlistID string) { if p, ok := BufferInformation.Load(playlistID); ok { @@ -1354,7 +1365,7 @@ func thirdPartyBuffer(streamID int, playlistID string) { var buf bytes.Buffer var fileSize = 0 var streamStatus = make(chan bool) - + //var dir_file_mode os.FileMode = fs.ModeDir var tmpFolder = playlist.Streams[streamID].Folder var url = playlist.Streams[streamID].URL @@ -1390,9 +1401,11 @@ func thirdPartyBuffer(streamID int, playlistID string) { } - os.RemoveAll(getPlatformPath(tmpFolder)) + if err := bufferVFS.RemoveAll(getPlatformPath(tmpFolder)); err != nil { + ShowError(err, 4005) + } - err := checkFolder(tmpFolder) + err := checkVFSFolder(tmpFolder, bufferVFS) if err != nil { ShowError(err, 0) addErrorToStream(err) @@ -1411,7 +1424,7 @@ func thirdPartyBuffer(streamID int, playlistID string) { var tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment) - f, err := os.Create(tmpFile) + f, err := bufferVFS.Create(tmpFile) f.Close() if err != nil { addErrorToStream(err) @@ -1420,7 +1433,7 @@ func thirdPartyBuffer(streamID int, playlistID string) { //args = strings.Replace(args, "[USER-AGENT]", Settings.UserAgent, -1) - // User-Agent setzen + // Set User-Agent var args []string for i, a := range strings.Split(options, " ") { @@ -1458,7 +1471,7 @@ func thirdPartyBuffer(streamID int, playlistID string) { debug = fmt.Sprintf("%s:%s %s", bufferType, path, args) showDebug(debug, 1) - // Byte-Daten vom Prozess + // Byte-Data from the Process stdOut, err := cmd.StdoutPipe() if err != nil { ShowError(err, 0) @@ -1468,7 +1481,7 @@ func thirdPartyBuffer(streamID int, playlistID string) { return } - // Log-Daten vom Prozess + // Log-Data from the Process logOut, err := cmd.StderrPipe() if err != nil { ShowError(err, 0) @@ -1478,7 +1491,7 @@ func thirdPartyBuffer(streamID int, playlistID string) { return } - if len(buf.Bytes()) == 0 && stream.Status == false { + if len(buf.Bytes()) == 0 && !stream.Status { showInfo(bufferType + ":Processing data") } @@ -1487,7 +1500,7 @@ func thirdPartyBuffer(streamID int, playlistID string) { go func() { - // Log Daten vom Prozess im Dubug Mode 1 anzeigen. + // Show Log Data from the Process in Debug Mode 1. scanner := bufio.NewScanner(logOut) scanner.Split(bufio.ScanLines) @@ -1508,7 +1521,7 @@ func thirdPartyBuffer(streamID int, playlistID string) { }() - f, err = os.OpenFile(tmpFile, os.O_APPEND|os.O_WRONLY, 0600) + f, err = bufferVFS.OpenFile(tmpFile, os.O_APPEND|os.O_WRONLY, 0600) if err != nil { panic(err) } @@ -1556,11 +1569,11 @@ func thirdPartyBuffer(streamID int, playlistID string) { } - if fileSize == 0 && stream.Status == false { + if fileSize == 0 && !stream.Status { showInfo("Streaming Status:Receive data from " + bufferType) } - if clientConnection(stream) == false { + if !clientConnection(stream) { cmd.Process.Kill() f.Close() cmd.Wait() @@ -1585,7 +1598,7 @@ func thirdPartyBuffer(streamID int, playlistID string) { if fileSize >= bufferSize/2 { - if tmpSegment == 1 && stream.Status == false { + if tmpSegment == 1 && !stream.Status { close(t) close(streamStatus) showInfo(fmt.Sprintf("Streaming Status:Buffering data from %s", bufferType)) @@ -1594,7 +1607,7 @@ func thirdPartyBuffer(streamID int, playlistID string) { f.Close() tmpSegment++ - if stream.Status == false { + if !stream.Status { Lock.Lock() stream.Status = true playlist.Streams[streamID] = stream @@ -1607,8 +1620,8 @@ func thirdPartyBuffer(streamID int, playlistID string) { fileSize = 0 var errCreate, errOpen error - f, errCreate = os.Create(tmpFile) - f, errOpen = os.OpenFile(tmpFile, os.O_APPEND|os.O_WRONLY, 0600) + _, errCreate = bufferVFS.Create(tmpFile) + f, errOpen = bufferVFS.OpenFile(tmpFile, os.O_APPEND|os.O_WRONLY, 0600) if errCreate != nil || errOpen != nil { cmd.Process.Kill() ShowError(err, 0) @@ -1660,6 +1673,16 @@ func getTuner(id, playlistType string) (tuner int) { return } +func initBufferVFS(virtual bool) { + + if virtual { + bufferVFS = memfs.New(memfs.WithMainDirs()) + } else { + bufferVFS = osfs.New() + } + +} + func debugRequest(req *http.Request) { var debugLevel = 3 @@ -1696,8 +1719,6 @@ func debugRequest(req *http.Request) { debug = "Request:* * * * * * END HTTP(S) REQUEST * * * * * *" showDebug(debug, debugLevel) - - return } func debugResponse(resp *http.Response) { @@ -1741,6 +1762,4 @@ func debugResponse(resp *http.Response) { debug = "Pesponse:* * * * * * END RESPONSE * * * * * * " showDebug(debug, debugLevel) - - return } diff --git a/src/cert.go b/src/cert.go new file mode 100644 index 0000000..3725b60 --- /dev/null +++ b/src/cert.go @@ -0,0 +1,79 @@ +package src + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "math/big" + "net" + "os" + "time" +) + +// genCertFiles creates a self-signed certificate and it's private key in config/certificates directory. +// +// Inspired by https://gist.github.com/shaneutt/5e1995295cff6721c89a71d13a71c251 +func genCertFiles() (err error) { + showInfo("Web server:" + "Generating certificate") + + subject := pkix.Name{ + CommonName: "xTeVe", + Country: []string{"US"}, + Locality: []string{"San Francisco"}, + Organization: []string{"xTeVe, Inc."}, + PostalCode: []string{"94016"}, + Province: []string{""}, + StreetAddress: []string{"Golden Gate Bridge"}, + } + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + return + } + + certPrivKey, err := rsa.GenerateKey(rand.Reader, 4096) + if err != nil { + return + } + + certPrivKeyPEM := pem.EncodeToMemory(&pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey), + }) + + cert := &x509.Certificate{ + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + IPAddresses: append(System.IPAddressesV4Raw, net.IPv6loopback), + KeyUsage: x509.KeyUsageDigitalSignature, + NotAfter: time.Now().AddDate(10, 0, 0), + NotBefore: time.Now(), + SerialNumber: serialNumber, + Subject: subject, + SubjectKeyId: []byte{1, 2, 3, 4, 6}, + } + + certBytes, err := x509.CreateCertificate(rand.Reader, cert, cert, &certPrivKey.PublicKey, certPrivKey) + if err != nil { + return + } + + certPEM := pem.EncodeToMemory(&pem.Block{ + Type: "CERTIFICATE", + Bytes: certBytes, + }) + + err = os.WriteFile(System.File.ServerCertPrivKey, certPrivKeyPEM, 0644) + if err != nil { + return + } + + err = os.WriteFile(System.File.ServerCert, certPEM, 0644) + if err != nil { + return + } + + return +} diff --git a/src/compression.go b/src/compression.go index ba76626..67fbc89 100644 --- a/src/compression.go +++ b/src/compression.go @@ -86,6 +86,7 @@ func extractZIP(archive, target string) (err error) { if err != nil { return err } + defer reader.Close() if err := os.MkdirAll(target, 0755); err != nil { return err @@ -127,7 +128,7 @@ func extractGZIP(gzipBody []byte, fileSource string) (body []byte, err error) { var r io.Reader r, err = gzip.NewReader(b) if err != nil { - // Keine gzip Datei + // Not a gzip file body = gzipBody err = nil return diff --git a/src/config.go b/src/config.go index 3584168..1f3ab1b 100644 --- a/src/config.go +++ b/src/config.go @@ -6,38 +6,43 @@ import ( "runtime" "strings" "sync" + + "github.com/avfs/avfs" ) -// System : Beinhaltet alle Systeminformationen +// System : Contains all System Information var System SystemStruct -// WebScreenLog : Logs werden im RAM gespeichert und für das Webinterface bereitgestellt +// WebScreenLog : Logs are saved in RAM and made available for the Web interface var WebScreenLog WebScreenLogStruct -// Settings : Inhalt der settings.json +// Settings : Content of settings.json var Settings SettingsStruct -// Data : Alle Daten werden hier abgelegt. (Lineup, XMLTV) +// Data : All data is stored here. (Lineup, XMLTV) var Data DataStruct -// SystemFiles : Alle Systemdateien +// SystemFiles : All System Files var SystemFiles = []string{"authentication.json", "pms.json", "settings.json", "xepg.json", "urls.json"} -// BufferInformation : Informationen über den Buffer (aktive Streams, maximale Streams) +// BufferInformation : Information about the Buffer (active Streams, maximum Streams) var BufferInformation sync.Map -// BufferClients : Anzahl der Clients die einen Stream über den Buffer abspielen +// BufferClients : Number of Clients playing a Stream over the Buffer var BufferClients sync.Map +// bufferVFS : Filesystem to use for the Buffer +var bufferVFS avfs.VFS + // Lock : Lock Map var Lock = sync.RWMutex{} -// Init : Systeminitialisierung +// Init : System Initialization func Init() (err error) { var debug string - // System Einstellungen + // System Settings System.AppName = strings.ToLower(System.Name) System.ARCH = runtime.GOARCH System.OS = runtime.GOOS @@ -47,25 +52,21 @@ func Init() (err error) { System.ServerProtocol.WEB = "http" System.ServerProtocol.XML = "http" System.PlexChannelLimit = 480 - System.UnfilteredChannelLimit = 480 System.Compatibility = "1.4.4" - // FFmpeg Default Einstellungen - System.FFmpeg.DefaultOptions = "-hide_banner -loglevel error -i [URL] -c copy -f mpegts pipe:1" + // FFmpeg Default Settings + System.FFmpeg.DefaultOptions = "-hide_banner -err_detect ignore_err -reconnect 1 -reconnect_at_eof 1 -reconnect_streamed 1 -reconnect_delay_max 20 -loglevel error -i [URL] -c copy -f mpegts pipe:1" System.VLC.DefaultOptions = "-I dummy [URL] --sout #std{mux=ts,access=file,dst=-}" - // Default Logeinträge, wird später von denen aus der settings.json überschrieben. Muss gemacht werden, damit die ersten Einträge auch im Log (webUI aangezeigt werden) + // Default Log Entries, which will later be overwritten by those from settings.json. Needed so that the first entries are also displayed in the Log (webUI are displayed) Settings.LogEntriesRAM = 500 - // Variablen für den Update Prozess + // Variables for the Update Process //System.Update.Git = "https://github.com/xteve-project/xTeVe-Downloads/blob" System.Update.Git = fmt.Sprintf("https://github.com/%s/%s/blob", System.GitHub.User, System.GitHub.Repo) System.Update.Name = "xteve_2" - // Ordnerpfade festlegen - var tempFolder = os.TempDir() + string(os.PathSeparator) + System.AppName + string(os.PathSeparator) - tempFolder = getPlatformPath(strings.Replace(tempFolder, "//", "/", -1)) - + // Define folder paths if len(System.Folder.Config) == 0 { System.Folder.Config = GetUserHomeDirectory() + string(os.PathSeparator) + "." + System.AppName + string(os.PathSeparator) } else { @@ -77,14 +78,15 @@ func Init() (err error) { System.Folder.Backup = System.Folder.Config + "backup" + string(os.PathSeparator) System.Folder.Data = System.Folder.Config + "data" + string(os.PathSeparator) System.Folder.Cache = System.Folder.Config + "cache" + string(os.PathSeparator) + System.Folder.Certificates = System.Folder.Config + "certificates" + string(os.PathSeparator) System.Folder.ImagesCache = System.Folder.Cache + "images" + string(os.PathSeparator) System.Folder.ImagesUpload = System.Folder.Data + "images" + string(os.PathSeparator) - System.Folder.Temp = tempFolder + System.Folder.Temp = getDefaultTempDir() // Dev Info showDevInfo() - // System Ordner erstellen + // Create System Folder err = createSystemFolders() if err != nil { ShowError(err, 1070) @@ -92,10 +94,12 @@ func Init() (err error) { } if len(System.Flag.Restore) > 0 { - // Einstellungen werden über CLI wiederhergestellt. Weitere Initialisierung ist nicht notwendig. + // Settings are restored via CLI. No further Initialization is necessary. return } + System.File.ServerCert = getPlatformFile(fmt.Sprintf("%sxteve.crt", System.Folder.Certificates)) + System.File.ServerCertPrivKey = getPlatformFile(fmt.Sprintf("%sxteve.key", System.Folder.Certificates)) System.File.XML = getPlatformFile(fmt.Sprintf("%s%s.xml", System.Folder.Data, System.AppName)) System.File.M3U = getPlatformFile(fmt.Sprintf("%s%s.m3u", System.Folder.Data, System.AppName)) @@ -106,18 +110,13 @@ func Init() (err error) { return } - err = resolveHostIP() - if err != nil { - ShowError(err, 1002) - } - - // Menü für das Webinterface + // Menu for the Web interface System.WEB.Menu = []string{"playlist", "filter", "xmltv", "mapping", "users", "settings", "log", "logout"} fmt.Println("For help run: " + getPlatformFile(os.Args[0]) + " -h") fmt.Println() - // Überprüfen ob xTeVe als root läuft + // Check whether xTeVe is running as root if os.Geteuid() == 0 { showWarning(2110) } @@ -129,24 +128,22 @@ func Init() (err error) { showInfo(fmt.Sprintf("Version:%s Build: %s", System.Version, System.Build)) showInfo(fmt.Sprintf("Database Version:%s", System.DBVersion)) - showInfo(fmt.Sprintf("System IP Addresses:IPv4: %d | IPv6: %d", len(System.IPAddressesV4), len(System.IPAddressesV6))) - showInfo("Hostname:" + System.Hostname) showInfo(fmt.Sprintf("System Folder:%s", getPlatformPath(System.Folder.Config))) - // Systemdateien erstellen (Falls nicht vorhanden) + // Create System Files (If not available) err = createSystemFiles() if err != nil { ShowError(err, 1071) return } - // Bedingte Update Änderungen durchführen + // Perform conditional Update Changes err = conditionalUpdateChanges() if err != nil { return } - // Einstellungen laden (settings.json) + // Load Settings (settings.json) showInfo(fmt.Sprintf("Load Settings:%s", System.File.Settings)) _, err = loadSettings() @@ -155,14 +152,22 @@ func Init() (err error) { return } - // Berechtigung aller Ordner überprüfen + err = resolveHostIP() + if err != nil { + ShowError(err, 1002) + } + + showInfo(fmt.Sprintf("System IP Addresses:IPv4: %d | IPv6: %d", len(System.IPAddressesV4), len(System.IPAddressesV6))) + showInfo("Hostname:" + System.Hostname) + + // Check the permissions on all Folders err = checkFilePermission(System.Folder.Config) if err == nil { - err = checkFilePermission(System.Folder.Temp) + checkFilePermission(System.Folder.Temp) } - // Separaten tmp Ordner für jede Instanz - //System.Folder.Temp = System.Folder.Temp + Settings.UUID + string(os.PathSeparator) + // Separate tmp Folder for each Instance + // System.Folder.Temp = System.Folder.Temp + Settings.UUID + string(os.PathSeparator) showInfo(fmt.Sprintf("Temporary Folder:%s", getPlatformPath(System.Folder.Temp))) err = checkFolder(System.Folder.Temp) @@ -175,10 +180,10 @@ func Init() (err error) { return } - // Branch festlegen + // Set Branch System.Branch = Settings.Branch - if System.Dev == true { + if System.Dev { System.Branch = "Development" } @@ -189,13 +194,17 @@ func Init() (err error) { showInfo(fmt.Sprintf("GitHub:https://github.com/%s", System.GitHub.User)) showInfo(fmt.Sprintf("Git Branch:%s [%s]", System.Branch, System.GitHub.User)) - // Domainnamen setzten - setGlobalDomain(fmt.Sprintf("%s:%s", System.IPAddress, Settings.Port)) + if len(strings.TrimSpace(Settings.HostName)) > 0 { + Settings.HostIP = strings.TrimSpace(Settings.HostName) + } - System.URLBase = fmt.Sprintf("%s://%s:%s", System.ServerProtocol.WEB, System.IPAddress, Settings.Port) + // Set Domain Names + setGlobalDomain(fmt.Sprintf("%s:%s", Settings.HostIP, Settings.Port)) - // HTML Dateien erstellen, mit dev == true werden die lokalen HTML Dateien verwendet - if System.Dev == true { + System.URLBase = fmt.Sprintf("%s://%s:%s", System.ServerProtocol.WEB, Settings.HostIP, Settings.Port) + + // Create HTML Files, with dev the local HTML Files are used + if System.Dev { HTMLInit("webUI", "src", "html"+string(os.PathSeparator), "src"+string(os.PathSeparator)+"webUI.go") err = BuildGoFile() @@ -205,19 +214,19 @@ func Init() (err error) { } - // DLNA Server starten + // Start the DLNA Server err = SSDP() if err != nil { return } - // HTML Datein laden + // Load HTML Files loadHTMLMap() return } -// StartSystem : System wird gestartet +// StartSystem : System is starting up func StartSystem(updateProviderFiles bool) (err error) { setDeviceID() @@ -226,15 +235,14 @@ func StartSystem(updateProviderFiles bool) (err error) { return } - // Systeminformationen in der Konsole ausgeben + // Output System Information in the Console showInfo(fmt.Sprintf("UUID:%s", Settings.UUID)) showInfo(fmt.Sprintf("Tuner (Plex / Emby):%d", Settings.Tuner)) showInfo(fmt.Sprintf("EPG Source:%s", Settings.EpgSource)) showInfo(fmt.Sprintf("Plex Channel Limit:%d", System.PlexChannelLimit)) - showInfo(fmt.Sprintf("Unfiltered Chan. Limit:%d", System.UnfilteredChannelLimit)) - // Providerdaten aktualisieren - if len(Settings.Files.M3U) > 0 && Settings.FilesUpdate == true || updateProviderFiles == true { + // Update Provider Data + if len(Settings.Files.M3U) > 0 && Settings.FilesUpdate || updateProviderFiles { err = xTeVeAutoBackup() if err != nil { @@ -260,3 +268,16 @@ func StartSystem(updateProviderFiles bool) (err error) { return } + +// reinitialize : Initialize and start up the system, updating provider files +func reinitialize() { + err := Init() + if err != nil { + ShowError(err, 0) + } + + err = StartSystem(true) + if err != nil { + ShowError(err, 0) + } +} diff --git a/src/data.go b/src/data.go index 3ea9bdc..77db7ed 100644 --- a/src/data.go +++ b/src/data.go @@ -15,7 +15,7 @@ import ( "xteve/src/internal/imgcache" ) -// Einstellungen ändern (WebUI) +// Change Settings (WebUI) func updateServerSettings(request RequestStruct) (settings SettingsStruct, err error) { var oldSettings = jsonToMap(mapToJSON(Settings)) @@ -25,8 +25,6 @@ func updateServerSettings(request RequestStruct) (settings SettingsStruct, err e var createXEPGFiles = false var debug string - // -vvv [URL] --sout '#transcode{vcodec=mp4v, acodec=mpga} :standard{access=http, mux=ogg}' - for key, value := range newSettings { if _, ok := oldSettings[key]; ok { @@ -40,7 +38,7 @@ func updateServerSettings(request RequestStruct) (settings SettingsStruct, err e reloadData = true case "update": - // Leerzeichen aus den Werten entfernen und Formatierung der Uhrzeit überprüfen (0000 - 2359) + // Remove spaces from the Values and check the formatting of the Time (0000 - 2359) var newUpdateTimes = make([]string, 0) for _, v := range value.([]interface{}) { @@ -57,9 +55,9 @@ func updateServerSettings(request RequestStruct) (settings SettingsStruct, err e } - if len(newUpdateTimes) == 0 { - //newUpdateTimes = append(newUpdateTimes, "0000") - } + // if len(newUpdateTimes) == 0 { + // //newUpdateTimes = append(newUpdateTimes, "0000") + // } value = newUpdateTimes @@ -86,20 +84,7 @@ func updateServerSettings(request RequestStruct) (settings SettingsStruct, err e } case "temp.path": - value = strings.TrimRight(value.(string), string(os.PathSeparator)) + string(os.PathSeparator) - err = checkFolder(value.(string)) - if err == nil { - - err = checkFilePermission(value.(string)) - if err != nil { - return - } - - } - - if err != nil { - return - } + value = getValidTempDir(value.(string)) case "ffmpeg.path", "vlc.path": var path = value.(string) @@ -115,6 +100,18 @@ func updateServerSettings(request RequestStruct) (settings SettingsStruct, err e case "scheme.m3u", "scheme.xml": createXEPGFiles = true + case "defaultMissingEPG": + // If DefaultMissingEPG was set, rebuild DVR and XEPG database + if newSettings["defaultMissingEPG"] != "-" && oldSettings["defaultMissingEPG"] == "-" { + reloadData = true + } + + case "enableMappedChannels": + // If EnableMappedChannels was turned on, rebuild DVR and XEPG database + if newSettings["enableMappedChannels"] == true && oldSettings["enableMappedChannels"] == false { + reloadData = true + } + } oldSettings[key] = value @@ -143,13 +140,13 @@ func updateServerSettings(request RequestStruct) (settings SettingsStruct, err e } - // Einstellungen aktualisieren + // Update Settings err = json.Unmarshal([]byte(mapToJSON(oldSettings)), &Settings) if err != nil { return } - if Settings.AuthenticationWEB == false { + if !Settings.AuthenticationWEB { Settings.AuthenticationAPI = false Settings.AuthenticationM3U = false @@ -159,7 +156,7 @@ func updateServerSettings(request RequestStruct) (settings SettingsStruct, err e } - // Buffer Einstellungen überprüfen + // Check Buffer Settings if len(Settings.FFmpegOptions) == 0 { Settings.FFmpegOptions = System.FFmpeg.DefaultOptions } @@ -191,7 +188,7 @@ func updateServerSettings(request RequestStruct) (settings SettingsStruct, err e settings = Settings - if reloadData == true { + if reloadData { err = buildDatabaseDVR() if err != nil { @@ -202,7 +199,7 @@ func updateServerSettings(request RequestStruct) (settings SettingsStruct, err e } - if cacheImages == true { + if cacheImages { if Settings.EpgSource == "XEPG" && System.ImageCachingInProgress == 0 { @@ -241,7 +238,7 @@ func updateServerSettings(request RequestStruct) (settings SettingsStruct, err e } - if createXEPGFiles == true { + if createXEPGFiles { go func() { createXMLTVFile() @@ -255,7 +252,7 @@ func updateServerSettings(request RequestStruct) (settings SettingsStruct, err e return } -// Providerdaten speichern (WebUI) +// Save Provider Data (WebUI) func saveFiles(request RequestStruct, fileType string) (err error) { var filesMap = make(map[string]interface{}) @@ -288,14 +285,14 @@ func saveFiles(request RequestStruct, fileType string) (err error) { if dataID == "-" { - // Neue Providerdatei + // New Provider File dataID = indicator + randomString(19) data.(map[string]interface{})["new"] = true filesMap[dataID] = data } else { - // Bereits vorhandene Providerdatei + // Existing Provider File for key, value := range data.(map[string]interface{}) { var oldData = filesMap[dataID].(map[string]interface{}) @@ -318,7 +315,7 @@ func saveFiles(request RequestStruct, fileType string) (err error) { } - // Neue Providerdatei + // New Provider File if _, ok := data.(map[string]interface{})["new"]; ok { reloadData = true @@ -344,7 +341,7 @@ func saveFiles(request RequestStruct, fileType string) (err error) { return } - if reloadData == true { + if reloadData { err = buildDatabaseDVR() if err != nil { @@ -362,7 +359,7 @@ func saveFiles(request RequestStruct, fileType string) (err error) { return } -// Providerdaten manuell aktualisieren (WebUI) +// Update Provider Data manually (WebUI) func updateFile(request RequestStruct, fileType string) (err error) { var updateData = make(map[string]interface{}) @@ -392,7 +389,7 @@ func updateFile(request RequestStruct, fileType string) (err error) { return } -// Providerdaten löschen (WebUI) +// Delete Provider Data (WebUI) func deleteLocalProviderFiles(dataID, fileType string) { var removeData = make(map[string]interface{}) @@ -418,10 +415,9 @@ func deleteLocalProviderFiles(dataID, fileType string) { os.RemoveAll(System.Folder.Data + dataID + fileExtension) } - return } -// Filtereinstellungen speichern (WebUI) +// Save Filter Settings (WebUI) func saveFilter(request RequestStruct) (settings SettingsStruct, err error) { var filterMap = make(map[int64]interface{}) @@ -431,6 +427,8 @@ func saveFilter(request RequestStruct) (settings SettingsStruct, err error) { defaultFilter.Active = true defaultFilter.CaseSensitive = false + defaultFilter.PreserveMapping = true + defaultFilter.StartingChannel = strconv.FormatFloat(Settings.MappingFirstChannel, 'f', -1, 64) // 1000 filterMap = Settings.Filter newData = request.Filter @@ -450,17 +448,17 @@ func saveFilter(request RequestStruct) (settings SettingsStruct, err error) { if dataID == -1 { - // Neuer Filter + // New Filter newFilter = true dataID = createNewID() filterMap[dataID] = jsonToMap(mapToJSON(defaultFilter)) } - // Filter aktualisieren / löschen + // Update / delete filters for key, value := range data.(map[string]interface{}) { - // Filter löschen + // Clear Filters if _, ok := data.(map[string]interface{})["delete"]; ok { delete(filterMap, dataID) break @@ -471,7 +469,7 @@ func saveFilter(request RequestStruct) (settings SettingsStruct, err error) { if len(filter) == 0 { err = errors.New(getErrMsg(1014)) - if newFilter == true { + if newFilter { delete(filterMap, dataID) } @@ -505,7 +503,7 @@ func saveFilter(request RequestStruct) (settings SettingsStruct, err error) { return } -// XEPG Mapping speichern +// Save XEPG Mapping func saveXEpgMapping(request RequestStruct) (err error) { var tmp = Data.XEPG @@ -536,10 +534,10 @@ func saveXEpgMapping(request RequestStruct) (err error) { } else { - // Wenn während des erstellen der Datanbank das Mapping erneut gespeichert wird, wird die Datenbank erst später erneut aktualisiert. + // If the Mapping is saved again while the Database is being created, the Database will not be updated again until later. go func() { - if System.BackgroundProcess == true { + if System.BackgroundProcess { return } @@ -557,7 +555,7 @@ func saveXEpgMapping(request RequestStruct) (err error) { cleanupXEPG() System.ScanInProgress = 0 buildXEPG(false) - showInfo("XEPG:" + fmt.Sprintf("Ready to use")) + showInfo("XEPG:" + "Ready to use") System.BackgroundProcess = false @@ -568,7 +566,7 @@ func saveXEpgMapping(request RequestStruct) (err error) { return } -// Benutzerdaten speichern (WebUI) +// Save User Data (WebUI) func saveUserData(request RequestStruct) (err error) { var userData = request.UserData @@ -598,7 +596,7 @@ func saveUserData(request RequestStruct) (err error) { return } - if request.DeleteUser == true { + if request.DeleteUser { err = authentication.RemoveUser(userID) return } @@ -624,7 +622,7 @@ func saveUserData(request RequestStruct) (err error) { return } -// Neuen Benutzer anlegen (WebUI) +// Create New User (WebUI) func saveNewUser(request RequestStruct) (err error) { var data = request.UserData @@ -745,7 +743,7 @@ func saveWizard(request RequestStruct) (nextStep int, err error) { return } -// Filterregeln erstellen +// Create Filter Rules func createFilterRules() (err error) { Data.Filter = nil @@ -781,6 +779,8 @@ func createFilterRules() (err error) { } dataFilter.CaseSensitive = filter.CaseSensitive + dataFilter.PreserveMapping = filter.PreserveMapping + dataFilter.StartingChannel = filter.StartingChannel dataFilter.Rule = fmt.Sprintf("%s%s%s", filter.Filter, include, exclude) dataFilter.Type = filter.Type @@ -792,14 +792,14 @@ func createFilterRules() (err error) { return } -// Datenbank für das DVR System erstellen +// Create a Database for the DVR System func buildDatabaseDVR() (err error) { System.ScanInProgress = 1 - Data.Streams.All = make([]interface{}, 0, System.UnfilteredChannelLimit) - Data.Streams.Active = make([]interface{}, 0, System.UnfilteredChannelLimit) - Data.Streams.Inactive = make([]interface{}, 0, System.UnfilteredChannelLimit) + Data.Streams.All = make([]interface{}, 0) + Data.Streams.Active = make([]interface{}, 0) + Data.Streams.Inactive = make([]interface{}, 0) Data.Playlist.M3U.Groups.Text = []string{} Data.Playlist.M3U.Groups.Value = []string{} Data.StreamPreviewUI.Active = []string{} @@ -807,6 +807,7 @@ func buildDatabaseDVR() (err error) { var availableFileTypes = []string{"m3u", "hdhr"} + var urlValuesMap = make(map[string]string) var tmpGroupsM3U = make(map[string]int64) err = createFilterRules() @@ -844,7 +845,7 @@ func buildDatabaseDVR() (err error) { playlistFile = append(playlistFile[:n], playlistFile[n+1:]...) } - // Streams analysieren + // Analyze Streams for _, stream := range channels { var s = stream.(map[string]string) @@ -852,7 +853,16 @@ func buildDatabaseDVR() (err error) { s["_file.m3u.name"] = playlistName s["_file.m3u.id"] = id - // Kompatibilität berechnen + if Settings.DisallowURLDuplicates { + if _, haveURL := urlValuesMap[s["url"]]; haveURL { + showInfo("Streams:" + fmt.Sprintf("Found duplicated URL %v, ignoring the channel %v", s["url"], s["name"])) + continue + } else { + urlValuesMap[s["url"]] = s["_values"] + } + } + + // Calculate Compatibility for _, key := range keys { switch key { @@ -867,12 +877,12 @@ func buildDatabaseDVR() (err error) { if value, ok := s[key]; ok { if len(value) > 0 { - if _, ok := tmpGroupsM3U[value]; ok { - tmpGroupsM3U[value]++ - } else { - tmpGroupsM3U[value] = 1 - } - + // if _, ok := tmpGroupsM3U[value]; ok { + // tmpGroupsM3U[value]++ + // } else { + // tmpGroupsM3U[value] = 1 + // } + tmpGroupsM3U[value]++ groupTitle++ } } @@ -890,7 +900,7 @@ func buildDatabaseDVR() (err error) { Data.Streams.All = append(Data.Streams.All, stream) - // Neuer Filter ab Version 1.3.0 + // New Filter from Version 1.3.0 var preview string var status = filterThisStream(stream) @@ -947,7 +957,7 @@ func buildDatabaseDVR() (err error) { for group, count := range tmpGroupsM3U { var text = fmt.Sprintf("%s (%d)", group, count) - var value = fmt.Sprintf("%s", group) + var value = group Data.Playlist.M3U.Groups.Text = append(Data.Playlist.M3U.Groups.Text, text) Data.Playlist.M3U.Groups.Value = append(Data.Playlist.M3U.Groups.Value, value) } @@ -955,7 +965,7 @@ func buildDatabaseDVR() (err error) { sort.Strings(Data.Playlist.M3U.Groups.Text) sort.Strings(Data.Playlist.M3U.Groups.Value) - if len(Data.Streams.Active) == 0 && len(Data.Streams.All) <= System.UnfilteredChannelLimit && len(Settings.Filter) == 0 { + if len(Data.Streams.Active) == 0 && len(Settings.Filter) == 0 { Data.Streams.Active = Data.Streams.All Data.Streams.Inactive = make([]interface{}, 0) @@ -968,10 +978,6 @@ func buildDatabaseDVR() (err error) { showWarning(2000) } - if len(Settings.Filter) == 0 && len(Data.Streams.All) > System.UnfilteredChannelLimit { - showWarning(2001) - } - System.ScanInProgress = 0 showInfo(fmt.Sprintf("All streams:%d", len(Data.Streams.All))) showInfo(fmt.Sprintf("Active streams:%d", len(Data.Streams.Active))) @@ -983,7 +989,7 @@ func buildDatabaseDVR() (err error) { return } -// Speicherort aller lokalen Providerdateien laden, immer für eine Dateityp (M3U, XMLTV usw.) +// Load Storage Location of all local Provider Files, always for one File Type (M3U, XMLTV etc.) func getLocalProviderFiles(fileType string) (localFiles []string) { var fileExtension string @@ -1012,7 +1018,7 @@ func getLocalProviderFiles(fileType string) (localFiles []string) { return } -// Providerparameter anhand von dem Key ausgeben +// Output Provider Parameters based on the Key func getProviderParameter(id, fileType, key string) (s string) { var dataMap = make(map[string]interface{}) @@ -1043,7 +1049,7 @@ func getProviderParameter(id, fileType, key string) (s string) { return } -// Provider Statistiken Kompatibilität aktualisieren +// Update Provider Statistics Compatibility func setProviderCompatibility(id, fileType string, compatibility map[string]int) { var dataMap = make(map[string]interface{}) diff --git a/src/hdhr.go b/src/hdhr.go index 830401a..490486d 100644 --- a/src/hdhr.go +++ b/src/hdhr.go @@ -5,6 +5,10 @@ import ( "encoding/json" "encoding/xml" "fmt" + "sort" + "strconv" + + "github.com/samber/lo" ) func makeInteraceFromHDHR(content []byte, playlistName, id string) (channels []interface{}, err error) { @@ -154,7 +158,7 @@ func getLineup() (jsonContent []byte, err error) { return } - if xepgChannel.XActive == true { + if xepgChannel.XActive { var stream LineupStream stream.GuideName = xepgChannel.XName stream.GuideNumber = xepgChannel.XChannelID @@ -169,9 +173,17 @@ func getLineup() (jsonContent []byte, err error) { } } - } + // Sort the lineup + // Have to use type assertions (https://golang.org/ref/spec#Type_assertions) to cast generic interface{} into LineupStream + sort.Slice(lineup, func(i, j int) bool { + var chanA, chanB float64 + chanA, _ = strconv.ParseFloat(lineup[i].(LineupStream).GuideNumber, 64) + chanB, _ = strconv.ParseFloat(lineup[j].(LineupStream).GuideNumber, 64) + return chanA < chanB + }) + jsonContent, err = json.MarshalIndent(lineup, "", " ") Data.Cache.PMS = nil @@ -212,7 +224,7 @@ func getGuideNumberPMS(channelName string) (pmsID string, err error) { ids = append(ids, v) } - if indexOfString(id, ids) != -1 { + if lo.IndexOf(ids, id) != -1 { i++ goto newID } diff --git a/src/html-build.go b/src/html-build.go index 2b7ba10..1c54172 100644 --- a/src/html-build.go +++ b/src/html-build.go @@ -9,6 +9,7 @@ import ( "os" "path/filepath" "runtime" + "sort" ) var htmlFolder string @@ -18,10 +19,10 @@ var packageName string var blankMap = make(map[string]interface{}) -// HTMLInit : Dateipfade festlegen -// mapName = Name der zu erstellenden map -// htmlFolder: Ordner der HTML Dateien -// packageName: Name des package +// HTMLInit : Define file paths +// mapName = Name of the map to be created +// htmlFolder: HTML Files Folder +// packageName: Name of the package func HTMLInit(name, pkg, folder, file string) { htmlFolder = folder @@ -31,7 +32,7 @@ func HTMLInit(name, pkg, folder, file string) { } -// BuildGoFile : Erstellt das GO Dokument +// BuildGoFile : Creates the GO Document func BuildGoFile() error { var err = checkHTMLFile(htmlFolder) @@ -70,7 +71,14 @@ func createMapFromFiles(folder string) string { var content string - for key := range blankMap { + // Sort map keys before writing to file to prevent git mark webUI.go as modified when no real changes has been made + keys := make([]string, 0, len(blankMap)) + for k := range blankMap { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, key := range keys { var newKey = key content += ` ` + mapName + `["` + newKey + `"` + `] = "` + blankMap[key].(string) + `"` + "\n" } @@ -80,9 +88,9 @@ func createMapFromFiles(folder string) string { func readFilesToMap(path string, info os.FileInfo, err error) error { - if info.IsDir() == false { + if !info.IsDir() { var base64Str = fileToBase64(getLocalPath(path)) - blankMap[path] = base64Str + blankMap[filepath.ToSlash(path)] = base64Str } return nil @@ -110,7 +118,7 @@ func fileToBase64(file string) string { func getLocalPath(filename string) string { path, file := filepath.Split(filename) - var newPath = filepath.Dir(path) + var newPath = filepath.ToSlash(filepath.Dir(path)) var newFileName = newPath + "/" + file diff --git a/src/images.go b/src/images.go index 04dd256..9e891af 100644 --- a/src/images.go +++ b/src/images.go @@ -1,30 +1,30 @@ package src import ( - b64 "encoding/base64" - "fmt" - "strings" + b64 "encoding/base64" + "fmt" + "strings" ) func uploadLogo(input, filename string) (logoURL string, err error) { - b64data := input[strings.IndexByte(input, ',')+1:] + b64data := input[strings.IndexByte(input, ',')+1:] - // BAse64 in bytes umwandeln un speichern - sDec, err := b64.StdEncoding.DecodeString(b64data) - if err != nil { - return - } + // Convert Base64 into bytes and save + sDec, err := b64.StdEncoding.DecodeString(b64data) + if err != nil { + return + } - var file = fmt.Sprintf("%s%s", System.Folder.ImagesUpload, filename) + var file = fmt.Sprintf("%s%s", System.Folder.ImagesUpload, filename) - err = writeByteToFile(file, sDec) - if err != nil { - return - } + err = writeByteToFile(file, sDec) + if err != nil { + return + } - logoURL = fmt.Sprintf("%s://%s/data_images/%s", System.ServerProtocol.XML, System.Domain, filename) + logoURL = fmt.Sprintf("%s://%s/data_images/%s", System.ServerProtocol.XML, System.Domain, filename) - return + return } diff --git a/src/info.go b/src/info.go index 26c5605..e837e1d 100644 --- a/src/info.go +++ b/src/info.go @@ -1,100 +1,100 @@ package src import ( - "fmt" - "strings" + "fmt" + "strings" ) -// ShowSystemInfo : Systeminformationen anzeigen -func ShowSystemInfo() { +// ShowSystemVersion basic version info +func ShowSystemVersion() { + fmt.Println(fmt.Sprintf("%s.%s", System.Version, System.Build)) +} - fmt.Print("Creating the information takes a moment...") - err := buildDatabaseDVR() - if err != nil { - ShowError(err, 0) - return - } +// ShowSystemInfo : View System Information +func ShowSystemInfo() { - buildXEPG(false) + fmt.Print("Creating the information takes a moment...") + err := buildDatabaseDVR() + if err != nil { + ShowError(err, 0) + return + } - fmt.Println("OK") - println() + buildXEPG(false) - fmt.Println(fmt.Sprintf("Version: %s %s.%s", System.Name, System.Version, System.Build)) - fmt.Println(fmt.Sprintf("Branch: %s", System.Branch)) - fmt.Println(fmt.Sprintf("GitHub: %s/%s | Git update = %t", System.GitHub.User, System.GitHub.Repo, System.GitHub.Update)) - fmt.Println(fmt.Sprintf("Folder (config): %s", System.Folder.Config)) + fmt.Println("OK") + println() - fmt.Println(fmt.Sprintf("Streams: %d / %d", len(Data.Streams.Active), len(Data.Streams.All))) - fmt.Println(fmt.Sprintf("Filter: %d", len(Data.Filter))) - fmt.Println(fmt.Sprintf("XEPG Chanels: %d", int(Data.XEPG.XEPGCount))) + fmt.Printf("Version: %s %s.%s\n", System.Name, System.Version, System.Build) + fmt.Printf("Branch: %s\n", System.Branch) + fmt.Printf("GitHub: %s/%s | Git update = %t\n", System.GitHub.User, System.GitHub.Repo, System.GitHub.Update) + fmt.Printf("Folder (config): %s\n", System.Folder.Config) - println() - fmt.Println(fmt.Sprintf("IPv4 Addresses:")) + fmt.Printf("Streams: %d / %d\n", len(Data.Streams.Active), len(Data.Streams.All)) + fmt.Printf("Filter: %d\n", len(Data.Filter)) + fmt.Printf("XEPG Chanels: %d\n", int(Data.XEPG.XEPGCount)) - for i, ipv4 := range System.IPAddressesV4 { + println() + fmt.Println("IPv4 Addresses:") - switch count := i; { + for i, ipv4 := range System.IPAddressesV4 { - case count < 10: - fmt.Println(fmt.Sprintf(" %d. %s", count, ipv4)) - break - case count < 100: - fmt.Println(fmt.Sprintf(" %d. %s", count, ipv4)) - break + switch count := i; { - } + case count < 10: + fmt.Printf(" %d. %s\n", count, ipv4) + case count < 100: + fmt.Printf(" %d. %s\n", count, ipv4) - } + } - println() - fmt.Println(fmt.Sprintf("IPv6 Addresses:")) + } - for i, ipv4 := range System.IPAddressesV6 { + println() + fmt.Println("IPv6 Addresses:") - switch count := i; { + for i, ipv4 := range System.IPAddressesV6 { - case count < 10: - fmt.Println(fmt.Sprintf(" %d. %s", count, ipv4)) - break - case count < 100: - fmt.Println(fmt.Sprintf(" %d. %s", count, ipv4)) - break + switch count := i; { - } + case count < 10: + fmt.Printf(" %d. %s\n", count, ipv4) + case count < 100: + fmt.Printf(" %d. %s\n", count, ipv4) + } - } + } - println("---") + println("---") - fmt.Println("Settings [General]") - fmt.Println(fmt.Sprintf("xTeVe Update: %t", Settings.XteveAutoUpdate)) - fmt.Println(fmt.Sprintf("UUID: %s", Settings.UUID)) - fmt.Println(fmt.Sprintf("Tuner (Plex / Emby): %d", Settings.Tuner)) - fmt.Println(fmt.Sprintf("EPG Source: %s", Settings.EpgSource)) + fmt.Println("Settings [General]") + fmt.Printf("xTeVe Update: %t\n", Settings.XteveAutoUpdate) + fmt.Printf("UUID: %s\n", Settings.UUID) + fmt.Printf("Tuner (Plex / Emby): %d\n", Settings.Tuner) + fmt.Printf("EPG Source: %s\n", Settings.EpgSource) - println("---") + println("---") - fmt.Println("Settings [Files]") - fmt.Println(fmt.Sprintf("Schedule: %s", strings.Join(Settings.Update, ","))) - fmt.Println(fmt.Sprintf("Files Update: %t", Settings.FilesUpdate)) - fmt.Println(fmt.Sprintf("Folder (tmp): %s", Settings.TempPath)) - fmt.Println(fmt.Sprintf("Image Chaching: %t", Settings.CacheImages)) - fmt.Println(fmt.Sprintf("Replace EPG Image: %t", Settings.XepgReplaceMissingImages)) + fmt.Println("Settings [Files]") + fmt.Printf("Schedule: %s\n", strings.Join(Settings.Update, ",")) + fmt.Printf("Files Update: %t\n", Settings.FilesUpdate) + fmt.Printf("Folder (tmp): %s\n", Settings.TempPath) + fmt.Printf("Image Chaching: %t\n", Settings.CacheImages) + fmt.Printf("Replace EPG Image: %t\n", Settings.XepgReplaceMissingImages) - println("---") + println("---") - fmt.Println("Settings [Streaming]") - fmt.Println(fmt.Sprintf("Buffer: %s", Settings.Buffer)) - fmt.Println(fmt.Sprintf("UDPxy: %s", Settings.UDPxy)) - fmt.Println(fmt.Sprintf("Buffer Size: %d KB", Settings.BufferSize)) - fmt.Println(fmt.Sprintf("Timeout: %d ms", int(Settings.BufferTimeout))) - fmt.Println(fmt.Sprintf("User Agent: %s", Settings.UserAgent)) + fmt.Println("Settings [Streaming]") + fmt.Printf("Buffer: %s\n", Settings.Buffer) + fmt.Printf("UDPxy: %s\n", Settings.UDPxy) + fmt.Printf("Buffer Size: %d KB\n", Settings.BufferSize) + fmt.Printf("Timeout: %d ms\n", int(Settings.BufferTimeout)) + fmt.Printf("User Agent: %s\n", Settings.UserAgent) - println("---") + println("---") - fmt.Println("Settings [Backup]") - fmt.Println(fmt.Sprintf("Folder (backup): %s", Settings.BackupPath)) - fmt.Println(fmt.Sprintf("Backup Keep: %d", Settings.BackupKeep)) + fmt.Println("Settings [Backup]") + fmt.Printf("Folder (backup): %s\n", Settings.BackupPath) + fmt.Printf("Backup Keep: %d\n", Settings.BackupKeep) } diff --git a/src/internal/authentication/authentication.go b/src/internal/authentication/authentication.go index 0f6bae4..4aa68cb 100755 --- a/src/internal/authentication/authentication.go +++ b/src/internal/authentication/authentication.go @@ -1,21 +1,21 @@ package authentication import ( - "encoding/json" - "errors" - "io/ioutil" - "net/http" - "os" - "path/filepath" - - "crypto/hmac" - "crypto/rand" - "crypto/sha256" - "encoding/base64" - - "time" - //"fmt" - //"log" + "encoding/json" + "errors" + "io/ioutil" + "net/http" + "os" + "path/filepath" + + "crypto/hmac" + "crypto/rand" + "crypto/sha256" + "encoding/base64" + + "time" + //"fmt" + //"log" ) const tokenLength = 40 @@ -34,12 +34,12 @@ var initAuthentication = false // Cookie : cookie type Cookie struct { - Name string - Value string - Path string - Domain string - Expires time.Time - RawExpires string + Name string + Value string + Path string + Domain string + Expires time.Time + RawExpires string } // Framework examples @@ -128,465 +128,457 @@ func main() { // Init : databasePath = Path to authentication.json func Init(databasePath string, validity int) (err error) { - database = filepath.Dir(databasePath) + string(os.PathSeparator) + databaseFile - - // Check if the database already exists - if _, err = os.Stat(database); os.IsNotExist(err) { - // Create an empty database - var defaults = make(map[string]interface{}) - defaults["dbVersion"] = "1.0" - defaults["hash"] = "sha256" - defaults["users"] = make(map[string]interface{}) - - if saveDatabase(defaults) != nil { - return - } - } - - // Loading the database - err = loadDatabase() - - // Set Token Validity - tokenValidity = validity - initAuthentication = true - return + database = filepath.Dir(databasePath) + string(os.PathSeparator) + databaseFile + + // Check if the database already exists + if _, err = os.Stat(database); os.IsNotExist(err) { + // Create an empty database + var defaults = make(map[string]interface{}) + defaults["dbVersion"] = "1.0" + defaults["hash"] = "sha256" + defaults["users"] = make(map[string]interface{}) + + if saveDatabase(defaults) != nil { + return + } + } + + // Loading the database + err = loadDatabase() + + // Set Token Validity + tokenValidity = validity + initAuthentication = true + return } // CreateDefaultUser = created efault user func CreateDefaultUser(username, password string) (err error) { - err = checkInit() - if err != nil { - return - } + err = checkInit() + if err != nil { + return + } - var users = data["users"].(map[string]interface{}) - // Check if the default user exists - if len(users) > 0 { - err = createError(001) - return - } + var users = data["users"].(map[string]interface{}) + // Check if the default user exists + if len(users) > 0 { + err = createError(001) + return + } - var defaults = defaultsForNewUser(username, password) - users[defaults["_id"].(string)] = defaults - saveDatabase(data) + var defaults = defaultsForNewUser(username, password) + users[defaults["_id"].(string)] = defaults + saveDatabase(data) - return + return } // CreateNewUser : create new user func CreateNewUser(username, password string) (userID string, err error) { - err = checkInit() - if err != nil { - return - } + err = checkInit() + if err != nil { + return + } - var checkIfTheUserAlreadyExists = func(username string, userData map[string]interface{}) (err error) { - var salt = userData["_salt"].(string) - var loginUsername = userData["_username"].(string) + var checkIfTheUserAlreadyExists = func(username string, userData map[string]interface{}) (err error) { + var salt = userData["_salt"].(string) + var loginUsername = userData["_username"].(string) - if SHA256(username, salt) == loginUsername { - err = createError(020) - } + if SHA256(username, salt) == loginUsername { + err = createError(020) + } - return - } + return + } - var users = data["users"].(map[string]interface{}) - for _, userData := range users { - err = checkIfTheUserAlreadyExists(username, userData.(map[string]interface{})) - if err != nil { - return - } - } + var users = data["users"].(map[string]interface{}) + for _, userData := range users { + err = checkIfTheUserAlreadyExists(username, userData.(map[string]interface{})) + if err != nil { + return + } + } - var defaults = defaultsForNewUser(username, password) - userID = defaults["_id"].(string) - users[userID] = defaults + var defaults = defaultsForNewUser(username, password) + userID = defaults["_id"].(string) + users[userID] = defaults - saveDatabase(data) + saveDatabase(data) - return + return } // UserAuthentication : user authentication func UserAuthentication(username, password string) (token string, err error) { - err = checkInit() - if err != nil { - return - } - - var login = func(username, password string, loginData map[string]interface{}) (err error) { - err = createError(010) - - var salt = loginData["_salt"].(string) - var loginUsername = loginData["_username"].(string) - var loginPassword = loginData["_password"].(string) - - if SHA256(username, salt) == loginUsername { - if SHA256(password, salt) == loginPassword { - err = nil - } - } - - return - } - - var users = data["users"].(map[string]interface{}) - for id, loginData := range users { - err = login(username, password, loginData.(map[string]interface{})) - if err == nil { - token = setToken(id, "-") - return - } - } - - return + err = checkInit() + if err != nil { + return + } + + var login = func(username, password string, loginData map[string]interface{}) (err error) { + err = createError(010) + + var salt = loginData["_salt"].(string) + var loginUsername = loginData["_username"].(string) + var loginPassword = loginData["_password"].(string) + + if SHA256(username, salt) == loginUsername { + if SHA256(password, salt) == loginPassword { + err = nil + } + } + + return + } + + var users = data["users"].(map[string]interface{}) + for id, loginData := range users { + err = login(username, password, loginData.(map[string]interface{})) + if err == nil { + token = setToken(id, "-") + return + } + } + + return } // CheckTheValidityOfTheToken : check token func CheckTheValidityOfTheToken(token string) (newToken string, err error) { - err = checkInit() - if err != nil { - return - } + err = checkInit() + if err != nil { + return + } - err = createError(011) + err = createError(011) - if v, ok := tokens[token]; ok { - var expires = v.(map[string]interface{})["expires"].(time.Time) - var userID = v.(map[string]interface{})["id"].(string) + if v, ok := tokens[token]; ok { + var expires = v.(map[string]interface{})["expires"].(time.Time) + var userID = v.(map[string]interface{})["id"].(string) - if expires.Sub(time.Now().Local()) < 0 { - return - } + if expires.Sub(time.Now().Local()) < 0 { + return + } - newToken = setToken(userID, token) + newToken = setToken(userID, token) - err = nil + err = nil - } else { - return - } + } else { + return + } - return + return } // GetUserID : get user ID func GetUserID(token string) (userID string, err error) { - err = checkInit() - if err != nil { - return - } + err = checkInit() + if err != nil { + return + } - err = createError(002) + err = createError(002) - if v, ok := tokens[token]; ok { - var expires = v.(map[string]interface{})["expires"].(time.Time) - userID = v.(map[string]interface{})["id"].(string) + if v, ok := tokens[token]; ok { + var expires = v.(map[string]interface{})["expires"].(time.Time) + userID = v.(map[string]interface{})["id"].(string) - if expires.Sub(time.Now().Local()) < 0 { - return - } + if expires.Sub(time.Now().Local()) < 0 { + return + } - err = nil - } + err = nil + } - return + return } // WriteUserData : save user date func WriteUserData(userID string, userData map[string]interface{}) (err error) { - err = checkInit() - if err != nil { - return - } + err = checkInit() + if err != nil { + return + } - err = createError(030) + err = createError(030) - if v, ok := data["users"].(map[string]interface{})[userID].(map[string]interface{}); ok { + if v, ok := data["users"].(map[string]interface{})[userID].(map[string]interface{}); ok { - v["data"] = userData - err = saveDatabase(data) + v["data"] = userData + err = saveDatabase(data) - } else { - return - } + } else { + return + } - return + return } // ReadUserData : load user date func ReadUserData(userID string) (userData map[string]interface{}, err error) { - err = checkInit() - if err != nil { - return - } + err = checkInit() + if err != nil { + return + } - err = createError(031) + err = createError(031) - if v, ok := data["users"].(map[string]interface{})[userID].(map[string]interface{}); ok { - userData = v["data"].(map[string]interface{}) - err = nil + if v, ok := data["users"].(map[string]interface{})[userID].(map[string]interface{}); ok { + userData = v["data"].(map[string]interface{}) + err = nil - return - } + return + } - return + return } // RemoveUser : remove user func RemoveUser(userID string) (err error) { - err = checkInit() - if err != nil { - return - } + err = checkInit() + if err != nil { + return + } - err = createError(032) + err = createError(032) - if _, ok := data["users"].(map[string]interface{})[userID]; ok { + if _, ok := data["users"].(map[string]interface{})[userID]; ok { - delete(data["users"].(map[string]interface{}), userID) - err = saveDatabase(data) + delete(data["users"].(map[string]interface{}), userID) + err = saveDatabase(data) - return - } + return + } - return + return } // SetDefaultUserData : set default user data func SetDefaultUserData(defaults map[string]interface{}) (err error) { - allUserData, err := GetAllUserData() - - for _, d := range allUserData { - var data = d.(map[string]interface{})["data"].(map[string]interface{}) - var userID = d.(map[string]interface{})["_id"].(string) - - for k, v := range defaults { - if _, ok := data[k]; ok { - // Key exist - } else { - data[k] = v - } - } - err = WriteUserData(userID, data) - } - return + allUserData, err := GetAllUserData() + + for _, d := range allUserData { + var data = d.(map[string]interface{})["data"].(map[string]interface{}) + var userID = d.(map[string]interface{})["_id"].(string) + + for k, v := range defaults { + if _, ok := data[k]; ok { + // Key exist + } else { + data[k] = v + } + } + err = WriteUserData(userID, data) + } + return } // ChangeCredentials : change credentials func ChangeCredentials(userID, username, password string) (err error) { - err = checkInit() - if err != nil { - return - } + err = checkInit() + if err != nil { + return + } - err = createError(032) + err = createError(032) - if userData, ok := data["users"].(map[string]interface{})[userID]; ok { - //var userData = tmp.(map[string]interface{}) - var salt = userData.(map[string]interface{})["_salt"].(string) + if userData, ok := data["users"].(map[string]interface{})[userID]; ok { + //var userData = tmp.(map[string]interface{}) + var salt = userData.(map[string]interface{})["_salt"].(string) - if len(username) > 0 { - userData.(map[string]interface{})["_username"] = SHA256(username, salt) - } + if len(username) > 0 { + userData.(map[string]interface{})["_username"] = SHA256(username, salt) + } - if len(password) > 0 { - userData.(map[string]interface{})["_password"] = SHA256(password, salt) - } + if len(password) > 0 { + userData.(map[string]interface{})["_password"] = SHA256(password, salt) + } - err = saveDatabase(data) - } + err = saveDatabase(data) + } - return + return } // GetAllUserData : get all user data func GetAllUserData() (allUserData map[string]interface{}, err error) { - err = checkInit() - if err != nil { - return - } - - if len(data) == 0 { - var defaults = make(map[string]interface{}) - defaults["dbVersion"] = "1.0" - defaults["hash"] = "sha256" - defaults["users"] = make(map[string]interface{}) - saveDatabase(defaults) - data = defaults - } - - allUserData = data["users"].(map[string]interface{}) - return + err = checkInit() + if err != nil { + return + } + + if len(data) == 0 { + var defaults = make(map[string]interface{}) + defaults["dbVersion"] = "1.0" + defaults["hash"] = "sha256" + defaults["users"] = make(map[string]interface{}) + saveDatabase(defaults) + data = defaults + } + + allUserData = data["users"].(map[string]interface{}) + return } // CheckTheValidityOfTheTokenFromHTTPHeader : get token from HTTP header func CheckTheValidityOfTheTokenFromHTTPHeader(w http.ResponseWriter, r *http.Request) (writer http.ResponseWriter, newToken string, err error) { - err = createError(011) - for _, cookie := range r.Cookies() { - if cookie.Name == "Token" { - var token string - token, err = CheckTheValidityOfTheToken(cookie.Value) - //fmt.Println("T", token, err) - writer = SetCookieToken(w, token) - newToken = token - } - } - //fmt.Println(err) - return + err = createError(011) + for _, cookie := range r.Cookies() { + if cookie.Name == "Token" { + var token string + token, err = CheckTheValidityOfTheToken(cookie.Value) + //fmt.Println("T", token, err) + writer = SetCookieToken(w, token) + newToken = token + } + } + //fmt.Println(err) + return } // Framework tools func checkInit() (err error) { - if initAuthentication == false { - err = createError(000) - } + if !initAuthentication { + err = createError(000) + } - return + return } func saveDatabase(tmpMap interface{}) (err error) { - jsonString, err := json.MarshalIndent(tmpMap, "", " ") + jsonString, err := json.MarshalIndent(tmpMap, "", " ") - if err != nil { - return - } + if err != nil { + return + } - err = ioutil.WriteFile(database, []byte(jsonString), 0600) - if err != nil { - return - } + err = ioutil.WriteFile(database, []byte(jsonString), 0600) + if err != nil { + return + } - return + return } func loadDatabase() (err error) { - jsonString, err := ioutil.ReadFile(database) - if err != nil { - return - } + jsonString, err := ioutil.ReadFile(database) + if err != nil { + return + } - err = json.Unmarshal([]byte(jsonString), &data) - if err != nil { - return - } + err = json.Unmarshal([]byte(jsonString), &data) + if err != nil { + return + } - return + return } // SHA256 : password + salt = sha256 string func SHA256(secret, salt string) string { - key := []byte(secret) - h := hmac.New(sha256.New, key) - h.Write([]byte("_remote_db")) - return base64.StdEncoding.EncodeToString(h.Sum(nil)) + key := []byte(secret) + h := hmac.New(sha256.New, key) + h.Write([]byte("_remote_db")) + return base64.StdEncoding.EncodeToString(h.Sum(nil)) } func randomString(n int) string { - const alphanum = "-AbCdEfGhIjKlMnOpQrStUvWxYz0123456789aBcDeFgHiJkLmNoPqRsTuVwXyZ_" - - var bytes = make([]byte, n) - rand.Read(bytes) - for i, b := range bytes { - bytes[i] = alphanum[b%byte(len(alphanum))] - } - return string(bytes) + const alphanum = "-AbCdEfGhIjKlMnOpQrStUvWxYz0123456789aBcDeFgHiJkLmNoPqRsTuVwXyZ_" + + var bytes = make([]byte, n) + rand.Read(bytes) + for i, b := range bytes { + bytes[i] = alphanum[b%byte(len(alphanum))] + } + return string(bytes) } func randomID(n int) string { - const alphanum = "ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789" - - var bytes = make([]byte, n) - rand.Read(bytes) - for i, b := range bytes { - bytes[i] = alphanum[b%byte(len(alphanum))] - } - return string(bytes) + const alphanum = "ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789" + + var bytes = make([]byte, n) + rand.Read(bytes) + for i, b := range bytes { + bytes[i] = alphanum[b%byte(len(alphanum))] + } + return string(bytes) } func createError(errCode int) (err error) { - var errMsg string - switch errCode { - case 000: - errMsg = "Authentication has not yet been initialized" - case 001: - errMsg = "Default user already exists" - case 002: - errMsg = "No user id found for this token" - case 010: - errMsg = "User authentication failed" - case 011: - errMsg = "Session has expired" - case 020: - errMsg = "User already exists" - case 030: - errMsg = "User data could not be saved" - case 031: - errMsg = "User data could not be read" - case 032: - errMsg = "User ID was not found" - } - - err = errors.New(errMsg) - return + var errMsg string + switch errCode { + case 000: + errMsg = "Authentication has not yet been initialized" + case 001: + errMsg = "Default user already exists" + case 002: + errMsg = "No user id found for this token" + case 010: + errMsg = "User authentication failed" + case 011: + errMsg = "Session has expired" + case 020: + errMsg = "User already exists" + case 030: + errMsg = "User data could not be saved" + case 031: + errMsg = "User data could not be read" + case 032: + errMsg = "User ID was not found" + } + + err = errors.New(errMsg) + return } func defaultsForNewUser(username, password string) map[string]interface{} { - var defaults = make(map[string]interface{}) - var salt = randomString(saltLength) - defaults["_username"] = SHA256(username, salt) - defaults["_password"] = SHA256(password, salt) - defaults["_salt"] = salt - defaults["_id"] = "id-" + randomID(idLength) - //defaults["_one.time.token"] = randomString(tokenLength) - defaults["data"] = make(map[string]interface{}) - - return defaults + var defaults = make(map[string]interface{}) + var salt = randomString(saltLength) + defaults["_username"] = SHA256(username, salt) + defaults["_password"] = SHA256(password, salt) + defaults["_salt"] = salt + defaults["_id"] = "id-" + randomID(idLength) + //defaults["_one.time.token"] = randomString(tokenLength) + defaults["data"] = make(map[string]interface{}) + + return defaults } func setToken(id, oldToken string) (newToken string) { - delete(tokens, oldToken) + delete(tokens, oldToken) loopToken: - newToken = randomString(tokenLength) - if _, ok := tokens[newToken]; ok { - goto loopToken - } + newToken = randomString(tokenLength) + if _, ok := tokens[newToken]; ok { + goto loopToken + } - var tmp = make(map[string]interface{}) - tmp["id"] = id - tmp["expires"] = time.Now().Local().Add(time.Minute * time.Duration(tokenValidity)) + var tmp = make(map[string]interface{}) + tmp["id"] = id + tmp["expires"] = time.Now().Local().Add(time.Minute * time.Duration(tokenValidity)) - tokens[newToken] = tmp + tokens[newToken] = tmp - return -} - -func mapToJSON(tmpMap interface{}) string { - jsonString, err := json.MarshalIndent(tmpMap, "", " ") - if err != nil { - return "{}" - } - return string(jsonString) + return } // SetCookieToken : set cookie func SetCookieToken(w http.ResponseWriter, token string) http.ResponseWriter { - expiration := time.Now().Add(time.Minute * time.Duration(tokenValidity)) - cookie := http.Cookie{Name: "Token", Value: token, Expires: expiration} - http.SetCookie(w, &cookie) - return w + expiration := time.Now().Add(time.Minute * time.Duration(tokenValidity)) + cookie := http.Cookie{Name: "Token", Value: token, Expires: expiration} + http.SetCookie(w, &cookie) + return w } diff --git a/src/internal/imgcache/cache.go b/src/internal/imgcache/cache.go index 0337dcc..9a2f3ce 100644 --- a/src/internal/imgcache/cache.go +++ b/src/internal/imgcache/cache.go @@ -30,7 +30,7 @@ type imageFunc struct { Remove func() } -// New : New cahce +// New : New cache func New(path, chacheURL string, caching bool) (c *Cache, err error) { c = &Cache{} diff --git a/src/internal/m3u-parser/m3u-parser_test.go b/src/internal/m3u-parser/m3u-parser_test.go deleted file mode 100644 index ca3e73d..0000000 --- a/src/internal/m3u-parser/m3u-parser_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package m3u - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "log" - "testing" -) - -type M3UStream struct { - GroupTitle string `json:"group-title,required"` - Name string `json:"name,required"` - TvgID string `json:"tvg-id,required"` - TvgLogo string `json:"tvg-logo,required"` - TvgName string `json:"tvg-name,required"` - URL string `json:"url,required"` - UUIDKey string `json:"_uuid.key,omitempty"` - UUIDValue string `json:"_uuid.value,omitempty"` -} - -func TestStream1(t *testing.T) { - - var file = "test_list_1.m3u" - var content, err = ioutil.ReadFile(file) - if err != nil { - t.Error(err) - return - } - - streams, err := MakeInterfaceFromM3U(content) - - if err != nil { - t.Error(err) - } - - err = checkStream(streams) - if err != nil { - t.Error(err) - } - - fmt.Println("Streams:", len(streams)) - t.Log(streams) - -} - -func checkStream(streamInterface []interface{}) (err error) { - - for i, s := range streamInterface { - - var stream = s.(map[string]string) - var m3uStream M3UStream - - jsonString, err := json.MarshalIndent(stream, "", " ") - - if err == nil { - - err = json.Unmarshal(jsonString, &m3uStream) - if err == nil { - - log.Print(fmt.Sprintf("Stream: %d", i)) - log.Print(fmt.Sprintf("Name*: %s", m3uStream.Name)) - log.Print(fmt.Sprintf("URL*: %s", m3uStream.URL)) - log.Print(fmt.Sprintf("tvg-name: %s", m3uStream.TvgName)) - log.Print(fmt.Sprintf("tvg-id**: %s", m3uStream.TvgID)) - log.Print(fmt.Sprintf("tvg-logo: %s", m3uStream.TvgLogo)) - log.Print(fmt.Sprintf("group-title**: %s", m3uStream.GroupTitle)) - - if len(m3uStream.UUIDKey) > 0 { - log.Print(fmt.Sprintf("UUID key***: %s", m3uStream.UUIDKey)) - log.Print(fmt.Sprintf("UUID value: %s", m3uStream.UUIDValue)) - } else { - log.Print(fmt.Sprintf("UUID key: false")) - } - - } - - } - - log.Println(fmt.Sprintf("- - - - - (*: Required) | (**: Nice to have) | (***: Love it) - - - - -")) - } - - return -} diff --git a/src/internal/m3u-parser/test_list_1.m3u b/src/internal/m3u-parser/test_playlist_1.m3u similarity index 58% rename from src/internal/m3u-parser/test_list_1.m3u rename to src/internal/m3u-parser/test_playlist_1.m3u index 478c95d..4ba02c0 100644 --- a/src/internal/m3u-parser/test_list_1.m3u +++ b/src/internal/m3u-parser/test_playlist_1.m3u @@ -2,12 +2,14 @@ #EXTINF:0 channelID="1" tvg-chno="1" tvg-name="Channel.1" tvg-id="tvg.id.1" tvg-logo="https://example/logo.png" group-title="Group 1", Channel 1 http://example.com/stream/1 -#EXTINF:0 channelID="2" tvg-chno="2" tvg-name="Channel.2" tvg-id="tvg.id.2" tvg-logo="https://example/logo.png" group-title="Group 2",Channel 2 +#EXTINF:0 channelID="2" tvg-chno="2" tvg-name="Channel.2" tvg-id="tvg.id.2" tvg-logo="https://example/logo/2.png",Channel 2 +#EXTGRP: Group 2 #123 http://example.com/stream/2 -#EXTINF:123, Sample artist - Sample title +#EXTINF:123,,:It's - a difficult name | http://example.com/stream/3 -#EXTINF:321,Example Artist - Example title +#EXTINF:-1 tvg-id="tvg.id.4" tvg-name="Channel.4" tvg-logo="https://example/logo/4.png" tvg-chno="4" channel-id="4" tvg-shift="-5" group-title="Group 4",Channel 4 +#EXTGRP:Group 99 http://example.com/stream/4 diff --git a/src/internal/m3u-parser/xteve_m3uParser.go b/src/internal/m3u-parser/xteve_m3uParser.go deleted file mode 100755 index 79641b3..0000000 --- a/src/internal/m3u-parser/xteve_m3uParser.go +++ /dev/null @@ -1,186 +0,0 @@ -package m3u - -import ( - "errors" - "fmt" - "log" - "net/url" - "regexp" - "strings" -) - -// MakeInterfaceFromM3U : -func MakeInterfaceFromM3U(byteStream []byte) (allChannels []interface{}, err error) { - - var content = string(byteStream) - var channelName string - var uuids []string - - var parseMetaData = func(channel string) (stream map[string]string) { - - stream = make(map[string]string) - var exceptForParameter = `[a-z-A-Z=]*(".*?")` - var exceptForChannelName = `,([^\n]*|,[^\r]*)` - - var lines = strings.Split(strings.Replace(channel, "\r\n", "\n", -1), "\n") - - // Zeilen mit # und leerer Zeilen entfernen - for i := len(lines) - 1; i >= 0; i-- { - - if len(lines[i]) == 0 || lines[i][0:1] == "#" { - lines = append(lines[:i], lines[i+1:]...) - } - - } - - if len(lines) >= 2 { - - for _, line := range lines { - - _, err := url.ParseRequestURI(line) - - switch err { - - case nil: - stream["url"] = strings.Trim(line, "\r\n") - - default: - - var value string - // Alle Parameter parsen - var p = regexp.MustCompile(exceptForParameter) - var streamParameter = p.FindAllString(line, -1) - - for _, p := range streamParameter { - - line = strings.Replace(line, p, "", 1) - - p = strings.Replace(p, `"`, "", -1) - var parameter = strings.SplitN(p, "=", 2) - - if len(parameter) == 2 { - - // TVG Key als Kleinbuchstaben speichern - switch strings.Contains(parameter[0], "tvg") { - - case true: - stream[strings.ToLower(parameter[0])] = parameter[1] - case false: - stream[parameter[0]] = parameter[1] - - } - - // URL's nicht an die Filterfunktion übergeben - if !strings.Contains(parameter[1], "://") && len(parameter[1]) > 0 { - value = value + parameter[1] + " " - } - - } - - } - - // Kanalnamen parsen - n := regexp.MustCompile(exceptForChannelName) - var name = n.FindAllString(line, 1) - - if len(name) > 0 { - channelName = name[0] - channelName = strings.Replace(channelName, `,`, "", 1) - channelName = strings.TrimRight(channelName, "\r\n") - channelName = strings.TrimRight(channelName, " ") - } - - if len(channelName) == 0 { - - if v, ok := stream["tvg-name"]; ok { - channelName = v - } - - } - - channelName = strings.TrimRight(channelName, " ") - - // Kanäle ohne Namen werden augelassen - if len(channelName) == 0 { - return - } - - stream["name"] = channelName - value = value + channelName - - stream["_values"] = value - - } - - } - - } - - // Nach eindeutiger ID im Stream suchen - for key, value := range stream { - - if !strings.Contains(strings.ToLower(key), "tvg-id") { - - if strings.Contains(strings.ToLower(key), "id") { - - if indexOfString(value, uuids) != -1 { - log.Println(fmt.Sprintf("Channel: %s - %s = %s ", stream["name"], key, value)) - break - } - - uuids = append(uuids, value) - - stream["_uuid.key"] = key - stream["_uuid.value"] = value - break - - } - - } - - } - - return - } - - //fmt.Println(content) - if strings.Contains(content, "#EXT-X-TARGETDURATION") || strings.Contains(content, "#EXT-X-MEDIA-SEQUENCE") { - err = errors.New("Invalid M3U file, an extended M3U file is required.") - return - } - - if strings.Contains(content, "#EXTM3U") { - - var channels = strings.Split(content, "#EXTINF") - - channels = append(channels[:0], channels[1:]...) - - for _, channel := range channels { - - var stream = parseMetaData(channel) - - if len(stream) > 0 && stream != nil { - allChannels = append(allChannels, stream) - } - - } - - } else { - - err = errors.New("Invalid M3U file, an extended M3U file is required.") - - } - - return -} - -func indexOfString(element string, data []string) int { - - for k, v := range data { - if element == v { - return k - } - } - - return -1 -} diff --git a/src/internal/m3u-parser/xteve_m3u_parser.go b/src/internal/m3u-parser/xteve_m3u_parser.go new file mode 100644 index 0000000..31b0654 --- /dev/null +++ b/src/internal/m3u-parser/xteve_m3u_parser.go @@ -0,0 +1,188 @@ +package m3u + +import ( + "errors" + "fmt" + "log" + "net/url" + "regexp" + "strings" + + "github.com/samber/lo" +) + +var exceptForParameterRx = regexp.MustCompile(`[a-z-A-Z=]*(".*?")`) +var exceptForChannelNameRx = regexp.MustCompile(`,([^\n]*|,[^\r]*)`) +var extGrpRx = regexp.MustCompile(`#EXTGRP: *(.*)`) + +// MakeInterfaceFromM3U : +func MakeInterfaceFromM3U(byteStream []byte) (allChannels []interface{}, err error) { + + var content = string(byteStream) + var channelName string + var uuids []string + + var parseMetaData = func(channel string) (stream map[string]string) { + + stream = make(map[string]string) + + var lines = strings.Split(strings.Replace(channel, "\r\n", "\n", -1), "\n") + + // Remove lines with # and blank lines + for i := len(lines) - 1; i >= 0; i-- { + + if len(lines[i]) == 0 || lines[i][0:1] == "#" { + lines = append(lines[:i], lines[i+1:]...) + } + + } + + if len(lines) >= 2 { + + for _, line := range lines { + + _, err := url.ParseRequestURI(line) + + switch err { + + case nil: + stream["url"] = strings.Trim(line, "\r\n") + + default: + + var value string + // Parse all parameters + var streamParameter = exceptForParameterRx.FindAllString(line, -1) + + for _, p := range streamParameter { + + line = strings.Replace(line, p, "", 1) + + p = strings.Replace(p, `"`, "", -1) + var parameter = strings.SplitN(p, "=", 2) + + if len(parameter) == 2 { + + // Set TVG Key as lowercase + switch strings.Contains(parameter[0], "tvg") { + + case true: + stream[strings.ToLower(parameter[0])] = parameter[1] + case false: + stream[parameter[0]] = parameter[1] + + } + + // URL's are not passed to the filter function + if !strings.Contains(parameter[1], "://") && len(parameter[1]) > 0 { + value = value + parameter[1] + " " + } + + } + + } + + // Parse channel names + var name = exceptForChannelNameRx.FindAllString(line, 1) + + if len(name) > 0 { + channelName = name[0] + channelName = strings.Replace(channelName, `,`, "", 1) + channelName = strings.TrimRight(channelName, "\r\n") + channelName = strings.Trim(channelName, " ") + } + + if len(channelName) == 0 { + + if v, ok := stream["tvg-name"]; ok { + channelName = v + } + + } + + channelName = strings.Trim(channelName, " ") + + // Channels without names are skipped + if len(channelName) == 0 { + return + } + + stream["name"] = channelName + value = value + channelName + + stream["_values"] = value + + } + + } + + } + + // Search for a unique ID in the stream + for key, value := range stream { + + if !strings.Contains(strings.ToLower(key), "tvg-id") { + + if strings.Contains(strings.ToLower(key), "id") { + + if lo.IndexOf(uuids, value) != -1 { + log.Println(fmt.Sprintf("Channel: %s - %s = %s ", stream["name"], key, value)) + break + } + + uuids = append(uuids, value) + + stream["_uuid.key"] = key + stream["_uuid.value"] = value + break + + } + + } + + } + + return + } + + if strings.Contains(content, "#EXT-X-TARGETDURATION") || strings.Contains(content, "#EXT-X-MEDIA-SEQUENCE") { + err = errors.New("Invalid M3U file, an extended M3U file is required.") + return + } + + if strings.Contains(content, "#EXTM3U") { + + var channels = strings.Split(content, "#EXTINF") + + channels = append(channels[:0], channels[1:]...) + + var lastExtGrp string + + for _, channel := range channels { + + var stream = parseMetaData(channel) + + if extGrp := extGrpRx.FindStringSubmatch(channel); len(extGrp) > 1 { + // EXTGRP applies to all subseqent channels until overriden + lastExtGrp = strings.Trim(extGrp[1], "\r\n") + } + + // group-title has priority over EXTGRP + if stream["group-title"] == "" && lastExtGrp != "" { + stream["group-title"] = lastExtGrp + } + + if len(stream) > 0 && stream != nil { + allChannels = append(allChannels, stream) + } + + } + + } else { + + err = errors.New("Invalid M3U file, an extended M3U file is required.") + + } + + return +} diff --git a/src/internal/m3u-parser/xteve_m3u_parser_test.go b/src/internal/m3u-parser/xteve_m3u_parser_test.go new file mode 100644 index 0000000..8ec353f --- /dev/null +++ b/src/internal/m3u-parser/xteve_m3u_parser_test.go @@ -0,0 +1,85 @@ +package m3u + +import ( + "encoding/json" + "io/ioutil" + "testing" + + "github.com/stretchr/testify/assert" +) + +type M3UStream struct { + GroupTitle string `json:"group-title,required"` + Name string `json:"name,required"` + TvgID string `json:"tvg-id,required"` + TvgLogo string `json:"tvg-logo,required"` + TvgName string `json:"tvg-name,required"` + TvgShift string `json:"tvg-shift,omitempty"` + URL string `json:"url,required"` + UUIDKey string `json:"_uuid.key,omitempty"` + UUIDValue string `json:"_uuid.value,omitempty"` +} + +func TestMakeInterfaceFromM3U(t *testing.T) { + + // Read playlist + file := "test_playlist_1.m3u" + content, err := ioutil.ReadFile(file) + assert.NoError(t, err, "Should read playlist") + + // Parse playlist into []interface{} + rawStreams, err := MakeInterfaceFromM3U(content) + assert.NoError(t, err, "Should parse playlist") + + // Build []M3UStream from []interface{} + streams := []M3UStream{} + + for _, rawStream := range rawStreams { + jsonString, err := json.MarshalIndent(rawStream, "", " ") + assert.NoError(t, err, "Should convert from interface") + + stream := M3UStream{} + err = json.Unmarshal(jsonString, &stream) + assert.NoError(t, err, "Should convert from interface") + + streams = append(streams, stream) + } + + assert.Len(t, streams, 4, "Should be 4 streams in total") + + // Test stream 1 + assert.Equal(t, "Channel 1", streams[0].Name, "Names should match") + assert.Equal(t, "Group 1", streams[0].GroupTitle, "Groups should match") + assert.Equal(t, "http://example.com/stream/1", streams[0].URL, "URL's should match") + assert.Equal(t, "Channel.1", streams[0].TvgName, "TVG names should match") + assert.Equal(t, "tvg.id.1", streams[0].TvgID, "TVG ID's should match") + assert.Equal(t, "https://example/logo.png", streams[0].TvgLogo, "TVG logos should match") + assert.Empty(t, streams[0].TvgShift, "Should not have tvg-shift tag") + + // Test stream 2 + assert.Equal(t, "Channel 2", streams[1].Name, "Names should match") + assert.Equal(t, "Group 2", streams[1].GroupTitle, "Should have a GroupTitle set from EXTGRP") + assert.Equal(t, "http://example.com/stream/2", streams[1].URL, "URL's should match") + assert.Equal(t, "Channel.2", streams[1].TvgName, "TVG names should match") + assert.Equal(t, "tvg.id.2", streams[1].TvgID, "TVG ID's should match") + assert.Equal(t, "https://example/logo/2.png", streams[1].TvgLogo, "TVG logos should match") + assert.Empty(t, streams[1].TvgShift, "Should not have tvg-shift tag") + + // Test stream 3 + assert.Equal(t, ",:It's - a difficult name |", streams[2].Name, "Names should match") + assert.Equal(t, "Group 2", streams[2].GroupTitle, "Should have a GroupTitle set from previous EXTGRP") + assert.Equal(t, "http://example.com/stream/3", streams[2].URL, "URL's should match") + assert.Empty(t, streams[2].TvgName, "Should not have tvg-name tag") + assert.Empty(t, streams[2].TvgID, "Should not have tvg-id tag") + assert.Empty(t, streams[2].TvgLogo, "Should not have tvg-logo tag") + assert.Empty(t, streams[2].TvgShift, "Should not have tvg-shift tag") + + // Test stream 4 + assert.Equal(t, "Channel 4", streams[3].Name, "Names should match") + assert.Equal(t, "Group 4", streams[3].GroupTitle, "Should have a GroupTitle set from group-title, over EXTGRP") + assert.Equal(t, "http://example.com/stream/4", streams[3].URL, "URL's should match") + assert.Equal(t, "Channel.4", streams[3].TvgName, "TVG names should match") + assert.Equal(t, "tvg.id.4", streams[3].TvgID, "TVG ID's should match") + assert.Equal(t, "https://example/logo/4.png", streams[3].TvgLogo, "TVG logos should match") + assert.Equal(t, "-5", streams[3].TvgShift, "TVG shifts should match") +} diff --git a/src/internal/up2date/client/client.go b/src/internal/up2date/client/client.go index 13eeccc..433db84 100755 --- a/src/internal/up2date/client/client.go +++ b/src/internal/up2date/client/client.go @@ -61,7 +61,7 @@ func serverRequest() (err error) { jsonByte, err := json.MarshalIndent(Updater, "", " ") if err == nil { - // Serververbindung prüfen + // Check server connection u, err := url.Parse(Updater.URL) if err != nil { return err diff --git a/src/internal/up2date/client/update.go b/src/internal/up2date/client/update.go index 7b3b15b..0418ecc 100755 --- a/src/internal/up2date/client/update.go +++ b/src/internal/up2date/client/update.go @@ -187,15 +187,6 @@ func restorOldBinary(oldBinary, newBinary string) { os.Rename(oldBinary, newBinary) } -func getPlatformFile(filename string) string { - - path, file := filepath.Split(filename) - var newPath = filepath.Dir(path) - var newFileName = newPath + string(os.PathSeparator) + file - - return newFileName -} - func getFilenameFromPath(path string) string { file := filepath.Base(path) diff --git a/src/m3u.go b/src/m3u.go index efb5231..033093f 100644 --- a/src/m3u.go +++ b/src/m3u.go @@ -10,9 +10,11 @@ import ( "strings" m3u "xteve/src/internal/m3u-parser" + + "github.com/samber/lo" ) -// Playlisten parsen +// Parse Playlists func parsePlaylist(filename, fileType string) (channels []interface{}, err error) { content, err := readByteFromFile(filename) @@ -33,7 +35,7 @@ func parsePlaylist(filename, fileType string) (channels []interface{}, err error return } -// Streams filtern +// Filter Streams func filterThisStream(s interface{}) (status bool) { status = false @@ -61,7 +63,7 @@ func filterThisStream(s interface{}) (status bool) { name = v } - // Unerwünschte Streams !{DEU} + // Unwanted Streams !{DEU} r := regexp.MustCompile(regexpNO) val := r.FindStringSubmatch(filter.Rule) @@ -73,7 +75,7 @@ func filterThisStream(s interface{}) (status bool) { } - // Muss zusätzlich erfüllt sein {DEU} + // Required Streams {DEU} r = regexp.MustCompile(regexpYES) val = r.FindStringSubmatch(filter.Rule) @@ -105,6 +107,8 @@ func filterThisStream(s interface{}) (status bool) { if group == filter.Rule { match = true + stream["_preserve-mapping"] = strconv.FormatBool(filter.PreserveMapping) + stream["_starting-channel"] = filter.StartingChannel } case "custom-filter": @@ -114,18 +118,18 @@ func filterThisStream(s interface{}) (status bool) { } } - if match == true { + if match { if len(exclude) > 0 { var status = checkConditions(search, exclude, "exclude") - if status == false { + if !status { return false } } if len(include) > 0 { var status = checkConditions(search, include, "include") - if status == false { + if !status { return false } } @@ -139,7 +143,7 @@ func filterThisStream(s interface{}) (status bool) { return false } -// Bedingungen für den Filter +// Conditions for the Filter func checkConditions(streamValues, conditions, coType string) (status bool) { switch coType { @@ -178,7 +182,7 @@ func checkConditions(streamValues, conditions, coType string) (status bool) { return } -// xTeVe M3U Datei erstellen +// Create xTeVe M3U file func buildM3U(groups []string) (m3u string, err error) { var imgc = Data.Cache.Images @@ -191,11 +195,11 @@ func buildM3U(groups []string) (m3u string, err error) { err := json.Unmarshal([]byte(mapToJSON(dxc)), &xepgChannel) if err == nil { - if xepgChannel.XActive == true { + if xepgChannel.XActive { if len(groups) > 0 { - if indexOfString(xepgChannel.XGroupTitle, groups) == -1 { + if lo.IndexOf(groups, xepgChannel.XGroupTitle) == -1 { goto Done } @@ -215,7 +219,7 @@ func buildM3U(groups []string) (m3u string, err error) { Done: } - // M3U Inhalt erstellen + // Create M3U Content sort.Float64s(channelNumbers) var xmltvURL = fmt.Sprintf("%s://%s/xmltv/xteve.xml", System.ServerProtocol.XML, System.Domain) diff --git a/src/maintenance.go b/src/maintenance.go index 76c499c..4698cda 100644 --- a/src/maintenance.go +++ b/src/maintenance.go @@ -6,7 +6,7 @@ import ( "time" ) -// InitMaintenance : Wartungsprozess initialisieren +// InitMaintenance : Initialize maintenance process func InitMaintenance() (err error) { rand.Seed(time.Now().Unix()) @@ -23,7 +23,7 @@ func maintenance() { var t = time.Now() - // Aktualisierung der Playlist und XMLTV Dateien + // Update the playlist and XMLTV files if System.ScanInProgress == 0 { for _, schedule := range Settings.Update { @@ -32,13 +32,13 @@ func maintenance() { showInfo("Update:" + schedule) - // Backup erstellen + // Create a backup err := xTeVeAutoBackup() if err != nil { ShowError(err, 000) } - // Playlist und XMLTV Dateien aktualisieren + // Update Playlist and XMLTV Files getProviderData("m3u", "") getProviderData("hdhr", "") @@ -46,17 +46,17 @@ func maintenance() { getProviderData("xmltv", "") } - // Datenbank für DVR erstellen + // Create database for DVR err = buildDatabaseDVR() if err != nil { ShowError(err, 000) } - if Settings.CacheImages == false && System.ImageCachingInProgress == 0 { + if !Settings.CacheImages && System.ImageCachingInProgress == 0 { removeChildItems(System.Folder.ImagesCache) } - // XEPG Dateien erstellen + // Create XEPG Files Data.Cache.XMLTV = make(map[string]XMLTV) buildXEPG(false) @@ -75,7 +75,6 @@ func maintenance() { } - return } func randomTime(min, max int) int { diff --git a/src/provider.go b/src/provider.go index f376b3a..5da3bb2 100644 --- a/src/provider.go +++ b/src/provider.go @@ -11,7 +11,7 @@ import ( m3u "xteve/src/internal/m3u-parser" ) -// fileType: Welcher Dateityp soll aktualisiert werden (m3u, hdhr, xml) | fileID: Update einer bestimmten Datei (Provider ID) +// fileType: Which File Type should be updated (m3u, hdhr, xml) | fileID: Update a specific File (Provider ID) func getProviderData(fileType, fileID string) (err error) { var fileExtension, serverFileName string @@ -30,7 +30,7 @@ func getProviderData(fileType, fileID string) (err error) { dataMap[id] = data } - // Default keys für die Providerdaten + // Default keys for the Provider Data var keys = []string{"name", "description", "type", "file." + System.AppName, "file.source", "tuner", "last.update", "compatibility", "counter.error", "counter.download", "provider.availability"} for _, key := range keys { @@ -85,14 +85,14 @@ func getProviderData(fileType, fileID string) (err error) { data["id.provider"] = id } - // Datei extrahieren + // Extract File body, err = extractGZIP(body, fileSource) if err != nil { ShowError(err, 000) return } - // Daten überprüfen + // Check Data showInfo("Check File:" + fileSource) switch fileType { @@ -151,8 +151,8 @@ func getProviderData(fileType, fileID string) (err error) { delete(data, "new") } - // Wenn eine ID vorhanden ist und nicht mit der aus der Datanbank übereinstimmt, wird die Aktualisierung übersprungen (goto) - if len(fileID) > 0 && newProvider == false { + // If an ID is available and does not match the one from the Database, the Update is skipped (goto) + if len(fileID) > 0 && !newProvider { if dataID != fileID { goto Done } @@ -162,7 +162,7 @@ func getProviderData(fileType, fileID string) (err error) { case "hdhr": - // Laden vom HDHomeRun Tuner + // Load from the HDHomeRun Tuner showInfo("Tuner:" + fileSource) var tunerURL = "http://" + fileSource + "/lineup.json" serverFileName, body, err = downloadFileFromServer(tunerURL) @@ -171,13 +171,13 @@ func getProviderData(fileType, fileID string) (err error) { if strings.Contains(fileSource, "http://") || strings.Contains(fileSource, "https://") { - // Laden vom Remote Server + // Load from the Remote Server showInfo("Download:" + fileSource) serverFileName, body, err = downloadFileFromServer(fileSource) } else { - // Laden einer lokalen Datei + // Load a local File showInfo("Open:" + fileSource) err = checkFile(fileSource) @@ -204,9 +204,9 @@ func getProviderData(fileType, fileID string) (err error) { ShowError(err, 000) var downloadErr = err - if newProvider == false { + if !newProvider { - // Prüfen ob ältere Datei vorhanden ist + // Check whether there is an older File var file = System.Folder.Data + dataID + fileExtension err = checkFile(file) @@ -219,7 +219,7 @@ func getProviderData(fileType, fileID string) (err error) { err = downloadErr } - // Fehler Counter um 1 erhöhen + // Increase Error Counter by 1 var data = make(map[string]interface{}) if value, ok := dataMap[dataID].(map[string]interface{}); ok { @@ -235,8 +235,8 @@ func getProviderData(fileType, fileID string) (err error) { } - // Berechnen der Fehlerquote - if newProvider == false { + // Calculate the Margin of Error + if !newProvider { if value, ok := dataMap[dataID].(map[string]interface{}); ok { @@ -294,7 +294,7 @@ func downloadFileFromServer(providerURL string) (filename string, body []byte, e return } - // Dateiname aus dem Header holen + // Get the File Mame from the Header var index = strings.Index(resp.Header.Get("Content-Disposition"), "filename") if index > -1 { diff --git a/src/screen.go b/src/screen.go index b3ac4df..45a60d4 100644 --- a/src/screen.go +++ b/src/screen.go @@ -3,6 +3,7 @@ package src import ( "fmt" "log" + "os" "runtime" "strconv" "strings" @@ -12,7 +13,7 @@ import ( func showInfo(str string) { - if System.Flag.Info == true { + if System.Flag.Info { return } @@ -39,7 +40,6 @@ func showInfo(str string) { } - return } func showDebug(str string, level int) { @@ -73,7 +73,6 @@ func showDebug(str string, level int) { } - return } func showHighlight(str string) { @@ -105,7 +104,6 @@ func showHighlight(str string) { addNotification(notification) - return } func showWarning(errCode int) { @@ -121,10 +119,9 @@ func showWarning(errCode int) { WebScreenLog.Warnings++ mutex.Unlock() - return } -// ShowError : Zeigt die Fehlermeldungen in der Konsole +// ShowError : Shows the Error Messages in the Console func ShowError(err error, errCode int) { var mutex = sync.RWMutex{} @@ -139,7 +136,6 @@ func ShowError(err error, errCode int) { WebScreenLog.Errors++ mutex.Unlock() - return } func printLogOnScreen(logMsg string, logType string) { @@ -211,10 +207,9 @@ func logCleanUp() { WebScreenLog.Log = logs - return } -// Fehlercodes +// Return Error Message from numeric Error Codes func getErrMsg(errCode int) (errMsg string) { switch errCode { @@ -224,166 +219,186 @@ func getErrMsg(errCode int) (errMsg string) { // Errors case 1001: - errMsg = fmt.Sprintf("Web server could not be started.") + errMsg = "Web server could not be started." case 1002: - errMsg = fmt.Sprintf("No local IP address found.") + errMsg = "No local IP address found." case 1003: - errMsg = fmt.Sprintf("Invalid xml") + errMsg = "Invalid xml" case 1004: - errMsg = fmt.Sprintf("File not found") + errMsg = "File not found" case 1005: - errMsg = fmt.Sprintf("Invalid M3U file, an extended M3U file is required.") + errMsg = "Invalid M3U file, an extended M3U file is required." case 1006: - errMsg = fmt.Sprintf("No playlist!") + errMsg = "No playlist!" case 1007: - errMsg = fmt.Sprintf("XEPG requires an XMLTV file.") + errMsg = "XEPG requires an XMLTV file." case 1010: - errMsg = fmt.Sprintf("Invalid file compression") + errMsg = "Invalid file compression" case 1011: errMsg = fmt.Sprintf("Data is corrupt or unavailable, %s now uses an older version of this file", System.Name) case 1012: - errMsg = fmt.Sprintf("Invalid formatting of the time") + errMsg = "Invalid formatting of the time" case 1013: errMsg = fmt.Sprintf("Invalid settings file (settings.json), file must be at least version %s", System.Compatibility) case 1014: - errMsg = fmt.Sprintf("Invalid filter rule") + errMsg = "Invalid filter rule" + case 1015: + errMsg = fmt.Sprintf("Specified temp folder path is invalid, fallback to %s", os.TempDir()) + case 1016: + errMsg = "Web server could not be stopped." + case 1017: + errMsg = "Web server could not be started in TLS mode, fallback to default." + case 1018: + errMsg = "Failed to compile channel name update regex" case 1020: - errMsg = fmt.Sprintf("Data could not be saved, invalid keyword") + errMsg = "Data could not be saved, invalid keyword" - // Datenbank Update + // Database Update case 1030: errMsg = fmt.Sprintf("Invalid settings file (%s)", System.File.Settings) case 1031: - errMsg = fmt.Sprintf("Database error. The database version of your settings is not compatible with this version.") + errMsg = "Database error. The database version of your settings is not compatible with this version." // M3U Parser case 1050: - errMsg = fmt.Sprintf("Invalid duration specification in the M3U8 playlist.") + errMsg = "Invalid duration specification in the M3U8 playlist." case 1060: - errMsg = fmt.Sprintf("Invalid characters found in the tvg parameters, streams with invalid parameters were skipped.") + errMsg = "Invalid characters found in the tvg parameters, streams with invalid parameters were skipped." - // Dateisystem + // Filesystem case 1070: - errMsg = fmt.Sprintf("Folder could not be created.") + errMsg = "Folder could not be created." case 1071: - errMsg = fmt.Sprintf("File could not be created") + errMsg = "File could not be created" case 1072: - errMsg = fmt.Sprintf("File not found") + errMsg = "File not found" + case 1073: + errMsg = "Can not remove old config folder contents before recover" // Backup case 1090: - errMsg = fmt.Sprintf("Automatic backup failed") + errMsg = "Automatic backup failed" // Websockets case 1100: - errMsg = fmt.Sprintf("WebUI build error") + errMsg = "WebUI build error" case 1101: - errMsg = fmt.Sprintf("WebUI request error") + errMsg = "WebUI request error" case 1102: - errMsg = fmt.Sprintf("WebUI response error") + errMsg = "WebUI response error" // PMS Guide Numbers case 1200: - errMsg = fmt.Sprintf("Could not create file") + errMsg = "Could not create file" - // Stream URL Fehler + // Stream URL Error case 1201: - errMsg = fmt.Sprintf("Plex stream error") + errMsg = "Plex stream error" case 1202: - errMsg = fmt.Sprintf("Steaming URL could not be found in any playlist") + errMsg = "Steaming URL could not be found in any playlist" case 1203: - errMsg = fmt.Sprintf("Steaming URL could not be found in any playlist") + errMsg = "Steaming URL could not be found in any playlist" case 1204: - errMsg = fmt.Sprintf("Streaming was stopped by third party transcoder (FFmpeg / VLC)") + errMsg = "Streaming was stopped by third party transcoder (FFmpeg / VLC)" // Warnings case 2000: - errMsg = fmt.Sprintf("Plex can not handle more than %d streams. If you do not use Plex, you can ignore this warning.", System.PlexChannelLimit) + errMsg = fmt.Sprintf("Plex can not handle more than %d streams. Use filter to reduce the number of streams. "+ + "If you do not use Plex, ignore this warning.", System.PlexChannelLimit) case 2001: - errMsg = fmt.Sprintf("%s has loaded more than %d streams. Use the filter to reduce the number of streams.", System.Name, System.UnfilteredChannelLimit) + // Free slot + return case 2002: - errMsg = fmt.Sprintf("PMS can not play m3u8 streams") + errMsg = "PMS can not play m3u8 streams" case 2003: - errMsg = fmt.Sprintf("PMS can not play streams over RTSP.") + errMsg = "PMS can not play streams over RTSP." case 2004: - errMsg = fmt.Sprintf("Buffer is disabled for this stream.") + errMsg = "Buffer is disabled for this stream." case 2005: - errMsg = fmt.Sprintf("There are no channels mapped, use the mapping menu to assign EPG data to the channels.") + errMsg = "There are no channels mapped, use the mapping menu to assign EPG data to the channels." case 2010: - errMsg = fmt.Sprintf("No valid streaming URL") + errMsg = "No valid streaming URL" case 2020: - errMsg = fmt.Sprintf("FFmpeg binary was not found. Check the FFmpeg binary path in the xTeVe settings.") + errMsg = "FFmpeg binary was not found. Check the FFmpeg binary path in the xTeVe settings." case 2021: - errMsg = fmt.Sprintf("VLC binary was not found. Check the VLC path binary in the xTeVe settings.") + errMsg = "VLC binary was not found. Check the VLC path binary in the xTeVe settings." + case 2022: + errMsg = "Loaded database had broken XEPG mapping (version <= 2.1.1). It was cleared." case 2099: - errMsg = fmt.Sprintf("Updates have been disabled by the developer") + errMsg = "Updates have been disabled by the developer" // Tuner case 2105: errMsg = fmt.Sprintf("The number of tuners has changed, you have to delete " + System.Name + " in Plex / Emby HDHR and set it up again.") case 2106: - errMsg = fmt.Sprintf("This function is only available with XEPG as EPG source") + errMsg = "This function is only available with XEPG as EPG source" case 2110: - errMsg = fmt.Sprintf("Don't run this as Root!") + errMsg = "Don't run this as Root!" case 2300: - errMsg = fmt.Sprintf("No channel logo found in the XMLTV or M3U file.") + errMsg = "No channel logo found in the XMLTV or M3U file." case 2301: - errMsg = fmt.Sprintf("XMLTV file no longer available, channel has been deactivated.") + errMsg = "XMLTV file no longer available, channel has been deactivated." case 2302: - errMsg = fmt.Sprintf("Channel ID in the XMLTV file has changed. Channel has been deactivated.") + errMsg = "Channel ID in the XMLTV file has changed. Channel has been deactivated." - // Benutzerauthentifizierung + // User Authentication case 3000: - errMsg = fmt.Sprintf("Database for user authentication could not be initialized.") + errMsg = "Database for user authentication could not be initialized." case 3001: - errMsg = fmt.Sprintf("The user has no authorization to load the channels.") + errMsg = "The user has no authorization to load the channels." // Buffer case 4000: - errMsg = fmt.Sprintf("Connection to streaming source was interrupted.") + errMsg = "Connection to streaming source was interrupted." case 4001: - errMsg = fmt.Sprintf("Too many errors connecting to the provider. Streaming is canceled.") + errMsg = "Too many errors connecting to the provider. Streaming is canceled." case 4002: - errMsg = fmt.Sprintf("New URL for the redirect to the streaming server is missing") + errMsg = "New URL for the redirect to the streaming server is missing" case 4003: - errMsg = fmt.Sprintf("Server sends an incompatible content-type") + errMsg = "Server sends an incompatible content-type" case 4004: - errMsg = fmt.Sprintf("This error message comes from the provider") + errMsg = "This error message comes from the provider" case 4005: - errMsg = fmt.Sprintf("Temporary buffer files could not be deleted") + errMsg = "Temporary buffer files could not be deleted" case 4006: - errMsg = fmt.Sprintf("Server connection timeout") + errMsg = "Server connection timeout" + case 4007: + errMsg = "Old temporary buffer file could not be deleted" - // Buffer (M3U8) + // Buffer (M3U8 case 4050: - errMsg = fmt.Sprintf("Invalid M3U8 file") + errMsg = "Invalid M3U8 file" case 4051: - errMsg = fmt.Sprintf("#EXTM3U header is missing") + errMsg = "#EXTM3U header is missing" // Caching case 4100: - errMsg = fmt.Sprintf("Unknown content type for downloaded image") + errMsg = "Unknown content type for downloaded image" case 4101: - errMsg = fmt.Sprintf("Invalid URL, original URL is used for this image") + errMsg = "Invalid URL, original URL is used for this image" // API case 5000: - errMsg = fmt.Sprintf("Invalid API command") + errMsg = "Invalid API command" // Update Server case 6001: - errMsg = fmt.Sprintf("Ivalid key") + errMsg = "Ivalid key" case 6002: - errMsg = fmt.Sprintf("Update failed") + errMsg = "Update failed" case 6003: - errMsg = fmt.Sprintf("Update server not available") + errMsg = "Update server not available" case 6004: - errMsg = fmt.Sprintf("xTeVe update available") + errMsg = "xTeVe update available" + + // Certificates + case 7000: + errMsg = "Can not generate a certificate" default: errMsg = fmt.Sprintf("Unknown error / warning (%d)", errCode) @@ -392,6 +407,17 @@ func getErrMsg(errCode int) (errMsg string) { return errMsg } +func sendAlert(text string) { + + select { + case webAlerts <- text: + // + default: + err := fmt.Errorf("client alert buffer is full, dropping the message: %v", text) + ShowError(err, 0) + } +} + func addNotification(notification Notification) (err error) { var i int diff --git a/src/ssdp.go b/src/ssdp.go index 63ce77c..9fc6074 100644 --- a/src/ssdp.go +++ b/src/ssdp.go @@ -1,72 +1,72 @@ package src import ( - "fmt" - "log" - "os" - "os/signal" - "time" + "fmt" + "log" + "os" + "os/signal" + "time" - "github.com/koron/go-ssdp" + "github.com/koron/go-ssdp" ) // SSDP : SSPD / DLNA Server func SSDP() (err error) { - if Settings.SSDP == false || System.Flag.Info == true { - return - } + if !Settings.SSDP || System.Flag.Info { + return + } - showInfo(fmt.Sprintf("SSDP / DLNA:%t", Settings.SSDP)) + showInfo(fmt.Sprintf("SSDP / DLNA:%t", Settings.SSDP)) - quit := make(chan os.Signal, 1) - signal.Notify(quit, os.Interrupt) + quit := make(chan os.Signal, 1) + signal.Notify(quit, os.Interrupt) - ad, err := ssdp.Advertise( - fmt.Sprintf("upnp:rootdevice"), // send as "ST" - fmt.Sprintf("uuid:%s::upnp:rootdevice", System.DeviceID), // send as "USN" - fmt.Sprintf("%s/device.xml", System.URLBase), // send as "LOCATION" - System.AppName, // send as "SERVER" - 1800) // send as "maxAge" in "CACHE-CONTROL" + ad, err := ssdp.Advertise( + "upnp:rootdevice", // send as "ST" + fmt.Sprintf("uuid:%s::upnp:rootdevice", System.DeviceID), // send as "USN" + fmt.Sprintf("%s/device.xml", System.URLBase), // send as "LOCATION" + System.AppName, // send as "SERVER" + 1800) // send as "maxAge" in "CACHE-CONTROL" - if err != nil { - return - } + if err != nil { + return + } - // Debug SSDP - if System.Flag.Debug == 3 { - ssdp.Logger = log.New(os.Stderr, "[SSDP] ", log.LstdFlags) - } + // Debug SSDP + if System.Flag.Debug == 3 { + ssdp.Logger = log.New(os.Stderr, "[SSDP] ", log.LstdFlags) + } - go func(adv *ssdp.Advertiser) { + go func(adv *ssdp.Advertiser) { - aliveTick := time.Tick(300 * time.Second) + aliveTick := time.NewTicker(300 * time.Second) - loop: - for { + loop: + for { - select { + select { - case <-aliveTick: - err = adv.Alive() - if err != nil { - ShowError(err, 0) - adv.Bye() - adv.Close() - break loop - } + case <-aliveTick.C: + err = adv.Alive() + if err != nil { + ShowError(err, 0) + adv.Bye() + adv.Close() + break loop + } - case <-quit: - adv.Bye() - adv.Close() - os.Exit(0) - break loop + case <-quit: + adv.Bye() + adv.Close() + os.Exit(0) + break loop - } + } - } + } - }(ad) + }(ad) - return + return } diff --git a/src/struct-buffer.go b/src/struct-buffer.go index b56e2d5..6c4cf5f 100644 --- a/src/struct-buffer.go +++ b/src/struct-buffer.go @@ -2,7 +2,7 @@ package src import "time" -// Playlist : Enthält allen Playlistinformationen, die der Buffer benötigr +// Playlist : Contains all Playlist Information that the Buffer needs type Playlist struct { Folder string PlaylistID string @@ -13,12 +13,12 @@ type Playlist struct { Streams map[int]ThisStream } -// ThisClient : Clientinfos +// ThisClient : Client Information type ThisClient struct { Connection int } -// ThisStream : Enthält Informationen zu dem abzuspielenden Stream einer Playlist +// ThisStream : Contains Information about the Playlist Stream to be played type ThisStream struct { ChannelName string Error string @@ -32,7 +32,7 @@ type ThisStream struct { Segment []Segment - // Serverinformationen + // Server information Location string URLFile string URLHost string @@ -41,7 +41,7 @@ type ThisStream struct { URLScheme string URLStreamingServer string - // Wird nur für HLS / M3U8 verwendet + // Is only used for HLS / M3U8 Body string Difference float64 Duration float64 @@ -62,11 +62,11 @@ type ThisStream struct { DynamicStream map[int]DynamicStream - // Lokale Temp Datein + // Local Temp Files OldSegments []string } -// Segment : URL Segmente (HLS / M3U8) +// Segment : URL Segments (HLS / M3U8) type Segment struct { Duration float64 Info bool @@ -85,7 +85,7 @@ type Segment struct { } } -// DynamicStream : Streaminformationen bei dynamischer Bandbreite +// DynamicStream : Stream Information with dynamic Bandwidth type DynamicStream struct { AverageBandwidth int Bandwidth int @@ -94,13 +94,13 @@ type DynamicStream struct { URL string } -// ClientConnection : Client Verbindungen +// ClientConnection : Client Connections type ClientConnection struct { Connection int Error error } -// BandwidthCalculation : Bandbreitenberechnung für den Stream +// BandwidthCalculation : Bandwidth Calculation for the Stream type BandwidthCalculation struct { NetworkBandwidth int Size int diff --git a/src/struct-hdhr.go b/src/struct-hdhr.go index f0376ce..7a361fe 100644 --- a/src/struct-hdhr.go +++ b/src/struct-hdhr.go @@ -53,7 +53,7 @@ type Lineup []interface { //URL string `json:"URL"` } -// LineupStream : HDHR einzelner Stream im Lineup +// LineupStream : HDHR single Stream in the Lineup type LineupStream struct { GuideName string `json:"GuideName"` GuideNumber string `json:"GuideNumber"` diff --git a/src/struct-system.go b/src/struct-system.go index 595f4d2..630dd4c 100644 --- a/src/struct-system.go +++ b/src/struct-system.go @@ -1,8 +1,11 @@ package src -import "xteve/src/internal/imgcache" +import ( + "net" + "xteve/src/internal/imgcache" +) -// SystemStruct : Beinhaltet alle Systeminformationen +// SystemStruct : Contains all System Information type SystemStruct struct { Addresses struct { DVR string @@ -10,20 +13,19 @@ type SystemStruct struct { XML string } - APIVersion string - AppName string - ARCH string - BackgroundProcess bool - Branch string - Build string - Compatibility string - ConfigurationWizard bool - DBVersion string - Dev bool - DeviceID string - Domain string - PlexChannelLimit int - UnfilteredChannelLimit int + APIVersion string + AppName string + ARCH string + BackgroundProcess bool + Branch string + Build string + Compatibility string + ConfigurationWizard bool + DBVersion string + Dev bool + DeviceID string + Domain string + PlexChannelLimit int FFmpeg struct { DefaultOptions string @@ -36,13 +38,15 @@ type SystemStruct struct { } File struct { - Authentication string - M3U string - PMS string - Settings string - URLS string - XEPG string - XML string + Authentication string + M3U string + PMS string + ServerCert string + ServerCertPrivKey string + Settings string + URLS string + XEPG string + XML string } Compressed struct { @@ -61,6 +65,7 @@ type SystemStruct struct { Folder struct { Backup string Cache string + Certificates string Config string Data string ImagesCache string @@ -70,10 +75,11 @@ type SystemStruct struct { Hostname string ImageCachingInProgress int - IPAddress string - IPAddressesList []string - IPAddressesV4 []string - IPAddressesV6 []string + IPAddressesList []string // Every IP address available (IPv4 + IPv6) + IPAddressesV4 []string // Every IPv4 address available in string format + IPAddressesV4Host []string // Every IPv4 address available except loopback and link-local + IPAddressesV4Raw []net.IP // Every IPv4 address available in net.IP format + IPAddressesV6 []string // Every IPv6 address available Name string OS string ScanInProgress int @@ -109,13 +115,13 @@ type SystemStruct struct { } } -// GitStruct : Updateinformationen von GitHub +// GitStruct : Update information from GitHub type GitStruct struct { Filename string `json:"filename"` Version string `json:"version"` } -// DataStruct : Alle Daten werden hier abgelegt. (Lineup, XMLTV) +// DataStruct : All Data is stored here. (Lineup, XMLTV) type DataStruct struct { Cache struct { Images *imgcache.Cache @@ -165,114 +171,130 @@ type DataStruct struct { } } -// Filter : Wird für die Filterregeln verwendet +// Filter : Used for the Filter Rules type Filter struct { - CaseSensitive bool - Rule string - Type string + CaseSensitive bool + PreserveMapping bool + Rule string + Type string + StartingChannel string } -// XEPGChannelStruct : XEPG Struktur +// XEPGChannelStruct : XEPG Structure type XEPGChannelStruct struct { - FileM3UID string `json:"_file.m3u.id,required"` - FileM3UName string `json:"_file.m3u.name,required"` - FileM3UPath string `json:"_file.m3u.path,required"` - GroupTitle string `json:"group-title,required"` - Name string `json:"name,required"` - TvgID string `json:"tvg-id,required"` - TvgLogo string `json:"tvg-logo,required"` - TvgName string `json:"tvg-name,required"` - URL string `json:"url,required"` - UUIDKey string `json:"_uuid.key,required"` - UUIDValue string `json:"_uuid.value,omitempty"` - Values string `json:"_values,required"` - XActive bool `json:"x-active,required"` - XCategory string `json:"x-category,required"` - XChannelID string `json:"x-channelID,required"` - XEPG string `json:"x-epg,required"` - XGroupTitle string `json:"x-group-title,required"` - XMapping string `json:"x-mapping,required"` - XmltvFile string `json:"x-xmltv-file,required"` - XName string `json:"x-name,required"` - XUpdateChannelIcon bool `json:"x-update-channel-icon,required"` - XUpdateChannelName bool `json:"x-update-channel-name,required"` - XDescription string `json:"x-description,required"` + FileM3UID string `json:"_file.m3u.id"` + FileM3UName string `json:"_file.m3u.name"` + FileM3UPath string `json:"_file.m3u.path"` + GroupTitle string `json:"group-title"` + Name string `json:"name"` + TvgID string `json:"tvg-id"` + TvgLogo string `json:"tvg-logo"` + TvgName string `json:"tvg-name"` + TvgShift string `json:"tvg-shift"` + UpdateChannelNameRegex string `json:"update-channel-name-regex"` + UpdateChannelNameByGroupRegex string `json:"update-channel-name-by-group-regex"` + URL string `json:"url"` + UUIDKey string `json:"_uuid.key"` + UUIDValue string `json:"_uuid.value,omitempty"` + Values string `json:"_values"` + XActive bool `json:"x-active"` + XCategory string `json:"x-category"` + XChannelID string `json:"x-channelID"` + XEPG string `json:"x-epg"` + XGroupTitle string `json:"x-group-title"` + XMapping string `json:"x-mapping"` + XmltvFile string `json:"x-xmltv-file"` + XName string `json:"x-name"` + XUpdateChannelIcon bool `json:"x-update-channel-icon"` + XUpdateChannelName bool `json:"x-update-channel-name"` + XUpdateChannelGroup bool `json:"x-update-channel-group"` + XDescription string `json:"x-description"` + XTimeshift string `json:"x-timeshift"` } -// M3UChannelStructXEPG : M3U Struktur für XEPG +// M3UChannelStructXEPG : M3U Structure for XEPG type M3UChannelStructXEPG struct { - FileM3UID string `json:"_file.m3u.id,required"` - FileM3UName string `json:"_file.m3u.name,required"` - FileM3UPath string `json:"_file.m3u.path,required"` - GroupTitle string `json:"group-title,required"` - Name string `json:"name,required"` - TvgID string `json:"tvg-id,required"` - TvgLogo string `json:"tvg-logo,required"` - TvgName string `json:"tvg-name,required"` - URL string `json:"url,required"` - UUIDKey string `json:"_uuid.key,required"` - UUIDValue string `json:"_uuid.value,required"` - Values string `json:"_values,required"` + FileM3UID string `json:"_file.m3u.id"` + FileM3UName string `json:"_file.m3u.name"` + FileM3UPath string `json:"_file.m3u.path"` + GroupTitle string `json:"group-title"` + Name string `json:"name"` + TvgID string `json:"tvg-id"` + TvgLogo string `json:"tvg-logo"` + TvgName string `json:"tvg-name"` + TvgShift string `json:"tvg-shift"` + URL string `json:"url"` + UUIDKey string `json:"_uuid.key"` + UUIDValue string `json:"_uuid.value"` + Values string `json:"_values"` + PreserveMapping string `json:"_preserve-mapping"` + StartingChannel string `json:"_starting-channel"` } -// FilterStruct : Filter Struktur +// FilterStruct : Filter Structure type FilterStruct struct { - Active bool `json:"active,required"` - CaseSensitive bool `json:"caseSensitive,required"` - Description string `json:"description,required"` - Exclude string `json:"exclude,required"` - Filter string `json:"filter,required"` - Include string `json:"include,required"` - Name string `json:"name,required"` - Rule string `json:"rule,omitempty"` - Type string `json:"type,required"` + Active bool `json:"active"` + CaseSensitive bool `json:"caseSensitive"` + PreserveMapping bool `json:"preserveMapping"` + Description string `json:"description"` + Exclude string `json:"exclude"` + Filter string `json:"filter"` + Include string `json:"include"` + Name string `json:"name"` + Rule string `json:"rule,omitempty"` + Type string `json:"type"` + StartingChannel string `json:"startingChannel"` } -// StreamingURLS : Informationen zu allen streaming URL's +// StreamingURLS : Information on all Streaming URL's type StreamingURLS struct { - Streams map[string]StreamInfo `json:"channels,required"` + Streams map[string]StreamInfo `json:"channels"` } -// StreamInfo : Informationen zum Kanal für die streaming URL +// StreamInfo : Information about the Channel for the Streaming URL type StreamInfo struct { - ChannelNumber string `json:"channelNumber,required"` - Name string `json:"name,required"` - PlaylistID string `json:"playlistID,required"` - URL string `json:"url,required"` - URLid string `json:"urlID,required"` + ChannelNumber string `json:"channelNumber"` + Name string `json:"name"` + PlaylistID string `json:"playlistID"` + URL string `json:"url"` + URLid string `json:"urlID"` } -// Notification : Notifikationen im Webinterface +// Notification : Notifications in the Web Interface type Notification struct { - Headline string `json:"headline,required"` - Message string `json:"message,required"` - New bool `json:"new,required"` - Time string `json:"time,required"` - Type string `json:"type,required"` + Headline string `json:"headline"` + Message string `json:"message"` + New bool `json:"new"` + Time string `json:"time"` + Type string `json:"type"` } -// SettingsStruct : Inhalt der settings.json +// SettingsStruct : Content of settings.json type SettingsStruct struct { - API bool `json:"api"` - AuthenticationAPI bool `json:"authentication.api"` - AuthenticationM3U bool `json:"authentication.m3u"` - AuthenticationPMS bool `json:"authentication.pms"` - AuthenticationWEB bool `json:"authentication.web"` - AuthenticationXML bool `json:"authentication.xml"` - BackupKeep int `json:"backup.keep"` - BackupPath string `json:"backup.path"` - Branch string `json:"git.branch,omitempty"` - Buffer string `json:"buffer"` - BufferSize int `json:"buffer.size.kb"` - BufferTimeout float64 `json:"buffer.timeout"` - CacheImages bool `json:"cache.images"` - EpgSource string `json:"epgSource"` - FFmpegOptions string `json:"ffmpeg.options"` - FFmpegPath string `json:"ffmpeg.path"` - VLCOptions string `json:"vlc.options"` - VLCPath string `json:"vlc.path"` - FileM3U []string `json:"file,omitempty"` // Beim Wizard wird die M3U in ein Slice gespeichert - FileXMLTV []string `json:"xmltv,omitempty"` // Altes Speichersystem der Provider XML Datei Slice (Wird für die Umwandlung auf das neue benötigt) + API bool `json:"api"` + AuthenticationAPI bool `json:"authentication.api"` + AuthenticationM3U bool `json:"authentication.m3u"` + AuthenticationPMS bool `json:"authentication.pms"` + AuthenticationWEB bool `json:"authentication.web"` + AuthenticationXML bool `json:"authentication.xml"` + BackupKeep int `json:"backup.keep"` + BackupPath string `json:"backup.path"` + Branch string `json:"git.branch,omitempty"` + Buffer string `json:"buffer"` + BufferSize int `json:"buffer.size.kb"` + BufferTimeout float64 `json:"buffer.timeout"` + CacheImages bool `json:"cache.images"` + ClearXMLTVCache bool `json:"clearXMLTVCache"` + DefaultMissingEPG string `json:"defaultMissingEPG"` + DisallowURLDuplicates bool `json:"disallowURLDuplicates"` + EnableMappedChannels bool `json:"enableMappedChannels"` + EpgSource string `json:"epgSource"` + FFmpegOptions string `json:"ffmpeg.options"` + FFmpegPath string `json:"ffmpeg.path"` + VLCOptions string `json:"vlc.options"` + VLCPath string `json:"vlc.path"` + FileM3U []string `json:"file,omitempty"` // In the Wizard, the M3U is saved in a Slice + FileXMLTV []string `json:"xmltv,omitempty"` // Old Storage System of the provider XML File Slice (Required for the conversion to the new one) Files struct { HDHR map[string]interface{} `json:"hdhr"` @@ -282,6 +304,8 @@ type SettingsStruct struct { FilesUpdate bool `json:"files.update"` Filter map[int64]interface{} `json:"filter"` + HostIP string `json:"hostIP"` // IP chosen in web client. Used to form m3u and xml files. + HostName string `json:"hostName"` // Hostname chosen in web client. Used to form m3u and xml files. Key string `json:"key,omitempty"` Language string `json:"language"` LogEntriesRAM int `json:"log.entries.ram"` @@ -289,7 +313,9 @@ type SettingsStruct struct { MappingFirstChannel float64 `json:"mapping.first.channel"` Port string `json:"port"` SSDP bool `json:"ssdp"` + StoreBufferInRAM bool `json:"storeBufferInRAM"` TempPath string `json:"temp.path"` + TLSMode bool `json:"tlsMode"` Tuner int `json:"tuner"` Update []string `json:"update"` UpdateURL string `json:"update.url,omitempty"` @@ -301,7 +327,7 @@ type SettingsStruct struct { XteveAutoUpdate bool `json:"xteveAutoUpdate"` } -// LanguageUI : Sprache für das WebUI +// LanguageUI : Language for the WebUI type LanguageUI struct { Login struct { Failed string diff --git a/src/struct-webserver.go b/src/struct-webserver.go index e87abcb..0640563 100644 --- a/src/struct-webserver.go +++ b/src/struct-webserver.go @@ -1,11 +1,11 @@ package src -// RequestStruct : Anfragen über die Websocket Schnittstelle +// RequestStruct : Requests via the Websocket Interface type RequestStruct struct { - // Befehle an xTeVe - Cmd string `json:"cmd,required"` + // Commands to xTeVe + Cmd string `json:"cmd"` - // Benutzer + // User DeleteUser bool `json:"deleteUser,omitempty"` UserData map[string]interface{} `json:"userData,omitempty"` @@ -15,7 +15,7 @@ type RequestStruct struct { // Restore Base64 string `json:"base64,omitempty"` - // Neue Werte für die Einstellungen (settings.json) + // New Values for the Settings (settings.json) Settings struct { API *bool `json:"api,omitempty"` AuthenticationAPI *bool `json:"authentication.api,omitempty"` @@ -26,16 +26,23 @@ type RequestStruct struct { BackupKeep *int `json:"backup.keep,omitempty"` BackupPath *string `json:"backup.path,omitempty"` Buffer *string `json:"buffer,omitempty"` - BufferSize *int `json:"buffer.size.kb, omitempty"` + BufferSize *int `json:"buffer.size.kb,omitempty"` BufferTimeout *float64 `json:"buffer.timeout,omitempty"` CacheImages *bool `json:"cache.images,omitempty"` + ClearXMLTVCache *bool `json:"clearXMLTVCache,omitempty"` + DefaultMissingEPG *string `json:"defaultMissingEPG,omitempty"` + DisallowURLDuplicates *bool `json:"disallowURLDuplicates,omitempty"` + EnableMappedChannels *bool `json:"enableMappedChannels,omitempty"` EpgSource *string `json:"epgSource,omitempty"` FFmpegOptions *string `json:"ffmpeg.options,omitempty"` FFmpegPath *string `json:"ffmpeg.path,omitempty"` VLCOptions *string `json:"vlc.options,omitempty"` VLCPath *string `json:"vlc.path,omitempty"` FilesUpdate *bool `json:"files.update,omitempty"` + HostIP *string `json:"hostIP,omitempty"` // IP chosen in web client. Used to form m3u and xml files. + HostName *string `json:"hostName"` // Hostname chosen in web client. Used to form m3u and xml files. TempPath *string `json:"temp.path,omitempty"` + TLSMode *bool `json:"tlsMode,omitempty"` Tuner *int `json:"tuner,omitempty"` UDPxy *string `json:"udpxy,omitempty"` Update *[]string `json:"update,omitempty"` @@ -44,6 +51,7 @@ type RequestStruct struct { XteveAutoUpdate *bool `json:"xteveAutoUpdate,omitempty"` SchemeM3U *string `json:"scheme.m3u,omitempty"` SchemeXML *string `json:"scheme.xml,omitempty"` + StoreBufferInRAM *bool `json:"storeBufferInRAM,omitempty"` } `json:"settings,omitempty"` // Upload Logo @@ -52,7 +60,7 @@ type RequestStruct struct { // Filter Filter map[int64]interface{} `json:"filter,omitempty"` - // Dateien (M3U, HDHR, XMLTV) + // Files (M3U, HDHR, XMLTV) Files struct { HDHR map[string]interface{} `json:"hdhr,omitempty"` M3U map[string]interface{} `json:"m3u,omitempty"` @@ -68,7 +76,7 @@ type RequestStruct struct { } `json:"wizard,omitempty"` } -// ResponseStruct : Antworten an den Client (WEB) +// ResponseStruct : Responses to the Client (WEB) type ResponseStruct struct { ClientInfo struct { ARCH string `json:"arch"` @@ -76,51 +84,52 @@ type ResponseStruct struct { DVR string `json:"DVR"` EpgSource string `json:"epgSource"` Errors int `json:"errors"` - M3U string `json:"m3u-url,required"` + M3U string `json:"m3u-url"` OS string `json:"os"` Streams string `json:"streams"` UUID string `json:"uuid"` Version string `json:"version"` Warnings int `json:"warnings"` XEPGCount int64 `json:"xepg"` - XML string `json:"xepg-url,required"` + XML string `json:"xepg-url"` } `json:"clientInfo,omitempty"` Data struct { Playlist struct { M3U struct { Groups struct { - Text []string `json:"text,required"` - Value []string `json:"value,required"` - } `json:"groups,required"` - } `json:"m3u,required"` - } `json:"playlist,required"` + Text []string `json:"text"` + Value []string `json:"value"` + } `json:"groups"` + } `json:"m3u"` + } `json:"playlist"` StreamPreviewUI struct { - Active []string `json:"activeStreams,required"` - Inactive []string `json:"inactiveStreams,required"` + Active []string `json:"activeStreams"` + Inactive []string `json:"inactiveStreams"` } - } `json:"data,required"` + } `json:"data"` Alert string `json:"alert,omitempty"` - ConfigurationWizard bool `json:"configurationWizard,required"` + ConfigurationWizard bool `json:"configurationWizard"` Error string `json:"err,omitempty"` - Log WebScreenLogStruct `json:"log,required"` + IPAddressesV4Host []string `json:"ipAddressesV4Host"` // Every IPv4 address to display in web client + Log WebScreenLogStruct `json:"log"` LogoURL string `json:"logoURL,omitempty"` OpenLink string `json:"openLink,omitempty"` OpenMenu string `json:"openMenu,omitempty"` Reload bool `json:"reload,omitempty"` - Settings SettingsStruct `json:"settings,required"` - Status bool `json:"status,required"` + Settings SettingsStruct `json:"settings"` + Status bool `json:"status"` Token string `json:"token,omitempty"` Users map[string]interface{} `json:"users,omitempty"` Wizard int `json:"wizard,omitempty"` - XEPG map[string]interface{} `json:"xepg,required"` + XEPG map[string]interface{} `json:"xepg"` Notification map[string]Notification `json:"notification,omitempty"` } -// APIRequestStruct : Anfrage über die API Schnittstelle +// APIRequestStruct : Request via the API interface type APIRequestStruct struct { Cmd string `json:"cmd"` Password string `json:"password"` @@ -128,15 +137,17 @@ type APIRequestStruct struct { Username string `json:"username"` } -// APIResponseStruct : Antwort an den Client (API) +// APIResponseStruct : Response to the Client (API) type APIResponseStruct struct { EpgSource string `json:"epg.source,omitempty"` Error string `json:"err,omitempty"` - Status bool `json:"status,required"` + Status bool `json:"status"` StreamsActive int64 `json:"streams.active,omitempty"` StreamsAll int64 `json:"streams.all,omitempty"` StreamsXepg int64 `json:"streams.xepg,omitempty"` Token string `json:"token,omitempty"` + TunerActive int64 `json:"tuners.active,omitempty"` + TunerAll int64 `json:"tuners.all,omitempty"` URLDvr string `json:"url.dvr,omitempty"` URLM3U string `json:"url.m3u,omitempty"` URLXepg string `json:"url.xepg,omitempty"` @@ -144,9 +155,9 @@ type APIResponseStruct struct { VersionXteve string `json:"version.xteve,omitempty"` } -// WebScreenLogStruct : Logs werden im RAM gespeichert und für das Webinterface bereitgestellt +// WebScreenLogStruct : Logs are saved in RAM and made available for the Web Interface type WebScreenLogStruct struct { - Errors int `json:"errors,required"` - Log []string `json:"log,required"` - Warnings int `json:"warnings,required"` + Errors int `json:"errors"` + Log []string `json:"log"` + Warnings int `json:"warnings"` } diff --git a/src/struct-xml.go b/src/struct-xml.go index c79f385..da9faa9 100644 --- a/src/struct-xml.go +++ b/src/struct-xml.go @@ -2,7 +2,7 @@ package src import "encoding/xml" -// XMLTV : XMLTV Datei +// XMLTV : XMLTV File type XMLTV struct { Generator string `xml:"generator-info-name,attr"` Source string `xml:"source-info-name,attr"` @@ -12,24 +12,24 @@ type XMLTV struct { Program []*Program `xml:"programme"` } -// Channel : Kanäle +// Channel : Channels type Channel struct { - ID string `xml:"id,attr"` - DisplayName []DisplayName `xml:"display-name"` - Icon Icon `xml:"icon"` + ID string `xml:"id,attr"` + DisplayNames []DisplayName `xml:"display-name"` + Icon Icon `xml:"icon"` } -// DisplayName : Kanalname +// DisplayName : Channel Name type DisplayName struct { Value string `xml:",chardata"` } -// Icon : Senderlogo +// Icon : Station Logo type Icon struct { Src string `xml:"src,attr"` } -// Program : Programme +// Program : Programs type Program struct { Channel string `xml:"channel,attr"` Start string `xml:"start,attr"` @@ -54,61 +54,61 @@ type Program struct { Premiere *Live `xml:"premiere"` } -// Title : Programmtitel +// Title : Program Title type Title struct { Lang string `xml:"lang,attr"` Value string `xml:",chardata"` } -// SubTitle : Kurzbeschreibung +// SubTitle : Brief Description type SubTitle struct { Lang string `xml:"lang,attr"` Value string `xml:",chardata"` } -//Desc : Programmbeschreibung +//Desc : Program Description type Desc struct { Lang string `xml:"lang,attr"` Value string `xml:",chardata"` } -// Category : Kategorien +// Category : Categories type Category struct { Lang string `xml:"lang,attr"` Value string `xml:",chardata"` } -// Rating : Bewertung +// Rating : Rating type Rating struct { System string `xml:"system,attr"` Value string `xml:"value"` Icon []Icon `xml:"icon"` } -// StarRating : Bewertung / Kritiken +// StarRating : Rating / Reviews type StarRating struct { Value string `xml:"value"` System string `xml:"system,attr"` } -// Language : Sprachen +// Language : Langueages type Language struct { Value string `xml:",chardata"` } -// Country : Länder +// Country : Countries type Country struct { Lang string `xml:"lang,attr"` Value string `xml:",chardata"` } -// EpisodeNum : Episodennummerierung +// EpisodeNum : Episode Numbering type EpisodeNum struct { System string `xml:"system,attr"` Value string `xml:",chardata"` } -// Poster : Programmposter / Cover +// Poster : Program Poster / Cover type Poster struct { Height string `xml:"height,attr"` Src string `xml:"src,attr"` @@ -151,7 +151,7 @@ type Producer struct { Value string `xml:",chardata"` } -// Video : Video Metadaten +// Video : Video Metadata type Video struct { Aspect string `xml:"aspect,omitempty"` Colour string `xml:"colour,omitempty"` @@ -159,17 +159,17 @@ type Video struct { Quality string `xml:"quality,omitempty"` } -// PreviouslyShown : Widerholung bzw. Erstausstrahlung +// PreviouslyShown : Repetition or first Broadcast type PreviouslyShown struct { Start string `xml:"start,attr"` } -// New : Sendung als neu deklarieren +// New : Declare the Broadcast as new type New struct { Value string `xml:",chardata"` } -// Live : Sendung als Liveübertragung deklarieren +// Live : Declare the Broadcast as a Live Broadcast type Live struct { Value string `xml:",chardata"` } diff --git a/src/system.go b/src/system.go index 82be0e1..f8b6c37 100644 --- a/src/system.go +++ b/src/system.go @@ -4,16 +4,15 @@ import ( "encoding/json" "errors" "fmt" - "os" "reflect" "strings" "time" ) -// Entwicklerinfos anzeigen +// Show Developer Information func showDevInfo() { - if System.Dev == true { + if System.Dev { fmt.Print("\033[31m") fmt.Println("* * * * * D E V M O D E * * * * *") @@ -25,10 +24,9 @@ func showDevInfo() { } - return } -// Alle Systemordner erstellen +// Create all System Folders func createSystemFolders() (err error) { e := reflect.ValueOf(&System.Folder).Elem() @@ -48,7 +46,7 @@ func createSystemFolders() (err error) { return } -// Alle Systemdateien erstellen +// Create all System Files func createSystemFiles() (err error) { var debug string @@ -58,7 +56,7 @@ func createSystemFiles() (err error) { err = checkFile(filename) if err != nil { - // Datei existiert nicht, wird jetzt erstellt + // File does not exist, will be created now err = saveMapToJSONFile(filename, make(map[string]interface{})) if err != nil { return @@ -89,7 +87,7 @@ func createSystemFiles() (err error) { return } -// Einstellungen laden und default Werte setzen (xTeVe) +// Load Settings and set Default Values (xTeVe) func loadSettings() (settings SettingsStruct, err error) { settingsMap, err := loadJSONFileToMap(System.File.Settings) @@ -97,7 +95,7 @@ func loadSettings() (settings SettingsStruct, err error) { return } - // Deafult Werte setzten + // Set Deafult Values var defaults = make(map[string]interface{}) var dataMap = make(map[string]interface{}) @@ -113,34 +111,42 @@ func loadSettings() (settings SettingsStruct, err error) { defaults["authentication.xml"] = false defaults["backup.keep"] = 10 defaults["backup.path"] = System.Folder.Backup - defaults["buffer"] = "-" defaults["buffer.size.kb"] = 1024 defaults["buffer.timeout"] = 500 + defaults["buffer"] = "-" defaults["cache.images"] = false + defaults["clearXMLTVCache"] = false + defaults["defaultMissingEPG"] = "-" + defaults["disallowURLDuplicates"] = false + defaults["enableMappedChannels"] = false defaults["epgSource"] = "PMS" defaults["ffmpeg.options"] = System.FFmpeg.DefaultOptions - defaults["vlc.options"] = System.VLC.DefaultOptions - defaults["files"] = dataMap defaults["files.update"] = true + defaults["files"] = dataMap defaults["filter"] = make(map[string]interface{}) defaults["git.branch"] = System.Branch + defaults["hostIP"] = "" // Will be set in resolveHostIP() + defaults["hostName"] = "" defaults["language"] = "en" defaults["log.entries.ram"] = 500 - defaults["mapping.first.channel"] = 1000 - defaults["xepg.replace.missing.images"] = true defaults["m3u8.adaptive.bandwidth.mbps"] = 10 + defaults["mapping.first.channel"] = 1000 defaults["port"] = "34400" defaults["ssdp"] = true + defaults["storeBufferInRAM"] = false + defaults["temp.path"] = System.Folder.Temp + defaults["tlsMode"] = false defaults["tuner"] = 1 + defaults["udpxy"] = "" defaults["update"] = []string{"0000"} defaults["user.agent"] = System.Name defaults["uuid"] = createUUID() - defaults["udpxy"] = "" defaults["version"] = System.DBVersion + defaults["vlc.options"] = System.VLC.DefaultOptions + defaults["xepg.replace.missing.images"] = true defaults["xteveAutoUpdate"] = true - defaults["temp.path"] = System.Folder.Temp - // Default Werte setzen + // Set Default Values for key, value := range defaults { if _, ok := settingsMap[key]; !ok { settingsMap[key] = value @@ -152,7 +158,7 @@ func loadSettings() (settings SettingsStruct, err error) { return } - // Einstellungen von den Flags übernehmen + // Adopt the settings from the Flags if len(System.Flag.Port) > 0 { settings.Port = System.Flag.Port } @@ -170,11 +176,14 @@ func loadSettings() (settings SettingsStruct, err error) { settings.VLCPath = searchFileInOS("cvlc") } - settings.Version = System.DBVersion + // Initialze virutal filesystem for the Buffer + initBufferVFS(settings.StoreBufferInRAM) + + settings.TempPath = getValidTempDir(settings.TempPath) err = saveSettings(settings) - // Warung wenn FFmpeg nicht gefunden wurde + // Warning if FFmpeg was not found if len(Settings.FFmpegPath) == 0 && Settings.Buffer == "ffmpeg" { showWarning(2020) } @@ -186,7 +195,7 @@ func loadSettings() (settings SettingsStruct, err error) { return } -// Einstellungen speichern (xTeVe) +// Save Settings (xTeVe) func saveSettings(settings SettingsStruct) (err error) { if settings.BackupKeep == 0 { @@ -201,7 +210,11 @@ func saveSettings(settings SettingsStruct) (err error) { settings.BufferTimeout = 0 } - System.Folder.Temp = settings.TempPath + settings.UUID + string(os.PathSeparator) + if System.Dev { + Settings.UUID = "2019-01-DEV-xTeVe!" + } + + System.Folder.Temp = getValidTempDir(settings.TempPath + settings.UUID) err = writeByteToFile(System.File.Settings, []byte(mapToJSON(settings))) if err != nil { @@ -210,20 +223,24 @@ func saveSettings(settings SettingsStruct) (err error) { Settings = settings - if System.Dev == true { - Settings.UUID = "2019-01-DEV-xTeVe!" - } - setDeviceID() return } -// Zugriff über die Domain ermöglichen +// Enable access via the Domain func setGlobalDomain(domain string) { System.Domain = domain + if Settings.TLSMode { + System.ServerProtocol.API = "https" + System.ServerProtocol.DVR = "https" + System.ServerProtocol.M3U = "https" + System.ServerProtocol.WEB = "https" + System.ServerProtocol.XML = "https" + } + switch Settings.AuthenticationPMS { case true: System.Addresses.DVR = "username:password@" + System.Domain @@ -250,16 +267,15 @@ func setGlobalDomain(domain string) { System.Addresses.XML = getErrMsg(2106) } - return } -// UUID generieren +// Generate UUID func createUUID() (uuid string) { uuid = time.Now().Format("2006-01") + "-" + randomString(4) + "-" + randomString(6) return } -// Eindeutige Geräte ID für Plex generieren +// Generate Unique Device ID for Plex func setDeviceID() { var id = Settings.UUID @@ -272,10 +288,9 @@ func setDeviceID() { System.DeviceID = fmt.Sprintf("%s:%d", id, Settings.Tuner) } - return } -// Provider Streaming-URL zu xTeVe Streaming-URL konvertieren +// Convert Provider Streaming URL to xTeVe Streaming URL func createStreamingURL(streamingType, playlistID, channelNumber, channelName, url string) (streamingURL string, err error) { var streamInfo StreamInfo @@ -338,7 +353,7 @@ func getStreamInfo(urlID string) (streamInfo StreamInfo, err error) { streamInfo = s streamInfo.URL = strings.Trim(streamInfo.URL, "\r\n") } else { - err = errors.New("Streaming error") + err = errors.New("streaming error") } return diff --git a/src/toolchain.go b/src/toolchain.go index 19e7f3c..1750561 100644 --- a/src/toolchain.go +++ b/src/toolchain.go @@ -6,7 +6,9 @@ import ( "crypto/rand" "encoding/hex" "encoding/json" + "errors" "fmt" + "io/fs" "io/ioutil" "net" "os" @@ -16,18 +18,21 @@ import ( "runtime" "strings" "text/template" + + "github.com/avfs/avfs" + "github.com/samber/lo" ) // --- System Tools --- -// Prüft ob der Ordner existiert, falls nicht, wir der Ordner erstellt +// Checks whether the Folder exists, if not, the Folder is created func checkFolder(path string) (err error) { var debug string _, err = os.Stat(filepath.Dir(path)) if os.IsNotExist(err) { - // Ordner existiert nicht, wird jetzt erstellt + // Folder does not exist, will now be created err = os.MkdirAll(getPlatformPath(path), 0755) if err == nil { @@ -45,7 +50,45 @@ func checkFolder(path string) (err error) { return nil } -// Prüft ob die Datei im Dateisystem existiert +// checkVFSFolder : Checks whether the Folder exists in provided virtual filesystem, if not, the Folder is created +func checkVFSFolder(path string, vfs avfs.VFS) (err error) { + + var debug string + _, err = vfs.Stat(filepath.Dir(path)) + + if fsIsNotExistErr(err) { + // Folder does not exist, will now be created + + err = vfs.MkdirAll(getPlatformPath(path), 0755) + if err == nil { + + debug = fmt.Sprintf("Create virtual filesystem Folder:%s", path) + showDebug(debug, 1) + + } else { + return err + } + + return nil + } + + return nil +} + +// fsIsNotExistErr : Returns true whether the is known to report that a file or directory does not exist, +// including virtual file system errors +func fsIsNotExistErr(err error) bool { + if errors.Is(err, fs.ErrNotExist) || + errors.Is(err, avfs.ErrWinPathNotFound) || + errors.Is(err, avfs.ErrNoSuchFileOrDir) || + errors.Is(err, avfs.ErrWinFileNotFound) { + return true + } + + return false +} + +// Checks whether the File exists in the Filesystem func checkFile(filename string) (err error) { var file = getPlatformFile(filename) @@ -62,14 +105,23 @@ func checkFile(filename string) (err error) { switch mode := fi.Mode(); { case mode.IsDir(): err = fmt.Errorf("%s: %s", file, getErrMsg(1072)) - case mode.IsRegular(): - break + // case mode.IsRegular(): + // break } return } -// GetUserHomeDirectory : Benutzer Homer Verzeichnis +func allFilesExist(list ...string) bool { + for _, f := range list { + if err := checkFile(f); err != nil { + return false + } + } + return true +} + +// GetUserHomeDirectory : User Home Directory func GetUserHomeDirectory() (userHomeDirectory string) { usr, err := user.Current() @@ -92,7 +144,7 @@ func GetUserHomeDirectory() (userHomeDirectory string) { return } -// Prüft Dateiberechtigung +// Checks File Permissions func checkFilePermission(dir string) (err error) { var filename = dir + "permission.test" @@ -105,12 +157,46 @@ func checkFilePermission(dir string) (err error) { return } -// Ordnerpfad für das laufende OS generieren +// Generate folder path for the running OS func getPlatformPath(path string) string { return filepath.Dir(path) + string(os.PathSeparator) } -// Dateipfad für das laufende OS generieren +// getDefaultTempDir returns default temporary folder path + application name, e.g.: "/tmp/xteve/" or %Tmp%\xteve. +// +// Function assumes default OS temporary folder exists and writable. +func getDefaultTempDir() string { + return os.TempDir() + string(os.PathSeparator) + System.AppName + string(os.PathSeparator) +} + +// getValidTempDir returns standartized temporary folder with trailing path separator: +// +// Slashes will be replaced with OS specific ones and duplicated slashes removed. +// +// On Windows, "/tmp" will be replaced with expanded system environment variable %Tmp%. +func getValidTempDir(path string) string { + if runtime.GOOS == "windows" { + if strings.HasPrefix(path, "/tmp") { + path = strings.Replace(path, "/tmp", os.TempDir(), 1) + } + } + path = filepath.Clean(path) + path = path + string(os.PathSeparator) + + err := checkFolder(path) + if err == nil { + err = checkFilePermission(path) + } + + if err != nil { + ShowError(err, 1015) + path = getDefaultTempDir() + } + + return path +} + +// Generate File Path for the running OS func getPlatformFile(filename string) (osFilePath string) { path, file := filepath.Split(filename) @@ -120,18 +206,12 @@ func getPlatformFile(filename string) (osFilePath string) { return } -// Dateinamen aus dem Dateipfad ausgeben +// Output Filenames from the File Path func getFilenameFromPath(path string) (file string) { return filepath.Base(path) } -// Nicht mehr verwendete Systemdaten löschen -func removeOldSystemData() { - // Temporären Ordner löschen - os.RemoveAll(System.Folder.Temp) -} - -// Sucht eine Datei im OS +// Searches for a File in the OS func searchFileInOS(file string) (path string) { switch runtime.GOOS { @@ -198,14 +278,6 @@ func jsonToMap(content string) map[string]interface{} { return (tmpMap) } -func jsonToMapInt64(content string) map[int64]interface{} { - - var tmpMap = make(map[int64]interface{}) - json.Unmarshal([]byte(content), &tmpMap) - - return (tmpMap) -} - func jsonToInterface(content string) (tmpMap interface{}, err error) { err = json.Unmarshal([]byte(content), &tmpMap) @@ -233,6 +305,9 @@ func saveMapToJSONFile(file string, tmpMap interface{}) error { func loadJSONFileToMap(file string) (tmpMap map[string]interface{}, err error) { f, err := os.Open(getPlatformFile(file)) + if err != nil { + panic(err) + } defer f.Close() content, err := ioutil.ReadAll(f) @@ -250,6 +325,9 @@ func loadJSONFileToMap(file string) (tmpMap map[string]interface{}, err error) { func readByteFromFile(file string) (content []byte, err error) { f, err := os.Open(getPlatformFile(file)) + if err != nil { + panic(err) + } defer f.Close() content, err = ioutil.ReadAll(f) @@ -287,7 +365,7 @@ func readStringFromFile(file string) (str string, err error) { return } -// Netzwerk +// Network func resolveHostIP() (err error) { netInterfaceAddresses, err := net.InterfaceAddrs() @@ -307,9 +385,10 @@ func resolveHostIP() (err error) { if networkIP.IP.To4() != nil { System.IPAddressesV4 = append(System.IPAddressesV4, ip) + System.IPAddressesV4Raw = append(System.IPAddressesV4Raw, networkIP.IP) if !networkIP.IP.IsLoopback() && ip[0:7] != "169.254" { - System.IPAddress = ip + System.IPAddressesV4Host = append(System.IPAddressesV4Host, ip) } } else { @@ -320,17 +399,22 @@ func resolveHostIP() (err error) { } - if len(System.IPAddress) == 0 { + // If IP previously set in settings (including the default, empty) is not available anymore + if !lo.Contains(System.IPAddressesV4Host, Settings.HostIP) { + Settings.HostIP = System.IPAddressesV4Host[0] + } + + if len(Settings.HostIP) == 0 { switch len(System.IPAddressesV4) { case 0: if len(System.IPAddressesV6) > 0 { - System.IPAddress = System.IPAddressesV6[0] + Settings.HostIP = System.IPAddressesV6[0] } default: - System.IPAddress = System.IPAddressesV4[0] + Settings.HostIP = System.IPAddressesV4[0] } @@ -344,7 +428,7 @@ func resolveHostIP() (err error) { return } -// Sonstiges +// Miscellaneous func randomString(n int) string { const alphanum = "AB1CD2EF3GH4IJ5KL6MN7OP8QR9ST0UVWXYZ" @@ -374,39 +458,6 @@ func parseTemplate(content string, tmpMap map[string]interface{}) (result string return } -func indexOfString(element string, data []string) int { - - for k, v := range data { - if element == v { - return k - } - } - - return -1 -} - -func indexOfFloat64(element float64, data []float64) int { - - for k, v := range data { - if element == v { - return (k) - } - } - - return -1 -} - -func indexOfInt(element int, data []int) int { - - for k, v := range data { - if element == v { - return (k) - } - } - - return -1 -} - func getMD5(str string) string { md5Hasher := md5.New() diff --git a/src/update.go b/src/update.go index 2c13d92..cc72a31 100644 --- a/src/update.go +++ b/src/update.go @@ -12,10 +12,10 @@ import ( "reflect" ) -// BinaryUpdate : Binary Update Prozess. Git Branch master und beta wird von GitHub geladen. +// BinaryUpdate : Binary update process. Git Branch master and beta is loaded from GitHub. func BinaryUpdate() (err error) { - if System.GitHub.Update == false { + if !System.GitHub.Update { showWarning(2099) return } @@ -30,7 +30,7 @@ func BinaryUpdate() (err error) { switch System.Branch { - // Update von GitHub + // Update from GitHub case "master", "beta": var gitInfo = fmt.Sprintf("%s/%s/info.json?raw=true", System.Update.Git, System.Branch) @@ -58,7 +58,7 @@ func BinaryUpdate() (err error) { return err } - body, err = ioutil.ReadAll(resp.Body) + body, _ = ioutil.ReadAll(resp.Body) err = json.Unmarshal(body, &git) if err != nil { @@ -70,7 +70,7 @@ func BinaryUpdate() (err error) { updater.Response.Version = git.Version updater.Response.Filename = git.Filename - // Update vom eigenen Server + // Update from your own Server default: updater.URL = Settings.UpdateURL @@ -83,11 +83,11 @@ func BinaryUpdate() (err error) { showInfo("Update URL:" + updater.URL) fmt.Println("-----------------") - // Versionsinformationen vom Server laden + // Load version information from the Server err = up2date.GetVersion() if err != nil { - debug = fmt.Sprintf(err.Error()) + debug = err.Error() showDebug(debug, 1) return nil @@ -105,22 +105,22 @@ func BinaryUpdate() (err error) { var currentVersion = System.Version + "." + System.Build - // Versionsnummer überprüfen - if updater.Response.Version > currentVersion && updater.Response.Status == true { + // Check Version Number + if updater.Response.Version > currentVersion && updater.Response.Status { - if Settings.XteveAutoUpdate == true { - // Update durchführen + if Settings.XteveAutoUpdate { + // Perform update var fileType, url string showInfo(fmt.Sprintf("Update Available:Version: %s", updater.Response.Version)) switch System.Branch { - // Update von GitHub + // Update from GitHub case "master", "beta": - showInfo(fmt.Sprintf("Update Server:GitHub")) + showInfo("Update Server:GitHub") - // Update vom eigenen Server + // Update from your own Server default: showInfo(fmt.Sprintf("Update Server:%s", Settings.UpdateURL)) @@ -128,13 +128,13 @@ func BinaryUpdate() (err error) { showInfo(fmt.Sprintf("Start Update:Branch: %s", updater.Branch)) - // Neue Version als BIN Datei herunterladen + // Download the new version as a BIN File if len(updater.Response.UpdateBIN) > 0 { url = updater.Response.UpdateBIN fileType = "bin" } - // Neue Version als ZIP Datei herunterladen + // Download the new version as a ZIP File if len(updater.Response.UpdateZIP) > 0 { url = updater.Response.UpdateZIP fileType = "zip" @@ -150,7 +150,7 @@ func BinaryUpdate() (err error) { } } else { - // Hinweis ausgeben + // Display update exception showWarning(6004) } @@ -176,7 +176,7 @@ checkVersion: return } - // Letzte Kompatible Version (1.4.4) + // Latest Compatible Version (1.4.4) if settingsVersion < System.Compatibility { err = errors.New(getErrMsg(1013)) return @@ -185,13 +185,13 @@ checkVersion: switch settingsVersion { case "1.4.4": - // UUID Wert in xepg.json setzen + // Set UUID Value in xepg.json err = setValueForUUID() if err != nil { return } - // Neuer Filter (WebUI). Alte Filtereinstellungen werden konvertiert + // New filter (WebUI). Old Filter Settings are converted if oldFilter, ok := settingsMap["filter"].([]interface{}); ok { var newFilterMap = convertToNewFilter(oldFilter) settingsMap["filter"] = newFilterMap @@ -238,14 +238,42 @@ checkVersion: return } - case "2.1.0": - // Falls es in einem späteren Update Änderungen an der Datenbank gibt, geht es hier weiter + case "2.1.0", "2.1.1": + // Database verison <= 2.1.1 has broken XEPG mapping + + // Clear XEPG mapping + Data.XEPG.Channels = make(map[string]interface{}) + Data.XEPG.XEPGCount = 0 + Data.Cache.Streams = struct{ Active []string }{} + + err = saveMapToJSONFile(System.File.XEPG, Data.XEPG.Channels) + if err != nil { + ShowError(err, 000) + return err + } + + // Notify user + showWarning(2022) + sendAlert(getErrMsg(2022)) + + // Update database version + settingsMap["version"] = "2.2.0" + + err = saveMapToJSONFile(System.File.Settings, settingsMap) + if err != nil { + return + } + + goto checkVersion + + case "2.2.0", "2.2.1", "2.2.2", "2.2.3", "2.3.0": + // If there are changes to the Database in a later update, continue here break } } else { - // settings.json ist zu alt (älter als Version 1.4.4) + // settings.json is too old (older than Version 1.4.4) err = errors.New(getErrMsg(1013)) } @@ -281,7 +309,7 @@ func convertToNewFilter(oldFilter []interface{}) (newFilterMap map[int]interface func setValueForUUID() (err error) { - xepg, err := loadJSONFileToMap(System.File.XEPG) + xepg, _ := loadJSONFileToMap(System.File.XEPG) for _, c := range xepg { diff --git a/src/version.go b/src/version.go new file mode 100644 index 0000000..4acf3aa --- /dev/null +++ b/src/version.go @@ -0,0 +1,4 @@ +package src + +// Version : Version, the Build Number is parsed in the main func +const Version = "2.5.1" diff --git a/src/webUI.go b/src/webUI.go index dc7a75a..447ea28 100644 --- a/src/webUI.go +++ b/src/webUI.go @@ -4,48 +4,37 @@ var webUI = make(map[string]interface{}) func loadHTMLMap() { - webUI["html/img/x_ transparent.png"] = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA6ppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0xMS0xNVQxNzoxMTo3NjwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6Q29tcHJlc3Npb24+NTwvdGlmZjpDb21wcmVzc2lvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MTQ0PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xNDQ8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4yNTY8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjI1NjwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgoeXQb1AAAaJElEQVR4Ae2dCZhcVZXHz+1KSFiGkISkqyIoOgI68EkgOBNkEcQRlIFRZDGABAQEhInGbxw+RUZRNhWRLawDYR0GHAaHUVkGvwGURUcgwIiAOGxjV3UHAslHQrbuM/9TlQ6d7qruWt527/u/7+uuqvvucu7vvnveuffde54IDxIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARLwiIDzQtayHi0q23shaydCOnlISu7nnWThRdrFOkPWyCleyNqJkF1yjhTd8k6yiDvtuLgLiCR/lVnIZ14keWU7k2Xyuu4oU92r2RazQ+nWypXI4W86zCXbyZ28KBvJ97MtpEhX1gWsyleS08TJU17I2omQKpvLarmqkywyn7ZHPw9rLvTOvwbX6xEyxS3Nenv4oQCcWwmQc/D3dtaBdiyfyv5S1mM7zieLGSzWEsS6KIuiRSzTGTD9H404z1iy80MBWNVL7hn8nx8LhaxlqnKBvKbvyppYHctTM/0nd5xPljNwcrcUs2/6DyL0RwGYxDOcjR3vGBQ+4M8tMElmdQ3n6NGjYPofGE6F6tTESRmm/1xxTuuczWSQH08BhqJbqlNkuTyJoK2GBgf53S6mkrvB+7qZ6b9Gfod6hHv3dzKAGbX9pNvd51N7+WUBGNlJbgm07FH4G/AJdFuyqlwotXFzW8kzk2itXAFZwu38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" - webUI["html/js/authentication_ts.js"] = "ZnVuY3Rpb24gbG9naW4oKSB7CiAgICB2YXIgZXJyID0gZmFsc2U7CiAgICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICAgIHZhciBkaXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiY29udGVudCIpOwogICAgdmFyIGZvcm0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiYXV0aGVudGljYXRpb24iKTsKICAgIHZhciBpbnB1dHMgPSBkaXYuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIklOUFVUIik7CiAgICBjb25zb2xlLmxvZyhpbnB1dHMpOwogICAgZm9yICh2YXIgaSA9IGlucHV0cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgICAgIHZhciBrZXkgPSBpbnB1dHNbaV0ubmFtZTsKICAgICAgICB2YXIgdmFsdWUgPSBpbnB1dHNbaV0udmFsdWU7CiAgICAgICAgaWYgKHZhbHVlLmxlbmd0aCA9PSAwKSB7CiAgICAgICAgICAgIGlucHV0c1tpXS5zdHlsZS5ib3JkZXJDb2xvciA9ICJyZWQiOwogICAgICAgICAgICBlcnIgPSB0cnVlOwogICAgICAgIH0KICAgICAgICBkYXRhW2tleV0gPSB2YWx1ZTsKICAgIH0KICAgIGlmIChlcnIgPT0gdHJ1ZSkgewogICAgICAgIGRhdGEgPSBuZXcgT2JqZWN0KCk7CiAgICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoImNvbmZpcm0iKSkgewogICAgICAgIGlmIChkYXRhWyJjb25maXJtIl0gIT0gZGF0YVsicGFzc3dvcmQiXSkgewogICAgICAgICAgICBhbGVydCgic2RhZnNkIik7CiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwYXNzd29yZCcpLnN0eWxlLmJvcmRlckNvbG9yID0gInJlZCI7CiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjb25maXJtJykuc3R5bGUuYm9yZGVyQ29sb3IgPSAicmVkIjsKICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImVyciIpLmlubmVySFRNTCA9ICJ7ey5hY2NvdW50LmZhaWxlZH19IjsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgIH0KICAgIGNvbnNvbGUubG9nKGRhdGEpOwogICAgZm9ybS5zdWJtaXQoKTsKfQo=" - webUI["html/js/configuration_ts.js"] = "dmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkgewogICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikgewogICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwKICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fAogICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9OwogICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpOwogICAgfTsKICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikgewogICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7CiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9CiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpOwogICAgfTsKfSkoKTsKdmFyIFdpemFyZENhdGVnb3J5ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gV2l6YXJkQ2F0ZWdvcnkoKSB7CiAgICAgICAgdGhpcy5Eb2N1bWVudElEID0gImNvbnRlbnQiOwogICAgfQogICAgV2l6YXJkQ2F0ZWdvcnkucHJvdG90eXBlLmNyZWF0ZUNhdGVnb3J5SGVhZGxpbmUgPSBmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgICB2YXIgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIkg0Iik7CiAgICAgICAgZWxlbWVudC5pbm5lckhUTUwgPSB2YWx1ZTsKICAgICAgICByZXR1cm4gZWxlbWVudDsKICAgIH07CiAgICByZXR1cm4gV2l6YXJkQ2F0ZWdvcnk7Cn0oKSk7CnZhciBXaXphcmRJdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikgewogICAgX19leHRlbmRzKFdpemFyZEl0ZW0sIF9zdXBlcik7CiAgICBmdW5jdGlvbiBXaXphcmRJdGVtKGtleSwgaGVhZGxpbmUpIHsKICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICAgIF90aGlzLmhlYWRsaW5lID0gaGVhZGxpbmU7CiAgICAgICAgX3RoaXMua2V5ID0ga2V5OwogICAgICAgIHJldHVybiBfdGhpczsKICAgIH0KICAgIFdpemFyZEl0ZW0ucHJvdG90eXBlLmNyZWF0ZVdpemFyZCA9IGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgaGVhZGxpbmUgPSB0aGlzLmNyZWF0ZUNhdGVnb3J5SGVhZGxpbmUodGhpcy5oZWFkbGluZSk7CiAgICAgICAgdmFyIGtleSA9IHRoaXMua2V5OwogICAgICAgIHZhciBjb250ZW50ID0gbmV3IFBvcHVwQ29udGVudCgpOwogICAgICAgIHZhciBkZXNjcmlwdGlvbjsKICAgICAgICB2YXIgZG9jID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5Eb2N1bWVudElEKTsKICAgICAgICBkb2MuaW5uZXJIVE1MID0gIiI7CiAgICAgICAgZG9jLmFwcGVuZENoaWxkKGhlYWRsaW5lKTsKICAgICAgICBzd2l0Y2ggKGtleSkgewogICAgICAgICAgICBjYXNlICJ0dW5lciI6CiAgICAgICAgICAgICAgICB2YXIgdGV4dCA9IG5ldyBBcnJheSgpOwogICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IG5ldyBBcnJheSgpOwogICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPD0gMTAwOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICB0ZXh0LnB1c2goaSk7CiAgICAgICAgICAgICAgICAgICAgdmFsdWVzLnB1c2goaSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ID0gY29udGVudC5jcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCAiMSIsIGtleSk7CiAgICAgICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJjbGFzcyIsICJ3aXphcmQiKTsKICAgICAgICAgICAgICAgIHNlbGVjdC5pZCA9IGtleTsKICAgICAgICAgICAgICAgIGRvYy5hcHBlbmRDaGlsZChzZWxlY3QpOwogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gPSAie3sud2l6YXJkLnR1bmVyLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImVwZ1NvdXJjZSI6CiAgICAgICAgICAgICAgICB2YXIgdGV4dCA9IFsiUE1TIiwgIlhFUEciXTsKICAgICAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBbIlBNUyIsICJYRVBHIl07CiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ID0gY29udGVudC5jcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCAiWEVQRyIsIGtleSk7CiAgICAgICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJjbGFzcyIsICJ3aXphcmQiKTsKICAgICAgICAgICAgICAgIHNlbGVjdC5pZCA9IGtleTsKICAgICAgICAgICAgICAgIGRvYy5hcHBlbmRDaGlsZChzZWxlY3QpOwogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gPSAie3sud2l6YXJkLmVwZ1NvdXJjZS5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJtM3UiOgogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGtleSwgIiIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey53aXphcmQubTN1LnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgiY2xhc3MiLCAid2l6YXJkIik7CiAgICAgICAgICAgICAgICBpbnB1dC5pZCA9IGtleTsKICAgICAgICAgICAgICAgIGRvYy5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiA9ICJ7ey53aXphcmQubTN1LmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInhtbHR2IjoKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBrZXksICIiKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3sud2l6YXJkLnhtbHR2LnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgiY2xhc3MiLCAid2l6YXJkIik7CiAgICAgICAgICAgICAgICBpbnB1dC5pZCA9IGtleTsKICAgICAgICAgICAgICAgIGRvYy5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbiA9ICJ7ey53aXphcmQueG1sdHYuZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGtleSk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdmFyIHByZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlBSRSIpOwogICAgICAgIHByZS5pbm5lckhUTUwgPSBkZXNjcmlwdGlvbjsKICAgICAgICBkb2MuYXBwZW5kQ2hpbGQocHJlKTsKICAgICAgICBjb25zb2xlLmxvZyhoZWFkbGluZSwga2V5KTsKICAgIH07CiAgICByZXR1cm4gV2l6YXJkSXRlbTsKfShXaXphcmRDYXRlZ29yeSkpOwpmdW5jdGlvbiByZWFkeUZvckNvbmZpZ3VyYXRpb24od2l6YXJkKSB7CiAgICB2YXIgc2VydmVyID0gbmV3IFNlcnZlcigiZ2V0U2VydmVyQ29uZmlnIik7CiAgICBzZXJ2ZXIucmVxdWVzdChuZXcgT2JqZWN0KCkpOwogICAgc2hvd0VsZW1lbnQoImxvYWRpbmciLCBmYWxzZSk7CiAgICBjb25maWd1cmF0aW9uV2l6YXJkW3dpemFyZF0uY3JlYXRlV2l6YXJkKCk7Cn0KZnVuY3Rpb24gc2F2ZVdpemFyZCgpIHsKICAgIHZhciBjbWQgPSAic2F2ZVdpemFyZCI7CiAgICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImNvbnRlbnQiKTsKICAgIHZhciBjb25maWcgPSBkaXYuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgid2l6YXJkIik7CiAgICB2YXIgd2l6YXJkID0gbmV3IE9iamVjdCgpOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb25maWcubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgbmFtZTsKICAgICAgICB2YXIgdmFsdWU7CiAgICAgICAgc3dpdGNoIChjb25maWdbaV0udGFnTmFtZSkgewogICAgICAgICAgICBjYXNlICJTRUxFQ1QiOgogICAgICAgICAgICAgICAgbmFtZSA9IGNvbmZpZ1tpXS5uYW1lOwogICAgICAgICAgICAgICAgdmFsdWUgPSBjb25maWdbaV0udmFsdWU7CiAgICAgICAgICAgICAgICAvLyBXZW5uIGRlciBXZXJ0IGVpbmUgWmFobCBpc3QsIHdpcmQgZGllc2VyIGFscyBaYWhsIGdlc3BlaWNoZXJ0CiAgICAgICAgICAgICAgICBpZiAoaXNOYU4odmFsdWUpKSB7CiAgICAgICAgICAgICAgICAgICAgd2l6YXJkW25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB3aXphcmRbbmFtZV0gPSBwYXJzZUludCh2YWx1ZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiSU5QVVQiOgogICAgICAgICAgICAgICAgc3dpdGNoIChjb25maWdbaV0udHlwZSkgewogICAgICAgICAgICAgICAgICAgIGNhc2UgInRleHQiOgogICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gY29uZmlnW2ldLm5hbWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gY29uZmlnW2ldLnZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUubGVuZ3RoID09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtc2cgPSBuYW1lLnRvVXBwZXJDYXNlKCkgKyAiOiAiICsgInt7LmFsZXJ0Lm1pc3NpbmdJbnB1dH19IjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsZXJ0KG1zZyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgd2l6YXJkW25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAvLyBjb2RlLi4uCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9CiAgICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICAgIGRhdGFbIndpemFyZCJdID0gd2l6YXJkOwogICAgdmFyIHNlcnZlciA9IG5ldyBTZXJ2ZXIoY21kKTsKICAgIHNlcnZlci5yZXF1ZXN0KGRhdGEpOwogICAgY29uc29sZS5sb2coZGF0YSk7Cn0KLy8gV2l6YXJkCnZhciBjb25maWd1cmF0aW9uV2l6YXJkID0gbmV3IEFycmF5KCk7CmNvbmZpZ3VyYXRpb25XaXphcmQucHVzaChuZXcgV2l6YXJkSXRlbSgidHVuZXIiLCAie3sud2l6YXJkLnR1bmVyLnRpdGxlfX0iKSk7CmNvbmZpZ3VyYXRpb25XaXphcmQucHVzaChuZXcgV2l6YXJkSXRlbSgiZXBnU291cmNlIiwgInt7LndpemFyZC5lcGdTb3VyY2UudGl0bGV9fSIpKTsKY29uZmlndXJhdGlvbldpemFyZC5wdXNoKG5ldyBXaXphcmRJdGVtKCJtM3UiLCAie3sud2l6YXJkLm0zdS50aXRsZX19IikpOwpjb25maWd1cmF0aW9uV2l6YXJkLnB1c2gobmV3IFdpemFyZEl0ZW0oInhtbHR2IiwgInt7LndpemFyZC54bWx0di50aXRsZX19IikpOwo=" - webUI["html/js/menu_ts.js"] = "dmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkgewogICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikgewogICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwKICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fAogICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9OwogICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpOwogICAgfTsKICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikgewogICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7CiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9CiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpOwogICAgfTsKfSkoKTsKdmFyIE1haW5NZW51ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkgewogICAgZnVuY3Rpb24gTWFpbk1lbnUoKSB7CiAgICAgICAgdGhpcy5Eb2N1bWVudElEID0gIm1haW4tbWVudSI7CiAgICAgICAgdGhpcy5IVE1MVGFnID0gIkxJIjsKICAgICAgICB0aGlzLkltYWdlUGF0aCA9ICJpbWcvIjsKICAgIH0KICAgIE1haW5NZW51LnByb3RvdHlwZS5jcmVhdGVJTUcgPSBmdW5jdGlvbiAoc3JjKSB7CiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJJTUciKTsKICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgic3JjIiwgdGhpcy5JbWFnZVBhdGggKyBzcmMpOwogICAgICAgIHJldHVybiBlbGVtZW50OwogICAgfTsKICAgIE1haW5NZW51LnByb3RvdHlwZS5jcmVhdGVWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgIHZhciBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiUCIpOwogICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gdmFsdWU7CiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9OwogICAgcmV0dXJuIE1haW5NZW51Owp9KCkpOwp2YXIgTWFpbk1lbnVJdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikgewogICAgX19leHRlbmRzKE1haW5NZW51SXRlbSwgX3N1cGVyKTsKICAgIGZ1bmN0aW9uIE1haW5NZW51SXRlbShtZW51S2V5LCB2YWx1ZSwgaW1hZ2UsIGhlYWRsaW5lKSB7CiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgICBfdGhpcy5tZW51S2V5ID0gbWVudUtleTsKICAgICAgICBfdGhpcy52YWx1ZSA9IHZhbHVlOwogICAgICAgIF90aGlzLmltZ1NyYyA9IGltYWdlOwogICAgICAgIF90aGlzLmhlYWRsaW5lID0gaGVhZGxpbmU7CiAgICAgICAgcmV0dXJuIF90aGlzOwogICAgfQogICAgTWFpbk1lbnVJdGVtLnByb3RvdHlwZS5jcmVhdGVJdGVtID0gZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBpdGVtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiTEkiKTsKICAgICAgICBpdGVtLnNldEF0dHJpYnV0ZSgib25jbGljayIsICJqYXZhc2NyaXB0OiBvcGVuVGhpc01lbnUodGhpcykiKTsKICAgICAgICBpdGVtLnNldEF0dHJpYnV0ZSgiaWQiLCB0aGlzLmlkKTsKICAgICAgICB2YXIgaW1nID0gdGhpcy5jcmVhdGVJTUcodGhpcy5pbWdTcmMpOwogICAgICAgIHZhciB2YWx1ZSA9IHRoaXMuY3JlYXRlVmFsdWUodGhpcy52YWx1ZSk7CiAgICAgICAgaXRlbS5hcHBlbmRDaGlsZChpbWcpOwogICAgICAgIGl0ZW0uYXBwZW5kQ2hpbGQodmFsdWUpOwogICAgICAgIHZhciBkb2MgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLkRvY3VtZW50SUQpOwogICAgICAgIGRvYy5hcHBlbmRDaGlsZChpdGVtKTsKICAgICAgICBzd2l0Y2ggKHRoaXMubWVudUtleSkgewogICAgICAgICAgICBjYXNlICJwbGF5bGlzdCI6CiAgICAgICAgICAgICAgICB0aGlzLnRhYmxlSGVhZGVyID0gWyJ7ey5wbGF5bGlzdC50YWJsZS5wbGF5bGlzdH19IiwgInt7LnBsYXlsaXN0LnRhYmxlLnR1bmVyfX0iLCAie3sucGxheWxpc3QudGFibGUubGFzdFVwZGF0ZX19IiwgInt7LnBsYXlsaXN0LnRhYmxlLmF2YWlsYWJpbGl0eX19ICUiLCAie3sucGxheWxpc3QudGFibGUudHlwZX19IiwgInt7LnBsYXlsaXN0LnRhYmxlLnN0cmVhbXN9fSIsICJ7ey5wbGF5bGlzdC50YWJsZS5ncm91cFRpdGxlfX0gJSIsICJ7ey5wbGF5bGlzdC50YWJsZS50dmdJRH19ICUiLCAie3sucGxheWxpc3QudGFibGUudW5pcXVlSUR9fSAlIl07CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAieG1sdHYiOgogICAgICAgICAgICAgICAgdGhpcy50YWJsZUhlYWRlciA9IFsie3sueG1sdHYudGFibGUuZ3VpZGV9fSIsICJ7ey54bWx0di50YWJsZS5sYXN0VXBkYXRlfX0iLCAie3sueG1sdHYudGFibGUuYXZhaWxhYmlsaXR5fX0gJSIsICJ7ey54bWx0di50YWJsZS5jaGFubmVsc319IiwgInt7LnhtbHR2LnRhYmxlLnByb2dyYW1zfX0iXTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJmaWx0ZXIiOgogICAgICAgICAgICAgICAgdGhpcy50YWJsZUhlYWRlciA9IFsie3suZmlsdGVyLnRhYmxlLm5hbWV9fSIsICJ7ey5maWx0ZXIudGFibGUudHlwZX19IiwgInt7LmZpbHRlci50YWJsZS5maWx0ZXJ9fSJdOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInVzZXJzIjoKICAgICAgICAgICAgICAgIHRoaXMudGFibGVIZWFkZXIgPSBbInt7LnVzZXJzLnRhYmxlLnVzZXJuYW1lfX0iLCAie3sudXNlcnMudGFibGUucGFzc3dvcmR9fSIsICJ7ey51c2Vycy50YWJsZS53ZWJ9fSIsICJ7ey51c2Vycy50YWJsZS5wbXN9fSIsICJ7ey51c2Vycy50YWJsZS5tM3V9fSIsICJ7ey51c2Vycy50YWJsZS54bWx9fSIsICJ7ey51c2Vycy50YWJsZS5hcGl9fSJdOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgIm1hcHBpbmciOgogICAgICAgICAgICAgICAgdGhpcy50YWJsZUhlYWRlciA9IFsiQlVMSyIsICJ7ey5tYXBwaW5nLnRhYmxlLmNoTm99fSIsICJ7ey5tYXBwaW5nLnRhYmxlLmxvZ299fSIsICJ7ey5tYXBwaW5nLnRhYmxlLmNoYW5uZWxOYW1lfX0iLCAie3subWFwcGluZy50YWJsZS5wbGF5bGlzdH19IiwgInt7Lm1hcHBpbmcudGFibGUuZ3JvdXBUaXRsZX19IiwgInt7Lm1hcHBpbmcudGFibGUueG1sdHZGaWxlfX0iLCAie3subWFwcGluZy50YWJsZS54bWx0dklEfX0iXTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICAvL2NvbnNvbGUubG9nKHRoaXMubWVudUtleSwgdGhpcy50YWJsZUhlYWRlcik7CiAgICB9OwogICAgcmV0dXJuIE1haW5NZW51SXRlbTsKfShNYWluTWVudSkpOwp2YXIgQ29udGVudCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIENvbnRlbnQoKSB7CiAgICAgICAgdGhpcy5Eb2N1bWVudElEID0gImNvbnRlbnQiOwogICAgICAgIHRoaXMuVGFibGVJRCA9ICJjb250ZW50X3RhYmxlIjsKICAgICAgICB0aGlzLmhlYWRlckNsYXNzID0gImNvbnRlbnRfdGFibGVfaGVhZGVyIjsKICAgICAgICB0aGlzLmludGVyYWN0aW9uSUQgPSAiY29udGVudC1pbnRlcmFjdGlvbiI7CiAgICB9CiAgICBDb250ZW50LnByb3RvdHlwZS5jcmVhdGVIZWFkbGluZSA9IGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgIHZhciBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiSDMiKTsKICAgICAgICBlbGVtZW50LmlubmVySFRNTCA9IHZhbHVlOwogICAgICAgIHJldHVybiBlbGVtZW50OwogICAgfTsKICAgIENvbnRlbnQucHJvdG90eXBlLmNyZWF0ZUhSID0gZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiSFIiKTsKICAgICAgICByZXR1cm4gZWxlbWVudDsKICAgIH07CiAgICBDb250ZW50LnByb3RvdHlwZS5jcmVhdGVJbnRlcmFjdGlvbiA9IGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIkRJViIpOwogICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCJpZCIsIHRoaXMuaW50ZXJhY3Rpb25JRCk7CiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9OwogICAgQ29udGVudC5wcm90b3R5cGUuY3JlYXRlRElWID0gZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiRElWIik7CiAgICAgICAgZWxlbWVudC5pZCA9IHRoaXMuRGl2SUQ7CiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9OwogICAgQ29udGVudC5wcm90b3R5cGUuY3JlYXRlVEFCTEUgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJUQUJMRSIpOwogICAgICAgIGVsZW1lbnQuaWQgPSB0aGlzLlRhYmxlSUQ7CiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9OwogICAgQ29udGVudC5wcm90b3R5cGUuY3JlYXRlVGFibGVSb3cgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJUUiIpOwogICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gdGhpcy5oZWFkZXJDbGFzczsKICAgICAgICByZXR1cm4gZWxlbWVudDsKICAgIH07CiAgICBDb250ZW50LnByb3RvdHlwZS5jcmVhdGVUYWJsZUNvbnRlbnQgPSBmdW5jdGlvbiAobWVudUtleSkgewogICAgICAgIHZhciBkYXRhID0gbmV3IE9iamVjdCgpOwogICAgICAgIHZhciByb3dzID0gbmV3IEFycmF5KCk7CiAgICAgICAgc3dpdGNoIChtZW51S2V5KSB7CiAgICAgICAgICAgIGNhc2UgInBsYXlsaXN0IjoKICAgICAgICAgICAgICAgIHZhciBmaWxlVHlwZXMgPSBuZXcgQXJyYXkoIm0zdSIsICJoZGhyIik7CiAgICAgICAgICAgICAgICBmaWxlVHlwZXMuZm9yRWFjaChmdW5jdGlvbiAoZmlsZVR5cGUpIHsKICAgICAgICAgICAgICAgICAgICBkYXRhID0gU0VSVkVSWyJzZXR0aW5ncyJdWyJmaWxlcyJdW2ZpbGVUeXBlXTsKICAgICAgICAgICAgICAgICAgICB2YXIga2V5cyA9IGdldE9iaktleXMoZGF0YSk7CiAgICAgICAgICAgICAgICAgICAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVFIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuaWQgPSBrZXk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoIicgKyBmaWxlVHlwZSArICciLCB0aGlzKScpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsibmFtZSJdOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoU0VSVkVSWyJzZXR0aW5ncyJdWyJidWZmZXIiXSAhPSAiLSIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bInR1bmVyIl07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gIi0iOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bImxhc3QudXBkYXRlIl07CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bInByb3ZpZGVyLmF2YWlsYWJpbGl0eSJdOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJ0eXBlIl0udG9VcHBlckNhc2UoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsiY29tcGF0aWJpbGl0eSJdWyJzdHJlYW1zIl07CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bImNvbXBhdGliaWxpdHkiXVsiZ3JvdXAudGl0bGUiXTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsiY29tcGF0aWJpbGl0eSJdWyJ0dmcuaWQiXTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsiY29tcGF0aWJpbGl0eSJdWyJzdHJlYW0uaWQiXTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICByb3dzLnB1c2godHIpOwogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiZmlsdGVyIjoKICAgICAgICAgICAgICAgIGRlbGV0ZSBTRVJWRVJbInNldHRpbmdzIl1bImZpbHRlciJdWy0xXTsKICAgICAgICAgICAgICAgIGRhdGEgPSBTRVJWRVJbInNldHRpbmdzIl1bImZpbHRlciJdOwogICAgICAgICAgICAgICAgdmFyIGtleXMgPSBnZXRPYmpLZXlzKGRhdGEpOwogICAgICAgICAgICAgICAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgdHIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJUUiIpOwogICAgICAgICAgICAgICAgICAgIHRyLmlkID0ga2V5OwogICAgICAgICAgICAgICAgICAgIHRyLnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoIicgKyBkYXRhW2tleV1bInR5cGUiXSArICciLCB0aGlzKScpOwogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJuYW1lIl07CiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGRhdGFba2V5XVsidHlwZSJdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgImN1c3RvbS1maWx0ZXIiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9ICJ7ey5maWx0ZXIuY3VzdG9tfX0iOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgImdyb3VwLXRpdGxlIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSAie3suZmlsdGVyLmdyb3VwfX0iOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJmaWx0ZXIiXTsKICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgcm93cy5wdXNoKHRyKTsKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInhtbHR2IjoKICAgICAgICAgICAgICAgIHZhciBmaWxlVHlwZXMgPSBuZXcgQXJyYXkoInhtbHR2Iik7CiAgICAgICAgICAgICAgICBmaWxlVHlwZXMuZm9yRWFjaChmdW5jdGlvbiAoZmlsZVR5cGUpIHsKICAgICAgICAgICAgICAgICAgICBkYXRhID0gU0VSVkVSWyJzZXR0aW5ncyJdWyJmaWxlcyJdW2ZpbGVUeXBlXTsKICAgICAgICAgICAgICAgICAgICB2YXIga2V5cyA9IGdldE9iaktleXMoZGF0YSk7CiAgICAgICAgICAgICAgICAgICAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVFIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuaWQgPSBrZXk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoIicgKyBmaWxlVHlwZSArICciLCB0aGlzKScpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsibmFtZSJdOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJsYXN0LnVwZGF0ZSJdOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJwcm92aWRlci5hdmFpbGFiaWxpdHkiXTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsiY29tcGF0aWJpbGl0eSJdWyJ4bWx0di5jaGFubmVscyJdOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJjb21wYXRpYmlsaXR5Il1bInhtbHR2LnByb2dyYW1zIl07CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgcm93cy5wdXNoKHRyKTsKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInVzZXJzIjoKICAgICAgICAgICAgICAgIHZhciBmaWxlVHlwZXMgPSBuZXcgQXJyYXkoInVzZXJzIik7CiAgICAgICAgICAgICAgICBmaWxlVHlwZXMuZm9yRWFjaChmdW5jdGlvbiAoZmlsZVR5cGUpIHsKICAgICAgICAgICAgICAgICAgICBkYXRhID0gU0VSVkVSW2ZpbGVUeXBlXTsKICAgICAgICAgICAgICAgICAgICB2YXIga2V5cyA9IGdldE9iaktleXMoZGF0YSk7CiAgICAgICAgICAgICAgICAgICAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVFIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuaWQgPSBrZXk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoIicgKyBmaWxlVHlwZSArICciLCB0aGlzKScpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsiZGF0YSJdWyJ1c2VybmFtZSJdOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gIioqKioqKiI7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhW2tleV1bImRhdGEiXVsiYXV0aGVudGljYXRpb24ud2ViIl0gPT0gdHJ1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9ICLinJMiOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9ICItIjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YVtrZXldWyJkYXRhIl1bImF1dGhlbnRpY2F0aW9uLnBtcyJdID09IHRydWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSAi4pyTIjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSAiLSI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFba2V5XVsiZGF0YSJdWyJhdXRoZW50aWNhdGlvbi5tM3UiXSA9PSB0cnVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gIuKckyI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gIi0iOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhW2tleV1bImRhdGEiXVsiYXV0aGVudGljYXRpb24ueG1sIl0gPT0gdHJ1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9ICLinJMiOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9ICItIjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YVtrZXldWyJkYXRhIl1bImF1dGhlbnRpY2F0aW9uLmFwaSJdID09IHRydWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSAi4pyTIjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSAiLSI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICByb3dzLnB1c2godHIpOwogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAibWFwcGluZyI6CiAgICAgICAgICAgICAgICBCVUxLX0VESVQgPSBmYWxzZTsKICAgICAgICAgICAgICAgIGNyZWF0ZVNlYXJjaE9iaigpOwogICAgICAgICAgICAgICAgY2hlY2tVbmRvKCJlcGdNYXBwaW5nIik7CiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygiTUFQUElORyIpOwogICAgICAgICAgICAgICAgZGF0YSA9IFNFUlZFUlsieGVwZyJdWyJlcGdNYXBwaW5nIl07CiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IGdldE9iaktleXMoZGF0YSk7CiAgICAgICAgICAgICAgICBrZXlzLmZvckVhY2goZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgICAgICAgICAgIHZhciB0ciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlRSIik7CiAgICAgICAgICAgICAgICAgICAgdHIuaWQgPSBrZXk7CiAgICAgICAgICAgICAgICAgICAgLy90ci5zZXRBdHRyaWJ1dGUoJ29uY29udGV4dG1lbnUnLCAnamF2YXNjcmlwdDogcmlnaHRDbGljayh0aGlzKScpCiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChkYXRhW2tleV1bIngtYWN0aXZlIl0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSB0cnVlOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHIuY2xhc3NOYW1lID0gImFjdGl2ZUVQRyI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBmYWxzZToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyLmNsYXNzTmFtZSA9ICJub3RBY3RpdmVFUEciOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIC8vIEJ1bGsKICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiQlVMSyI7CiAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAvLyBLYW5hbG51bW1lcgogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJJTlBVVENIQU5ORUwiOwogICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bIngtY2hhbm5lbElEIl07CiAgICAgICAgICAgICAgICAgICAgLy90ZC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogY2hhbmdlQ2hhbm5lbE51bWJlcigiJyArIGtleSArICciLCB0aGlzKScpCiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgIC8vIExvZ28KICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiSU1HIjsKICAgICAgICAgICAgICAgICAgICBjZWxsLmltYWdlVVJMID0gZGF0YVtrZXldWyJ0dmctbG9nbyJdOwogICAgICAgICAgICAgICAgICAgIHZhciB0ZCA9IGNlbGwuY3JlYXRlQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgIHRkLnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoIm1hcHBpbmciLCB0aGlzKScpOwogICAgICAgICAgICAgICAgICAgIHRkLmlkID0ga2V5OwogICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKHRkKTsKICAgICAgICAgICAgICAgICAgICAvLyBLYW5hbG5hbWUKICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jbGFzc05hbWUgPSBkYXRhW2tleV1bIngtY2F0ZWdvcnkiXTsKICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJ4LW5hbWUiXTsKICAgICAgICAgICAgICAgICAgICB2YXIgdGQgPSBjZWxsLmNyZWF0ZUNlbGwoKTsKICAgICAgICAgICAgICAgICAgICB0ZC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogb3BlblBvcFVwKCJtYXBwaW5nIiwgdGhpcyknKTsKICAgICAgICAgICAgICAgICAgICB0ZC5pZCA9IGtleTsKICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZCh0ZCk7CiAgICAgICAgICAgICAgICAgICAgLy8gUGxheWxpc3QKICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgLy9jZWxsLnZhbHVlID0gZGF0YVtrZXldWyJfZmlsZS5tM3UubmFtZSJdIAogICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBnZXRWYWx1ZUZyb21Qcm92aWRlckZpbGUoZGF0YVtrZXldWyJfZmlsZS5tM3UuaWQiXSwgIm0zdSIsICJuYW1lIik7CiAgICAgICAgICAgICAgICAgICAgdmFyIHRkID0gY2VsbC5jcmVhdGVDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgdGQuc2V0QXR0cmlidXRlKCdvbmNsaWNrJywgJ2phdmFzY3JpcHQ6IG9wZW5Qb3BVcCgibWFwcGluZyIsIHRoaXMpJyk7CiAgICAgICAgICAgICAgICAgICAgdGQuaWQgPSBrZXk7CiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQodGQpOwogICAgICAgICAgICAgICAgICAgIC8vIEdydXBwZSAoZ3JvdXAtdGl0bGUpCiAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bIngtZ3JvdXAtdGl0bGUiXTsKICAgICAgICAgICAgICAgICAgICB2YXIgdGQgPSBjZWxsLmNyZWF0ZUNlbGwoKTsKICAgICAgICAgICAgICAgICAgICB0ZC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogb3BlblBvcFVwKCJtYXBwaW5nIiwgdGhpcyknKTsKICAgICAgICAgICAgICAgICAgICB0ZC5pZCA9IGtleTsKICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZCh0ZCk7CiAgICAgICAgICAgICAgICAgICAgLy8gWE1MVFYgRGF0ZWkKICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFba2V5XVsieC14bWx0di1maWxlIl0gIT0gIi0iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBnZXRWYWx1ZUZyb21Qcm92aWRlckZpbGUoZGF0YVtrZXldWyJ4LXhtbHR2LWZpbGUiXSwgInhtbHR2IiwgIm5hbWUiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bIngteG1sdHYtZmlsZSJdOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB2YXIgdGQgPSBjZWxsLmNyZWF0ZUNlbGwoKTsKICAgICAgICAgICAgICAgICAgICB0ZC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogb3BlblBvcFVwKCJtYXBwaW5nIiwgdGhpcyknKTsKICAgICAgICAgICAgICAgICAgICB0ZC5pZCA9IGtleTsKICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZCh0ZCk7CiAgICAgICAgICAgICAgICAgICAgLy8gWE1MVFYgS2FuYWwKICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgLy92YXIgdmFsdWUgPSBzdHIuc3Vic3RyaW5nKDEsIDQpOwogICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IGRhdGFba2V5XVsieC1tYXBwaW5nIl07CiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlLmxlbmd0aCA+IDIwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gZGF0YVtrZXldWyJ4LW1hcHBpbmciXS5zdWJzdHJpbmcoMCwgMjApICsgIi4uLiI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICB2YXIgdGQgPSBjZWxsLmNyZWF0ZUNlbGwoKTsKICAgICAgICAgICAgICAgICAgICB0ZC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogb3BlblBvcFVwKCJtYXBwaW5nIiwgdGhpcyknKTsKICAgICAgICAgICAgICAgICAgICB0ZC5pZCA9IGtleTsKICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZCh0ZCk7CiAgICAgICAgICAgICAgICAgICAgcm93cy5wdXNoKHRyKTsKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInNldHRpbmdzIjoKICAgICAgICAgICAgICAgIGFsZXJ0KCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCJUYWJsZSBjb250ZW50IChtZW51S2V5KToiLCBtZW51S2V5KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcm93czsKICAgIH07CiAgICByZXR1cm4gQ29udGVudDsKfSgpKTsKdmFyIENlbGwgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBDZWxsKCkgewogICAgfQogICAgQ2VsbC5wcm90b3R5cGUuY3JlYXRlQ2VsbCA9IGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgdGQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgIGlmICh0aGlzLmNoaWxkID09IHRydWUpIHsKICAgICAgICAgICAgdmFyIGVsZW1lbnQ7CiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5jaGlsZFR5cGUpIHsKICAgICAgICAgICAgICAgIGNhc2UgIlAiOgogICAgICAgICAgICAgICAgICAgIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRoaXMuY2hpbGRUeXBlKTsKICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmlubmVySFRNTCA9IHRoaXMudmFsdWU7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgPSB0aGlzLmNsYXNzTmFtZTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgIklOUFVUIjoKICAgICAgICAgICAgICAgICAgICBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0aGlzLmNoaWxkVHlwZSk7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC52YWx1ZSA9IHRoaXMudmFsdWU7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC50eXBlID0gInRleHQiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiSU5QVVRDSEFOTkVMIjoKICAgICAgICAgICAgICAgICAgICBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiSU5QVVQiKTsKICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2c2NyaXB0OiBjaGFuZ2VDaGFubmVsTnVtYmVyKHRoaXMpIik7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC52YWx1ZSA9IHRoaXMudmFsdWU7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC50eXBlID0gInRleHQiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiQlVMSyI6CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIklOUFVUIik7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5jaGVja2VkID0gdGhpcy52YWx1ZTsKICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnR5cGUgPSAiY2hlY2tib3giOwogICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gImJ1bGsgaGlkZUJ1bGsiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiQlVMS19IRUFEIjoKICAgICAgICAgICAgICAgICAgICBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiSU5QVVQiKTsKICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmNoZWNrZWQgPSB0aGlzLnZhbHVlOwogICAgICAgICAgICAgICAgICAgIGVsZW1lbnQudHlwZSA9ICJjaGVja2JveCI7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgPSAiYnVsayBoaWRlQnVsayI7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAiamF2YXNjcmlwdDogc2VsZWN0QWxsQ2hhbm5lbHMoKSIpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiSU1HIjoKICAgICAgICAgICAgICAgICAgICBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0aGlzLmNoaWxkVHlwZSk7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoInNyYyIsIHRoaXMuaW1hZ2VVUkwpOwogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmltYWdlVVJMICE9ICIiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCJvbmVycm9yIiwgImphdmFzY3JpcHQ6IHRoaXMub25lcnJvcj1udWxsO3RoaXMuc3JjPScnIik7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vb25lcnJvcj0idGhpcy5vbmVycm9yPW51bGw7dGhpcy5zcmM9J21pc3NpbmcuZ2lmJzsiCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHRkLmFwcGVuZENoaWxkKGVsZW1lbnQpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgdGQuaW5uZXJIVE1MID0gdGhpcy52YWx1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKHRoaXMub25jbGljayA9PSB0cnVlKSB7CiAgICAgICAgICAgIHRkLnNldEF0dHJpYnV0ZSgib25jbGljayIsIHRoaXMub25jbGlja0Z1bmt0aW9uKTsKICAgICAgICAgICAgdGQuY2xhc3NOYW1lID0gInBvaW50ZXIiOwogICAgICAgIH0KICAgICAgICBpZiAodGhpcy50ZENsYXNzTmFtZSAhPSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgdGQuY2xhc3NOYW1lID0gdGhpcy50ZENsYXNzTmFtZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRkOwogICAgfTsKICAgIHJldHVybiBDZWxsOwp9KCkpOwp2YXIgU2hvd0NvbnRlbnQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7CiAgICBfX2V4dGVuZHMoU2hvd0NvbnRlbnQsIF9zdXBlcik7CiAgICBmdW5jdGlvbiBTaG93Q29udGVudChtZW51SUQpIHsKICAgICAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzOwogICAgICAgIF90aGlzLm1lbnVJRCA9IG1lbnVJRDsKICAgICAgICByZXR1cm4gX3RoaXM7CiAgICB9CiAgICBTaG93Q29udGVudC5wcm90b3R5cGUuY3JlYXRlSW5wdXQgPSBmdW5jdGlvbiAodHlwZSwgbmFtZSwgdmFsdWUpIHsKICAgICAgICB2YXIgaW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJJTlBVVCIpOwogICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgidHlwZSIsIHR5cGUpOwogICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgibmFtZSIsIG5hbWUpOwogICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgcmV0dXJuIGlucHV0OwogICAgfTsKICAgIFNob3dDb250ZW50LnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gKCkgewogICAgICAgIENPTFVNTl9UT19TT1JUID0gLTE7CiAgICAgICAgLy8gQWx0ZW4gSW5oYWx0IGzDtnNjaGVuCiAgICAgICAgdmFyIGRvYyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuRG9jdW1lbnRJRCk7CiAgICAgICAgZG9jLmlubmVySFRNTCA9ICIiOwogICAgICAgIHNob3dQcmV2aWV3KGZhbHNlKTsKICAgICAgICAvLyDDnGJlcnNjaHJpZnQKICAgICAgICB2YXIgaGVhZGxpbmUgPSBtZW51SXRlbXNbdGhpcy5tZW51SURdLmhlYWRsaW5lOwogICAgICAgIHZhciBtZW51S2V5ID0gbWVudUl0ZW1zW3RoaXMubWVudUlEXS5tZW51S2V5OwogICAgICAgIHZhciBoID0gdGhpcy5jcmVhdGVIZWFkbGluZShoZWFkbGluZSk7CiAgICAgICAgZG9jLmFwcGVuZENoaWxkKGgpOwogICAgICAgIHZhciBociA9IHRoaXMuY3JlYXRlSFIoKTsKICAgICAgICBkb2MuYXBwZW5kQ2hpbGQoaHIpOwogICAgICAgIC8vIEludGVyYWt0aW9uCiAgICAgICAgdmFyIGRpdiA9IHRoaXMuY3JlYXRlSW50ZXJhY3Rpb24oKTsKICAgICAgICBkb2MuYXBwZW5kQ2hpbGQoZGl2KTsKICAgICAgICB2YXIgaW50ZXJhY3Rpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmludGVyYWN0aW9uSUQpOwogICAgICAgIHN3aXRjaCAobWVudUtleSkgewogICAgICAgICAgICBjYXNlICJwbGF5bGlzdCI6CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLmNyZWF0ZUlucHV0KCJidXR0b24iLCBtZW51S2V5LCAie3suYnV0dG9uLm5ld319Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoImlkIiwgIi0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoInBsYXlsaXN0IiknKTsKICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJmaWx0ZXIiOgogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcy5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgbWVudUtleSwgInt7LmJ1dHRvbi5uZXd9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJpZCIsIC0xKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoImZpbHRlciIsIHRoaXMpJyk7CiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAieG1sdHYiOgogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcy5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgbWVudUtleSwgInt7LmJ1dHRvbi5uZXd9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJpZCIsICJ4bWx0diIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IG9wZW5Qb3BVcCgieG1sdHYiKScpOwogICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24uYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInVzZXJzIjoKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMuY3JlYXRlSW5wdXQoImJ1dHRvbiIsIG1lbnVLZXksICJ7ey5idXR0b24ubmV3fX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgiaWQiLCAidXNlcnMiKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoInVzZXJzIiknKTsKICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJtYXBwaW5nIjoKICAgICAgICAgICAgICAgIHNob3dFbGVtZW50KCJsb2FkaW5nIiwgdHJ1ZSk7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLmNyZWF0ZUlucHV0KCJidXR0b24iLCBtZW51S2V5LCAie3suYnV0dG9uLnNhdmV9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHNhdmVQb3B1cERhdGEoIm1hcHBpbmciLCAiIiwgIiIpJyk7CiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLmNyZWF0ZUlucHV0KCJidXR0b24iLCBtZW51S2V5LCAie3suYnV0dG9uLmJ1bGtFZGl0fX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBidWxrRWRpdCgpJyk7CiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLmNyZWF0ZUlucHV0KCJzZWFyY2giLCAic2VhcmNoIiwgIiIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJpZCIsICJzZWFyY2hNYXBwaW5nIik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LmJ1dHRvbi5zZWFyY2h9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuY2xhc3NOYW1lID0gInNlYXJjaCI7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgJ2phdmFzY3JpcHQ6IHNlYXJjaEluTWFwcGluZygpJyk7CiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAic2V0dGluZ3MiOgogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcy5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgbWVudUtleSwgInt7LmJ1dHRvbi5zYXZlfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBzYXZlU2V0dGluZ3MoKTsnKTsKICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMuY3JlYXRlSW5wdXQoImJ1dHRvbiIsIG1lbnVLZXksICJ7ey5idXR0b24uYmFja3VwfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBiYWNrdXAoKTsnKTsKICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMuY3JlYXRlSW5wdXQoImJ1dHRvbiIsIG1lbnVLZXksICJ7ey5idXR0b24ucmVzdG9yZX19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogcmVzdG9yZSgpOycpOwogICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24uYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgdmFyIHdyYXBwZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJESVYiKTsKICAgICAgICAgICAgICAgIHdyYXBwZXIuc2V0QXR0cmlidXRlKCJpZCIsICJib3gtd3JhcHBlciIpOwogICAgICAgICAgICAgICAgZG9jLmFwcGVuZENoaWxkKHdyYXBwZXIpOwogICAgICAgICAgICAgICAgdGhpcy5EaXZJRCA9ICJjb250ZW50X3NldHRpbmdzIjsKICAgICAgICAgICAgICAgIHZhciBzZXR0aW5ncyA9IHRoaXMuY3JlYXRlRElWKCk7CiAgICAgICAgICAgICAgICB3cmFwcGVyLmFwcGVuZENoaWxkKHNldHRpbmdzKTsKICAgICAgICAgICAgICAgIHNob3dTZXR0aW5ncygpOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImxvZyI6CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLmNyZWF0ZUlucHV0KCJidXR0b24iLCBtZW51S2V5LCAie3suYnV0dG9uLnJlc2V0TG9nc319Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogcmVzZXRMb2dzKCk7Jyk7CiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICB2YXIgd3JhcHBlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIkRJViIpOwogICAgICAgICAgICAgICAgd3JhcHBlci5zZXRBdHRyaWJ1dGUoImlkIiwgImJveC13cmFwcGVyIik7CiAgICAgICAgICAgICAgICBkb2MuYXBwZW5kQ2hpbGQod3JhcHBlcik7CiAgICAgICAgICAgICAgICB0aGlzLkRpdklEID0gImNvbnRlbnRfbG9nIjsKICAgICAgICAgICAgICAgIHZhciBsb2dzID0gdGhpcy5jcmVhdGVESVYoKTsKICAgICAgICAgICAgICAgIHdyYXBwZXIuYXBwZW5kQ2hpbGQobG9ncyk7CiAgICAgICAgICAgICAgICBzaG93TG9ncyh0cnVlKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJsb2dvdXQiOgogICAgICAgICAgICAgICAgbG9jYXRpb24ucmVsb2FkKCk7CiAgICAgICAgICAgICAgICBkb2N1bWVudC5jb29raWUgPSAiVG9rZW49IDsgZXhwaXJlcyA9IFRodSwgMDEgSmFuIDE5NzAgMDA6MDA6MDAgR01UIjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgY29uc29sZS5sb2coIlNob3cgY29udGVudCAobWVudUtleSk6IiwgbWVudUtleSk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgLy8gVGFiZWxsZSBlcnN0ZWxsZW4gKGZhbGxzIGJlbsO2dGlndCkKICAgICAgICB2YXIgdGFibGVIZWFkZXIgPSBtZW51SXRlbXNbdGhpcy5tZW51SURdLnRhYmxlSGVhZGVyOwogICAgICAgIGlmICh0YWJsZUhlYWRlci5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIHZhciB3cmFwcGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiRElWIik7CiAgICAgICAgICAgIGRvYy5hcHBlbmRDaGlsZCh3cmFwcGVyKTsKICAgICAgICAgICAgd3JhcHBlci5zZXRBdHRyaWJ1dGUoImlkIiwgImJveC13cmFwcGVyIik7CiAgICAgICAgICAgIHZhciB0YWJsZSA9IHRoaXMuY3JlYXRlVEFCTEUoKTsKICAgICAgICAgICAgd3JhcHBlci5hcHBlbmRDaGlsZCh0YWJsZSk7CiAgICAgICAgICAgIHZhciBoZWFkZXIgPSB0aGlzLmNyZWF0ZVRhYmxlUm93KCk7CiAgICAgICAgICAgIHRhYmxlLmFwcGVuZENoaWxkKGhlYWRlcik7CiAgICAgICAgICAgIC8vIEtvcGZ6ZWlsZSBkZXIgVGFibGxlCiAgICAgICAgICAgIHRhYmxlSGVhZGVyLmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHsKICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZWxlbWVudDsKICAgICAgICAgICAgICAgIGlmIChlbGVtZW50ID09ICJCVUxLIikgewogICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIkJVTEtfSEVBRCI7CiAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKG1lbnVLZXkgPT0gIm1hcHBpbmciKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQgPT0gInt7Lm1hcHBpbmcudGFibGUuY2hOb319IikgewogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2sgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2tGdW5rdGlvbiA9ICJqYXZhc2NyaXB0OiBzb3J0VGFibGUoMSk7IjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC50ZENsYXNzTmFtZSA9ICJzb3J0VGhpcyI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50ID09ICJ7ey5tYXBwaW5nLnRhYmxlLmNoYW5uZWxOYW1lfX0iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwub25jbGljayA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwub25jbGlja0Z1bmt0aW9uID0gImphdmFzY3JpcHQ6IHNvcnRUYWJsZSgzKTsiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCA9PSAie3subWFwcGluZy50YWJsZS5wbGF5bGlzdH19IikgewogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2sgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2tGdW5rdGlvbiA9ICJqYXZhc2NyaXB0OiBzb3J0VGFibGUoNCk7IjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQgPT0gInt7Lm1hcHBpbmcudGFibGUuZ3JvdXBUaXRsZX19IikgewogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2sgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2tGdW5rdGlvbiA9ICJqYXZhc2NyaXB0OiBzb3J0VGFibGUoNSk7IjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBoZWFkZXIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgdGFibGUuYXBwZW5kQ2hpbGQoaGVhZGVyKTsKICAgICAgICAgICAgLy8gSW5oYWx0IGRlciBUYWJlbGxlCiAgICAgICAgICAgIHZhciByb3dzID0gdGhpcy5jcmVhdGVUYWJsZUNvbnRlbnQobWVudUtleSk7CiAgICAgICAgICAgIHJvd3MuZm9yRWFjaChmdW5jdGlvbiAodHIpIHsKICAgICAgICAgICAgICAgIHRhYmxlLmFwcGVuZENoaWxkKHRyKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIHN3aXRjaCAobWVudUtleSkgewogICAgICAgICAgICBjYXNlICJtYXBwaW5nIjoKICAgICAgICAgICAgICAgIHNvcnRUYWJsZSgxKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJmaWx0ZXIiOgogICAgICAgICAgICAgICAgc2hvd1ByZXZpZXcodHJ1ZSk7CiAgICAgICAgICAgICAgICBzb3J0VGFibGUoMCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIENPTFVNTl9UT19TT1JUID0gLTE7CiAgICAgICAgICAgICAgICBzb3J0VGFibGUoMCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgc2hvd0VsZW1lbnQoImxvYWRpbmciLCBmYWxzZSk7CiAgICB9OwogICAgcmV0dXJuIFNob3dDb250ZW50Owp9KENvbnRlbnQpKTsKZnVuY3Rpb24gUGFnZVJlYWR5KCkgewogICAgdmFyIHNlcnZlciA9IG5ldyBTZXJ2ZXIoImdldFNlcnZlckNvbmZpZyIpOwogICAgc2VydmVyLnJlcXVlc3QobmV3IE9iamVjdCgpKTsKICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJyZXNpemUiLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgY2FsY3VsYXRlV3JhcHBlckhlaWdodCgpOwogICAgfSwgdHJ1ZSk7CiAgICBzZXRJbnRlcnZhbChmdW5jdGlvbiAoKSB7CiAgICAgICAgdXBkYXRlTG9nKCk7CiAgICB9LCAxMDAwMCk7CiAgICByZXR1cm47Cn0KZnVuY3Rpb24gY3JlYXRlTGF5b3V0KCkgewogICAgLy8gQ2xpZW50IEluZm8KICAgIHZhciBvYmogPSBTRVJWRVJbImNsaWVudEluZm8iXTsKICAgIHZhciBrZXlzID0gZ2V0T2JqS2V5cyhvYmopOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgaWYgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGtleXNbaV0pKSB7CiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGtleXNbaV0pLmlubmVySFRNTCA9IG9ialtrZXlzW2ldXTsKICAgICAgICB9CiAgICB9CiAgICBpZiAoIWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJtYWluLW1lbnUiKSkgewogICAgICAgIHJldHVybjsKICAgIH0KICAgIC8vIE1lbsO8IGVyc3RlbGxlbgogICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm1haW4tbWVudSIpLmlubmVySFRNTCA9ICIiOwogICAgZm9yICh2YXIgaV8xID0gMDsgaV8xIDwgbWVudUl0ZW1zLmxlbmd0aDsgaV8xKyspIHsKICAgICAgICBtZW51SXRlbXNbaV8xXS5pZCA9IGlfMTsKICAgICAgICBzd2l0Y2ggKG1lbnVJdGVtc1tpXzFdWyJtZW51S2V5Il0pIHsKICAgICAgICAgICAgY2FzZSAidXNlcnMiOgogICAgICAgICAgICBjYXNlICJsb2dvdXQiOgogICAgICAgICAgICAgICAgaWYgKFNFUlZFUlsic2V0dGluZ3MiXVsiYXV0aGVudGljYXRpb24ud2ViIl0gPT0gdHJ1ZSkgewogICAgICAgICAgICAgICAgICAgIG1lbnVJdGVtc1tpXzFdLmNyZWF0ZUl0ZW0oKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJtYXBwaW5nIjoKICAgICAgICAgICAgY2FzZSAieG1sdHYiOgogICAgICAgICAgICAgICAgaWYgKFNFUlZFUlsiY2xpZW50SW5mbyJdWyJlcGdTb3VyY2UiXSA9PSAiWEVQRyIpIHsKICAgICAgICAgICAgICAgICAgICBtZW51SXRlbXNbaV8xXS5jcmVhdGVJdGVtKCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIG1lbnVJdGVtc1tpXzFdLmNyZWF0ZUl0ZW0oKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybjsKfQpmdW5jdGlvbiBvcGVuVGhpc01lbnUoZWxlbWVudCkgewogICAgdmFyIGlkID0gZWxlbWVudC5pZDsKICAgIHZhciBjb250ZW50ID0gbmV3IFNob3dDb250ZW50KGlkKTsKICAgIGNvbnRlbnQuc2hvdygpOwogICAgY2FsY3VsYXRlV3JhcHBlckhlaWdodCgpOwogICAgcmV0dXJuOwp9CnZhciBQb3B1cFdpbmRvdyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFBvcHVwV2luZG93KCkgewogICAgICAgIHRoaXMuRG9jdW1lbnRJRCA9ICJwb3B1cC1jdXN0b20iOwogICAgICAgIHRoaXMuSW50ZXJhY3Rpb25JRCA9ICJpbnRlcmFjdGlvbiI7CiAgICAgICAgdGhpcy5kb2MgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLkRvY3VtZW50SUQpOwogICAgfQogICAgUG9wdXBXaW5kb3cucHJvdG90eXBlLmNyZWF0ZVRpdGxlID0gZnVuY3Rpb24gKHRpdGxlKSB7CiAgICAgICAgdmFyIHRkID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICB0ZC5jbGFzc05hbWUgPSAibGVmdCI7CiAgICAgICAgdGQuaW5uZXJIVE1MID0gdGl0bGUgKyAiOiI7CiAgICAgICAgcmV0dXJuIHRkOwogICAgfTsKICAgIFBvcHVwV2luZG93LnByb3RvdHlwZS5jcmVhdGVDb250ZW50ID0gZnVuY3Rpb24gKGVsZW1lbnQpIHsKICAgICAgICB2YXIgdGQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgIHRkLmFwcGVuZENoaWxkKGVsZW1lbnQpOwogICAgICAgIHJldHVybiB0ZDsKICAgIH07CiAgICBQb3B1cFdpbmRvdy5wcm90b3R5cGUuY3JlYXRlSW50ZXJhY3Rpb24gPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOwogICAgICAgIGRpdi5zZXRBdHRyaWJ1dGUoImlkIiwgInBvcHVwLWludGVyYWN0aW9uIik7CiAgICAgICAgZGl2LmNsYXNzTmFtZSA9ICJpbnRlcmFjdGlvbiI7CiAgICAgICAgdGhpcy5kb2MuYXBwZW5kQ2hpbGQoZGl2KTsKICAgIH07CiAgICByZXR1cm4gUG9wdXBXaW5kb3c7Cn0oKSk7CnZhciBQb3B1cENvbnRlbnQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7CiAgICBfX2V4dGVuZHMoUG9wdXBDb250ZW50LCBfc3VwZXIpOwogICAgZnVuY3Rpb24gUG9wdXBDb250ZW50KCkgewogICAgICAgIHZhciBfdGhpcyA9IF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzOwogICAgICAgIF90aGlzLnRhYmxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEFCTEUiKTsKICAgICAgICByZXR1cm4gX3RoaXM7CiAgICB9CiAgICBQb3B1cENvbnRlbnQucHJvdG90eXBlLmNyZWF0ZUhlYWRsaW5lID0gZnVuY3Rpb24gKGhlYWRsaW5lKSB7CiAgICAgICAgdGhpcy5kb2MuaW5uZXJIVE1MID0gIiI7CiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJIMyIpOwogICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gaGVhZGxpbmUudG9VcHBlckNhc2UoKTsKICAgICAgICB0aGlzLmRvYy5hcHBlbmRDaGlsZChlbGVtZW50KTsKICAgICAgICAvLyBUYWJlbGxlIGVyc3RlbGxlbgogICAgICAgIHRoaXMudGFibGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJUQUJMRSIpOwogICAgICAgIHRoaXMuZG9jLmFwcGVuZENoaWxkKHRoaXMudGFibGUpOwogICAgfTsKICAgIFBvcHVwQ29udGVudC5wcm90b3R5cGUuYXBwZW5kUm93ID0gZnVuY3Rpb24gKHRpdGxlLCBlbGVtZW50KSB7CiAgICAgICAgdmFyIHRyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVFIiKTsKICAgICAgICAvLyBCZXplaWNobnVuZwogICAgICAgIGlmICh0aXRsZS5sZW5ndGggIT0gMCkgewogICAgICAgICAgICB0ci5hcHBlbmRDaGlsZCh0aGlzLmNyZWF0ZVRpdGxlKHRpdGxlKSk7CiAgICAgICAgfQogICAgICAgIC8vIENvbnRlbnQKICAgICAgICB0ci5hcHBlbmRDaGlsZCh0aGlzLmNyZWF0ZUNvbnRlbnQoZWxlbWVudCkpOwogICAgICAgIHRoaXMudGFibGUuYXBwZW5kQ2hpbGQodHIpOwogICAgfTsKICAgIFBvcHVwQ29udGVudC5wcm90b3R5cGUuY3JlYXRlSW5wdXQgPSBmdW5jdGlvbiAodHlwZSwgbmFtZSwgdmFsdWUpIHsKICAgICAgICB2YXIgaW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJJTlBVVCIpOwogICAgICAgIGlmICh2YWx1ZSA9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgdmFsdWUgPSAiIjsKICAgICAgICB9CiAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJ0eXBlIiwgdHlwZSk7CiAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJuYW1lIiwgbmFtZSk7CiAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJ2YWx1ZSIsIHZhbHVlKTsKICAgICAgICByZXR1cm4gaW5wdXQ7CiAgICB9OwogICAgUG9wdXBDb250ZW50LnByb3RvdHlwZS5jcmVhdGVDaGVja2JveCA9IGZ1bmN0aW9uIChuYW1lKSB7CiAgICAgICAgdmFyIGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiSU5QVVQiKTsKICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInR5cGUiLCAiY2hlY2tib3giKTsKICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm5hbWUiLCBuYW1lKTsKICAgICAgICByZXR1cm4gaW5wdXQ7CiAgICB9OwogICAgUG9wdXBDb250ZW50LnByb3RvdHlwZS5jcmVhdGVTZWxlY3QgPSBmdW5jdGlvbiAodGV4dCwgdmFsdWVzLCBzZXQsIGRiS2V5KSB7CiAgICAgICAgdmFyIHNlbGVjdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlNFTEVDVCIpOwogICAgICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoIm5hbWUiLCBkYktleSk7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0ZXh0Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHZhciBvcHRpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJPUFRJT04iKTsKICAgICAgICAgICAgb3B0aW9uLnNldEF0dHJpYnV0ZSgidmFsdWUiLCB2YWx1ZXNbaV0pOwogICAgICAgICAgICBvcHRpb24uaW5uZXJUZXh0ID0gdGV4dFtpXTsKICAgICAgICAgICAgc2VsZWN0LmFwcGVuZENoaWxkKG9wdGlvbik7CiAgICAgICAgfQogICAgICAgIGlmIChzZXQgIT0gIiIpIHsKICAgICAgICAgICAgc2VsZWN0LnZhbHVlID0gc2V0OwogICAgICAgIH0KICAgICAgICBpZiAoc2V0ID09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBzZWxlY3QudmFsdWUgPSB2YWx1ZXNbMF07CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZWxlY3Q7CiAgICB9OwogICAgUG9wdXBDb250ZW50LnByb3RvdHlwZS5zZWxlY3RPcHRpb24gPSBmdW5jdGlvbiAoc2VsZWN0LCB2YWx1ZSkgewogICAgICAgIC8vc2VsZWN0LnNlbGVjdGVkT3B0aW9ucyA9IHZhbHVlCiAgICAgICAgdmFyIHMgPSBzZWxlY3Q7CiAgICAgICAgcy5vcHRpb25zW3Muc2VsZWN0ZWRJbmRleF0udmFsdWUgPSB2YWx1ZTsKICAgICAgICByZXR1cm4gc2VsZWN0OwogICAgfTsKICAgIFBvcHVwQ29udGVudC5wcm90b3R5cGUuZGVzY3JpcHRpb24gPSBmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgICB2YXIgdHIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJUUiIpOwogICAgICAgIHZhciB0ZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgdmFyIHNwYW4gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJQUkUiKTsKICAgICAgICBzcGFuLmlubmVySFRNTCA9IHZhbHVlOwogICAgICAgIHRyLmFwcGVuZENoaWxkKHRkKTsKICAgICAgICB0ci5hcHBlbmRDaGlsZCh0aGlzLmNyZWF0ZUNvbnRlbnQoc3BhbikpOwogICAgICAgIHRoaXMudGFibGUuYXBwZW5kQ2hpbGQodHIpOwogICAgfTsKICAgIC8vIEludGVyYWt0aW9uCiAgICBQb3B1cENvbnRlbnQucHJvdG90eXBlLmFkZEludGVyYWN0aW9uID0gZnVuY3Rpb24gKGVsZW1lbnQpIHsKICAgICAgICB2YXIgaW50ZXJhY3Rpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgicG9wdXAtaW50ZXJhY3Rpb24iKTsKICAgICAgICBpbnRlcmFjdGlvbi5hcHBlbmRDaGlsZChlbGVtZW50KTsKICAgIH07CiAgICByZXR1cm4gUG9wdXBDb250ZW50Owp9KFBvcHVwV2luZG93KSk7CmZ1bmN0aW9uIG9wZW5Qb3BVcChkYXRhVHlwZSwgZWxlbWVudCkgewogICAgdmFyIGRhdGEgPSBuZXcgT2JqZWN0KCk7CiAgICB2YXIgaWQ7CiAgICBzd2l0Y2ggKGVsZW1lbnQpIHsKICAgICAgICBjYXNlIHVuZGVmaW5lZDoKICAgICAgICAgICAgc3dpdGNoIChkYXRhVHlwZSkgewogICAgICAgICAgICAgICAgY2FzZSAiZ3JvdXAtdGl0bGUiOgogICAgICAgICAgICAgICAgICAgIGlmIChpZCA9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWQgPSAtMTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdldExvY2FsRGF0YSgiZmlsdGVyIiwgaWQpOwogICAgICAgICAgICAgICAgICAgIGRhdGFbInR5cGUiXSA9ICJncm91cC10aXRsZSI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJjdXN0b20tZmlsdGVyIjoKICAgICAgICAgICAgICAgICAgICBpZiAoaWQgPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlkID0gLTE7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZXRMb2NhbERhdGEoImZpbHRlciIsIGlkKTsKICAgICAgICAgICAgICAgICAgICBkYXRhWyJ0eXBlIl0gPSAiY3VzdG9tLWZpbHRlciI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgIGRhdGFbImlkLnByb3ZpZGVyIl0gPSAiLSI7CiAgICAgICAgICAgICAgICAgICAgZGF0YVsidHlwZSJdID0gZGF0YVR5cGU7CiAgICAgICAgICAgICAgICAgICAgaWQgPSAiLSI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgaWQgPSBlbGVtZW50LmlkOwogICAgICAgICAgICBkYXRhID0gZ2V0TG9jYWxEYXRhKGRhdGFUeXBlLCBpZCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgfQogICAgdmFyIGNvbnRlbnQgPSBuZXcgUG9wdXBDb250ZW50KCk7CiAgICBzd2l0Y2ggKGRhdGFUeXBlKSB7CiAgICAgICAgY2FzZSAicGxheWxpc3QiOgogICAgICAgICAgICBjb250ZW50LmNyZWF0ZUhlYWRsaW5lKCJ7ey5wbGF5bGlzdC5wbGF5bGlzdFR5cGUudGl0bGV9fSIpOwogICAgICAgICAgICAvLyBUeXBlCiAgICAgICAgICAgIHZhciB0ZXh0ID0gWyJNM1UiLCAiSERIb21lUnVuIl07CiAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBbImphdmFzY3JpcHQ6IG9wZW5Qb3BVcCgnbTN1JykiLCAiamF2YXNjcmlwdDogb3BlblBvcFVwKCdoZGhyJykiXTsKICAgICAgICAgICAgdmFyIHNlbGVjdCA9IGNvbnRlbnQuY3JlYXRlU2VsZWN0KHRleHQsIHZhbHVlcywgIiIsICJ0eXBlIik7CiAgICAgICAgICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoImlkIiwgInR5cGUiKTsKICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAnamF2YXNjcmlwdDogY2hhbmdlQnV0dG9uQWN0aW9uKHRoaXMsICJuZXh0IiwgIm9uY2xpY2siKScpOyAvLyBjaGFuZ2VCdXR0b25BY3Rpb24KICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnBsYXlsaXN0LnR5cGUudGl0bGV9fSIsIHNlbGVjdCk7CiAgICAgICAgICAgIC8vIEludGVyYWt0aW9uCiAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSW50ZXJhY3Rpb24oKTsKICAgICAgICAgICAgLy8gQWJicmVjaGVuCiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJjYW5jZWwiLCAie3suYnV0dG9uLmNhbmNlbH19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBzaG93RWxlbWVudCgicG9wdXAiLCBmYWxzZSk7Jyk7CiAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICAvLyBXZWl0ZXIKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgIm5leHQiLCAie3suYnV0dG9uLm5leHR9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogb3BlblBvcFVwKCJtM3UiKScpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoImlkIiwgJ25leHQnKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm0zdSI6CiAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSGVhZGxpbmUoZGF0YVR5cGUpOwogICAgICAgICAgICAvLyBOYW1lCiAgICAgICAgICAgIHZhciBkYktleSA9ICJuYW1lIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3sucGxheWxpc3QubmFtZS5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5wbGF5bGlzdC5uYW1lLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIEJlc2NocmVpYnVuZwogICAgICAgICAgICB2YXIgZGJLZXkgPSAiZGVzY3JpcHRpb24iOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5wbGF5bGlzdC5kZXNjcmlwdGlvbi5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5wbGF5bGlzdC5kZXNjcmlwdGlvbi50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAvLyBVUkwKICAgICAgICAgICAgdmFyIGRiS2V5ID0gImZpbGUuc291cmNlIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3sucGxheWxpc3QuZmlsZU0zVS5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5wbGF5bGlzdC5maWxlTTNVLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIFR1bmVyCiAgICAgICAgICAgIGlmIChTRVJWRVJbInNldHRpbmdzIl1bImJ1ZmZlciJdICE9ICItIikgewogICAgICAgICAgICAgICAgdmFyIHRleHQgPSBuZXcgQXJyYXkoKTsKICAgICAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBuZXcgQXJyYXkoKTsKICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDw9IDEwMDsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgdGV4dC5wdXNoKGkudG9TdHJpbmcoKSk7CiAgICAgICAgICAgICAgICAgICAgdmFsdWVzLnB1c2goaS50b1N0cmluZygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHZhciBkYktleSA9ICJ0dW5lciI7CiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ID0gY29udGVudC5jcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCBkYXRhW2RiS2V5XSwgZGJLZXkpOwogICAgICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgib25mb2N1cyIsICJqYXZhc2NyaXB0OiByZXR1cm47Iik7CiAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3sucGxheWxpc3QudHVuZXIudGl0bGV9fSIsIHNlbGVjdCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB2YXIgZGJLZXkgPSAidHVuZXIiOwogICAgICAgICAgICAgICAgaWYgKGRhdGFbZGJLZXldID09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgICAgIGRhdGFbZGJLZXldID0gMTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJyZWFkb25seSIsICJ0cnVlIik7CiAgICAgICAgICAgICAgICBpbnB1dC5jbGFzc05hbWUgPSAibm90QXZhaWxhYmxlIjsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5wbGF5bGlzdC50dW5lci50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnRlbnQuZGVzY3JpcHRpb24oInt7LnBsYXlsaXN0LnR1bmVyLmRlc2NyaXB0aW9ufX0iKTsKICAgICAgICAgICAgLy8gSW50ZXJha3Rpb24KICAgICAgICAgICAgY29udGVudC5jcmVhdGVJbnRlcmFjdGlvbigpOwogICAgICAgICAgICAvLyBMw7ZzY2hlbgogICAgICAgICAgICBpZiAoZGF0YVsiaWQucHJvdmlkZXIiXSAhPSAiLSIpIHsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJkZWxldGUiLCAie3suYnV0dG9uLmRlbGV0ZX19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5jbGFzc05hbWUgPSAiZGVsZXRlIjsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBzYXZlUG9wdXBEYXRhKCJtM3UiLCAiJyArIGlkICsgJyIsIHRydWUsIDApJyk7CiAgICAgICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJiYWNrIiwgInt7LmJ1dHRvbi5iYWNrfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoInBsYXlsaXN0IiknKTsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIEFiYnJlY2hlbgogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAiY2FuY2VsIiwgInt7LmJ1dHRvbi5jYW5jZWx9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogc2hvd0VsZW1lbnQoInBvcHVwIiwgZmFsc2UpOycpOwogICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgLy8gQWt0dWFsaXNpZXJlbgogICAgICAgICAgICBpZiAoZGF0YVsiaWQucHJvdmlkZXIiXSAhPSAiLSIpIHsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJ1cGRhdGUiLCAie3suYnV0dG9uLnVwZGF0ZX19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogc2F2ZVBvcHVwRGF0YSgibTN1IiwgIicgKyBpZCArICciLCBmYWxzZSwgMSknKTsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIFNwZWljaGVybgogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAic2F2ZSIsICJ7ey5idXR0b24uc2F2ZX19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBzYXZlUG9wdXBEYXRhKCJtM3UiLCAiJyArIGlkICsgJyIsIGZhbHNlLCAwKScpOwogICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiaGRociI6CiAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSGVhZGxpbmUoZGF0YVR5cGUpOwogICAgICAgICAgICAvLyBOYW1lCiAgICAgICAgICAgIHZhciBkYktleSA9ICJuYW1lIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3sucGxheWxpc3QubmFtZS5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5wbGF5bGlzdC5uYW1lLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIEJlc2NocmVpYnVuZwogICAgICAgICAgICB2YXIgZGJLZXkgPSAiZGVzY3JpcHRpb24iOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5wbGF5bGlzdC5kZXNjcmlwdGlvbi5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5wbGF5bGlzdC5kZXNjcmlwdGlvbi5wbGFjZWhvbGRlcn19IiwgaW5wdXQpOwogICAgICAgICAgICAvLyBVUkwKICAgICAgICAgICAgdmFyIGRiS2V5ID0gImZpbGUuc291cmNlIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3sucGxheWxpc3QuZmlsZUhESFIucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3sucGxheWxpc3QuZmlsZUhESFIudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gVHVuZXIKICAgICAgICAgICAgaWYgKFNFUlZFUlsic2V0dGluZ3MiXVsiYnVmZmVyIl0gIT0gIi0iKSB7CiAgICAgICAgICAgICAgICB2YXIgdGV4dCA9IG5ldyBBcnJheSgpOwogICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IG5ldyBBcnJheSgpOwogICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPD0gMTAwOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICB0ZXh0LnB1c2goaS50b1N0cmluZygpKTsKICAgICAgICAgICAgICAgICAgICB2YWx1ZXMucHVzaChpLnRvU3RyaW5nKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFyIGRiS2V5ID0gInR1bmVyIjsKICAgICAgICAgICAgICAgIHZhciBzZWxlY3QgPSBjb250ZW50LmNyZWF0ZVNlbGVjdCh0ZXh0LCB2YWx1ZXMsIGRhdGFbZGJLZXldLCBkYktleSk7CiAgICAgICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJvbmZvY3VzIiwgImphdmFzY3JpcHQ6IHJldHVybjsiKTsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5wbGF5bGlzdC50dW5lci50aXRsZX19Iiwgc2VsZWN0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHZhciBkYktleSA9ICJ0dW5lciI7CiAgICAgICAgICAgICAgICBpZiAoZGF0YVtkYktleV0gPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgZGF0YVtkYktleV0gPSAxOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInJlYWRvbmx5IiwgInRydWUiKTsKICAgICAgICAgICAgICAgIGlucHV0LmNsYXNzTmFtZSA9ICJub3RBdmFpbGFibGUiOwogICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnBsYXlsaXN0LnR1bmVyLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29udGVudC5kZXNjcmlwdGlvbigie3sucGxheWxpc3QudHVuZXIuZGVzY3JpcHRpb259fSIpOwogICAgICAgICAgICAvLyBJbnRlcmFrdGlvbgogICAgICAgICAgICBjb250ZW50LmNyZWF0ZUludGVyYWN0aW9uKCk7CiAgICAgICAgICAgIC8vIEzDtnNjaGVuCiAgICAgICAgICAgIGlmIChkYXRhWyJpZC5wcm92aWRlciJdICE9ICItIikgewogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgImRlbGV0ZSIsICJ7ey5idXR0b24uZGVsZXRlfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBzYXZlUG9wdXBEYXRhKCJoZGhyIiwgIicgKyBpZCArICciLCB0cnVlLCAwKScpOwogICAgICAgICAgICAgICAgaW5wdXQuY2xhc3NOYW1lID0gImRlbGV0ZSI7CiAgICAgICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJiYWNrIiwgInt7LmJ1dHRvbi5iYWNrfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoInBsYXlsaXN0IiknKTsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIEFiYnJlY2hlbgogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAiY2FuY2VsIiwgInt7LmJ1dHRvbi5jYW5jZWx9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogc2hvd0VsZW1lbnQoInBvcHVwIiwgZmFsc2UpOycpOwogICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgLy8gQWt0dWFsaXNpZXJlbgogICAgICAgICAgICBpZiAoZGF0YVsiaWQucHJvdmlkZXIiXSAhPSAiLSIpIHsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJ1cGRhdGUiLCAie3suYnV0dG9uLnVwZGF0ZX19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogc2F2ZVBvcHVwRGF0YSgiaGRociIsICInICsgaWQgKyAnIiwgZmFsc2UsIDEpJyk7CiAgICAgICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBTcGVpY2hlcm4KICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgInNhdmUiLCAie3suYnV0dG9uLnNhdmV9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogc2F2ZVBvcHVwRGF0YSgiaGRociIsICInICsgaWQgKyAnIiwgZmFsc2UsIDApJyk7CiAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJmaWx0ZXIiOgogICAgICAgICAgICBjb250ZW50LmNyZWF0ZUhlYWRsaW5lKGRhdGFUeXBlKTsKICAgICAgICAgICAgLy8gVHlwZQogICAgICAgICAgICB2YXIgZGJLZXkgPSAidHlwZSI7CiAgICAgICAgICAgIHZhciB0ZXh0ID0gWyJNM1U6ICIgKyAie3suZmlsdGVyLnR5cGUuZ3JvdXBUaXRsZX19IiwgInhUZVZlOiAiICsgInt7LmZpbHRlci50eXBlLmN1c3RvbUZpbHRlcn19Il07CiAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBbImphdmFzY3JpcHQ6IG9wZW5Qb3BVcCgnZ3JvdXAtdGl0bGUnKSIsICJqYXZhc2NyaXB0OiBvcGVuUG9wVXAoJ2N1c3RvbS1maWx0ZXInKSJdOwogICAgICAgICAgICB2YXIgc2VsZWN0ID0gY29udGVudC5jcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCAiamF2YXNjcmlwdDogb3BlblBvcFVwKCdncm91cC10aXRsZScpIiwgZGJLZXkpOwogICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJpZCIsIGlkKTsKICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAnamF2YXNjcmlwdDogY2hhbmdlQnV0dG9uQWN0aW9uKHRoaXMsICJuZXh0IiwgIm9uY2xpY2siKTsnKTsgLy8gY2hhbmdlQnV0dG9uQWN0aW9uCiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5maWx0ZXIudHlwZS50aXRsZX19Iiwgc2VsZWN0KTsKICAgICAgICAgICAgLy8gSW50ZXJha3Rpb24KICAgICAgICAgICAgY29udGVudC5jcmVhdGVJbnRlcmFjdGlvbigpOwogICAgICAgICAgICAvLyBBYmJyZWNoZW4KICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgImNhbmNlbCIsICJ7ey5idXR0b24uY2FuY2VsfX0iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHNob3dFbGVtZW50KCJwb3B1cCIsIGZhbHNlKTsnKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIC8vIFdlaXRlcgogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAibmV4dCIsICJ7ey5idXR0b24ubmV4dH19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoImdyb3VwLXRpdGxlIiknKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJpZCIsICduZXh0Jyk7CiAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJjdXN0b20tZmlsdGVyIjoKICAgICAgICBjYXNlICJncm91cC10aXRsZSI6CiAgICAgICAgICAgIHN3aXRjaCAoZGF0YVR5cGUpIHsKICAgICAgICAgICAgICAgIGNhc2UgImN1c3RvbS1maWx0ZXIiOgogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSGVhZGxpbmUoInt7LmZpbHRlci5jdXN0b219fSIpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiZ3JvdXAtdGl0bGUiOgogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSGVhZGxpbmUoInt7LmZpbHRlci5ncm91cH19Iik7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gTmFtZSAgICAgIAogICAgICAgICAgICB2YXIgZGJLZXkgPSAibmFtZSI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LmZpbHRlci5uYW1lLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LmZpbHRlci5uYW1lLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIEJlc2NocmVpYnVuZwogICAgICAgICAgICB2YXIgZGJLZXkgPSAiZGVzY3JpcHRpb24iOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5maWx0ZXIuZGVzY3JpcHRpb24ucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3suZmlsdGVyLmRlc2NyaXB0aW9uLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIFR5cAogICAgICAgICAgICB2YXIgZGJLZXkgPSAidHlwZSI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImhpZGRlbiIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCIiLCBpbnB1dCk7CiAgICAgICAgICAgIHZhciBmaWx0ZXJUeXBlID0gZGF0YVtkYktleV07CiAgICAgICAgICAgIHN3aXRjaCAoZmlsdGVyVHlwZSkgewogICAgICAgICAgICAgICAgY2FzZSAiY3VzdG9tLWZpbHRlciI6CiAgICAgICAgICAgICAgICAgICAgLy8gR3Jvw58tIEtsZWluc2NocmVpYnVuZyBiZWFjaHRlbgogICAgICAgICAgICAgICAgICAgIHZhciBkYktleSA9ICJjYXNlU2Vuc2l0aXZlIjsKICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KGRiS2V5KTsKICAgICAgICAgICAgICAgICAgICBpbnB1dC5jaGVja2VkID0gZGF0YVtkYktleV07CiAgICAgICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LmZpbHRlci5jYXNlU2Vuc2l0aXZlLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgICAgICAgICAgLy8gRmlsdGVycmVnZWwgKEJlbnV0emVyZGVmaW5pZXJ0KQogICAgICAgICAgICAgICAgICAgIHZhciBkYktleSA9ICJmaWx0ZXIiOwogICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3suZmlsdGVyLmZpbHRlclJ1bGUucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5maWx0ZXIuZmlsdGVyUnVsZS50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiZ3JvdXAtdGl0bGUiOgogICAgICAgICAgICAgICAgICAgIC8vYWxlcnQoZGJLZXkgKyAiICIgKyBmaWx0ZXJUeXBlKQogICAgICAgICAgICAgICAgICAgIC8vIEZpbHRlciBiYXNpZXJlbmQgYXVmIGRlbiBHcnVwcGVuIGluIGRlciBNM1UKICAgICAgICAgICAgICAgICAgICB2YXIgZGJLZXkgPSAiZmlsdGVyIjsKICAgICAgICAgICAgICAgICAgICB2YXIgZ3JvdXBzTTNVID0gZ2V0TG9jYWxEYXRhKCJtM3VHcm91cHMiLCAiIik7CiAgICAgICAgICAgICAgICAgICAgdmFyIHRleHQgPSBncm91cHNNM1VbInRleHQiXTsKICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWVzID0gZ3JvdXBzTTNVWyJ2YWx1ZSJdOwogICAgICAgICAgICAgICAgICAgIHZhciBzZWxlY3QgPSBjb250ZW50LmNyZWF0ZVNlbGVjdCh0ZXh0LCB2YWx1ZXMsIGRhdGFbZGJLZXldLCBkYktleSk7CiAgICAgICAgICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3suZmlsdGVyLmZpbHRlckdyb3VwLnRpdGxlfX0iLCBzZWxlY3QpOwogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuZGVzY3JpcHRpb24oInt7LmZpbHRlci5maWx0ZXJHcm91cC5kZXNjcmlwdGlvbn19Iik7CiAgICAgICAgICAgICAgICAgICAgLy8gR3Jvw58tIEtsZWluc2NocmVpYnVuZyBiZWFjaHRlbgogICAgICAgICAgICAgICAgICAgIHZhciBkYktleSA9ICJjYXNlU2Vuc2l0aXZlIjsKICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KGRiS2V5KTsKICAgICAgICAgICAgICAgICAgICBpbnB1dC5jaGVja2VkID0gZGF0YVtkYktleV07CiAgICAgICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LmZpbHRlci5jYXNlU2Vuc2l0aXZlLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgICAgICAgICAgdmFyIGRiS2V5ID0gImluY2x1ZGUiOwogICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3suZmlsdGVyLmluY2x1ZGUucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5maWx0ZXIuaW5jbHVkZS50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuZGVzY3JpcHRpb24oInt7LmZpbHRlci5pbmNsdWRlLmRlc2NyaXB0aW9ufX0iKTsKICAgICAgICAgICAgICAgICAgICB2YXIgZGJLZXkgPSAiZXhjbHVkZSI7CiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5maWx0ZXIuZXhjbHVkZS5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LmZpbHRlci5leGNsdWRlLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgICAgICAgICAgY29udGVudC5kZXNjcmlwdGlvbigie3suZmlsdGVyLmV4Y2x1ZGUuZGVzY3JpcHRpb259fSIpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBJbnRlcmFrdGlvbgogICAgICAgICAgICBjb250ZW50LmNyZWF0ZUludGVyYWN0aW9uKCk7CiAgICAgICAgICAgIC8vIEzDtnNjaGVuCiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJkZWxldGUiLCAie3suYnV0dG9uLmRlbGV0ZX19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBzYXZlUG9wdXBEYXRhKCJmaWx0ZXIiLCAiJyArIGlkICsgJyIsIHRydWUsIDApJyk7CiAgICAgICAgICAgIGlucHV0LmNsYXNzTmFtZSA9ICJkZWxldGUiOwogICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgLy8gQWJicmVjaGVuCiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJjYW5jZWwiLCAie3suYnV0dG9uLmNhbmNlbH19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBzaG93RWxlbWVudCgicG9wdXAiLCBmYWxzZSk7Jyk7CiAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICAvLyBTcGVpY2hlcm4KICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgInNhdmUiLCAie3suYnV0dG9uLnNhdmV9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogc2F2ZVBvcHVwRGF0YSgiZmlsdGVyIiwgIicgKyBpZCArICciLCBmYWxzZSwgMCknKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInhtbHR2IjoKICAgICAgICAgICAgY29udGVudC5jcmVhdGVIZWFkbGluZShkYXRhVHlwZSk7CiAgICAgICAgICAgIC8vIE5hbWUKICAgICAgICAgICAgdmFyIGRiS2V5ID0gIm5hbWUiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey54bWx0di5uYW1lLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnhtbHR2Lm5hbWUudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gQmVzY2hyZWlidW5nCiAgICAgICAgICAgIHZhciBkYktleSA9ICJkZXNjcmlwdGlvbiI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LnhtbHR2LmRlc2NyaXB0aW9uLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnhtbHR2LmRlc2NyaXB0aW9uLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIFVSTAogICAgICAgICAgICB2YXIgZGJLZXkgPSAiZmlsZS5zb3VyY2UiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey54bWx0di5maWxlWE1MVFYucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3sueG1sdHYuZmlsZVhNTFRWLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIEludGVyYWt0aW9uCiAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSW50ZXJhY3Rpb24oKTsKICAgICAgICAgICAgLy8gTMO2c2NoZW4KICAgICAgICAgICAgaWYgKGRhdGFbImlkLnByb3ZpZGVyIl0gIT0gIi0iKSB7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAiZGVsZXRlIiwgInt7LmJ1dHRvbi5kZWxldGV9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCdvbmNsaWNrJywgJ2phdmFzY3JpcHQ6IHNhdmVQb3B1cERhdGEoInhtbHR2IiwgIicgKyBpZCArICciLCB0cnVlLCAwKScpOwogICAgICAgICAgICAgICAgaW5wdXQuY2xhc3NOYW1lID0gImRlbGV0ZSI7CiAgICAgICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBBYmJyZWNoZW4KICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgImNhbmNlbCIsICJ7ey5idXR0b24uY2FuY2VsfX0iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHNob3dFbGVtZW50KCJwb3B1cCIsIGZhbHNlKTsnKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIC8vIEFrdHVhbGlzaWVyZW4KICAgICAgICAgICAgaWYgKGRhdGFbImlkLnByb3ZpZGVyIl0gIT0gIi0iKSB7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAidXBkYXRlIiwgInt7LmJ1dHRvbi51cGRhdGV9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCdvbmNsaWNrJywgJ2phdmFzY3JpcHQ6IHNhdmVQb3B1cERhdGEoInhtbHR2IiwgIicgKyBpZCArICciLCBmYWxzZSwgMSknKTsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIFNwZWljaGVybgogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAic2F2ZSIsICJ7ey5idXR0b24uc2F2ZX19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBzYXZlUG9wdXBEYXRhKCJ4bWx0diIsICInICsgaWQgKyAnIiwgZmFsc2UsIDApJyk7CiAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJ1c2VycyI6CiAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSGVhZGxpbmUoInt7Lm1haW5NZW51Lml0ZW0udXNlcnN9fSIpOwogICAgICAgICAgICAvLyBCZW51dHplcm5hbWUgCiAgICAgICAgICAgIHZhciBkYktleSA9ICJ1c2VybmFtZSI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LnVzZXJzLnVzZXJuYW1lLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnVzZXJzLnVzZXJuYW1lLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIE5ldWVzIFBhc3N3b3J0IAogICAgICAgICAgICB2YXIgZGJLZXkgPSAicGFzc3dvcmQiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJwYXNzd29yZCIsIGRiS2V5LCAiIik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3sudXNlcnMucGFzc3dvcmQucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3sudXNlcnMucGFzc3dvcmQudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gQmVzdMOkdGlndW5nIAogICAgICAgICAgICB2YXIgZGJLZXkgPSAiY29uZmlybSI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInBhc3N3b3JkIiwgZGJLZXksICIiKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey51c2Vycy5jb25maXJtLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnVzZXJzLmNvbmZpcm0udGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gQmVyZWNodGlndW5nIFdFQgogICAgICAgICAgICB2YXIgZGJLZXkgPSAiYXV0aGVudGljYXRpb24ud2ViIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVDaGVja2JveChkYktleSk7CiAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhW2RiS2V5XTsKICAgICAgICAgICAgaWYgKGRhdGFbImRlZmF1bHRVc2VyIl0gPT0gdHJ1ZSkgewogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgImphdmFzY3JpcHQ6IHJldHVybiBmYWxzZSIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey51c2Vycy53ZWIudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gQmVyZWNodGlndW5nIFBNUwogICAgICAgICAgICB2YXIgZGJLZXkgPSAiYXV0aGVudGljYXRpb24ucG1zIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVDaGVja2JveChkYktleSk7CiAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhW2RiS2V5XTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnVzZXJzLnBtcy50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAvLyBCZXJlY2h0aWd1bmcgTTNVCiAgICAgICAgICAgIHZhciBkYktleSA9ICJhdXRoZW50aWNhdGlvbi5tM3UiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KGRiS2V5KTsKICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGFbZGJLZXldOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3sudXNlcnMubTN1LnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIEJlcmVjaHRpZ3VuZyBYTUwKICAgICAgICAgICAgdmFyIGRiS2V5ID0gImF1dGhlbnRpY2F0aW9uLnhtbCI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goZGJLZXkpOwogICAgICAgICAgICBpbnB1dC5jaGVja2VkID0gZGF0YVtkYktleV07CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey51c2Vycy54bWwudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gQmVyZWNodGlndW5nIEFQSQogICAgICAgICAgICB2YXIgZGJLZXkgPSAiYXV0aGVudGljYXRpb24uYXBpIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVDaGVja2JveChkYktleSk7CiAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhW2RiS2V5XTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnVzZXJzLmFwaS50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAvLyBJbnRlcmFrdGlvbgogICAgICAgICAgICBjb250ZW50LmNyZWF0ZUludGVyYWN0aW9uKCk7CiAgICAgICAgICAgIC8vIEzDtnNjaGVuCiAgICAgICAgICAgIGlmIChkYXRhWyJkZWZhdWx0VXNlciJdICE9IHRydWUgJiYgaWQgIT0gIi0iKSB7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAiZGVsZXRlIiwgInt7LmJ1dHRvbi5kZWxldGV9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuY2xhc3NOYW1lID0gImRlbGV0ZSI7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogc2F2ZVBvcHVwRGF0YSgiJyArIGRhdGFUeXBlICsgJyIsICInICsgaWQgKyAnIiwgdHJ1ZSwgMCknKTsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIEFiYnJlY2hlbgogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAiY2FuY2VsIiwgInt7LmJ1dHRvbi5jYW5jZWx9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogc2hvd0VsZW1lbnQoInBvcHVwIiwgZmFsc2UpOycpOwogICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgLy8gU3BlaWNoZXJuCiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJzYXZlIiwgInt7LmJ1dHRvbi5zYXZlfX0iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHNhdmVQb3B1cERhdGEoIicgKyBkYXRhVHlwZSArICciLCAiJyArIGlkICsgJyIsICJmYWxzZSIpOycpOwogICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibWFwcGluZyI6CiAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSGVhZGxpbmUoInt7Lm1haW5NZW51Lml0ZW0ubWFwcGluZ319Iik7CiAgICAgICAgICAgIC8vIEFrdGl2IAogICAgICAgICAgICB2YXIgZGJLZXkgPSAieC1hY3RpdmUiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KGRiS2V5KTsKICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGFbZGJLZXldOwogICAgICAgICAgICBpbnB1dC5pZCA9ICJhY3RpdmUiOwogICAgICAgICAgICAvL2lucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKQogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRvZ2dsZUNoYW5uZWxTdGF0dXMoJyIgKyBpZCArICInLCB0aGlzKSIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3subWFwcGluZy5hY3RpdmUudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gS2FuYWxuYW1lIAogICAgICAgICAgICB2YXIgZGJLZXkgPSAieC1uYW1lIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgaWYgKEJVTEtfRURJVCA9PSB0cnVlKSB7CiAgICAgICAgICAgICAgICBpbnB1dC5zdHlsZS5ib3JkZXIgPSAic29saWQgMXB4IHJlZCI7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInJlYWRvbmx5IiwgInRydWUiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3subWFwcGluZy5jaGFubmVsTmFtZS50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICBjb250ZW50LmRlc2NyaXB0aW9uKGRhdGFbIm5hbWUiXSk7CiAgICAgICAgICAgIC8vIEJlc2NocmVpYnVuZyAKICAgICAgICAgICAgdmFyIGRiS2V5ID0gIngtZGVzY3JpcHRpb24iOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5tYXBwaW5nLmRlc2NyaXB0aW9uLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3subWFwcGluZy5kZXNjcmlwdGlvbi50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAvLyBBa3R1YWxpc2llcnVuZyBkZXMgS2FuYWxuYW1lbnMKICAgICAgICAgICAgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoIl91dWlkLmtleSIpKSB7CiAgICAgICAgICAgICAgICBpZiAoZGF0YVsiX3V1aWQua2V5Il0gIT0gIiIpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgZGJLZXkgPSAieC11cGRhdGUtY2hhbm5lbC1uYW1lIjsKICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KGRiS2V5KTsKICAgICAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGFbZGJLZXldOwogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5tYXBwaW5nLnVwZGF0ZUNoYW5uZWxOYW1lLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gTG9nbyBVUkwgKEthbmFsKSAKICAgICAgICAgICAgdmFyIGRiS2V5ID0gInR2Zy1sb2dvIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJpZCIsICJjaGFubmVsLWljb24iKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7Lm1hcHBpbmcuY2hhbm5lbExvZ28udGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gQWt0dWFsaXNpZXJ1bmcgZGVzIEthbmFsbG9nb3MKICAgICAgICAgICAgdmFyIGRiS2V5ID0gIngtdXBkYXRlLWNoYW5uZWwtaWNvbiI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goZGJLZXkpOwogICAgICAgICAgICBpbnB1dC5jaGVja2VkID0gZGF0YVtkYktleV07CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgiaWQiLCAidXBkYXRlLWljb24iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJzsgY2hhbmdlQ2hhbm5lbExvZ28oJyIgKyBpZCArICInKTsiKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7Lm1hcHBpbmcudXBkYXRlQ2hhbm5lbExvZ28udGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gRXJ3ZWl0ZXJuIGRlciBFUEcgS2F0ZWdvcmllCiAgICAgICAgICAgIHZhciBkYktleSA9ICJ4LWNhdGVnb3J5IjsKICAgICAgICAgICAgdmFyIHRleHQgPSBbIi0iLCAiS2lkcyAoRW1ieSBvbmx5KSIsICJOZXdzIiwgIk1vdmllIiwgIlNlcmllcyIsICJTcG9ydHMiXTsKICAgICAgICAgICAgdmFyIHZhbHVlcyA9IFsiIiwgIktpZHMiLCAiTmV3cyIsICJNb3ZpZSIsICJTZXJpZXMiLCAiU3BvcnRzIl07CiAgICAgICAgICAgIHZhciBzZWxlY3QgPSBjb250ZW50LmNyZWF0ZVNlbGVjdCh0ZXh0LCB2YWx1ZXMsIGRhdGFbZGJLZXldLCBkYktleSk7CiAgICAgICAgICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5tYXBwaW5nLmVwZ0NhdGVnb3J5LnRpdGxlfX0iLCBzZWxlY3QpOwogICAgICAgICAgICAvLyBNM1UgR3J1cHBlbnRpdGVsCiAgICAgICAgICAgIHZhciBkYktleSA9ICJ4LWdyb3VwLXRpdGxlIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7Lm1hcHBpbmcubTN1R3JvdXBUaXRsZS50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICBpZiAoZGF0YVsiZ3JvdXAtdGl0bGUiXSAhPSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgIGNvbnRlbnQuZGVzY3JpcHRpb24oZGF0YVsiZ3JvdXAtdGl0bGUiXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gWE1MVFYgRGF0ZWkKICAgICAgICAgICAgdmFyIGRiS2V5ID0gIngteG1sdHYtZmlsZSI7CiAgICAgICAgICAgIHZhciB4bWxGaWxlID0gZGF0YVtkYktleV07CiAgICAgICAgICAgIHZhciB4bWx0diA9IG5ldyBYTUxUVkZpbGUoKTsKICAgICAgICAgICAgdmFyIHNlbGVjdCA9IHhtbHR2LmdldEZpbGVzKGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgibmFtZSIsIGRiS2V5KTsKICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgiaWQiLCAicG9wdXAteG1sdHYiKTsKICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCc7IHNldFhtbHR2Q2hhbm5lbCgnIiArIGlkICsgIicsdGhpcyk7Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5tYXBwaW5nLnhtbHR2RmlsZS50aXRsZX19Iiwgc2VsZWN0KTsKICAgICAgICAgICAgdmFyIGZpbGUgPSBkYXRhW2RiS2V5XTsKICAgICAgICAgICAgLy8gWE1MVFYgTWFwcGluZwogICAgICAgICAgICB2YXIgZGJLZXkgPSAieC1tYXBwaW5nIjsKICAgICAgICAgICAgdmFyIHhtbHR2ID0gbmV3IFhNTFRWRmlsZSgpOwogICAgICAgICAgICB2YXIgc2VsZWN0ID0geG1sdHYuZ2V0UHJvZ3JhbXMoZmlsZSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJuYW1lIiwgZGJLZXkpOwogICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJpZCIsICJwb3B1cC1tYXBwaW5nIik7CiAgICAgICAgICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnOyBjaGVja1htbHR2Q2hhbm5lbCgnIiArIGlkICsgIicsdGhpcywnIiArIHhtbEZpbGUgKyAiJyk7Iik7CiAgICAgICAgICAgIHNvcnRTZWxlY3Qoc2VsZWN0KTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7Lm1hcHBpbmcueG1sdHZDaGFubmVsLnRpdGxlfX0iLCBzZWxlY3QpOwogICAgICAgICAgICAvLyBJbnRlcmFrdGlvbgogICAgICAgICAgICBjb250ZW50LmNyZWF0ZUludGVyYWN0aW9uKCk7CiAgICAgICAgICAgIC8vIExvZ28gaG9jaGxhZGVuCiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJjYW5jZWwiLCAie3suYnV0dG9uLnVwbG9hZExvZ299fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogdXBsb2FkTG9nbygpOycpOwogICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgLy8gQWJicmVjaGVuCiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJjYW5jZWwiLCAie3suYnV0dG9uLmNhbmNlbH19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBzaG93RWxlbWVudCgicG9wdXAiLCBmYWxzZSk7Jyk7CiAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICAvLyBGZXJ0aWcKICAgICAgICAgICAgdmFyIGlkcyA9IG5ldyBBcnJheSgpOwogICAgICAgICAgICBpZHMgPSBnZXRBbGxTZWxlY3RlZENoYW5uZWxzKCk7CiAgICAgICAgICAgIGlmIChpZHMubGVuZ3RoID09IDApIHsKICAgICAgICAgICAgICAgIGlkcy5wdXNoKGlkKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAic2F2ZSIsICJ7ey5idXR0b24uZG9uZX19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBkb25lUG9wdXBEYXRhKCInICsgZGF0YVR5cGUgKyAnIiwgIicgKyBpZHMgKyAnIiwgImZhbHNlIik7Jyk7CiAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICBicmVhazsKICAgIH0KICAgIHNob3dQb3BVcEVsZW1lbnQoJ3BvcHVwLWN1c3RvbScpOwp9CnZhciBYTUxUVkZpbGUgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBYTUxUVkZpbGUoKSB7CiAgICB9CiAgICBYTUxUVkZpbGUucHJvdG90eXBlLmdldEZpbGVzID0gZnVuY3Rpb24gKHNldCkgewogICAgICAgIHZhciBmaWxlSURzID0gZ2V0T2JqS2V5cyhTRVJWRVJbInhlcGciXVsieG1sdHZNYXAiXSk7CiAgICAgICAgdmFyIHZhbHVlcyA9IG5ldyBBcnJheSgiLSIpOwogICAgICAgIHZhciB0ZXh0ID0gbmV3IEFycmF5KCItIik7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmaWxlSURzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGlmIChmaWxlSURzW2ldICE9ICJ4VGVWZSBEdW1teSIpIHsKICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKGdldFZhbHVlRnJvbVByb3ZpZGVyRmlsZShmaWxlSURzW2ldLCAieG1sdHYiLCAiZmlsZS54dGV2ZSIpKTsKICAgICAgICAgICAgICAgIHRleHQucHVzaChnZXRWYWx1ZUZyb21Qcm92aWRlckZpbGUoZmlsZUlEc1tpXSwgInhtbHR2IiwgIm5hbWUiKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB2YWx1ZXMucHVzaChmaWxlSURzW2ldKTsKICAgICAgICAgICAgICAgIHRleHQucHVzaChmaWxlSURzW2ldKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB2YXIgc2VsZWN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiU0VMRUNUIik7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0ZXh0Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHZhciBvcHRpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJPUFRJT04iKTsKICAgICAgICAgICAgb3B0aW9uLnNldEF0dHJpYnV0ZSgidmFsdWUiLCB2YWx1ZXNbaV0pOwogICAgICAgICAgICBvcHRpb24uaW5uZXJUZXh0ID0gdGV4dFtpXTsKICAgICAgICAgICAgc2VsZWN0LmFwcGVuZENoaWxkKG9wdGlvbik7CiAgICAgICAgfQogICAgICAgIGlmIChzZXQgIT0gIiIpIHsKICAgICAgICAgICAgc2VsZWN0LnZhbHVlID0gc2V0OwogICAgICAgIH0KICAgICAgICByZXR1cm4gc2VsZWN0OwogICAgfTsKICAgIFhNTFRWRmlsZS5wcm90b3R5cGUuZ2V0UHJvZ3JhbXMgPSBmdW5jdGlvbiAoZmlsZSwgc2V0KSB7CiAgICAgICAgLy92YXIgZmlsZUlEczpzdHJpbmdbXSA9IGdldE9iaktleXMoU0VSVkVSWyJ4ZXBnIl1bInhtbHR2TWFwIl0pCiAgICAgICAgdmFyIHZhbHVlcyA9IGdldE9iaktleXMoU0VSVkVSWyJ4ZXBnIl1bInhtbHR2TWFwIl1bZmlsZV0pOwogICAgICAgIHZhciB0ZXh0ID0gbmV3IEFycmF5KCk7CiAgICAgICAgdmFyIGRpc3BsYXlOYW1lOwogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmFsdWVzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGlmIChTRVJWRVJbInhlcGciXVsieG1sdHZNYXAiXVtmaWxlXVt2YWx1ZXNbaV1dLmhhc093blByb3BlcnR5KCdkaXNwbGF5LW5hbWUnKSA9PSB0cnVlKSB7CiAgICAgICAgICAgICAgICBkaXNwbGF5TmFtZSA9IFNFUlZFUlsieGVwZyJdWyJ4bWx0dk1hcCJdW2ZpbGVdW3ZhbHVlc1tpXV1bImRpc3BsYXktbmFtZSJdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgZGlzcGxheU5hbWUgPSAiLSI7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGV4dFtpXSA9IGRpc3BsYXlOYW1lICsgIiAoIiArIHZhbHVlc1tpXSArICIpIjsKICAgICAgICB9CiAgICAgICAgdGV4dC51bnNoaWZ0KCItIik7CiAgICAgICAgdmFsdWVzLnVuc2hpZnQoIi0iKTsKICAgICAgICB2YXIgc2VsZWN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiU0VMRUNUIik7CiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0ZXh0Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHZhciBvcHRpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJPUFRJT04iKTsKICAgICAgICAgICAgb3B0aW9uLnNldEF0dHJpYnV0ZSgidmFsdWUiLCB2YWx1ZXNbaV0pOwogICAgICAgICAgICBvcHRpb24uaW5uZXJUZXh0ID0gdGV4dFtpXTsKICAgICAgICAgICAgc2VsZWN0LmFwcGVuZENoaWxkKG9wdGlvbik7CiAgICAgICAgfQogICAgICAgIGlmIChzZXQgIT0gIiIpIHsKICAgICAgICAgICAgc2VsZWN0LnZhbHVlID0gc2V0OwogICAgICAgIH0KICAgICAgICBpZiAoc2VsZWN0LnZhbHVlICE9IHNldCkgewogICAgICAgICAgICBzZWxlY3QudmFsdWUgPSAiLSI7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZWxlY3Q7CiAgICB9OwogICAgcmV0dXJuIFhNTFRWRmlsZTsKfSgpKTsKZnVuY3Rpb24gZ2V0VmFsdWVGcm9tUHJvdmlkZXJGaWxlKGZpbGUsIGZpbGVUeXBlLCBrZXkpIHsKICAgIGlmIChmaWxlID09ICJ4VGVWZSBEdW1teSIpIHsKICAgICAgICByZXR1cm4gZmlsZTsKICAgIH0KICAgIHZhciBmaWxlSUQ7CiAgICB2YXIgaW5kaWNhdG9yID0gZmlsZS5jaGFyQXQoMCk7CiAgICBzd2l0Y2ggKGluZGljYXRvcikgewogICAgICAgIGNhc2UgIk0iOgogICAgICAgICAgICBmaWxlVHlwZSA9ICJtM3UiOwogICAgICAgICAgICBmaWxlSUQgPSBmaWxlOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJIIjoKICAgICAgICAgICAgZmlsZVR5cGUgPSAiaGRociI7CiAgICAgICAgICAgIGZpbGVJRCA9IGZpbGU7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlgiOgogICAgICAgICAgICBmaWxlVHlwZSA9ICJ4bWx0diI7CiAgICAgICAgICAgIGZpbGVJRCA9IGZpbGUuc3Vic3RyaW5nKDAsIGZpbGUubGFzdEluZGV4T2YoJy4nKSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgfQogICAgaWYgKFNFUlZFUlsic2V0dGluZ3MiXVsiZmlsZXMiXVtmaWxlVHlwZV0uaGFzT3duUHJvcGVydHkoZmlsZUlEKSA9PSB0cnVlKSB7CiAgICAgICAgdmFyIGRhdGEgPSBTRVJWRVJbInNldHRpbmdzIl1bImZpbGVzIl1bZmlsZVR5cGVdW2ZpbGVJRF07CiAgICAgICAgcmV0dXJuIGRhdGFba2V5XTsKICAgIH0KICAgIHJldHVybjsKfQpmdW5jdGlvbiBzZXRYbWx0dkNoYW5uZWwoaWQsIGVsZW1lbnQpIHsKICAgIHZhciB4bWx0diA9IG5ldyBYTUxUVkZpbGUoKTsKICAgIHZhciB4bWxGaWxlID0gZWxlbWVudC52YWx1ZTsKICAgIHZhciB0dmdJZCA9IFNFUlZFUlsieGVwZyJdWyJlcGdNYXBwaW5nIl1baWRdWyJ0dmctaWQiXTsKICAgIHZhciB0ZCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJwb3B1cC1tYXBwaW5nIikucGFyZW50RWxlbWVudDsKICAgIHRkLmlubmVySFRNTCA9ICIiOwogICAgdmFyIHNlbGVjdCA9IHhtbHR2LmdldFByb2dyYW1zKGVsZW1lbnQudmFsdWUsIHR2Z0lkKTsKICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoIm5hbWUiLCAieC1tYXBwaW5nIik7CiAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJpZCIsICJwb3B1cC1tYXBwaW5nIik7CiAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJzsgY2hlY2tYbWx0dkNoYW5uZWwoJyIgKyBpZCArICInLHRoaXMsJyIgKyB4bWxGaWxlICsgIicpOyIpOwogICAgc2VsZWN0LmNsYXNzTmFtZSA9ICJjaGFuZ2VkIjsKICAgIHNvcnRTZWxlY3Qoc2VsZWN0KTsKICAgIHRkLmFwcGVuZENoaWxkKHNlbGVjdCk7CiAgICBjaGVja1htbHR2Q2hhbm5lbChpZCwgc2VsZWN0LCB4bWxGaWxlKTsKfQpmdW5jdGlvbiBjaGVja1htbHR2Q2hhbm5lbChpZCwgZWxlbWVudCwgeG1sRmlsZSkgewogICAgdmFyIHZhbHVlID0gZWxlbWVudC52YWx1ZTsKICAgIHZhciBib29sOwogICAgdmFyIGNoZWNrYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2FjdGl2ZScpOwogICAgdmFyIGNoYW5uZWwgPSBTRVJWRVJbInhlcGciXVsiZXBnTWFwcGluZyJdW2lkXTsKICAgIHZhciB1cGRhdGVMb2dvOwogICAgaWYgKHZhbHVlID09ICItIikgewogICAgICAgIGJvb2wgPSBmYWxzZTsKICAgIH0KICAgIGVsc2UgewogICAgICAgIGJvb2wgPSB0cnVlOwogICAgfQogICAgY2hlY2tib3guY2hlY2tlZCA9IGJvb2w7CiAgICBjaGVja2JveC5jbGFzc05hbWUgPSAiY2hhbmdlZCI7CiAgICBjb25zb2xlLmxvZyh4bWxGaWxlKTsKICAgIC8vIEthbmFsbG9nbyBha3R1YWxpc2llcmVuCiAgICAvKgogICAgdXBkYXRlTG9nbyA9IChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidXBkYXRlLWljb24iKSBhcyBIVE1MSW5wdXRFbGVtZW50KS5jaGVja2VkCiAgICBjb25zb2xlLmxvZyh1cGRhdGVMb2dvKTsKICAgICovCiAgICBpZiAoeG1sRmlsZSAhPSAieFRlVmUgRHVtbXkiICYmIGJvb2wgPT0gdHJ1ZSkgewogICAgICAgIC8vKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ1cGRhdGUtaWNvbiIpIGFzIEhUTUxJbnB1dEVsZW1lbnQpLmNoZWNrZWQgPSB0cnVlOwogICAgICAgIC8vKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ1cGRhdGUtaWNvbiIpIGFzIEhUTUxJbnB1dEVsZW1lbnQpLmNsYXNzTmFtZSA9ICJjaGFuZ2VkIjsKICAgICAgICBjb25zb2xlLmxvZygiSUQiLCBpZCk7CiAgICAgICAgY2hhbmdlQ2hhbm5lbExvZ28oaWQpOwogICAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh4bWxGaWxlID09ICJ4VGVWZSBEdW1teSIpIHsKICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidXBkYXRlLWljb24iKS5jaGVja2VkID0gZmFsc2U7CiAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInVwZGF0ZS1pY29uIikuY2xhc3NOYW1lID0gImNoYW5nZWQiOwogICAgfQogICAgcmV0dXJuOwp9CmZ1bmN0aW9uIGNoYW5nZUNoYW5uZWxMb2dvKGlkKSB7CiAgICB2YXIgdXBkYXRlTG9nbzsKICAgIHZhciBjaGFubmVsID0gU0VSVkVSWyJ4ZXBnIl1bImVwZ01hcHBpbmciXVtpZF07CiAgICB2YXIgZiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJwb3B1cC14bWx0diIpOwogICAgdmFyIHhtbHR2RmlsZSA9IGYub3B0aW9uc1tmLnNlbGVjdGVkSW5kZXhdLnZhbHVlOwogICAgdmFyIG0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgicG9wdXAtbWFwcGluZyIpOwogICAgdmFyIHhNYXBwaW5nID0gbS5vcHRpb25zW20uc2VsZWN0ZWRJbmRleF0udmFsdWU7CiAgICB2YXIgeG1sdHZMb2dvID0gU0VSVkVSWyJ4ZXBnIl1bInhtbHR2TWFwIl1beG1sdHZGaWxlXVt4TWFwcGluZ11bImljb24iXTsKICAgIHVwZGF0ZUxvZ28gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidXBkYXRlLWljb24iKS5jaGVja2VkOwogICAgaWYgKHVwZGF0ZUxvZ28gPT0gdHJ1ZSAmJiB4bWx0dkZpbGUgIT0gInhUZVZlIER1bW15IikgewogICAgICAgIGlmIChTRVJWRVJbInhlcGciXVsieG1sdHZNYXAiXVt4bWx0dkZpbGVdLmhhc093blByb3BlcnR5KHhNYXBwaW5nKSkgewogICAgICAgICAgICB2YXIgbG9nbyA9IHhtbHR2TG9nbzsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGxvZ28gPSBjaGFubmVsWyJ0dmctbG9nbyJdOwogICAgICAgIH0KICAgICAgICB2YXIgbG9nb0lucHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImNoYW5uZWwtaWNvbiIpOwogICAgICAgIGxvZ29JbnB1dC52YWx1ZSA9IGxvZ287CiAgICAgICAgaWYgKEJVTEtfRURJVCA9PSBmYWxzZSkgewogICAgICAgICAgICBsb2dvSW5wdXQuY2xhc3NOYW1lID0gImNoYW5nZWQiOwogICAgICAgIH0KICAgIH0KfQpmdW5jdGlvbiBzYXZlUG9wdXBEYXRhKGRhdGFUeXBlLCBpZCwgcmVtb3ZlLCBvcHRpb24pIHsKICAgIGlmIChkYXRhVHlwZSA9PSAibWFwcGluZyIpIHsKICAgICAgICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICAgICAgICBjb25zb2xlLmxvZygiU2F2ZSBtYXBwaW5nIGRhdGEiKTsKICAgICAgICBjbWQgPSAic2F2ZUVwZ01hcHBpbmciOwogICAgICAgIGRhdGFbImVwZ01hcHBpbmciXSA9IFNFUlZFUlsieGVwZyJdWyJlcGdNYXBwaW5nIl07CiAgICAgICAgY29uc29sZS5sb2coIlNFTkQgVE8gU0VSVkVSIik7CiAgICAgICAgdmFyIHNlcnZlciA9IG5ldyBTZXJ2ZXIoY21kKTsKICAgICAgICBzZXJ2ZXIucmVxdWVzdChkYXRhKTsKICAgICAgICBkZWxldGUgVU5ET1siZXBnTWFwcGluZyJdOwogICAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnNvbGUubG9nKCJTYXZlIHBvcHVwIGRhdGEiKTsKICAgIHZhciBkaXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgicG9wdXAtY3VzdG9tIik7CiAgICB2YXIgaW5wdXRzID0gZGl2LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJUQUJMRSIpWzBdLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJJTlBVVCIpOwogICAgdmFyIHNlbGVjdHMgPSBkaXYuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlRBQkxFIilbMF0uZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlNFTEVDVCIpOwogICAgdmFyIGlucHV0ID0gbmV3IE9iamVjdCgpOwogICAgdmFyIGNvbmZpcm1Nc2c7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNlbGVjdHMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgbmFtZTsKICAgICAgICBuYW1lID0gc2VsZWN0c1tpXS5uYW1lOwogICAgICAgIHZhciB2YWx1ZSA9IHNlbGVjdHNbaV0udmFsdWU7CiAgICAgICAgc3dpdGNoIChuYW1lKSB7CiAgICAgICAgICAgIGNhc2UgInR1bmVyIjoKICAgICAgICAgICAgICAgIGlucHV0W25hbWVdID0gcGFyc2VJbnQodmFsdWUpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBpbnB1dFtuYW1lXSA9IHZhbHVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgfQogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbnB1dHMubGVuZ3RoOyBpKyspIHsKICAgICAgICBzd2l0Y2ggKGlucHV0c1tpXS50eXBlKSB7CiAgICAgICAgICAgIGNhc2UgImNoZWNrYm94IjoKICAgICAgICAgICAgICAgIG5hbWUgPSBpbnB1dHNbaV0ubmFtZTsKICAgICAgICAgICAgICAgIGlucHV0W25hbWVdID0gaW5wdXRzW2ldLmNoZWNrZWQ7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAidGV4dCI6CiAgICAgICAgICAgIGNhc2UgImhpZGRlbiI6CiAgICAgICAgICAgIGNhc2UgInBhc3N3b3JkIjoKICAgICAgICAgICAgICAgIG5hbWUgPSBpbnB1dHNbaV0ubmFtZTsKICAgICAgICAgICAgICAgIHN3aXRjaCAobmFtZSkgewogICAgICAgICAgICAgICAgICAgIGNhc2UgInR1bmVyIjoKICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRbbmFtZV0gPSBwYXJzZUludChpbnB1dHNbaV0udmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICBpbnB1dFtuYW1lXSA9IGlucHV0c1tpXS52YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9CiAgICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICAgIHZhciBjbWQ7CiAgICBpZiAocmVtb3ZlID09IHRydWUpIHsKICAgICAgICBpbnB1dFsiZGVsZXRlIl0gPSB0cnVlOwogICAgfQogICAgc3dpdGNoIChkYXRhVHlwZSkgewogICAgICAgIGNhc2UgInVzZXJzIjoKICAgICAgICAgICAgY29uZmlybU1zZyA9ICJEZWxldGUgdGhpcyB1c2VyPyI7CiAgICAgICAgICAgIGlmIChpZCA9PSAiLSIpIHsKICAgICAgICAgICAgICAgIGNtZCA9ICJzYXZlTmV3VXNlciI7CiAgICAgICAgICAgICAgICBkYXRhWyJ1c2VyRGF0YSJdID0gaW5wdXQ7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBjbWQgPSAic2F2ZVVzZXJEYXRhIjsKICAgICAgICAgICAgICAgIHZhciBkID0gbmV3IE9iamVjdCgpOwogICAgICAgICAgICAgICAgZFtpZF0gPSBpbnB1dDsKICAgICAgICAgICAgICAgIGRhdGFbInVzZXJEYXRhIl0gPSBkOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm0zdSI6CiAgICAgICAgICAgIGNvbmZpcm1Nc2cgPSAiRGVsZXRlIHRoaXMgcGxheWxpc3Q/IjsKICAgICAgICAgICAgc3dpdGNoIChvcHRpb24pIHsKICAgICAgICAgICAgICAgIC8vIFBvcHVwOiBTYXZlCiAgICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICAgICAgY21kID0gInNhdmVGaWxlc00zVSI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAvLyBQb3B1cDogVXBkYXRlCiAgICAgICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgICAgICAgY21kID0gInVwZGF0ZUZpbGVNM1UiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRhdGFbImZpbGVzIl0gPSBuZXcgT2JqZWN0OwogICAgICAgICAgICBkYXRhWyJmaWxlcyJdW2RhdGFUeXBlXSA9IG5ldyBPYmplY3Q7CiAgICAgICAgICAgIGRhdGFbImZpbGVzIl1bZGF0YVR5cGVdW2lkXSA9IGlucHV0OwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJoZGhyIjoKICAgICAgICAgICAgY29uZmlybU1zZyA9ICJEZWxldGUgdGhpcyBIREhvbWVSdW4gdHVuZXI/IjsKICAgICAgICAgICAgc3dpdGNoIChvcHRpb24pIHsKICAgICAgICAgICAgICAgIC8vIFBvcHVwOiBTYXZlCiAgICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICAgICAgY21kID0gInNhdmVGaWxlc0hESFIiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgLy8gUG9wdXA6IFVwZGF0ZQogICAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgICAgIGNtZCA9ICJ1cGRhdGVGaWxlSERIUiI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZGF0YVsiZmlsZXMiXSA9IG5ldyBPYmplY3Q7CiAgICAgICAgICAgIGRhdGFbImZpbGVzIl1bZGF0YVR5cGVdID0gbmV3IE9iamVjdDsKICAgICAgICAgICAgZGF0YVsiZmlsZXMiXVtkYXRhVHlwZV1baWRdID0gaW5wdXQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInhtbHR2IjoKICAgICAgICAgICAgY29uZmlybU1zZyA9ICJEZWxldGUgdGhpcyBYTUxUViBmaWxlPyI7CiAgICAgICAgICAgIHN3aXRjaCAob3B0aW9uKSB7CiAgICAgICAgICAgICAgICAvLyBQb3B1cDogU2F2ZQogICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICAgIGNtZCA9ICJzYXZlRmlsZXNYTUxUViI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAvLyBQb3B1cDogVXBkYXRlCiAgICAgICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgICAgICAgY21kID0gInVwZGF0ZUZpbGVYTUxUViI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZGF0YVsiZmlsZXMiXSA9IG5ldyBPYmplY3Q7CiAgICAgICAgICAgIGRhdGFbImZpbGVzIl1bZGF0YVR5cGVdID0gbmV3IE9iamVjdDsKICAgICAgICAgICAgZGF0YVsiZmlsZXMiXVtkYXRhVHlwZV1baWRdID0gaW5wdXQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImZpbHRlciI6CiAgICAgICAgICAgIGNvbmZpcm1Nc2cgPSAiRGVsZXRlIHRoaXMgZmlsdGVyPyI7CiAgICAgICAgICAgIGNtZCA9ICJzYXZlRmlsdGVyIjsKICAgICAgICAgICAgZGF0YVsiZmlsdGVyIl0gPSBuZXcgT2JqZWN0OwogICAgICAgICAgICBkYXRhWyJmaWx0ZXIiXVtpZF0gPSBpbnB1dDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgY29uc29sZS5sb2coZGF0YVR5cGUsIGlkKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICBicmVhazsKICAgIH0KICAgIGlmIChyZW1vdmUgPT0gdHJ1ZSkgewogICAgICAgIGlmICghY29uZmlybShjb25maXJtTXNnKSkgewogICAgICAgICAgICBzaG93RWxlbWVudCgicG9wdXAiLCBmYWxzZSk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICB9CiAgICBjb25zb2xlLmxvZygiU0VORCBUTyBTRVJWRVIiKTsKICAgIGNvbnNvbGUubG9nKGRhdGEpOwogICAgdmFyIHNlcnZlciA9IG5ldyBTZXJ2ZXIoY21kKTsKICAgIHNlcnZlci5yZXF1ZXN0KGRhdGEpOwp9CmZ1bmN0aW9uIGRvbmVQb3B1cERhdGEoZGF0YVR5cGUsIGlkc1N0cikgewogICAgdmFyIGlkcyA9IGlkc1N0ci5zcGxpdCgnLCcpOwogICAgdmFyIGRpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJwb3B1cC1jdXN0b20iKTsKICAgIHZhciBpbnB1dHMgPSBkaXYuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgiY2hhbmdlZCIpOwogICAgaWRzLmZvckVhY2goZnVuY3Rpb24gKGlkKSB7CiAgICAgICAgdmFyIGlucHV0ID0gbmV3IE9iamVjdCgpOwogICAgICAgIGlucHV0ID0gU0VSVkVSWyJ4ZXBnIl1bImVwZ01hcHBpbmciXVtpZF07CiAgICAgICAgY29uc29sZS5sb2coaW5wdXQpOwogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5wdXRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHZhciBuYW1lOwogICAgICAgICAgICB2YXIgdmFsdWU7CiAgICAgICAgICAgIHN3aXRjaCAoaW5wdXRzW2ldLnRhZ05hbWUpIHsKICAgICAgICAgICAgICAgIGNhc2UgIklOUFVUIjoKICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGlucHV0c1tpXS50eXBlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgImNoZWNrYm94IjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSBpbnB1dHNbaV0ubmFtZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gaW5wdXRzW2ldLmNoZWNrZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dFtuYW1lXSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgInRleHQiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9IGlucHV0c1tpXS5uYW1lOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBpbnB1dHNbaV0udmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dFtuYW1lXSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiU0VMRUNUIjoKICAgICAgICAgICAgICAgICAgICBuYW1lID0gaW5wdXRzW2ldLm5hbWU7CiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBpbnB1dHNbaV0udmFsdWU7CiAgICAgICAgICAgICAgICAgICAgaW5wdXRbbmFtZV0gPSB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBzd2l0Y2ggKG5hbWUpIHsKICAgICAgICAgICAgICAgIGNhc2UgInR2Zy1sb2dvIjoKICAgICAgICAgICAgICAgICAgICAvLyhkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCkuY2hpbGROb2Rlc1syXS5maXJzdENoaWxkIGFzIEhUTUxFbGVtZW50KS5zZXRBdHRyaWJ1dGUoInNyYyIsIHZhbHVlKQogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAieC1uYW1lIjoKICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCkuY2hpbGROb2Rlc1szXS5maXJzdENoaWxkLmlubmVySFRNTCA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAieC1jYXRlZ29yeSI6CiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpLmNoaWxkTm9kZXNbM10uZmlyc3RDaGlsZC5jbGFzc05hbWUgPSB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgIngtZ3JvdXAtdGl0bGUiOgogICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jaGlsZE5vZGVzWzVdLmZpcnN0Q2hpbGQuaW5uZXJIVE1MID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJ4LXhtbHR2LWZpbGUiOgogICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSAhPSAieFRlVmUgRHVtbXkiICYmIHZhbHVlICE9ICItIikgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGdldFZhbHVlRnJvbVByb3ZpZGVyRmlsZSh2YWx1ZSwgInhtbHR2IiwgIm5hbWUiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlID09ICItIikgewogICAgICAgICAgICAgICAgICAgICAgICBpbnB1dFsieC1hY3RpdmUiXSA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCkuY2hpbGROb2Rlc1s2XS5maXJzdENoaWxkLmlubmVySFRNTCA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAieC1tYXBwaW5nIjoKICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgPT0gIi0iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0WyJ4LWFjdGl2ZSJdID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jaGlsZE5vZGVzWzddLmZpcnN0Q2hpbGQuaW5uZXJIVE1MID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB9CiAgICAgICAgICAgIGNyZWF0ZVNlYXJjaE9iaigpOwogICAgICAgICAgICBzZWFyY2hJbk1hcHBpbmcoKTsKICAgICAgICB9CiAgICAgICAgaWYgKGlucHV0WyJ4LWFjdGl2ZSJdID09IGZhbHNlKSB7CiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jbGFzc05hbWUgPSAibm90QWN0aXZlRVBHIjsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jbGFzc05hbWUgPSAiYWN0aXZlRVBHIjsKICAgICAgICB9CiAgICAgICAgY29uc29sZS5sb2coaW5wdXRbInR2Zy1sb2dvIl0pOwogICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jaGlsZE5vZGVzWzJdLmZpcnN0Q2hpbGQuc2V0QXR0cmlidXRlKCJzcmMiLCBpbnB1dFsidHZnLWxvZ28iXSk7CiAgICB9KTsKICAgIHNob3dFbGVtZW50KCJwb3B1cCIsIGZhbHNlKTsKICAgIHJldHVybjsKfQpmdW5jdGlvbiBzaG93UHJldmlldyhlbGVtZW50KSB7CiAgICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm15U3RyZWFtc0JveCIpOwogICAgc3dpdGNoIChlbGVtZW50KSB7CiAgICAgICAgY2FzZSBmYWxzZToKICAgICAgICAgICAgZGl2LmNsYXNzTmFtZSA9ICJub3RWaXNpYmxlIjsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICBicmVhazsKICAgIH0KICAgIHZhciBzdHJlYW1zID0gWyJhY3RpdmVTdHJlYW1zIiwgImluYWN0aXZlU3RyZWFtcyJdOwogICAgc3RyZWFtcy5mb3JFYWNoKGZ1bmN0aW9uIChwcmV2aWV3KSB7CiAgICAgICAgdmFyIHRhYmxlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocHJldmlldyk7CiAgICAgICAgdGFibGUuaW5uZXJIVE1MID0gIiI7CiAgICAgICAgdmFyIG9iaiA9IFNFUlZFUlsiZGF0YSJdWyJTdHJlYW1QcmV2aWV3VUkiXVtwcmV2aWV3XTsKICAgICAgICBvYmouZm9yRWFjaChmdW5jdGlvbiAoY2hhbm5lbCkgewogICAgICAgICAgICB2YXIgdHIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJUUiIpOwogICAgICAgICAgICB2YXIgdGRLZXkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICB2YXIgdGRWYWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICB0ZEtleS5jbGFzc05hbWUgPSAidGRLZXkiOwogICAgICAgICAgICB0ZFZhbC5jbGFzc05hbWUgPSAidGRWYWwiOwogICAgICAgICAgICBzd2l0Y2ggKHByZXZpZXcpIHsKICAgICAgICAgICAgICAgIGNhc2UgImFjdGl2ZVN0cmVhbXMiOgogICAgICAgICAgICAgICAgICAgIHRkS2V5LmlubmVyVGV4dCA9ICJDaGFubmVsOiAoKykiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiaW5hY3RpdmVTdHJlYW1zIjoKICAgICAgICAgICAgICAgICAgICB0ZEtleS5pbm5lclRleHQgPSAiQ2hhbm5lbDogKC0pIjsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICB0ZFZhbC5pbm5lclRleHQgPSBjaGFubmVsOwogICAgICAgICAgICB0ci5hcHBlbmRDaGlsZCh0ZEtleSk7CiAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKHRkVmFsKTsKICAgICAgICAgICAgdGFibGUuYXBwZW5kQ2hpbGQodHIpOwogICAgICAgIH0pOwogICAgfSk7CiAgICBzaG93RWxlbWVudCgibG9hZGluZyIsIGZhbHNlKTsKICAgIGRpdi5jbGFzc05hbWUgPSAidmlzaWJsZSI7CiAgICByZXR1cm47Cn0K" - webUI["html/css/screen.css"] = "bmF2IGltZyB7CiAgZGlzcGxheTogYmxvY2s7CiAgbWF4LWhlaWdodDogMjBweDsKICBtYXgtd2lkdGg6IDIwcHg7CiAgZmxvYXQ6IGxlZnQ7Cn0KCm5hdiBwIHsKICB0ZXh0LWFsaWduOiBsZWZ0OwogIHBhZGRpbmc6IDBweCAzMHB4Owp9CgojbGF5b3V0IHsKICBkaXNwbGF5OiBibG9jazsKICBoZWlnaHQ6IDEwMCU7Cn0KCgoubGF5b3V0LWxlZnQgewogIGRpc3BsYXk6IGJsb2NrOwogIG1pbi13aWR0aDogMTUwcHg7CiAgbWF4LXdpZHRoOiAyMCU7CiAgYmFja2dyb3VuZC1jb2xvcjogIzExMTsKICBoZWlnaHQ6IGluaGVyaXQ7CiAgZmxvYXQ6IGxlZnQ7Cn0KCi5sYXlvdXQtcmlnaHQgewogIGRpc3BsYXk6IGJsb2NrOwogIGJhY2tncm91bmQtY29sb3I6ICM0NDQ7Cn0KCiNtZW51LXdyYXBwZXIgewogIGhlaWdodDogMTAwJTsKfQoKCiNsb2dvIHsKICBkaXNwbGF5OiBibG9jazsKICBtaW4td2lkdGg6IDE4MHB4OwogIHdpZHRoOiAxMDAlOwogIGhlaWdodDogMTAwcHg7CiAgYmFja2dyb3VuZDogdXJsKCIuLi9pbWcvbG9nb193XzYwMHgyMDAucG5nIik7CiAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDsKICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiBjZW50ZXI7IAogIGJhY2tncm91bmQtc2l6ZTogMTAwJTsKfQoKCiNwYWdlIHsKICBtYXgtd2lkdGg6IDk1MHB4OwogIG1hcmdpbjogYXV0bzsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDQ0OwoKICAvKgogIGhlaWdodDogLXdlYmtpdC1jYWxjKDEwMCUgLSAxMzBweCk7CiAgaGVpZ2h0OiAtbW96LWNhbGMoMTAwJSAtIDEzMHB4KTsKICBoZWlnaHQ6IGNhbGMoMTAwJSAtIDEzMHB4KTsKICAqLwogIAogIG1pbi1oZWlnaHQ6IC13ZWJraXQtY2FsYygxMDAlIC0gMTIwcHgpOwogIG1pbi1oZWlnaHQ6IC1tb3otY2FsYygxMDAlIC0gMTIwcHgpOwogIG1pbi1oZWlnaHQ6IGNhbGMoMTAwJSAtIDEyMHB4KTsKICAKICAKICBib3gtc2hhZG93OiAwcHggNXB4IDVweCAjMjIyOwogIAp9CgojdWlTZXR0aW5nIHsKICBmbG9hdDogcmlnaHQ7CiAgbWFyZ2luLXJpZ2h0OiAyNXB4Owp9CgojYm94IGlucHV0W3R5cGU9dGV4dF0sICNib3ggaW5wdXRbdHlwZT1wYXNzd29yZF0gewogIHdpZHRoOiAtd2Via2l0LWNhbGMoMTAwJSAtIDIwcHgpOwogIHdpZHRoOiAtbW96LWNhbGMoMTAwJSAtIDIwcHgpOwogIHdpZHRoOiBjYWxjKDEwMCUgLSAyMHB4KTsKfQoKI2JveCBpbnB1dFt0eXBlPXN1Ym1pdF17CiAgbWFyZ2luOiA1MHB4IGF1dG87Cn0KCiNzZXR0aW5ncyB7CiAgZGlzcGxheTogYmxvY2s7CiAgcGFkZGluZzogMTBweCAxMHB4Owp9Cgojc2V0dGluZ3MgaDUgewogIG1hcmdpbjogNTBweCAwcHggMTBweCAwcHg7Cn0KCiNjb250ZW50LWludGVyYWN0aW9uIC5zZWFyY2ggewogIHdpZHRoOiAyMDBweDsKICBib3JkZXI6IDFweCBzb2xpZCAjMDAwOwogIHBhZGRpbmc6IDlweDsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzMzOwogIG1hcmdpbjogMTBweDsKICBmbG9hdDogcmlnaHQ7CiAgYm9yZGVyLXJhZGl1czogM3B4OwoKfQoKI215U3RyZWFtcyB7CiAgcG9zaXRpb246IGZpeGVkOwogIGJvdHRvbTogMHB4OwogIGJhY2tncm91bmQtY29sb3I6ICMxMTE7CiAgd2lkdGg6IDEwMCU7CiAgbWF4LXdpZHRoOiA5NTBweDsKCiAgLyoKICBtYXgtaGVpZ2h0OiAxMDBweDsKICAqLwogIG1hcmdpbi1ib3R0b206IDBweDsKfQoKI215U3RyZWFtcyBpbWcgewogIHdpZHRoOiA0JTsKICBwYWRkaW5nOiAycHggNXB4OwogIGN1cnNvcjogcG9pbnRlcjsKICBmbG9hdDogcmlnaHQ7Cn0KCiNzZXR0aW5ncy1mb290ZXIgewoKfQoKCi8qIFdpemFyZCovCiNib3ggewogIGJhY2tncm91bmQtY29sb3I6ICM0NDQ7CiAgbWluLWhlaWdodDogNDAwcHg7CiAgCiAgZGlzcGxheTogZmxleDsKICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjsKfQoKI2JveCBwewogIHBhZGRpbmc6IDEwcHggMHB4Owp9CgojYm94LWZvb3RlciB7CiAgbWFyZ2luLXRvcDogYXV0bzsKfQoKI2JveC1mb290ZXIgewogIG1hcmdpbjogYXV0bzsKICBwYWRkaW5nOiAxMHB4Owp9CgojaGVhZGxpbmUgewogIGJhY2tncm91bmQtY29sb3I6ICMyMjI7CiAgYm9yZGVyLWJvdHRvbTogc29saWQgMnB4ICMyMjI7CiAgdHJhbnNpdGlvbjogYWxsIDAuNXM7CiAgcGFkZGluZzogMTBweCAwcHg7CiAgZGlzcGxheTogYmxvY2s7Cn0KCiNjb250ZW50IHsKICBkaXNwbGF5OiBibG9jazsKICBvdmVyZmxvdzogYXV0bzsKICBwYWRkaW5nOiAxMHB4Owp9CgovKiAtLS0gKi8KCgojY2xpZW50SW5mbywgI2FjdGl2ZVN0cmVhbXMsICNpbmFjdGl2ZVN0cmVhbXMgewogIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7CiAgZGlzcGxheTogYmxvY2s7CiAgZm9udC1zaXplOiA5cHg7CiAgYmFja2dyb3VuZC1jb2xvcjogIzExMTsKICBjb2xvcjogIzAwRTZGRjsKICBib3JkZXItYm90dG9tOiBzb2xpZCAwcHg7OwogIHBhZGRpbmc6IDBweDsKICBsZXR0ZXItc3BhY2luZzogMXB4OwogIG92ZXJmbG93LXg6IGhpZGRlbjsKICBib3JkZXItc3BhY2luZzogNHB4IDRweDsKICBib3JkZXItYm90dG9tOiBzb2xpZCAxcHggIzQ0NDsKfQoKI215U3RyZWFtc0JveCB7CiAgcG9zaXRpb246IHJlbGF0aXZlOwogIHBhZGRpbmc6IDBweDsKICAvKmhlaWdodDogMTAwcHg7Ki8KICBtYXgtaGVpZ2h0OiAxNTBweDsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTExOwogIGNvbG9yOiB3aGl0ZTsKICBkaXNwbGF5OmZsZXg7CiAganVzdGlmeS1jb250ZW50OmNlbnRlcjsKICBhbGlnbi1pdGVtczpjZW50ZXI7Cn0KCiNvcGVuU3RyZWFtcyB7CiAgd2lkdGg6IDIwcHg7CiAgaGVpZ2h0OiAyMHB4OwogIGN1cnNvcjogcG9pbnRlcjsKICBmbG9hdDogcmlnaHQ7CiAgcG9zaXRpb246IGFic29sdXRlOwogIHJpZ2h0OiAwcHg7CiAgYm90dG9tOiAwcHg7CiAgYmFja2dyb3VuZDogdXJsKCIuLi9pbWcvdG91Y2gucG5nIik7CiAgYmFja2dyb3VuZC1jb2xvcjogIzExMTsKICAKICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiBib3R0b20gcmlnaHQ7ICAKfQoKI2FsbFN0cmVhbXMgewogIHdpZHRoOiAxMDAlOwogIGhlaWdodDogMTAwJTsKICBwYWRkaW5nOiAycHg7ICAgICAKfQoKI2FjdGl2ZVN0cmVhbXMsICNpbmFjdGl2ZVN0cmVhbXMgewogIG92ZXJmbG93LXk6IHNjcm9sbDsKICB3aWR0aDogNTAlOwogIG1heC1oZWlnaHQ6IDEwMHB4OwogIGZsb2F0OiBsZWZ0Owp9CgojYWN0aXZlU3RyZWFtcyAudGRLZXksICNpbmFjdGl2ZVN0cmVhbXMgLnRkS2V5IHsKICB3aWR0aDogNzVweDsKfQoKCgoKI2luYWN0aXZlU3RyZWFtcyAudGRLZXkgewogIGNvbG9yOiByZWQ7Cn0KCiNjbGllbnRJbmZvIC50ZFZhbCwgI2xvZ0luZm8gLnRkVmFsLCAjYWN0aXZlU3RyZWFtcyAudGRWYWwsICNpbmFjdGl2ZVN0cmVhbXMgLnRkVmFsLCAjbWFwcGluZ0luZm8gLnRkVmFsewogIGNvbG9yOiAjYWFhOwogIHdoaXRlLXNwYWNlOiBpbmhlcml0Owp9CgojYm94LXdyYXBwZXIgewogIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICB3aWR0aDogMTAwJTsKICAKICBvdmVyZmxvdy15OiBzY3JvbGw7Cn0KCiNjb250ZW50X3RhYmxlLCAjbWFwcGluZy1kZXRhaWwtdGFibGUsICNjb250ZW50X3RhYmxlIHsKICBkaXNwbGF5OiB0YWJsZTsKICAKICBib3JkZXItY29sbGFwc2U6IGNvbGxhcHNlOwogIG92ZXJmbG93LXk6IHNjcm9sbDsKICB3aWR0aDogMTAwJTsKfQoKCiNjb250ZW50X3RhYmxlIC5jb250ZW50X3RhYmxlX2hlYWRlciB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzMzMzsKICBoZWlnaHQ6IDUwcHg7CiAgYm9yZGVyLWJvdHRvbTogc29saWQgMXB4ICMxMTE7CiAgYm9yZGVyLWxlZnQ6IHNvbGlkIDNweCAjMzMzOwogIGN1cnNvcjogYXV0bzsKCn0KCgp0Ym9keSB7CiAgd2lkdGg6IDEwMCU7Cn0KCgoudGFibGVFbGxpcHNpcyB7CiAgd2lkdGg6IDE1MHB4OwogIG92ZXJmbG93OiBoaWRkZW47CiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7CiAgd2hpdGUtc3BhY2U6IG5vd3JhcDsKfQoKI2NvbnRlbnRfdGFibGUgaW1nIHsKICBkaXNwbGF5OiBibG9jazsKICBtYXgtaGVpZ2h0OiAyOHB4OwogIG1hcmdpbi1sZWZ0OiBhdXRvOwogIG1hcmdpbi1yaWdodDogYXV0bzsKICBtYXgtd2lkdGg6IDMwcHg7Cn0KCiNjb250ZW50X3RhYmxlIHRyewogIGJvcmRlci1sZWZ0OiBzb2xpZCAzcHggNDQ0OwogIGJvcmRlci1ib3R0b206IHNvbGlkIDFweCAjMzMzOwogIGN1cnNvcjogcG9pbnRlcjsKfQoKI2NvbnRlbnRfdGFibGUgdHI6aG92ZXIgewogIGJhY2tncm91bmQtY29sb3I6ICMzMzM7Cn0KCiNjb250ZW50X3RhYmxlIHRkIHsKCiAgcGFkZGluZzogMHB4IDJweDsKfQoKI2NvbnRlbnRfdGFibGUgaW5wdXRbdHlwZT10ZXh0XXsKICB3aWR0aDogODAlOwogIG1pbi13aWR0aDogMzVweDsKICBtYXgtd2lkdGg6IDYwcHg7CiAgYm9yZGVyOiAwcHg7CiAgYmFja2dyb3VuZC1jb2xvcjogIzMzMzsKICBtYXJnaW4tbGVmdDogNXB4OwogIHRleHQtYWxpZ246IGxlZnQ7Cn0KCiNjb250ZW50X3RhYmxlIGlucHV0W3R5cGU9Y2hlY2tib3hdewogIG1heC13aWR0aDogMjVweDsKICBtYXJnaW46IGF1dG87Cn0KCgouc2hvd0J1bGsgewogIGRpc3BsYXk6IGJsb2NrOwp9CgouaGlkZUJ1bGsgewogIGRpc3BsYXk6IG5vbmU7Cn0KCi5ub0J1bGsgewoKfQoKI2NvbnRlbnRfdGFibGUgdHIuYWN0aXZlRVBHewogIGJvcmRlci1sZWZ0OiBzb2xpZCAzcHggbGF3bmdyZWVuOwp9CgojY29udGVudF90YWJsZSB0ci5ub3RBY3RpdmVFUEd7CiAgYm9yZGVyLWxlZnQ6IHNvbGlkIDNweCByZWQ7Cn0KCgojbG9nU2NyZWVuIHB7CiAgd2hpdGUtc3BhY2U6IHByZTsKICBmb250LXNpemU6IDEwcHg7CiAgLyoKICBsaW5lLWhlaWdodDogMS42ZW07CiAgZm9udC1mYW1pbHk6ICJBcmlhbCIsIHNhbnMtc2VyaWY7CiAgKi8KICBsZXR0ZXItc3BhY2luZzogMXB4OwogIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7IAogIGZvbnQtc2l6ZTogMTJweDsgCiAgZm9udC1zdHlsZTogbm9ybWFsOyAKICBmb250LXZhcmlhbnQ6IG5vcm1hbDsgCiAgbGluZS1oZWlnaHQ6IDEuNmVtOyAKfQoKI3BvcHVwIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDAsIDAsIDAsIDAuNCk7CiAgcG9zaXRpb246IGZpeGVkOwogIGxlZnQ6IDBweDsKICB3aWR0aDogMTAwJTsKICB6LWluZGV4OiAxMDA7CiAgaGVpZ2h0OiAxMDAlOwp9CgojbWFwcGluZy1kZXRhaWwsICN1c2VyLWRldGFpbCwgI2ZpbGUtZGV0YWlsLCAjcG9wdXAtY3VzdG9tIHsKICBib3gtc2hhZG93OiAwcHggNXB4IDQwcHggIzAwMDsKICBtYXJnaW4tdG9wOiAyMHB4OwogIG1hcmdpbi1sZWZ0OiBhdXRvOwogIG1hcmdpbi1yaWdodDogYXV0bzsKICAKICBtYXgtd2lkdGg6IDYwMHB4OwogIGJhY2tncm91bmQtY29sb3I6ICMyMjI7CiAgcGFkZGluZzogMTBweDsKICBvdmVyZmxvdzphdXRvOwp9CgojcG9wdXAtY3VzdG9tIGgzIHsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCiNmaWxlLWRldGFpbCBpbnB1dFt0eXBlPXRleHRdIHsKICB3aWR0aDogLXdlYmtpdC1jYWxjKDEwMCUgLSAyMHB4KTsKICB3aWR0aDogLW1vei1jYWxjKDEwMCUgLSAyMHB4KTsKICB3aWR0aDogY2FsYygxMDAlIC0gMjBweCk7Cn0KCiNtYXBwaW5nLWRldGFpbCBpbWcgewogIGRpc3BsYXk6IGJsb2NrOwogIG1heC1oZWlnaHQ6IDMwcHg7CiAgbWFyZ2luLWJvdHRvbTogMjBweDsKICBtYXJnaW4tbGVmdDogYXV0bzsKICBtYXJnaW4tcmlnaHQ6IGF1dG87Cn0KCiNwb3B1cC1jdXN0b20gaW5wdXRbdHlwZT10ZXh0XSwgI3BvcHVwLWN1c3RvbSBpbnB1dFt0eXBlPXBhc3N3b3JkXSwgI21hcHBpbmctZGV0YWlsIGlucHV0W3R5cGU9dGV4dF0sICNjb250ZW50X3NldHRpbmdzIGlucHV0W3R5cGU9dGV4dF0sICNjb250ZW50X3NldHRpbmdzIGlucHV0W3R5cGU9cGFzc3dvcmRdewogIGJvcmRlcjogc29saWQgMXB4OwogIGJvcmRlci1jb2xvcjogdHJhbnNwYXJlbnQ7CiAgYmFja2dyb3VuZC1jb2xvcjogIzMzMzsKICB0ZXh0LWFsaWduOiBsZWZ0OwogIHdpZHRoOiAtd2Via2l0LWNhbGMoMTAwJSAtIDIwcHgpOwogIHdpZHRoOiAgICAtbW96LWNhbGMoMTAwJSAtIDIwcHgpOwogIHdpZHRoOiAgICAgICAgIGNhbGMoMTAwJSAtIDIwcHgpOwp9CgojcG9wdXAtY3VzdG9tIGlucHV0W3R5cGU9dGV4dF0ubm90QXZhaWxhYmxlIHsKICBib3JkZXItY29sb3I6IHJlZDsKICBjb2xvcjogIzY2NjsKICBjdXJzb3I6IG5vdC1hbGxvd2VkOwp9CgojbWFwcGluZy1kZXRhaWwtdGFibGUsICN1c2VyLWRldGFpbC10YWJsZSB7CiAgZGlzcGxheTogaW5saW5lLXRhYmxlOwogIHdpZHRoOiAxMDAlOwp9CgojcG9wdXAtY3VzdG9tIHRhYmxlLCAjY29udGVudF9zZXR0aW5ncyB0YWJsZSB7CiAgZGlzcGxheTogaW5saW5lLXRhYmxlOwogIHRhYmxlLWxheW91dDogZml4ZWQ7CiAgd2lkdGg6IDEwMCU7Cn0KCgojbWFwcGluZy1kZXRhaWwtdGFibGUgdGQsICN1c2VyLWRldGFpbC10YWJsZSB0ZCB7CiAgcGFkZGluZzogMTBweCAwcHg7Cgp9CgojbWFwcGluZy1kZXRhaWwtdGFibGUgdGQubGVmdCwgI3VzZXItZGV0YWlsLXRhYmxlIHRkLmxlZnQsICNwb3B1cC1jdXN0b20gdGQubGVmdCB7CiAgd2lkdGg6IDM4JTsKfQoKLmludGVyYWN0aW9uLCAjaW50ZXJhY3Rpb24gewogIG1hcmdpbi10b3A6IDIwcHg7CiAgZGlzcGxheTogaW5saW5lLWZsZXg7CiAgZmxvYXQ6IHJpZ2h0Owp9CgouaW50ZXJhY3Rpb24gaW5wdXRbdHlwZT1idXR0b25dLCAuaW50ZXJhY3Rpb24gaW5wdXRbdHlwZT1zdWJtaXRdIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwOwogIG1pbi13aWR0aDogMTAwcHg7CiAgbWFyZ2luOiAwcHggMTBweDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCiNub3RpZmljYXRpb24gewogIGRpc3BsYXk6IGJsb2NrOwogIHBvc2l0aW9uOiBmaXhlZDsKICByaWdodDogMHB4OwogIGhlaWdodDogMTAwJTsKICB3aWR0aDogMjUwcHg7CiAgCiAgYmFja2dyb3VuZC1jb2xvcjogIzIyMjsKICBib3gtc2hhZG93OiAwcHggMHB4IDIwcHggIzAwMDsKfQoKI25vdGlmaWNhdGlvbiBoNSB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzEyMTIxMjsKICBwYWRkaW5nOiA1cHggMTBweCA1cHggMTBweDsKfQoKI25vdGlmaWNhdGlvbiBwcmUgewogIHBhZGRpbmc6IDBweCAxMHB4IDBweCAxMHB4Owp9Cgojbm90aWZpY2F0aW9uIHAgewogIGZvbnQtc2l6ZTogMTAgcHg7CiAgbWFyZ2luOiAwcHg7CiAgcGFkZGluZzogMHB4IDEwcHggNXB4IDEwcHg7Cn0KCiNub3RpZmljYXRpb24gLmVsZW1lbnQgewogIC8qcGFkZGluZzogMHB4IDVweDsqLwogIG1hcmdpbjogNXB4IDVweDsKICBib3JkZXItcmFkaXVzOiA1cHg7CiAgYmFja2dyb3VuZC1jb2xvcjogIzE4MTgxODsKICBib3JkZXItbGVmdDogMTBweCBzb2xpZCBncmVlbjsKfQoKCkBtZWRpYSBvbmx5IHNjcmVlbiBhbmQgKG1pbi13aWR0aDogNjIwcHgpewogIGJvZHkgewogICAgd2lkdGg6IDEwMCU7CiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDQ0OwogIH0KCiAgaDEgewogICAgZm9udC1zaXplOiAyNnB4OwogICAgbGV0dGVyLXNwYWNpbmc6IDNweDsKICB9CgogIG5hdiBwIHsKICAgIGRpc3BsYXk6IGJsb2NrOwogIH0KCgoKICAjaGVhZGVyX2NvbmZpZyB7CiAgICBkaXNwbGF5OiBibG9jazsKICAgIGhlaWdodDogMTAwcHg7CiAgICBiYWNrZ3JvdW5kOiB1cmwoIi4uL2ltZy9sb2dvX3dfNjAweDIwMC5wbmciKTsKICAgIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7CiAgICAKICAgIGJhY2tncm91bmQtc2l6ZTogMzAwcHggMTAwcHg7CiAgfQoKICAjc2NyZWVuTG9nIHsKICAgIG1hcmdpbi1sZWZ0OiAzMDBweDsKCiAgICB0cmFuc2l0aW9uOiBub25lOwogICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7CiAgICBib3JkZXItYm90dG9tOiBzb2xpZCAxcHggdHJhbnNwYXJlbnQ7CiAgICBib3gtc2hhZG93OiAwcHggMHB4IDBweCAjMjIyOwogIH0KCiAgI3NldHRpbmdzIHsKICAgIC8qCiAgICBoZWlnaHQ6IC13ZWJraXQtY2FsYygxMDAlIC0gMTAwcHgpOwogICAgaGVpZ2h0OiAtbW96LWNhbGMoMTAwJSAtIDEwMHB4KTsKICAgIGhlaWdodDogY2FsYygxMDAlIC0gMTAwcHgpOwogICAgKi8KICAgIHBvc2l0aW9uOiByZWxhdGl2ZTsKICAgIG92ZXJmbG93OiBhdXRvOwogIH0KCgogIC5zY3JlZW5Mb2dIaWRkZW4gewogICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoMHB4LCAwcHgpOwogIH0KCgogICNib3ggewogICAgZGlzcGxheTogYmxvY2s7CiAgICBtaW4taGVpZ2h0OiA1MDBweDsKICAgIG1heC13aWR0aDogNTAwcHg7CiAgICBtYXJnaW46IDEwcHggYXV0bzsKICAgIGJhY2tncm91bmQtY29sb3I6ICM0NDQ7CiAgICBib3gtc2hhZG93OiAwcHggNXB4IDVweCAjMjIyOwoKICAgIGRpc3BsYXk6IGZsZXg7CiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogIH0KCiAgI3NldHRpbmdzLCAjc2V0dGluZ3MtZm9vdGVyIHsKICAgIAogIH0KfQo=" - webUI["html/js/authentication.js"] = "ZnVuY3Rpb24gY3JlYXRlRmlyc3RBY2NvdW50KGVsbSkgewogIHZhciBlcnIgPSBmYWxzZTsKICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZWxtKTsKICBjb25zb2xlLmxvZyhkaXYpOwoKICB2YXIgZm9ybSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhdXRoZW50aWNhdGlvbicpOwogIAogIGNvbnN0IHVzZXJuYW1lICA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd1c2VybmFtZScpOwogIGNvbnN0IHBhc3N3b3JkICA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwYXNzd29yZCcpOwogIGNvbnN0IGNvbmZpcm0gICA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjb25maXJtJyk7CgogIHZhciBpbnB1dHMgPSBkaXYuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ0lOUFVUJykKICBjb25zb2xlLmxvZyhjb25maXJtKTsKCiAgc3dpdGNoKGNvbmZpcm0pIHsKICAgIGNhc2UgbnVsbDogYnJlYWs7CiAgICAKICAgIGRlZmF1bHQ6IAogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGlucHV0cy5sZW5ndGg7IGkrKykgewogICAgICAgIGlmIChpbnB1dHNbaV0udmFsdWUubGVuZ3RoID09IDApIHsKICAgICAgICAgIGlucHV0c1tpXS5zdHlsZS5ib3JkZXJDb2xvciA9ICdyZWQnOwogICAgICAgICAgZXJyID0gdHJ1ZQogICAgICAgIH0KICAgICAgfQoKICAgICAgc3dpdGNoKGVycikgewogICAgICAgIGNhc2UgdHJ1ZTogcmV0dXJuOyBicmVhazsKICAgICAgICBjYXNlIGZhbHNlOiAKICAgICAgICAgIGlmIChwYXNzd29yZC52YWx1ZSAhPSBjb25maXJtLnZhbHVlKSB7CiAgICAgICAgICAgIGNvbmZpcm0uc3R5bGUuYm9yZGVyQ29sb3IgPSAncmVkJzsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICB9CgoKICAKCiAgZm9ybS5zdWJtaXQoKTsKICByZXR1cm47Cn0=" - webUI["html/js/configuaration.js"] = "dmFyIGNvbmZpZ01lbnUgPSBuZXcgT2JqZWN0KCk7CnZhciB3aXphcmQgPSBuZXcgQXJyYXkoImtleSIsICJ0dW5lciIsICJlcGdTb3VyY2UiLCAibTN1IiwgImNvbXBsZXRlIik7CnZhciBhY3RpdmVXaXphcmQ7CnZhciBkdnJJUAoKdmFyIGNvbmZpZ01lbnVfdHVuZXIgPSBuZXcgT2JqZWN0KCk7CmNvbmZpZ01lbnVfdHVuZXJbIl9lbGVtZW50Il0gICAgICA9ICJTRUxFQ1QiOwpjb25maWdNZW51X3R1bmVyWyJfbWVudVR5cGUiXSAgICAgPSAic2luZ2xlSW5wdXQiOwpjb25maWdNZW51X3R1bmVyWyJfY29uZmlnS2V5Il0gICAgPSAidHVuZXIiOwpjb25maWdNZW51X3R1bmVyWyJfbGFiZWwiXSAgICAgICAgPSAiQXZhaWxhYmxlIHR1bmVycyI7CmNvbmZpZ01lbnVfdHVuZXJbIm5hbWUiXSAgICAgICAgICA9ICJ0dW5lciI7CmNvbmZpZ01lbnVfdHVuZXJbImlkIl0gICAgICAgICAgICA9ICJUdW5lciI7CmNvbmZpZ01lbnVfdHVuZXJbInBsYWNlaG9sZGVyIl0gICA9ICJUdW5lciI7CmNvbmZpZ01lbnVfdHVuZXJbIl91c2FnZSJdICAgICAgICA9ICJUaGlzIHNldHRpbmcgaXMgb25seSB1c2VkIGJ5IFBsZXggYW5kIEVtYnkuPGJyPlRoZSBudW1iZXIgb2YgY29uY3VycmVudCBzdHJlYW1zIGFsbG93ZWQgYnkgdGhlIElQVFYgcHJvdmlkZXIuIgoKCnZhciBvcHRpb25WYWx1ZXMgPSBuZXcgQXJyYXkoKTsKZm9yICh2YXIgaSA9IDE7IGkgPD0gMTAwOyBpKyspIHsKICBvcHRpb25WYWx1ZXMucHVzaChpKQp9CmNvbmZpZ01lbnVfdHVuZXJbIl9vcHRpb25WYWx1ZXMiXSA9IG9wdGlvblZhbHVlczsKCnZhciBjb25maWdNZW51X2VwZyA9IG5ldyBPYmplY3QoKTsKY29uZmlnTWVudV9lcGdbIl9lbGVtZW50Il0gICAgICA9ICJTRUxFQ1QiOwpjb25maWdNZW51X2VwZ1siX21lbnVUeXBlIl0gICAgID0gInNpbmdsZUlucHV0IjsKY29uZmlnTWVudV9lcGdbIl9jb25maWdLZXkiXSAgICA9ICJlcGdTb3VyY2UiOwpjb25maWdNZW51X2VwZ1siX2xhYmVsIl0gICAgICAgID0gIlNlbGVjdGlvbiBvZiB0aGUgRVBHIHNvdXJjZSI7CmNvbmZpZ01lbnVfZXBnWyJuYW1lIl0gICAgICAgICAgPSAiZXBnU291cmNlIjsKY29uZmlnTWVudV9lcGdbImlkIl0gICAgICAgICAgICA9ICJFUEcgc291cmNlIjsKY29uZmlnTWVudV9lcGdbInBsYWNlaG9sZGVyIl0gICA9ICJFUEcgc291cmNlIjsKY29uZmlnTWVudV9lcGdbIl9vcHRpb25WYWx1ZXMiXSA9IG5ldyBBcnJheSgiUE1TIiwgIlhFUEciKTsKY29uZmlnTWVudV9lcGdbIl91c2FnZSJdICAgICAgICA9ICJQTVM6ICAgVXNlIEVQRyBkYXRhIGZyb20gUGxleCBvciBFbWJ5PGJyPlhFUEc6ICBVc2Ugb2YgZXh0ZXJuYWwgRVBHIGRhdGEgKFhNTFRWKTxicj4gICAgICAgU2V2ZXJhbCBYTUxUViBzb3VyY2VzIHBvc3NpYmxlPGJyPiAgICAgICBBbGxvd3MgZWRpdGluZyBhbmQgb3JkZXIgY2hhbm5lbHM8YnI+ICAgICAgIE0zVSAvIFhNTFRWIGV4cG9ydCAoSFRUUCBsaW5rIGZvciBJUFRWIGFwcHMpIgoKdmFyIGNvbmZpZ01lbnVfbTN1ID0gbmV3IE9iamVjdCgpOwpjb25maWdNZW51X20zdVsiX2VsZW1lbnQiXSAgICAgICAgPSAiSU5QVVQiOwpjb25maWdNZW51X20zdVsiX21lbnVUeXBlIl0gICAgICAgPSAiaW5wdXRBcnJheSI7CmNvbmZpZ01lbnVfbTN1WyJfY29uZmlnS2V5Il0gICAgICA9ICJmaWxlIjsKY29uZmlnTWVudV9tM3VbIl9sYWJlbCJdICAgICAgICAgID0gIk0zVSBGaWxlOiBsb2NhbCBvciByZW1vdGUiOwpjb25maWdNZW51X20zdVsibmFtZSJdICAgICAgICAgICAgPSAiZmlsZSI7CmNvbmZpZ01lbnVfbTN1WyJpZCJdICAgICAgICAgICAgICA9ICJtM3UiOwpjb25maWdNZW51X20zdVsidHlwZSJdICAgICAgICAgICAgPSAidGV4dCI7CmNvbmZpZ01lbnVfbTN1WyJwbGFjZWhvbGRlciJdICAgICA9ICJNM1UgRmlsZSI7CmNvbmZpZ01lbnVfbTN1WyJfdXNhZ2UiXSAgICAgICAgICA9ICJSZW1vdGUgcGxheWxpc3Q6IGh0dHA6Ly95b3VyLnByb3ZpZGVyLmNvbS9maWxlLm0zdTxicj5Mb2NhbCAgcGxheWxpc3Q6IC9wYXRoL3RvL2ZpbGUubTN1IgoKCmNvbmZpZ01lbnVfbTN1WyJ2YWx1ZSJdICAgICAgICAgICA9ICJodHRwOi8vd2Vic3J2LmxvY2FsOjgwODAva2FiZWwubTN1IjsKCnZhciBjb25maWdNZW51X2NvbXBsZXRlID0gbmV3IE9iamVjdCgpOwpjb25maWdNZW51X2NvbXBsZXRlWyJfZWxlbWVudCJdICAgICAgICA9ICJIMiI7CmNvbmZpZ01lbnVfY29tcGxldGVbIl9tZW51VHlwZSJdICAgICAgID0gImlucHV0QXJyYXkiOwpjb25maWdNZW51X2NvbXBsZXRlWyJfY29uZmlnS2V5Il0gICAgICA9ICJmaWxlIjsKY29uZmlnTWVudV9jb21wbGV0ZVsiX3RleHQiXSAgICAgICAgICAgPSAieFRlVmUgd2FzIHN1Y2Nlc3NmdWxseSBzZXQgdXAiOwpjb25maWdNZW51X2NvbXBsZXRlWyJuYW1lIl0gICAgICAgICAgICA9ICJjb21wbGV0ZSI7CmNvbmZpZ01lbnVfY29tcGxldGVbImlkIl0gICAgICAgICAgICAgID0gImNvbXBsZXRlIjsKY29uZmlnTWVudV9jb21wbGV0ZVsidHlwZSJdICAgICAgICAgICAgPSAidGV4dCI7CmNvbmZpZ01lbnVfY29tcGxldGVbImNsYXNzIl0gICAgICAgICAgID0gImNlbnRlciI7Cgpjb25maWdNZW51WyJ0dW5lciJdICAgICA9IGNvbmZpZ01lbnVfdHVuZXI7CmNvbmZpZ01lbnVbImVwZ1NvdXJjZSJdID0gY29uZmlnTWVudV9lcGc7CmNvbmZpZ01lbnVbIm0zdSJdICAgICAgID0gY29uZmlnTWVudV9tM3U7CmNvbmZpZ01lbnVbImNvbXBsZXRlIl0gID0gY29uZmlnTWVudV9jb21wbGV0ZTsKCmZ1bmN0aW9uIHJlYWR5Rm9yQ29uZmlndXJhdGlvbigpIHsKICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICBkYXRhWyJjbWQiXSA9ICJnZXRTZXJ2ZXJDb25maWciOwogIHhUZVZlKGRhdGEpOwogIHNob3dMb2FkaW5nU2NyZWVuKGZhbHNlKTsKfQoKZnVuY3Rpb24gY3JlYXRlQ29uZmlndXJhdGlvbihlbG0pIHsKCiAgYWN0aXZlV2l6YXJkID0gZWxtOwogIHZhciBpdGVtICA9IGNvbmZpZ01lbnVbZWxtXTsKCiAgdmFyIGRpdiAgID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImNvbnRlbnQiKTsKICBkaXYuaW5uZXJIVE1MID0gIiI7CiAgZGl2LnNldEF0dHJpYnV0ZSgiZGF0YS1jb25maWdLZXkiLCBpdGVtWyJfY29uZmlnS2V5Il0pOwogIGRpdi5zZXRBdHRyaWJ1dGUoImRhdGEtbWVudVR5cGUiLCBpdGVtWyJfbWVudVR5cGUiXSk7CiAgCiAgc3dpdGNoKGl0ZW0uaGFzT3duUHJvcGVydHkoIl9sYWJlbCIpKSB7CiAgICBjYXNlIHRydWU6CiAgICAgIHZhciBuZXdJdGVtID0gbmV3IE9iamVjdCgpOwogICAgICBuZXdJdGVtWyJfZWxlbWVudCJdID0gIkxBQkVMIjsKICAgICAgbmV3SXRlbVsiX3RleHQiXSAgICA9IGl0ZW1bIl9sYWJlbCJdOyAKICAgICAgbmV3SXRlbVsiZm9yIl0gICAgICA9IGl0ZW1bImlkIl07CiAgICAgIGRpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0l0ZW0pKTsKICAgICAgYnJlYWsKICB9CgogIHN3aXRjaChpdGVtWyJfZWxlbWVudCJdKSB7CiAgICBjYXNlICJTRUxFQ1QiOgogICAgICBkaXYuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChpdGVtKSk7CiAgICAgIHZhciBzZWxlY3RFbGVtZW50ID0gZGl2LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJTRUxFQ1QiKVswXTsKICAgICAgdmFyIHZhbHVlcyA9IGl0ZW1bIl9vcHRpb25WYWx1ZXMiXTsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2YWx1ZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgbmV3RW50cnkgPSBuZXcgT2JqZWN0OwogICAgICAgIG5ld0VudHJ5WyJfZWxlbWVudCJdICA9ICJPUFRJT04iOwogICAgICAgIG5ld0VudHJ5WyJfdGV4dCJdICAgICA9IGl0ZW1bImlkIl0gKyAiOiAiICsgdmFsdWVzW2ldOwogICAgICAgIG5ld0VudHJ5WyJ2YWx1ZSJdICAgICA9IHZhbHVlc1tpXTsKICAgICAgICBzZWxlY3RFbGVtZW50LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKICAgICAgfQogICAgICAvL3JldHVybgogICAgICBicmVhazsKCiAgICBkZWZhdWx0OiAKICAgICAgZGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQoaXRlbSkpOwogICAgICBicmVhazsKCgogIH0KICAvL2FsZXJ0KCkKCiAgc3dpdGNoKGl0ZW0uaGFzT3duUHJvcGVydHkoIl91c2FnZSIpKSB7CiAgICBjYXNlIHRydWU6IAogICAgICB2YXIgdXNhZ2VJdGVtID0gbmV3IE9iamVjdCgpOwogICAgICB1c2FnZUl0ZW1bIl9lbGVtZW50Il0gPSAiUFJFIgogICAgICB1c2FnZUl0ZW1bIl90ZXh0Il0gICAgPSBpdGVtWyJfdXNhZ2UiXTsKICAgICAgZGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQodXNhZ2VJdGVtKSk7CiAgfQoKICBpZiAoYWN0aXZlV2l6YXJkID09ICJjb21wbGV0ZSIpIHsKICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJuZXh0IikudmFsdWUgPSAiRmluaXNoZWQiCiAgICAvL2RvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJuZXh0Iikuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgImphdmFzY3JpcHQ6IGxvY2F0aW9uLnJlbG9hZCgpOyIpCiAgfQoKICAvL2Rpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KGl0ZW0pKTsKfQoKZnVuY3Rpb24gc2F2ZURhdGEoKSB7CgogIHZhciBkaXYgICA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJjb250ZW50Iik7CiAgdmFyIGlucHV0cyA9IGRpdi5nZXRFbGVtZW50c0J5VGFnTmFtZSgiSU5QVVQiKTsKICB2YXIgc2VsZWN0cyA9IGRpdi5nZXRFbGVtZW50c0J5VGFnTmFtZSgiU0VMRUNUIik7CiAgdmFyIHZhbHVlOwogIHZhciBkYXRhID0gbmV3IE9iamVjdCgpOwogIHZhciB2YWx1ZUFyciA9IG5ldyBBcnJheSgpOwogIHZhciBuZXdEYXRhID0gZmFsc2U7CgogIGlmIChhY3RpdmVXaXphcmQgPT0gImNvbXBsZXRlIikgewogICAgZGF0YVsiY21kIl0gPSAid2l6YXJkQ29tcGxldGVkIjsKICAgIHNob3dMb2FkaW5nU2NyZWVuKHRydWUpCiAgICB4VGVWZShkYXRhKTsKICAgIHJldHVybgogIH0KICAKICBmb3IgKHZhciBpID0gMDsgaSA8IGlucHV0cy5sZW5ndGg7IGkrKykgewogICAgdmFyIG1lbnVUeXBlID0gaW5wdXRzW2ldLnBhcmVudEVsZW1lbnQuZ2V0QXR0cmlidXRlKCJkYXRhLW1lbnV0eXBlIik7CiAgICBpZiAoaW5wdXRzW2ldLnZhbHVlICE9IHVuZGVmaW5lZCAmJiBpbnB1dHNbaV0udmFsdWUgIT0gIiIgKSB7CiAgICAgIG5ld0RhdGEgPSB0cnVlOwoKICAgICAgY29uc29sZS5sb2coaW5wdXRzW2ldLmlkKQogICAgICBzd2l0Y2goaW5wdXRzW2ldLmlkKSB7CiAgICAgICAgY2FzZSAibTN1IjogCiAgICAgICAgICB2YXIgbmV3UGxheWxpc3QgPSBuZXcgT2JqZWN0KCk7CiAgICAgICAgICBuZXdQbGF5bGlzdFsiZmlsZS5zb3VyY2UiXSA9IGlucHV0c1tpXS52YWx1ZTsKICAgICAgICAgIC8vbmV3UGxheWxpc3RbIm5hbWUiXSA9IGlucHV0c1tpXS52YWx1ZTsKICAgICAgICAgIG5ld1BsYXlsaXN0WyJ0eXBlIl0gPSAibTN1IjsKICAgICAgICAgIG5ld1BsYXlsaXN0WyJuZXciXSA9IHRydWU7CgogICAgICAgICAgZGF0YVsiZmlsZXMiXSA9IG5ldyBPYmplY3QoKTsKICAgICAgICAgIGRhdGFbImZpbGVzIl1bIm0zdSJdID0gbmV3IE9iamVjdCgpOwogICAgICAgICAgZGF0YVsiZmlsZXMiXVsibTN1Il1bIi0iXSA9IG5ld1BsYXlsaXN0OwogICAgICAgICAgCiAgICAgICAgICBkYXRhWyJjbWQiXSA9ICJzYXZlRmlsZXNNM1UiOwogICAgICAgICAgeFRlVmUoZGF0YSkKICAgICAgICAgIHJldHVybgogICAgICB9CiAgICAgIC8qCiAgICAgIHN3aXRjaChtZW51VHlwZSkgewogICAgICAgIGNhc2UgInNpbmdsZUlucHV0IjoKICAgICAgICAgIGRhdGFbaW5wdXRzW2ldLm5hbWVdID0gaW5wdXRzW2ldLnZhbHVlOyBicmVhazsKICAgICAgICBjYXNlICJpbnB1dEFycmF5IjogCiAgICAgICAgICB2YWx1ZUFyci5wdXNoKGlucHV0c1tpXS52YWx1ZSk7CiAgICAgICAgICBkYXRhW2lucHV0c1tpXS5uYW1lXSA9IHZhbHVlQXJyOyBicmVhawoKICAgICAgfQogICAgICAqLwogICAgfSBlbHNlIHsKICAgICAgaW5wdXRzW2ldLnN0eWxlLmJvcmRlckJvdHRvbUNvbG9yID0gInJlZCI7CiAgICAgIHJldHVybjsKICAgIH0KICB9CgoKICBmb3IgKHZhciBpID0gMDsgaSA8IHNlbGVjdHMubGVuZ3RoOyBpKyspIHsKICAgIHZhciB2YWx1ZSA9IHNlbGVjdHNbaV0ub3B0aW9uc1tzZWxlY3RzW2ldLnNlbGVjdGVkSW5kZXhdLnZhbHVlOwogICAgaWYgKGlzTmFOKHZhbHVlKSA9PSBmYWxzZSkgewogICAgICB2YWx1ZSA9IHBhcnNlSW50KHZhbHVlKTsKICAgICAgZGF0YVtzZWxlY3RzW2ldLm5hbWVdID0gdmFsdWU7CiAgICAgIG5ld0RhdGEgPSB0cnVlOwogICAgICBicmVhazsKICAgIH0KICAgIGRhdGFbc2VsZWN0c1tpXS5uYW1lXSA9IHZhbHVlOwogICAgbmV3RGF0YSA9IHRydWU7CiAgfQoKCiAgLy9jb25zb2xlLmxvZyhkYXRhLCBuZXdEYXRhKTsKICBpZiAobmV3RGF0YSA9PSB0cnVlKSB7CiAgICBjb25maWcgPSBkYXRhCiAgICBkYXRhWyJjbWQiXSA9ICJzYXZlQ29uZmlnIjsKICAgIHhUZVZlKGRhdGEpOwogIH0KfQoKZnVuY3Rpb24geFRlVmUoZGF0YSkgewoKICBpZiAod2ViU29ja2V0cyA9PSBmYWxzZSkgewogICAgYWxlcnQoIllvdXIgYnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IFdlYlNvY2tldHMiKTsKICAgIHJldHVybjsKICB9CgogIGlmIChhY3RpdmVXaXphcmQgPT0gIm0zdSIgfHwgYWN0aXZlV2l6YXJkID09ICJlcGdTb3VyY2UiKSB7CiAgICBzaG93TG9hZGluZ1NjcmVlbih0cnVlKTsKICB9CgogIHZhciBwcm90b2NvbFdTCiAgc3dpdGNoKHdpbmRvdy5sb2NhdGlvbi5wcm90b2NvbCkgewogICAgY2FzZSAiaHR0cDoiOiAgIHByb3RvY29sV1MgPSAid3M6Ly8iOyBicmVhazsKICAgIGNhc2UgImh0dHBzOiI6ICBwcm90b2NvbFdTID0gIndzczovLyI7IGJyZWFrOwogIH0KCiAgdmFyIHdzID0gbmV3IFdlYlNvY2tldChwcm90b2NvbFdTICsgd2luZG93LmxvY2F0aW9uLmhvc3RuYW1lICsgIjoiICsgd2luZG93LmxvY2F0aW9uLnBvcnQgKyAiL2RhdGEvIiArICI/VG9rZW49IiArIGdldENvb2tpZSgiVG9rZW4iKSk7CiAgCiAgd3Mub25vcGVuID0gZnVuY3Rpb24oKSB7CiAgICB3cy5zZW5kKEpTT04uc3RyaW5naWZ5KGRhdGEpKTsKICB9CgogIHdzLm9ubWVzc2FnZSA9IGZ1bmN0aW9uIChlKSB7CiAgICAKICAgIHZhciByZXNwb25zZSA9IEpTT04ucGFyc2UoZS5kYXRhKTsKICAgIAogICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KCJjbGllbnRJbmZvIikpIHsKICAgICAgY3JlYXRlQ2xpbnRJbmZvKHJlc3BvbnNlWyJjbGllbnRJbmZvIl0pOwogICAgfQoKICAgIGlmIChyZXNwb25zZS5oYXNPd25Qcm9wZXJ0eSgic3RhdHVzIikpIHsKICAgICAgaWYgKHJlc3BvbnNlWyJzdGF0dXMiXSA9PSBmYWxzZSkgewogICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJoZWFkbGluZSIpLnN0eWxlLmJvcmRlckNvbG9yID0gInJlZCI7CiAgICAgICAgc2hvd0VycihyZXNwb25zZVsiZXJyIl0pOwogICAgICAgIHNob3dMb2FkaW5nU2NyZWVuKGZhbHNlKQogICAgICAgIHJldHVybgogICAgICB9IGVsc2UgewogICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJlcnIiKS5pbm5lckhUTUwgPSAiIjsKICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiaGVhZGxpbmUiKS5zdHlsZS5ib3JkZXJDb2xvciA9ICJsYXduZ3JlZW4iOwogICAgICB9CgogICAgICBkdnJJUCA9IHJlc3BvbnNlWyJEVlIiXQogICAgICBzd2l0Y2gocmVzcG9uc2VbImNvbmZpZ3VyYXRpb25XaXphcmQiXSkgewogICAgICAgIGNhc2UgdHJ1ZTogCiAgICAgICAgICBpZiAoYWN0aXZlV2l6YXJkID09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBhY3RpdmVXaXphcmQgPSB3aXphcmRbMF0KICAgICAgICAgIH0KICAgICAgICAgIHZhciBuID0gd2l6YXJkLmluZGV4T2YoYWN0aXZlV2l6YXJkKTsKICAgICAgICAgIG4rKzsKICAgICAgICAgIGFjdGl2ZVdpemFyZCA9IHdpemFyZFtuXQoKICAgICAgICAgIGlmIChhY3RpdmVXaXphcmQgPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGRhdGFbImNtZCJdID0gIndpemFyZENvbXBsZXRlZCI7CiAgICAgICAgICAgIHhUZVZlKGRhdGEpCiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAvL2NvbnNvbGUubG9nKGFjdGl2ZVdpemFyZCk7CiAgICAgICAgICAgIGNyZWF0ZUNvbmZpZ3VyYXRpb24oYWN0aXZlV2l6YXJkKTsgCiAgICAgICAgICB9CiAgICAgICAgICAKICAgICAgICBicmVhazsKICAgICAgfQoKICAgICAgc3dpdGNoKHJlc3BvbnNlWyJyZWxvYWQiXSkgewogICAgICAgIAogICAgICAgIAogICAgICAgIGNhc2UgdHJ1ZTogCiAgICAKICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKXsgCiAgICAgICAgICAgIGxvY2F0aW9uLnJlbG9hZCgpOwogICAgICAgICAgfSwgMTAwKTsKICAgICAgICAgIAogICAgICAgICAgLy9sb2NhdGlvbi5yZWxvYWQoKTsKICAgICAgICAgIAogICAgICAgICAgYnJlYWs7CiAgICAgICAgCiAgICAgIH0KCiAgICAgIAogICAgfQoKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKXsgc2hvd0xvYWRpbmdTY3JlZW4oZmFsc2UpOyB9LCAzMDApOwogIH0KICAKfQoKZnVuY3Rpb24gc2hvd0VycihlbG0pIHsKICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZXJyIikuaW5uZXJIVE1MID0gZWxtOwp9" - webUI["html/js/files.js"] = "ZnVuY3Rpb24gb3BlbkZpbGVzKGVsbSwgZmlsZVR5cGUpIHsKICAvL2RvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJzZXR0aW5ncyIpLmlubmVySFRNTCA9ICJUZXN0IjsKICAKICBjb2x1bW5Ub1NvcnQgPSAwOyAKICB2YXIgbmV3RGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNldHRpbmdzIik7CiAgCiAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogIG5ld0VudHJ5WyJfZWxlbWVudCJdICA9ICJIUiI7CiAgbmV3RGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKCiAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogIG5ld0VudHJ5WyJfZWxlbWVudCJdICA9ICJJTlBVVCI7CiAgbmV3RW50cnlbInR5cGUiXSA9ICJidXR0b24iOwogIG5ld0VudHJ5WyJjbGFzcyJdID0gImJ1dHRvbiI7CiAgbmV3RW50cnlbInZhbHVlIl0gPSAiTmV3IjsKICBuZXdFbnRyeVsib25jbGljayJdID0gJ2ZpbGVEZXRhaWwoIi0iLCAiJyArIGZpbGVUeXBlICsgJyIpJzsKICBuZXdEaXYuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdFbnRyeSkpOwoKICB2YXIgbmV3RW50cnkgPSBuZXcgT2JqZWN0KCk7CiAgbmV3RW50cnlbIl9lbGVtZW50Il0gID0gIklOUFVUIjsKICBuZXdFbnRyeVsidHlwZSJdID0gImJ1dHRvbiI7CiAgbmV3RW50cnlbImNsYXNzIl0gPSAiYnV0dG9uIjsKICBuZXdFbnRyeVsidmFsdWUiXSA9ICJVcGRhdGUiOwogIG5ld0VudHJ5WyJvbmNsaWNrIl0gPSAiZmlsZURldGFpbCgwKSI7CiAgLy9uZXdEaXYuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdFbnRyeSkpOwoKICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNldHRpbmdzIik7CgogICAvLyBCdWlsZCB0YWJsZQogIHZhciBuZXdUYWJsZSA9IG5ldyBPYmplY3QoKTsKICBuZXdUYWJsZVsiX2VsZW1lbnQiXSAgPSAiVEFCTEUiOwogIG5ld1RhYmxlWyJpZCJdICAgICAgICA9ICJpZF9tYXBwaW5nIjsKICBuZXdUYWJsZVsiY2xhc3MiXSAgICAgPSAidGFibGUtbWFwcGluZyI7CiAgZGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3VGFibGUpKTsKCiAgc2V0VGltZW91dChmdW5jdGlvbigpeyAKICAgIGNyZWF0ZUZpbGVzVGFibGUoZmlsZVR5cGUpOyAKICB9LCAxMCk7Cgp9CgpmdW5jdGlvbiBjcmVhdGVGaWxlc1RhYmxlKGZpbGVUeXBlKSB7CiAgdmFyIHRhYmxlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImlkX21hcHBpbmciKTsKICB2YXIgYXZhaWxhYmxlRmlsZVR5cGVzID0gbmV3IEFycmF5KCk7CiAgCiAgdGFibGUuaW5uZXJIVE1MID0gIiI7CiAgdmFyIG5ld1RSID0gbmV3IE9iamVjdCgpOwogIG5ld1RSWyJfZWxlbWVudCJdID0gIlRSIjsKICBuZXdUUlsiY2xhc3MiXSAgICA9ICJ0YWJsZS1tYXBwaW5nLWhlYWRlciI7CiAgdGFibGUuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdUUikpOwoKICB2YXIgdHIgPSB0YWJsZS5sYXN0Q2hpbGQ7CgogIHN3aXRjaChmaWxlVHlwZSkgewogICAgY2FzZSAieG1sdHYiOiAKICAgICAgYXZhaWxhYmxlRmlsZVR5cGVzID0gbmV3IEFycmF5KCJ4bWx0diIpOyAKICAgICAgdmFyIHRySGVhZGxpbmVzID0gbmV3IEFycmF5KCJHdWlkZSIsICJMYXN0IFVwZGF0ZSIsICJBdmFpbGFiaWxpdHkgJSIsICJDaGFubmVscyIsICJQcm9ncmFtcyIpCiAgICAgIHZhciBjb21wYXRpYmlsaXR5S2V5cyA9IG5ldyBBcnJheSgieG1sdHYuY2hhbm5lbHMiLCAieG1sdHYucHJvZ3JhbXMiKQogICAgICBicmVhazsKCiAgICBjYXNlICJtM3UiOgogICAgICBhdmFpbGFibGVGaWxlVHlwZXMgPSBuZXcgQXJyYXkoIm0zdSIsICJoZGhyIik7IAogICAgICB2YXIgdHJIZWFkbGluZXMgPSBuZXcgQXJyYXkoIlBsYXlsaXN0IiwgIkxhc3QgVXBkYXRlIiwgIkF2YWlsYWJpbGl0eSAlIiwgIlR5cGUiLCAiU3RyZWFtcyIsICJncm91cC10aXRsZSAlIiwgInR2Zy1pZCAlIiwgIlVuaXF1ZSBJRCAlIik7CiAgICAgIHZhciBjb21wYXRpYmlsaXR5S2V5cyA9IG5ldyBBcnJheSgic3RyZWFtcyIsICJncm91cC50aXRsZSIsICJ0dmcuaWQiLCAic3RyZWFtLmlkIik7CiAgICAgIGJyZWFrOwogIH0KCiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0ckhlYWRsaW5lcy5sZW5ndGg7IGkrKykgewogICAgdmFyIG5ld1REID0gbmV3IE9iamVjdCgpOwogICAgbmV3VERbIl9lbGVtZW50Il0gPSAiVEQiOwogICAgbmV3VERbIl90ZXh0Il0gICAgPSB0ckhlYWRsaW5lc1tpXTsKICAgIHRyLmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3VEQpKTsKICB9CiAgCiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhdmFpbGFibGVGaWxlVHlwZXMubGVuZ3RoOyBpKyspIHsKICAgIAogICAgdmFyIGZpbGVUeXBlID0gYXZhaWxhYmxlRmlsZVR5cGVzW2ldCgogICAgdmFyIGRhdGEgPSBjb25maWdbImZpbGVzIl1bZmlsZVR5cGVdOwogICAgCiAgICB2YXIgYWxsRmlsZXMgPSBnZXRPYmpLZXlzKGRhdGEpCiAgCiAgICBmb3IgKHZhciBmID0gMDsgZiA8IGFsbEZpbGVzLmxlbmd0aDsgZisrKSB7CiAgICAgIHZhciBlbG0gICAgICAgICAgID0gZGF0YVthbGxGaWxlc1tmXV07CiAgICAgIHZhciB0YWJsZSAgICAgICAgID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImlkX21hcHBpbmciKTsKICAgICAgdmFyIGZpbGVJRCAgICAgICAgPSBlbG1bImlkLnByb3ZpZGVyIl07CiAgICAgIHZhciBuYW1lICAgICAgICAgID0gZWxtWyJuYW1lIl07CiAgICAgIHZhciBsYXN0VXBkYXRlICAgID0gZWxtWyJsYXN0LnVwZGF0ZSJdOwogICAgICB2YXIgYXZhaWxhYmlsaXR5ICA9IGVsbVsicHJvdmlkZXIuYXZhaWxhYmlsaXR5Il07CiAgICAgIHZhciB0eXBlICAgICAgICAgID0gZWxtWyJ0eXBlIl0udG9VcHBlckNhc2UoKTsKICAgICAgdmFyIGNvbXBhdGliaWxpdHkgPSBlbG1bImNvbXBhdGliaWxpdHkiXTsKCiAgICAgIC8vIENyZWF0ZSBUUgogICAgICB2YXIgbmV3VFIgPSBuZXcgT2JqZWN0KCk7CiAgICAgIG5ld1RSWyJfZWxlbWVudCJdICAgICAgID0gIlRSIjsKICAgICAgbmV3VFJbImNsYXNzIl0gICAgICAgICAgPSAiIjsKICAgICAgbmV3VFJbImlkIl0gICAgICAgICAgICAgPSBmaWxlSUQ7CiAgICAgIG5ld1RSWyJvbmNsaWNrIl0gICAgICAgID0gJ2phdmFzY3JpcHQ6IGZpbGVEZXRhaWwoIicgKyBmaWxlSUQgKyAnIiwiJyArIGZpbGVUeXBlICsgJyIpOyc7CiAgICAgIHRhYmxlLmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3VFIpKTsKCiAgICAgIHZhciB0ciA9IHRhYmxlLmxhc3RDaGlsZDsKCiAgICAgIC8vIENyZWF0ZSBmaWxlIG5hbWUgVEQKICAgICAgdmFyIG5ld1REID0gbmV3IE9iamVjdCgpOwogICAgICBuZXdURFsiX2VsZW1lbnQiXSA9ICJQIjsKICAgICAgbmV3VERbIl90ZXh0Il0gICAgPSBuYW1lOwogICAgICBjcmVhdGVOZXdURChuZXdURCwgdHIpOwoKICAgICAgLy8gQ3JlYXRlIGxhc3QgdXBkYXRlIFRECiAgICAgIHZhciBuZXdURCA9IG5ldyBPYmplY3QoKTsKICAgICAgbmV3VERbIl9lbGVtZW50Il0gPSAiUCI7CiAgICAgIG5ld1REWyJfdGV4dCJdICAgID0gbGFzdFVwZGF0ZTsKICAgICAgY3JlYXRlTmV3VEQobmV3VEQsIHRyKTsKCiAgICAgIC8vIENyZWF0ZSBhdmFpbGFiaWxpdHkgVEQKICAgICAgdmFyIG5ld1REID0gbmV3IE9iamVjdCgpOwogICAgICBuZXdURFsiX2VsZW1lbnQiXSA9ICJQIjsKICAgICAgbmV3VERbIl90ZXh0Il0gICAgPSBhdmFpbGFiaWxpdHk7CiAgICAgIGNyZWF0ZU5ld1REKG5ld1RELCB0cik7CgogICAgICBpZiAoZmlsZVR5cGUgPT0gIm0zdSIgfHwgZmlsZVR5cGUgPT0gImhkaHIiKSB7CgogICAgICAgIC8vIENyZWF0ZSBUeXBlIFRECiAgICAgICAgdmFyIG5ld1REID0gbmV3IE9iamVjdCgpOwogICAgICAgIG5ld1REWyJfZWxlbWVudCJdID0gIlAiOwogICAgICAgIG5ld1REWyJfdGV4dCJdICAgID0gdHlwZTsKICAgICAgICBjcmVhdGVOZXdURChuZXdURCwgdHIpOwogIAogICAgICB9CiAgICAgIAogICAgICAvLyBDcmVhdGUgYWxsIGNvbXBhdGliaWxpdHkgVERzCgogICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGNvbXBhdGliaWxpdHlLZXlzLmxlbmd0aDsgaisrKSB7CiAgICAgICAgdmFyIG5ld1REID0gbmV3IE9iamVjdCgpOwogICAgICAgIG5ld1REWyJfZWxlbWVudCJdID0gIlAiOwogICAgICAgIG5ld1REWyJfdGV4dCJdICAgID0gY29tcGF0aWJpbGl0eVtjb21wYXRpYmlsaXR5S2V5c1tqXV07CiAgICAgICAgY3JlYXRlTmV3VEQobmV3VEQsIHRyKTsKICAgICAgfQoKICAgIH0KCiAgfQogIAogIAogIHNvcnRUYWJsZSgwKQoKICAvLyB1c2FnZSBJbmZvICAKICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNldHRpbmdzIik7CiAgc3dpdGNoKG1lbnVbYWN0aXZlTWVudS5pZF0uaGFzT3duUHJvcGVydHkoIl91c2FnZSIpKSB7CiAgICBjYXNlIHRydWU6IAogICAgICB2YXIgdXNhZ2VJdGVtID0gbmV3IE9iamVjdCgpOwogICAgICB1c2FnZUl0ZW1bIl9lbGVtZW50Il0gPSAiUFJFIgogICAgICB1c2FnZUl0ZW1bIl90ZXh0Il0gICAgPSBtZW51W2FjdGl2ZU1lbnUuaWRdWyJfdXNhZ2UiXTsKCiAgICAgIHZhciBuZXdIUiA9IG5ldyBPYmplY3QoKTsKICAgICAgbmV3SFJbIl9lbGVtZW50Il0gPSAiSFIiCiAgICAgIGRpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0hSKSk7CiAgICAgIGRpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KHVzYWdlSXRlbSkpOwogICAgICBicmVhazsKICB9CgogIGNhbGN1bGF0ZVdyYXBwZXJIZWlnaHQoKTsKICByZXR1cm47Cn0KCgpmdW5jdGlvbiBmaWxlRGV0YWlsKGZpbGVJRCwgZmlsZVR5cGUpIHsKCiAgb3B0aW9uc1RleHQgID0gbmV3IEFycmF5KCJNM1UiLCAiSERIb21lUnVuIC0gW0V4cGVyaW1lbnRhbF0iKQogIG9wdGlvbnNWYWx1ZSA9IG5ldyBBcnJheSgibTN1IiwgImhkaHIiKQoKICBzd2l0Y2ggKGZpbGVUeXBlKSB7CiAgICAKICAgIGNhc2UgIm0zdSI6IAogICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgibmFtZSIpLnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAiUGxheWxpc3QgbmFtZSIpOyAKICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImRlc2NyaXB0aW9uIikuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJEZXNjcmlwdGlvbiBvZiB0aGlzIHBsYXlsaXN0Iik7IAogICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZmlsZS1kZXRhaWwtaGVhZGxpbmUiKS5pbm5lckhUTUwgPSAiTTNVIFBsYXlsaXN0IjsgCiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJmaWxlLXBhdGgiKS5pbm5lckhUTUwgPSAiTTNVIEZpbGU6IjsgCiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJmaWxlLnNvdXJjZSIpLnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAiTG9jYWwgb3IgcmVtb3RlIik7CiAgICAgIGJyZWFrOwoKICAgIGNhc2UgImhkaHIiOiAKICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm5hbWUiKS5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgIkhESG9tZVJ1biBuYW1lIik7IAogICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZGVzY3JpcHRpb24iKS5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgIkRlc2NyaXB0aW9uIG9mIHRoaXMgSERIb21lUnVuIHR1bmVyIik7IAogICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZmlsZS1kZXRhaWwtaGVhZGxpbmUiKS5pbm5lckhUTUwgPSAiSERIb21lUnVuIjsgCiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJmaWxlLXBhdGgiKS5pbm5lckhUTUwgPSAiSERIb21lUnVuIElQOiI7IAogICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZmlsZS5zb3VyY2UiKS5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgIklQIGFkZHJlc3MgYW5kIHBvcnQgb2YgdGhlIHR1bmVyICgxOTIuMTY4LjEuMTA6NTAwNCkiKTsKICAgICAgYnJlYWs7CiAgICAKICAgIGNhc2UgInhtbHR2IjogCiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJuYW1lIikuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJYTUxUViBuYW1lIik7IAogICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZGVzY3JpcHRpb24iKS5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgIkRlc2NyaXB0aW9uIG9mIHRoaXMgWE1MVFYgZmlsZSIpOyAKICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImZpbGUtZGV0YWlsLWhlYWRsaW5lIikuaW5uZXJIVE1MID0gIlhNTFRWIEZpbGUiOyAKICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImZpbGUtcGF0aCIpLmlubmVySFRNTCA9ICJYTUxUViBGaWxlOiI7CiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJmaWxlLnNvdXJjZSIpLnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAiTG9jYWwgb3IgcmVtb3RlIik7CgogICAgICBvcHRpb25zVGV4dCAgPSBuZXcgQXJyYXkoIlhNTFRWIikKICAgICAgb3B0aW9uc1ZhbHVlID0gbmV3IEFycmF5KCJ4bWx0diIpCiAgICAgIGJyZWFrOwogIH0KCiAgbW9kaWZ5T3B0aW9uKCJ0eXBlIiwgb3B0aW9uc1RleHQsIG9wdGlvbnNWYWx1ZSkKICAKICBzaG93UG9wVXBFbGVtZW50KCdmaWxlLWRldGFpbCcpOwoKICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgic2F2ZUZpbGVEZXRhaWwiKS5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogc2F2ZUZpbGVEZXRhaWwoIicgKyBmaWxlSUQgKyAnIiwiJyArIGZpbGVUeXBlICsgJyIsIGZhbHNlKScpOwogIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ1cGRhdGVGaWxlRGV0YWlsIikuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHVwZGF0ZUZpbGUoIicgKyBmaWxlSUQgKyAnIiwiJyArIGZpbGVUeXBlICsgJyIsIGZhbHNlKScpOwogIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJkZWxldGVGaWxlRGV0YWlsIikuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHNhdmVGaWxlRGV0YWlsKCInICsgZmlsZUlEICsgJyIsIicgKyBmaWxlVHlwZSArICciLCB0cnVlKScpOwoKICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKCiAgc3dpdGNoKGZpbGVJRCkgewoKICAgIGNhc2UgIi0iOiAvLyBOZXcgZmlsZQogICAgICBkYXRhWyJuYW1lIl0gICAgICAgID0gIiI7CiAgICAgIGRhdGFbImRlc2NyaXB0aW9uIl0gPSAiIjsKICAgICAgZGF0YVsiZmlsZS5zb3VyY2UiXSA9ICIiOwogICAgICBkYXRhWyJ0eXBlIl0gPSBmaWxlVHlwZTsKICAgICAgCiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJkZWxldGVGaWxlRGV0YWlsIikuY2xhc3NOYW1lID0gImRlbGV0ZSI7CiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ0eXBlIikuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJjaGFuZ2VGaWxlVHlwZSh0aGlzKTsiKQogICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidHlwZSIpLnNldEF0dHJpYnV0ZSgiZGF0YS1pZCIsIGZpbGVJRCkKICAgICAgCiAgICAgIHNob3dFbGVtZW50KCJkZWxldGVGaWxlRGV0YWlsIiwgZmFsc2UpOwogICAgICBzaG93RWxlbWVudCgidXBkYXRlRmlsZURldGFpbCIsIGZhbHNlKTsKICAgICAgCiAgICAgIGlmIChmaWxlVHlwZSA9PSAieG1sdHYiKSB7CiAgICAgICAgc2hvd0VsZW1lbnQoInR5cGUiLCBmYWxzZSk7CiAgICAgICAgc2hvd0VsZW1lbnQoImZpbGUtdHlwZSIsIGZhbHNlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBzaG93RWxlbWVudCgidHlwZSIsIHRydWUpOwogICAgICAgIHNob3dFbGVtZW50KCJmaWxlLXR5cGUiLCB0cnVlKTsKICAgICAgfQogICAgICAKICAgICAgYnJlYWs7CgogICAgZGVmYXVsdDogCiAgICAgIGRhdGEgPSBjb25maWdbImZpbGVzIl1bZmlsZVR5cGVdW2ZpbGVJRF07CiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJkZWxldGVGaWxlRGV0YWlsIikuY2xhc3NOYW1lID0gImRlbGV0ZSI7CiAgICAgIAogICAgICBzaG93RWxlbWVudCgidXBkYXRlRmlsZURldGFpbCIsIHRydWUpOwogICAgICBzaG93RWxlbWVudCgidHlwZSIsIGZhbHNlKTsKICAgICAgc2hvd0VsZW1lbnQoImZpbGUtdHlwZSIsIGZhbHNlKTsKICAgICAgCiAgICAgIGJyZWFrOwoKICB9CgogIHZhciBrZXlzID0gZ2V0T2JqS2V5cyhkYXRhKTsKICAKICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKCiAgICBpZihkb2N1bWVudC5nZXRFbGVtZW50QnlJZChrZXlzW2ldKSl7CiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGtleXNbaV0pLnZhbHVlID0gZGF0YVtrZXlzW2ldXTsKICAgIH0gCgoKICB9Cgp9CgpmdW5jdGlvbiBjaGFuZ2VGaWxlVHlwZShlbG0pIHsKCiAgdmFyIGZpbGVJRCA9IGVsbS5nZXRBdHRyaWJ1dGUoImRhdGEtaWQiKTsKICB2YXIgZmlsZVR5cGUgPSBlbG0ub3B0aW9uc1tlbG0uc2VsZWN0ZWRJbmRleF0udmFsdWU7CiAgCiAgZmlsZURldGFpbChmaWxlSUQsIGZpbGVUeXBlKQoKfQoKCmZ1bmN0aW9uIHNhdmVGaWxlRGV0YWlsKGZpbGVJRCwgZmlsZVR5cGUsIGRlbGV0ZUZpbGUpIHsKCiAgaWYgKGZpbGVJRCA9PSB1bmRlZmluZWQpIHsKICAgIGFsZXJ0KCJJRCBpcyBtaXNzaW5nISEhIik7CiAgICByZXR1cm4gCiAgfQoKICB2YXIgaW5wdXRzICAgICAgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZmlsZS1kZXRhaWwiKS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiSU5QVVQiKTsKICB2YXIgc2VsZWN0cyAgICAgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZmlsZS1kZXRhaWwiKS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiU0VMRUNUIik7CiAgdmFyIG5ld0ZpbGVEYXRhID0gbmV3IE9iamVjdCgpOwogIHZhciBkYXRhICAgICAgICA9IG5ldyBPYmplY3QoKTsKCiAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbnB1dHMubGVuZ3RoOyBpKyspIHsKICAgIHN3aXRjaChpbnB1dHNbaV0udHlwZSkgewogICAgICBjYXNlICJ0ZXh0IjogbmV3RmlsZURhdGFbaW5wdXRzW2ldLm5hbWVdID0gaW5wdXRzW2ldLnZhbHVlOyBicmVhazsKICAgIH0KICB9CgogIGZvciAodmFyIGkgPSAwOyBpIDwgc2VsZWN0cy5sZW5ndGg7IGkrKykgewogICAgbmV3RmlsZURhdGFbc2VsZWN0c1tpXS5pZF0gPSBzZWxlY3RzW2ldLm9wdGlvbnNbc2VsZWN0c1tpXS5zZWxlY3RlZEluZGV4XS52YWx1ZTsKICB9CgogIGlmIChkZWxldGVGaWxlID09IHRydWUpIHsKICAgIHN3aXRjaChmaWxlVHlwZSkgewogICAgICBjYXNlICJtM3UiOiAgIHZhciBhbGVydFRleHQgPSAiRGVsZXRlIHRoaXMgcGxheWxpc3Q/IjsgYnJlYWs7CiAgICAgIGNhc2UgImhkaHIiOiB2YXIgYWxlcnRUZXh0ID0gIkRlbGV0ZSB0aGlzIEhESG9tZVJ1biB0dW5lcj8iOyBicmVhazsKICAgICAgY2FzZSAieG1sdHYiOiB2YXIgYWxlcnRUZXh0ID0gIkRlbGV0ZSB0aGlzIFhNTFRWIGZpbGU/IjsgYnJlYWs7CiAgICB9CgogICAgaWYgKGNvbmZpcm0oYWxlcnRUZXh0KSkgewogICAgICBuZXdGaWxlRGF0YVsiZGVsZXRlIl0gPSB0cnVlCiAgICAgIGRhdGEgPSBidWlsZEZpbGVzT2JqKGZpbGVUeXBlLCBmaWxlSUQsIG5ld0ZpbGVEYXRhKTsKICAgICAgY29uc29sZS5sb2coZGF0YSk7CiAgICAgIAogICAgfSBlbHNlIHsKICAgICAgc2hvd0VsZW1lbnQoInBvcHVwIiwgZmFsc2UpOwogICAgICByZXR1cm4KICAgIAogICAgfQoKICB9IGVsc2UgewogIAogICAgc3dpdGNoKGNvbmZpZ1siZmlsZXMiXVtmaWxlVHlwZV0uaGFzT3duUHJvcGVydHkoZmlsZUlEKSkgewoKICAgICAgY2FzZSB0cnVlOiAKICAgICAgICBkYXRhID0gY29uZmlnWyJmaWxlcyJdW2ZpbGVUeXBlXVtmaWxlSURdOyAKICAgICAgICBpZiAoZGF0YVsiZmlsZS5zb3VyY2UiXSAhPSBuZXdGaWxlRGF0YVsiZmlsZS5zb3VyY2UiXSkgewogICAgICAgICAgZGF0YVsidXBkYXRlIl0gPSB0cnVlCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGRhdGFbInVwZGF0ZVBsYXlsaXN0TmFtZSJdID0gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIAogICAgICBjYXNlIGZhbHNlOiAKICAgICAgICBuZXdGaWxlRGF0YVsibmV3Il0gPSB0cnVlOwogICAgICAgIGRhdGEgPSBidWlsZEZpbGVzT2JqKGZpbGVUeXBlLCBmaWxlSUQsIG5ld0ZpbGVEYXRhKTsKICAgICAgICBicmVhawoKICAgIH0KICAKICB9ICAKICAKICBzd2l0Y2goZmlsZVR5cGUpIHsKCiAgICBjYXNlICJtM3UiOiAgIGRhdGFbImNtZCJdID0gInNhdmVGaWxlc00zVSI7IGJyZWFrOwogICAgY2FzZSAiaGRociI6ICBkYXRhWyJjbWQiXSA9ICJzYXZlRmlsZXNIREhSIjsgYnJlYWs7CiAgICBjYXNlICJ4bWx0diI6IGRhdGFbImNtZCJdID0gInNhdmVGaWxlc1hNTFRWIjsgYnJlYWs7CgogIH0KICAvL2NvbnNvbGUubG9nKGRhdGEpOwogIHhUZVZlKGRhdGEpOwogIHJldHVybgp9CgpmdW5jdGlvbiB1cGRhdGVGaWxlKGZpbGVJRCwgZmlsZVR5cGUsIGFsbEZpbGVzKSB7CiAgCiAgc3dpdGNoKGNvbmZpZ1siZmlsZXMiXVtmaWxlVHlwZV0uaGFzT3duUHJvcGVydHkoZmlsZUlEKSkgewoKICAgIGNhc2UgdHJ1ZTogCiAgICAKICAgICAgdmFyIGRhdGEgPSBuZXcgT2JqZWN0KCk7CiAgICAgIHZhciBkYXRhID0gYnVpbGRGaWxlc09iaihmaWxlVHlwZSwgZmlsZUlELCBjb25maWdbImZpbGVzIl1bZmlsZVR5cGVdW2ZpbGVJRF0pCiAgICAgIGRhdGFbIm5ldyJdID0gdHJ1ZQoKICAgICAgc3dpdGNoKGZpbGVUeXBlKSB7CgogICAgICAgIGNhc2UgIm0zdSI6ICAgZGF0YVsiY21kIl0gPSAidXBkYXRlRmlsZU0zVSI7IGJyZWFrOwogICAgICAgIGNhc2UgImhkaHIiOiAgZGF0YVsiY21kIl0gPSAidXBkYXRlRmlsZUhESFIiOyBicmVhazsKICAgICAgICBjYXNlICJ4bWx0diI6IGRhdGFbImNtZCJdID0gInVwZGF0ZUZpbGVYTUxUViI7IGJyZWFrOwoKICAgICAgfQogICAgICAKICAgICAgeFRlVmUoZGF0YSk7CiAgICAgIAogICAgICBicmVhazsKICB9Cgp9CgpmdW5jdGlvbiBidWlsZEZpbGVzT2JqKGZpbGVUeXBlLCBmaWxlSUQsIG9iaikgewoKICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICBkYXRhWyJmaWxlcyJdID0gbmV3IE9iamVjdCgpOwogIGRhdGFbImZpbGVzIl1bZmlsZVR5cGVdID0gbmV3IE9iamVjdCgpOwogIGRhdGFbImZpbGVzIl1bZmlsZVR5cGVdW2ZpbGVJRF0gPSBvYmoKICByZXR1cm4gZGF0YQoKfQ==" - webUI["html/js/mapping-editor.js"] = "dmFyIG1hcHBpbmdFcnJvciAgPSBmYWxzZTsKdmFyIGJ1bGsgICAgICAgICAgPSBmYWxzZTsKdmFyIGJ1bGtFZGl0QWxsICAgPSBmYWxzZTsgCnZhciBzZWxlY3RPYmogICAgID0gbmV3IE9iamVjdCgpOwp2YXIgc2VhcmNoT2JqICAgICA9IG5ldyBPYmplY3QoKTsKCnZhciBidWxrSURzICAgICAgID0gbmV3IEFycmF5KCk7CnZhciBidWxrQ2hhbmdlT2JqID0gbmV3IE9iamVjdCgpOwoKZnVuY3Rpb24gY2hlY2tVbmRvKGtleSwgZWxtKSB7CiAgdmFyIHRtcCA9IG5ldyBPYmplY3QoKTsKICB0bXAgPSBlbG0KICBjb25zb2xlLmxvZygiLS0iKTsKICBpZiAodW5kby5oYXNPd25Qcm9wZXJ0eSgiZXBnTWFwcGluZyIpKSB7CiAgICB4RVBHWyJlcGdNYXBwaW5nIl0gPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHVuZG9bImVwZ01hcHBpbmciXSkpOzsKICB9IGVsc2UgewogICAgdW5kb1siZXBnTWFwcGluZyJdID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShlbG0pKTsKICB9Cn0KCi8vdmFyIHBsZXhDYXRlZ29yaWVzID0gbmV3IEFycmF5KCItIiwgIkFjdGlvbiBzcG9ydHMiLCAiQWN0aW9uIiwgIkFkdWx0cyBvbmx5IiwgIkFkdmVudHVyZSIsICJBZXJvYmljcyIsICJBbmltYWxzIiwgIkFuaW1hdGVkIiwgIkFuaW1lIiwgIkFudGhvbG9neSIsICJBcmNoZXJ5IiwgIkFydCIsICJBcnRzL2NyYWZ0cyIsICJBdWN0aW9uIiwgIkF1dG8gcmFjaW5nIiwgIkF1dG8iLCAiQXZpYXRpb24iLCAiQXdhcmRzIiwgIkJhbGxldCIsICJCYXNlYmFsbCIsICJCYXNrZXRiYWxsIiwgIkJpY3ljbGUgcmFjaW5nIiwgIkJpY3ljbGUiLCAiQmlsbGlhcmRzIiwgIkJpb2dyYXBoeSIsICJCb2F0IHJhY2luZyIsICJCb2F0IiwgIkJvd2xpbmciLCAiQm94aW5nIiwgIkJ1cy4vZmluYW5jaWFsIiwgIkNoaWxkcmVuIiwgIkNvbGxlY3RpYmxlcyIsICJDb21lZHkgZHJhbWEiLCAiQ29tZWR5IiwgIkNvbW11bml0eSIsICJDb21wdXRlcnMiLCAiQ29uc3VtZXIiLCAiQ29va2luZyIsICJDcmltZSBkcmFtYSIsICJDcmltZSIsICJEYW5jZSIsICJEYXJrIGNvbWVkeSIsICJEZWJhdGUiLCAiRGl2aW5nIiwgIkRvY3VkcmFtYSIsICJEb2N1bWVudGFyeSIsICJEcmFtYSIsICJFZHVjYXRpb25hbCIsICJFbnRlcnRhaW5tZW50IiwgIkVudmlyb25tZW50IiwgIkVxdWVzdHJpYW4iLCAiRXJvdGljIiwgIkV2ZW50IiwgIkZhbnRhc3kiLCAiRmFzaGlvbiIsICJGZWF0dXJlIEZpbG0iLCAiRmlzaGluZyIsICJGb290YmFsbCIsICJHYW1lIHNob3ciLCAiR2FtaW5nIiwgIkdheS9sZXNiaWFuIiwgIkdvbGYiLCAiSGFuZGJhbGwiLCAiSGVhbHRoIiwgIkhpc3RvcmljYWwgZHJhbWEiLCAiSGlzdG9yeSIsICJIb2NrZXkiLCAiSG9saWRheSIsICJIb21lIGltcHJvdmVtZW50IiwgIkhvcnJvciIsICJIb3JzZSIsICJIb3VzZS9nYXJkZW4iLCAiSG93LXRvIiwgIkludGVydmlldyIsICJJbnRsIHNvY2NlciIsICJMYXciLCAiTWFydGlhbCBhcnRzIiwgIk1lZGljYWwiLCAiTWlsaXRhcnkiLCAiTWluaXNlcmllcyIsICJNaXhlZCBtYXJ0aWFsIGFydHMiLCAiTW90b3JjeWNsZSByYWNpbmciLCAiTW90b3JjeWNsZSIsICJNb3RvcnNwb3J0cyIsICJNb3VudGFpbiBiaWtpbmciLCAiTXVzaWMiLCAiTXVzaWNhbCBjb21lZHkiLCAiTXVzaWNhbCIsICJNeXN0ZXJ5IiwgIk5hdHVyZSIsICJOZXdzIiwgIk5ld3NtYWdhemluZSIsICJPbHltcGljcyIsICJPcGVyYSIsICJPdXRkb29ycyIsICJQYXJhZGUiLCAiUGFyYW5vcm1hbCIsICJQYXJlbnRpbmciLCAiUGVyZm9ybWluZyBhcnRzIiwgIlBsYXlvZmYgc3BvcnRzIiwgIlBva2VyIiwgIlBvbGl0aWNzIiwgIlBybyB3cmVzdGxpbmciLCAiUHVibGljIGFmZmFpcnMiLCAiUmVhbGl0eSIsICJSZWxpZ2lvdXMiLCAiUm9kZW8iLCAiUm9sbGVyIGRlcmJ5IiwgIlJvbWFuY2UiLCAiUm9tYW50aWMgY29tZWR5IiwgIlJ1Z2J5IiwgIlJ1bm5pbmciLCAiU2FpbGluZyIsICJTY2llbmNlIGZpY3Rpb24iLCAiU2NpZW5jZSIsICJTZWxmIGltcHJvdmVtZW50IiwgIlNlcmllcyIsICJTaG9vdGluZyIsICJTaG9wcGluZyIsICJTaG9ydCBGaWxtIiwgIlNpdGNvbSIsICJTa2lpbmciLCAiU25vb2tlciIsICJTb2FwIiwgIlNvY2NlciIsICJTcGVjaWFsIiwgIlNwb3J0cyIsICJzcG9ydHMiLCAiU3BvcnRzIGV2ZW50IiwgIlNwb3J0cyBub24tZXZlbnQiLCAiU3BvcnRzIHRhbGsiLCAiU3RhbmR1cCIsICJTdXJmaW5nIiwgIlN1c3BlbnNlIiwgIlRWIE1vdmllIiwgIlRhbGsiLCAiVGVjaG5vbG9neSIsICJUZW5uaXMiLCAiVGhlYXRlciIsICJUaHJpbGxlciIsICJUcmFjay9maWVsZCIsICJUcmF2ZWwiLCAiVHJpYXRobG9uIiwgIlZhcmlldHkiLCAiVm9sbGV5YmFsbCIsICJXYXIiLCAiV2F0ZXJzcG9ydHMiLCAiV2VhdGhlciIsICJXZXN0ZXJuIiwgIldyZXN0bGluZyIsICJZYWNodCByYWNpbmciLCAibW92aWUiLCAic2VyaWVzIiwgInNwb3J0cyIsICJ0dnNob3ciKTsKdmFyIHBsZXhDYXRlZ29yaWVzVmFsdWVzID0gbmV3IEFycmF5KCItIiwgIktpZHMiLCAiTmV3cyIsICJNb3ZpZSIsICJTZXJpZXMiLCAiU3BvcnRzIikKdmFyIHBsZXhDYXRlZ29yaWVzT3B0aW9uID0gbmV3IEFycmF5KCItIiwgIktpZHMgKEVtYnkgb25seSkiLCAiTmV3cyIsICJNb3ZpZSIsICJTZXJpZXMiLCAiU3BvcnRzIikKCgpmdW5jdGlvbiBvcGVuTWFwcGluZ0VkaXRvcihlbG0pIHsKICB2YXIgY29sdW1uVG9Tb3J0ICA9IDEKCiAgY2hlY2tVbmRvKCJlcGdNYXBwaW5nIiwgeEVQR1siZXBnTWFwcGluZyJdKQoKICB2YXIgbmV3RGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNldHRpbmdzIik7CiAgCiAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogIG5ld0VudHJ5WyJfZWxlbWVudCJdICA9ICJIUiI7CiAgbmV3RGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKCiAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogIG5ld0VudHJ5WyJfZWxlbWVudCJdICAgID0gIklOUFVUIjsKICBuZXdFbnRyeVsidHlwZSJdICAgICAgICA9ICJidXR0b24iOwogIG5ld0VudHJ5WyJjbGFzcyJdICAgICAgID0gImJ1dHRvbiI7CiAgbmV3RW50cnlbInZhbHVlIl0gICAgICAgPSAiU2F2ZSI7CiAgbmV3RW50cnlbIm9uY2xpY2siXSAgICAgPSAic2F2ZVhFUEcoKSI7CiAgbmV3RGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKCiAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogIG5ld0VudHJ5WyJfZWxlbWVudCJdICAgID0gIklOUFVUIjsKICBuZXdFbnRyeVsidHlwZSJdICAgICAgICA9ICJidXR0b24iOwogIG5ld0VudHJ5WyJjbGFzcyJdICAgICAgID0gImJ1dHRvbiI7CiAgbmV3RW50cnlbInZhbHVlIl0gICAgICAgPSAiQnVsayBFZGl0IjsKICBuZXdFbnRyeVsib25jbGljayJdICAgICA9ICJidWxrRWRpdCgpIjsKICBuZXdEaXYuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdFbnRyeSkpOwoKICB2YXIgbmV3RW50cnkgPSBuZXcgT2JqZWN0KCk7CiAgbmV3RW50cnlbIl9lbGVtZW50Il0gICAgPSAiSU5QVVQiOwogIG5ld0VudHJ5WyJ0eXBlIl0gICAgICAgID0gImJ1dHRvbiI7CiAgbmV3RW50cnlbImNsYXNzIl0gICAgICAgPSAiYnV0dG9uIjsKICBuZXdFbnRyeVsidmFsdWUiXSAgICAgICA9ICJTaG93IFhFUEciOwogIG5ld0VudHJ5WyJvbmNsaWNrIl0gICAgID0gInNob3dYRVBHKCkiOwogIG5ld0Rpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0VudHJ5KSk7CgogIHZhciBuZXdFbnRyeSA9IG5ldyBPYmplY3QoKTsKICBuZXdFbnRyeVsiX2VsZW1lbnQiXSAgICA9ICJJTlBVVCI7CiAgbmV3RW50cnlbImNsYXNzIl0gICAgICAgPSAic2VhcmNoIjsKICBuZXdFbnRyeVsiaWQiXSAgICAgICAgICA9ICJzZWFyY2hNYXBwaW5nIjsKICBuZXdFbnRyeVsidHlwZSJdICAgICAgICA9ICJzZWFyY2giOwogIG5ld0VudHJ5WyJwbGFjZWhvbGRlciJdID0gIlNlYXJjaCI7CiAgbmV3RW50cnlbIm9uY2hhbmdlIl0gICAgPSAic2VhcmNoSW5NYXBwaW5nKCkiOwogIG5ld0Rpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0VudHJ5KSk7CgogIHZhciBkaXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgic2V0dGluZ3MiKTsKICAvL3NjcmVlbkxvZygiRHVwbGljYXRlIElEIiwgImVycm9yIiwgdHJ1ZSkKICAKCiAgLy8gQnVpbGQgdGFibGUKCiAgdmFyIG5ld1dyYXBwZXIgPSBuZXcgT2JqZWN0KCk7CiAgbmV3V3JhcHBlclsiX2VsZW1lbnQiXSAgPSAiRElWIjsKICBuZXdXcmFwcGVyWyJpZCJdICAgICAgICA9ICJib3gtd3JhcHBlciI7CiAgZGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3V3JhcHBlcikpOwoKCiAgdmFyIG5ld1RhYmxlID0gbmV3IE9iamVjdCgpOwogIG5ld1RhYmxlWyJfZWxlbWVudCJdICA9ICJUQUJMRSI7CiAgbmV3VGFibGVbImlkIl0gICAgICAgID0gImlkX21hcHBpbmciOwogIG5ld1RhYmxlWyJjbGFzcyJdICAgICA9ICJ0YWJsZS1tYXBwaW5nIjsKICBkaXYubGFzdENoaWxkLmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3VGFibGUpKTsKICBzaG93TG9hZGluZ1NjcmVlbih0cnVlKTsKCiAgc2V0VGltZW91dChmdW5jdGlvbigpeyAKICAgIGNyZWF0ZU1hcHBpbmdUYWJsZSgpOyAKICB9LCAxMCk7Cgp9CgpmdW5jdGlvbiBjcmVhdGVTZWFyY2hPYmooKSB7CiAgc2VhcmNoT2JqID0gbmV3IE9iamVjdCgpOwogIHZhciBJRHMgPSBnZXRPYmpLZXlzKHhFUEdbImVwZ01hcHBpbmciXSkKICBmb3IgKHZhciBpID0gSURzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICB2YXIgaXRlbSA9IHhFUEdbImVwZ01hcHBpbmciXVtJRHNbaV1dOwogICAgdmFyIHNlYXJjaElEID0gaXRlbVsieC1lcGciXTsKICAgIHZhciBzZWFyY2hWYWx1ZSA9ICIiOyAKICAgIHNlYXJjaFZhbHVlID0gc2VhcmNoVmFsdWUgKyBpdGVtWyJ4LWNoYW5uZWxJRCJdICsgIiAiOwogICAgc2VhcmNoVmFsdWUgPSBzZWFyY2hWYWx1ZSArIGl0ZW1bIngtY2F0ZWdvcnkiXSArICIgIjsKICAgIHNlYXJjaFZhbHVlID0gc2VhcmNoVmFsdWUgKyBpdGVtWyJ4LW5hbWUiXSArICIgIjsKICAgIHNlYXJjaFZhbHVlID0gc2VhcmNoVmFsdWUgKyBpdGVtWyJ4LWdyb3VwLXRpdGxlIl0gKyAiICI7CiAgICBzZWFyY2hWYWx1ZSA9IHNlYXJjaFZhbHVlICsgaXRlbVsieC14bWx0di1maWxlIl0gKyAiICI7CiAgICBzZWFyY2hWYWx1ZSA9IHNlYXJjaFZhbHVlICsgaXRlbVsiX2ZpbGUubTN1Lm5hbWUiXSArICIgIjsKCiAgICBzd2l0Y2goaXRlbVsieC1hY3RpdmUiXSkgewogICAgICBjYXNlIHRydWU6ICBzZWFyY2hWYWx1ZSA9IHNlYXJjaFZhbHVlICsgIm9ubGluZSI7IGJyZWFrOwogICAgICBjYXNlIGZhbHNlOiBzZWFyY2hWYWx1ZSA9IHNlYXJjaFZhbHVlICsgIm9mZmxpbmUiOyBicmVhazsKICAgIH0KCiAgICBzZWFyY2hPYmpbc2VhcmNoVmFsdWVdID0gc2VhcmNoSUQ7CgogIH0KfQoKCmZ1bmN0aW9uIGNhbGN1bGF0ZVdyYXBwZXJIZWlnaHQoKSB7CgogIGlmIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiYm94LXdyYXBwZXIiKSl7CgogICAgdmFyIGVsbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJib3gtd3JhcHBlciIpOwogICAgCiAgICB2YXIgZGl2cyA9IG5ldyBBcnJheSgibXlTdHJlYW1zQm94IiwgImNsaWVudEluZm8iLCAic2V0dGluZ3MiKTsKICAgIHZhciBlbGVtZW50c0hlaWdodCA9IDAgLSBlbG0ub2Zmc2V0SGVpZ2h0OwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkaXZzLmxlbmd0aDsgaSsrKSB7CiAgICAgIGVsZW1lbnRzSGVpZ2h0ID0gZWxlbWVudHNIZWlnaHQgKyBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChkaXZzW2ldKS5vZmZzZXRIZWlnaHQ7CiAgICB9CgogICAgZWxtLnN0eWxlLmhlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodCAtIGVsZW1lbnRzSGVpZ2h0ICsgInB4IjsKCiAgfQoKICBpZiAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm1lbnUtd3JhcHBlciIpKXsKCiAgICB2YXIgZWxtID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm1lbnUtd3JhcHBlciIpOwogICAgCiAgICB2YXIgb2ZmZXN0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNldHRpbmdzIikub2Zmc2V0SGVpZ2h0ICsgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm15U3RyZWFtc0JveCIpLm9mZnNldEhlaWdodCArIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJjbGllbnRJbmZvIikub2Zmc2V0SGVpZ2h0OwogICAgCiAgICBpZiAod2luZG93LmlubmVySGVpZ2h0ID4gb2ZmZXN0KSB7CiAgICAgIGVsbS5zdHlsZS5oZWlnaHQgPSB3aW5kb3cuaW5uZXJIZWlnaHQgKyAicHgiCiAgICB9IGVsc2UgewogICAgICBlbG0uc3R5bGUuaGVpZ2h0ID0gb2ZmZXN0ICsgInB4IgogICAgfQogICAgCgogIH0KCgp9CgpmdW5jdGlvbiBjcmVhdGVNYXBwaW5nVGFibGUoKSB7CiAgY29sdW1uVG9Tb3J0ID0gMTsKICBjcmVhdGVTZWFyY2hPYmooKTsKCiAgLy8gQ3JlYXRlIHRhYmxlIChIZWFkZXIpCiAgdmFyIHRhYmxlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImlkX21hcHBpbmciKTsKICB0YWJsZS5pbm5lckhUTUwgPSAiIjsKICB2YXIgbmV3VFIgPSBuZXcgT2JqZWN0KCk7CiAgbmV3VFJbIl9lbGVtZW50Il0gPSAiVFIiOwogIG5ld1RSWyJjbGFzcyJdICAgID0gInRhYmxlLW1hcHBpbmctaGVhZGVyIjsKICB0YWJsZS5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld1RSKSk7CgogIHZhciB0ciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJpZF9tYXBwaW5nIikubGFzdENoaWxkOwogIHZhciB0ckhlYWRsaW5lcyA9IG5ldyBBcnJheSgiQnVsayIsICJDaC4gTm8uIiwgIkxvZ28iLCAiQ2hhbm5lbCBOYW1lIiwgIlBsYXlsaXN0IiwgIkdyb3VwIFRpdGxlIiwgIlhNTFRWIEZpbGUiLCAiWE1MVFYgSUQiKQoKICBmb3IgKHZhciBpID0gMDsgaSA8IHRySGVhZGxpbmVzLmxlbmd0aDsgaSsrKSB7CiAgICB2YXIgbmV3VEQgPSBuZXcgT2JqZWN0KCk7CgogICAgbmV3VERbIl9lbGVtZW50Il0gPSAiVEQiOwogICAgbmV3VERbIl90ZXh0Il0gICAgPSB0ckhlYWRsaW5lc1tpXTsKCiAgICAKCiAgICB2YXIgd2lkdGggPSAiIjsKICAgIHN3aXRjaCh0ckhlYWRsaW5lc1tpXSkgewoKICAgICAgY2FzZSAiQnVsayI6ICAKICAgICAgICAKICAgICAgICBtYXhXaWR0aCA9ICIzMnB4IjsgCiAgICAgICAgbWluV2lkdGggPSAiMzJweCI7IAogICAgCiAgICAgICAgLy8gQ3JlYXRlIGJ1bGsgVEQKICAgICAgICB2YXIgbmV3Q2hlY2tib3ggPSBuZXcgT2JqZWN0KCk7CiAgICAgICAgbmV3Q2hlY2tib3hbIl9lbGVtZW50Il0gPSAiSU5QVVQiOwogICAgICAgIG5ld0NoZWNrYm94WyJ0eXBlIl0gICAgID0gImNoZWNrYm94IjsKICAgICAgICBuZXdDaGVja2JveFsiY2xhc3MiXSAgICA9ICJidWxrIGhpZGVCdWxrIjsKICAgICAgICBuZXdDaGVja2JveFsib25tb3VzZW91dCJdID0gImphdmFzY3JpcHQ6IHRoaXMuYmx1cigpIgogICAgICAgIG5ld0NoZWNrYm94WyJvbmNsaWNrIl0gICAgPSAiamF2YXNjcmlwdDogYnVsa0VkaXRBbGxDaGFubmVscygpIgoKICAgIAogICAgICAgIC8vbmV3VEQuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdDaGVja2JveCkpOwoKICAgICAgICBicmVhazsKCiAgICAgIGNhc2UgIkNoLiBOby4iOiAKICAgICAgICBtYXhXaWR0aCA9ICI4MHB4IjsgCiAgICAgICAgbWluV2lkdGggPSAiNzBweCI7IAogICAgICAgIG5ld1REWyJvbmNsaWNrIl0gID0gImphdnNjcmlwdDogc29ydFRhYmxlKCIgKyBpICsgIik7IjsKICAgICAgICBuZXdURFsiY2xhc3MiXSAgICA9ICJwb2ludGVyIjsKICAgICAgICBicmVhazsKICAgICAgCiAgICAgIGNhc2UgIkxvZ28iOiAgbWF4V2lkdGggPSAiMTIwcHgiOyBtaW5XaWR0aCA9ICI2MHB4IjsgYnJlYWs7CiAgICAgIAogICAgICBjYXNlICJDaGFubmVsIE5hbWUiOiAgCiAgICAgICAgbWF4V2lkdGggPSAiNTAlIjsgCiAgICAgICAgbWluV2lkdGggPSAiMjAwcHgiOyAKICAgICAgICBuZXdURFsib25jbGljayJdICA9ICJqYXZzY3JpcHQ6IHNvcnRUYWJsZSgiICsgaSArICIpOyI7CiAgICAgICAgbmV3VERbImNsYXNzIl0gPSAicG9pbnRlciI7CiAgICAgICAgYnJlYWs7CgogICAgICBjYXNlICJQbGF5bGlzdCI6ICAgICAgCiAgICAgICAgbWF4V2lkdGggPSAiMTUwcHgiOyAKICAgICAgICBtaW5XaWR0aCA9ICIxMDBweCI7IAogICAgICAgIG5ld1REWyJvbmNsaWNrIl0gID0gImphdnNjcmlwdDogc29ydFRhYmxlKCIgKyBpICsgIik7IjsKICAgICAgICBuZXdURFsiY2xhc3MiXSAgICA9ICJwb2ludGVyIjsKICAgICAgICBicmVhazsKICAgICAgCiAgICAgIGNhc2UgIkdyb3VwIFRpdGxlIjogICAKICAgICAgICBtYXhXaWR0aCA9ICIxNTBweCI7IAogICAgICAgIG1pbldpZHRoID0gIjEwMHB4IjsgCiAgICAgICAgbmV3VERbIm9uY2xpY2siXSAgPSAiamF2c2NyaXB0OiBzb3J0VGFibGUoIiArIGkgKyAiKTsiOwogICAgICAgIG5ld1REWyJjbGFzcyJdICAgID0gInBvaW50ZXIiOwogICAgICAgIGJyZWFrOwogICAgICAKICAgICAgY2FzZSAiWE1MVFYgRmlsZSI6ICAgIAogICAgICAgIG1heFdpZHRoID0gIjE1MHB4IjsgCiAgICAgICAgbWluV2lkdGggPSAiMTAwcHgiOyAKICAgICAgICAvL25ld1REWyJvbmNsaWNrIl0gID0gImphdnNjcmlwdDogc29ydFRhYmxlKCIgKyBpICsgIik7IjsKICAgICAgICBuZXdURFsiY2xhc3MiXSAgICA9ICIiOwogICAgICAgIGJyZWFrOwogICAgICAKCiAgICAgIGNhc2UgIlhNTFRWIElEIjogICAgICBtYXhXaWR0aCA9ICIxNTBweCI7IG1pbldpZHRoID0gIjEwMHB4IjsgYnJlYWs7CgogICAgICBkZWZhdWx0OiAKICAgICAgICBuZXdURFsiY2xhc3MiXSAgICA9ICIiOwogICAgICAgIGJyZWFrOwogICAgfQoKICAgIHRyLmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3VEQpKTsKICAgIGlmICh0ckhlYWRsaW5lc1tpXSA9PSAiQnVsayIpIHsKICAgICAgdHIubGFzdENoaWxkLmlubmVySFRNTCA9ICIiOwogICAgICB0ci5sYXN0Q2hpbGQuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdDaGVja2JveCkpOwogICAgICAKICAgIH0KICAgIAogICAgdmFyIGVsbSA9IHRyLmxhc3RDaGlsZDsKICAgIGVsbS5zdHlsZS53aWR0aCA9IG1heFdpZHRoOwogICAgZWxtLnN0eWxlLm1heFdpZHRoID0gbWF4V2lkdGg7CiAgICBlbG0uc3R5bGUubWluV2lkdGggPSBtaW5XaWR0aDsKCiAgfQogIGNhbGN1bGF0ZVdyYXBwZXJIZWlnaHQoKTsKICB2YXIgSURzID0gZ2V0T2JqS2V5cyh4RVBHWyJlcGdNYXBwaW5nIl0pCgogIHZhciBhbGxYbWx0dkZpbGVzID0gZ2V0T2JqS2V5cyh4RVBHWyJ4bWx0dk1hcCJdKTsKCiAgaWYgKGFsbFhtbHR2RmlsZXMgPT0gMCkgewogICAgc2hvd0xvYWRpbmdTY3JlZW4oZmFsc2UpOwogICAgcmV0dXJuOwogIH0KCiAgLy8gU29ydCBJRHMKICB2YXIgcG9zT2JqID0gbmV3IE9iamVjdCgpOwogIGZvciAodmFyIGkgPSAwOyBpIDwgSURzLmxlbmd0aDsgaSsrKSB7CiAgICB2YXIgaXRlbSAgPSB4RVBHWyJlcGdNYXBwaW5nIl1bSURzW2ldXTsKICAgIHZhciBwb3MKICAgIHN3aXRjaChpc05hTih4RVBHWyJlcGdNYXBwaW5nIl1bSURzW2ldXVsieC1jaGFubmVsSUQiXSkpIHsKICAgICAgY2FzZSBmYWxzZTogcG9zID0gcGFyc2VGbG9hdCh4RVBHWyJlcGdNYXBwaW5nIl1bSURzW2ldXVsieC1jaGFubmVsSUQiXSkgOyBicmVhazsKICAgIH0KICAgIHBvc09ialtwb3NdID0gaXRlbTsKICB9CiAgcG9zRmxvYXQgPSBnZXRPYmpLZXlzKHBvc09iaikKICBmdW5jdGlvbiBzb3J0RmxvYXQoYSxiKSB7IHJldHVybiBhIC0gYjsgfQogIHBvc0Zsb2F0LnNvcnQoc29ydEZsb2F0KQoKICAvL2NvbnNvbGUubG9nKHBvc0Zsb2F0KTsKCiAgLy8gLS0tCgogIGlmIChJRHMubGVuZ3RoID4gMjAwKSB7CiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7IAogICAgICBzaG93TG9hZGluZ1NjcmVlbih0cnVlKTsKICAgIH0sIDEpOwoKICB9CgoKICAvLyB0YWJsZSBmb3IgaW50IGNoYW5uZWwgSUQncwogIGZvciAodmFyIGkgPSAwOyBpIDwgcG9zRmxvYXQubGVuZ3RoOyBpKyspIHsKCiAgICB2YXIgdGFibGUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiaWRfbWFwcGluZyIpOwogICAgdmFyIGl0ZW0gID0gcG9zT2JqW3Bvc0Zsb2F0W2ldXTsKICAgIC8vdmFyIGl0ZW0gID0geEVQR1siZXBnTWFwcGluZyJdW0lEc1tpXV07CiAgICAvL2NvbnNvbGUubG9nKGl0ZW0pOwogICAgdmFyIG5ld1RSID0gbmV3IE9iamVjdCgpOwogICAgbmV3VFJbIl9lbGVtZW50Il0gICAgICAgPSAiVFIiOwogICAgbmV3VFJbImNsYXNzIl0gICAgICAgICAgPSAiIjsKICAgIG5ld1RSWyJpZCJdICAgICAgICAgICAgID0gaXRlbVsieC1lcGciXTsKICAgIG5ld1RSWyJvbmNvbnRleHRtZW51Il0gID0gJ2phdmFzY3JpcHQ6IHN3aXRjaENoYW5uZWxTdGF0dXMoIicgKyBpdGVtWyJ4LWVwZyJdICsgJyIpOyByZXR1cm4gZmFsc2U7JzsKICAgIHRhYmxlLmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3VFIpKTsKCiAgICB2YXIgdHIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiaWRfbWFwcGluZyIpLmxhc3RDaGlsZDsKICAgIAogICAgLy8gQ3JlYXRlIGJ1bGsgVEQKICAgIHZhciBuZXdURCA9IG5ldyBPYmplY3QoKTsKICAgIG5ld1REWyJfZWxlbWVudCJdICAgPSAiSU5QVVQiOwogICAgbmV3VERbInR5cGUiXSAgICAgICA9ICJjaGVja2JveCI7CiAgICBuZXdURFsiY2xhc3MiXSAgICAgID0gImJ1bGsgaGlkZUJ1bGsiOwogICAgbmV3VERbIm9ubW91c2VvdXQiXSA9ICJqYXZhc2NyaXB0OiB0aGlzLmJsdXIoKSIKICAgIAogICAgY3JlYXRlTmV3VEQobmV3VEQsIHRyKTsKICAgIAoKICAgIC8vIENyZWF0ZSBJRCBURAogICAgdmFyIG5ld1REID0gbmV3IE9iamVjdCgpOwogICAgbmV3VERbIl9lbGVtZW50Il0gPSAiSU5QVVQiOwogICAgbmV3VERbInR5cGUiXSAgICAgPSAidGV4dCIKICAgIG5ld1REWyJjbGFzcyJdICAgID0gInc0MHB4IjsKICAgIG5ld1REWyJ2YWx1ZSJdICAgID0gaXRlbVsieC1jaGFubmVsSUQiXTsKICAgIG5ld1REWyJvbmZvY3Vzb3V0Il0gPSAiamF2YXNjcmlwdDogYXJyYW5nZVRhYmxlKHRoaXMpOyIKICAgIGNyZWF0ZU5ld1REKG5ld1RELCB0cik7CgogICAgLy8gQ3JlYXRlIElNRyBURAogICAgdmFyIG5ld1REID0gbmV3IE9iamVjdCgpOwogICAgbmV3VERbIl9lbGVtZW50Il0gPSAiSU1HIjsKICAgIG5ld1REWyJvbmNsaWNrIl0gID0gJ2phdmFzY3JpcHQ6IG1hcHBpbmdEZXRhaWwoIicgKyBpdGVtWyJ4LWVwZyJdICsgJyIpOyc7CiAgICBpZiAoaXRlbVsidHZnLWxvZ28iXSAhPSB1bmRlZmluZWQpIHsKICAgICAgbmV3VERbInNyYyJdICAgICAgPSBpdGVtWyJ0dmctbG9nbyJdOwogICAgfSBlbHNlIHsKICAgICAgaXRlbVsidHZnLWxvZ28iXSA9ICIiOwogICAgICBuZXdURFsic3JjIl0gPSAiIjsKICAgIH0KICAgIGNyZWF0ZU5ld1REKG5ld1RELCB0cik7CiAgICB0ci5sYXN0Q2hpbGQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IG1hcHBpbmdEZXRhaWwoIicgKyBpdGVtWyJ4LWVwZyJdICsgJyIpOycpCgogICAgLy8gQ3JlYXRlIFAgVEQgKGNoYW5uZWwgbmFtZSkKICAgIHZhciBuZXdURCA9IG5ldyBPYmplY3QoKTsKICAgIG5ld1REWyJfZWxlbWVudCJdID0gIlAiOwogICAgbmV3VERbIl90ZXh0Il0gICAgPSBpdGVtWyJ4LW5hbWUiXTsKICAgIG5ld1REWyJjbGFzcyJdICAgICA9IGl0ZW1bIngtY2F0ZWdvcnkiXTsKCiAgICBjcmVhdGVOZXdURChuZXdURCwgdHIpOwogICAgdHIubGFzdENoaWxkLnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBtYXBwaW5nRGV0YWlsKCInICsgaXRlbVsieC1lcGciXSArICciKTsnKQogICAgdHIubGFzdENoaWxkLmxhc3RDaGlsZC5zdHlsZS5wYWRkaW5nID0gIjVweCAxMHB4IjsKCiAgICAvLyBDcmVhdGUgUCBURCAoUGxheWxpc3QgTmFtZSkKICAgIHZhciBuZXdURCA9IG5ldyBPYmplY3QoKTsKICAgIG5ld1REWyJfZWxlbWVudCJdID0gIlAiOwogICAgbmV3VERbIl90ZXh0Il0gICAgPSBpdGVtWyJfZmlsZS5tM3UubmFtZSJdOwogICAgbmV3VERbImNsYXNzIl0gICAgID0gaXRlbVsidGFibGVFbGxpcHNpcyJdOwogICAgCiAgICBjcmVhdGVOZXdURChuZXdURCwgdHIpOwogICAgdHIubGFzdENoaWxkLnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBtYXBwaW5nRGV0YWlsKCInICsgaXRlbVsieC1lcGciXSArICciKTsnKQogICAgCiAgICAvLyBDcmVhdGUgUCBURCAoR3JvdXAgVGl0bGUpCiAgICB2YXIgbmV3VEQgPSBuZXcgT2JqZWN0KCk7CiAgICBuZXdURFsiX2VsZW1lbnQiXSA9ICJQIjsKICAgIG5ld1REWyJfdGV4dCJdICAgID0gaXRlbVsieC1ncm91cC10aXRsZSJdOwogICAgbmV3VERbImNsYXNzIl0gICAgID0gaXRlbVsidGFibGVFbGxpcHNpcyJdOwogICAgCiAgICBjcmVhdGVOZXdURChuZXdURCwgdHIpOwogICAgdHIubGFzdENoaWxkLnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBtYXBwaW5nRGV0YWlsKCInICsgaXRlbVsieC1lcGciXSArICciKTsnKQoKICAgIAogICAgLy8gQ3JlYXRlIFAgVEQgKFhNTFRWIGZpbGUpCiAgICB2YXIgbmV3VEQgPSBuZXcgT2JqZWN0KCk7CiAgICBuZXdURFsiX2VsZW1lbnQiXSAgICAgICA9ICJQIjsKICAgIG5ld1REWyJjbGFzcyJdICAgID0gInRhYmxlRWxsaXBzaXMiOwogICAgbmV3VERbIl90ZXh0Il0gPSAiLSIKCiAgICBpZiAoYWxsWG1sdHZGaWxlcy5pbmRleE9mKGl0ZW1bIngteG1sdHYtZmlsZSJdKSAhPSAtMSkgewogICAgICB2YXIgeFhtbHR2RmlsZSA9IGl0ZW1bIngteG1sdHYtZmlsZSJdOwogICAgICBzd2l0Y2goeFhtbHR2RmlsZSkgewogICAgICAgIGNhc2UgIi0iOiAgICAgICAgICAgbmV3VERbIl90ZXh0Il0gID0geFhtbHR2RmlsZTsgYnJlYWs7CiAgICAgICAgY2FzZSAieFRlVmUgRHVtbXkiOiBuZXdURFsiX3RleHQiXSAgPSB4WG1sdHZGaWxlOyBicmVhazsKICAgICAgICBkZWZhdWx0OiAgICAgICAgICAgIG5ld1REWyJfdGV4dCJdICA9IGdldFZhbHVlRnJvbVByb3ZpZGVyRmlsZSh4WG1sdHZGaWxlLCAieG1sdHYiLCAibmFtZSIpOyBicmVhazsKICAgICAgICAKICAgICAgfQogICAgICAvL2NvbnNvbGUubG9nKG5ld1REKTsKCiAgICAgIC8vbmV3VERbIl90ZXh0Il0gICAgPSBpdGVtWyJ4LXhtbHR2LWZpbGUiXTsKICAgIH0gZWxzZSB7CiAgICAgIC8vbmV3VERbIl90ZXh0Il0gPSAiLSIKICAgIH0KICAgIGNyZWF0ZU5ld1REKG5ld1RELCB0cik7CiAgICB0ci5sYXN0Q2hpbGQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IG1hcHBpbmdEZXRhaWwoIicgKyBpdGVtWyJ4LWVwZyJdICsgJyIpOycpCgogICAgLy8gQ3JlYXRyIFAgVEQgKFhNTFRWIGNoYW5uZWwgSUQpCiAgICBuZXdURFsiX2VsZW1lbnQiXSA9ICJQIjsKICAgIG5ld1REWyJjbGFzcyJdICAgID0gInRhYmxlRWxsaXBzaXMiOwoKICAgIGlmIChpdGVtWyJ4LW1hcHBpbmciXSAhPSB1bmRlZmluZWQpIHsKICAgICAgbmV3VERbIl90ZXh0Il0gICAgPSBpdGVtWyJ4LW1hcHBpbmciXTsKICAgIH0KICAgIAogICAgY3JlYXRlTmV3VEQobmV3VEQsIHRyKTsKICAgIHRyLmxhc3RDaGlsZC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogbWFwcGluZ0RldGFpbCgiJyArIGl0ZW1bIngtZXBnIl0gKyAnIik7JykKCgogICAgdmFyIHhYbWx0dkZpbGUgID0gaXRlbVsieC14bWx0di1maWxlIl07CiAgICB2YXIgeE1hcHBpbmcgICAgPSBpdGVtWyJ4LW1hcHBpbmciXTsKICAgIHZhciB0dmdJRCAgICAgICA9IGl0ZW1bInR2Zy1pZCJdOwogICAgCiAgICAvL2NvbnNvbGUubG9nKGl0ZW1bIngtZXBnIl0pOwogICAgLy9jb25zb2xlLmxvZyhpdGVtKTsKCiAgICBpZiAoaXRlbVsieC1hY3RpdmUiXSA9PSB0cnVlKSB7CiAgICAgIHRyLmNsYXNzTmFtZSA9ICJhY3RpdmVFUEciOwogICAgfSBlbHNlIHsKICAgICAgdHIuY2xhc3NOYW1lID0gIm5vdEFjdGl2ZUVQRyI7CiAgICB9CiAgICAKICB9CgogIHNvcnRUYWJsZSgxKTsKCiAgc2V0VGltZW91dChmdW5jdGlvbigpeyAKICAgIHNob3dMb2FkaW5nU2NyZWVuKGZhbHNlKTsKICB9LCA1KTsKfQoKZnVuY3Rpb24gc2VhcmNoSW5NYXBwaW5nKGVsbSkgewoKICB2YXIgc2VhcmNoID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNlYXJjaE1hcHBpbmciKS52YWx1ZTsKICB2YXIgdmFsdWVzID0gZ2V0T2JqS2V5cyhzZWFyY2hPYmopCiAgCiAgZm9yICh2YXIgaSA9IHZhbHVlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgdmFyIGlkID0gc2VhcmNoT2JqW3ZhbHVlc1tpXV07CiAgICB2YXIgYm9vbCA9IHZhbHVlc1tpXS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHNlYXJjaC50b0xvd2VyQ2FzZSgpKTsKICAgIHN3aXRjaChib29sKSB7CiAgICAgIGNhc2UgdHJ1ZTogIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5zdHlsZS5kaXNwbGF5ID0gIiI7IGJyZWFrOwogICAgICBjYXNlIGZhbHNlOiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCkuc3R5bGUuZGlzcGxheSA9ICJub25lIjsgYnJlYWs7CiAgICB9CiAgfQoKfQoKZnVuY3Rpb24gbWFwcGluZ0RldGFpbCh4ZXBnKSB7CiAgCiAgYnVsa0lEcyAgID0gbmV3IEFycmF5KCk7CiAgdmFyIGFjdGl2ZUVsZW1lbnQgPSBkb2N1bWVudC5hY3RpdmVFbGVtZW50OwogIC8vIElmIGlucHV0IGlkLCByZXR1cm4KICBpZiAoYWN0aXZlRWxlbWVudC50YWdOYW1lID09ICJJTlBVVCIpIHsKICAgIHJldHVybgogIH0KCiAgaWYgKGJ1bGsgPT0gdHJ1ZSkgewogICAgdmFyIGVsbSA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoImJ1bGsiKTsKICAgIGZvciAodmFyIGkgPSAxOyBpIDwgZWxtLmxlbmd0aDsgaSsrKSB7CiAgICAgIGlmIChlbG1baV0uY2hlY2tlZCA9PSB0cnVlKSB7CiAgICAgICAgdmFyIGlkID0gZWxtW2ldLnBhcmVudEVsZW1lbnQucGFyZW50RWxlbWVudC5pZDsKICAgICAgICBidWxrSURzLnB1c2goaWQpCiAgICAgIH0KICAgICAgCiAgICB9CgogICAgaWYgKGJ1bGtJRHMubGVuZ3RoID09IDApIHsKICAgICAgc2hvd0VsZW1lbnQoJ3BvcHVwJywgZmFsc2UpCiAgICAgIGFsZXJ0KCJObyBjaGFubmVscyBzZWxlY3RlZCBmb3IgZWRpdGluZyIpCiAgICAgIHJldHVybgogICAgfQoKICAgIHhlcGcgPSBidWxrSURzWzBdCiAgfQoKCiAgY3JlYXRlU2VhcmNoT2JqKCk7CiAgCiAgc2hvd1BvcFVwRWxlbWVudCgnbWFwcGluZy1kZXRhaWwnKTsKCiAgdmFyIHRoaXNDaGFubmVsID0geEVQR1siZXBnTWFwcGluZyJdW3hlcGddOwogIC8vY29uc29sZS5sb2codGhpc0NoYW5uZWwpOwogIHZhciB4WG1sdHZGaWxlICA9IHRoaXNDaGFubmVsWyJ4LXhtbHR2LWZpbGUiXTsKICB2YXIgeE1hcHBpbmcgICAgPSB0aGlzQ2hhbm5lbFsieC1tYXBwaW5nIl07CiAgdmFyIHhDYXRlZ29yeSAgID0gdGhpc0NoYW5uZWxbIngtY2F0ZWdvcnkiXTsKCiAgaWYgKHhYbWx0dkZpbGUgPT0gdW5kZWZpbmVkKSB7CiAgICB0aGlzQ2hhbm5lbFsieC14bWx0di1maWxlIl0gPSAiLSI7CiAgICB4WG1sdHZGaWxlID0gIi0iOwogIH0KCiAgaWYgKHhNYXBwaW5nID09IHVuZGVmaW5lZCkgewogICAgdGhpc0NoYW5uZWxbIngtbWFwcGluZyJdID0gIi0iOwogICAgeE1hcHBpbmcgPSAiLSI7CiAgfQoKICAvKgogIGNvbnNvbGUubG9nKCJJRDoiLCB4ZXBnKTsKICBjb25zb2xlLmxvZygiWE1MVFYgRmlsZToiLCB4WG1sdHZGaWxlKTsKICBjb25zb2xlLmxvZygiTWFwcGluZzoiLCB4TWFwcGluZyk7CiAgKi8KCiAgdmFyIGtleXMgPSBnZXRPYmpLZXlzKHRoaXNDaGFubmVsKTsKICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgIGlmKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGtleXNbaV0pKXsKICAgICAgdmFyIHRkID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoa2V5c1tpXSkKICAgIH0gZWxzZSB7CiAgICAgIHZhciB0ZCA9IHVuZGVmaW5lZDsKICAgIH0KICAgIAogICAgdmFyIG5ld0l0ZW0gPSBuZXcgT2JqZWN0KCk7CiAgICB2YXIgdmFsdWVzLCB0ZXh0ID0gbmV3IEFycmF5KCk7CiAgICBzd2l0Y2goa2V5c1tpXSkgewogICAgICBjYXNlICJ4LXhtbHR2LWZpbGUiOiAKICAgICAgICB2YXIgZmlsZUlEcyA9IGdldE9iaktleXMoeEVQR1sieG1sdHZNYXAiXSk7CiAgICAgICAgdmFyIHZhbHVlID0gbmV3IEFycmF5KCItIik7CiAgICAgICAgdmFyIHRleHQgID0gbmV3IEFycmF5KCItIik7CgogICAgICAgIGZvciAodmFyIGogPSBmaWxlSURzLmxlbmd0aCAtIDE7IGogPj0gMDsgai0tKSB7CiAgICAgICAgICBpZiAoZmlsZUlEc1tqXSAhPSAieFRlVmUgRHVtbXkiKSB7CiAgICAgICAgICAgIHZhbHVlLnB1c2goZ2V0VmFsdWVGcm9tUHJvdmlkZXJGaWxlKGZpbGVJRHNbal0sICJ4bWx0diIsICJmaWxlLnh0ZXZlIikpCiAgICAgICAgICAgIHRleHQucHVzaChnZXRWYWx1ZUZyb21Qcm92aWRlckZpbGUoZmlsZUlEc1tqXSwgInhtbHR2IiwgIm5hbWUiKSkKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHZhbHVlLnB1c2goZmlsZUlEc1tqXSkKICAgICAgICAgICAgdGV4dC5wdXNoKGZpbGVJRHNbal0pCiAgICAgICAgICB9CiAgICAgICAgICAKICAgICAgICB9CiAgICAgICAgCiAgICAgICAgbmV3SXRlbVsiX2VsZW1lbnQiXSAgICAgICA9ICJTRUxFQ1QiOwogICAgICAgIG5ld0l0ZW1bIl9vcHRpb25WYWx1ZXMiXSAgPSB2YWx1ZTsKICAgICAgICBuZXdJdGVtWyJfb3B0aW9uVGV4dCJdICAgID0gdGV4dAogICAgICAgIG5ld0l0ZW1bInZhbHVlIl0gICAgICAgICAgPSB4WG1sdHZGaWxlOwogICAgICAgIG5ld0l0ZW1bIm9uY2hhbmdlIl0gICAgICAgPSAnamF2YXNjcmlwdDogY2hhbmdlWG1sdHZGaWxlKCInICsgeGVwZyArICciLHRoaXMpOyc7CgogICAgICAgIGJyZWFrOwoKICAgICAgY2FzZSAieC1tYXBwaW5nIjogCgogICAgICAgIHZhciB2YWx1ZXMgPSBnZXRPYmpLZXlzKHhFUEdbInhtbHR2TWFwIl1beFhtbHR2RmlsZV0pOwoKICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHZhbHVlcy5sZW5ndGg7IGorKykgewogICAgICAgICAgCiAgICAgICAgICBpZiAoeEVQR1sieG1sdHZNYXAiXVt4WG1sdHZGaWxlXVt2YWx1ZXNbal1dLmhhc093blByb3BlcnR5KCdkaXNwbGF5LW5hbWUnKSA9PSB0cnVlKSB7CiAgICAgICAgICAgIHZhciBkaXNwbGF5TmFtZSA9IHhFUEdbInhtbHR2TWFwIl1beFhtbHR2RmlsZV1bdmFsdWVzW2pdXVsiZGlzcGxheS1uYW1lIl07CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB2YXIgZGlzcGxheU5hbWUgPSAiLSIKICAgICAgICAgIH0KICAgICAgICAgIAogICAgICAgICAgLy90ZXh0W2pdID0gdmFsdWVzW2pdICsgIiAoIiArIGRpc3BsYXlOYW1lICsgIikiOwogICAgICAgICAgdGV4dFtqXSA9IGRpc3BsYXlOYW1lICsgIiAoIiArIHZhbHVlc1tqXSAgKyAiKSI7CiAgICAgICAgfQoKICAgICAgICB0ZXh0LnVuc2hpZnQoIi0iKTsKICAgICAgICB2YWx1ZXMudW5zaGlmdCgiLSIpOwogICAgICAgIG5ld0l0ZW1bIl9lbGVtZW50Il0gICAgICAgPSAiU0VMRUNUIjsKICAgICAgICBuZXdJdGVtWyJfb3B0aW9uVmFsdWVzIl0gID0gdmFsdWVzOwogICAgICAgIG5ld0l0ZW1bIl9vcHRpb25UZXh0Il0gICAgPSB0ZXh0CiAgICAgICAgbmV3SXRlbVsidmFsdWUiXSAgICAgICAgICA9IHhNYXBwaW5nOwogICAgICAgIG5ld0l0ZW1bIm9uY2hhbmdlIl0gICAgICAgPSAnamF2YXNjcmlwdDogbWFwcGluZ0NoYW5uZWwoIicgKyB4ZXBnICsgJyIsdGhpcyk7JzsKICAgICAgICBicmVhazsKCiAgICAgIGNhc2UgIngtY2F0ZWdvcnkiOgogICAgICAgIC8vdmFyIHZhbHVlcyA9IHBsZXhDYXRlZ29yaWVzVmFsdWVzCiAgICAgICAgbmV3SXRlbVsiX2VsZW1lbnQiXSAgICAgICA9ICJTRUxFQ1QiOwogICAgICAgIG5ld0l0ZW1bIl9vcHRpb25WYWx1ZXMiXSAgPSBwbGV4Q2F0ZWdvcmllc1ZhbHVlczsKICAgICAgICBuZXdJdGVtWyJfb3B0aW9uVGV4dCJdICAgID0gcGxleENhdGVnb3JpZXNPcHRpb247CiAgICAgICAgbmV3SXRlbVsidmFsdWUiXSAgICAgICAgICA9IHhDYXRlZ29yeTsKICAgICAgICBuZXdJdGVtWyJvbmNoYW5nZSJdICAgICAgID0gJ3NhdmVDYXRlZ29yeSgiJyArIHhlcGcgKyAnIiknOwogICAgICAgIGJyZWFrOwoKICAgICAgY2FzZSAidHZnLWxvZ28iOgogICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJjaGFubmVsLWxvZ28iKS5zZXRBdHRyaWJ1dGUoInNyYyIsIHRoaXNDaGFubmVsWyJ0dmctbG9nbyJdKTsKICAgICAgICBuZXdJdGVtWyJfZWxlbWVudCJdICAgICAgID0gIklOUFVUIjsKICAgICAgICBuZXdJdGVtWyJ0eXBlIl0gICAgICAgICAgID0gInRleHQiOwogICAgICAgIG5ld0l0ZW1bInZhbHVlIl0gICAgICAgICAgPSB0aGlzQ2hhbm5lbFsidHZnLWxvZ28iXTsKICAgICAgICBuZXdJdGVtWyJvbmZvY3Vzb3V0Il0gICAgID0gJ3NhdmVDaGFubmVsTG9nbygiJyArIHhlcGcgKyAnIiknOwogICAgICAgIG5ld0l0ZW1bInBsYWNlaG9sZGVyIl0gICAgPSAnSW1hZ2UgVVJMJzsKICAgICAgICBicmVhazsKCiAgICAgIGNhc2UgIngtdXBkYXRlLWNoYW5uZWwtaWNvbiI6CiAgICAgICAgbmV3SXRlbVsiX2VsZW1lbnQiXSAgICAgICA9ICJJTlBVVCI7CiAgICAgICAgbmV3SXRlbVsidHlwZSJdICAgICAgICAgICA9ICJjaGVja2JveCI7CiAgICAgICAgc3dpdGNoKEpTT04ucGFyc2UodGhpc0NoYW5uZWxbIngtdXBkYXRlLWNoYW5uZWwtaWNvbiJdKSkgewogICAgICAgICAgY2FzZSB0cnVlOiBuZXdJdGVtWyJjaGVja2VkIl0gICAgICAgID0gdGhpc0NoYW5uZWxbIngtdXBkYXRlLWNoYW5uZWwtaWNvbiJdOwogICAgICAgICAgICBicmVhawogICAgICAgIH0KICAgICAgICBuZXdJdGVtWyJvbmNoYW5nZSJdICAgICA9ICdzYXZlQ2hhbm5lbEljb25VcGRhdGUoIicgKyB4ZXBnICsgJyIpJzsKICAgICAgICBicmVhazsKCiAgICAgIGNhc2UgIngtbmFtZSI6CiAgICAgICAgbmV3SXRlbVsiX2VsZW1lbnQiXSAgICAgICA9ICJJTlBVVCI7CiAgICAgICAgbmV3SXRlbVsidHlwZSJdICAgICAgICAgICA9ICJ0ZXh0IjsKICAgICAgICBuZXdJdGVtWyJ2YWx1ZSJdICAgICAgICAgID0gdGhpc0NoYW5uZWxbIngtbmFtZSJdOwogICAgICAgIG5ld0l0ZW1bIm9uZm9jdXNvdXQiXSAgICAgPSAnc2F2ZUNoYW5uZWxOYW1lKCInICsgeGVwZyArICciKSc7CiAgICAgICAgbmV3SXRlbVsicGxhY2Vob2xkZXIiXSAgICA9ICdDaGFubmVsIE5hbWUnOwogICAgICAgIGJyZWFrOwoKICAgICAgY2FzZSAieC11cGRhdGUtY2hhbm5lbC1uYW1lIjoKICAgICAgICBpZiAodGhpc0NoYW5uZWwuaGFzT3duUHJvcGVydHkoIl91dWlkLmtleSIpID09IHRydWUpIHsKICAgICAgICAgIG5ld0l0ZW1bIl9lbGVtZW50Il0gICAgICAgPSAiSU5QVVQiOwogICAgICAgICAgbmV3SXRlbVsidHlwZSJdICAgICAgICAgICA9ICJjaGVja2JveCI7CiAgICAgICAgICBzd2l0Y2goSlNPTi5wYXJzZSh0aGlzQ2hhbm5lbFsieC11cGRhdGUtY2hhbm5lbC1uYW1lIl0pKSB7CiAgICAgICAgICAgIGNhc2UgdHJ1ZTogbmV3SXRlbVsiY2hlY2tlZCJdICAgICAgICA9IHRoaXNDaGFubmVsWyJ4LXVwZGF0ZS1jaGFubmVsLW5hbWUiXTsKICAgICAgICAgICAgICBicmVhawogICAgICAgICAgfQogICAgICAgICAgbmV3SXRlbVsib25jaGFuZ2UiXSAgICAgPSAnc2F2ZUNoYW5uZWxOYW1lVXBkYXRlKCInICsgeGVwZyArICciKSc7CiAgICAgICAgICBzaG93RWxlbWVudCgic3RyZWFtSGFzQ1VJRCIsIHRydWUpCgogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIC8vc3RyZWFtSGFzQ1VJRAogICAgICAgICAgc2hvd0VsZW1lbnQoInN0cmVhbUhhc0NVSUQiLCBmYWxzZSkKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICAKICAgICAgY2FzZSAieC1hY3RpdmUiOgogICAgICAgIG5ld0l0ZW1bIl9lbGVtZW50Il0gICAgICAgPSAiSU5QVVQiOwogICAgICAgIG5ld0l0ZW1bInR5cGUiXSAgICAgICAgICAgPSAiY2hlY2tib3giOwogICAgICAgIHN3aXRjaChKU09OLnBhcnNlKHRoaXNDaGFubmVsWyJ4LWFjdGl2ZSJdKSkgewogICAgICAgICAgY2FzZSB0cnVlOiBuZXdJdGVtWyJjaGVja2VkIl0gICAgICAgID0gdGhpc0NoYW5uZWxbIngtYWN0aXZlIl07CiAgICAgICAgICAgIGJyZWFrCiAgICAgICAgfQogICAgICAgIG5ld0l0ZW1bIm9uY2hhbmdlIl0gICAgID0gJ3NhdmVDaGFubmVsU3RhdHVzKCInICsgeGVwZyArICciKSc7CiAgICAgICAgYnJlYWs7CgogICAgICBjYXNlICJ4LWdyb3VwLXRpdGxlIjoKICAgICAgICBuZXdJdGVtWyJfZWxlbWVudCJdICAgICAgID0gIklOUFVUIjsKICAgICAgICBuZXdJdGVtWyJ0eXBlIl0gICAgICAgICAgID0gInRleHQiOwogICAgICAgIG5ld0l0ZW1bInZhbHVlIl0gICAgICAgICAgPSB0aGlzQ2hhbm5lbFsieC1ncm91cC10aXRsZSJdOwogICAgICAgIG5ld0l0ZW1bIm9uZm9jdXNvdXQiXSAgICAgPSAnc2F2ZUdyb3VwVGl0bGUoIicgKyB4ZXBnICsgJyIpJzsKICAgICAgICBuZXdJdGVtWyJwbGFjZWhvbGRlciJdICAgID0gJ0dyb3VwIFRpdGxlJzsKICAgICAgICBicmVhazsKCiAgICAgIGRlZmF1bHQ6CiAgICAgICAgbmV3SXRlbVsiX2VsZW1lbnQiXSAgICAgICA9ICJQIjsKICAgICAgICBuZXdJdGVtWyJfdGV4dCJdICAgICAgICAgID0gdGhpc0NoYW5uZWxba2V5c1tpXV07CiAgICAgICAgYnJlYWs7CiAgICAgIAogICAgfQogICAgCiAgICBpZiAodGQgIT0gdW5kZWZpbmVkKSB7CiAgICAgIHRkLmlubmVySFRNTCA9ICIiOwogICAgICB2YXIgZWxlbWVudCA9IGNyZWF0ZU5ld0VsZW1lbnQobmV3SXRlbSkKICAgICAgLy9jb25zb2xlLmxvZyhlbGVtZW50KTsKICAgICAgdGQuYXBwZW5kQ2hpbGQoZWxlbWVudCk7CiAgICB9CgogIH0KCiAgaWYgKGJ1bGsgPT0gdHJ1ZSkgewoKICAgIHZhciBlbG0gPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCJub0J1bGsiKTsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxtLmxlbmd0aDsgaSsrKSB7CiAgICAgIGVsbVtpXS5sYXN0Q2hpbGQuc2V0QXR0cmlidXRlKCJyZWFkb25seSIsIHRydWUpCiAgICAgIGVsbVtpXS5sYXN0Q2hpbGQuc3R5bGUuYm9yZGVyQ29sb3IgPSAicmVkIjsKICAgIH0KCiAgICB4ZXBnID0gYnVsa0lEc1swXQogIH0KCiAgc29ydFNlbGVjdChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgieC14bWx0di1maWxlIikubGFzdENoaWxkKTsKICBzb3J0U2VsZWN0KGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ4LW1hcHBpbmciKS5sYXN0Q2hpbGQpOwogIAp9CgpmdW5jdGlvbiBzb3J0U2VsZWN0KGVsZW0pIHsKCiAgdmFyIHRtcEFyeSA9IFtdOwogIC8vIFJldGFpbiBzZWxlY3RlZCB2YWx1ZSBiZWZvcmUgc29ydGluZwogIHZhciBzZWxlY3RlZFZhbHVlID0gZWxlbVtlbGVtLnNlbGVjdGVkSW5kZXhdLnZhbHVlOwogIC8vIEdyYWIgYWxsIGV4aXN0aW5nIGVudHJpZXMKICBmb3IgKHZhciBpPTA7aTxlbGVtLm9wdGlvbnMubGVuZ3RoO2krKykgdG1wQXJ5LnB1c2goZWxlbS5vcHRpb25zW2ldKTsKICAvLyBTb3J0IGFycmF5IGJ5IHRleHQgYXR0cmlidXRlCiAgdG1wQXJ5LnNvcnQoZnVuY3Rpb24oYSxiKXsgcmV0dXJuIChhLnRleHQgPCBiLnRleHQpPy0xOjE7IH0pOwogIC8vIFdpcGUgb3V0IGV4aXN0aW5nIGVsZW1lbnRzCiAgd2hpbGUgKGVsZW0ub3B0aW9ucy5sZW5ndGggPiAwKSBlbGVtLm9wdGlvbnNbMF0gPSBudWxsOwogIC8vIFJlc3RvcmUgc29ydGVkIGVsZW1lbnRzCiAgdmFyIG5ld1NlbGVjdGVkSW5kZXggPSAwOwogIGZvciAodmFyIGk9MDtpPHRtcEFyeS5sZW5ndGg7aSsrKSB7CiAgICAgIGVsZW0ub3B0aW9uc1tpXSA9IHRtcEFyeVtpXTsKICAgICAgaWYoZWxlbS5vcHRpb25zW2ldLnZhbHVlID09IHNlbGVjdGVkVmFsdWUpIG5ld1NlbGVjdGVkSW5kZXggPSBpOwogIH0KICBlbGVtLnNlbGVjdGVkSW5kZXggPSBuZXdTZWxlY3RlZEluZGV4OyAvLyBTZXQgbmV3IHNlbGVjdGVkIGluZGV4IGFmdGVyIHNvcnRpbmcKICByZXR1cm47Cn0KCgpmdW5jdGlvbiBzd2l0Y2hDaGFubmVsU3RhdHVzKHhlcGcpIHsKICB2YXIgdGhpc0NoYW5uZWwgPSB4RVBHWyJlcGdNYXBwaW5nIl1beGVwZ107CiAgdmFyIHhYbWx0dkZpbGUgPSB0aGlzQ2hhbm5lbFsieC14bWx0di1maWxlIl07CgogIGlmICh4RVBHWyJ4bWx0dk1hcCJdLmhhc093blByb3BlcnR5KHhYbWx0dkZpbGUpID09IHRydWUpIHsKICAgIGlmICh0aGlzQ2hhbm5lbFsieC1tYXBwaW5nIl0gIT0gIi0iICYmIHRoaXNDaGFubmVsWyJ4LW1hcHBpbmciXSAhPSB1bmRlZmluZWQpIHsKICAgICAgdGhpc0NoYW5uZWxbIngtYWN0aXZlIl0gPSAhdGhpc0NoYW5uZWxbIngtYWN0aXZlIl07CiAgICAgIHZhciB0ciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHhlcGcpOwogICAgICBzd2l0Y2godGhpc0NoYW5uZWxbIngtYWN0aXZlIl0pIHsKICAgICAgICBjYXNlIHRydWU6IHRyLmNsYXNzTmFtZSA9ICJhY3RpdmVFUEciOyBicmVhazsKICAgICAgICBjYXNlIGZhbHNlOiB0ci5jbGFzc05hbWUgPSAibm90QWN0aXZlRVBHIjsgYnJlYWs7CiAgICAgIH0KICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImxvZ0luZm8iKS5jbGFzc05hbWUgPSAibm90VmlzaWJsZSI7CgogICAgfSBlbHNlIHsKICAgICAgdmFyIGVyciA9ICJYTUxUViBDaGFubmVsIGlzIG5vdCBzZWxlY3RlZCIKICAgICAgYWxlcnQoZXJyKQogICAgICAvKgogICAgICB2YXIgbmV3RXJyb3IgPSBuZXcgT2JqZWN0KCk7CiAgICAgIG5ld0Vycm9yWyJlcnIiXSA9ICJDaGFubmVsIGlzIG5vdCBzZWxlY3RlZCI7CiAgICAgIGNoZWNrRXJyKG5ld0Vycm9yKTsKICAgICAgKi8KICAgIH0KCiAgfSBlbHNlIHsKICAgIHZhciBlcnIgPSAiWE1MVFYgRmlsZSBpcyBub3Qgc2VsZWN0ZWQiCiAgICBhbGVydChlcnIpCiAgICAvKgogICAgdmFyIG5ld0Vycm9yID0gbmV3IE9iamVjdCgpOwogICAgbmV3RXJyb3JbImVyciJdID0gIlhNTFRWIGZpbGUgaXMgbm90IHNlbGVjdGVkIjsKICAgIGNoZWNrRXJyKG5ld0Vycm9yKTsKICAgICovCiAgfQoKICBzZWFyY2hJbk1hcHBpbmcoKTsKCn0KCmZ1bmN0aW9uIGNyZWF0ZU5ld0VsZW1lbnQobmV3SXRlbSkgewoKICB2YXIgZWxlbWVudCA9IGNyZWF0ZUVsZW1lbnQobmV3SXRlbSk7CiAgCiAgc3dpdGNoKG5ld0l0ZW1bIl9lbGVtZW50Il0pIHsKICAgIGNhc2UgIlNFTEVDVCI6CiAgICAgIC8vZWxlbWVudFtdCiAgICAgIHZhciB2YWx1ZXMgID0gbmV3SXRlbVsiX29wdGlvblZhbHVlcyJdOwogICAgICB2YXIgdGV4dCAgICA9IG5ld0l0ZW1bIl9vcHRpb25UZXh0Il07CgogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZhbHVlcy5sZW5ndGg7IGkrKykgewogICAgICAgIC8vY29uc29sZS5sb2coaXRlbSk7CiAgICAgICAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdDsKICAgICAgICBuZXdFbnRyeVsiX2VsZW1lbnQiXSAgPSAiT1BUSU9OIjsKICAgICAgICBuZXdFbnRyeVsiX3RleHQiXSAgICAgPSB0ZXh0W2ldOwogICAgICAgIG5ld0VudHJ5WyJ2YWx1ZSJdICAgICA9IHZhbHVlc1tpXTsKICAgICAgICBlbGVtZW50LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKICAgICAgfQogICAgICBlbGVtZW50LnZhbHVlID0gbmV3SXRlbVsidmFsdWUiXTsKICAgICAgYnJlYWs7CiAgICAKICAgIGRlZmF1bHQ6IAogICAgICAKICAgICAgLy9lbGVtZW50LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3SXRlbSkpOwogICAgICBicmVhazsKICB9CiAgCiAgcmV0dXJuIGVsZW1lbnQ7Cn0KCmZ1bmN0aW9uIHNhdmVCdWxrKGtleSwgdmFsdWUpIHsKICBmb3IgKHZhciBpID0gMDsgaSA8IGJ1bGtJRHMubGVuZ3RoOyBpKyspIHsKICAgIHZhciBpZCA9IGJ1bGtJRHNbaV0KICAgIHZhciB0aGlzQ2hhbm5lbCA9IHhFUEdbImVwZ01hcHBpbmciXVtpZF07CiAgICB0aGlzQ2hhbm5lbFtrZXldID0gdmFsdWU7CgogICAgc3dpdGNoKGtleSkgewogICAgICBjYXNlICJ0dmctbG9nbyI6ICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpLmNoaWxkTm9kZXNbMl0ubGFzdENoaWxkLnNldEF0dHJpYnV0ZSgic3JjIiwgdmFsdWUpOyBicmVhazsKICAgICAgCiAgICAgIGNhc2UgIngtY2F0ZWdvcnkiOiAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCkuY2hpbGROb2Rlc1szXS5sYXN0Q2hpbGQuY2xhc3NOYW1lID0gdmFsdWU7IGJyZWFrOwoKICAgICAgY2FzZSAieC14bWx0di1maWxlIjoKICAgICAgICB2YXIgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jaGlsZE5vZGVzWzZdLmxhc3RDaGlsZDsKICAgICAgICBzd2l0Y2godmFsdWUpIHsKICAgICAgICAgIGNhc2UgIi0iOiAgICAgICAgICAgZWxlbWVudC5pbm5lckhUTUwgPSB2YWx1ZTsgYnJlYWs7CiAgICAgICAgICBjYXNlICJ4VGVWZSBEdW1teSI6IGVsZW1lbnQuaW5uZXJIVE1MID0gdmFsdWU7IGJyZWFrOwogICAgICAgICAgZGVmYXVsdDogICAgICAgICAgICBlbGVtZW50LmlubmVySFRNTCA9IGdldFZhbHVlRnJvbVByb3ZpZGVyRmlsZSh2YWx1ZSwgInhtbHR2IiwgIm5hbWUiKTsgYnJlYWs7CiAgICAgICAgfQoKCgogICAgICAvL2RvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jaGlsZE5vZGVzWzVdLmxhc3RDaGlsZC5pbm5lckhUTUwgPSB2YWx1ZS5yZXBsYWNlKC9eLipbXFxcL10vLCAnJyk7IGJyZWFrOwogICAgICBjYXNlICJ4LW1hcHBpbmciOiAgIAogICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jaGlsZE5vZGVzWzddLmxhc3RDaGlsZC5pbm5lckhUTUwgPSB2YWx1ZTsKICAgICAgICBpZiAodmFsdWUgPT0gIi0iKSB7CiAgICAgICAgICB0aGlzQ2hhbm5lbFsieC1hY3RpdmUiXSA9IGZhbHNlOwogICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpLmNsYXNzTmFtZSA9ICJub3RBY3RpdmVFUEciOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzQ2hhbm5lbFsieC1hY3RpdmUiXSA9IHRydWU7CiAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCkuY2xhc3NOYW1lID0gImFjdGl2ZUVQRyI7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwoKICAgICAgY2FzZSAieC1ncm91cC10aXRsZSI6IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jaGlsZE5vZGVzWzVdLmxhc3RDaGlsZC5pbm5lckhUTUwgPSB2YWx1ZTsgYnJlYWs7CgogICAgICBjYXNlICJ4LWFjdGl2ZSI6CiAgICAgICAgdmFyIHRyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpOwogICAgICAgIAogICAgICAgIGlmICh0aGlzQ2hhbm5lbC5oYXNPd25Qcm9wZXJ0eSgieC14bWx0di1maWxlIikgPT0gdHJ1ZSkgewogICAgICAgICAgaWYgKHRoaXNDaGFubmVsWyJ4LW1hcHBpbmciXSAhPSAiLSIgJiYgdGhpc0NoYW5uZWxbIngtbWFwcGluZyJdICE9IHVuZGVmaW5lZCAmJiB0aGlzQ2hhbm5lbFsieC14bWx0di1maWxlIl0gIT0gIi0iICYmIHRoaXNDaGFubmVsWyJ4LXhtbHR2LWZpbGUiXSAhPSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgc3dpdGNoKHRoaXNDaGFubmVsWyJ4LWFjdGl2ZSJdKSB7CiAgICAgICAgICAgICAgY2FzZSB0cnVlOiB0ci5jbGFzc05hbWUgPSAiYWN0aXZlRVBHIjsgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSBmYWxzZTogdHIuY2xhc3NOYW1lID0gIm5vdEFjdGl2ZUVQRyI7IGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KCiAgICB9CgogICAgdXBkYXRlQ2hhbm5lbExvZ28oaWQpCgogIH0KCn0KCmZ1bmN0aW9uIHVwZGF0ZUNoYW5uZWxMb2dvKHhlcGcpIHsKICB2YXIgdGhpc0NoYW5uZWwgPSB4RVBHWyJlcGdNYXBwaW5nIl1beGVwZ107CiAgaWYgKHRoaXNDaGFubmVsWyJ4LXVwZGF0ZS1jaGFubmVsLWljb24iXSA9PSB0cnVlKSB7CiAgICB2YXIgeFhtbHR2RmlsZSAgPSB0aGlzQ2hhbm5lbFsieC14bWx0di1maWxlIl07CiAgICB2YXIgeE1hcHBpbmcgICAgPSB0aGlzQ2hhbm5lbFsieC1tYXBwaW5nIl07CgogICAgaWYgKHhYbWx0dkZpbGUgIT0gIi0iICYmIHhYbWx0dkZpbGUubGVuZ3RoID4gMCAmJiB4TWFwcGluZyAhPSAiLSIgJiYgeE1hcHBpbmcubGVuZ3RoID4gMCkgewogICAgICBpZiAoeEVQR1sieG1sdHZNYXAiXVt4WG1sdHZGaWxlXVt4TWFwcGluZ10uaGFzT3duUHJvcGVydHkoImljb24iKSkgewogICAgICAgIHZhciBsb2dvVVJMID0geEVQR1sieG1sdHZNYXAiXVt4WG1sdHZGaWxlXVt4TWFwcGluZ11bImljb24iXTsKICAgICAgICB0aGlzQ2hhbm5lbFsidHZnLWxvZ28iXSA9IGxvZ29VUkw7CiAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoeGVwZykuY2hpbGROb2Rlc1syXS5sYXN0Q2hpbGQuc2V0QXR0cmlidXRlKCJzcmMiLCBsb2dvVVJMKTsKICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiY2hhbm5lbC1sb2dvIikuc2V0QXR0cmlidXRlKCJzcmMiLCBsb2dvVVJMKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBhbGVydCgiTm8gbG9nbyBVUkwgaW4gdGhlIFhNTFRWIGZpbGUgYXZhaWxhYmxlIikKICAgICAgfQogICAgICAKICAgIH0KICAgIAogICAgLyoKICAgIGlmICh4RVBHWyJ4bWx0dk1hcCJdW3hYbWx0dkZpbGVdW3hNYXBwaW5nXVsiaWNvbiJdICE9IHVuZGVmaW5lZCkgewoKICAgICAgCiAgICB9CiAgICAqLwogICAgCiAgfQp9CgpmdW5jdGlvbiBzYXZlQ2hhbm5lbExvZ28oeGVwZykgewogIGlmIChidWxrID09IGZhbHNlKSB7CiAgICB2YXIgdGhpc0NoYW5uZWwgPSB4RVBHWyJlcGdNYXBwaW5nIl1beGVwZ107CiAgICB0aGlzQ2hhbm5lbFsidHZnLWxvZ28iXSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ0dmctbG9nbyIpLmxhc3RDaGlsZC52YWx1ZTsKICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHhlcGcpLmNoaWxkTm9kZXNbMl0ubGFzdENoaWxkLnNldEF0dHJpYnV0ZSgic3JjIiwgdGhpc0NoYW5uZWxbInR2Zy1sb2dvIl0pOwogICAgbWFwcGluZ0RldGFpbCh4ZXBnKTsKICAgIHJldHVybgogIH0KCiAgaWYgKGJ1bGsgPT0gdHJ1ZSkgewogICAgdmFyIGtleSAgID0gInR2Zy1sb2dvIjsKICAgIHZhciB2YWx1ZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ0dmctbG9nbyIpLmxhc3RDaGlsZC52YWx1ZTsKICAgIHNhdmVCdWxrKGtleSwgdmFsdWUpOwoKICAgIG1hcHBpbmdEZXRhaWwoeGVwZyk7CiAgICByZXR1cm4KICB9Cn0KCmZ1bmN0aW9uIHNhdmVDaGFubmVsSWNvblVwZGF0ZSh4ZXBnKSB7CgogIHZhciBrZXkgICA9ICJ4LXVwZGF0ZS1jaGFubmVsLWljb24iOwogIHZhciB2YWx1ZSA9IEpTT04ucGFyc2UoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIngtdXBkYXRlLWNoYW5uZWwtaWNvbiIpLmxhc3RDaGlsZC5jaGVja2VkKTsKICBpZiAoYnVsayA9PSBmYWxzZSkgewogICAgdmFyIHRoaXNDaGFubmVsID0geEVQR1siZXBnTWFwcGluZyJdW3hlcGddOwogICAgdGhpc0NoYW5uZWxba2V5XSA9IHZhbHVlCiAgICB1cGRhdGVDaGFubmVsTG9nbyh4ZXBnKQogICAgCiAgICBtYXBwaW5nRGV0YWlsKHhlcGcpOwogICAgc2VhcmNoSW5NYXBwaW5nKCk7CiAgICByZXR1cm4KICB9CgogIGlmIChidWxrID09IHRydWUpIHsKICAgIHNhdmVCdWxrKGtleSwgdmFsdWUpOwogICAgbWFwcGluZ0RldGFpbCh4ZXBnKTsKICAgIHJldHVybgogIH0KICAKfQoKZnVuY3Rpb24gc2F2ZUNoYW5uZWxOYW1lKHhlcGcpIHsKICBpZiAoYnVsayA9PSBmYWxzZSkgewogICAgdmFyIHRoaXNDaGFubmVsID0geEVQR1siZXBnTWFwcGluZyJdW3hlcGddOwogICAgdGhpc0NoYW5uZWxbIngtbmFtZSJdID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIngtbmFtZSIpLmxhc3RDaGlsZC52YWx1ZTsKICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHhlcGcpLmNoaWxkTm9kZXNbM10ubGFzdENoaWxkLmlubmVySFRNTCA9IHRoaXNDaGFubmVsWyJ4LW5hbWUiXTsKICAgIG1hcHBpbmdEZXRhaWwoeGVwZyk7CiAgICBzZWFyY2hJbk1hcHBpbmcoKTsKICB9CiAgCn0KCmZ1bmN0aW9uIHNhdmVDaGFubmVsTmFtZVVwZGF0ZSh4ZXBnKSB7CiAgdmFyIGtleSAgID0gIngtdXBkYXRlLWNoYW5uZWwtbmFtZSI7CiAgdmFyIHZhbHVlID0gSlNPTi5wYXJzZShkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgieC11cGRhdGUtY2hhbm5lbC1uYW1lIikubGFzdENoaWxkLmNoZWNrZWQpOwoKICBpZiAoYnVsayA9PSBmYWxzZSkgewogICAgdmFyIHRoaXNDaGFubmVsID0geEVQR1siZXBnTWFwcGluZyJdW3hlcGddOwogICAgdGhpc0NoYW5uZWxba2V5XSA9IHZhbHVlCiAgICBtYXBwaW5nRGV0YWlsKHhlcGcpOwogICAgc2VhcmNoSW5NYXBwaW5nKCk7CiAgICByZXR1cm4KICB9CgogIGlmIChidWxrID09IHRydWUpIHsKICAgIHNhdmVCdWxrKGtleSwgdmFsdWUpOwogICAgbWFwcGluZ0RldGFpbCh4ZXBnKTsKICAgIHJldHVybgogIH0KCn0KCmZ1bmN0aW9uIHNhdmVDaGFubmVsU3RhdHVzKHhlcGcpIHsKICB2YXIgdGhpc0NoYW5uZWwgPSB4RVBHWyJlcGdNYXBwaW5nIl1beGVwZ107CiAgdmFyIHhYbWx0dkZpbGUgPSB0aGlzQ2hhbm5lbFsieC14bWx0di1maWxlIl07CgogIHZhciBrZXkgICA9ICJ4LWFjdGl2ZSI7CiAgdmFyIHZhbHVlID0gSlNPTi5wYXJzZShkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgieC1hY3RpdmUiKS5sYXN0Q2hpbGQuY2hlY2tlZCk7CgogIGlmICh4RVBHWyJ4bWx0dk1hcCJdLmhhc093blByb3BlcnR5KHhYbWx0dkZpbGUpID09IHRydWUpIHsKICAgIGlmICh0aGlzQ2hhbm5lbFsieC1tYXBwaW5nIl0gIT0gIi0iICYmIHRoaXNDaGFubmVsWyJ4LW1hcHBpbmciXSAhPSB1bmRlZmluZWQpIHsKICAgICAgdGhpc0NoYW5uZWxbIngtYWN0aXZlIl0gPSAhdGhpc0NoYW5uZWxbIngtYWN0aXZlIl07CiAgICAgIHZhciB0ciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHhlcGcpOwogICAgICBzd2l0Y2godGhpc0NoYW5uZWxbIngtYWN0aXZlIl0pIHsKICAgICAgICBjYXNlIHRydWU6IHRyLmNsYXNzTmFtZSA9ICJhY3RpdmVFUEciOyBicmVhazsKICAgICAgICBjYXNlIGZhbHNlOiB0ci5jbGFzc05hbWUgPSAibm90QWN0aXZlRVBHIjsgYnJlYWs7CiAgICAgIH0KICAgICAgCiAgICB9IGVsc2UgewogICAgICB2YXIgZXJyID0gIlhNTFRWIENoYW5uZWwgaXMgbm90IHNlbGVjdGVkIgogICAgICBhbGVydChlcnIpCiAgICAgIHZhbHVlID0gZmFsc2UKICAgIH0KCiAgfSBlbHNlIHsKICAgIGlmICh2YWx1ZSA9PSB0cnVlKSB7CiAgICAgIHZhciBlcnIgPSAiWE1MVFYgRmlsZSBpcyBub3Qgc2VsZWN0ZSIKICAgICAgYWxlcnQoZXJyKQogICAgICB2YWx1ZSA9IGZhbHNlCiAgICB9CiAgfQoKICAKCiAgaWYgKGJ1bGsgPT0gZmFsc2UpIHsKICAgIHZhciB0aGlzQ2hhbm5lbCA9IHhFUEdbImVwZ01hcHBpbmciXVt4ZXBnXTsKICAgIHRoaXNDaGFubmVsW2tleV0gPSB2YWx1ZQogICAgbWFwcGluZ0RldGFpbCh4ZXBnKTsKICAgIHNlYXJjaEluTWFwcGluZygpOwoKICAgIHZhciB0ciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHhlcGcpOwogICAgc3dpdGNoKHRoaXNDaGFubmVsWyJ4LWFjdGl2ZSJdKSB7CiAgICAgIGNhc2UgdHJ1ZTogdHIuY2xhc3NOYW1lID0gImFjdGl2ZUVQRyI7IGJyZWFrOwogICAgICBjYXNlIGZhbHNlOiB0ci5jbGFzc05hbWUgPSAibm90QWN0aXZlRVBHIjsgYnJlYWs7CiAgICB9CgogICAgcmV0dXJuCiAgfQoKICBpZiAoYnVsayA9PSB0cnVlKSB7CiAgICBzYXZlQnVsayhrZXksIHZhbHVlKTsKICAgIG1hcHBpbmdEZXRhaWwoeGVwZyk7CiAgICByZXR1cm4KICB9Cgp9CgpmdW5jdGlvbiBzYXZlR3JvdXBUaXRsZSh4ZXBnKSB7CiAgdmFyIGtleSAgID0gIngtZ3JvdXAtdGl0bGUiOwogIHZhciB2YWx1ZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ4LWdyb3VwLXRpdGxlIikubGFzdENoaWxkLnZhbHVlOwoKICBpZiAoYnVsayA9PSBmYWxzZSkgewogICAgdmFyIHRoaXNDaGFubmVsID0geEVQR1siZXBnTWFwcGluZyJdW3hlcGddOwogICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoeGVwZykuY2hpbGROb2Rlc1s1XS5sYXN0Q2hpbGQuaW5uZXJIVE1MID0gdmFsdWU7CiAgICB0aGlzQ2hhbm5lbFtrZXldID0gdmFsdWU7CiAgICBtYXBwaW5nRGV0YWlsKHhlcGcpOwogICAgc2VhcmNoSW5NYXBwaW5nKCk7CiAgfQoKICBpZiAoYnVsayA9PSB0cnVlKSB7CiAgICBzYXZlQnVsayhrZXksIHZhbHVlKTsKICAgIG1hcHBpbmdEZXRhaWwoeGVwZyk7CiAgICByZXR1cm4KICB9Cgp9CgpmdW5jdGlvbiBzYXZlQ2F0ZWdvcnkoeGVwZykgewogIHZhciBrZXkgICA9ICJ4LWNhdGVnb3J5IjsKICB2YXIgdmFsdWUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgieC1jYXRlZ29yeSIpLmxhc3RDaGlsZC52YWx1ZTsKCiAgaWYgKGJ1bGsgPT0gZmFsc2UpIHsKICAgIHZhciB0aGlzQ2hhbm5lbCA9IHhFUEdbImVwZ01hcHBpbmciXVt4ZXBnXTsKICAgIHRoaXNDaGFubmVsW2tleV0gPSB2YWx1ZQogICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoeGVwZykuY2hpbGROb2Rlc1szXS5sYXN0Q2hpbGQuY2xhc3NOYW1lID0gdmFsdWUKICAgIG1hcHBpbmdEZXRhaWwoeGVwZyk7CiAgICBzZWFyY2hJbk1hcHBpbmcoKTsKICB9CgogIGlmIChidWxrID09IHRydWUpIHsKICAgIHNhdmVCdWxrKGtleSwgdmFsdWUpOwogICAgbWFwcGluZ0RldGFpbCh4ZXBnKTsKICAgIHJldHVybgogIH0KCn0KCmZ1bmN0aW9uIGFycmFuZ2VUYWJsZShlbG0pIHsKICB2YXIgdHIgPSBlbG0ucGFyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50OwogIHZhciBuZXdQb3NpdGlvbiA9IGVsbS52YWx1ZTsKICB2YXIgeF9jaGFubmVsSUQgPSB0ci5pZDsKCiAgc3dpdGNoKGlzTmFOKG5ld1Bvc2l0aW9uKSkgewogICAgY2FzZSB0cnVlOiAKICAgICAgYWxlcnQoIkNoLiBOby4gbXVzdCBiZSBhIG51bWJlciIpOwogICAgICBtYXBwaW5nRXJyb3IgPSB0cnVlOwogICAgICBicmVhazsKICB9CgoKICAvL3ZhciBpdGVtID0geEVQR1siZXBnTWFwcGluZyJdW2lkXTsKICB2YXIga2V5cyA9IGdldE9iaktleXMoeEVQR1siZXBnTWFwcGluZyJdKQogIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewogICAgdmFyIGl0ZW0gPSB4RVBHWyJlcGdNYXBwaW5nIl1ba2V5c1tpXV07CiAgICBpZiAoaXRlbVsieC1lcGciXSA9PSB4X2NoYW5uZWxJRCkgewoKICAgICAgLy8gQ2hlY2sgaWYgcG9zaXRpb24gZXhpc3QKICAgICAgdmFyIG9sZFBvc2l0aW9uID0gaXRlbVsieC1jaGFubmVsSUQiXTsKCiAgICAgIGlmIChvbGRQb3NpdGlvbiAhPSBuZXdQb3NpdGlvbikgewoKICAgICAgICBjb25zb2xlLmxvZyhuZXdQb3NpdGlvbiwgbmV3UG9zaXRpb24ubGVuZ3RoKTsKICAgICAgICBpZiAobmV3UG9zaXRpb24ubGVuZ3RoID09IDApIHsKICAgICAgICAgIG1hcHBpbmdFcnJvciA9IHRydWUKICAgICAgICAgIG5ld1Bvc2l0aW9uID0gb2xkUG9zaXRpb247CiAgICAgICAgICAKICAgICAgICB9CgogICAgICAgIGlmIChtYXBwaW5nRXJyb3IgPT0gdHJ1ZSkgewogICAgICAgICAgZWxtLnZhbHVlID0gb2xkUG9zaXRpb247CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBmb3IgKHZhciBqID0ga2V5cy5sZW5ndGggLSAxOyBqID49IDA7IGotLSkgewogICAgICAgICAgdmFyIGNoYW5uZWwgPSB4RVBHWyJlcGdNYXBwaW5nIl1ba2V5c1tqXV07CiAgICAgICAgICBpZiAoa2V5c1tqXSAhPSB4X2NoYW5uZWxJRCkgewogICAgICAgICAgICBpZiAobmV3UG9zaXRpb24gPT0gY2hhbm5lbFsieC1jaGFubmVsSUQiXSkgeyAvLyBJZiBwb3NpdGlvbiBleGlzdCwgc2V0IG5leHQgZnJlZSBwb3NpdGlvbi4KICAgICAgICAgICAgICBuZXdQb3NpdGlvbisrOwogICAgICAgICAgICAgIGVsbS52YWx1ZSA9IG5ld1Bvc2l0aW9uOwogICAgICAgICAgICAgIGFycmFuZ2VUYWJsZShlbG0pOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAvKgogICAgICAgICAgICAgIHZhciBuZXdFcnJvciA9IG5ldyBPYmplY3QoKTsKICAgICAgICAgICAgICBuZXdFcnJvclsiZXJyIl0gPSAiRHVwbGljYXRlIElEIjsKICAgICAgICAgICAgICBjaGVja0VycihuZXdFcnJvcik7CiAgICAgICAgICAgICAgc29ydFRhYmxlKCk7CiAgICAgICAgICAgICAgbWFwcGluZ0Vycm9yID0gdHJ1ZTsKICAgICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh4X2NoYW5uZWxJRCkuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIklOUFVUIilbMF0uZm9jdXMoKTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgKi8KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgIH0KCiAgICAgIC8vY29uc29sZS5sb2cob2xkUG9zaXRpb24sIG5ld1Bvc2l0aW9uKTsKICAgICAgaWYgKGtleXNbaV0gPT0geF9jaGFubmVsSUQgJiYgb2xkUG9zaXRpb24gIT0gbmV3UG9zaXRpb24pIHsgIAogICAgICAgIGl0ZW1bIngtY2hhbm5lbElEIl0gPSBuZXdQb3NpdGlvbjsKICAgICAgfSAKCiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJsb2dJbmZvIikuY2xhc3NOYW1lID0gIm5vdFZpc2libGUiOwogICAgICBpZiAoY29sdW1uVG9Tb3J0ID09IDEpIHsKICAgICAgICBzb3J0VGFibGUoY29sdW1uVG9Tb3J0KTsKICAgICAgfQogICAgICBtYXBwaW5nRXJyb3IgPSBmYWxzZTsKCiAgICB9CiAgfQp9CgpmdW5jdGlvbiBjaGFuZ2VYbWx0dkZpbGUoeGVwZywgZWxtKSB7CgogIHZhciB0aGlzQ2hhbm5lbCA9IHhFUEdbImVwZ01hcHBpbmciXVt4ZXBnXTsKICAKICB2YXIgeFhtbHR2RmlsZSAgICA9IGVsbS52YWx1ZTsKICB2YXIgY2hhbm5lbElEICAgICA9IHRoaXNDaGFubmVsWyJ0dmctaWQiXTsKICB0aGlzQ2hhbm5lbFsieC14bWx0di1maWxlIl0gPSB4WG1sdHZGaWxlOwoKICBpZiAoYnVsayA9PSBmYWxzZSkgewoKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKXsgCgogICAgICB2YXIgeE1hcHBpbmcgPSAiLSIKCiAgICAgIC8vIEF1dG9tYXAKICAgICAgaWYgKHhYbWx0dkZpbGUgIT0gIi0iKSB7CiAgICAgICAgaWYgKHhFUEdbInhtbHR2TWFwIl1beFhtbHR2RmlsZV0uaGFzT3duUHJvcGVydHkoY2hhbm5lbElEKSA9PSB0cnVlKSB7CiAgICAgICAgICB0aGlzQ2hhbm5lbFsieC1tYXBwaW5nIl0gPSBjaGFubmVsSUQ7CiAgICAgICAgICB4TWFwcGluZyA9IGNoYW5uZWxJRAogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzQ2hhbm5lbFsieC1tYXBwaW5nIl0gPSB4TWFwcGluZwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzQ2hhbm5lbFsieC1tYXBwaW5nIl0gPSB4TWFwcGluZwoKICAgICAgfQogICAgICAKICAgICAgdmFyIHRyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoeGVwZyk7CgogICAgICBpZiAoeE1hcHBpbmcgPT0gIi0iKSB7CiAgICAgICAgdGhpc0NoYW5uZWxbIngtYWN0aXZlIl0gPSBmYWxzZTsKICAgICAgICB0ci5jbGFzc05hbWUgPSAibm90QWN0aXZlRVBHIgogICAgICB9IGVsc2UgewogICAgICAgIHRoaXNDaGFubmVsWyJ4LWFjdGl2ZSJdICA9IHRydWU7CiAgICAgICAgdHIuY2xhc3NOYW1lID0gImFjdGl2ZUVQRyIKICAgICAgfQoKICAgICAgLy8gU2hvdyBkYXRhIGluIHRhYmxlCiAgICAgIHZhciB0ZCA9IHRyLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJURCIpOwogICAgICB2YXIgZGF0YUZpbGUgPSB0ZFt0ZC5sZW5ndGggLSAyXS5sYXN0Q2hpbGQ7CiAgICAgIHN3aXRjaCh4WG1sdHZGaWxlKSB7CiAgICAgICAgY2FzZSAiLSI6ICAgICAgICAgICBkYXRhRmlsZS5pbm5lckhUTUwgPSB4WG1sdHZGaWxlOyBicmVhazsKICAgICAgICBjYXNlICJ4VGVWZSBEdW1teSI6IGRhdGFGaWxlLmlubmVySFRNTCA9IHhYbWx0dkZpbGU7IGJyZWFrOwogICAgICAgIGRlZmF1bHQ6ICAgICAgICAgICAgZGF0YUZpbGUuaW5uZXJIVE1MID0gZ2V0VmFsdWVGcm9tUHJvdmlkZXJGaWxlKHhYbWx0dkZpbGUsICJ4bWx0diIsICJuYW1lIik7IGJyZWFrOwogICAgICB9CgogICAgICAvL3hYbWx0dkZpbGUucmVwbGFjZSgvXi4qW1xcXC9dLywgJycpOwoKICAgICAgdmFyIGRhdGFYbWx0dklEID0gdGRbdGQubGVuZ3RoIC0gMV0ubGFzdENoaWxkOwogICAgICBkYXRhWG1sdHZJRC5pbm5lckhUTUwgPSB4TWFwcGluZzsKICAgICAgCiAgICAgIG1hcHBpbmdEZXRhaWwoeGVwZyk7CgogICAgfSwgMTApOwogIH0KCiAgaWYgKGJ1bGsgPT0gdHJ1ZSkgewogICAgdmFyIGtleSA9ICJ4LXhtbHR2LWZpbGUiCiAgICB2YXIgdmFsdWUgPSB4WG1sdHZGaWxlCiAgICBzYXZlQnVsayhrZXksIHZhbHVlKTsKCiAgICB2YXIga2V5ID0gIngtbWFwcGluZyIKICAgIHZhciB2YWx1ZSA9ICItIgogICAgc2F2ZUJ1bGsoa2V5LCB2YWx1ZSk7CiAgICBtYXBwaW5nRGV0YWlsKHhlcGcpOwogICAgcmV0dXJuCiAgfQoKICByZXR1cm4KfQoKZnVuY3Rpb24gbWFwcGluZ0NoYW5uZWwoeGVwZywgZWxtKSB7CiAgdmFyIHRoaXNDaGFubmVsID0geEVQR1siZXBnTWFwcGluZyJdW3hlcGddOwogIC8vdmFyIHhNYXBwaW5nICAgICAgPSBlbG0udmFsdWU7CiAgdmFyIHhNYXBwaW5nICAgICAgPSBlbG0ub3B0aW9uc1tlbG0uc2VsZWN0ZWRJbmRleF0udmFsdWUKICAKICBpZiAoYnVsayA9PSBmYWxzZSkgewogICAgCiAgICB0aGlzQ2hhbm5lbFsieC1tYXBwaW5nIl0gPSB4TWFwcGluZzsKCiAgICB2YXIgdHIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh4ZXBnKTsKCiAgICBpZiAoeE1hcHBpbmcgPT0gIi0iKSB7CiAgICAgIHRoaXNDaGFubmVsWyJ4LWFjdGl2ZSJdID0gZmFsc2U7CiAgICAgIHRyLmNsYXNzTmFtZSA9ICJub3RBY3RpdmVFUEciCiAgICB9IGVsc2UgewogICAgICB0aGlzQ2hhbm5lbFsieC1hY3RpdmUiXSAgPSB0cnVlOwogICAgICB0ci5jbGFzc05hbWUgPSAiYWN0aXZlRVBHIgogICAgfQoKICAgIC8vIFNob3cgZGF0YSBpbiB0YWJsZQogICAgdmFyIHRkID0gdHIuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlREIik7CiAgICB2YXIgZGF0YVhtbHR2SUQgPSB0ZFt0ZC5sZW5ndGggLSAxXS5sYXN0Q2hpbGQ7CiAgICBkYXRhWG1sdHZJRC5pbm5lckhUTUwgPSB4TWFwcGluZzsKICAgIC8vY29uc29sZS5sb2codGRbdGQubGVuZ3RoIC0gMV0pOwogICAgLy9jb25zb2xlLmxvZyh4TWFwcGluZywgZWxtKTsKCiAgICBjcmVhdGVTZWFyY2hPYmooKTsKICAgIHNlYXJjaEluTWFwcGluZygpOwogICAgdXBkYXRlQ2hhbm5lbExvZ28oeGVwZykKICAgIG1hcHBpbmdEZXRhaWwoeGVwZyk7CiAgICByZXR1cm4KICB9CgogIGlmIChidWxrID09IHRydWUpIHsKCiAgICB2YXIga2V5ID0gIngtbWFwcGluZyIKICAgIHZhciB2YWx1ZSA9IHhNYXBwaW5nCiAgICBzYXZlQnVsayhrZXksIHZhbHVlKTsKCiAgICBtYXBwaW5nRGV0YWlsKHhlcGcpOwogICAgcmV0dXJuCiAgfQoKICByZXR1cm4KfQoKCmZ1bmN0aW9uIGNyZWF0ZU5ld1REKG5ld0l0ZW0sIGVsbSkgewogIHZhciBuZXdURCA9IG5ldyBPYmplY3QoKTsKICBuZXdURFsiX2VsZW1lbnQiXSA9ICJURCI7CiAgCiAgZWxtLmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3VEQpKTsKICB2YXIgdGQgPSBlbG0ubGFzdENoaWxkOyAKICAKICBzd2l0Y2gobmV3SXRlbVsiX2VsZW1lbnQiXSkgewogICAgY2FzZSAiU0VMRUNUIjoKICAgICAgdGQuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdJdGVtKSk7CiAgICAgIHZhciB0ZCA9IGVsbS5sYXN0Q2hpbGQubGFzdENoaWxkOyAKICAgICAgdmFyIHZhbHVlcyA9IG5ld0l0ZW1bIl9vcHRpb25WYWx1ZXMiXTsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2YWx1ZXMubGVuZ3RoOyBpKyspIHsKICAgICAgICAvL2NvbnNvbGUubG9nKGl0ZW0pOwogICAgICAgIHZhciBuZXdFbnRyeSA9IG5ldyBPYmplY3Q7CiAgICAgICAgbmV3RW50cnlbIl9lbGVtZW50Il0gID0gIk9QVElPTiI7CiAgICAgICAgbmV3RW50cnlbIl90ZXh0Il0gICAgID0gdmFsdWVzW2ldOwogICAgICAgIG5ld0VudHJ5WyJ2YWx1ZSJdICAgICA9IHZhbHVlc1tpXTsKICAgICAgICB0ZC5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0VudHJ5KSk7CiAgICAgIH0KICAgICAgdGQudmFsdWUgPSBuZXdJdGVtWyJ2YWx1ZSJdOwoKICAgICAgYnJlYWs7CiAgICAKICAgIGRlZmF1bHQ6IAogICAgICAKICAgICAgdGQuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdJdGVtKSk7CiAgICAgIGJyZWFrOwogIH0KICAKfQoKZnVuY3Rpb24gc2F2ZVhFUEcoKSB7CiAgaWYgKG1hcHBpbmdFcnJvciA9PSB0cnVlKSB7CiAgICBhbGVydCgiRGF0YSBjb3VsZCBub3QgYmUgc2F2ZWQsIGVycm9ycyBpbiB0aGUgWEVQRyBkYXRhLiIpOwogICAgcmV0dXJuOwogIH0KICBzaG93TG9hZGluZ1NjcmVlbih0cnVlKTsKCiAgdmFyIGRhdGEgPSBuZXcgT2JqZWN0KCk7CiAgZGF0YVsiZXBnTWFwcGluZyJdID0geEVQR1siZXBnTWFwcGluZyJdOwogIGRhdGFbImNtZCJdID0gInNhdmVFcGdNYXBwaW5nIjsKICAvL2NvbnNvbGUubG9nKGRhdGEpOwogIHhUZVZlKGRhdGEpOwp9CgpmdW5jdGlvbiBidWxrRWRpdCgpIHsKICBidWxrID0gIWJ1bGs7CiAgdmFyIGNsYXNzTmFtZTsKCiAgdmFyIGVsbSA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoImJ1bGsiKTsKCiAgc3dpdGNoKGJ1bGspIHsKICAgIGNhc2UgdHJ1ZTogCiAgICAgIGNsYXNzTmFtZSA9ICJidWxrIHNob3dCdWxrIjsKICAgICAgYnJlYWs7CgogICAgY2FzZSBmYWxzZTogCiAgICAgIGNsYXNzTmFtZSA9ICJidWxrIGhpZGVCdWxrIjsKICAgICAgYnVsa0VkaXRBbGwgPSBmYWxzZTsKICAgICAgYnJlYWs7CiAgfQoKICBmb3IgKHZhciBpID0gMDsgaSA8IGVsbS5sZW5ndGg7IGkrKykgewogICAgZWxtW2ldLmNsYXNzTmFtZSA9IGNsYXNzTmFtZTsKICAgIGVsbVtpXS5jaGVja2VkID0gZmFsc2U7CiAgfQoKfQoKZnVuY3Rpb24gYnVsa0VkaXRBbGxDaGFubmVscygpIHsKCiAgdmFyIGFsbFRSID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImlkX21hcHBpbmciKS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiVFIiKTsKCiAgZm9yICh2YXIgaSA9IDE7IGkgPCBhbGxUUi5sZW5ndGg7IGkrKykgewogICAgaWYgKGFsbFRSW2ldLnN0eWxlLmRpc3BsYXkgIT0gIm5vbmUiKSB7CiAgICAgIHN3aXRjaChidWxrRWRpdEFsbCkgewogICAgICAgIGNhc2UgZmFsc2U6IGFsbFRSW2ldLmZpcnN0Q2hpbGQuZmlyc3RDaGlsZC5jaGVja2VkID0gdHJ1ZTsgYnJlYWs7CiAgICAgICAgY2FzZSB0cnVlOiBhbGxUUltpXS5maXJzdENoaWxkLmZpcnN0Q2hpbGQuY2hlY2tlZCA9IGZhbHNlOyBicmVhazsgCiAgICAgIH0KCiAgICB9CiAgICAKICB9CgogIGJ1bGtFZGl0QWxsID0gIWJ1bGtFZGl0QWxsOwp9CgpmdW5jdGlvbiBzb3J0VGFibGUoY29sdW1tKSB7CiAgLy9jb25zb2xlLmxvZyhjb2x1bW0pOwogIGlmIChjb2x1bW0gPT0gY29sdW1uVG9Tb3J0KSB7CiAgICAvL3JldHVybjsKICB9CgogIHZhciB0YWJsZSAgICAgICA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJpZF9tYXBwaW5nIik7CiAgdmFyIHRhYmxlSGVhZCAgID0gdGFibGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlRSIilbMF07CiAgdmFyIHRhYmxlSXRlbXMgID0gdGFibGVIZWFkLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJURCIpOwogIAogIHZhciBzb3J0T2JqID0gbmV3IE9iamVjdCgpOwogIHZhciB4LCB4VmFsdWU7CiAgdmFyIHRhYmxlSGVhZGVyCiAgdmFyIHNvcnRCeVN0cmluZyA9IGZhbHNlCgogIGlmIChjb2x1bW0gPiAwICYmIGNvbHVtblRvU29ydCA+IDApICB7CiAgICB0YWJsZUl0ZW1zW2NvbHVtblRvU29ydF0uY2xhc3NOYW1lID0gInBvaW50ZXIiOwogICAgdGFibGVJdGVtc1tjb2x1bW1dLmNsYXNzTmFtZSA9ICJzb3J0VGhpcyI7CiAgfQoKICBjb2x1bW5Ub1NvcnQgPSBjb2x1bW07CgogIHZhciByb3dzID0gdGFibGUucm93czsKCiAgaWYgKHJvd3NbMV0gIT0gdW5kZWZpbmVkKSB7CiAgICB0YWJsZUhlYWRlciA9IHJvd3NbMF0KCiAgICB4ID0gcm93c1sxXS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiVEQiKVtjb2x1bW1dOwogICAgCiAgICBmb3IgKGkgPSAxOyBpIDwgcm93cy5sZW5ndGg7IGkrKykgewoKICAgICAgeCA9IHJvd3NbaV0uZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlREIilbY29sdW1tXTsKCiAgICAgIHN3aXRjaCh4LmNoaWxkTm9kZXNbMF0udGFnTmFtZS50b0xvd2VyQ2FzZSgpKSB7CiAgICAgICAgY2FzZSAiaW5wdXQiOgogICAgICAgICAgeFZhbHVlID0geC5nZXRFbGVtZW50c0J5VGFnTmFtZSgiSU5QVVQiKVswXS52YWx1ZS50b0xvd2VyQ2FzZSgpOwogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgInAiOgogICAgICAgICAgeFZhbHVlID0geC5nZXRFbGVtZW50c0J5VGFnTmFtZSgiUCIpWzBdLmlubmVyVGV4dC50b0xvd2VyQ2FzZSgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgCiAgICAgICAgZGVmYXVsdDogY29uc29sZS5sb2coeC5jaGlsZE5vZGVzWzBdLnRhZ05hbWUpOwogICAgICB9CgogICAgICBpZiAoeFZhbHVlID09ICIiIHx8IHhWYWx1ZSA9PSBOYU4pIHsKICAgICAgICB4VmFsdWUgPSBpCiAgICAgICAgc29ydE9ialtpXSA9IHJvd3NbaV07CiAgICAgIAogICAgICB9IGVsc2UgewoKICAgICAgICBzd2l0Y2goaXNOYU4oeFZhbHVlKSkgewogICAgICAgICAgY2FzZSBmYWxzZTogCgogICAgICAgICAgICB4VmFsdWUgPSBwYXJzZUZsb2F0KHhWYWx1ZSk7CiAgICAgICAgICAgIHNvcnRPYmpbeFZhbHVlXSA9IHJvd3NbaV0KICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgY2FzZSB0cnVlOgoKICAgICAgICAgICAgc29ydEJ5U3RyaW5nID0gdHJ1ZQogICAgICAgICAgICBzb3J0T2JqW3hWYWx1ZS50b0xvd2VyQ2FzZSgpICsgaV0gPSByb3dzW2ldCiAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICB9CgogICAgICB9CiAgICAKICAgIH0KCiAgICB3aGlsZSAodGFibGUuZmlyc3RDaGlsZCkgewogICAgICB0YWJsZS5yZW1vdmVDaGlsZCh0YWJsZS5maXJzdENoaWxkKTsKICAgIH0KICAgIAogICAgdmFyIHNvcnRWYWx1ZXMgPSBnZXRPYmpLZXlzKHNvcnRPYmopCiAgICBpZiAoc29ydEJ5U3RyaW5nID09IHRydWUpIHsKICAgICAgc29ydFZhbHVlcy5zb3J0KCkKICAgIH0gZWxzZSB7CiAgICAgIGZ1bmN0aW9uIHNvcnRGbG9hdChhLCBiKSB7IAogICAgICAgIHJldHVybiBhIC0gYjsgCiAgICAgIH0KICAgICAgc29ydFZhbHVlcy5zb3J0KHNvcnRGbG9hdCk7CiAgICB9CgogICAgdGFibGUuYXBwZW5kQ2hpbGQodGFibGVIZWFkZXIpCiAgICAKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc29ydFZhbHVlcy5sZW5ndGg7IGkrKykgewogICAgIAogICAgICB0YWJsZS5hcHBlbmRDaGlsZChzb3J0T2JqW3NvcnRWYWx1ZXNbaV1dKQoKICAgIH0KICAgIAogIH0KCn0KCgpmdW5jdGlvbiBzb3J0VGFibGVfb2xkKGNvbHVtbSkgewogIHNob3dMb2FkaW5nU2NyZWVuKHRydWUpOwogIAogIHNldFRpbWVvdXQoZnVuY3Rpb24oKXsgCgogICAgdmFyIHRhYmxlLCByb3dzLCBzd2l0Y2hpbmcsIGksIHgsIHksIHNob3VsZFN3aXRjaDsKICAgIHRhYmxlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImlkX21hcHBpbmciKTsKCiAgICB2YXIgdGFibGVIZWFkID0gdGFibGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlRSIilbMF07CiAgICB2YXIgdGFibGVJdGVtcyA9IHRhYmxlSGVhZC5nZXRFbGVtZW50c0J5VGFnTmFtZSgiVEQiKTsKCiAgICBpZiAoY29sdW1tID4gMCkgIHsKICAgICAgdGFibGVJdGVtc1tjb2x1bW5Ub1NvcnRdLmNsYXNzTmFtZSA9ICJwb2ludGVyIjsKICAgICAgdGFibGVJdGVtc1tjb2x1bW1dLmNsYXNzTmFtZSA9ICJzb3J0VGhpcyI7CiAgICB9CiAgICAKICAgIGNvbHVtblRvU29ydCA9IGNvbHVtbTsKCiAgICAvKgogICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0YWJsZUl0ZW1zLmxlbmd0aDsgaSsrKSB7CiAgICAgIGlmICh0YWJsZUl0ZW1zW2ldLmNsYXNzTmFtZSAhPSB1bmRlZmluZWQpIHsKICAgICAgICB0YWJsZUl0ZW1zW2ldLmNsYXNzTmFtZSA9ICJwb2ludGVyIgogICAgICB9CgogICAgfQogICAgKi8KCiAgICAKCiAgICBjb25zb2xlLmxvZyh0YWJsZUl0ZW1zKTsgCgogICAgc3dpdGNoaW5nID0gdHJ1ZTsKICAgIHdoaWxlIChzd2l0Y2hpbmcpIHsKICAgICAgc3dpdGNoaW5nID0gZmFsc2U7CiAgICAgIHJvd3MgPSB0YWJsZS5yb3dzOwogICAgICBmb3IgKGkgPSAxOyBpIDwgKHJvd3MubGVuZ3RoIC0gMSk7IGkrKykgewogICAgICAgIHNob3VsZFN3aXRjaCA9IGZhbHNlOwoKICAgICAgICB4ID0gcm93c1tpXS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiVEQiKVtjb2x1bW1dOwogICAgICAgIHkgPSByb3dzW2kgKyAxXS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiVEQiKVtjb2x1bW1dOwoKICAgICAgICBzd2l0Y2goeC5jaGlsZE5vZGVzWzBdLnRhZ05hbWUudG9Mb3dlckNhc2UoKSkgewogICAgICAgICAgY2FzZSAiaW5wdXQiOgogICAgICAgICAgICB4VmFsdWUgPSB4LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJJTlBVVCIpWzBdLnZhbHVlLnRvTG93ZXJDYXNlKCk7CiAgICAgICAgICAgIHlWYWx1ZSA9IHkuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIklOUFVUIilbMF0udmFsdWUudG9Mb3dlckNhc2UoKTsKICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgY2FzZSAicCI6CiAgICAgICAgICAgIHhWYWx1ZSA9IHguZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlAiKVswXS5pbm5lclRleHQudG9Mb3dlckNhc2UoKTsKICAgICAgICAgICAgeVZhbHVlID0geS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiUCIpWzBdLmlubmVyVGV4dC50b0xvd2VyQ2FzZSgpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIAogICAgICAgICAgZGVmYXVsdDogY29uc29sZS5sb2coeC5jaGlsZE5vZGVzWzBdLnRhZ05hbWUpOwogICAgICAgIH0KCiAgICAgICAgCiAgICAgICAgc3dpdGNoKGlzTmFOKHhWYWx1ZSkpIHsKICAgICAgICAgIGNhc2UgZmFsc2U6IHhWYWx1ZSA9IHBhcnNlRmxvYXQoeFZhbHVlKSA7IGJyZWFrOwogICAgICAgIH0KCiAgICAgICAgc3dpdGNoKGlzTmFOKHlWYWx1ZSkpIHsKICAgICAgICAgIGNhc2UgZmFsc2U6IHlWYWx1ZSA9IHBhcnNlRmxvYXQoeVZhbHVlKSA7IGJyZWFrOwogICAgICAgIH0KICAgICAgICAKCiAgICAgICAgaWYgKHhWYWx1ZSA+IHlWYWx1ZSkgewogICAgICAgICAgc2hvdWxkU3dpdGNoID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KCiAgICAgIH0KICAgICAgaWYgKHNob3VsZFN3aXRjaCkgewogICAgICAgIHJvd3NbaV0ucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUocm93c1tpICsgMV0sIHJvd3NbaV0pOwogICAgICAgIHN3aXRjaGluZyA9IHRydWU7CiAgICAgIH0KICAgIH0KICAgIGNyZWF0ZVNlYXJjaE9iaigpCiAgICAKICAgIHNob3dMb2FkaW5nU2NyZWVuKGZhbHNlKTsKICB9LCAyMCk7Cgp9CgpmdW5jdGlvbiBzaG93WEVQRygpIHsKICB2YXIgdXJsID0gbG9jYXRpb24ucHJvdG9jb2wgKyAiLy8iICsgbG9jYXRpb24uaG9zdG5hbWUgKyAiOiIgKyBsb2NhdGlvbi5wb3J0ICsgIi94bWx0di94dGV2ZS54bWwiCiAgdmFyIHdpbiA9IHdpbmRvdy5vcGVuKHVybCwgJ19ibGFuaycpOwogIHdpbi5mb2N1cygpOwp9" - webUI["html/index.html"] = "PCFkb2N0eXBlIGh0bWw+CjxodG1sPgogIDxoZWFkPgogICAgPG1ldGEgY2hhcnNldD0idXRmLTgiPgogICAgPCEtLS0KICAgIDxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MS4wIiAvPiAKICAgIC0tPgogICAgPHRpdGxlPnhUZVZlPC90aXRsZT4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL3NjcmVlbi5jc3MiIHR5cGU9InRleHQvY3NzIj4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL2Jhc2UuY3NzIiB0eXBlPSJ0ZXh0L2NzcyI+CgogICAgPHNjcmlwdCBsYW5ndWFnZT0iamF2YXNjcmlwdCIgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImpzL25ldHdvcmtfdHMuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBsYW5ndWFnZT0iamF2YXNjcmlwdCIgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImpzL21lbnVfdHMuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBsYW5ndWFnZT0iamF2YXNjcmlwdCIgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImpzL3NldHRpbmdzX3RzLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgbGFuZ3VhZ2U9ImphdmFzY3JpcHQiIHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJqcy9sb2dzX3RzLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgbGFuZ3VhZ2U9ImphdmFzY3JpcHQiIHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJqcy9iYXNlX3RzLmpzIj48L3NjcmlwdD4KCiAgPC9oZWFkPgoKICAgIDxib2R5IG9ubG9hZD0iamF2YXNjcmlwdDogUGFnZVJlYWR5KCk7Ij4KCiAgICAgIDxkaXYgaWQ9ImxvYWRpbmciIGNsYXNzPSJub25lIj4KICAgICAgICA8ZGl2IGNsYXNzPSJsb2FkZXIiPjwvZGl2PgogICAgICA8L2Rpdj4KCiAgICAgIDxkaXYgaWQ9InBvcHVwIiBjbGFzcz0ibm9uZSI+CiAgICAgICAgPGRpdiBpZD0icG9wdXAtY3VzdG9tIj48L2Rpdj4KICAgICAgPC9kaXY+CgogICAgICA8ZGl2IGlkPSJsYXlvdXQiPgoKICAgICAgICA8IS0tCiAgICAgICAgPGRpdiBpZD0ibm90aWZpY2F0aW9uIj4KICAgICAgICAgIDxkaXYgY2xhc3M9ImVsZW1lbnQiPgogICAgICAgICAgICA8aDU+WEVQRzwvaDU+CiAgICAgICAgICAgIDxwcmU+MTEuMDUuMjAxOSAtIDIwOjIxPC9wcmU+CiAgICAgICAgICAgIDxocj4KICAgICAgICAgICAgPHA+SGFsbG8gZGFzIGlzdCBlaW4gVGVzdC4gVW5kIG5vY2ggbWVociBUZXh0LjwvcD4KICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgogICAgICAtLT4KCiAgICAgICAgPGRpdiBpZD0ibWVudS13cmFwcGVyIiBjbGFzcz0ibGF5b3V0LWxlZnQiPgogICAgICAgICAgPGRpdiBpZD0gImJyYW5jaCI+PC9kaXY+CiAgICAgICAgICA8ZGl2IGlkPSJsb2dvIj48L2Rpdj4KICAgICAgICAgIDxuYXYgaWQ9Im1haW4tbWVudSI+PC9uYXY+CiAgICAgICAgPC9kaXY+CgogICAgICAgIDxkaXYgY2xhc3M9ImxheW91dC1yaWdodCI+CgogICAgICAgICAgPHRhYmxlIGlkPSJjbGllbnRJbmZvIiBjbGFzcz0iIj4KCiAgICAgICAgICAgIDx0cj4KICAgICAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij54VGVWZTo8L3RkPgogICAgICAgICAgICAgIDx0ZCBpZD0idmVyc2lvbiIgY2xhc3M9InRkVmFsIj4mbmJzcDs8L3RkPgogICAgICAgICAgICAgIDx0ZCBjbGFzcz0idGRLZXkiPk9TOjwvdGQ+CiAgICAgICAgICAgICAgPHRkIGlkPSJvcyIgY2xhc3M9InRkVmFsIj4mbmJzcDs8L3RkPgogICAgICAgICAgICAgIDx0ZCBjbGFzcz0idGRLZXkgcGhvbmUiPkRWUiBJUDo8L3RkPgogICAgICAgICAgICAgIDx0ZCBpZD0iRFZSIiBjbGFzcz0idGRWYWwgcGhvbmUiPiZuYnNwOzwvdGQ+CiAgICAgICAgICAgIDwvdHI+CgogICAgICAgICAgICA8dHI+CiAgICAgICAgICAgICAgPHRkIGNsYXNzPSJ0ZEtleSI+VVVJRDo8L3RkPgogICAgICAgICAgICAgIDx0ZCBpZD0idXVpZCIgY2xhc3M9InRkVmFsIj4mbmJzcDs8L3RkPgogICAgICAgICAgICAgIDx0ZCBjbGFzcz0idGRLZXkiPkFyY2g6PC90ZD4KICAgICAgICAgICAgICA8dGQgaWQ9ImFyY2giIGNsYXNzPSJ0ZFZhbCI+Jm5ic3A7PC90ZD4KICAgICAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5IHBob25lIj5NM1UgVVJMOjwvdGQ+CiAgICAgICAgICAgICAgPHRkIGlkPSJtM3UtdXJsIiBjbGFzcz0idGRWYWwgcGhvbmUiPiZuYnNwOzwvdGQ+CiAgICAgICAgICAgIDwvdHI+CgogICAgICAgICAgICA8dHI+CiAgICAgICAgICAgICAgPHRkIGNsYXNzPSJ0ZEtleSI+QXZhaWxhYmxlIFN0cmVhbXM6PC90ZD4KICAgICAgICAgICAgICA8dGQgaWQ9InN0cmVhbXMiIGNsYXNzPSJ0ZFZhbCI+Jm5ic3A7PC90ZD4KICAgICAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij5FUEcgU291cmNlOjwvdGQ+CiAgICAgICAgICAgICAgPHRkIGlkPSJlcGdTb3VyY2UiIGNsYXNzPSJ0ZFZhbCI+Jm5ic3A7PC90ZD4KICAgICAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5IHBob25lIj5YRVBHIFVSTDo8L3RkPgogICAgICAgICAgICAgIDx0ZCBpZD0ieGVwZy11cmwiIGNsYXNzPSJ0ZFZhbCBwaG9uZSI+Jm5ic3A7PC90ZD4KICAgICAgICAgICAgPC90cj4KCiAgICAgICAgICAgIDx0cj4KICAgICAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij5YRVBHIENoYW5uZWxzOjwvdGQ+CiAgICAgICAgICAgICAgPHRkIGlkPSJ4ZXBnIiBjbGFzcz0idGRWYWwiPiZuYnNwOzwvdGQ+CiAgICAgICAgICAgICAgPHRkIGNsYXNzPSJ0ZEtleSI+RXJyb3JzOjwvdGQ+CiAgICAgICAgICAgICAgPHRkIGlkPSJlcnJvcnMiIGNsYXNzPSJ0ZFZhbCI+Jm5ic3A7PC90ZD4KICAgICAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij5XYXJuaW5nczo8L3RkPgogICAgICAgICAgICAgIDx0ZCBpZD0id2FybmluZ3MiIGNsYXNzPSJ0ZFZhbCI+Jm5ic3A7PC90ZD4KICAgICAgICAgICAgPC90cj4KCiAgICAgICAgICA8L3RhYmxlPgogICAgICAgICAKICAgICAgICAgIDxkaXYgaWQ9Im15U3RyZWFtc0JveCIgY2xhc3M9Im5vdFZpc2libGUiPgoKICAgICAgICAgICAgPGRpdiBpZD0iYWxsU3RyZWFtcyI+CiAgICAgICAgICAgICAgPHRhYmxlIGlkPSJhY3RpdmVTdHJlYW1zIj48L3RhYmxlPgogICAgICAgICAgICAgIDx0YWJsZSBpZD0iaW5hY3RpdmVTdHJlYW1zIj48L3RhYmxlPgogICAgICAgICAgICA8L2Rpdj4KCiAgICAgICAgICA8L2Rpdj4KICAgICAgICAgIAogICAgICAgICAgPGRpdiBpZD0iY29udGVudCIgY2xhc3M9IiI+PC9kaXY+CiAgICAgICAgICAgIAogICAgICAgIDwvZGl2PgoKICAgICAgPC9kaXY+CiAgICAgIAogICAgPC9ib2R5PgogICAgCjwvaHRtbD4=" + webUI["html/configuration.html"] = "PCFkb2N0eXBlIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KCjxoZWFkPgogIDxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCIgLz4KICA8dGl0bGU+eFRlVmU8L3RpdGxlPgogIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL3NjcmVlbi5jc3MiIHR5cGU9InRleHQvY3NzIj4KICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9ImNzcy9iYXNlLmNzcyIgdHlwZT0idGV4dC9jc3MiPgogIDxzY3JpcHQgbGFuZ3VhZ2U9ImphdmFzY3JpcHQiIHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJqcy9jb25maWd1cmF0aW9uX3RzLmpzIj48L3NjcmlwdD4KICA8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvbmV0d29ya190cy5qcyI+PC9zY3JpcHQ+CiAgPHNjcmlwdCBsYW5ndWFnZT0iamF2YXNjcmlwdCIgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImpzL21lbnVfdHMuanMiPjwvc2NyaXB0PgogIDxzY3JpcHQgbGFuZ3VhZ2U9ImphdmFzY3JpcHQiIHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJqcy9zZXR0aW5nc190cy5qcyI+PC9zY3JpcHQ+CiAgPHNjcmlwdCBsYW5ndWFnZT0iamF2YXNjcmlwdCIgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImpzL2Jhc2VfdHMuanMiPjwvc2NyaXB0Pgo8L2hlYWQ+Cgo8Ym9keSBvbmxvYWQ9ImphdmFzY3JpcHQ6IHJlYWR5Rm9yQ29uZmlndXJhdGlvbigwKTsiPgoKICA8ZGl2IGlkPSJsb2FkaW5nIiBjbGFzcz0iYmxvY2siPgogICAgPGRpdiBjbGFzcz0ibG9hZGVyIj48L2Rpdj4KICA8L2Rpdj4KCiAgPGRpdiBpZD0iaGVhZGVyIiBjbGFzcz0iaW1nQ2VudGVyIj48L2Rpdj4KICA8ZGl2IGlkPSJib3giPgoKICAgIDx0YWJsZSBpZD0iY2xpZW50SW5mbyIgY2xhc3M9InZpc2libGUiPgogICAgICA8dHI+CiAgICAgICAgPHRkIGNsYXNzPSJ0ZEtleSI+VmVyc2lvbjo8L3RkPgogICAgICAgIDx0ZCBpZD0idmVyc2lvbiIgY2xhc3M9InRkVmFsIj4mbmJzcDs8L3RkPgogICAgICAgIDx0ZCBjbGFzcz0idGRLZXkiPk9TOjwvdGQ+CiAgICAgICAgPHRkIGlkPSJvcyIgY2xhc3M9InRkVmFsIj4mbmJzcDs8L3RkPgogICAgICA8L3RyPgogICAgICA8dHI+CiAgICAgICAgPHRkIGNsYXNzPSJ0ZEtleSI+VVVJRDo8L3RkPgogICAgICAgIDx0ZCBpZD0idXVpZCIgY2xhc3M9InRkVmFsIj4mbmJzcDs8L3RkPgogICAgICAgIDx0ZCBjbGFzcz0idGRLZXkiPkFyY2g6PC90ZD4KICAgICAgICA8dGQgaWQ9ImFyY2giIGNsYXNzPSJ0ZFZhbCI+Jm5ic3A7PC90ZD4KICAgICAgPC90cj4KICAgICAgPHRyPgogICAgICAgIDx0ZCBjbGFzcz0idGRLZXkiPlN0cmVhbXM6PC90ZD4KICAgICAgICA8dGQgaWQ9InN0cmVhbXMiIGNsYXNzPSJ0ZFZhbCI+Jm5ic3A7PC90ZD4KICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij5EVlI6PC90ZD4KICAgICAgICA8dGQgaWQ9IkRWUiIgY2xhc3M9InRkVmFsIj4mbmJzcDs8L3RkPgogICAgICA8L3RyPgogICAgPC90YWJsZT4KCiAgICA8ZGl2IGlkPSJoZWFkbGluZSI+CiAgICAgIDxoMSBpZD0iaGVhZC10ZXh0IiBjbGFzcz0iY2VudGVyIj5Db25maWd1cmF0aW9uPC9oMT4KICAgIDwvZGl2PgogICAgPHAgaWQ9ImVyciIgY2xhc3M9ImVycm9yTXNnIGNlbnRlciI+PC9wPgogICAgPGRpdiBpZD0iY29udGVudCI+CgogICAgPC9kaXY+CiAgICA8ZGl2IGlkPSJib3gtZm9vdGVyIj4KICAgICAgPGlucHV0IGlkPSJuZXh0IiBjbGFzcz0iIiB0eXBlPSJidXR0b24iIG5hbWU9Im5leHQiIHZhbHVlPSJOZXh0IiBvbmNsaWNrPSJqYXZhc2NyaXB0OiBzYXZlV2l6YXJkKCk7Ij4KICAgIDwvZGl2PgogIDwvZGl2Pgo8L2JvZHk+Cgo8L2h0bWw+" + webUI["html/create-first-user.html"] = "PCFkb2N0eXBlIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KCjxoZWFkPgogIDxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCIgLz4KICA8dGl0bGU+eFRlVmU8L3RpdGxlPgogIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL3NjcmVlbi5jc3MiIHR5cGU9InRleHQvY3NzIj4KICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9ImNzcy9iYXNlLmNzcyIgdHlwZT0idGV4dC9jc3MiPgogIDxzY3JpcHQgbGFuZ3VhZ2U9ImphdmFzY3JpcHQiIHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJqcy9uZXR3b3JrX3RzLmpzIj48L3NjcmlwdD4KICA8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvYXV0aGVudGljYXRpb25fdHMuanMiPjwvc2NyaXB0Pgo8L2hlYWQ+Cgo8Ym9keT4KCiAgPGRpdiBpZD0iaGVhZGVyIiBjbGFzcz0iaW1nQ2VudGVyIj48L2Rpdj4KCiAgPGRpdiBpZD0iYm94Ij4KCiAgICA8ZGl2IGlkPSJoZWFkbGluZSI+CiAgICAgIDxoMSBpZD0iaGVhZC10ZXh0IiBjbGFzcz0iY2VudGVyIj57ey5hY2NvdW50LmhlYWRsaW5lfX08L2gxPgogICAgPC9kaXY+CgogICAgPHAgaWQ9ImVyciIgY2xhc3M9ImVycm9yTXNnIGNlbnRlciI+PC9wPgoKICAgIDxkaXYgaWQ9ImNvbnRlbnQiPgoKICAgICAgPGZvcm0gaWQ9ImF1dGhlbnRpY2F0aW9uIiBhY3Rpb249IiIgbWV0aG9kPSJwb3N0Ij4KCiAgICAgICAgPGg1Pnt7LmFjY291bnQudXNlcm5hbWUudGl0bGV9fTo8L2g1PgogICAgICAgIDxpbnB1dCBpZD0idXNlcm5hbWUiIHR5cGU9InRleHQiIG5hbWU9InVzZXJuYW1lIiBwbGFjZWhvbGRlcj0iVXNlcm5hbWUiIHZhbHVlPSIiPgogICAgICAgIDxoNT57ey5hY2NvdW50LnBhc3N3b3JkLnRpdGxlfX06PC9oNT4KICAgICAgICA8aW5wdXQgaWQ9InBhc3N3b3JkIiB0eXBlPSJwYXNzd29yZCIgbmFtZT0icGFzc3dvcmQiIHBsYWNlaG9sZGVyPSJQYXNzd29yZCIgdmFsdWU9IiI+CiAgICAgICAgPGg1Pnt7LmFjY291bnQuY29uZmlybS50aXRsZX19OjwvaDU+CiAgICAgICAgPGlucHV0IGlkPSJjb25maXJtIiB0eXBlPSJwYXNzd29yZCIgbmFtZT0iY29uZmlybSIgcGxhY2Vob2xkZXI9IkNvbmZpcm0iIHZhbHVlPSIiPgoKICAgICAgPC9mb3JtPgoKICAgIDwvZGl2PgoKICAgIDxkaXYgaWQ9ImJveC1mb290ZXIiPgogICAgICA8aW5wdXQgaWQ9InN1Ym1pdCIgY2xhc3M9IiIgdHlwZT0iYnV0dG9uIiB2YWx1ZT0ie3suYnV0dG9uLmNyYWV0ZUFjY291bnR9fSIgb25jbGljaz0iamF2YXNjcmlwdDogbG9naW4oKTsiPgogICAgPC9kaXY+CgoKICA8L2Rpdj4KPC9ib2R5PgoKPC9odG1sPg==" + webUI["html/css/base.css"] = "KiB7CiAgLXdlYmtpdC1hcHBlYXJhbmNlOiBub25lOwogIC1tb3otYXBwZWFyYW5jZTogbm9uZTsKICAtbXMtYXBwZWFyYW5jZTogbm9uZTsKICBmb250LWZhbWlseTogIkFyaWFsIiwgc2Fucy1zZXJpZjsKICBsZXR0ZXItc3BhY2luZzogMnB4Owp9CgovKgo6Oi13ZWJraXQtc2Nyb2xsYmFyIHsgCiAgICBkaXNwbGF5OiBub25lOyAKfQoqLwoKOjotd2Via2l0LXNjcm9sbGJhciB7CiAgd2lkdGg6IDEycHg7CiAgaGVpZ2h0OiAxMnB4Owp9CgoKOjotd2Via2l0LXNjcm9sbGJhci10cmFjayB7CiAgLXdlYmtpdC1ib3gtc2hhZG93OiBpbnNldCAwIDAgNnB4IHJnYmEoMCwgMCwgMCwgMC4zKTsKICBib3gtc2hhZG93OiBpbnNldCAwIDAgNnB4IHJnYmEoMCwgMCwgMCwgMC4zKTsKICBib3JkZXItcmFkaXVzOiA1cHg7Cgp9Cgo6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iIHsKICBib3JkZXItcmFkaXVzOiA1cHg7CiAgLXdlYmtpdC1ib3gtc2hhZG93OiBpbnNldCAwIDAgNnB4IHJnYmEoMCwgMCwgMCwgMC42KTsKICBib3gtc2hhZG93OiBpbnNldCAwIDAgNnB4IHJnYmEoMCwgMCwgMCwgMC42KTsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDQ0Owp9Cgo6Oi13ZWJraXQtc2Nyb2xsYmFyLXRodW1iOmhvdmVyIHsKICBiYWNrZ3JvdW5kOiAjMzMzOwp9Cgo6Oi13ZWJraXQtc2Nyb2xsYmFyLWNvcm5lciB7CiAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7Cn0KCmEgewogIGNvbG9yOiAjMDBFNkZGOwp9CgpodG1sLApib2R5IHsKICBjb2xvcjogI2ZmZjsKICBtYXJnaW46IDBweCBhdXRvOwogIGhlaWdodDogMTAwJTsKICBmb250LXNpemU6IDE0cHg7Cn0KCmgyIHsKICBmb250LXNpemU6IDI0cHg7CiAgbGV0dGVyLXNwYWNpbmc6IDJweDsKfQoKaDMgewogIGZvbnQtc2l6ZTogMjJweDsKICBsZXR0ZXItc3BhY2luZzogMXB4Owp9CgpoNCB7CiAgZm9udC1zaXplOiAyMHB4OwogIGxldHRlci1zcGFjaW5nOiAxcHg7CiAgbGluZS1oZWlnaHQ6IDEuNWVtOwoKfQoKaDUgewogIGZvbnQtc2l6ZTogMTZweDsKICBsZXR0ZXItc3BhY2luZzogMXB4OwogIGxpbmUtaGVpZ2h0OiAxLjJlbTsKICBtYXJnaW46IDI1cHggMHB4IDEwcHggMHB4Owp9CgpociB7CiAgYm9yZGVyOiAwOwogIGhlaWdodDogMXB4OwogIGJhY2tncm91bmQ6ICMzMzM7CiAgbWFyZ2luOiAxMHB4IDBweDsKfQoKcCB7CiAgbWFyZ2luOiAycHg7CiAgcGFkZGluZzogMnB4IDVweDsKfQoKcHJlIHsKICBtYXJnaW46IDBweCAwcHggNXB4IDBweDsKICBmb250LXNpemU6IDEycHg7CiAgY29sb3I6ICNkZGQ7CiAgbGV0dGVyLXNwYWNpbmc6IDFweDsKICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7CiAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTsKICBmb250LXNpemU6IDEycHg7CiAgZm9udC1zdHlsZTogbm9ybWFsOwogIGZvbnQtdmFyaWFudDogbm9ybWFsOwogIGxpbmUtaGVpZ2h0OiAxLjZlbTsKfQoKbGFiZWwgewogIG1hcmdpbi1ib3R0b206IDIwcHg7CiAgZGlzcGxheTogYmxvY2s7Cn0KCmxpIHsKICBsaXN0LXN0eWxlLXR5cGU6IG5vbmU7CiAgYmFja2dyb3VuZC1jb2xvcjogIzExMTsKICBwYWRkaW5nOiAxMHB4IDIwcHg7CiAgY3Vyc29yOiBwb2ludGVyOwogIGJvcmRlci1sZWZ0OiBzb2xpZCAycHggIzExMTsKICB0cmFuc2l0aW9uOiBhbGwgMC4zOwp9CgpsaTpob3ZlciB7CiAgYm9yZGVyLWNvbG9yOiAjMDBFNkZGCn0KCnNlbGVjdCB7CiAgY3Vyc29yOiBwb2ludGVyOwogIHdpZHRoOiBjYWxjKDEwMCUgKyAycHgpOwogIGJvcmRlcjogc29saWQgMHB4ICMwMEU2RkY7CiAgYm9yZGVyLXJhZGl1czogMHB4OwogIG91dGxpbmU6IG5vbmU7CiAgY29sb3I6ICNmZmY7CiAgcGFkZGluZzogOXB4IDEwcHg7CiAgZGlzcGxheTogYmxvY2s7CiAgYmFja2dyb3VuZC1jb2xvcjogIzMzMzsKICBmb250LXNpemU6IDE0cHg7CiAgbWFyZ2luOiA1cHggMHB4IDVweCAwcHg7Cn0KCnNlbGVjdDpmb2N1cyB7CiAgb3V0bGluZTogbm9uZTsKfQoKaW5wdXQgewogIC13ZWJraXQtYXBwZWFyYW5jZTogbm9uZTsKICBtYXJnaW46IDVweCAwcHg7CiAgcGFkZGluZzogMi41cHggMTBweDsKICBvdXRsaW5lOiBub25lOwogIGZvbnQtc2l6ZTogMTRweDsKfQoKaW5wdXRbdHlwZT1idXR0b25dLAppbnB1dFt0eXBlPXN1Ym1pdF0gewogIGN1cnNvcjogcG9pbnRlcjsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwOwogIG1hcmdpbjogMTBweCAxMHB4OwogIHBhZGRpbmc6IDEwcHggMjVweDsKICBib3JkZXI6IHNvbGlkIDBweDsKICBib3JkZXItY29sb3I6ICMwMDA7CiAgYm9yZGVyLXJhZGl1czogM3B4OwogIG91dGxpbmU6IG5vbmU7CiAgY29sb3I6ICNmZmY7Cn0KCmlucHV0W3R5cGU9YnV0dG9uXTpmb2N1cyB7CiAgb3V0bGluZTogbm9uZTsKfQoKaW5wdXRbdHlwZT1idXR0b25dOmhvdmVyIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDBFNkZGOwogIGNvbG9yOiAjMDAwOwp9CgppbnB1dFt0eXBlPWJ1dHRvbl06aG92ZXIuZGVsZXRlIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiByZWQ7CiAgY29sb3I6ICNmZmY7Cn0KCmlucHV0W3R5cGU9dGV4dF0sCmlucHV0W3R5cGU9c2VhcmNoXSwKaW5wdXRbdHlwZT1wYXNzd29yZF0gewogIGNvbG9yOiAjZmZmOwogIHdpZHRoOiAtd2Via2l0LWNhbGMoMTAwJSAtIDBweCk7CiAgd2lkdGg6IC1tb3otY2FsYygxMDAlIC0gMHB4KTsKICB3aWR0aDogY2FsYygxMDAlIC0gMHB4KTsKICBvdXRsaW5lOiBub25lOwogIGJvcmRlcjogc29saWQgMXB4IHRyYW5zcGFyZW50OwogIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50OwogIGJvcmRlci1ib3R0b20tY29sb3I6ICM1NTU7CiAgYm9yZGVyLXJhZGl1czogMHB4OwogIHBhZGRpbmc6IDhweCAxMHB4Owp9CgppbnB1dFt0eXBlPSJjaGVja2JveCJdIHsKICBib3JkZXI6IHNvbGlkIDFweCAjMDBFNkZGOwogIGJhY2tncm91bmQtY29sb3I6ICMzMzM7CiAgaGVpZ2h0OiAyNXB4OwogIHdpZHRoOiAyNXB4OwogIGN1cnNvcjogcG9pbnRlcjsKICAvKgogIC13ZWJraXQtYXBwZWFyYW5jZTogY2hlY2tib3g7CiAgKi8KfQoKaW5wdXRbdHlwZT0iY2hlY2tib3giXTpjaGVja2VkIHsKICBjb2xvcjogI2ZmZjsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDBFNkZGOwogIC8qZGlzcGxheTogaW5saW5lLWJsb2NrOyovCn0KCmlucHV0W3R5cGU9ImNoZWNrYm94Il06YmVmb3JlIHsKICBwb3NpdGlvbjogaW5pdGlhbDsKICBsZWZ0OiAwcHg7CiAgbWFyZ2luLWxlZnQ6IC00cHg7CiAgY29udGVudDogIiAiOwp9CgppbnB1dFt0eXBlPSJjaGVja2JveCJdOmNoZWNrZWQ6YmVmb3JlIHsKICBwb3NpdGlvbjogaW5pdGlhbDsKICBsZWZ0OiAwcHg7CiAgbWFyZ2luLWxlZnQ6IC0zcHg7CiAgY29udGVudDogIuKckyI7CiAgY29sb3I6ICMwMDA7Cn0KCgppbnB1dFt0eXBlPWJ1dHRvbl0uY2FuY2VsIHsKCiAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7CiAgYm9yZGVyLWNvbG9yOiByZWQ7Cn0KCmlucHV0W3R5cGU9YnV0dG9uXS5zYXZlIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTExOwogIGZsb2F0OiByaWdodDsKfQoKCmlucHV0W3R5cGU9YnV0dG9uXS5ibGFjaywKaW5wdXRbdHlwZT1zdWJtaXRdLmJsYWNrIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwOwogIGJvcmRlci1jb2xvcjogIzAwMDsKfQoKaW5wdXRbdHlwZT1idXR0b25dLmNlbnRlciB7CiAgbWFyZ2luLXJpZ2h0OiBhdXRvOwogIG1hcmdpbi1sZWZ0OiBhdXRvOwogIGJhY2tncm91bmQtY29sb3I6ICMwMDA7CiAgYm9yZGVyLWNvbG9yOiAjMDAwOwp9CgoucG9pbnRlciB7CiAgY3Vyc29yOiBwb2ludGVyOwp9CgoucG9pbnRlcjpob3ZlciB7CiAgY29sb3I6ICMwMEU2RkY7CiAgY3Vyc29yOiBwb2ludGVyOwp9Cgouc29ydFRoaXMgewogIGNvbG9yOiAjMDBFNkZGOwp9CgoudzQwcHggewogIG1heC13aWR0aDogNDBweDsKfQoKLnc1MHB4IHsKICBtYXgtd2lkdGg6IDUwcHg7Cn0KCi53ODBweCB7CiAgbWF4LXdpZHRoOiA4MHB4Owp9CgoudzE1MHB4IHsKICBtYXgtd2lkdGg6IDE1MHB4Owp9CgoudzIwMHB4IHsKICBtYXgtd2lkdGg6IDIwMHB4OwogIG1pbi13aWR0aDogMTAwcHg7CiAgd2lkdGg6IDIwMHB4OwogIG92ZXJmbG93LXg6IGhpZGRlbjsKICB3aGl0ZS1zcGFjZTogbm93cmFwOwogIG92ZXJmbG93OiBoaWRkZW47CiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7Cn0KCi53MzAwcHggewogIG1heC13aWR0aDogMzAwcHg7Cn0KCi53MjIwcHggewogIG1heC13aWR0aDogMjIwcHg7CiAgY3Vyc29yOiBhbGlhczsKfQoKLmZvb3RlciB7CiAgZm9udC1zaXplOiAxMHB4Owp9CgouY2VudGVyIHsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCi5zY3JlZW5Mb2dIaWRkZW4gewogIHRyYW5zZm9ybTogdHJhbnNsYXRlKDBweCwgLTExMHB4KTsKfQoKLmJvcmRlclNwYWNlIHsKICBtYXJnaW4tYm90dG9tOiAzMHB4Owp9Cgoubm9uZSB7CiAgZGlzcGxheTogbm9uZTsKfQoKLm5vdFZpc2libGUgewogIGhlaWdodDogMHB4OwogIGRpc3BsYXk6IG5vbmU7CiAgb3BhY2l0eTogMDsKICBib3JkZXItYm90dG9tOiAjMDAwIHNvbGlkIDBweDsKCn0KCi52aXNpYmxlIHsKICBvcGFjaXR5OiAxOwogIGRpc3BsYXk6IGJsb2NrOwogIGJvcmRlci1ib3R0b206ICM0NDQgc29saWQgMXB4OwogIHBhZGRpbmc6IDEwcHg7Cn0KCi5mbG9hdFJpZ2h0IHsKICBmbG9hdDogcmlnaHQ7Cn0KCi5mbG9hdExlZnQgewogIGZsb2F0OiBsZWZ0Owp9CgoubWVudS1hY3RpdmUgewogIGJhY2tncm91bmQtY29sb3I6ICMwMEU2RkY7Cn0KCiNicmFuY2ggewogIGRpc3BsYXk6IHRhYmxlOwogIG1hcmdpbjogYXV0bzsKICBjb2xvcjogcmVkOwp9CgojaW50ZXJhY3Rpb24gewogIG1hcmdpbi1ib3R0b206IDEwMHB4OwogIHRleHQtYWxpZ246IGNlbnRlcjsKICBib3JkZXItYm90dG9tOiBzb2xpZCAwcHggIzc3NzsKfQoKCi5oYWxmIHsKICBkaXNwbGF5OiBibG9jazsKICB3aWR0aDogNDUlOwp9CgoubWVudSB7CiAgYm9yZGVyOiBzb2xpZCAxcHggIzAwRTZGRjsKfQoKLmluZm9Nc2cgewogIGNvbG9yOiAjYWFhOwp9CgouZXJyb3JNc2cgewogIGNvbG9yOiByZWQ7Cn0KCi53YXJuaW5nTXNnIHsKICBjb2xvcjogeWVsbG93Owp9CgouZGVidWdNc2cgewogIGNvbG9yOiBtYWdlbnRhOwp9CgouTmV3cywKLk1vdmllLAouU2VyaWVzLAouU3BvcnRzLAouS2lkcyB7CiAgYm9yZGVyLWxlZnQ6IHNvbGlkIDJweAp9CgouTmV3cyB7CiAgYm9yZGVyLWNvbG9yOiB0b21hdG8KfQoKLk1vdmllIHsKICBib3JkZXItY29sb3I6IHJveWFsYmx1ZTsKfQoKLlNlcmllcyB7CiAgYm9yZGVyLWNvbG9yOiBnb2xkOwp9CgouU3BvcnRzIHsKICBib3JkZXItY29sb3I6IHllbGxvd2dyZWVuOwp9CgouS2lkcyB7CiAgYm9yZGVyLWNvbG9yOiBtZWRpdW1wdXJwbGU7Cn0KCi8qIExvYWRpbmcgKi8KI2xvYWRpbmcgewogIGxlZnQ6IDBweDsKICB0b3A6IDBweDsKICB6LWluZGV4OiAxMDAwMDsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgwLCAwLCAwLCAwLjgpOwogIG1hcmdpbjogYXV0bzsKICB3aWR0aDogMTAwJTsKICBoZWlnaHQ6IDEwMCU7Cn0KCgoubG9hZGVyIHsKICBib3JkZXI6IDVweCBzb2xpZCB0cmFuc3BhcmVudDsKICBib3JkZXItcmFkaXVzOiA1MCU7CiAgYm9yZGVyLXRvcDogNXB4IHNvbGlkICMwMEU2RkY7CiAgYm9yZGVyLWJvdHRvbTogNXB4IHNvbGlkICMwMEU2RkY7CiAgd2lkdGg6IDUwcHg7CiAgaGVpZ2h0OiA1MHB4OwogIC13ZWJraXQtYW5pbWF0aW9uOiBzcGluIDEuMnMgbGluZWFyIGluZmluaXRlOwogIGFuaW1hdGlvbjogc3BpbiAxLjJzIGxpbmVhciBpbmZpbml0ZTsKCiAgcG9zaXRpb246IGZpeGVkOwogIG1hcmdpbjogYXV0bzsKCiAgdG9wOiAwOwogIHJpZ2h0OiAwOwogIGJvdHRvbTogMDsKICBsZWZ0OiAwOwoKfQoKQC13ZWJraXQta2V5ZnJhbWVzIHNwaW4gewogIDAlIHsKICAgIC13ZWJraXQtdHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7CiAgfQoKICAxMDAlIHsKICAgIC13ZWJraXQtdHJhbnNmb3JtOiByb3RhdGUoMzYwZGVnKTsKICB9Cn0KCkBrZXlmcmFtZXMgc3BpbiB7CiAgMCUgewogICAgdHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7CiAgfQoKICAxMDAlIHsKICAgIHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7CiAgfQp9" + webUI["html/css/screen.css"] = "bmF2IGltZyB7CiAgZGlzcGxheTogYmxvY2s7CiAgbWF4LWhlaWdodDogMjBweDsKICBtYXgtd2lkdGg6IDIwcHg7CiAgZmxvYXQ6IGxlZnQ7Cn0KCm5hdiBwIHsKICB0ZXh0LWFsaWduOiBsZWZ0OwogIHBhZGRpbmc6IDBweCAzMHB4Owp9CgojbGF5b3V0IHsKICBkaXNwbGF5OiBibG9jazsKICBoZWlnaHQ6IDEwMCU7Cn0KCgoubGF5b3V0LWxlZnQgewogIGRpc3BsYXk6IGJsb2NrOwogIG1pbi13aWR0aDogMTUwcHg7CiAgbWF4LXdpZHRoOiAyMCU7CiAgYmFja2dyb3VuZC1jb2xvcjogIzExMTsKICBoZWlnaHQ6IGluaGVyaXQ7CiAgZmxvYXQ6IGxlZnQ7Cn0KCi5sYXlvdXQtcmlnaHQgewogIGRpc3BsYXk6IGJsb2NrOwogIGJhY2tncm91bmQtY29sb3I6ICM0NDQ7Cn0KCiNtZW51LXdyYXBwZXIgewogIGhlaWdodDogMTAwJTsKfQoKCiNsb2dvIHsKICBkaXNwbGF5OiBibG9jazsKICBtaW4td2lkdGg6IDE4MHB4OwogIHdpZHRoOiAxMDAlOwogIGhlaWdodDogMTAwcHg7CiAgYmFja2dyb3VuZDogdXJsKCIuLi9pbWcvbG9nb193XzYwMHgyMDAucG5nIik7CiAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDsKICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiBjZW50ZXI7CiAgYmFja2dyb3VuZC1zaXplOiAxMDAlOwp9CgoKI3BhZ2UgewogIG1heC13aWR0aDogOTUwcHg7CiAgbWFyZ2luOiBhdXRvOwogIGJhY2tncm91bmQtY29sb3I6ICM0NDQ7CgogIC8qCiAgaGVpZ2h0OiAtd2Via2l0LWNhbGMoMTAwJSAtIDEzMHB4KTsKICBoZWlnaHQ6IC1tb3otY2FsYygxMDAlIC0gMTMwcHgpOwogIGhlaWdodDogY2FsYygxMDAlIC0gMTMwcHgpOwogICovCgogIG1pbi1oZWlnaHQ6IC13ZWJraXQtY2FsYygxMDAlIC0gMTIwcHgpOwogIG1pbi1oZWlnaHQ6IC1tb3otY2FsYygxMDAlIC0gMTIwcHgpOwogIG1pbi1oZWlnaHQ6IGNhbGMoMTAwJSAtIDEyMHB4KTsKCgogIGJveC1zaGFkb3c6IDBweCA1cHggNXB4ICMyMjI7Cgp9CgojdWlTZXR0aW5nIHsKICBmbG9hdDogcmlnaHQ7CiAgbWFyZ2luLXJpZ2h0OiAyNXB4Owp9CgojYm94IGlucHV0W3R5cGU9dGV4dF0sCiNib3ggaW5wdXRbdHlwZT1wYXNzd29yZF0gewogIHdpZHRoOiAtd2Via2l0LWNhbGMoMTAwJSAtIDIwcHgpOwogIHdpZHRoOiAtbW96LWNhbGMoMTAwJSAtIDIwcHgpOwogIHdpZHRoOiBjYWxjKDEwMCUgLSAyMHB4KTsKfQoKI2JveCBpbnB1dFt0eXBlPXN1Ym1pdF0gewogIG1hcmdpbjogNTBweCBhdXRvOwp9Cgojc2V0dGluZ3MgewogIGRpc3BsYXk6IGJsb2NrOwogIHBhZGRpbmc6IDEwcHggMTBweDsKfQoKI3NldHRpbmdzIGg1IHsKICBtYXJnaW46IDUwcHggMHB4IDEwcHggMHB4Owp9CgojY29udGVudC1pbnRlcmFjdGlvbiAuc2VhcmNoIHsKICB3aWR0aDogMjAwcHg7CiAgYm9yZGVyOiAxcHggc29saWQgIzAwMDsKICBwYWRkaW5nOiA5cHg7CiAgYmFja2dyb3VuZC1jb2xvcjogIzMzMzsKICBtYXJnaW46IDEwcHg7CiAgZmxvYXQ6IHJpZ2h0OwogIGJvcmRlci1yYWRpdXM6IDNweDsKCn0KCiNteVN0cmVhbXMgewogIHBvc2l0aW9uOiBmaXhlZDsKICBib3R0b206IDBweDsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTExOwogIHdpZHRoOiAxMDAlOwogIG1heC13aWR0aDogOTUwcHg7CgogIC8qCiAgbWF4LWhlaWdodDogMTAwcHg7CiAgKi8KICBtYXJnaW4tYm90dG9tOiAwcHg7Cn0KCiNteVN0cmVhbXMgaW1nIHsKICB3aWR0aDogNCU7CiAgcGFkZGluZzogMnB4IDVweDsKICBjdXJzb3I6IHBvaW50ZXI7CiAgZmxvYXQ6IHJpZ2h0Owp9CgovKiBXaXphcmQqLwojYm94IHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDQ0OwogIG1pbi1oZWlnaHQ6IDQwMHB4OwoKICBkaXNwbGF5OiBmbGV4OwogIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47CiAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuOwp9CgojYm94IHAgewogIHBhZGRpbmc6IDEwcHggMHB4Owp9CgojYm94LWZvb3RlciB7CiAgbWFyZ2luLXRvcDogYXV0bzsKfQoKI2JveC1mb290ZXIgewogIG1hcmdpbjogYXV0bzsKICBwYWRkaW5nOiAxMHB4Owp9CgojaGVhZGxpbmUgewogIGJhY2tncm91bmQtY29sb3I6ICMyMjI7CiAgYm9yZGVyLWJvdHRvbTogc29saWQgMnB4ICMyMjI7CiAgdHJhbnNpdGlvbjogYWxsIDAuNXM7CiAgcGFkZGluZzogMTBweCAwcHg7CiAgZGlzcGxheTogYmxvY2s7Cn0KCiNjb250ZW50IHsKICBkaXNwbGF5OiBibG9jazsKICBvdmVyZmxvdzogYXV0bzsKICBwYWRkaW5nOiAxMHB4Owp9CgovKiAtLS0gKi8KCgojY2xpZW50SW5mbywKI2FjdGl2ZVN0cmVhbXMsCiNpbmFjdGl2ZVN0cmVhbXMgewogIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7CiAgZGlzcGxheTogYmxvY2s7CiAgZm9udC1zaXplOiA5cHg7CiAgYmFja2dyb3VuZC1jb2xvcjogIzExMTsKICBjb2xvcjogIzAwRTZGRjsKICBib3JkZXItYm90dG9tOiBzb2xpZCAwcHg7CiAgOwogIHBhZGRpbmc6IDBweDsKICBsZXR0ZXItc3BhY2luZzogMXB4OwogIG92ZXJmbG93LXg6IGhpZGRlbjsKICBib3JkZXItc3BhY2luZzogNHB4IDRweDsKICBib3JkZXItYm90dG9tOiBzb2xpZCAxcHggIzQ0NDsKfQoKI215U3RyZWFtc0JveCB7CiAgcG9zaXRpb246IHJlbGF0aXZlOwogIHBhZGRpbmc6IDBweDsKICAvKmhlaWdodDogMTAwcHg7Ki8KICBtYXgtaGVpZ2h0OiAxNTBweDsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTExOwogIGNvbG9yOiB3aGl0ZTsKICBkaXNwbGF5OiBmbGV4OwogIGp1c3RpZnktY29udGVudDogY2VudGVyOwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7Cn0KCiNvcGVuU3RyZWFtcyB7CiAgd2lkdGg6IDIwcHg7CiAgaGVpZ2h0OiAyMHB4OwogIGN1cnNvcjogcG9pbnRlcjsKICBmbG9hdDogcmlnaHQ7CiAgcG9zaXRpb246IGFic29sdXRlOwogIHJpZ2h0OiAwcHg7CiAgYm90dG9tOiAwcHg7CiAgYmFja2dyb3VuZDogdXJsKCIuLi9pbWcvdG91Y2gucG5nIik7CiAgYmFja2dyb3VuZC1jb2xvcjogIzExMTsKCiAgYmFja2dyb3VuZC1wb3NpdGlvbjogYm90dG9tIHJpZ2h0Owp9CgojYWxsU3RyZWFtcyB7CiAgd2lkdGg6IDEwMCU7CiAgaGVpZ2h0OiAxMDAlOwogIHBhZGRpbmc6IDJweDsKfQoKI2FjdGl2ZVN0cmVhbXMsCiNpbmFjdGl2ZVN0cmVhbXMgewogIG92ZXJmbG93LXk6IHNjcm9sbDsKICB3aWR0aDogNTAlOwogIG1heC1oZWlnaHQ6IDEwMHB4OwogIGZsb2F0OiBsZWZ0Owp9CgojYWN0aXZlU3RyZWFtcyAudGRLZXksCiNpbmFjdGl2ZVN0cmVhbXMgLnRkS2V5IHsKICB3aWR0aDogNzVweDsKfQoKCgoKI2luYWN0aXZlU3RyZWFtcyAudGRLZXkgewogIGNvbG9yOiByZWQ7Cn0KCiNjbGllbnRJbmZvIC50ZFZhbCwKI2xvZ0luZm8gLnRkVmFsLAojYWN0aXZlU3RyZWFtcyAudGRWYWwsCiNpbmFjdGl2ZVN0cmVhbXMgLnRkVmFsLAojbWFwcGluZ0luZm8gLnRkVmFsIHsKICBjb2xvcjogI2FhYTsKICB3aGl0ZS1zcGFjZTogaW5oZXJpdDsKfQoKI2NsaWVudEluZm8gLnRkVmFsTGluaywKI2xvZ0luZm8gLnRkVmFsTGluaywKI2FjdGl2ZVN0cmVhbXMgLnRkVmFsTGluaywKI2luYWN0aXZlU3RyZWFtcyAudGRWYWxMaW5rLAojbWFwcGluZ0luZm8gLnRkVmFsTGluayB7CiAgY29sb3I6IGxpbWU7CiAgd2hpdGUtc3BhY2U6IGluaGVyaXQ7Cn0KCiNib3gtd3JhcHBlciB7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwogIHdpZHRoOiAxMDAlOwoKICBvdmVyZmxvdy15OiBzY3JvbGw7Cn0KCiNjb250ZW50X3RhYmxlLAojbWFwcGluZy1kZXRhaWwtdGFibGUsCiNjb250ZW50X3RhYmxlIHsKICBkaXNwbGF5OiB0YWJsZTsKCiAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTsKICBvdmVyZmxvdy15OiBzY3JvbGw7CiAgd2lkdGg6IDEwMCU7Cn0KCgojY29udGVudF90YWJsZSAuY29udGVudF90YWJsZV9oZWFkZXIgewogIGJhY2tncm91bmQtY29sb3I6ICMzMzM7CiAgaGVpZ2h0OiA1MHB4OwogIGJvcmRlci1ib3R0b206IHNvbGlkIDFweCAjMTExOwogIGJvcmRlci1sZWZ0OiBzb2xpZCAzcHggIzMzMzsKICBjdXJzb3I6IGF1dG87Cgp9CgoKdGJvZHkgewogIHdpZHRoOiAxMDAlOwp9CgoKLnRhYmxlRWxsaXBzaXMgewogIHdpZHRoOiAxNTBweDsKICBvdmVyZmxvdzogaGlkZGVuOwogIHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzOwogIHdoaXRlLXNwYWNlOiBub3dyYXA7Cn0KCiNjb250ZW50X3RhYmxlIGltZyB7CiAgZGlzcGxheTogYmxvY2s7CiAgbWF4LWhlaWdodDogMjhweDsKICBtYXJnaW4tbGVmdDogYXV0bzsKICBtYXJnaW4tcmlnaHQ6IGF1dG87CiAgbWF4LXdpZHRoOiAzMHB4Owp9CgojY29udGVudF90YWJsZSB0ciB7CiAgYm9yZGVyLWxlZnQ6IHNvbGlkIDNweCA0NDQ7CiAgYm9yZGVyLWJvdHRvbTogc29saWQgMXB4ICMzMzM7CiAgY3Vyc29yOiBwb2ludGVyOwp9CgojY29udGVudF90YWJsZSB0cjpob3ZlciB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzMzMzsKfQoKI2NvbnRlbnRfdGFibGUgdGQgewoKICBwYWRkaW5nOiAwcHggMnB4Owp9CgojY29udGVudF90YWJsZSBpbnB1dFt0eXBlPXRleHRdIHsKICB3aWR0aDogODAlOwogIG1pbi13aWR0aDogMzVweDsKICBtYXgtd2lkdGg6IDYwcHg7CiAgYm9yZGVyOiAwcHg7CiAgYmFja2dyb3VuZC1jb2xvcjogIzMzMzsKICBtYXJnaW4tbGVmdDogNXB4OwogIHRleHQtYWxpZ246IGxlZnQ7Cn0KCiNjb250ZW50X3RhYmxlIGlucHV0W3R5cGU9Y2hlY2tib3hdIHsKICBtYXgtd2lkdGg6IDI1cHg7CiAgbWFyZ2luOiBhdXRvOwp9CgoKLnNob3dCdWxrIHsKICBkaXNwbGF5OiBibG9jazsKfQoKLmhpZGVCdWxrIHsKICBkaXNwbGF5OiBub25lOwp9CgojY29udGVudF90YWJsZSB0ci5hY3RpdmVFUEcgewogIGJvcmRlci1sZWZ0OiBzb2xpZCAzcHggbGF3bmdyZWVuOwp9CgojY29udGVudF90YWJsZSB0ci5ub3RBY3RpdmVFUEcgewogIGJvcmRlci1sZWZ0OiBzb2xpZCAzcHggcmVkOwp9CgoKI2xvZ1NjcmVlbiBwIHsKICB3aGl0ZS1zcGFjZTogcHJlOwogIGZvbnQtc2l6ZTogMTBweDsKICAvKgogIGxpbmUtaGVpZ2h0OiAxLjZlbTsKICBmb250LWZhbWlseTogIkFyaWFsIiwgc2Fucy1zZXJpZjsKICAqLwogIGxldHRlci1zcGFjaW5nOiAxcHg7CiAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTsKICBmb250LXNpemU6IDEycHg7CiAgZm9udC1zdHlsZTogbm9ybWFsOwogIGZvbnQtdmFyaWFudDogbm9ybWFsOwogIGxpbmUtaGVpZ2h0OiAxLjZlbTsKfQoKI3BvcHVwIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDAsIDAsIDAsIDAuNCk7CiAgcG9zaXRpb246IGZpeGVkOwogIGxlZnQ6IDBweDsKICB3aWR0aDogMTAwJTsKICB6LWluZGV4OiAxMDA7CiAgaGVpZ2h0OiAxMDAlOwogIG92ZXJmbG93OiBzY3JvbGw7Cn0KCiNtYXBwaW5nLWRldGFpbCwKI3VzZXItZGV0YWlsLAojZmlsZS1kZXRhaWwsCiNwb3B1cC1jdXN0b20gewogIGJveC1zaGFkb3c6IDBweCA1cHggNDBweCAjMDAwOwogIG1hcmdpbi10b3A6IDIwcHg7CiAgbWFyZ2luLWxlZnQ6IGF1dG87CiAgbWFyZ2luLXJpZ2h0OiBhdXRvOwoKICBtYXgtd2lkdGg6IDgwMHB4OwogIGJhY2tncm91bmQtY29sb3I6ICMyMjI7CiAgcGFkZGluZzogMTBweDsKICBvdmVyZmxvdzogYXV0bzsKfQoKI3BvcHVwLWN1c3RvbSBoMyB7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgojZmlsZS1kZXRhaWwgaW5wdXRbdHlwZT10ZXh0XSB7CiAgd2lkdGg6IC13ZWJraXQtY2FsYygxMDAlIC0gMjBweCk7CiAgd2lkdGg6IC1tb3otY2FsYygxMDAlIC0gMjBweCk7CiAgd2lkdGg6IGNhbGMoMTAwJSAtIDIwcHgpOwp9CgojbWFwcGluZy1kZXRhaWwgaW1nIHsKICBkaXNwbGF5OiBibG9jazsKICBtYXgtaGVpZ2h0OiAzMHB4OwogIG1hcmdpbi1ib3R0b206IDIwcHg7CiAgbWFyZ2luLWxlZnQ6IGF1dG87CiAgbWFyZ2luLXJpZ2h0OiBhdXRvOwp9CgojcG9wdXAtY3VzdG9tIGlucHV0W3R5cGU9dGV4dF0sCiNwb3B1cC1jdXN0b20gaW5wdXRbdHlwZT1wYXNzd29yZF0sCiNtYXBwaW5nLWRldGFpbCBpbnB1dFt0eXBlPXRleHRdLAojY29udGVudF9zZXR0aW5ncyBpbnB1dFt0eXBlPXRleHRdLAojY29udGVudF9zZXR0aW5ncyBpbnB1dFt0eXBlPXBhc3N3b3JkXSB7CiAgYm9yZGVyOiBzb2xpZCAxcHg7CiAgYm9yZGVyLWNvbG9yOiB0cmFuc3BhcmVudDsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzMzOwogIHRleHQtYWxpZ246IGxlZnQ7CiAgd2lkdGg6IC13ZWJraXQtY2FsYygxMDAlIC0gMjBweCk7CiAgd2lkdGg6IC1tb3otY2FsYygxMDAlIC0gMjBweCk7CiAgd2lkdGg6IGNhbGMoMTAwJSAtIDIwcHgpOwp9CgojcG9wdXAtY3VzdG9tIGlucHV0W3R5cGU9dGV4dF0ubm90QXZhaWxhYmxlIHsKICBib3JkZXItY29sb3I6IHJlZDsKICBjb2xvcjogIzY2NjsKICBjdXJzb3I6IG5vdC1hbGxvd2VkOwp9CgojcG9wdXAtY3VzdG9tIGlucHV0W3R5cGU9dGV4dF06ZGlzYWJsZWQgewogIGNvbG9yOiAjNjY2OwogIGN1cnNvcjogbm90LWFsbG93ZWQ7Cn0KCiNtYXBwaW5nLWRldGFpbC10YWJsZSwKI3VzZXItZGV0YWlsLXRhYmxlIHsKICBkaXNwbGF5OiBpbmxpbmUtdGFibGU7CiAgd2lkdGg6IDEwMCU7Cn0KCiNwb3B1cC1jdXN0b20gdGFibGUsCiNjb250ZW50X3NldHRpbmdzIHRhYmxlIHsKICBkaXNwbGF5OiBpbmxpbmUtdGFibGU7CiAgdGFibGUtbGF5b3V0OiBmaXhlZDsKICB3aWR0aDogMTAwJTsKfQoKCiNtYXBwaW5nLWRldGFpbC10YWJsZSB0ZCwKI3VzZXItZGV0YWlsLXRhYmxlIHRkIHsKICBwYWRkaW5nOiAxMHB4IDBweDsKCn0KCiNtYXBwaW5nLWRldGFpbC10YWJsZSB0ZC5sZWZ0LAojdXNlci1kZXRhaWwtdGFibGUgdGQubGVmdCwKI3BvcHVwLWN1c3RvbSB0ZC5sZWZ0IHsKICB3aWR0aDogMzglOwp9CgouaW50ZXJhY3Rpb24sCiNpbnRlcmFjdGlvbiB7CiAgbWFyZ2luLXRvcDogMjBweDsKICBkaXNwbGF5OiBpbmxpbmUtZmxleDsKICBmbG9hdDogcmlnaHQ7Cn0KCi5pbnRlcmFjdGlvbiBpbnB1dFt0eXBlPWJ1dHRvbl0sCi5pbnRlcmFjdGlvbiBpbnB1dFt0eXBlPXN1Ym1pdF0gewogIGJhY2tncm91bmQtY29sb3I6ICMwMDA7CiAgbWluLXdpZHRoOiAxMDBweDsKICBtYXJnaW46IDBweCAxMHB4OwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKI25vdGlmaWNhdGlvbiB7CiAgZGlzcGxheTogYmxvY2s7CiAgcG9zaXRpb246IGZpeGVkOwogIHJpZ2h0OiAwcHg7CiAgaGVpZ2h0OiAxMDAlOwogIHdpZHRoOiAyNTBweDsKCiAgYmFja2dyb3VuZC1jb2xvcjogIzIyMjsKICBib3gtc2hhZG93OiAwcHggMHB4IDIwcHggIzAwMDsKfQoKI25vdGlmaWNhdGlvbiBoNSB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzEyMTIxMjsKICBwYWRkaW5nOiA1cHggMTBweCA1cHggMTBweDsKfQoKI25vdGlmaWNhdGlvbiBwcmUgewogIHBhZGRpbmc6IDBweCAxMHB4IDBweCAxMHB4Owp9Cgojbm90aWZpY2F0aW9uIHAgewogIGZvbnQtc2l6ZTogMTAgcHg7CiAgbWFyZ2luOiAwcHg7CiAgcGFkZGluZzogMHB4IDEwcHggNXB4IDEwcHg7Cn0KCiNub3RpZmljYXRpb24gLmVsZW1lbnQgewogIC8qcGFkZGluZzogMHB4IDVweDsqLwogIG1hcmdpbjogNXB4IDVweDsKICBib3JkZXItcmFkaXVzOiA1cHg7CiAgYmFja2dyb3VuZC1jb2xvcjogIzE4MTgxODsKICBib3JkZXItbGVmdDogMTBweCBzb2xpZCBncmVlbjsKfQoKCkBtZWRpYSBvbmx5IHNjcmVlbiBhbmQgKG1pbi13aWR0aDogNjIwcHgpIHsKICBib2R5IHsKICAgIHdpZHRoOiAxMDAlOwogICAgYmFja2dyb3VuZC1jb2xvcjogIzQ0NDsKICB9CgogIGgxIHsKICAgIGZvbnQtc2l6ZTogMjZweDsKICAgIGxldHRlci1zcGFjaW5nOiAzcHg7CiAgfQoKICBuYXYgcCB7CiAgICBkaXNwbGF5OiBibG9jazsKICB9CgoKCiAgI2hlYWRlcl9jb25maWcgewogICAgZGlzcGxheTogYmxvY2s7CiAgICBoZWlnaHQ6IDEwMHB4OwogICAgYmFja2dyb3VuZDogdXJsKCIuLi9pbWcvbG9nb193XzYwMHgyMDAucG5nIik7CiAgICBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0OwoKICAgIGJhY2tncm91bmQtc2l6ZTogMzAwcHggMTAwcHg7CiAgfQoKICAjc2NyZWVuTG9nIHsKICAgIG1hcmdpbi1sZWZ0OiAzMDBweDsKCiAgICB0cmFuc2l0aW9uOiBub25lOwogICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7CiAgICBib3JkZXItYm90dG9tOiBzb2xpZCAxcHggdHJhbnNwYXJlbnQ7CiAgICBib3gtc2hhZG93OiAwcHggMHB4IDBweCAjMjIyOwogIH0KCiAgI3NldHRpbmdzIHsKICAgIC8qCiAgICBoZWlnaHQ6IC13ZWJraXQtY2FsYygxMDAlIC0gMTAwcHgpOwogICAgaGVpZ2h0OiAtbW96LWNhbGMoMTAwJSAtIDEwMHB4KTsKICAgIGhlaWdodDogY2FsYygxMDAlIC0gMTAwcHgpOwogICAgKi8KICAgIHBvc2l0aW9uOiByZWxhdGl2ZTsKICAgIG92ZXJmbG93OiBhdXRvOwogIH0KCgogIC5zY3JlZW5Mb2dIaWRkZW4gewogICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoMHB4LCAwcHgpOwogIH0KCgogICNib3ggewogICAgZGlzcGxheTogYmxvY2s7CiAgICBtaW4taGVpZ2h0OiA1MDBweDsKICAgIG1heC13aWR0aDogNTAwcHg7CiAgICBtYXJnaW46IDEwcHggYXV0bzsKICAgIGJhY2tncm91bmQtY29sb3I6ICM0NDQ7CiAgICBib3gtc2hhZG93OiAwcHggNXB4IDVweCAjMjIyOwoKICAgIGRpc3BsYXk6IGZsZXg7CiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogIH0KCn0=" + webUI["html/favicon.ico"] = "AAABAAMAEBAAAAEAIABoBAAANgAAACAgAAABACAAKBEAAJ4EAAAwMAAAAQAgAGgmAADGFQAAKAAAABAAAAAgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO2cIH7unCD57pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg+e2cIH7unCD57pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD57pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unSP/7p0k/+6cIP/voSz/7pwg/+6fJv/unSP/7p4k/+6cIP/unCD/7pwh/+6eJP/unCD/7pwg/+6cIP/unSP/+Nmr//vpzv/zumT/++nO/++hK//87tr/99Se//rkwv/30JX/9s2P//zt1//41qL/9ceC/+6cIP/unCD/7p0i//nds//30Zj/7qAo//rmx//unib/++vS//bMjP/54Lv/9suK//TAcf/758n/8Kg6/++gKv/unCD/7pwg/+6cIf/1xn//8rJS/++iLf/30Zn/8Kk+//GuSf/0wnX/9MBx//GsRP/xr0z/+d20//fTnP/wpjj/7pwg/+6cIP/unCD/7pwg/+6cIP/yt13/+d62//ndsv/0v3D/7pwg/+6cIP/unCD/7pwg//ncsP/53rb/9cmF/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unSP/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg+e6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg+e2cIH7unCD57pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg+e2cIH4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAACAAAABAAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+AAALsmiF87pwg5u6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg5uyaIXz/gAAC7JwhfO6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+ycIXzunCDm7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg5u6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/76Es/+6cIP/uoCn/7p4m/+6cIP/unCD/8KxE/++iLf/unCD/7pwg/+6cIf/wpzj/76It/+6cIP/unCD/76Qy/+6cIP/unCD/7pwg/+6cIP/unCD/7p0j/++iL//unSL/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/++hLf/99ej/9MBy//747//++fL/871r/+6cIP/88d//+eC5/+6cIP/uniT/++nO/////////v7/+uPA//CrQv/++vT/+uC5/+6fJv/wq0L/76Mv//fRl//++/X///////769P/31aD/7p8n/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg//K0WP///fv///36//K3Xf/87NT/76Qy//zt1//758r/7pwg//GtR///////99Kb//CnOf/1x4L//fXo//316f/30pr//O/b//3y4v/99ur///////vq0P/xsE7/8a5J//jZqv/30Zj/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwh//3z5v/76tD/7pwg/++lNP/voi3/+d+2//zy4v/unCD/76Qy///+/f/88d7/9s2P/++iLf/3057/+uXF/+6dI//++PD/875s//O3Xv//////9suL/+6cIP/unCD/7pwg//GuSf/unCD/7pwg/+6cIP/unCD/7pwg/++gKf/65sb///////3y4//2zY7/7pwg/+6cIP/2y4r///78/+6eJv/unCD/+d62//netv/537b/+uK9//jarP/88N7/7pwg//779//87tj/7p0j//rkw//87db/9L1r//CqP//unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7p4m//3z5P/76Mv/76Iv//zu2f/ys1X/7pwg//KzU///////8a5I/+6cIP/voi//+d+3//769P/41qL/9s6Q//748P/unCD/+dyx//vpz//unCD/8a1H//78+f/64r3/871q/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/76Aq/+6dJP/unCD/7pwg/+6cIP/unCD/7p0j//337v/0v2//7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7p4k/+6cIP/unCD/7pwg/+6cIP/20JX//v37//bNj//54Lv/9cZ//+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/8K1F//vpzv/30Zj/++rQ//nftv/1xHr/9cV8/+6fJ//unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg//XGf///////+uK+//O8aP///v7/8KtB/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/8KtD//jXpv/76Mz/++nN//vozP/658n/8rNT/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/+d60//bNj//76c7//fPj//ndsv/uniX/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/voSv/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCDm7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg5uyaIXzunCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/smiF8/4AAAuycIXzunCDm7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCDm7JwhfP+AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAADAAAABgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADumSIP7JseXO6cIMbunSD27pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unSD27pwgxuybHlztpCQOAAAAAO6ZIg/unCGV7pwg9+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6bIPjunCGV7aQkDuybHlzunCD37pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD47JseXO6cIMbunCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwgxu6dIPbunCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7p0g9u6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/++lNP/uoCr/7pwg/+6eJv/wpzn/7p0j/+6cIP/unCD/7pwg//GwT//zt17/758o/+6cIP/unCD/7pwg/+6cIf/vpTT/8a9M//CqP//uniT/7pwg/+6cIP/voCn/8K1G/+6cIf/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/758o//CnOP/vozH/7p0h/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/8atD//758f/41qT/8Kk9//zs0////////O/b//K2Wv/uniT/7pwg//vnyP//////9cmF/+6cIP/unCD/7p0i//bLiv/++/b//////////v/98uH/9cR5/++iLf/2yIL///z5//riv//wqTz/7pwh/++gKf/voSz/7p0i//GvTP/64Lv///35/////////////fLi//bKiP/vpTX/7pwh/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg//bJhf/99ej/++rQ///////99Oj/++bH//316f/yuGD/7pwh//voyv//////99Kb/+6cIP/unCD/8K1G///9+v///v7/++nN//jXp//64r7//vrz//ncr//65cX///79//zv2//64bv/87pk//jaq//53rX/9smG//zy4v////////36//vlxv/527D/+uK///747//64r3/76U0/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/++hK//416b///79///+/P/30Jb/76U0//fTnP/42Kn/76Ap//netf//////+dqt/+6cIP/unCD/87tl///////99ej/8bBM/++fKP/voy//87lh//337f///fr/+uTE//GvS//769L//vjw//305v/65ML//vrz////////////9cmF/++kMv/voSv/76Mw//K1WP/87db/9L9w/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/0vmz//vrz//747//zuGD/7pwg/++hLP/ytVn/758o//bOkP//////+ubI/+6cIP/unCD/8q9N/////v/+/fv/+uG6//O6ZP/vpDP/7p0h//K4Yf//////99Wg/+6dIf/2yoj///37//XIhP/unSH/99Ka///////+/Pj/8axE/+6cIP/unCD/7pwg/+6cIP/xsE7/8rNU/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg//GvS//53LH///79//789//3zpL/76Ao/+6cIP/unCD/7pwg//O6ZP///////fXo/+6cIP/unCD/7p4l//zu2v///v3/+Nin//zv2//65sf/8a9M//K6ZP//////+Nmp/+6cIP/1x4L///37//zt1v/wqDv/8a5K//769f///v3/87pk/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/8KY4//305//+/Pn///////rjwf/99ur/986S/+6cIP/unCD/7pwg//GrQv/++PD///79/++jMP/unCD/7pwg//O9av///Pr/99Od//O5Yv///v7/+Nmq//XEev///////OzV/+6cIP/2yof///78//779//0wnb/7p0i//XDef/++fL//fHh//fRmf/3zpL/76U1/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/76Mx//747v///v7//O7Y/++jMf/2z5P//vz4//TDef/unCD/7pwg/++lNf/76c3///////K1WP/unCD/7pwg/++gKP/2z5P//fft//779f/+/Pj/99Kb//O9af///fv//vfu/+6cIP/zu2X//fXp//768//1xHv/7pwg/+6fJv/30pn///78//737f/98eD/8rde/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg//O7Z//30pr/8a5I/+6cIP/wpjj/9cZ///GvS//unCD/7pwg/+6fJ//41qT///////XIg//unCD/7pwg/+6cIP/unyj/8rdd//bJhf/1xXz/76U1/++jMP/2yYX/9ceA/+6cIP/unyj/87xo//TCdv/vpTX/7pwg//CqQP/99ej///78//O5Yv/ytFf/8bBN/++iLv/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIf/uniX/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/0wnX//vv2//narv/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCH/7pwh/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg//G0V/////7//vz5//rft//98+X//fXo//vq0P/ys1P/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/++kM//43LD/+Nmq//O6Zf/zuWH//fXp//zs1f/wqT3/8Ko///CqQP/vpDH/7pwh/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg//GtR//++/b///////zv2v/0vm7/87xn///+/f/52q3/76Aq/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6dIv/ytVf/+uTD///9+//++fL///38///9+//99Ob//fbq//337v/42qv/76It/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg//K1Wf/99ej//v36//758//64r7/+uO////+/f/41qT/76Ao/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCH/76Qy//K2W//30Zf/+Nqs//jarP/42qv/+Nmq//fYpv/2zI3/76Iv/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg//jbrf/2y4n/8rVX//jVoP/758r/++rQ//fVoP/wqkD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg//CnOv/unSL/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6dIPbunCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7p0g9u6cIMbunCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwgxuybHlzumyD47pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD37JseXO2kJA7unCGV7pwg+O6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIPfunCGV7pkiDwAAAADtpCQO7JseXO6cIMbunSD27pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unCD/7pwg/+6cIP/unSD27pwgxuybHlzumSIPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + webUI["html/img/filter.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0wNy0yOFQxOTowNzo2OTwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cs038OQAAAOISURBVGgF5ZpLSBVRGMfvvfmqCKKiKCqKtE3SQ8haJJm1ctPCZYHrFhXtohcUBLVsU1BRBJKLXpsSKs1aCL1oUUhvMgIloodZKmLZ72+OzNVx7jzOXGfqg/89Z875zv/7f35n7px7vanUP2JptzyGhoYKmK8GW0EZmA/mgW7wHrwDN0BTOp0epPVtxBBnLdgIVoE5YBboBR2gDTTA/5DWn0FeDPaBz8CLdeF0EBR5jYRvKbgABoAXa8Opwit/CudK8NoLs4PPM8ZyBsNnB/jpsD7X0C8cjgDXnaQkqkEPCGMSuGWivxxzx8OQj6xtpHWuPhPloHfEMWzTD0HN2GQY2xuW2Lb+/Fh+VaIQPLE5meh+gmSxFYz+BjBogtjGscfiH26Z2GmbNNltVQAIpwDdP6ZNO2iRYqTpZGhfgWUaiMC2w1kCzkbALcqLvDVvUyK6MW9HFES0b8BvsFwXEZi4F+iBtykCcjtlqf0igr52VJ1eqiIgzzdlrRIZfWfJd3SD8ZbqHvkB4XSDpJNB9V0VcX/cT4Ys/zEzSuSj/3WxW9GpRD7ETpZ/QcOJ6LyfdHugitxNehbob9G7lo4PXWBmQhPqQ/fsDOeUfjqNCU1Csi+TQ5+2luzc3yaRr6elevQZwhZr4bomYam0U41yabYqov5hvSTMjlp6RyuiAarSTLPZmox5246+lVREx/isiuh6NxhUJwF2yEpCWu1bK8WEsjyRgCSa0XrVrjNra2mC7TWD5ilYAuJoA4jSlnppF5dVEU3g0ENTD4b3nsZiZsfGJuGqj8qY+CINGqP2GLZCJ+HjtpblxAJ9k3cPrLfGJrnVUaSCarxw0jFua1lOLNBerANx+byya6IkLM2uLZWpAl6/Mcc1EjvjKtLrJNLqI5HnjfQ+bsVeteb0g2y/t7hGvd7CNjenOL8OkJ40KtOdTF+Cl/nV6Mkf4gxocI9vZPYLLKs9iQrqRIACcM2IXGeSboYrg+rztY5ARaDJWUeo0W+sXudLTFhnApaAW6FkZy/+yuXasLoCrSfwVHAnW0+gK93YawKJMLUIAdNAKwhqnSxcYUpPKB6EBE2mg7VR///EX24jybTQerXnOC70FyVP3gjTPXPTQyaP8NFPNeJrCNTPP667JKOq6VNo/A2hes5ccUjmEmPmDoD5+FMgWCcA+3FG57QJP//kQ1PgGBIOToEDgUn+t4V/AJeGknwARIKLAAAAAElFTkSuQmCC" + webUI["html/img/log.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0xMC0xNFQxMToxMDo0MjwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CkP32mEAAANASURBVGgF7ZlPiE1RHMffw1AYhiL5k1HEijJiYaFZiHoyFspW2RFRkkSZGgtFWJIwi9FYmo0VOywkKTbKgjSlWcifRCPX51dv6s2d33md77vvXjfmV9859/7u93x/v98959x73p1KRbAkSargAhgDH0E/qIYkuHYEvAPGvwbmNOEerXM/0Q6BRSFuZj/ix0DaDnvCkGppIucDAe4OhzvkcUO+GaELAf8ux7/b8Zlrr+Pvc3zm6nX8NccXdKmFLHaUPJ/Ruhyu5zNap8Nd6PiCLrUQTyi0Rjy/5/M0Zd+smB7M32XwtgBr07aC6yfSTs7XO77OALfH4VbgHsD/HLytVquJx4nyIdQFBsHftscksK5Z0sGhpuN8Or4Aa5sJFHjtO7G2MjKvvZjN1sglOpSlCMt9LrDZ4S4Hd0Qg24vrK+gAZbPtjMqTdFKhEdkIsYxFWP720JlioUK6pzDL41jtpRIqxOOWxecuB3fhRGT8E85YBK8VygI6GSRTCxlH3TaJgyw4O2678aCxO94LbNPovYDdmOrUukIBN/MqwjJEOwGPOHR31W4VONVCLEBR9lAJpBbSrYhn5K5R+quFnGUOr1ICtMIlxjz6XVb6qot9JeKvCPSAdlQJJHDtd8hOIN0wtRDLxx6Ntr0ulalTq1TJNyYzXUjj3SjD8X87Iva7uR8s5+2bi6FtX1oOgi8g2tSn1g2yPx+t3gIR/c90s1+C1vuO/YkxdWrdjxFtE2dE0VELWaqIZ+QuUfqrhZxmyKUvgEoyE1xizOR4YOI8plXXyAZEbYsyTJvXFsUW+x6wGUSbWogJ237rZHSEgojq1CooLT3MdCH6Pcu3xz8zIq0s9lvc2+sgz6dWH/rnQPB/jlybZGoh99hCHJqk0P6TD0jaI/4b7dVYeXVq2bemokyKpRZiHwWKMimWWshxhryjoEpOKXHUNbIN8WcUc5s2r8Vue7l9oAaiTS3EhDeB6EUYnUlGojq1MobLr3uokB/5hcys7OYWKuRl5nD5Cbi5uYXw0ntPHoay2S8Seuol5RZSJ0r/n/DEc/BdrN9kTZrH7BkwDspgwyQxW6uggU3nHnAXvAG/QZE2SrARsL8hJffwDxM0mNDPvT8IAAAAAElFTkSuQmCC" + webUI["html/img/logo_b_880x200.jpg"] = "/9j/4AAQSkZJRgABAQABLAEsAAD/4QDIRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAPAAAAcgEyAAIAAAAUAAAAgodpAAQAAAABAAAAlgAAAAAAAAEsAAAAAQAAASwAAAABUGl4ZWxtYXRvciAzLjMAADIwMTk6MDg6MDIgMjA6MDg6MTQAAAOgAQADAAAAAQABAACgAgAEAAAAAQAAA3CgAwAEAAAAAQAAAMgAAAAA/+EJkGh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iUGl4ZWxtYXRvciAzLjMiIHhtcDpNb2RpZnlEYXRlPSIyMDE5LTA4LTAyVDIwOjA4OjE0Ii8+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD94cGFja2V0IGVuZD0idyI/PgD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgAyANwAwERAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/bAEMBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/dAAQAbv/aAAwDAQACEQMRAD8A/iHoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP/9D+IegAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA//0f4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//S/iHoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP/9P+IegAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA//1P4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDvPDXws+J3jPT31bwf8OfHnivSo7mSyfU/DXhDxBrunpeQpFLNaPe6Xp11bLcxRzwSSQNL5saTROyhZUNAHQf8M//AB4/6In8XP8Aw23jL/5TUAH/AAz/APHj/oifxc/8Nt4y/wDlNQAf8M//AB4/6In8XP8Aw23jL/5TUAH/AAz/APHj/oifxc/8Nt4y/wDlNQAf8M//AB4/6In8XP8Aw23jL/5TUAH/AAz/APHj/oifxc/8Nt4y/wDlNQAf8M//AB4/6In8XP8Aw23jL/5TUAH/AAz/APHj/oifxc/8Nt4y/wDlNQAf8M//AB4/6In8XP8Aw23jL/5TUAH/AAz/APHj/oifxc/8Nt4y/wDlNQB5bfWN9pd9eaZqdndadqWnXVxY6hp99bzWl9Y31pM9vd2d5aXCRz2t1azxvBcW80cc0MyPHIiurKoBVoAKACgAoAKACgAoAKACgDvPDXws+J3jPT31bwf8OfHnivSo7mSyfU/DXhDxBrunpeQpFLNaPe6Xp11bLcxRzwSSQNL5saTROyhZUNAHQf8ADP8A8eP+iJ/Fz/w23jL/AOU1AB/wz/8AHj/oifxc/wDDbeMv/lNQBja/8I/iv4T0ufXPFPwx+IfhrRbVoUudX1/wV4k0bS7d7mZLe3SfUNR0y3tIWnnljghWSZTLNIkabnZFoA88oAKACgAoAKAPTNK+Cvxk13TrPWNE+EvxM1jSNRgS60/VNK8B+KdR06/tZRmO5s7600qa2uoJByk0ErxsOVZuqgGh/wAM/wDx4/6In8XP/DbeMv8A5TUAH/DP/wAeP+iJ/Fz/AMNt4y/+U1AHG+KfAnjfwPLZweNfB3irwfPqEcsthD4p8Pav4flvooGRJ5bOPVrS0e5jheSNJXhV1jZ0VyCyCgDlaACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//1f4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD/Tt/4NGv+UUWo/8AZ0/xh/8AUb+GlAH9QdABQAUAFABQAUAFABQAUAFAH+MF/wAFUP8AlJ1/wUX/AOz6f2tP/V9ePqAPgygAoAKACgAoAKACgAoAKAP7zP8AgzT/AGuRc6R+1P8AsNeIdTzNpt1pX7THwvsZpdzvZX66P8Ovi3bw+Y26O3sryD4VX1raW+5Gn1bXLxo0dpZJQD+6SgAoA+Kv+CjX7Ltp+2l+wx+1F+zHNbQXWp/FX4R+JdN8Hfatgt7X4kaJDH4q+F+pTGTCiLSviJoXhjUpfmiYxWrhZYmYSIAf4tl5Z3en3d1YX9tPZX1jcT2d5Z3UUkF1aXdtK0NxbXMEqrLDPBMjxTRSKskciMjqGUhQCvQAUAFAHpfwY+FXiv47fF/4WfBPwLa/bfGnxe+Ingz4Z+E7Uq7pN4i8c+ItO8M6OsojBYQC/wBTgadxxHCskjEKpKgH+2v8E/hN4V+Avwc+FPwP8C2/2TwZ8H/hz4K+GXhWAokbp4f8DeHNO8M6SZhH8puJLLTIZbl/mMlw8sjMzuzsAenUAFAH+Xh/wdWftdD9oj/gppqvwf0HU/tngX9kTwLo3wktI7eXzbCf4i6+sfjn4oanDzmO/tbzV9A8B6tGVQJd/D/aFbDTSgH8z1ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB//9b+IegAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA/07f+DRr/lFFqP/AGdP8Yf/AFG/hpQB/UHQAUAFABQAUAFABQAUAFABQB/jBf8ABVD/AJSdf8FF/wDs+n9rT/1fXj6gD4MoAKACgAoAKACgAoAKACgD9P8A/gjR+11/wxH/AMFJ/wBln446lqf9l+B/+Fg2nw5+Kk0s3lWC/DH4qRSeA/FupakuQJrXwrba3D42hhZlH9peGLCUEtEooA/2MaACgAoA/wAib/gv3+yj/wAMif8ABVX9qDwdpumf2b4J+KPieP8AaF+HapF5FpL4b+M3neKdYttNgACQ6Z4e+IMnjfwjYwxZhig8OrHHtRQiAH40UAFABQB/TB/waofso/8ADQH/AAU90f4t61pv2zwX+yX8PPEnxbupbiHzdPl8fa/Cfh98ONNlOCU1CC78Ra7430lsoEuvAbSFmKLFKAf6iFABQB4r+0h8cfCn7M37P/xp/aG8cyBfCfwV+GPjX4ma3F5qwy39p4P8P32tDSbNmDbtR1me0i0nTIFV5bnUb21t4Y3llRGAP8Tb4qfEnxZ8Zfid8Rfi9481A6r44+Kfjrxb8RfGOpkMDqHijxrr1/4k169Cu8jKLnVNSupVQyOUVwu47QWAOCoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP/9f+IegAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA/o6/wCCV3/BxX8T/wDglx+zDdfsy+E/2ZvAfxc0m4+Jviz4lDxV4i8f+IfDGox3PivTfDenzaUdO03QdUtnhs/+EeWaK6FwryfamjeJfKDuAfpL/wARo/x0/wCjFvhN/wCHh8Yf/MhQAf8AEaP8dP8Aoxb4Tf8Ah4fGH/zIUAH/ABGj/HT/AKMW+E3/AIeHxh/8yFAH91v7OnxSuvjl+z58CfjXe6PB4evfjD8G/hh8UrvQLW7kv7XQ7r4g+CdD8WXGj219LDbS3sGmS6u9lDdy28ElzHAszwxM7IoB7JQAUAfy3f8ABa//AIOEviT/AMEpP2rfBP7Ofg79mvwP8YNM8V/APwn8Y5/E/iXx9r3hi/tL/wASePvif4Ol0SLTtL0DU7eS0tbfwBa3sd29wJpJtRniaJUhjZgD8f8A/iNH+On/AEYt8Jv/AA8PjD/5kKAD/iNH+On/AEYt8Jv/AA8PjD/5kKAD/iNH+On/AEYt8Jv/AA8PjD/5kKAP5Df2l/jXqH7Sf7Rvx9/aK1fQrLwvqvx6+NPxR+M2p+GtOu57/T/D1/8AE/xvrnja80OxvrqOG5vbPSrjW5LC2u7iKKa4ht0mljR3ZKAPEqACgAoA+zPhF/wTp/b4+Pmj23iT4M/sZftOfEfwvebPsnizwt8E/iFqHhK68xd6fZ/FK6Avh+bKEP8AutSbajK5+RlLAH1no/8AwQL/AOCwuu2UmoWX7B/xdggjj81o9YvvAfh29K+kem6/4w03UZZP+mMVo8vovUqAeY+M/wDgjP8A8FV/ANreXviH9gH9qGS0sIpJ7ufw18LPEHjhIoIRulm/4oq38Ql4o0BkeSLeqxq0jEIpegD87PE3hbxP4L1q+8NeMfDmveE/EemS+RqWgeJtI1DQda0+YdYb7StUtrS+tJR/zznt439uu0AwaACgAoA/2IP+CKv7XX/DbH/BM/8AZa+M2pap/anjrTvAdv8ACr4qSyzedqDfEn4TOfAviDU9V+Z/LvvF0Okad48Ee4j7F4qs3AQOI0AP1QoAKAP4if8Ag8r/AGUf7a+Gn7K37aug6buvfA3iXW/2ePiNewQ+ZPJ4d8ZW1946+Gtzduo3W+m6Dr+g+PrDzpC0Laj44sYPkmmjEoB/ALQAUAFAH+mH/wAGjn7KP/Cmf+CeHi39ovWtN+y+Kv2tvipqetafdyReTcTfCz4RS6l4A8G28quPOx/wmjfFTV7aQ7YbnTtZsLiFDGyTSgH9VtABQB/KH/wdzftd/wDCmP2A/BX7Mmgap9l8XftcfEq1stZtYpvLuW+Enwfn0nxr4tkUxkTRC78c3Pwv0t1O2G+0y71q0kLxiaFwD/NLoAKACgAoA+pfgr+w7+2Z+0hYf2v8Av2Uv2iPjHogID+Ifhx8HfH3i3w3ES2wLP4j0bQbrQ7di2Qom1CMttfGNjUAfaHhz/ggt/wWA8Uw+fpn7BnxntU2GTb4j/4Q/wAHTbQNxH2fxd4o0SfeR0jERkY/KE3/ACMAcn4q/wCCJX/BWjwckz6v+wB+0ndiBXZ/+EW8B3XjpiEBLeSngmbxC9wxA+VbcSs5wEDEqtAH52+P/hn8R/hR4hufCPxS+H/jf4a+K7PP2vwx4/8ACmu+DfENrtYo32nRfEVhpupQ7XUofNtlwwKnkGgDiKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP/0P4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAPpv9kP496V+zh8c/C3xF8TeCPDnxF8FHzNA8d+EvEfh/RvEKaj4R1ae1OqT6NDrdrcW9l4j0t7a21XRryJrVpbqyGmXdyul6jqEcv23h9xXQ4O4owOcY3LMHnGW64TNcvxmEw2LVbL686ft5YaOJhKFPGUHThiMNUi6blUpewqVFQrVoy/BfpK+DuY+OPhJxDwRkPFmecEcVLkznhDiXI85zTJZ4HiTLqOIWX0s0q5VXoV8VkmYRxFfLs0w1RV408Pi3j8NQlmOCwU4f28eCPhp+y98R/CHhvx74J+FnwX8Q+EvF2jWGv+HtasPh14Oe21DS9SgS4tp1DaIskUmx/LuLWdIrm0uEltbqGG5hliX/TTLMl4HznL8FmuWZFw3i8vzDDUsXhMTSyfLnCtQrQU4SX+zpxdnacJKM6c06dSMZxlE/5O+K+PfpA8D8S57wfxX4h+KmS8ScNZpjMmzrKsZxxxRDEYLMMDWlRxFKXLmk6dSHNHno16M6lDE0ZU8Rh6tSjUpzn1P/DP/wAB/wDoifwj/wDDbeDf/lNXd/qlwr/0TXD/AP4Zsu/+UHz/APxGfxg/6Ov4lf8Aid8U/wDzyD/hn/4D/wDRE/hH/wCG28G//Kaj/VLhX/omuH//AAzZd/8AKA/4jP4wf9HX8Sv/ABO+Kf8A55H873/BZ79gzS/BLWP7Vfwb8LWGi+E7k6b4d+Lvhjw3pltp2k6BqJ8rTvDfjiz03T4orOx0/Vz9m8PeIBBDbwR6yui3/lT3WuapcJ/IX0kPCuhljpcd8OYClhsBU9jg+IMDg6MKOHwlb3aODzSnQpQVOlRxPuYTFqKhCOJ+rVrSqYqvOP8Atl+y2+mFmHFkcX9HjxQ4hxma8R0Pr+eeGuf57j6+OzHOcD+8x2e8JYrH4yrUxWLxuWL2+dZM6069WplbzXB89HD5TgKEv55K/kQ/2sCgD+oP/gjn/wAE/wDQNO+H9x+0x8cPBej+INW+I+nfYvhb4W8W6JZatY6R4GklSWfxlcaVq1vcW/8Aafi6eCIaDO9sstr4YgF/aXEtt4odU/t/6O3hNhKOUz414ny3D4uvnFH2eRYHMMNTxFKhlcmpSzKdCvGUPb5hKKWFk4c0MDD2tOcoY1qP+AH7Tv6Zmc43jOh4DeEvFOZ5Nl/A+O+t+IXEPDea4vLcXmXF0Kc6dLhejmOW1qNf6hw1RrTecUY13TxGf1ng8TQpV+H4zq/tz/wz/wDAf/oifwj/APDbeDf/AJTV/TP+qXCv/RNcP/8Ahmy7/wCUH+UH/EZ/GD/o6/iV/wCJ3xT/APPIP+Gf/gP/ANET+Ef/AIbbwb/8pqP9UuFf+ia4f/8ADNl3/wAoD/iM/jB/0dfxK/8AE74p/wDnkeDftLT/ALJf7Lfwc8WfGP4g/Bz4RjS/D9r5Ok6ND8PfBMOp+LPE14ki6H4W0YSaI+/UNWuUIaQRyR6dp8N9q94EsNOu5U+V40lwBwNw7j+Is24c4f8AYYSHLh8NHKMtjXx+NqJrC4HDc1DWtiJrWVpKjRjVxFRKjRqSj+w+A9L6SH0g/E/hzww4L8UPEr+0M6xHtcyzSrxrxZUwHDmQYWUJZvxDmjhmkOXBZdQmnGnzxqY7G1cJlmFbxmNw8J/w9fFL4g6j8VviJ4w+I2q6V4f0G98X65eaw+h+FdIstB8OaLDOwSz0jRdKsIobe10/TbOOCytyyvdXCwfar+e6vp7i4l/zHz3Nq2fZxmOcV8PhMJUzDFVMQ8LgMPSwuDw0ZO1PD4ahSUYQpUaajTjvOaj7SrKdWU5y/wCszw94LwXh1wTwzwRl+Y51nGF4aynDZZHN+IszxWcZ5mtWlFyxOZZrmOMq1a2IxmOxU62KrJSjh6Mqv1fB0cPhKVHD0uBryT7EKACgAoAKACgAoAKAP9rb/gn7/wAmGfsSf9mi/s2/+qa8GUAfXVABQB/mmf8AB4n/AMpPvg7/ANmPfC7/ANXh+0fQB/KFQAUAFABQAUAf0n/8Egf+DcL9oL/go3oml/Hb406/q/7NH7Kl68E/h3xPdeHhf/Ev4yWfmZuJvhj4d1WW0s9M8LNErRR/EnxFHd6PPdSw/wDCN+H/ABlDBqj6aAf33/sY/wDBH7/gnl+wh4f0nTvgZ+zh4GufGGneRNc/GL4l6PpXxH+Muq6hEoV9Qk8eeI7Ce88P+eyLNJo3gi38K+GI51E1poVtIN1AH6ZUAFABQB4H+0F+yz+zj+1b4Mvvh/8AtH/BP4b/ABm8J31rLaHTvHnhbTNauNPWU7vtOgaxNb/234a1OGT99aav4d1HS9VsrgC4s7yCZVkUA/h0/wCCvn/BqldfCfwnr/7Qn/BM4eNfH3h/RFvtY8bfst+IdQfxV430nRYlM8t/8FNfkgXW/G0GmQLIZvAXiWbVvHF5BE8ugeIfFeqzW/h6gD+Jy4t57See1uoJra6tppLe5triN4Z7eeFzHNBPDIFkimikVo5I5FV0dSrAMCKAIaAP7kv+DNX9rv8As7xV+1J+w14i1TbbeJNO0r9pP4X2M03lwrrOhnSvh/8AFi1txISs9/qukXfwx1C3tYNkq2PhfWrtkmijle3AP73qACgD87P+Cs/7KQ/bV/4J1ftX/s9Wem/2p4q8UfCvV/EXw4tVi8y4k+KXw7lt/iD8Oba2kUGW3bVfF/hnSdEu5oMyHTdTvoDHNDNLbzgH+NGQQSCCCCQQRggjggg8gg9Qf6UAJQB1ngLwR4l+JnjnwX8N/BmnS6x4w+IPizw54I8KaRD/AK7VfEvivWLPQdC06LAJ82+1S/tbaPAPzyjg9KAP9s79l/4EeGv2Xv2cvgZ+zp4QEbeHfgn8KvA3w00+6jhEDaofCPh6w0e81y5Qcm/16/tbrWtRlcmS4v7+5nlZpJGZgD3agAoA/wArX/g5+/a6/wCGnP8AgqX8RvBGiap9u8Bfso+HtI/Z70BIJt1k/i3RpbnxF8V74wAlYtUtfH+vap4L1CTJee38EaaHCiFEQA/nZoAKAP3D/wCCR/8AwQo/ad/4Ko6zL4wsblvgb+y/oV/LY+I/j/4p8PXWq2+u6naSiK78LfCrwybzR38e+IbZw6avepqum+F/DIjlj1jXBrDWGgakAf6Dv7DH/BB3/gm5+wholg3g34FeH/jF8Too7eTUfjV+0BpWg/E7x5NfwYb7V4cttW0lfCXw/jSXzBAvgXw5oN/JaskGr6nrEsZunAP2Mhhit4ooIIo4YII0hhhhRY4oYo1CRxRRoAkccaKERFAVVUKoAGKAJKACgDzX4q/Br4R/HTwlf+AvjT8MfAPxZ8FapBPb3/hX4i+EtC8Y6DcR3MRhmzpmv2GoWqStGcLPFEk8ZCvHIrojKAfxw/8ABVj/AINOvhl4g8JeKvjV/wAEyv7U8GfEbTRc63e/sveKPEz6n4C8Y2iJLcXmn/CvxZ4lll1vwb4okfc2m6D4u8Qat4R1KR4tNs9S8FWsEZnAP4G/GHg7xZ8PfFXiLwL478Na74N8aeEdY1Dw94p8KeJ9KvdD8ReHdd0q5ks9T0fWtH1KG3v9N1KwuopLe7s7uCKeCZGSSNWGKAOboAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP//R/iHoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP3o/4I0/t5f8ACsPFlt+yr8VNa8r4eePNXZ/hZrOoz/6P4O8e6pN+88MySysBbaB43unH2JFYQWHi6RHEIXxJqd7b/wBU/Ry8VP7EzCnwJnuJ5cnzXEN5HiK0vcy7Na8tcE5SaUMJmdR/u0ny0swknyL65Xqw/wAe/wBqH9D/AP4iBw5X+kP4e5X7Tjbg/LYx8QsswVH9/wAT8H5fS9zPoU6Sbr5xwlhoP61KUXVxnDUJxda+RYDCV/6sK/u8/wCdsKAOc8X+EvDnj7wr4i8E+MNItNf8K+LNG1Hw/wCIdFv0Mlpqekaray2d9ZzKCrhZreZ1EkTpNE+2WGSOVEdePMMvwea4DGZZmOHp4vA4/DVsJi8NVV6dbD14OnVpyWjtKEmrpqUXaUXGSTPc4Z4kzzg7iHJOK+GcyxOT8Q8OZpgc6yXNMHPkxOAzLLsRTxWDxNJtSi5Uq1KEnCcZU6kb06sJU5ThL+Er9uD9k7xJ+x58evEnwx1L7Xf+Er0v4j+Gnie4jwviPwRqFxMunPNKiJCda0aSObRPEEKJDt1Oylu4IE06+sJZ/wDLXxO4Cxnh3xVjMkre0q4CpfGZLjpr/fMsqzkqLlJWj9Zw8oyw2LioxtXpSqRj7GpRnL/r0+ib9I3I/pN+D2R8fYH6tg+I8Ko5Jx3kFGd3kfFeCo0njYUqcpSqLK80pzp5tktSc6reAxdPDVqssbhMbCl61/wTQ/Ysu/2wfjtaQ+IrK5Hwa+G0lh4k+J+oKJYodUiM7tongW2uYyjJfeLbm1niu3ikims/D1nrd7DMl7FYpP8AQeC3htU8Q+KacMZTmuHMmdLG55WV1GvHmbw2VwmrNVcwnCUajjKMqeDpYqrGSqxpRn+b/Tx+lPhvoy+EOJq5Ji6L8UOOoY3IuAMG/Z1KmX1FRjHNuLq9CanGWE4boYmjUw0akJ0sVnWKyrCVaVTCTxs6H9utnZ2mnWdrp+n2ttY2FjbQWdjZWcEVtaWdpaxLBbWtrbQqkNvbW8KJFBBEiRRRIscaqiqK/wBM6dOnRp06NGnClSpQjTpUqcVCnTpwiowpwhFKMYQilGMYpKMUkkkrH/J9isVicdicRjcbiK+LxmLr1sVi8Vias6+JxOJxFSVWviMRXqylVrV61WcqlWrUlKdSpKU5ycpNys1ZgUtR1HT9H0+/1fVr600zStLsrrUdT1K/uIrSx0/T7GCS5vL69up3jgtrS0t4pJ7m4mdIoYY3kkdUVmrOtWo4ajVxGIq06FChTqVq9arONOlRo0oOdSrUqSajCnThFznOTUYxTbaSbOrA4HG5njcHluXYTE4/MMwxWHwOAwODo1MTi8bjcXWhQwuEwuHoxlVr4nE16lOjQo0oyqVas404RcpJS/id/wCCmP7cuoftifGN7LwveXdv8DvhvdX2k/DnTG823XX7kv5Gq/EDU7Vwj/btfMKpo8FyiS6R4ejtLbyLfUbzW3uv80vGnxPreInETp4GpUhwxk06tDJqD5oLFzvyV82r03Z+1xfKlh4TXNh8HGlBxhWqYlz/AOrL6Bv0ScF9GPwwhiuIMLhq3i1xzQwmY8cY+Ps60smoKPtsu4My/ERc4/VMmVRzzOth5zp5lnc8TXVavgsLlaw/5rV+MH92BQAUAFABQAUAFABQAUAf7W3/AAT9/wCTDP2JP+zRf2bf/VNeDKAPrqgAoA/zTP8Ag8T/AOUn3wd/7Me+F3/q8P2j6AP5QqACgAoAKAP6sv8Ag2w/4Ipwftu/EtP2xv2mvB8eofsl/B7xC1t4O8HeIbETaT+0D8VNJeOQ6XeWNyhi1b4YeAp2hu/GHnJJpXijxCLDwS6arp9v44sbAA/0trS0tdPtbawsba3srGyt4bSzs7SGO2tbS1to1ht7a2t4VWGC3ghRIoYYlWOKNFjjUIoCgFigDyz4v/HH4Mfs+eD7j4g/Hf4s/Dj4NeBrWZbWbxd8UPGnh3wL4e+2SRySw2EWreJdR02zuNRuUhlNpp1vLLe3bIUtreZ/kYA/N22/4L0/8Ef7zXU8Oxft5/BhNQeZLcXFyPGFloQd5PKDP4ovPC0HhmOENy9zJrC28cf76SVIRvoA/Tz4cfE/4a/GPwfpPxC+EfxB8E/FHwDr0ckuh+Nvh34q0Pxp4T1iOJzFK2meIvDl9qOkXwhlVopvs13J5UqtHJtdSKAO5oAKAP8AOy/4OtP+CUHh34AfETSP+CiXwN0WPSPh78ffGzeGPj94S02z8vTvDHxs1Wwv9Z074hafFbJ5VppXxTtdK1h/E8ckdvBa+PrB9TN1eXnjtLSwAP43KAP0H/4JVftayfsPf8FBv2W/2kbi/k0/wt4N+Jul6P8AEmRXYRv8KfHcVx4F+JbSwg+XdPY+DPEWsatp8E/7tdW07T7gNFNBHNEAf7M0UsU8Uc0MiTQzIksUsTrJFLFIoeOSORSVdHUhkdSVZSCCQQaAH0AFAH+O/wD8Frv2Uf8AhjX/AIKc/tY/B/T9N/s3wZqHxFvPip8NYoofJ09Ph98X4YviHoOm6VwoksfCr69e+Cd+Mi88MXcRaRomkYA/K+gD+hr/AINhv2Uf+Gl/+Cq/ws8V6vpv27wT+y34d8Q/tE+IWmizanxB4c+x+GvhhAtwymOPUrT4j+KPDniuygGZp7bwnqLxKEt5pogD/VWoAKAPnH9sD9orw5+yP+y38fv2mPFXkSaR8E/hV4x8fiwuJfJXXNY0TR7mXw34ZikBXF54q8RtpXhywG9N97qlunmR7t6gH+KH418YeI/iH4x8W+P/ABjqlxrfi7xz4m17xh4p1q7IN1q/iPxNqt1rWuapckcG4v8AU725u5iODJKxHWgDmaAP3l/4IMf8Ef8AX/8AgqH+0iNb+IOn6ppX7IfwP1TStY+N3iWE3Fg3jbU2YX2h/BbwvqMRim/trxXHF5/irUdPmSfwl4L+1X5urLXNY8JRakAf6sfgnwR4O+GvhHw34A+HvhbQPBHgfwfo9j4e8KeEfCuk2OheHPDmh6ZAttp+k6No+mw29hp1hZwIsUFtawRRRqOEGTQB1FAHIePPiF4B+FnhTWPHnxO8b+EPhx4G8PQC61/xn488S6N4Q8KaJatIkS3Or+IvEF7p+kabA0rpGJry8gjMjogbcyigD8vNX/4Lzf8ABIHRNdk8OXv7efwVm1CKeS2a40iTxZ4g0IyRPsZo/FOg+GNS8MTQE8x3UWrtbTJ+8hldDvoA/RL4KftB/Ar9pLwenxA/Z9+MXw0+NXgppxZv4n+F/jXw9430e1vxEk76ZqN34fv7+PTNWhilRrnSdQ+zalabttzbRPlVAPYKACgD+KD/AIOv/wDglB4d8X/De6/4KefBrRY9O+IXw+Xwx4Y/ac0XTbPEfjnwHd3lj4V8I/FB47ZC7eKPAt9eaN4Y8RXTxS/2n4GutMvru6sbbwHt1AA/z7qACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD/0v4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgByO8TpJG7RyRsrxyIxR0dDuV0ZcMrKwDKynIIyMEU02mmm000007NNapprVNPZr9CZwjUjKE4xnCcXCcJpSjOMlaUZRd1KMk2mmrNOzvqf2Vf8Eov270/am+Ff8AwrX4h6us3x3+FOl2lvrM93MPtnj/AMHRNFY6V44j3kSXOqWrtb6R4xK+YRqr2OsyvGPEUVra/wCjPgN4prjrIv7FzfEKXFOQ0KcMTKpL95m2XRcaVDM1eXNOvBuGHzGyl+/dLEtx+uRhS/5e/wBot9EGX0e/EP8A184Ky2VPwh8RcwxNbK6WHpP6twbxRUVTF5hwnPk5oUMvxEI1sy4Y5vZJ5fHGZXThUeR1MTiP1sr9+P8AN0KAPgX/AIKJfsYab+2Z8C7vw3psen2XxY8FSXPiP4U6/fEQRRawYo01PwxqN4EaSHQvFtpBFZXbcxWep22i6zLHOulfZ5fyjxf8N6PiPwvUwdFUqef5a54zIcXVahGOIcUq+BrVLNxwuYU4RpVHpGnXhhcTLmVBwn/Y/wBCX6UuP+i54uYbPcfPG4rw54qhQyPxEybCp1qlTLFVnLAZ/gcM5RhVzfhvE1amKw0bKeKwFfNcrp1KMsxVel6n+xv+y54U/ZD+BPhX4SeHvs19q8Mf9t+PfE0MRjk8W+OdRggGtaw29VlWxh8iDStDtpR5lnoWnadbzNLcpcXE/u+HPA2A8PuFsDkGE5KuIivrOa42MeWWPzStCP1nEO/veyjyRoYWElenhaNGEnOanOX579KD6QXEX0lfF7iHxIzr2+EyyrP+yeDsgqVOenw3wlga1Z5Vli5ZSpyxdX2tXMc3r07QxOb43HVqShh5UaNL6nr7o/noKAP5uv8AgtD+3t5KX/7Hfwl1r97KtvL8dfEOmXHMcTCO6sPhjbXMTfemUw6j41ELDEJ0/wANyyv5viTTU/jX6SHityqr4d5BidWoS4pxdGVrRdp0skhOL3kuWtmXL9n2WCk3zY2if7nfstPod+0ng/pOeJGVfu6cq0PCLJcfR+OpFzw+M4+r4eopLlpNVcDwq6q1qfXc9p0oeyyPGy/msr+MT/doKACgAoAKACgAoAKACgAoA/2tv+Cfv/Jhn7En/Zov7Nv/AKprwZQB9dUAFAH+aZ/weJ/8pPvg7/2Y98Lv/V4ftH0AfyhUAFABQB6t8Cfg142/aJ+NPwo+Avw3s4r/AMe/GT4h+EPhr4RtriQw2Z17xlrtloOnTahcBJPsmmWlxfLd6nespjsrCC5u5cRwuVAP9pH9kn9mnwD+x1+zT8Ff2YvhjAI/BnwX8A6L4M0+7a3jtbrXtQtIjc+JPFupwwlol1rxn4mutY8Wa4Yj5b6xrN9JHhGUKAfRNAHzT+2N+1H8Pf2Kv2YPjX+1N8UXd/BvwY8Eaj4qutNguIrW98S6y0kGleEvBul3M6vBBrPjbxbqOh+EtGluFa3j1PWbV7nbAruoB/j6/t2/t7/tHf8ABRH47+Ivjv8AtF+Nb/XtSvry+h8GeC7a6uY/A3ws8JTXbzad4J8A6C0htdJ0fToPJiubzZJrPiK9il1zxLqGq63eXd/OAfF9AH6/f8EZP+CpXxQ/4Jk/tY+B/FNv4p1iT9m74heKND8NftIfDSS7uJ/DeteCtRuY9LufHVppGJoYfHPw7t7t/Evh3VLGK11K/j0+68KXV8uha/qcDgH+vZbXNveW1veWc8N1aXcMVza3VvKk1vc286LLBPBNGWjlhmjdZIpY2ZJEYMpKkGgCagD4i/4KR/st6H+2h+wt+0/+zdrOkprF58Q/hL4oXwXEVVpbH4neHLNvFXwu1i2JVmE2k/EHRfDl8UTabmCGaydhDcyBgD/FtIKkqwKspIZSMEEcEEHBBB4II49qAEoA/wBeX/ggl+11/wANl/8ABLb9mbx7qmp/2n49+G3hpv2f/ifJJN9ovR4w+Dsdr4Zsr/VJyS0uqeKvAy+DPG987BWabxQSVGaAP2LoAKAP4Q/+DzH9lHbL+yb+23oem8SLr37M3xJ1GOLA3p/avxL+EgkeMcs6t8XYZ5p+dsWmW8bkBEUA/hLoA/0ff+DPn9lH/hWf7Ffxj/au1zTPI8QftOfFIeGvCl5LFuaf4W/BFNR0G1u7KZ1DQpqPxK174jafqMMH7q4PhjS5JpJZII47UA/rzoAKAP5B/wDg8D/a6/4Vh+xn8IP2RfD+p+R4j/af+I//AAlHjK0hl3O/wo+Csmma7JZ30SMrwJrPxM1fwBfaZNNmO6HhHWYIo5Ghme3AP84egC1Y2V5qV7aadp9tPe3+oXVvZWNnaxPNc3d5dSpBbW1vDGGklnnmkSKGJFZ5JHVVBYgUAf7Hn/BI39hLS/8AgnT+wX8Ef2cfstkvxAg0b/hPfjdqtmYZBrfxo8cQ2up+NpDeQYj1G08Nsmn+A9A1AKjXXhfwloTyIJd9AH6VUAch8QfHvhL4V+AvG3xO8fa1aeG/Avw58JeI/HXjTxFfllsdB8KeEtHvNf8AEOsXZQM4ttM0nT7u8n2Kz+XC21WYqtAH+Qt/wVi/4KvfHr/gqR+0Dr/jjxpruu+HfgT4b1zUrf4D/AuPUGTwz8P/AAosjW1hqmqWFq62Ot/EbXrJEvvF3iu7F3eSXlxJo2kT2XhbTtH0myAPynoA+2f2Af29vj1/wTo/aN8G/tC/AnxJqFlPpOo6db+P/Aj6jPbeE/i14CW+hm13wB4zsVWe2u9N1a0WZNP1J7SfUfDOrmz8RaFJa6vp1rcIAf7I/wAEvi74N+P/AMHPhX8c/h5etqHgT4w/Dzwd8S/CN3IFWeTw9420Cw8RaUt3ErOLe+htNQigv7VmMlpeRz20uJInVQD1CgDz34tfC7wV8b/hb8Rvg38SNIi1/wCH/wAVfBHij4eeNNGlwF1Lwx4w0W90HW7RZCr+TNLp9/OLe5VTJbT+XcRYkiRlAP8AEk+Ofwr1r4FfGz4wfBLxJv8A+Eh+D3xR8f8Awt13zI/Kc6x4A8V6t4U1Jmj42FrzSZm2jgZ4yMGgDyygAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//T/iHoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD1n4GfGnx1+zz8VPB3xf+HGpHTvFPg7VI763WQyGw1WxkU2+q6BrEETxtdaNrmnS3OmalbiSORra4d7ea3uo4LiL3+F+Jc04Rz3LuIcmrexx2XV1Vgnf2WIpP3MRhMRFNOphsVRlOjWgnGThNuE4TUJw/OPFvwr4R8avDzifw044wKxvD/E+XzwlaUFBYzLsXBqtl2c5ZVnCpHD5plGOp0MfgKzhOEa9CMK1Oth51qM/wC8P9mX9ojwL+1L8GvCXxj8AXAGneILXyNZ0WWeObUvCXiiySJNd8K6uECbb7SrqQeVMYoo9S02ew1i0Q2Go2jt/qdwTxhlfHXDmA4iymdqOLhyYnDSmpVsvx1NJYrA4iyVqtCb92XLFVqM6WJpp0q1Nn/ID49+CXF30e/FDiTww4yot43JsR7bK81p0p0sDxHw/ipVJZRxDljm5KWEzChB+0pqpUngcdSxuWYiaxmCxEI++V9WfjgUAFABQB+cX/BSj9uLTP2N/g1KPDt1Z3Xxt+Ilvf6P8M9HkENydI2xrFqnj3VbSTKHS/DSzxmwguEki1fX5tPsGgmsE1aay/HPGfxOoeHXDklg6lOfE2cQq4fJMO7T+r2SjXzWvBu3sMEpr2UZxksRi5UaXJKisRKl/cf0E/ol4/6T/ijTed4fFYfwp4IrYPM+Pczh7Sj/AGlzTdTL+D8vxEHCSzDPZUaixlajUp1MsyaljcYqtLGTy2niv4k9V1XU9d1TUtb1rULzVtY1i/vNU1bVNRuZbzUNS1LULiW7vr++u52ee6vLy6lluLm4md5ZppJJJGZ2Jr/M+vXrYqvWxOJq1K+IxNWpXxFetOVSrWrVpupVq1akm5TqVKkpTnOTcpSk2222z/q5y7L8BlGX4HKsrweGy7LMsweGy/LsvwVGnhsHgcBgqNPDYTB4TD0owpUMNhsPSp0aFGlCFOlShGnCMYxiihWR2BQAUAFABQAUAFABQAUAFAH+1t/wT9/5MM/Yk/7NF/Zt/wDVNeDKAPrqgAoA/wA0z/g8T/5SffB3/sx74Xf+rw/aPoA/lCoAKACgD+jz/g1c/Z9g+Nn/AAVp8A+L9RtorrR/2bfhX8TvjndQXAUwTaothp/wp8MDDctdad4i+KOneIrIIQ63GhLPykDqwB/qaUAFAH4u/wDBd/8AYR/ac/4KN/sR6d+zL+y74l+GvhjxFrHxt8CeLviBP8U/EviLwx4d1X4deEdF8Y3zaRBdeGvB/jO8u9TPjyXwHq0Fpcafa2nkaRc3DXizwW8E4B/G1/xB+f8ABUn/AKKN+xl/4df4q/8Azh6AD/iD8/4Kk/8ARRv2Mv8Aw6/xV/8AnD0AH/EH5/wVJ/6KN+xl/wCHX+Kv/wA4egD/AEUf2XPA/j74Y/sy/s6/Db4rajpWr/FH4e/Ar4R+B/iTq2g313qeh6p4+8J/D/w9oPjHUdG1LUNP0m/1DSr7xDYajc6dfXulabd3dpLDPc6fZTSPboAe7UAFAH+KD+3v4G0/4Yft0ftn/DbSLKPTdJ+H/wC1f+0T4K0rT4V2w2Wl+Fvi94w0TT7WBecQQWdjBHDgkGJVILAg0AfJtAH9q3/Bm/8Atdf8It8a/wBpP9ibxFqnl6V8WPCenfHT4a2lzNsgj8cfDt4PDfjzTdOi3fvdU8UeC9b0PWLgFPl034aTOJF2FHAP9BqgAoA/Kb/gtv8Aso/8Nk/8Ewv2sPhJp2m/2l400f4eXXxb+GsUUPnag/j74PSx/EHR9M0kYYJqHiy00LUvA6sRg23ii6jLRhzIoB/j+6Foer+J9c0bw14f0+61fXvEOq6doeiaTZRma81PV9WvIbDTdPtIhgy3V7e3EFtBGDl5ZEUYzQB/tbfsQ/s26R+x9+yH+zl+zJoy2rRfBf4R+DfBWq3lmoWDWfFllpMM/jbxGFAAEnifxjc674hnwFUz6nKQqghaAPqWgAoA/wAnn/g5L/a7/wCGsP8Agqr8brTR9U/tDwD+zZDp37M/goRTb7YXPw6udRn+JNyqITbtPL8Wda8c2S3kW57vStN0cPIyQQpEAfgrQB+p3/BEr9n2D9pv/gqr+xL8Lb+2iu9Eh+M2l/E3xJa3AU2l74c+COmap8Zda0y8D8Na61ZeBJNElj4ab+0RDGQ8isoB/sRUAFAH57f8FV/2cvjn+13/AME/f2k/2aP2cNd8H+G/i38ZfC3h/wAGaNrHj7W9Y8PeE4PD15478KXHxCtNW1TQfD3inVIU1f4d2virRreK30W6W6u9Qgtrh7a2lluEAP4Qf+IPz/gqT/0Ub9jL/wAOv8Vf/nD0AH/EH5/wVJ/6KN+xl/4df4q//OHoAP8AiD8/4Kk/9FG/Yy/8Ov8AFX/5w9AH93P/AASh/Zm+M/7G/wDwT4/Zs/Zj/aC1rwh4g+K/wd8OeK/C+v6r4C1nVtf8JTaU3xH8Zar4Jt9H1bXNA8L6pcx6d4E1Hw1p1ylzodkLS+tLqzgN1bW8N7cAH6HUAFAH+Rf/AMHDfgbT/h7/AMFlv25dC0uyjsLTUvHngXxy0US7Y5dQ+Jnwb+HHxF1m97hpL/WvFOoXtwwPNzPNna25VAPxfoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA//9T+IegAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD9Lv8AgmT+3He/se/GWPT/ABVe3MvwO+Jl1YaP8RdP/ezx+HbsP5GkfEHTrZNzi60Bpmi1uG2R5NU8OS3kQtrvUbHRPs/7T4KeJ9Xw84jVHH1Zy4YzqpSw+cUvemsHUvyYfN6ME7qphHJxxUYJyr4OVSKhUrUsMofwf9Pb6JWF+k14XTxnDuEw9Pxa4DoYzM+CMY/Z0Z53hnH2uZ8F43EScIvD5wqUamU1K8408vzylhqjr4XA4zNXiP7ZopY54o5oZElhmjSWKWNgySRyKHSRGGQyOpDKwOCCCM5Ff6XRlGUVKLUoySlGSd1KLV001dNNapp/fc/5SqlOdKpOlVhKnUpTlTqU5pxnCcJOM4Ti7OMoyTjJNXTTTtqSUyAoA89+LPxK0D4OfDLx58VfFMWoz+Hvh94W1nxZq9vpFlJqGp3Flo1lLeS29lax/fuJ/LESSTPDaW+/7TfXNtZxXFxF5Gf51hOHMkzXPsdGtLB5RgcTj8RDD03Vrzp4anKo4UoLec7cqcnGnC/PVnCnGc4/a+HHAmc+J/HvB/h3w9UwNHO+NOIcr4cyytmWKp4PAUcVmmKp4WnWxeIqfDRo+0dSUKUauJrcvsMJQr4qrRoT/gr/AGn/ANo7x3+1V8ZfFfxi8fTlb3W7gWmg6FFO82m+EfCli8q6F4W0kOqAWmm28jPcXCxRPqeq3Go6xdR/bdRuWr/KvjfjHNOO+I8fxFm07VcTP2eFwsZOVHL8BScvquBw97fu6MJNzmoxdevOtiZr2tacpf8AYZ4A+B/CH0ePC7h3wx4NoqWFymj9YzjN6lGFLHcS8RYqFN5vxDmXK5t4nHVqcY0KLq1YYDL6GCyzDzeFwWHR8+18kfs4UAFABQAUAFABQAUAFABQAUAf7W3/AAT9/wCTDP2JP+zRf2bf/VNeDKAPrqgAoA/zTP8Ag8T/AOUn3wd/7Me+F3/q8P2j6AP5QqACgAoA/s9/4MwvC32v9qH9s7xr5eT4f+Angbwt5uOU/wCEw+If9reXnqPM/wCEGDEd/KGegoA/0M6ACgAoAKACgAoAKACgAoA/xt/+Cx1pb2X/AAVW/wCChENtGI43/a1+Nd2yjobi/wDG2qX11J9Zbq4mlb/ac0AfmvQB9qf8E5/2qr/9iX9uL9mT9qC1nuodO+FPxV8P6j4yisxIbnUPhrrbS+FvihpECR7mafV/h5rniXTbcFJVW4uopDDLs8tgD/aQ07UbDWNPsNW0q8ttR0vVLO11HTdQspo7mzvrC9gS5s7y0uIi0U9tdW8sc8E0bNHLE6yISrA0AXKAEZVZSrAMrAqysAVZSMEEHIIIyCCMEcHNAH+bf+xH/wAEpT4V/wCDm/xX+zfc+HCvwh/ZQ+LXiz9rSwtTalrK2+FGlf2R8Rf2eIVLJ9ku47bxV49+EWg6mq/uHks9Zt/KWS2ltVAP9JGgAoA+Rv29v2n9I/Yv/Yz/AGkv2odXe1B+Dnwp8T+JfD9relRa6v46nthovw58PTFiFC+JfH2q+G/D4J3YbUgQjkbGAP8AFc1zW9X8Ta1rHiPX9RutX17xBqmoa3rerX0rT3uqavqt3Lf6lqN5O3zTXV7eXE1zcSt80k0rueSaAMugD+k//g1D8Lf8JB/wV58Eat5e/wD4Qb4GfG/xSGxnyvtfh+x8FeYPQkeMPKyO0uO9AH+pDQAUAFABQAUAFABQAUAFAH+VL/wdH2lvbf8ABZj9oaaGMJJf+BvgBd3TDrLcJ8FPBVisje4tbK2i/wB2Me9AH89NABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH//1f4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP24/wCCP/7BH/C9vHcP7RXxT0XzvhB8NNZT/hE9I1G33WfxD+IGnOk8IkglG298L+EJfJvdV3j7Hqmt/YdFb7baW3iGzi/pj6PXhV/rTmseMM9w3Nw9kuJX1DD1ofu83zai1KKcZK1XA5dLlq17v2dfE+ywz9rCGMpR/wAof2mX0xP+IQ8IVPBLw9zX2XiZx3lcv9Y8ywNa2J4K4MxsZ0arhVptSwnEHE1P2uFy7ll9Zy/Kfrmar6ria+SYmf8AXBX+gB/zahQAUAVryztNRtLrT9Qtbe+sL62ns72yvII7m0vLS5iaG5tbq2mV4bi3uIXeKeCVHjlido5FZGIqKlOnWp1KVWnCrSqwlTq0qkYzp1Kc4uM6dSEk4zhOLcZRknGUW0002jfC4rE4LE4fGYPEV8JjMJXpYrC4rDVZ0MThsTQqRq0MRh69KUatGvRqwjUpVacozp1IxnCSkk4/xUf8FPf2Gbv9kH4xNrXhDT7h/gX8Try+1TwBeKJJofC2phvtOr/Dy/uWLus2j+b9q8PS3LNJqXhySAfaL7UdK1uS3/zW8bvC+p4e8RPE5fSm+F87qVa+U1LSlHA1r8+IyirNtvmw/Nz4SU/erYOUffqVqGJkf9VP0A/pb4b6S/hjHKuJsZQj4ucA4bCZfxlhm6dKpxBgGvYZZxrg6EVCMqeZqH1fOqdCKp4DPIVX7HC4LMcqhX/MevxM/vgKACgAoAKACgAoAKACgAoAKAP9rb/gn7/yYZ+xJ/2aL+zb/wCqa8GUAfXVABQB/mmf8Hif/KT74O/9mPfC7/1eH7R9AH8oVABQAUAf2Yf8GY3iv7H+1j+2J4G83H/CRfs7+FPFfk7v9Z/whnxJ07SPN29/K/4TzZu/h87H8VAH+iBQAUAfmH/wVq/4KQf8Os/2XNM/acm+CV/8eNNuPix4S+Gmr+FtO8dwfD2bRbLxXoni3UIPFMms3HhLxlHdQ22q+HdN0Q6X/Zts00mvxXY1CL7CbW7AP5qf+I1Twb/0ju8Tf+JO6X/84ugA/wCI1Twb/wBI7vE3/iTul/8Azi6AD/iNU8G/9I7vE3/iTul//OLoAP8AiNU8G/8ASO7xN/4k7pf/AM4ugA/4jVPBv/SO7xN/4k7pf/zi6AD/AIjVPBv/AEju8Tf+JO6X/wDOLoA/i+/bS/aIh/a3/a0/aI/abtvCcvgS3+Ovxb8Z/E2DwbPrSeI5vDUPivWLnU4tHm11NM0VNVlskmWKS9TSrBJ3UstrEMLQB8xUAFAH+tT/AMG6v7XX/DXf/BKr9n7UNW1P+0vHvwEtrz9mj4gGSbzrlL74UW2nWvgm5upXY3Fxc6p8J9T+H+p315cDzLnVbrUS0kzo8rgH7j0AFAHgGhfs0/Crw7+0z8RP2tNN0TyvjD8TvhD8Nvgr4k1j9yID4P8Ahn4m8e+KdLa2jSBJl1PWLvxzFZ69dz3E4vNN8HeDbWGO2GkubgA9/oAKAP4zP+Dxf9rv/hCP2bv2ff2MPDup+Vrfx18dXnxa+IdrbTYmT4c/ChY7PwzpeqQZGbDxR8Qdftta0+QK5N98M5xmIIRKAf54VABQB/SF/wAGpniv/hHf+CwHw30fzfL/AOE8+DPxz8Kbd2PO+x+Dj458rH8WP+EM87b/ANMt38NAH+pdQAUAfGv/AAUG/a1n/YT/AGOvjd+1pD8NLr4wD4LaL4f8QXfw8svE8fg2513TNU8a+GfC+rzx+JJdA8Tx6aNB0vXbzxHJv0O9F5FpD2G60N0L21AP5N/+I1Twb/0ju8Tf+JO6X/8AOLoAP+I1Twb/ANI7vE3/AIk7pf8A84ugA/4jVPBv/SO7xN/4k7pf/wA4ugA/4jVPBv8A0ju8Tf8AiTul/wDzi6AD/iNU8G/9I7vE3/iTul//ADi6AD/iNU8G/wDSO7xN/wCJO6X/APOLoA/k6/4Kr/t52f8AwUo/bT+IX7Wun/DG6+EFp438PfD7QYfAt54ui8b3Onf8IP4L0fwpJdSeIYPDvhaK5/tKXS3vUhXR4fsscywGWdlaRwD85qACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP/9b+IegAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAPrf9iv8AZM8Yfti/G/Qvhh4fNzpnhu18vXPiN4vSDzYPCXg21uIkvrtS4MMus6k7ppfh2wfP2vVbmKScR6ba6ld2n3/htwDmHiJxPhckwnPRwULYrOMxUOaGX5bTmlVqK/uyxNZtUMHSf8SvNOfLRhWqUv5u+lR9I7hn6MXhPm/H+dewx+e1+fKeCOGZ1eStxJxRiKM5YTCyUJRq08rwMYSzDO8ZD/dcvoVIUnPHYnBYfEf3WfDj4d+D/hL4E8K/DbwBott4e8HeDNGtNC0DSbUHZbWVomPMmlbMt1fXkzS3upX9w0l3qOoXF1fXks11cSyN/qNk2T5dkGV4DJcpw0MJl2W4anhcJh6e0KdNbyk/eqVaknKrWrTbqVq051akpTnKUv8AkS44424m8R+L+IeOuMs0r51xPxTmmJzfOcyxD96visTK/JSppRp4fCYalGnhcDg6MYYfBYKhQwmGpww9CnCPa16Z8qFABQAUAeE/tJ/s+eBP2oPg74u+DfxBts6T4ks9+mavDDHLqfhXxJZrJJofinRmkK+XqOkXbCTy98cWoWMl7pN6X0/UbuJ/luM+Ecr444dzDhzNoXw+Mp3oYiMYuvgMbTvLC47DN7VsPUd7XUa1KVXD1OajWqQl+veBXjRxf9H/AMTuGvE/gyvbMcjxPJj8tqVZ08BxDkWJcIZvw9mihzc+BzPDRcOfknUweLhhcxwvJjcFhq1L+Dz48/BDx3+zp8V/GHwf+I2n/YfE3hDU3tHniWT+z9a0yUCfSPEWjTSJG1zo+uafJBqFhKVWVIp/s11FBewXNvF/ljxVwzmnB+fZjw9nFH2WNy+s6blFS9jiaMvew+Mw0pWc8PiqLjWpSspKMuSpGFWM4Q/6/vB7xY4Q8b/DnhjxN4Hxv1vIeJsBHExpVHD67lWPpP2OZ5JmlKE5rD5nlONhWwWMpqUqcp0vb4apWwtbD15+QV88fpgUAFABQAUAFABQAUAFABQB/tbf8E/f+TDP2JP+zRf2bf8A1TXgygD66oAKAP8ANM/4PE/+Un3wd/7Me+F3/q8P2j6AP5QqACgAoA/oQ/4Nhf2j4v2fP+Ct3wc0XUruOy8OftHeEPHn7O2uXErKEW68UWVl4z8DwIr4DXGp/ErwD4M0SEqRIo1WTbuDNG4B/qwUAFAHwN/wU/8A2MbL/goB+wp+0P8Asss+m2viXx/4Ma++G2r6szw2Oh/FXwffWni34c6jeXkMNxdWGmSeK9G03TPEF1aQy3J8N6jrFusM6XD28oB/jd/EX4d+N/hH4+8Z/C74leGtV8G/EH4e+Jta8HeNPCmt25tdW8PeJfD1/PpmsaTfw5ZVns762mhZ43khlCrLBLLC6SMAcZQAUAFABQB+yn7FH/BBf/gpB+3f8Lr/AONfwn+FGkeC/hSlst14a8a/GnXpvh1pvxEgEU00118PbO40rU9Z8S6TbpEFbxJFptv4Wubh2srDXLq+tb+2tAD8a6ACgAoA/sb/AODO/wDa6/4V9+1V8df2OPEOp+VoP7Q/w+g+I3gK0uJsxj4nfB37XNq2m6ZbkgLdeI/hvrviHWNTmXcZLb4dWCMFESlgD/RVoAKACgAoAKAP8j3/AIOEf2uv+Gwv+CqX7RniPStT/tPwF8F9Vt/2bvhwyS+dapoXwgnv9K8TXVjOrGK50/XfiheeP/EunXUAWKbT9ZtChlUCecA/FGgAoA/SL/gkD+0fF+yb/wAFMv2MvjhfXcen6BoXxq0Dwn4xv5mVYbDwF8VYL34UePNRm34Rl0zwh421rUlViP3lpGVZHCugB/snUAFAHjn7Q3wR8HftK/Aj4w/s+/EGAz+C/jR8NvGPw08R7I0kuLXTfGGg32iS6lYb+I9U0lrxNU0q5UpJaalZ2t1DJHLCjqAf4vv7Wf7Lfxa/Yu/aH+KX7M/xv0NtE+Ifwr8S3OhakYlmOla9pjql54e8X+HLmeKGS/8ADHi/QrjT/EXh++aKKWfS9Rt/tMFteLcWsAB86UAFABQAUAfqb+wF/wAEav29/wDgpLZaz4k/Z1+FMNp8NtDW4iuPi98TtSm8B/DK/wBYt5lgk8OeHPEF1YX9z4s12Fy51C08L6Zq8OhhFHiC50lrvT1uwD8+fjF8LPFPwM+LvxT+Cfjkacvjb4PfEfxx8LPGC6ReHUNJXxT8PvE2p+EvEA0u/MVub7Thq2kXYsrwwQG5tvKmMUe8ooB5xQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB//9f+IegAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA6Twd4P8TfEDxX4d8D+DNGvfEPivxXrFhoPh7RNOj8281PVtTuEtbO1hUlUXzJZF3zSvHBBEJJ7iWKGN5F7cuy/G5tj8HlmW4apjMfj8RSwmEw1FXqV8RXmoU6ceivKSvKTUIxvKcoxTlHwuJ+Jsh4M4dzvizijNMLkvDvDmWYzOM6zXGz9nhcBl2AozxGJxFVpSlLkpwfJSpwnWrVOSjRp1Ks4Ql/c1+wZ+xx4Z/Yy+CGmeCLYWWp/EPxH9k8QfFXxbbx5OueKGtyq6ZY3EkcdwfDXhiKWXS9AgkWISKb3WZLW21DWtQRv9P8Awq8OsF4ccMUcsh7Ovm+M9ni89x8F/vOOcLKjSm1GX1PAxlKhhItRUl7XEunTq4mqpf8AJD9ML6T2ffSj8WMfxZiPrWA4KyP6xk3h3w3XnZZTw+q3NLHYujCUqP8Abuf1KVPMM5qwdRwksJllPEV8HlWDlH7ar9MP5SCgD8Mv+CxP7e+o/BDwvY/s6/B7xLd6P8W/Gtraaz4z8S6Dfy2mreAPBPnebZWNnfWkiT6d4l8YTQYjdJFutP8ADMF3cGKJte0i+T+X/pEeK1bhnA0uD+HcbUw+f5lCniMyxuEqyp4jKcs5ualSp1acoyo43MZR0cZe0o4KNSbUXisNUj/rf+zG+h1gfFnP8X43eJ2Q4bM/DfhTEYjK+FshzjBwxOW8ZcV+ydPFYvFYTEwnSx2RcM0qt5wnTlhsbn1XDUVOrHJ8zwkvs3/gnJ+2Xp37Y3wF07XdVurSL4teBBY+GPixo8IihZ9YFu/9meLrS1TaItI8ZWltNqEKxxpb2erwa5o1v5kWlJPL+j+DviNR8ReFaOKrzhHP8qVLA5/h48sb4lQfscwp01blw+ZU4SrRSjGFPEQxWGjeNBTl/Ln04fovY76MPjDjsoy6hiKnhvxe8XxB4c5nV56qjljrR+vcN4nET5nUzPhfEV6eCqudSVbFZbXynNK3JUzGVGl+gFfrJ/GYUAfk/wD8FVv2Eo/2rfhP/wAJ/wCANKSX48fCrTbu68OJbRKLvx34TjMt9qvgKZ1+ee/EjTar4P8AM3iHWmu9LTyIfEV5d2/4L47+Fq48yD+1spw6lxVkNGpPBqCSqZrgE5Va+VSaTc6qfNXy7mUuXEupQXJHG1Ksf9GP2d/0van0dfEb/U3jLMZ0/B/xEx+Gw+eSr1G8NwhxHNU8Jl3GNKLvGjg3BUsu4nVNRdXKo4bMJutUyPC4Wv8AxlyxSwSyQzRyQzQyPFLFKjRyxSxsUkjkjYBkkRgVdGAZWBBAIIr/ADilFxbjJOMotxlGSacWnZpp6pp6NPVPRn/UbTqU6tOFWlOFSlVhGpTqU5KdOpTmuaE4TjeM4Ti1KMou0k7q6ZHSLCgAoAKACgAoAKACgAoA/wBrb/gn7/yYZ+xJ/wBmi/s2/wDqmvBlAH11QAUAf5pn/B4n/wApPvg7/wBmPfC7/wBXh+0fQB/KFQAUAFAHafDf4heL/hJ8Q/AnxV+H2s3Hhzx58NPGXhjx/wCCvEFoEa60PxZ4O1qy8Q+HdXt1lVonm07V9OtLuNJEeN3hCyIyFlYA/wBl3/gnJ+2v4K/4KEfsb/BT9qfwb9js5/H3hqK28e+GLSYynwP8UfD7f2P8QvB0qySPdJBpPiS2u5NDnvRFcar4Yu9C10RC31WBqAPt+gAoA/D3/gqr/wAEF/2Qv+Co7P8AEHxBJqfwN/aXs9Hj0nS/jz8P9M0+9n123s4Vg0mw+K3gy6ksLH4jaZpMCLb6fcrq/hzxfZWcdrplp4ut9FtYtMYA/jl+O/8AwaO/8FPPhvqmo/8ACn9V+BH7Rnh2Mu+kXPhvx+vw68VXkALBE1Tw98T7Pw5oGlXz7c+RZ+ONbslV0zqRbeiAHx+v/BtP/wAFsGvfsP8AwxVcLJ1M7fH/APZaFkFz9/7YPjebY8fN5azGbHAiZ8LQB91/s7f8GhH/AAUS+JOq2Mvx++IPwN/Zr8KN5R1Nz4guvjD4+t1dhuXTvC3gpbXwdqEkKhvN+1fE/SU3mJYXuFZ3gAP6i/2DP+DZX/gnN+xfq+l+PvGnh/Wv2t/i3phtrmx8TfHm00S/8B+H9TgIb7f4U+EOn2Q8KxS+akVza3Hje48farpN3DHdaNq2nzKWoA/oN1iGK38PapBBFHDBBo17DDDCixxQxR2MqRxRRoAkccaKERFAVVUKoAGKAP8ACooAKACgD6n/AGIP2l9c/Y4/a7/Z1/af0A3T3PwX+K/hPxjqljZvsn1vwnb6gln458Mh98ZWPxV4LvNf8N3GHU/Z9UlAYdaAP9q7w14j0Pxj4c0Dxd4Y1O11rw14p0TSvEfh7WbGTzbLVtD1ywg1PSdTs5cDzLW/sLm3ureTA3xSo2BnFAG3QAUAFAHwv/wUx/avtf2If2Dv2n/2nHure11v4bfC3Wz4DFz5Ziu/ij4paDwb8LrKSKTPnQXPj/xB4dS8jRHZbD7VNsZImoA/xf7u7u9Qu7q/v7m4vb69uJ7u8vLqaS4uru7uZGmuLm5nlZpZ7ieZ3lmmkZpJJHZ3YsxLAFegAoAUEqQykqykFWBwQRyCCMEEHkEHj2oA/wBdT/ghF/wUXg/4KO/sC/D3x54n1iK++PPwiFt8HP2gbaSRP7QvPGvhnTbX+yPH00OVka2+Jnhh9M8VTXcdvBp6+J5vFeh6fvXQJ9gB+zdABQB+Wn/BTP8A4JB/sh/8FTPBemaZ8dvD+p+Gfih4Rsbqz+Hfx2+H72Gl/EjwnBOZbgaJe3F7Y3uneLvBb6hK17ceE/EVrc28E019c+Hrzw/q2oXGq0AfxT/tE/8ABoB/wUG+HerXs37PnxP+Bf7RvhNTMdNN5rOo/B3x/MqMfLXUPDHiqHVvBtm0qFRG1t8Tb8GRZRKsCBHlAPge5/4Npv8AgthbXi2X/DFc9wzsVjubb4//ALLktm4B4drn/hdqxwKeoF01s+Oqr92gD6x+BH/BpL/wVG+JeqacPi5L8Df2b/D8jq2r3fi74j2fxC8S2dtkBxpegfCeHxfomq34zuS2vPGWiWbqr7tUiYIkoB/S/wDsQf8ABqJ+wB+zNrOi+Ov2gda8V/tm+PtIMNxDpXxC0zT/AAf8EYdRhZZEvf8AhU2j3Wr3evhW3xSaX478ceMPDN3Ayi58OmZRLQB/TpoHh/QfCmiaV4a8L6JpHhvw5oVhbaXomgaBptno+iaNpllEsFnp2laVp8NvY6dYWkKJDbWdpBDbwRKscUaIAtAH+L//AMFLf+Ujf7f/AP2ez+1X/wCr18eUAfE1ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH//0P4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD+q3/gjZ+wT/AMKx8LWn7VfxX0Xy/iH440ll+FWiajb4uPBvgbVYMSeKZYZl3W3iDxtZyYsGVRNp/hKUDzg/iTULKy/u36OfhV/YuBp8eZ9huXN8zoNZDhq0fey7K68bSx0oyScMXmdN2pfao5fL4m8ZVpw/53v2oP0xP9fuIMT9Hbw6zX2nBXCeZRfiJmuCrXo8T8XZdWvT4ep1KbtWybhTFU3LGRlKVLHcSU7+yjHIsFisV+9df1Wf48BQB8x/te/tO+D/ANkj4G+Kvi94qMN5e2UX9keCvDTTCG48X+N9Rhn/ALC0CAhhIluzwTajrN1Esj6foNhqd+kU0lukEvxPiFxvl3h/wvj+Icfy1KlNfV8twTlyzzDM60ZfVcJF7qF4yrYipHWlhaVeqozlCMJfvn0afALib6SXi3w74acPKrhcLiqn9pcVZ9Gl7Wjw1wngatL+184rJ2hKso1aWCyvD1JRhjc3xmAwcqlGFadaH8HfxL+I3jD4u+PvFvxN8favNrvjHxtrd5r+vanNx515ePkQ20OWS00+xgWGw0ywh222n6dbWtjapHb28SL/AJY51nGY8QZtmGd5tiJYrMczxNTFYqvLTmqVH8MI7U6VKKjSoUo2hSowp0oJQhGMf+v/AID4H4Z8NeDeG+AuDctpZRwxwplWFyfJ8BS19nhcLCzq16loyxONxdZ1MZj8ZVvXxuOr4jF4iU61apOX0N+xB+1h4k/Y8+PXhv4n6b9rv/Cd2V8O/EvwxbyYXxJ4I1C4hOoxwxO8cR1nR5I4db8PzO8QXVLGK1nmXTr3UIp/rvDLj3G+HfFWCzuh7SrgKjWDzrAwemMyytOPtoxi7ReJw7jHE4STlG1elGEpexqVoS/FfpZfRzyP6Tfg9nvAGP8Aq2D4iwylnfAmf1oa5HxZgqFVYGdWpGE6qyvM4Tq5TnNKEKjll+MqYilSeNwuDnD+7fwf4u8N+PvCvh3xv4P1e01/wr4s0bTvEHh7WrBzJaanpGq2sV5Y3cJIV1E1vMjNHKqTQvuimjSVHRf9SsuzDBZtgMHmeXYini8Bj8NRxeExNJ3p1sPXhGpSqRejXNGSbjJKUXeMlGSaP+QribhrPeDeIs74T4ny3E5NxDw5mmNyXOsrxkOTE4DMsuxFTC4vDVUnKLdOtTko1KcpUqsLVKU5U5QnLo67DwwoA/lc/wCCzP7Bv/CuvE91+1j8K9G8vwJ421WOP4uaNp8H7jwp441ScJB4vjihULBofjW7fytVdlWKx8XSrI00p8T2tvZfwr9I7wr/ALHx0+Pciw1sqzOulxBhqMPcwGZ15JQzBRivcwuZVHau2kqeYSu5P69CFL/oZ/Zc/TB/13yDD/Ry8Q805+L+FMunPw2zTG1r1uI+E8vpOdbhqdSo062bcK4aHtMvjGUqmL4apuEaUFw/iK+L/Aqv5RP9jwoAKACgAoAKACgAoAKAP9rb/gn7/wAmGfsSf9mi/s2/+qa8GUAfXVABQB/mmf8AB4n/AMpPvg7/ANmPfC7/ANXh+0fQB/KFQAUAFABQB+4H/BEX/gsb8Qv+CVfx58jxBJrXjL9kv4r6tp1r8c/hjaSm5udJlHlWNr8Wfh/ZzyJbW3jzwzabUv7ES21n468OW58N6tLBe2nhjXfDYB/qkfs/ftE/BD9qn4V+GvjZ+zz8S/C3xY+F/i2DztG8WeFL77Va+fGkbXek6rZTLDqnh/xDpjSpBrPhvXrLTdf0W7zaarptncq0SgHtFABQAUAFABQAUAZWu/8AIE1n/sFaj/6SS0Af4UlABQAUAFAH+rd/wbPftd/8NUf8ErPhBoOs6p/aHj79l/UtU/Zs8WLNNuuv7G8E29hqfwtulgcmdbCP4Wa74S8Pw3TM8V3qXhvWBE6tby28AB/QFQAUAFAH8SP/AAeS/tdf2B8Lv2Y/2IfDuqeXqPxD8Q6n+0J8TbK3m8udPCXgxL7wb8NbG9jBLXGl+I/FWqeNdUEbBUTUvh7YTAu8ahAD/P8AaACgAoAKAP0j/wCCXP8AwUx+Nn/BLr9pbRfjh8Lpp9f8F6x9i8P/ABr+EV3qEtp4d+K3gBbrzp9Muj5c8WmeKtEMtxqfgfxYltNd+HdYeWOWLUPD+q+IdD1oA/1lP2Lv25v2Zv2//g5pXxt/Zi+JOleOvDNzHZweI9DMkdj42+HfiC5tvtE/hH4h+FZJX1Hwx4hsyJUWO4STTdXgh/tbw5qWs6Fc2eqXQB9c0AFABQAUAFABQAUAf4tH/BS3/lI3+3//ANns/tV/+r18eUAfE1ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH/9H+IegAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD7F/YbsP2XT8ddE8SftcePIPCXwr8Fxp4lGhS+FPGXisfEDxDZ3UH9keF7y28IeHfEElroSyltT159Qiig1Gxsv7DjDjVJri0/RfDClwO+KMNjfEDNY5fkWWpY36rLAZjj/7WxdOcfq+BqQy/B4x08KpXr4t1oKNalT+qq/t5TofzF9LXGfSBXhFmuR/Rt4QrcSeIfFU5ZE83p8RcL8OPgzJcVh639pcQYWvxNneSQxObumll+TxwVWpVwOLxf9rza/s6lQxX9Vaf8Fdv+CdsaLHH+0EqIiqiInwk+OCoiKMKqqvw2CqqgAKAAABgAdK/uxfSC8IEklxakkrJLIOJ0klskv7FVkl5fcf88Ev2av02pylOfgvKc5ycpzl4k+E8pSlJ3lKUnx025Ntttu7ervcd/wAPeP8Agnf/ANHC/wDmJvjj/wDO3p/8TB+EP/RXf+YDif8A+cxP/FNP6bH/AEZb/wA6P4Tf/R0H/D3j/gnf/wBHC/8AmJvjj/8AO3o/4mD8If8Aorv/ADAcT/8AzmD/AIpp/TY/6Mt/50fwm/8Ao6P5p/8AgpV+23d/tkfG2WfwzeXsfwU+HZvdC+F+mzx3Nn/ascskY1nx3qFhdJDcQal4qmtoGtLe7t7a603w/Z6RYXNrBqKak9x/F/jP4mVPEXiaU8FUqLhrJ3VwuR0ZKdP28ZSX1nNa1KoozhWx8oRdOFSMJ0cJTw9KdONZV3L/AHe+gl9FHD/Rg8KKdHPsNhZ+KvGywmceIGOpToYr+z504TeV8IYPGYedahWwPDtKvWjiK+Gr18Pj85xWZ4yhXq4GWBjS/OWvx0/uAKAP3n/4JQf8FMPBH7PfhfxF8Cv2kfFl5oPwysPtHiT4ZeLG0XxJ4mHhvULy7V9e8Fzab4X0rXNYGlavcXL+IdImh08Wum6kuupeTEaxZi1/qnwF8acs4RwOM4W4yx9TC5JS58ZkuPeGxmN+pVqlRPFZbKjgaGJxHsMROcsXh5Ro8lGt9aVSbWIpKH+Pn7Rf6BvFnjVxBkni74GcOYXN+PsX7DI+PeHFmuR5C89wWFw0o5PxTSx2f5jlOWf2jllChDJcyp1cZ9Yx2AeTywtJPLsXKv8AsX/w94/4J3/9HC/+Ym+OP/zt6/on/iYPwh/6K7/zAcT/APzmP8xP+Kaf02P+jLf+dH8Jv/o6D/h7x/wTv/6OF/8AMTfHH/529H/EwfhD/wBFd/5gOJ//AJzB/wAU0/psf9GW/wDOj+E3/wBHRzfjH/gqT/wTK+IHhTxF4H8Z/Gyy8Q+FPFmj3+geIdE1D4RfHGSz1PSdTt3tby1mA+G6uvmRSN5c0LxTwShJ7eWGeNJV4sx8cvBTN8BjMrzLiWnjMBj8PVwmLw1bh/id061CvBwqQl/wjXV4vSUWpwlacJRklKPu8Mfs+fp7cF8RZJxbwt4U4rJeI+HMzwecZLmuC8SvCaGJwGY4CvDEYbEUm+OnCXJUguelVjKjWpudGtCdKc4S/kF+N2gfDDwx8VvG2i/Bfx2/xK+FdrrDy+BvGM+i674fvNR0G9ghvrW11LS/Emk6Hq0Wq6Kbl9E1O4k0u0tdQv8ATrjUNOjGn3VqW/z34mwmSYHPszw3DeaPOsip4lvK8xnhsVhKlbCVIxq04VqGMw+Frxr4bneGrzdCnCrVozrUV7GcGf8AS94T5zx/n/h3wpmvinwhHgTxDxGWRp8W8MUs0yfOcLgc4wtWrhMRiMDmGRZlm+XVMvzX2Ec2y+jDMMRiMFg8dRwWNn9dw+IR5XXhH6GFABQAUAFABQAUAFAH+oP+x5/wcT/8Ec/hd+yP+y18MvHn7YB0Dxz8Ov2cvgj4E8Z6E37P/wC1Jqh0XxZ4R+Gfhjw/4i0g6nonwR1LRtROm6xp95Zm+0jUb/TLsw/aLC9urR4p3APo3/iJi/4Ij/8AR63/AJrh+1v/APOEoAP+ImL/AIIj/wDR63/muH7W/wD84SgD+Hj/AIOTf24v2Xv2/f27/hv8Zf2Sviafiv8ADXw9+yx4C+G2reJT4L+IXgQW3jPRfil8avEup6Ouj/Erwn4N1+cWujeL/D91/aMGlS6XM18be3vZrm1vIrcA/nyoAKACgAoAKAPuv9hL/gpH+17/AME4fiLc/EP9lr4oXnhVNZ8iLxp8P9cg/wCEj+F/xCtLbcLe38ZeCruaKxvrm0V5Y9N8QadLpfirRori7i0XXdOS9uxOAf2q/sV/8Hhf7OfjyxsfDf7dHwW8UfAbxakMcdz8SfhBb3/xL+FWqTqF+0Xl34TnlHxJ8GRsWK2ul6evxOLLE0lxrMJZIaAP6B/gb/wWK/4JeftGR23/AAqv9uP9n28v71Q1p4f8aeNbf4S+LLrI3FLbwf8AFmHwR4ouJYxzLFBpEkkSgs4RASwB9z+HPi58KfGHl/8ACJfE74e+KfNx5X/COeNPDet+Zu6eX/Zmp3W/PGNpbPagDuZr2ytojPcXdtbwKXDTTTxRRKYmKyAyO6oDGysrgtlWUggFSKAPmz4pftr/ALHXwQsbjUfjD+1V+zt8Mra23iT/AITj4zfDzw3cvIgybe2stU8RW97e3jY2x2VnbzXcr/JFE7lUoA/If9oH/g6B/wCCRXwNtb2Pw98aPGP7Q/iOz8xD4a+BHw18R6t5kq5EXleL/HsXw++Hl1BI/WfTvF+oNGgZ/KYmNZQD+aP9tr/g73/av+LtrrXgz9jX4R+EP2Y/Cd9FdWA+IHjN7H4t/F66tZVkhF5ptrqWm2nw18JPcQSMLjT7rwx49uLaRY5LHxFEwLUAfx/0AFABQAUAf0y/8G0P/BVb4I/8E4vjz8fPC/7VXxDuvhx+zv8AHD4c6NqEviWPwr458cQ6N8Wfh3rTf8Iju8PeAPDnizxFFa694X8V+NrDUNQsdFljN7ZeHY9RkS2hSe1AP7L/APiJi/4Ij/8AR63/AJrh+1v/APOEoAP+ImL/AIIj/wDR63/muH7W/wD84SgA/wCImL/giP8A9Hrf+a4ftb//ADhKAP8AO/8A+C0/7cWjf8FB/wDgov8AHr9oHwRrV1rvwij1DSfhv8EL25sNV0lbj4V/D3To9E0bWbXSNetNP13SLbxprA1/4g/2Vrenadq2n3Hi2e01DTrG7imtIAD8q6ACgAoAKACgD6a/ZO/bF/aR/Ye+LelfGz9mD4qeIfhd4805VtbyfSpYrrQvFGjGVJrjw1418L6jFdeH/F/hu7kjSWXSNe0+9tobqO31GyW21Szsr23AP7S/2H/+Dxfwjqsel+D/APgoH8AbzwpqISO2l+NH7O0c2teHLiXaEF14j+E3inVzr+iRKsZlvtQ8L+MfFslzcTlLHwnp1sirQB/Rj8Cf+C4n/BJ79or7HD8Pv24fgppep3vlxw6F8VtYv/gdrb3b4H9n29h8Y9N8DNqN75h8qOPSm1BLlxmzkuUKSMAfoT4c+OPwV8YeX/wiXxg+F3inzceV/wAI58QPCet+Znp5f9m6vdb85425z6cjaAekm7tVjaZrm3WFdu6UzRiNdyLIu59wUbo3SRcsMo6sMqwLAHhvxH/ap/Zh+Dtnd6j8Wv2jfgR8MLGxBN5d/EL4ueAPBtvbbc5E0viHxBp6xvxgI2HZvlA3YFAH5OfHr/g5O/4JA/Am2v41/aaPxo8Q2Icx+FvgL4H8V/EC51Ax5yLDxdLp2ifC9yzAIn2nx9bB94dSYg7oAfzlftm/8HjXxd8W2+p+Fv2FP2eNG+EmnzrNb2/xZ+O9zZ+OvHghkB8q80b4b+H7iPwL4Z1W2YKVbX/EXxN0uZWdZNMUqjsAfxqfEf4g+MPi38QvHnxV+Iesv4j8f/E3xn4o+IPjnxDLaafp8mveMPGet33iPxNrMlhpNpYaVZPqmtale3z2mmWNlp9s05hsrS2tkjhQA4ygAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//S/iHoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAczu+N7M2BgbmLYHoM9BnJxx1/FgBtABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAOLuwVWZiq/dUsSFz12joM4HQduc4FADaACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//0/4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//U/iHoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP/9X+IegAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA//1v4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//X/iHoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP/9k=" + webUI["html/img/logo_w_600x200.png"] = "iVBORw0KGgoAAAANSUhEUgAAAlgAAADICAYAAAA0n5+2AAAAAXNSR0IArs4c6QAAAAlwSFlzAAAuIwAALiMBeKU/dgAABCZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjMwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MzAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NjAwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4yMDA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8ZGM6c3ViamVjdD4KICAgICAgICAgICAgPHJkZjpCYWcvPgogICAgICAgICA8L2RjOnN1YmplY3Q+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDE5LTA4LTAxVDEyOjA4OjQzPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5QaXhlbG1hdG9yIDMuMzwveG1wOkNyZWF0b3JUb29sPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KaDoJhwAAJyJJREFUeAHtnQm8XUV9x+ckIQHZEkKWF4UCAlZZZSuyuICRRRCQtmxWwYoohYIial0qrljcgbYqCmhRjEEoAaIGFShirLJ8gCI0CBqweS8JYYkQlkBOf/+X98J9793lnHtm5px773c+n8m7Z87M//+f70zu+d+ZOTPOESAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAgV4ikPRSZakrBNI03UwUjoKEdwKrkiS53LvUHhMYuX8uV5vN6xTEYvM62bptBHsfFJcbIuhBRZcTwMHq8gameiMJ6Ev6MKVcMzKVK08EJurBtNqTrJ4Uo/45WxVfEKnyz0jPNLXZk5H0FVIjNr+XgJcXEpKt8A1ickC2rOSCQGMC4xrf4g4EIAABCEQmcKP0rYikc33pOTSSrkJq5FztLAExnCuz80eFjKUwBIYI4GDRFSAAAQhUhMDQCOCVEc15a0RdRVTFsvMFGTm3iKGUhcAwARysYRL8hQAEIFANAj+IaMahGh2aFFFfu6piOVg2PbisXSMpB4FaAjhYtTT4DAEIQKB8AjfJhIFIZmwsPW+KpKstNXIAt1PBndoqnL9QTOc2v3WU6CgCOFgd1VwYCwEIdDsBjaDEnqaKNTrUbtPFsu85GRhzerZdHpTrEAI4WB3SUJgJAQj0FIGYIymHa5RoQoXpxnKwFsi5fazCHDCtwwjgYHVYg2EuBCDQEwQWqpYPRarpVOmxPaYqF+T4bSGj9oxkWEynNlKVUFMmARysMumjGwIQgEAdAhpJSZU8p86tUEmxRony2n+kCsTYr3GV9Fyd1zjyQ6AZARysZnS4BwEIQKA8AjFHVI7UaFEMRyYvzaPzFmgz/3w5tR2x4Wqb9aNYCQRwsEqAjkoIQAACrQjogX+78ixqlc/T/VmS8xpPsryIkcM3TYL28yKstZCYzmxra8jRFQRwsLqiGakEBCDQpQR6eZrwCLXp+AjtulI6rougBxU9RgAHq8canOpCAAIdRSCmg1W1Q9BjrQubp9FCO5eRAAGvBHCwvOJEGAQgAAF/BPTgv0fS7vYnsamkbTQtt2vTHJFuyo5NperASOqYHowEutfU4GD1WotTXwhAoNMIxHQAYo0atWqDw5RhYqtMHu7bwdoLPMhBBATGEMDBGoOEBAhAAAKVIhBzmjDWW3utAMdy9K7SKOHqVsZwHwLtEMDBaocaZSAAAQhEIiAH4AGp+m0kda/S9NwrIumqq0b6X6IbB9e96T8x5uigf+uRWGkCOFiVbh6MgwAEIDBIIKYjEGv0qFHTHqQb5mSFDgNScGNoJcjvXQI4WL3b9tQcAhDoHAJzZart7h4jlO1gxdJ/hUYH7WBtAgSCEKjyAZ9BKozQnidwnwh8pwQKW0lnrPPeyqifHTXCwypQx5Ij8LCmzn4p8fsHUlErdg/p2lI6H6pNjPFZem1h++ExdElHzFHBSFVCDQQgAIEeI6AHx96KMcITPYa2Z6qrznNqjA40pOPMMsBK98GR6vhH6ani0UBlYEdnIAJMEQYCi1gIQAACnglcIXmxRgljTdONRhRL71yN0MWach1dR657hABThD3S0FQTAr1EQKMT01XfzYfi1FF/Ld3SNlG0qU3bC+nRmr+1nx/Ug/gR3Ss9yI5lqtcvZMjsCMbsK10zpHNpBF2DKqTPjsWx43FihMpPD3ZjH47RsFXSgYNVpdbAFghAoC0Cehj9hQrazt8HDMW+tgSNLSTR6e+UfKPiTRbN0dHfsoI5BjEcLJvdMGfnmxEruq90mWMcOixSG94WWkle+T3Uh/Oi6dj8vT0HvSQ92iVuw2itN979wU1Pbo6mb3m6vXve7R1NX+z6RatYcUX68rR2WFhcUksJK/XwsGNGujqIpz2Ih50pc6y2iVjhe6XrRsVrxPrHEfU61XuK9Nn2ArYYPHT4qep3cGglw/JVt6/q8xnD1wH/fkb1+nhA+ZlE92ofzgSnSzL1roNlw9H9zr4ot4vYlk+7CW4XOVn3B9eZppP0NXyHXux+ZXBdwwoSvZ3Xl5w4fMnfFwnoyxQH60UcbX8Sxz1U+BzFN7ctxG/BOyTuM4q2I3iUNT1iME/6YrxpZzucT1e9HtffoEF1smfRYsUtgipaK3xH1cnOeCwl0IdLwV6KUhsG7s2wdv+T4zSCFfOYhA00onSxfoaG5z7gPhnZuXpQv6n/sTc7E7UOTUAPpT0Vr5Ue29G8Ks6VVfvVij9SvEv2HasY/v92vO0F1lO9YjhyUuPMcY7hXN1VlnNFH7Zm7q0Q48ugukRnDc7DfySygfu5pe60oDr7070k/wNBddQKX+ukHuumJitrk/kMgaIEah5Kv5GsKjlWo6u2oxIuV/ydbLa1SyGDjWA9HVJBjexYb/XF0vPDmrpF+UgfjoK5kkp628GyJpnpvqR/r4/aOmvcuW5p+vIgOm1q0LlLNHo1Poj8+kI/oqlBG1kgQMALAT2UtlK0EauqO1aj6/sKJfynbD9HMcgSDI3APCkdxiZGOEj12DCColgOVrS3B8WNPhyh41RZBQ6WrZuY4N6uqcLlERvqJW6N+7amCv1/AfdrfUrqXhWtLombP+SkRlOJou4moAfTa1VDc9jf3ME1/YRsn6O6bBCoDrEcBbM/6EJ3MdpBOrYPxKlW7K1yTh+oTQj1mT4cimxnycXBsvaangzo35OiNl2qY1MG3Kledfane8pRPNurzGbCErdEt090kRb3NjOFe91BQA+mk1WTnylu3gU1+hvV4WbV6aUB6jJfMlcGkFtPZOjRpaPrKQ2QFsUppQ8HaLkOFYmDNdxwfcl1+nj+8GWkv593A+nWXnStnRq8NNrUYKIxOOfepqnBmCN/XlAhpHoE9FAar/g1WWb7Ltni6m4Ju6siv1HddvVZIY3EPCN5V/uU2UTWYbI/5LYQoR04q5q94TmnSR0L36IPF0bYdQJwsGqbtM99UJd31iYF/Zy6jfTf/ltepgr73SeiTg0691k5VzcE5YPwniCgB9NkVdT2k+rWt1BnqW7zVM/NPDdolBEZ2byJ4hs92z4oTkxsLeouIWSPknmLnNI/jUrzdkkf9oayqwThYNU2Z5I8q8vjFFfVJgf9nGqzxH53SiEda6cGzTmMFW7WuqtPxlKGnu4loAfTdNXuvxVnd28tB2tmWxBc7LmO9nLOCs8yG4kLNcp0VCOFntODOaP0Yc8t1UXicLBGN+asxDYffd/o5KDXiTvPLRk86iO/mvhvDa5wk9zxWnf1Qn5jKQGBFwnowWRvutq0TYwFzi8qLu/TEaqzt1E6jcjYHn5XRqrOW4bay7e6UI5brZ32XTW3NsHXZ/qwL5LdKQcHq167zkq+qcXisb64bHXAxjLjonqmtEzrd/+s8vYWTpwwzr1T+10FG2qPUwm0VITA52TH6ytiSywzvqCH8m4elQUbmRll4zRd7z8qrdClONji/xhHed0gZ3RZIWMbF6YPN2bT83dwsBp1gQ3cu3Tr4Ua3A6TP1oJ305k9LNGxIcngurHsZYrlPN/NTOYVE0FpCOg3RZra1FDMae2qYLfF4rZ9g/2o8hFukpABH4IyyPD9tt+R0plk0Fs0SxAnlD7srQ8Xbd/KlsfBatQ0k5PHdOtt+u9vb8vFCak2PV2R2lqN1sHe6kkGNxSd0Dqzlxy3u76IW0B4MRkhVSSgB5NNCV5aRdsi2bSt9JzlQ5dGZoJNf9Wx70i1nU+HKMb04HOqh/fZCPqw89aH6/Szrkny+Z+la6CMqEh/+ilNwX18RFrIi8T9RG/nHdJSxUD6Gbl+H22Zz0eGxP1Z+8LvHuWQah/2VlCGvpA57FntIg4b6s+vFe1omRjBXs+3N4N/rvgHxUcU7ceTnXhge23NVNxX8XWKGynGCjZltaUcJHuxplAQ030k4JZCQrIX3ls220sJhYJsnioBSxVtHV7IcK3sPdynAvrwOpre+vA6iV32IdboR+dis7fl+t2BqoB9iYUPqXZN7k9PkpN1SUNlS9Ld5fR9qOF93zfGuffiXPmG2rPyzlfNYzhX/dJzruIP9IBtuVebHpq299abFD+t+GrF0MHenjxB0cebhQsl5yHFLRVDBxt1KuxgScZbFEM7V8YixPQgfdjIaotuRV99eFBgt/3DFGGrFrUh+ESdKHFPtMrq7X7qvuweabD789qpwUvlYMVxjhNN5cxIvuetbgjqWQJyYrZT5U8MDGC15NuPj5fLsbogi3Nl9ijfakXbbNg2Bv07xVWKocOZPhTIbhulm+NDVgYZvqb1fMlpZrK14dXNMuS9Rx8eQ8xLHx4jtUsScLCyNGRf8kc5WKdkyeopz2S32n2jrqylmq5Mo4wAmPr7VO/T6tpBIgTyE/iwioT8znlU8mfL4ThP8en85g06WqnKXqayNpr1eDsycpTZSQ/sN+bI3yxriJGaevq2lc0717uRNU3lbYH/7Kz5C+Sbr7a0g7F9BvrwSJo++/BIyV1wFfLLrgvw1FRhZjJHzkbjabuarF4+pjrotj99+whZy/V6d+rsP3iM8IwG8I/RW4NPxVCGju4moIeqTV/ZyFCosEKCbX2QvVVXOEjOLRJymOKawsKaC3hf89vZ7sre25VzUbbchXMVHX16syyYVNiK1gK8Op304YbAvfThhtI7+AYOVp7GS9zpyh7rS8z2x/qqW572DZpoU4PPu5hTg2dpavCuPHjIC4EmBM7WvfWa3C9yy5ygE+Rk3F9EyOiyQ07WV0ene74+RA/uWZ5kdso0YVEHLQuulcpkU74+A324Pk2ffbi+hg5NxcHK03BrR3OOV5Hn8hQrkHeKnKqvD5ZfOzW4UwFZ2YvaJqt9yb9lL0BOCDQmIAdihu6+q3GOwnfOlTP008JS6gv4mJL769/ykmpvcu/rRVK8dVg2LbRtOzar3Poqd0g7ZXOWmac+8UzOMg2z04cborEbPvtwU0WddhMHK2+LzUpuU3f6aN5ibedP9bZNf/qlaFODiVvs1nd/37a9FITAWALvV5I9WEOERyT03BCCTaYe0raW69uh5A/J3ceHfNl6j+Tc7UNWBhntjkLZ2raNMsgvmsXr9KCMoQ83bxEvfbi5is67i4PVTpvN1Iagzi1op2hbZVL9547x1mCi8bJxOux6ShJ6cW9bGCjUeQT0y98epu8NaPmX5Fg8FVC+if6WYsi1WL5GsMxW346FyawX2nWwjq4nzHOarcfz9v1MH87UOj77cCaFnZAJB6udVrLXoie4d2gkK9T5Vu1YVbxMojcUZyQLiwtCAgTWEdhPnzZed+X3g23SGXwqWw7cYum51a/pI6Ttqof4BiNS2r+ItQ5rL9n8sjxmKr+twTs8T5k2816lNlvdZtl6xejD9aiMTPPZh0dK7uArHKx2G296MqCiJ8nJsj1ouiFc72a4f+mGilCHShF4Q0BrbtaDdGVA+bWif1174fmzOR57+pApHg9Izm99yGohw9bdHNUiz+jbr1fClNGJAa59j+LRh1s3krc+3FpV5+TAwSrSVn3JfLlX5xcRUYmyiY6sGK9X6NduWFgJkzCiawiEfDjNj0gppINl1fC5hsW3g9EIc95pwrz5G+ltlj6gmzc2y9DGPfpwNmg++3A2jRXPhYNVtIH6BneNvrOomNLK2wjcODlXM5KlpdmA4q4koCmhTVWx3QJW7saAskeLDr14fO/RCgtcz1XZGCPr+6uNp2WxU/nsWXNklrwF81yhUbwXCspYV5w+vA5Flg8++3AWfZXPg4NVtInssNaJ7liJsWMZOi+kmhackVzfeYZjcQcQ2F82hjxv7sGIDFqeZ1jQlpkFy68rLgfjYV38cl1CuA/WtnamYJbwGmXyVscmCn2P3tGHm8AedStG+45SWe1LHCwf7bN5cp9Ggc70ISqqjMQtdH1a2E6AQBgCIadWHpcj8UQYs+tKte0gQo4K+V6b5NvRqAtFiVnfCsyar5GeLOmLlelXWTLmyEMfzg7Ldx/OrrmiOSdU1K7OM2tmcpH2qzpIX8Exvkh88HlMth6ndVfP+xCGDAjUIRDy4TRZ0ze/r6MzZFISULjvh9MVstXWh4YcQTQcB6odNpGzu9IumoSjmtzzdWuu7PDtBNOHs7eO7z6cXXNFc4b8wqholQOa9Xg6RROFd0rDFgG1+BJ9tJuVXOlLGHKaE9BDaG/liLEFxko9ZGztU6lB9bWtGWw/NUbJs7XE82o3r0cJqQ1sL6jZ2dQXymXHFH2/kQTZYevwbmt032P6HrLDmx76cO6W8d6Hc1tQsQJ8+flskMnJY9of6wRt3fCCT7HeZSXaOwjnyjtWBI4gYMfj8P0yAknTiwl6oNumrD5DrGnCt7YwutX9FsUz3V7k07ka0kgfzoR+XaYQfXid8E78wBeg71abntwskZ/1LdajvDu11PQsj/IQBYF6BDavl0haUwK+p1iukrbnmmr0c/NgOYfNNkqN4WD90E9VRkihD4/AkenCdx/OpLSqmXCwQrTMTPcpifW92LK4pYl7avCNR4+HoBY3CgldSmBql9YrZLW8Ppw0ovOYjA11CHYthw11cXBtwvBnOV6v1GeLoUOI0Tr6cP5W89qH86uvVgkcrBDtsXYfluM1VfhECPEFZJ7m7I1HAgTCE+DhlJ/xZvmLtCwRwvGop7TRKFWj9Hoy2k27S86kHXTtO9CH8xMN0YfzW1GREjhYoRpils4vS9wpocTnljvOXeb6kktzl6MABNojwPRKfm6T8hdpWWKecjzdMlfxDIdptKreIv0YDlaI6UEjQh/O3y9C9OH8VlSkBA5WyIaYmcyRk3VJSBUZZd+vl7VPzZiXbBDwQYBf/z4oFpShkZ0nJeLagmKyFJ+sTAfUZpTDtZWud6tNC/Q51CgdfThQg/WKWBys0C2duNOlYlFoNU3kP+fW007z05I/N8nDLQj4JsDDyTfR9uWFckBGWzR6tOqo0RkCXN8qJ/KBAHJNJH04ENheEYuDFbqlZyZPycE5TmpivM0ztjaJu1DO1e1jb5ACgaAEmF4JijeXcDsUe2WuEu1lPkKjVrXPlKPbE5OrVEjnkT6cqynIPJpA7X+G0fe49kXAHJyktFGs/Vz9tRG+aoccCNQjYFNGhAoQ0AjPMzLj6gim2L5R+5keOVp2Lp2dPxgy2K7tcwIqoA8HhNsLonGwYrRyf/peHUuzYwxVY3Skbi834D49Jp0ECIQl8GxY8UjPSSDkSE+tKcPThEcqMfTz5RY5j3+qVe75M33YM9BeExf6P0Cv8Rxb36XpznKuvjz2RtSUs91AemBUjSjrdQJ2ODKhOgSulykrIpgzvO5q2NEKqTK000gfDtl6PSAbBytkIw+kG7o1zr4E1g+ppqXsVL8kU/ddtzJlTUFLWGTwRGC5JzmI8UBAIz2rJSbG2aNbanrwTdIV8pBkI2LHkc21DwEDfTgg3F4QjYMVspVTd4Ecmxi7GLeuRepmaR/3i1tnJAcEvBDg139+jGvyF8lVIvSIz7AxtjXNhOGLQH9vkNO4LJDsYbH04WES2f+G7sPZLalAztD/CSpQxZJMWJqeoN9YJ5Wkvb7a1B3u+tPTtOHohfUzkAoBbwRi/PrfWdY+783i8gX9b2ATbpL8AUVbgB4yzAopfEh2DGeRPpy/IUP34fwWlVgCBysE/GXptnKu/j2E6MIyU/cFrce6yc1M7i4sCwEQaEwgxq//VRrFCLUHUuOadegdsXpB03c2rWZ783VysC1vYkx30oc7uZdUwHamCH03QppO1G/qOZoa3Ni3aE/y1pdtl+s96g08yUMMBOoRiPFwekU9xaQ1JRBj5KepAR5uLpCzaAdZhw704dCEu1w+DpbvBu5350nkbr7FepWXuh00UVD2m41eq4SwyhGIMb2yfeVqXX2DFsrEh6pvZlMLYzmJ9OGmzcDNVgRwsFoRynN/ID1c2c/IU6S0vKl7j1ua2l41BAiEIBDj1/8uIQzvZpka+Qm9OWdofKukIMamqVYP+nDo1uxy+ThYvhp4RfoybclQhYOds9foBfdtZ3YTIOCfgE3hhH7L6yitKWKqO3/bxRoBym9Z6xLz5SQ+2Tqblxz0YS8Ye1cIDpaPtk/T8e5Z932J6rTDQTfTCYn/ofVY9AMf/QAZ6wgMjZTY5pYhw6YSPryxZUg9XSVbbXO7KlTmAfRFeEZzDunDRZqJskaAB6uPfjDg/lli9vchKrqM1L3e9bt/iq4Xhb1AYEGESlZrK5QIFfakIuQZfp5MHCPGDqy+bkxq2AT6cFi+XS0dB6to8/antmPxx4qKKbV84s7R1g17l2oDyruRQOgRLGN2gKYJq7GZb2e1YCc6WPM0qmQHV8cM9OGYtLtMFw5WkQbtT6ep+GXa9qCzOabadTnVFOeKdJMiOCgLgVoCehj26zr0fmv2f+87crI6Zk8/2TpO8SzFOUPxK7XcYnxW29wToW18VyXa9OCw4fThYRIj/1ahD4+0qJpXne0YlMk0TROpv1SOyawyzfCmO3Vbax1ZNTdH9VZJBJVAIMYUy56q10dKqFtulXowbadCtqP6FxX/diger79lhOgOS4FK2kHVMfpSPRNj6KUP1yPf4Wk4WO024IB7v5yrQ9stXtFyx+sonXdU1DbM6kwCMR5ORubjcl5eU1VEsm2ioi0luEtxv4rY2UnThFdpNMkOrC4j0IdFvaJ9uIz+kFknDlZmVDUZ+9O9dHVuTUrIj89J+H0hFYySfaFbNvgre1QylxBoi8DNKhVj3YxNES7QQ+DgtqwMVEj2jFd8u8Tfq/hpxfUDqcotVg6LHTP029wFyylQ5mgbfbiifbicrphdKw5WdlZrcz6a2qvhOmrGrZe3aFv5E72hOM69TmVjbHqnnyluI52j+H39XIlTv7agUKhTCOgh/rRsvTySvRtJzzVyaN4VSV9DNbIhUbQpwP9R/I7iNg0zl3ujTMcla80HlPHGrJl956MPV74P+25yb/JwsPKifNZ9Q05InC/LxC3Uufdf1MHMy+RknZbX1Lbzp24PHaXz2bbLUxACIwmco8tnRyYFu7KRrIvk3NjC9y2CaWkgWDonKNoJCXco2hTcXzbIWpVkO/zZdnevcrhCTs4LJRt4jvTTh0tuhE5Tj4OVp8UG0pP1VXRMniIF8q5y49073PAXy8zEvqyvKiAvb9EP6Cid2XkLkR8Cowno4fiQ0mK/QGHTcovk7Hxe0UadgwXJX0/xIMWLpMTenLT/p7sEU+hRsNrmYYn7pUeRIUSVPspGHw7RrN0v096EI2Qh0J/uIOfK1itskCV74TyJO931JReOkLM0naHpu98pbbMR6aEuksGHxS6yI8ahp6FqUQm5evjaPmMLIxizUg+DoA5FO3VQ/W1LE1vzs3E75QuWeUrlf6xojs914vNEQXmDC34lw36A/LXiEYpTFNsNy2TTjHYLFy2ntjlVMv61qJxA5RdL7tbiU/ooG324aQuX2oebWlbiTRysLPDtvLMBOVep2yFL9sJ5EvdzTQ3O1ujV2C+VpekJcrIuK6wjq4BEOyf3JYdlzU6++gR63cEyKmLwSf2xUw/KDPbSiDm6tjbq3qFoL5E8qof4mMX4stm+I80ptGUB9v9/x6G4v/76cmRLfTipjtNVlyWK4xWrFr6odjm7KkbRhxu2RKl9uKFVJd/AwcrSAEvSbyrbyVmyFs6TuJVuktvJbTY4rVJfXH96tZy9t9S/GSB1nDtD68DODyC5Z0Tqi7mnR7CsocXANrK1UazN7bqC4XnZ9GdFG/EadqzMuQr9PVn6w0ltY1sRVHFJwB5ysG6TbZUI9OGGzVB6H25oWYk3WIPVCv5AeoyyxHGu1tpyZlPnyvJMcO/Rv4+tzR7h3zXuPK3H2iWCJlR0MQE9KO0suXMrXEVbIG9TfS9TfKmiOYShnSupqEQofZ1THQqLquRcmX304TqtRFJDAjhYDdHoxtJ0G40U2ehVnJC4azQdd0lLZdN0BEnizmyZz1+GSW6NbU2RvsSfSCT1KIGvqd7X9Gjdq1ztq2ScTZ9WKfywSsbU2EIfroHBx8YEcLAasbF9oNa4H8jBinU+3wqtgHh3I3PGpPcl35WTdd2Y9FAJqXullrx/JZR45PYGAY0A2Ov2xyr+pjdq3Bm1VLvYiPhPK2ZtFUfVbBSLPlyxjlJVc3CwGrXMgKYyUrdno9ve0xN3qpueDOSSu547RU7WE7nKFMv8brckfWsxEZTudQJ6QK0SA3txwtZjEapDoEoOzV3qJ/dUB81IS+jDI3lwVZ8ADlY9Lv3poUp+f71bQdISbUjYl+QfDt88+T/Z874gNjUW+i23Iv4Gjo3N4U4nEtADyrb+OETxkU60v0ttnqd6PV2RuuX/PoxsOH04MvAOVIeDNbrRlqezlHSpRq/iLG5NtAHEhu4fRpuR+drWbCXuJ5nzF884RSs1LtN6LPpOcZY9LUEPqPsF4HDFqjzUe709nhSAaysCoUqjaQ2R0IcbouGGCPCQrO0G5jQ8b86Dm1abHPRzojcUN0lWFNIxUWu3bHuHWCF1r5Vb+NFY6tDTvQT0gPq1amdrsnCyqtHMVXBsblW/6JjpY/pwNTpuFa3AwaptlQH3MTlXb6hNCvo5cRdrf6nivxin6riLxH0gqK1jhX9Cb1nuMzaZFAjkI6AHlE1N7a54R76S5A5AYL5kxvuxVr8CVXDy6lvWIJU+3ABMjyfjYA13gCXpa/Ux3i7TiVvsJnpcPzUzsXPQrh+uTvC/qd55XOO+5x4Ne85b8HqgoBIE9IC6V4bYZqxfUBx7gkElrOx+I9QOz6iWV5dYU2t7O3e14wJ9uOOaLLjBOFiGeGU6Vf9+T1/rcY6KSKQpce90Uwc3XvTZyCdLru1EHSekbiudL//1OMrQ0u0E9IB6TvGDqueBin/q9vpWuH5ljiDdoj7QsW1PH65wry7BNBwsg/6Us809bffmWOFCTQ3+wruyWcliuW72gIoXUq2f6U9PiqcQTd1OQA+pG1THnRUr/yaZp7Z4yJMcX2JsJLzYutD2LSnTuWvf6lEl6cOjgPToJQ7WQHqGnBJ7kylWWKSDnD8cTFmf+4ZGsfw7b80NvsAtT7dvnoW7EMhOQA+oxxSPUQnbL2uBYrdNG65WncyBtNG6vRQrE8TdbLuyBINsA8+5JegNopI+HARrRwmNsxVBVZEsSW1h7a8UJ0YxMXEv6L3N/d2MZGFQfQPp1noc3a24YVA9I4Xf5vrcPtrmuGrHbYy0sqQrDnsuBl78zIG37UxOVIx1uoJUeQ+/l8SLFC/VA3iZd+meBIr3ARL1c0/isor5mZhU8cDprPY3zUcfboqnK2/27gjW8nRjjfTYcHQc58q6T6oFvKGdK9MzM/mD/v2QfYwYdtfWDZ+LqA9VPURAD147+PcMVfmliqcqVnaX7zrNslhpFyjurTpsp3ieYmWdqyH7b9LfgaHPsf50xfRgI1hqc/pwIzhdmt67I1j96WlyeOxLL05INKI00+0RbYQnTW0L0xtUx9fFqaC02AjdBtpDbPLguWbR1HaCIv16tTVFd0awtV9f5LZZbtcHMX2DKnmkor19uKtivB9LUtYkPK57/6V4veICe7A2yVvZW+J7vow7PZKBNvI9U6zsTMSeCfTh7m7q3nWwurtdqR0EeoqAHlSTVOFXK5qz9VdDf7fS39DBnKnbFW8birfq74NyFLptzZiqRQhJgD4ckm45snGwyuGOVghAIDABPbBmSIU5W1srTlGcPCrWpm2se7bB5qaKFmyh97OKNrJiR8jYdNlw7NfnexVxpgSBEI4AfTgc2xiScbBiUEYHBCBQaQJ6kNkeeLYm1f4+ywhUpZsL4+oQoA/XgUISBCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIQgAAEIAABCEAAAhCAAAQgAAEIQAACEIAABCAAAQhAAAIBCfw/OGy5D6vVjuMAAAAASUVORK5CYII=" webUI["html/img/logout.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0xMC0xM1QxMToxMDoxODwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cg27QeEAAANQSURBVGgF7Zk9aBRBGIZzSRSN8YdoCpEkghCCqK1o4g9IsBCCNmIniCAiWAhqI8G02qiIoqCCWggSEcFKEFPYpVAU8QdFUyiKRpRokBjP55OdZDLZvZnZ7N3Ngh887M7sN/O9797t7c5eTc3/8D8DxWKxGS5Ai//oAEYgvB4OwleQaAtAlp8ERG+Bp6Jei/wYQfRy6NfE67vhG0FtA/TBqK7c2A/bCGJ3wpAhOq4ZphGUroEHcYoT+sIygsgmOAu/EwQndYdhBHV1sB8+Jym19Lf6/faVIRuBG+GRRajtcPWMoKwFbtgUOh6vvBGEzYFj8MNRpEtaZY2gaAe8cVHmmXOc/K3QXIZv/+SUFFgJ96AS8ZwiZ6Ab6iZVzGCPiRbCKRiDasQHip6EdD/PDKyFvfAJQgg5kVfB/VoieT0MQojxE1G9UG/7otWS0A7pPkrb7DM/Ppcp+mAAM/bFGEmL4RL8gVDjI8JWOZ0bEjvhSahO0CXXsLMZWZYegREIMV4jaoHTJyNJJLfC7RCdoOm6sxGVyKAeeBegoU6l0XmLiXlwAqp1o4w7j3d1AwW9YdtnNrnQzkOXLddyfAPHv8Ey6ABpd8N88In2QqHwymfARC5mCrAH0i6qGDr9jk3fbNgFz8A1DkwIS7tDpSVwGdLcexIfPZhPHpf2wS+wRX9a/dPGUakLzBdwNgGJRlQBJtgMw5aJ3qr8TLYUmwVHwXXxZTUiwphvHYxDUnzPxIA5CdXa4E5SVa3fyUhkRtYqpSKbNYxpJiq+ncpDJar7GGlknvcl5mqM05BZH4Xl3iOLpLh7j7OR6MScSzAykplg20QIWA0PDSG+RuTdQVy8sNXP9DgK5N4jK9AvkRpfI4sYF/c2836mQl0nQ4zce66AfZFkTMqYl2DGaSMt/CYOHpsuaPco5bLUzUuMGkLHaQ+ovjwZUZrVdpAHRnnw/Bd5MrJCiY62t4x2+E2uBfkfRg95TdSkK8/LJ7JWF83+Nb5Ww0Zf+E3OviwXVMgT8dLwVRsKEd0A+uP8biMlH01MHAYVF/Oh2lCJenkDqpbUN9nPyzU91QnCRbyEPEXn1sQhxMv7tG1T7cW3rK/r44eVtxfxm6gwBh38zJqPJuUtXu3Z/wLwuBaBLgMkKwAAAABJRU5ErkJggg==" + webUI["html/img/m3u.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0wNy0yOFQxOTowNzozMTwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CumjVbcAAAGWSURBVGgF7VoxTgJRFGTFaGKBFnbEcABjb0fiBego7D2ABYmn8ARKRWFNQ6gx4QRQGWJJoY2VhXGdl7Dkh7Dsx3ns3yXvJ5P97L6d92bmhwYqlcWK43gK5L2enP51NP8F7pN721wPnOITZx9qG6HxI8QIZO+9XCHeL+VQKKm8QMyxb6+iCpH528AQYs58xIQWknV8mhDxCjEXWWJCC8maT55fAmOIudpUXAYhMn8dGEHMTZqYsgiR+U+BAcTcrhNTJiEy/xHQg5jOqpjD1RsBP3+id8u3P8TUoij6SuoLIwRDfWOofjLYtteyHa1UfcvvcUT1jqpGauVuHnyAdragjv/TAkley3uhj9Y5ZhDQa2+Olgmhz4IygSWibChNZ4nQFioTWCLKhtJ0lghtoTKBJaJsKE1nidAWKhNYIsqG0nSWCG2hMoElomwoTWeJ0BYqE1giyobSdJYIbaEygSWibChNZ4nQFioTWCLKhtJ0biJzmi1/guXMrpDn/OegO3bXMuAH0TtgAvwARV3y57Q34AGoJkL+AErKZ9cqbH7AAAAAAElFTkSuQmCC" + webUI["html/img/mapping.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0wOC0wMlQxMjowODo5NzwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CpRxQsEAAAJLSURBVGgF7VoxTgMxEMwBHWlAaeABVCEtBcoD+EBewCdCyQsQtLyAPCBvCBSRIBUPCF1ogqBJjlkrezGr6HTrO98lhy1Z9trr2VmvnbMNjUadUhzHLeQB8hw5LS3QOUbubvIf7X3kKXIZibgS51bCZdWgMT6D8nECgArkngagQN0B8dhbkblalVmLIyheCGUthhjuLBq77MihA0xTjHHBEBBOorHLjjghbNOg4Mg2RYO4hIiEiHiaAV5aSwf8hRgjZdHtTTTc2ZFXpZkY+hMx5k3IZYlr7jgudJHp2JElLaF0K1mirYn8nAWgQB3ibM59ERNCA52d6Nghv9isQiUtn0kURe92I9eBcYA6YZxym8dyDuwRuMw82gjQYQbsPdLDdNCROO0US3uEfp3usTZpjf5J2CNtNFwjl7FHvmBnCB5PCQkQoJudJtGvE23sJEFuI39rQArS7dskXK6nlwkAKiB1VxAxLcyUePAH8cQmlbEul4+UM8LkVjPc2ZHcaFUDBEeqjoC0HyIiZ6RqOUSk6ghI+xyRD9mRQTYfIktPylaX16rhzo48KE29QH8kxjxC/hFtZYiGe70OjWVMW7Dx32bA3iO7//iAC8DOPweZFQhH6O+CmkRvW2f28oV8owEoUHdMPPg70rFJZajTkqT7uZ3ObaHEuuHOjnCpsb8vlKUsur2JhruLA94Y5QEOjuSZPR9jQ0R8zGoezNpFhN5RtUm+/bpgaG1u0jd2OSLDTRopbZ/okxcrLUYKvKprbRfHhXr8m5PK/y1V/gWRKLfiNSmxEAAAAABJRU5ErkJggg==" + webUI["html/img/settings.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0wOC0xMFQxODowODo4OTwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Ckxt87EAAAS7SURBVGgFzZpdiFVVGIbn5N+IMgVhaRLqWI7mQIJoIVRgOhQZNDAhWcbcVuPV3BRE6I14440iQQSaN0p6kz8zI0k5inUhZSSaYOVYODMo5eiMOOPf+LzH2cPMPmvttdbe53jOBy9rr2+938/ae51vr733qaoqgQwPD68B/wDJfXAP3AE94JMShCy+SxJ9CvSDJFlU7MiPFdsh/hrBdIffBsd48HApJjLPI4tnPThBlFJMZI5HBuWZCIt9AmgEzeAJR6JzHeMadnKI8wbYCz4Fkz18JlNwMgf8BCL5j4O3bVaMdUfEhPZqgv1U7HbEbDvoT7HZOPUYNwAlHheV09a4A3RTgMqtj9QY7JdgeM5i3I4+fDIYrQeq/UnyNYOTlBDtS+BwEjk2doz+KyO2OY5bwVCME+/qylTHT4C1D3k+uB33Yul3ov/eMuajlu1RH+II5wtT4hNNSnQ6U/kzbRkfq351bCfF8apAm7kmvq38njWRK0S305SHcSK5XO4U5O9MBmXWbSe3E6YccialdKzH2TTnQEF10XgZ5DdivsxEhkyxjVdERAwu03xmMiqD7hYx19km4cyHq6KyeHKkWpSz+ciVrHVpRYZk/wLHp0H2bULkNKzt4Eq86TKxLq3IECf6nXwV9QPbAfjHQSfoD7SN6L63gYhvbrkiTwKf/dPYpbdPVxKMnigdg0VAG8FQye8AzBl6aIk2A+wPiNoHd63LNZx3wbUAvz/CfTzJb/43AmkGpLfAi0DPE/NALQgtve+xFPdi5xRiNkHa5ySOJ/TR7RrBJdqL4AAxL+p+8ToYAFklNCnF3pM1KPba2L6v8vons5oPsko9ZyZoa0PsOoKezxoY+y5N5DYHWSvDTXzUMJH7IUkRW0tbyyV0CcfDDKmqDMe1KfqnQyehGNgo9q8p4hWYFGsiBY4fsSK/BRkkaPgj5PhMy720BnVFesfnlKo3Das0bw8XYJf196GEuzWRLSDoRypLg2w06FyqTS6Cx7iK1eeqGqrnugmuBgvB8+A5UAuqQYiU+oZ4h2T+BV3gAlDp/pai0U1rFpVGMAv8AHzFd4vShMOQLcoB+DNB/sSbM3ZoMV4BQsW0adSJSbNp1Hu1mY40/YZxpPdJaUSfFzrBMXAjjQNsdvll6cHCWVvKJIphdhcny11pqmolCk5aIDif0BKdZBucgPlO8kh/r8O4HtwClSCbk86HtQqQuUrvKVCf5OARjt0lll4H/WKKmbS0tmJQKZNQ7nq9+w0n2LhTN04E8jKMPpZ1hcli8tGTZYEYJwJrZQGzchTGz3a2ifwdkHc73LYAfpx6DcWXQK1LeiDsdpFGx7UOwUGQJKpmGyIjjvWh50iSQWzsZ/ofgvx+jnYp+B/YpJcB7QXDBKPJ4JDF6+/oCwoBuhoL36R+Jp4RJH16u2IgaxJpHhMehsBY3wTjV2YbOuuumLHrwCW6msbSj74O/DHGgV4Ohl8Jw1nSMmsB+tL6Wnw83odzBrhEr2GtgvFE8A74ADxtJZZygMC25cjQqBwqdg62qpUlziUP45Cq6OGuqqoUE/FJ8i+v7MpJYvEsHl1A5gNty2vLmaN3bBLdAvqB3svqXxLRvyEuc9zs7SiA+ACpw05pJx8SoAAAAABJRU5ErkJggg==" + webUI["html/img/stream-limit.jpg"] = "/9j/4AAQSkZJRgABAQAAAQABAAD/4gJoSUNDX1BST0ZJTEUAAQEAAAJYbGNtcwQwAABtbnRyUkdCIFhZWiAH4wAFABcAFgAuAAphY3NwQVBQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtkZXNjAAABCAAAAEBjcHJ0AAABSAAAAE53dHB0AAABmAAAABRjaGFkAAABrAAAACxyWFlaAAAB2AAAABRiWFlaAAAB7AAAABRnWFlaAAACAAAAABRyVFJDAAACFAAAACBnVFJDAAACFAAAACBiVFJDAAACFAAAACBjaHJtAAACNAAAACRtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACQAAAAcAHMAUgBHAEIAIABJAEUAQwA2ADEAOQA2ADYALQAyAC4AMQAAbWx1YwAAAAAAAAABAAAADGVuVVMAAAAyAAAAHABOAG8AIABjAG8AcAB5AHIAaQBnAGgAdAAsACAAdQBzAGUAIABmAHIAZQBlAGwAeQAAAABYWVogAAAAAAAA9tYAAQAAAADTLXNmMzIAAAAAAAEMSgAABeP///MqAAAHmwAA/Yf///ui///9owAAA9gAAMCUWFlaIAAAAAAAAG+UAAA47gAAA5BYWVogAAAAAAAAJJ0AAA+DAAC2vlhZWiAAAAAAAABipQAAt5AAABjecGFyYQAAAAAAAwAAAAJmZgAA8qcAAA1ZAAAT0AAACltjaHJtAAAAAAADAAAAAKPXAABUewAATM0AAJmaAAAmZgAAD1z/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAQ4B4ADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD/AD/6KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD9PvBf/AARa/wCCrXxF8HeE/iD4G/YM/aL8UeCfHfhrQvGXg/xNpHgia50nxF4W8T6Xa634f13TLkTgXGn6vpN9aahZTgAS21xFIAN1dL/w4o/4LB/9I7/2m/8AwgZ//kiv9b3/AIJp/wDKOX9gH/syf9lX/wBUV4Dr7YoA/wAWr/hxR/wWD/6R3/tN/wDhAz//ACRR/wAOKP8AgsH/ANI7/wBpv/wgZ/8A5Ir/AGlaKAP8Wr/hxR/wWD/6R3/tN/8AhAz/APyRR/w4o/4LB/8ASO/9pv8A8IGf/wCSK/2laKAP8Wr/AIcUf8Fg/wDpHf8AtN/+EDP/APJFH/Dij/gsH/0jv/ab/wDCBn/+SK/2laKAP8Wr/hxR/wAFg/8ApHf+03/4QM//AMkUf8OKP+Cwf/SO/wDab/8ACBn/APkiv9pWigD/ABav+HFH/BYP/pHf+03/AOEDP/8AJFH/AA4o/wCCwf8A0jv/AGm//CBn/wDkiv8AaVooA/xav+HFH/BYP/pHf+03/wCEDP8A/JFH/Dij/gsH/wBI7/2m/wDwgZ//AJIr/aVooA/xav8AhxR/wWD/AOkd/wC03/4QM/8A8kUf8OKP+Cwf/SO/9pv/AMIGf/5Ir/aVooA/xav+HFH/AAWD/wCkd/7Tf/hAz/8AyRR/w4o/4LB/9I7/ANpv/wAIGf8A+SK/2laKAP8AFq/4cUf8Fg/+kd/7Tf8A4QM//wAkUf8ADij/AILB/wDSO/8Aab/8IGf/AOSK/wBpWigD/Fq/4cUf8Fg/+kd/7Tf/AIQM/wD8kUf8OKP+Cwf/AEjv/ab/APCBn/8Akiv9pWigD/Fq/wCHFH/BYP8A6R3/ALTf/hAz/wDyRR/w4o/4LB/9I7/2m/8AwgZ//kiv9pWigD/E88f/APBGT/gqj8K/AnjT4nfEX9hL9ofwf8P/AIdeFPEPjnxz4t1zwTNaaL4X8IeE9Ju9d8SeIdXujORbaZo2j2F5qN9OQRDa20shB24r8yq/28f+Ctf/ACit/wCClX/ZhH7Xv/rP/wAQK/xDqACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA+j/ANmj9kL9pr9snxbrvgL9lr4K+Ovjn408M+HH8X6/4Y+H2ljWdZ0vwvFqen6NLr1zYrNHMNMh1XVtL0+a7RWihu9RsoZSj3MIf7U/4cUf8Fg/+kd/7Tf/AIQM/wD8kV2v/BAD9sj/AIYi/wCCrf7K/wATNW1X+yvh98QPFw+AHxWklm+z6f8A8IJ8aWg8HjU9Xl3Ls0rwd4wufCPxAuz82B4RQlJACjf7MFAH+LV/w4o/4LB/9I7/ANpv/wAIGf8A+SKP+HFH/BYP/pHf+03/AOEDP/8AJFf7StFAH+LV/wAOKP8AgsH/ANI7/wBpv/wgZ/8A5Io/4cUf8Fg/+kd/7Tf/AIQM/wD8kV/tK0UAf4tX/Dij/gsH/wBI7/2m/wDwgZ//AJIo/wCHFH/BYP8A6R3/ALTf/hAz/wDyRX+0rRQB/gx/HT4CfGb9mT4n+Ivgt+0B8NfFnwj+K3hJNHl8SeA/G2lzaP4i0iLxBomneI9Emu7KbJWLU9C1bTtTs5UZ45rW7idWySB5HX9yX/B69+yL/wAIr8eP2V/22/D2meXpfxb8Da18BfiPd2sOy3i8afDG9k8U+BdR1OXbiXVPFHg/xZrukWzB2P8AZnw0jjZIxEjS/wANtABRRRQAUUUUAFFFFABRRRQAUUUUAPRHldIokeSSR1SONFLu7uQqIiKCzOzEKqqCWJAAJNfq8n/BCv8A4LBSIki/8E7/ANp3a6q67vh/dI21gGG5HnV0bB5V1VlPDAEEVv8A/BBj9kX/AIbU/wCCrf7Ivwo1PTP7T8DeGPiFb/Gz4nRTQ+fpzeAvgpE3xDv9L1hQrEaZ4w1nRdD8BSkAFp/FdvH5kO/zo/8AZ4oA/wAWr/hxR/wWD/6R3/tN/wDhAz//ACRR/wAOKP8AgsH/ANI7/wBpv/wgZ/8A5Ir/AGlaKAP8Wr/hxR/wWD/6R3/tN/8AhAz/APyRR/w4o/4LB/8ASO/9pv8A8IGf/wCSK/2laKAP8Wr/AIcUf8Fg/wDpHf8AtN/+EDP/APJFH/Dij/gsH/0jv/ab/wDCBn/+SK/2laKAP8Kz9p39iX9rL9i7UfCOkftV/AT4ifAfVPHtlq+o+DtO+IejjRb3xDp+gz2Ntq97p1s00k0lrY3GpWUEs7IkbSz+XGztHKI/lqv6F/8Ag5+/bI/4a5/4K2/HDTNF1X+0fh7+y5aaZ+y74KEU261GofDq61K8+KVz5UbG3N0fi9r3jnSTexl5bzSdE0USybLeCGD+eigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD/cg/4Jp/8o5f2Af+zJ/2Vf8A1RXgOvtivif/AIJp/wDKOX9gH/syf9lX/wBUV4Dr7YoAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD8+P8AgrX/AMorf+ClX/ZhH7Xv/rP/AMQK/wAQ6v8Abx/4K1/8orf+ClX/AGYR+17/AOs//ECv8Q6gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAHI7xOkkbtHJGyvHIjFHR0IZXRlIZWVgGVlIIIBBBFf7Z//BIH9sRP28f+Cbv7J37St5qS6n4x8VfC/TPDXxTmMqvc/wDC3PhxNcfD/wCJdxdQ5Mtp/bPi7w3qfiLT7e4zK2jazplyHnhuIrib/Eur/QW/4Mm/2yPteh/tZfsE+JNV3T6PeaT+1D8KNPml3yNp2pDRvht8YrW381t0NrYahB8JtRtLK33Rtda5r980cUjzyzgH98VFFFABRRRQAUUUUAfhR/wcifsif8Ngf8Eif2ndD0vTP7T8dfAvSbH9p74ehYvPuINW+DCXur+MUs4FUzXF/qvwjvfiRoFhb25E819q9skazn/R5v8AHer/AH6NW0rTdd0rU9D1mxtdU0fWdPvNK1bTL6FLmy1HTdRtpLS+sby3kDRz2t3azS29xDIrJLFI6OCrEV/hv/8ABQv9lrUv2J/23/2ov2V9Riuo4Pgv8Y/GHhbwzPe7/tWqeAJdQbWfhrr83mfPu8R/D7VPDOvjcWO3Uh88n32APjeiiigAooooAKKKKACiiigAooooA/0D/wDgyU/ZE+z6T+19+3Xr+mYl1G70D9lz4Y6lJFtdbSwTSfif8YfKaRd0lvd3Vz8HreC4g2xifS9VtneSRHSD++mvyl/4Ih/sif8ADEf/AAS3/ZB+B2o6X/ZXjV/hhYfE/wCKEEsPlahH8S/jDNN8SfFmmaq21WnvfCl14ki8EpKw+Ww8M2MCExQxmv1aoAKKKKACiiigAr5A/b+/ao0X9iP9iv8AaZ/as1xrRk+Cfwi8V+LdCsr5gtrrfjk2R0j4c+GZWLKF/wCEq8f6n4a8NodwxJqqdeh+v6/ib/4PTP2yP+EA/Za/Z5/Yk8N6r5WvftCfEG7+LPxGtLWb98nww+Dogh8OaVqtvuA+weKviT4g03W9Nk2uWvvhfdrujEZEoB/nB+IfEGteLPEGueKvEup3eteIvE2san4g1/WL+Uz32ra1rN7PqOq6nezNzNd399cz3VzKeZJpXc8mseiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD/cg/4Jp/8AKOX9gH/syf8AZV/9UV4Dr7Yr4n/4Jp/8o5f2Af8Asyf9lX/1RXgOvtigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAPz4/4K1/8orf+ClX/AGYR+17/AOs//ECv8Q6v9vH/AIK1/wDKK3/gpV/2YR+17/6z/wDECv8AEOoAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAr9V/+CJP7ZH/DCn/BT39k348anqv9leA2+Itp8Mvi1NNN5Onp8LPi3FJ8P/F+qaou5RPaeEbfXYPHcMLMB/aXhXT5R80Sg/lRRQB/v8UV+TP/AAQ5/bI/4bo/4JdfsnfG7VNV/tXx9p/w+tfhN8WpZZvO1Fvid8IJG8A+JNV1f5m8u/8AGUWi6d8QFjDECx8W2TgRh/LT9ZqACiiigAooooAK/wA07/g9I/ZE/wCFcftj/AD9sXQNM8jQP2lfhZdfD7xtd28O5H+KPwOnsbO31HUp1A8q41z4a+KvBmkaXDN808HgPUnhZ1tplh/0sa/nd/4Oi/2RP+Gq/wDgkT8cNZ0fS/7R8dfsuapoP7T/AITMUO64TS/ACahpXxSVp0Bnjsbf4ReJvHOuz26hoLi+0HS2nQG3iuLcA/yKaKKKACiiigAooooAKKKKACv02/4I3fsi/wDDcf8AwUy/ZC/Z3vtM/tXwfr3xX0nxh8TrWSLfaS/Cr4XQ3PxJ+IlleyMGhto9d8L+FtQ8NWk04MbaprWn2yxzz3EUEv5k1/eL/wAGTH7In9reP/2uf259f0zdZ+D9A0H9mf4Z6hND5sEmveK7jTviL8VprV3Gy21LQ9E0b4YWSTwlp207xnqVsWhgnkS5AP8AQzooooAKKKKACiiigAr/AB3f+DkD9sj/AIbN/wCCtf7SWvaRqv8Aanw9+BGpWv7MPw1aOf7RaJovwcudR0zxfd2E6MYLnT9d+LV/8RfEWm3dsPJuNM1axZJJ1VbiX/Ux/wCCnv7XVn+wl+wF+1T+1TLdW1trXws+E2vXHgJbsRtBe/FTxOYPBnwo02aKQMJbe/8AiN4h8MW16qxysti9zN5UixMp/wAQK+vr3U7281LUru5v9R1C6uL6/vryaS5u729u5XuLq7uriZnlnubieR5p5pXaSWV2d2ZmJIBVooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA/sa/Z9/4PGv2mv2ffgJ8EPgJo37HXwJ8QaP8EPhD8NfhDpOv6n43+IFtqWt6b8NfBmi+DLHV9Qt7QfZbe+1K10WK9u4bb/R4riaSOH92q169/xG8ftWf9GRfs9/+F98R/8ACv4h6KAP7eP+I3j9qz/oyL9nv/wvviP/AIUf8RvH7Vn/AEZF+z3/AOF98R/8K/iHooA/t4/4jeP2rP8AoyL9nv8A8L74j/4Uf8RvH7Vn/RkX7Pf/AIX3xH/wr+IeigD+3j/iN4/as/6Mi/Z7/wDC++I/+FH/ABG8ftWf9GRfs9/+F98R/wDCv4h6KAP9GT/gmX/wdhftE/t2/t3fs3/skeLv2T/gt4E8N/G/xpf+F9W8XeHPGPjnUNb0O3tPCviHxCt1p9lqY+wXEzzaNFbslz8gimkYfOq1/cpX+NT/AMG73/KaX9gD/srmtf8AqtPHVf7K1ABRRRQAUUUUAFFFFAH8KH/BRT/g7X/aN/Yq/bf/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WOj6BoOn3Gq6xql5Jg+Xaafp1pcXdw+DshhdsHGKAP8AN2/4PR/2yP8AhY37XHwD/Yq8N6r53h/9m34dT/Er4g2dtNiP/hanxqFlcaTpmqW4Yh7rw38MdB8M6zpUzhWitviTqKICJmJ/itr6y/bt/ah179tX9sf9pP8Aaq8RG6juvjh8XfF/jbS7C9fzLjQfCN1qUln4D8LF98m6Lwl4IsvD/hm2Jkc/ZtJiBdj8x+TaACiiigAooooAK/2Hv+DZvSf7G/4Id/sIWe3Z53hv40atjGM/29+0r8Ztc3f8D/tHfnvuzzmv8eGv9kD/AINw7+HUv+CJ37A1xAqqkfw58c2DBOhm0r40fEvTLhj/ALb3FnKz/wC2WoA/biiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAr/JJ/4Ow/+U2X7Q//AGTv9nj/ANUr4Nr/AFtq/wAkn/g7D/5TZftD/wDZO/2eP/VK+DaAP5vaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKK6vwJ4G8W/E3xn4X+HngLQdQ8UeNPGmu6b4a8L+HtLi86/1fWtXuo7OwsrdCVRTLPKoeaZ47e3iD3FzLFBFJIt06dSrUhSpQnUq1Zwp06dOMp1KlSpOMKdOEIKUpznOcIQhGMpSlKMYpuST58Xi8LgMJisfjsTh8FgcDhsRjcbjcXXpYXCYPB4OhWxWLxeKxOIqUaGHw2Fw2GxGIxGIr1aVGhQoVq1WpTp0pzj9Y/sAfsT+O/27/wBofw38HvC32vSfCtqY/EXxU8cx2/nWvgfwDZ3MMep6gDIpgm13VHkTR/C2myZ+361dwPcCLSrTVL2z/wBHr4T/AAs8CfBD4beC/hL8MtAtPDHgPwBoNl4c8NaJZj5LWwskOZriZv3t7qV/cvPqOr6ndNJe6rqt3eal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gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAr+z7/ggp/wTT/4VH4Psf20vjV4f8r4n/ELRXX4K+HtVtsXPgT4d6zbFJvGk8E6brXxN8QbCXZpbIqz6X4Hn/17P4t1GysPyI/4Ip/8E13/AGxfjB/wuX4r6G837N3wa1q0m1S1voD9h+KPxAtlg1HSvAMXmL5V3oOmRyWmt+O8ear6bNpfh14h/wAJK95p/wDedHGkSJFEiRxxoscccahEjRAFRERQFVFUBVVQAoAAAAr+o/AXw29vUpcdZ3h/3FGclw3ha0NK1eDlTq5zOE1rTw8lOjlzaaniFXxkbxw+Hkf4Nfta/psf2Tg8d9FLwvzi2aZlh6E/GrPctxHv5dleIhRxeC8NsPiKFS8Mbm1KWFzPjSMKkZ4bKJZTw5VUKub5vRT6KKK/rU/55AooooAKKKr3d3a2Frc319c29lY2VvNd3l5dzR21raWttG01xc3NxMyQwW8EKPLNNK6RxRozuyqpIG0k22kkm220kkk2222kkkm220kk22km04xlOUYQjKc5yjCEIRlOc5zlGMIQhGMpSnKUoxjGMZSlKUYxjKUoxlYoqlpuo6frGn2Gr6TfWeqaVqlla6jpmp6fcw3un6jp99AlzZX1jeWzyW93Z3dtLHcW1zBJJDPDIksTsjqxu0k1JKUWnFpNNNNNNJppptNNNNNNpppptNNucJ0pzp1ITp1Kc506lOpCdOpTqU5zp1KdSnUjCpTqU6lOdOpTqQhOE4ThOEJwnCBRRRTJCiiigD8if+Cvv/BOiw/bq+A0ms+CNNtIv2i/hFZalrXwv1HENtN4u00p9q1z4X6pdvsRrXxCIRc+Gp7yRIdI8Vw2j/arDS9W8QPcf59Ooaff6Tf32larZXem6npl5c6fqWnX9vNZ31hf2Uz215ZXtpcJHPa3drcRyQXNvPGk0E0bxSIrqyj/AFjK/kJ/4L+/8E2P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/DSP/BUjUvgr4f1X7d4A/Y18AaL8IbSK3m87TpviZ4mSHx78VtVhBYmPULa61fw18PtYjCoEvPh1sCsVMsoB/LfRRRQAUUUUAFFFFABRRRQAUUUUAFf6lH/BsR/wW/h/bw+Ddn+xj+0n4qib9sH4C+E7ePwt4i1m7Vb/APaF+D2gQwWFp4kW4nYPqXxM8BWv2TS/H9u5k1LxFpA03x8kmp3U3jWXRP8ALXr0j4P/ABg+J3wA+J/gf4z/AAY8b6/8OPil8N/EFl4o8E+NvDF61jrWg61YMTFcW8oDxT288TzWWpabew3OmavplzeaVqtneabeXVrMAf72FFfzsf8ABCH/AIL2fCb/AIKr/DKw+GXxPvvDPwy/bk8CaKg8e/DJbqLTdK+K+nadbZuvil8HrW8nM9/pc8cL3fi7wbBJeav4DvTKZvtnhqfStbu/6J6ACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA+HP8Agp3/AMo1v+Chf/Zjn7WX/qhPH9f4dVf7iv8AwU7/AOUa3/BQv/sxz9rL/wBUJ4/r/DqoAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKtWNje6ne2em6bZ3WoajqF1b2NhYWNvLd3t9e3cqQWtnaWsCST3N1czyRw29vCjyzSukcaM7AFpNtJJttpJJNtttJJJJtttpJJNttJJtpOZzhThKpUlGEIRlOc5yjCEIQjKc5znOUIQhCEJznOc4QhCE5znGMZSj7x+y5+zX8Sf2t/jj4G+BHwr0/7V4l8ZaksdzqVxHK2keFPDtpifxB4v8AEM0SsbbRPD+nCW8uiM3F5MLbStOjudV1CxtLj/SQ/ZX/AGZ/ht+yJ8DPA/wH+Flh9n8O+D9PAvtWniiTV/F3iW8CzeIfGHiGWIYuNZ1+/wB9zMNxgsLUWej6ctvpWm2FrB+fv/BHj/gnDZfs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FABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFF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FFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAH//Z" webUI["html/img/users.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0wOC0zMFQxNzowODozODwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CjU01MMAAANJSURBVGgF1ZnLaxNRFMYz2rpoFbW+SCsihaJQRMT6rPhAXAq6c+HChSguRFd1oRtd+A/oWhQ3oiiWFB91UbqRqlXXgoIIQhFbQTTQao2/GzLDZEjIPefO7SQHPjJz55zzfd/MZCa5N8h5ilKptJvWp8FekAed4Bv4Cj6Dh2A4CIJZPpszMHEV2MQ0SZdB0DROENMHjoEzQBoFCpZnbgYR58E/qfpE/kv2F2dmBvJ94G9ClHb3SiZGUBuASa3qGnVzjG3RmFmkKYrVHGB7e2zfdbOdBhc1TVyNnNSQNqg5wVURf/FdjRxpIEpzuIOio9JCtRHO2hrINkgJLfPFt6vaCII2WYrSpPVJi1RGuBrmTbxeSibIX5j3CUauAfOo9BXzNH4nMJ5TXREI1gHzqPQVRtc2zCyxJdAaGbclcMj7zi/jOdt6rZFhCH7akijznknqVEY4U78heSAhUuTekNSojFQIChIiYe57TtZrSY2LkecQzUjIBLljglz3VJ4qg+AXSDNGabbWXZ2wA6Qjabqg136hhHK6y60V8o2EGyl8/qHHpKZPGkYeQzyvIa9RM86XvFhjvOGQsxGIp2B50ZDJLuG2XZqnLO5rM3viGh9o0OZJon1bRLxxdHLcns1jJiYOAu2U0D2P0uStMXJdcVU+UdMlZ/NYgaA28ERg5ge5/R4l6VsjrANMWJiZJWeXnqm60vnxW90ul6u8ByaS4zX2i+S+qjGuGkrdSEWFzT1vlhlSC19Gui0UtnNriSfi6vX1ZWRjPcLEeGrzYqkb4SyvQGxvQnC93cF6BzIfx8gpYBsfSdycuei4AAR1ggugCCRh1lbugIF4vwXbhtisjfSDc+ARSOOf4lv6mNWv1VIj1ouQNF9K851gDzArtWbV1uYxS5o4zB+sp+AuKPC+cVv5RXwPuATMmUpreY1Wopgh+ybYKj4dFHWB+8DMwTZTjCHmsJUhEgfAF9DMcQtx9V8dHMyDqWZ2ENM2FL8yVV92kkY56GM5Lc6Z1vY0jbp5EJQnuqPLg4kdLWTCnIxVIJoDi4wweNYcbbGIfuLEjRxqMRNGbvTvsmyE22oZg70taKQn1BxekXw40GKfK0O9oZHsJ8ZCRbLPaI3xP7YzeQoHxWckAAAAAElFTkSuQmCC" - webUI["html/img/logo_b_880x200.jpg"] = "/9j/4AAQSkZJRgABAQABLAEsAAD/4QDIRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAPAAAAcgEyAAIAAAAUAAAAgodpAAQAAAABAAAAlgAAAAAAAAEsAAAAAQAAASwAAAABUGl4ZWxtYXRvciAzLjMAADIwMTk6MDg6MDIgMjA6MDg6MTQAAAOgAQADAAAAAQABAACgAgAEAAAAAQAAA3CgAwAEAAAAAQAAAMgAAAAA/+EJkGh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iUGl4ZWxtYXRvciAzLjMiIHhtcDpNb2RpZnlEYXRlPSIyMDE5LTA4LTAyVDIwOjA4OjE0Ii8+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD94cGFja2V0IGVuZD0idyI/PgD/7QA4UGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAA4QklNBCUAAAAAABDUHYzZjwCyBOmACZjs+EJ+/8AAEQgAyANwAwERAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/bAEMBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/dAAQAbv/aAAwDAQACEQMRAD8A/iHoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP/9D+IegAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA//0f4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//S/iHoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP/9P+IegAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA//1P4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDvPDXws+J3jPT31bwf8OfHnivSo7mSyfU/DXhDxBrunpeQpFLNaPe6Xp11bLcxRzwSSQNL5saTROyhZUNAHQf8M//AB4/6In8XP8Aw23jL/5TUAH/AAz/APHj/oifxc/8Nt4y/wDl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f/E3xn4o+IPjnxDLaafp8mveMPGet33iPxNrMlhpNpYaVZPqmtale3z2mmWNlp9s05hsrS2tkjhQA4ygAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//S/iHoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAczu+N7M2BgbmLYHoM9BnJxx1/FgBtABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAOLuwVWZiq/dUsSFz12joM4HQduc4FADaACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//0/4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//U/iHoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP/9X+IegAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA//1v4h6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//X/iHoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP/9k=" - webUI["html/img/filter.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0wNy0yOFQxOTowNzo2OTwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cs038OQAAAOISURBVGgF5ZpLSBVRGMfvvfmqCKKiKCqKtE3SQ8haJJm1ctPCZYHrFhXtohcUBLVsU1BRBJKLXpsSKs1aCL1oUUhvMgIloodZKmLZ72+OzNVx7jzOXGfqg/89Z875zv/7f35n7px7vanUP2JptzyGhoYKmK8GW0EZmA/mgW7wHrwDN0BTOp0epPVtxBBnLdgIVoE5YBboBR2gDTTA/5DWn0FeDPaBz8CLdeF0EBR5jYRvKbgABoAXa8Opwit/CudK8NoLs4PPM8ZyBsNnB/jpsD7X0C8cjgDXnaQkqkEPCGMSuGWivxxzx8OQj6xtpHWuPhPloHfEMWzTD0HN2GQY2xuW2Lb+/Fh+VaIQPLE5meh+gmSxFYz+BjBogtjGscfiH26Z2GmbNNltVQAIpwDdP6ZNO2iRYqTpZGhfgWUaiMC2w1kCzkbALcqLvDVvUyK6MW9HFES0b8BvsFwXEZi4F+iBtykCcjtlqf0igr52VJ1eqiIgzzdlrRIZfWfJd3SD8ZbqHvkB4XSDpJNB9V0VcX/cT4Ys/zEzSuSj/3WxW9GpRD7ETpZ/QcOJ6LyfdHugitxNehbob9G7lo4PXWBmQhPqQ/fsDOeUfjqNCU1Csi+TQ5+2luzc3yaRr6elevQZwhZr4bomYam0U41yabYqov5hvSTMjlp6RyuiAarSTLPZmox5246+lVREx/isiuh6NxhUJwF2yEpCWu1bK8WEsjyRgCSa0XrVrjNra2mC7TWD5ilYAuJoA4jSlnppF5dVEU3g0ENTD4b3nsZiZsfGJuGqj8qY+CINGqP2GLZCJ+HjtpblxAJ9k3cPrLfGJrnVUaSCarxw0jFua1lOLNBerANx+byya6IkLM2uLZWpAl6/Mcc1EjvjKtLrJNLqI5HnjfQ+bsVeteb0g2y/t7hGvd7CNjenOL8OkJ40KtOdTF+Cl/nV6Mkf4gxocI9vZPYLLKs9iQrqRIACcM2IXGeSboYrg+rztY5ARaDJWUeo0W+sXudLTFhnApaAW6FkZy/+yuXasLoCrSfwVHAnW0+gK93YawKJMLUIAdNAKwhqnSxcYUpPKB6EBE2mg7VR///EX24jybTQerXnOC70FyVP3gjTPXPTQyaP8NFPNeJrCNTPP667JKOq6VNo/A2hes5ccUjmEmPmDoD5+FMgWCcA+3FG57QJP//kQ1PgGBIOToEDgUn+t4V/AJeGknwARIKLAAAAAElFTkSuQmCC" + webUI["html/img/x_ transparent.png"] = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA6ppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0xMS0xNVQxNzoxMTo3NjwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6Q29tcHJlc3Npb24+NTwvdGlmZjpDb21wcmVzc2lvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MTQ0PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xNDQ8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4yNTY8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjI1NjwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgoeXQb1AAAaJElEQVR4Ae2dCZhcVZXHz+1KSFiGkISkqyIoOgI68EkgOBNkEcQRlIFRZDGABAQEhInGbxw+RUZRNhWRLawDYR0GHAaHUVkGvwGURUcgwIiAOGxjV3UHAslHQrbuM/9TlQ6d7qruWt527/u/7+uuqvvucu7vvnveuffde54IDxIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARIgARLwiIDzQtayHi0q23shaydCOnlISu7nnWThRdrFOkPWyCleyNqJkF1yjhTd8k6yiDvtuLgLiCR/lVnIZ14keWU7k2Xyuu4oU92r2RazQ+nWypXI4W86zCXbyZ28KBvJ97MtpEhX1gWsyleS08TJU17I2omQKpvLarmqkywyn7ZHPw9rLvTOvwbX6xEyxS3Nenv4oQCcWwmQc/D3dtaBdiyfyv5S1mM7zieLGSzWEsS6KIuiRSzTGTD9H404z1iy80MBWNVL7hn8nx8LhaxlqnKBvKbvyppYHctTM/0nd5xPljNwcrcUs2/6DyL0RwGYxDOcjR3vGBQ+4M8tMElmdQ3n6NGjYPofGE6F6tTESRmm/1xxTuuczWSQH08BhqJbqlNkuTyJoK2GBgf53S6mkrvB+7qZ6b9Gfod6hHv3dzKAGbX9pNvd51N7+WUBGNlJbgm07FH4G/AJdFuyqlwotXFzW8kzk2itXAFZwu38BlrlPN86v4ntnwIwqUvuASiAc+1r4MdkqXUef6tZM/0P8rcCTUmO9RvyraZiZiySf0OAQYCq46QiD0Lz7jYYFOxnARZPt7vZu/r1aREKzEz/Kd7J3rzAS2Si7IxHfq80nyQ7Mf20AIyfc2thBRyJv2XZwRmTJP14dNar3THlHl+2Nesl5M4vUpDjfe381vD+KgCTvuhehAI4yb4GfkzFjMdlXtWxV4+EvH/rlcytCutkASwzr59K+TsEGNpYZb0OQ4G5Q4OC/N4ln4PSuzXzdcuH6b8I4/7ZsERXZb49RhHQbwtgsGIFORWWwAuDP4P9HJBLsUpwWubrt1Yuh4zhmv5O3pLxUMaed367jsJQANPdW7AA5kAJrMl85+hMwC2RfEFnWcScuqJHoIRPx1xK2tmfKtPcc2kLEUX5YSgAIzHD/Rb/T48CSqbzUDkUVsAhmZTRTP8BuTiTskUllJMb8Bj6+qiySzufMOYABimq2mLMe/DzrweDgvx00iebyg6yuXstU/XrUZsQC/nu/5yMk13FLM5AjnAsAGsQW4M93tZiy+JA2qd+NVSmYzn0JfVPphRa0TkoOeTOvwqdf05Ind+ulLAUgNVomivj/7H2NehDMQnVq5/JRB1tjcJAxhRS1GC65Gvo/E9EnW3a+YWnAIxoyf0M/8Mei1o9bW2AbY5K++ivzvpPTVuMGMv/CR6/ZsviiqiyYSoAg1OSf8BQ4KmIOGUzG8XO8+UpK7qKfg5wsmGJxNNKr2C+5bh4sk4/17AmAYfzLOtf4PGgPR3YePipoH53YcVd0d2ZeJ3M9O+vrvUP8+7vsJOhIPvA9P9V4mwTKjBcC8AA5sWLkGK77Zua/Hbb2vLkMDu/XT8qZ4bc+a2KYSsAq6F5EXLyb/Y12EMx4HkbvgOSPCp6ODrIwUkWmWhZTn4BquckWmYKhYU9BBgEmhcvQk4OgNUT/3sFKjodE5C2zddWJoZ32DqLcTJz3ROl8Oo3pEbhWwBW2bx4EVK4FF+ik4a0bzxftbozMdTOr7Bs5uah89vFkQ8FYDWteREK3aR7l6yCR+E4j7Iehg7y2TiLSDnv8zFsvDtlGRIrPh9DgEGcefEiVMC7BbqdLYmO9gjf9H8UD1b3worS0DeVrb8u8mMBWJXNi5DgjS1Olq4nEOKXfrkarxjbPPKqaXUnYpimv8ibuC5wbeSn89v1kS8FYDUuuZfQ0KF7EdoaQ4HzrbqRHWU9FKb/IZHll7WMnHyx6mEqa3LFLE++hgBDYZZ1IS7oY4YGBfe9gF2RUfiprzkh+R14Zd8ZSXuNeBXG/Se2l9TvVPlVAH26GdZ5PY7m29bvJhxFeicvYyXbjh3vYCvrbej8h45Skr+nnDyNcf9fwfQP/72TdVopf0OAQQi1Pd1hexFSeQ+W6v5gsMptfdZM/zA7v8gKMDHXXrns/HY95FcBWO1nuMfw/xv2NeDjRHgQ2qet+tVM/wVtpfUhUZfMW7dc3AdpY5Ex3wrAkBblh/j/n7HQzUKmiilPkWukopu2Ic6lAY/7b8Gk3zVtMAkqCRWAeREaJ0ejm4TrRUjlvejI57V05ZrfQZXDWkrjS2Qnf5QJwT8Jaqo18jsJOBxPWQ/ABf/T4cHB/HaonWBrq62IHOtYplvCz4DN+k8fK6qH51dD5t0x/LNt4rk/aAEMXgKhexEaHAqobjJY5Yafy/H+gTA7v1X56+z877Q8LYB3WGD/t06AV+FfI2inocGBfb8IHeArDevUo7bO/18bnvf5hIOFV5SDMOtv1hAPEKACGH4Z9OgHEWTm4dh3yuFpffjtsJG3IB+t6+gibNP/T7IZtvhmzZV6ytcMhwDDG2CG+z2C5g8PDua34tHvWjwVUB3pJi1U099hNYTDK9bZ+UdcxlQAI5AgYIa7ChdMyF6EtpOKnLVB1Xv0YIz7D98gLJwfZ2Hy8/5wqhNdTTgEaMTSfOytkCdxeutGUbwOt6FAl+yBvQKPSMimv5MHMO7fF+P+fq/bKybhaQE0AruFewOnjoIlMNAoitfhNhTol2sxFJhYfctQmLP+r+FNUUey8ze+UmkBNGZTO1PW78A0PmOsaN6et0UxKn/urfyjCd4lB2K1X7hrO0are5PnqADGAqVawKPBBxHtI2NF5flMEbgQcznhTuZGhJoKoBmQZd0G0RbhThm/w81m5GGc0Qk4PMYtYrWfc7bqj8coBDgHMAqc9adqXoRy6TBiPQNfvjhZhnUO2ObNzt9Mk1EBNEPJ4hTdrZgQXNhsdMZLiYCTk7HI6YWUSveuWA4BWmky21I7UPUitF0ryRg3IQIOTzVKLtgXecZBkQqgVao9OgtJHsbfRq0mZfwYCTh5BuP+D8P0Ny8/PJokwCFAk6DWRzMvQi54L0Lrq+vJl7fRJubai52/xQajAmgRWDV6sfr2nXvbSco0sRD4KuZono4l58Az5RCg3Qbu0yJW0j2JR4MhOs1ol0ry6Zz8GOP+w5IvOIwSaQG0247TXQVJj4Xpyb3l7TLsNJ2Tl2QiXujBo20CVABto0NCexW3ysWdZMG0bRJwsgbKd45Mdm+2mQOTgQAVQKeXQUlOQxaLOs2G6VsmcAbG/Y+2nIoJNiDAOYANcLT54zX9gKwWe8dAmF6E2sQSY7J7pCSfxKw/h18dQqYF0CHAavIt3bOwpRr72YuiDOZRI+DgyqTL3Liz80dxSVABREHR8ii6qzEmvT2q7JhPHQI1JyafB+u+OmcZ1AYBKoA2oDVMsrGcgHOvNjzPE50RsJebRPG2486kCCo15wCibs4+3RPrA/4LTwcKUWed8/wewrh/b5j+a3POIdLq0wKIFCcym+5+if9nR51tzvNbguf9R7DzR38V0AKInqm9YMS8CD2ArHePI/vc5VmQg2H635G7eidQYVoAcUCueaCFM0pZGkf2ucrTyQJ2/vhanBZAfGxFynoY5gJujbOIwPNehHH/bJj+qwKvZ2rVowUQJ/qSuw1WwLVxFhFs3k7egktv2+LLzh9jI1MBxAi3mrWTefh8Pu5iAsz/VJnmnguwXpmqEhVA3M1RdMtxJ5uDYuihtlnWTm7ARqvrm43OeO0ToAJon13zKae5xzEU+EbzCXId83msoDgl1wQSrDwnAZOCrerwaPAuFLdfUkV6WM4qGSe7YS3FEx7K7qXItACSajbbvFKQubAEuI69EfMu+Ro7fyM48YRTAcTDtX6u3a4XJ46BEuA21pGEfoJNPpeMDGZInASoAOKkWy/vkrsL3f+ieqdyHPaKbCrH5bj+qVWdcwBpoFedgPkA82YzM43iM1Wmw9apguwN0/9XmZIrJ8LQAkijoW1xy0bVR4P0Y6/ybXb+NC7CWplUAGmxr3kR+nJaxWeiXCe/wFLfczIhS06F4BAg7YYv648xJ3BI2mIkXr49DRmHIdA0V068bBa4ngAtgPUoUvoysepF6JWUSk+z2MvY+dPEXyubCiDtNjC/9g6PBvN3zJUlOil/1c5WjakAstAeTvbNghiJyqDyXlkplydaJgsbQYBzACOQJBzQqx+XAbkH8wD5VMYOr1cruesSps7i1hGgAkjzUqjodHR8e8FoMU0xUi3b9v0XZBc8CvxDqnLktPB83nWy0Ni2OWgA217z3PmtHVQ2w1Kgf4YfxY2y0Cx5k4EKIK0Wr2DjC3cG1uir7Ir3/dCTcgrXIocAKUCXis7Gne9B/I1Po/hMlmkbpLpkfzgAvTeT8gUqFBVA0g37hm6B2e8ncLlvk3TRmS/P3vvnZCe++iu5luIQIDnWtZJWytXs/A2g23yI0olqAzqxBFMBxIK1QaY9ehIu8Pwt+22Ao26wygEYIuV7j0RdMPEEcggQD9eRufbqhzDb/WucmDjyJEOGETDXYLPxaHDRsHD+jJgALYCIgdbNTnUTPPL7F5xj568LaETghHWPBjcZcYYBkRKgAogUZ4PMKnIJTP8PNjjL4HoEjFdZLqx3imHREeAQIDqW9XOq6BG4+99c/yRDmyBwiMxwtzcRj1HaIEAF0Aa0ppP06fthyj6Ou/+fNZ2GEYcTeEMm4NHgVPfq8BP83TkBDgE6Z1g/B1vauhbjfnb++nyaD52MdyrdVH3levNpGLNJAlQATYJqOVpZvoc0s1pOxwQjCajshSVCp488wZBOCXAI0CnBeukreiDG/XfWO8WwNgmY9+Au+SiWCj/UZg5MVocAFUAdKB0Fva5bySqx59dTO8qHiUcScPISHqTuLOZFiUckBDgEiATjukxUCxiv2ow/O3+UXAfzsv0TK+WKwZ/87JwAFUDnDN/JoSJnYNJvr3cC+C1yAiqHY6nwFyLPN6cZcggQVcOXdR9kdR8UAJVqVEwb5eNkOZYKz4JX4ecaRWF4cwR4sTbHafRYZZ2GCHhUxc4/OqiIzireJLiGXoSioEkF0ClFc+0lch06/4xOs2L6lgjsgkeD57aUgpFHEKACGIGkxYCyzEfn/1SLqRg9GgLzpUf3jyarfObCOYBO2r2sH0byh6AAxneSDdN2QMBJLwZeO2F9QG8HueQ2KS2Adpv+dd0cSW2pLzt/uwyjSKfSjUVXC7FUmDezNnhSAbQBrZpktVyJzv++dpMzXYQEVD6JrcNfiTDH3GRFrdlOU1f0eNx1rm4nKdPERsC8CO0GL0JPxFZCgBlTAbTaqGXdAXf+3yAZvdW0yi7++M9iPmBXeBVeHn9RYZTAIUAr7ai6MaKbay92/la4JRf3A7DMLkquOP9LogJopQ3NRZXKjq0kYdzECRwnZT008VI9LZBDgGYbrqKH4+5id38e2SdguwVnwpXYy9kXNV0JaQE0w79X34c7/5XNRGWcTBDYAlLQi1ATTUEFMBYk1fG4898CBTBprKg8nykCe2Cp8BmZkiiDwlABjNUoFTkHnf8vx4rm5Xknl0Huh72UvTmhvyl9umdzUfMZi3MAo7V7WW2N/0+hAELk9LyU4F3nNdkaO+sWoZ5hvrTEycuo2Ux6Eap/odMCqM9FZLHa7j7b5Rde5zf/egU5RpxbUd1T7wI2lVXeAy9CVzVq5ryHUwHUuwJUu+DS2/b32z7/EI/zsXnmkfUVK8qPoOYeXf87tC8qh8KL0PGhVSuK+oR3d4uCSlnNtdd3osgqc3k4eRov4d4Vd//VG8jWo/bqMltGO2GD8FB+mBeh8aj3lu7ZUKoURT1oAQyn2KPm0+9bw4OD+O0w2i/I0SM6v1Vuhvs9rIAw6231My9Cq6tehMJUcFbHNg4qgKHQlql5870ZF0thaHBA37876iu3i3I+lMB/B1Tf4VXZGbsGzxsemOffHAIMbf2y/js6/0FDg4L57rCBqSi74+6/dtQ6VXRHrHt4DHE2GjWerycdWljkACm5u3ytQpRy0wIYpFnRecF2fsE8uFZn/Ufv/Mai6P4HO+rOHMQS3Gftqc51WB9QDK5ubVSICsCg9egs3PV+0AY/X5KcXh3jNyttt3wfUR9vNrp38VSm4ykPHvHSixAVwGK1V3ffgr9QTd4HsODnwpY6qQ0TCnIs5gPWtJTOr8j7YanwV/0SOXppqQDWyOXAum30aDOQo5O30InRkd1Ay9J0u6eQ5qyW0/mUQLHMe7Hu4pPIUcua70nAsh6DsfHCqKFmKL+TYPq3v4vRNkKVq96PZmaoTlGL8hzmPGbl1YtQfi2A2sKXS6O+mjKTn5O7O+r8VhHn1sDP3hcCHwpsj5vAJZlpt4QFyacCUJ2Ii9pcem+aMO+kinsDq96iWfpac7J5blKCp1KOYphkDl9yeORTAVTkAnT+DwXc3vOw5PVPkdWvKGdDYT4dWX5ZzGgArx0v6zZZFC1OmfKnAHr0s+j8J8cJNdW8ndwO0/+mSGWwfQN2l3R4eBbusQXqmDsvQvlSADUN/0/BXsNO+lC3eJTbDPcYFMD3gmVXq9jueDQY7n6IOo2Xn6cAquPQuA9Cy+9Wh0MYQQU5GNt874itMqoTwPAxMNwhtjLSzth8Jah8DFbUg2mLkkT5+bEAyvLdoDt/F8zXODu/XY3OrcJ/eyrQn8TFmUoZtY1gN8mbOjmV8hMuNB8KoFc/gYv2tITZJlnc/2EX/98lUmDJ/QblnJ9IWekVsrW8nY9Xv4U/BLBNH/3weWdvkQ31KMj+uPvfk1j17DFqBXsFVMyJSMjHiRgKBO1OLGwLoOba68agO38X3leQZOe37u7cSlhUNhRofYmxX+riR9goFrSSC1sB9FbN/o/7dc21IK2TP2IZ69+3kCK6qEVnPgQviC7DTOa0CaTCOyEw+RnoEe4QoFd3x/3pftz9xwXZdnb3Lcje8PDzy9TqZy9LLVddim+XmgzJFHwxhgJfTqaoZEsJ0wKwGdx+8/8WaOevXSMXptr5TQbn3oYSysNQYB5WCR6QbNdMprQwFcAKuQb43p0MwhRKcfIM3HudnkLJI4vsdg9hLiAPr+ReiK3DpZEA/A4JTwGU9RQ0yWf8bpZRpLfluCpzqxNxo0RL9FS3fBNK4IVEy0y6MHtHxJrwvAiFpQD6dCY6xw+TvjYSLu9cjEd/m3CZoxdnbxhSOQ5KwBxuhnx8Ao8/05l0jYlqOJOAfboZ7o3WMbaPiVUWsn0c7r1m4+6fTVddZb0YKiCZBUlptYa5SVP5SOaUcJs8wrEA+sWce4Tc+VfhkZ+Z/tns/HYBOvk6/v63zWvRj2QKTwuCCWa74QRwhKEAyno0tPLcANqjcRXsrT3msjvLR9Eth3jH52AosC2eMtkNx/vD/yHAYt0Opr/tUAtCIze4oh6G6b8n7v5+rLwr6wK0x5ca1CWc4C45Akr5Fp8r5LcCsBVaZXkEDbCzz40whuwrsJphJp75/2GMeNk5beZxPzwIqWyTHaFikMTJUlg7O0MJvBhD7olk6fcQoFJ9mUfInd/G1ad51fntsp3u3sJ8xQnBDwVUJkHJ4V2S8DXh6eGvAujVTwN+2DPOIvdhwc8CL6+tbncfFEDQO+mq7WIOZnrl2162EYT2cwiwRN+Nt93Zu+yn+Ap+TLnNvJwAx6VT3Ctjxs1qhNd1c1lVdSYa7qpMY1/bFbkvXjh6f1abopFc/lkAZm6thNkVcuevtdZ8rzu/1WGqW4a9Al+sVSfg/4oBj8qNslS9uyH5pwBq5tYeAV9Odke5E3eThUHUsearwPZmhH5sJSv88yLk1xCgovtC096LP/8UV/OX/+uY9d8RE2mV5pNkPOYSnQSrzdYwbJVxSaMQ72SsErwiioySyMOfjlTR6VUzK+zOb3f/LwXV+e0qnuLscdmJSVzQGSjjAmwd9sZrsh8KwN7jrnI9/oLbjrnBBWuvKyu52zYIC+VHyf0cSuC6UKozSj02xjn4ooDfRA8OPxSA7cBSOL4M+XBY0rSJ2FbmcI+JMh9KoCfcCq6rmb12rrZGJfNVzb4CqOhsUDw78yQ7F/AEmeSWdJ5NhnOY7N6EAjgpwxJGJ5rKqXjh6IHRZRhPTtlXACr/iLu/7cAK93ByLUz/n4VbwSE1K7r/gBK4cUhIuF8H5MxwK8eakQAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkEB6BP4fVPHi4U0ZOJEAAAAASUVORK5CYII=" webUI["html/img/x_black.png"] = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA6ppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0xMS0xNVQxNzoxMTozNzwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6Q29tcHJlc3Npb24+NTwvdGlmZjpDb21wcmVzc2lvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MTQ0PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xNDQ8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4yNTY8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFj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a1jSekqmtA1rrGsx7JYkDuvrVahwRdgVXD1xcwri6mmYRULLe4CuPc2wfrGo4U+7Y/3S9ZHD+GcflbnfiCJbr77whoaS6ucCXVkVkuLKgORQwNJFygRDJnqwb9i3b0HxkqjT0L4erGy5Rh1IRnhXrpaZq6GZCyRLf6cvhoTY6V9koX8bGdEUlyWVm6W5q1GuostihNm97L/dpm5k+QHCbDna0zRzgSS/lRHWL7iHPOa+9YsYkpttoCwSMcQRkrWioz5Qsc7aFJ1coHY3QyJ9jSjfJEOCfTUpWzehVBnUbqCJOCHEkB1xsmXDwq9DnObUz9q4QOUqYPaPKFzUKcVj6Eeu461q67Vhlqy6+Xo11G52JhRZNNW1FRbN00FWPVwguSa+8YEZ1i+D9vQjelm/iHTwAB69Vwd7CkuGLOcWtxfR4o+dHhNg4DNmhDvJ8M6ehknvhTXMDp8kQQgT33W4z+i7k/2gho+Jvrp1NTVwgW5opV76yl8F/cufe9CyJiRllZ6lYCHMXWPAXmNp9CRb8Pi30r658sHtCSCPsZNXQDYdMaLIek/No13V/rBfGMFSCXnsKNo1dDelnKt/dyUH8uvjjLH+zyfpbv1iUl/NVBt4mVJy58HoDyFZLt0rrj4G7TfIjARvMjy7d6JnR/UXS/+yeD5kLYkETxpRZL2jZJVzb7cl9yZA/cYqh4z+20AEzOj+BKxbZYRFqXQssvLs5gQzpBUp616rNsX55WdXBHbPBRrwlBm5v2VYJo1FsjmOtQg8ezo+fd8Ve4qy04HPRlmR1UiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABGwg8D8UnyVeZFwGAQAAAABJRU5ErkJggg==" - webUI["html/js/base_ts.js"] = "dmFyIFNFUlZFUiA9IG5ldyBPYmplY3QoKTsKdmFyIEJVTEtfRURJVCA9IGZhbHNlOwp2YXIgQ09MVU1OX1RPX1NPUlQ7CnZhciBTRUFSQ0hfTUFQUElORyA9IG5ldyBPYmplY3QoKTsKdmFyIFVORE8gPSBuZXcgT2JqZWN0KCk7CnZhciBTRVJWRVJfQ09OTkVDVElPTiA9IGZhbHNlOwp2YXIgV1NfQVZBSUxBQkxFID0gZmFsc2U7Ci8vIE1lbsO8CnZhciBtZW51SXRlbXMgPSBuZXcgQXJyYXkoKTsKbWVudUl0ZW1zLnB1c2gobmV3IE1haW5NZW51SXRlbSgicGxheWxpc3QiLCAie3subWFpbk1lbnUuaXRlbS5wbGF5bGlzdH19IiwgIm0zdS5wbmciLCAie3subWFpbk1lbnUuaGVhZGxpbmUucGxheWxpc3R9fSIpKTsKLy9tZW51SXRlbXMucHVzaChuZXcgTWFpbk1lbnVJdGVtKCJwbXNJRCIsICJ7ey5tYWluTWVudS5pdGVtLnBtc0lEfX0iLCAibnVtYmVyLnBuZyIsICJ7ey5tYWluTWVudS5oZWFkbGluZS5wbXNJRH19IikpCm1lbnVJdGVtcy5wdXNoKG5ldyBNYWluTWVudUl0ZW0oImZpbHRlciIsICJ7ey5tYWluTWVudS5pdGVtLmZpbHRlcn19IiwgImZpbHRlci5wbmciLCAie3subWFpbk1lbnUuaGVhZGxpbmUuZmlsdGVyfX0iKSk7Cm1lbnVJdGVtcy5wdXNoKG5ldyBNYWluTWVudUl0ZW0oInhtbHR2IiwgInt7Lm1haW5NZW51Lml0ZW0ueG1sdHZ9fSIsICJ4bWx0di5wbmciLCAie3subWFpbk1lbnUuaGVhZGxpbmUueG1sdHZ9fSIpKTsKbWVudUl0ZW1zLnB1c2gobmV3IE1haW5NZW51SXRlbSgibWFwcGluZyIsICJ7ey5tYWluTWVudS5pdGVtLm1hcHBpbmd9fSIsICJtYXBwaW5nLnBuZyIsICJ7ey5tYWluTWVudS5oZWFkbGluZS5tYXBwaW5nfX0iKSk7Cm1lbnVJdGVtcy5wdXNoKG5ldyBNYWluTWVudUl0ZW0oInVzZXJzIiwgInt7Lm1haW5NZW51Lml0ZW0udXNlcnN9fSIsICJ1c2Vycy5wbmciLCAie3subWFpbk1lbnUuaGVhZGxpbmUudXNlcnN9fSIpKTsKbWVudUl0ZW1zLnB1c2gobmV3IE1haW5NZW51SXRlbSgic2V0dGluZ3MiLCAie3subWFpbk1lbnUuaXRlbS5zZXR0aW5nc319IiwgInNldHRpbmdzLnBuZyIsICJ7ey5tYWluTWVudS5oZWFkbGluZS5zZXR0aW5nc319IikpOwptZW51SXRlbXMucHVzaChuZXcgTWFpbk1lbnVJdGVtKCJsb2ciLCAie3subWFpbk1lbnUuaXRlbS5sb2d9fSIsICJsb2cucG5nIiwgInt7Lm1haW5NZW51LmhlYWRsaW5lLmxvZ319IikpOwptZW51SXRlbXMucHVzaChuZXcgTWFpbk1lbnVJdGVtKCJsb2dvdXQiLCAie3subWFpbk1lbnUuaXRlbS5sb2dvdXR9fSIsICJsb2dvdXQucG5nIiwgInt7Lm1haW5NZW51LmhlYWRsaW5lLmxvZ291dH19IikpOwovLyBLYXRlZ29yaWVuIGbDvHIgZGllIEVpbnN0ZWxsdW5nZW4KdmFyIHNldHRpbmdzQ2F0ZWdvcnkgPSBuZXcgQXJyYXkoKTsKc2V0dGluZ3NDYXRlZ29yeS5wdXNoKG5ldyBTZXR0aW5nc0NhdGVnb3J5SXRlbSgie3suc2V0dGluZ3MuY2F0ZWdvcnkuZ2VuZXJhbH19IiwgInh0ZXZlQXV0b1VwZGF0ZSx0dW5lcixlcGdTb3VyY2UsYXBpIikpOwpzZXR0aW5nc0NhdGVnb3J5LnB1c2gobmV3IFNldHRpbmdzQ2F0ZWdvcnlJdGVtKCJ7ey5zZXR0aW5ncy5jYXRlZ29yeS5maWxlc319IiwgInVwZGF0ZSxmaWxlcy51cGRhdGUsdGVtcC5wYXRoLGNhY2hlLmltYWdlcyx4ZXBnLnJlcGxhY2UubWlzc2luZy5pbWFnZXMiKSk7CnNldHRpbmdzQ2F0ZWdvcnkucHVzaChuZXcgU2V0dGluZ3NDYXRlZ29yeUl0ZW0oInt7LnNldHRpbmdzLmNhdGVnb3J5LnN0cmVhbWluZ319IiwgImJ1ZmZlcix1ZHB4eSxidWZmZXIuc2l6ZS5rYixidWZmZXIudGltZW91dCx1c2VyLmFnZW50LGZmbXBlZy5wYXRoLGZmbXBlZy5vcHRpb25zLHZsYy5wYXRoLHZsYy5vcHRpb25zIikpOwpzZXR0aW5nc0NhdGVnb3J5LnB1c2gobmV3IFNldHRpbmdzQ2F0ZWdvcnlJdGVtKCJ7ey5zZXR0aW5ncy5jYXRlZ29yeS5iYWNrdXB9fSIsICJiYWNrdXAucGF0aCxiYWNrdXAua2VlcCIpKTsKc2V0dGluZ3NDYXRlZ29yeS5wdXNoKG5ldyBTZXR0aW5nc0NhdGVnb3J5SXRlbSgie3suc2V0dGluZ3MuY2F0ZWdvcnkuYXV0aGVudGljYXRpb259fSIsICJhdXRoZW50aWNhdGlvbi53ZWIsYXV0aGVudGljYXRpb24ucG1zLGF1dGhlbnRpY2F0aW9uLm0zdSxhdXRoZW50aWNhdGlvbi54bWwsYXV0aGVudGljYXRpb24uYXBpIikpOwpmdW5jdGlvbiBzaG93UG9wVXBFbGVtZW50KGVsbSkgewogICAgdmFyIGFsbEVsZW1lbnRzID0gbmV3IEFycmF5KCJwb3B1cC1jdXN0b20iKTsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYWxsRWxlbWVudHMubGVuZ3RoOyBpKyspIHsKICAgICAgICBzaG93RWxlbWVudChhbGxFbGVtZW50c1tpXSwgZmFsc2UpOwogICAgfQogICAgc2hvd0VsZW1lbnQoZWxtLCB0cnVlKTsKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgewogICAgICAgIHNob3dFbGVtZW50KCJwb3B1cCIsIHRydWUpOwogICAgfSwgMTApOwogICAgcmV0dXJuOwp9CmZ1bmN0aW9uIHNob3dFbGVtZW50KGVsbUlELCB0eXBlKSB7CiAgICB2YXIgY3NzQ2xhc3M7CiAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICBjYXNlIHRydWU6CiAgICAgICAgICAgIGNzc0NsYXNzID0gImJsb2NrIjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBmYWxzZToKICAgICAgICAgICAgY3NzQ2xhc3MgPSAibm9uZSI7CiAgICAgICAgICAgIGJyZWFrOwogICAgfQogICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZWxtSUQpLmNsYXNzTmFtZSA9IGNzc0NsYXNzOwp9CmZ1bmN0aW9uIGNoYW5nZUJ1dHRvbkFjdGlvbihlbGVtZW50LCBidXR0b25JRCwgYXR0cmlidXRlKSB7CiAgICB2YXIgdmFsdWUgPSBlbGVtZW50Lm9wdGlvbnNbZWxlbWVudC5zZWxlY3RlZEluZGV4XS52YWx1ZTsKICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGJ1dHRvbklEKS5zZXRBdHRyaWJ1dGUoYXR0cmlidXRlLCB2YWx1ZSk7Cn0KZnVuY3Rpb24gZ2V0TG9jYWxEYXRhKGRhdGFUeXBlLCBpZCkgewogICAgdmFyIGRhdGEgPSBuZXcgT2JqZWN0KCk7CiAgICBzd2l0Y2ggKGRhdGFUeXBlKSB7CiAgICAgICAgY2FzZSAibTN1IjoKICAgICAgICAgICAgZGF0YSA9IFNFUlZFUlsic2V0dGluZ3MiXVsiZmlsZXMiXVtkYXRhVHlwZV1baWRdOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJoZGhyIjoKICAgICAgICAgICAgZGF0YSA9IFNFUlZFUlsic2V0dGluZ3MiXVsiZmlsZXMiXVtkYXRhVHlwZV1baWRdOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJmaWx0ZXIiOgogICAgICAgIGNhc2UgImN1c3RvbS1maWx0ZXIiOgogICAgICAgIGNhc2UgImdyb3VwLXRpdGxlIjoKICAgICAgICAgICAgaWYgKGlkID09IC0xKSB7CiAgICAgICAgICAgICAgICBkYXRhWyJhY3RpdmUiXSA9IHRydWU7CiAgICAgICAgICAgICAgICBkYXRhWyJjYXNlU2Vuc2l0aXZlIl0gPSBmYWxzZTsKICAgICAgICAgICAgICAgIGRhdGFbImRlc2NyaXB0aW9uIl0gPSAiIjsKICAgICAgICAgICAgICAgIGRhdGFbImV4Y2x1ZGUiXSA9ICIiOwogICAgICAgICAgICAgICAgZGF0YVsiZmlsdGVyIl0gPSAiIjsKICAgICAgICAgICAgICAgIGRhdGFbImluY2x1ZGUiXSA9ICIiOwogICAgICAgICAgICAgICAgZGF0YVsibmFtZSJdID0gIiI7CiAgICAgICAgICAgICAgICBkYXRhWyJ0eXBlIl0gPSAiZ3JvdXAtdGl0bGUiOwogICAgICAgICAgICAgICAgU0VSVkVSWyJzZXR0aW5ncyJdWyJmaWx0ZXIiXVtpZF0gPSBkYXRhOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRhdGEgPSBTRVJWRVJbInNldHRpbmdzIl1bImZpbHRlciJdW2lkXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAieG1sdHYiOgogICAgICAgICAgICBkYXRhID0gU0VSVkVSWyJzZXR0aW5ncyJdWyJmaWxlcyJdW2RhdGFUeXBlXVtpZF07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInVzZXJzIjoKICAgICAgICAgICAgZGF0YSA9IFNFUlZFUlsidXNlcnMiXVtpZF1bImRhdGEiXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibWFwcGluZyI6CiAgICAgICAgICAgIGRhdGEgPSBTRVJWRVJbInhlcGciXVsiZXBnTWFwcGluZyJdW2lkXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibTN1R3JvdXBzIjoKICAgICAgICAgICAgZGF0YSA9IFNFUlZFUlsiZGF0YSJdWyJwbGF5bGlzdCJdWyJtM3UiXVsiZ3JvdXBzIl07CiAgICAgICAgICAgIGJyZWFrOwogICAgfQogICAgcmV0dXJuIGRhdGE7Cn0KZnVuY3Rpb24gZ2V0T2JqS2V5cyhvYmopIHsKICAgIHZhciBrZXlzID0gbmV3IEFycmF5KCk7CiAgICBmb3IgKHZhciBpIGluIG9iaikgewogICAgICAgIGlmIChvYmouaGFzT3duUHJvcGVydHkoaSkpIHsKICAgICAgICAgICAga2V5cy5wdXNoKGkpOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiBrZXlzOwp9CmZ1bmN0aW9uIGdldEFsbFNlbGVjdGVkQ2hhbm5lbHMoKSB7CiAgICB2YXIgY2hhbm5lbHMgPSBuZXcgQXJyYXkoKTsKICAgIGlmIChCVUxLX0VESVQgPT0gZmFsc2UpIHsKICAgICAgICByZXR1cm4gY2hhbm5lbHM7CiAgICB9CiAgICB2YXIgdHJzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImNvbnRlbnRfdGFibGUiKS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiVFIiKTsKICAgIGZvciAodmFyIGkgPSAxOyBpIDwgdHJzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgaWYgKHRyc1tpXS5zdHlsZS5kaXNwbGF5ICE9ICJub25lIikgewogICAgICAgICAgICBpZiAodHJzW2ldLmZpcnN0Q2hpbGQuZmlyc3RDaGlsZC5jaGVja2VkID09IHRydWUpIHsKICAgICAgICAgICAgICAgIGNoYW5uZWxzLnB1c2godHJzW2ldLmlkKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIHJldHVybiBjaGFubmVsczsKfQpmdW5jdGlvbiBzZWxlY3RBbGxDaGFubmVscygpIHsKICAgIHZhciBidWxrID0gZmFsc2U7CiAgICB2YXIgdHJzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImNvbnRlbnRfdGFibGUiKS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiVFIiKTsKICAgIGlmICh0cnNbMF0uZmlyc3RDaGlsZC5maXJzdENoaWxkLmNoZWNrZWQgPT0gdHJ1ZSkgewogICAgICAgIGJ1bGsgPSB0cnVlOwogICAgfQogICAgZm9yICh2YXIgaSA9IDE7IGkgPCB0cnMubGVuZ3RoOyBpKyspIHsKICAgICAgICBpZiAodHJzW2ldLnN0eWxlLmRpc3BsYXkgIT0gIm5vbmUiKSB7CiAgICAgICAgICAgIHN3aXRjaCAoYnVsaykgewogICAgICAgICAgICAgICAgY2FzZSB0cnVlOgogICAgICAgICAgICAgICAgICAgIHRyc1tpXS5maXJzdENoaWxkLmZpcnN0Q2hpbGQuY2hlY2tlZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIGZhbHNlOgogICAgICAgICAgICAgICAgICAgIHRyc1tpXS5maXJzdENoaWxkLmZpcnN0Q2hpbGQuY2hlY2tlZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuOwp9CmZ1bmN0aW9uIGJ1bGtFZGl0KCkgewogICAgQlVMS19FRElUID0gIUJVTEtfRURJVDsKICAgIHZhciBjbGFzc05hbWU7CiAgICB2YXIgcm93cyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoImJ1bGsiKTsKICAgIHN3aXRjaCAoQlVMS19FRElUKSB7CiAgICAgICAgY2FzZSB0cnVlOgogICAgICAgICAgICBjbGFzc05hbWUgPSAiYnVsayBzaG93QnVsayI7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgZmFsc2U6CiAgICAgICAgICAgIGNsYXNzTmFtZSA9ICJidWxrIGhpZGVCdWxrIjsKICAgICAgICAgICAgYnJlYWs7CiAgICB9CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJvd3MubGVuZ3RoOyBpKyspIHsKICAgICAgICByb3dzW2ldLmNsYXNzTmFtZSA9IGNsYXNzTmFtZTsKICAgICAgICByb3dzW2ldLmNoZWNrZWQgPSBmYWxzZTsKICAgIH0KICAgIHJldHVybjsKfQpmdW5jdGlvbiBzb3J0VGFibGUoY29sdW1uKSB7CiAgICAvL2NvbnNvbGUubG9nKGNvbHVtbSk7CiAgICBpZiAoY29sdW1uID09IENPTFVNTl9UT19TT1JUKSB7CiAgICAgICAgcmV0dXJuOwogICAgfQogICAgdmFyIHRhYmxlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImNvbnRlbnRfdGFibGUiKTsKICAgIHZhciB0YWJsZUhlYWQgPSB0YWJsZS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiVFIiKVswXTsKICAgIHZhciB0YWJsZUl0ZW1zID0gdGFibGVIZWFkLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJURCIpOwogICAgdmFyIHNvcnRPYmogPSBuZXcgT2JqZWN0KCk7CiAgICB2YXIgeCwgeFZhbHVlOwogICAgdmFyIHRhYmxlSGVhZGVyOwogICAgdmFyIHNvcnRCeVN0cmluZyA9IGZhbHNlOwogICAgaWYgKGNvbHVtbiA+IDAgJiYgQ09MVU1OX1RPX1NPUlQgPiAwKSB7CiAgICAgICAgdGFibGVJdGVtc1tDT0xVTU5fVE9fU09SVF0uY2xhc3NOYW1lID0gInBvaW50ZXIiOwogICAgICAgIHRhYmxlSXRlbXNbY29sdW1uXS5jbGFzc05hbWUgPSAic29ydFRoaXMiOwogICAgfQogICAgQ09MVU1OX1RPX1NPUlQgPSBjb2x1bW47CiAgICB2YXIgcm93cyA9IHRhYmxlLnJvd3M7CiAgICBpZiAocm93c1sxXSAhPSB1bmRlZmluZWQpIHsKICAgICAgICB0YWJsZUhlYWRlciA9IHJvd3NbMF07CiAgICAgICAgeCA9IHJvd3NbMV0uZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlREIilbY29sdW1uXTsKICAgICAgICBmb3IgKGkgPSAxOyBpIDwgcm93cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICB4ID0gcm93c1tpXS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiVEQiKVtjb2x1bW5dOwogICAgICAgICAgICBzd2l0Y2ggKHguY2hpbGROb2Rlc1swXS50YWdOYW1lLnRvTG93ZXJDYXNlKCkpIHsKICAgICAgICAgICAgICAgIGNhc2UgImlucHV0IjoKICAgICAgICAgICAgICAgICAgICB4VmFsdWUgPSB4LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJJTlBVVCIpWzBdLnZhbHVlLnRvTG93ZXJDYXNlKCk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJwIjoKICAgICAgICAgICAgICAgICAgICB4VmFsdWUgPSB4LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJQIilbMF0uaW5uZXJUZXh0LnRvTG93ZXJDYXNlKCk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBkZWZhdWx0OiBjb25zb2xlLmxvZyh4LmNoaWxkTm9kZXNbMF0udGFnTmFtZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHhWYWx1ZSA9PSAiIiB8fCB4VmFsdWUgPT0gTmFOKSB7CiAgICAgICAgICAgICAgICB4VmFsdWUgPSBpOwogICAgICAgICAgICAgICAgc29ydE9ialtpXSA9IHJvd3NbaV07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBzd2l0Y2ggKGlzTmFOKHhWYWx1ZSkpIHsKICAgICAgICAgICAgICAgICAgICBjYXNlIGZhbHNlOgogICAgICAgICAgICAgICAgICAgICAgICB4VmFsdWUgPSBwYXJzZUZsb2F0KHhWYWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHNvcnRPYmpbeFZhbHVlXSA9IHJvd3NbaV07CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIGNhc2UgdHJ1ZToKICAgICAgICAgICAgICAgICAgICAgICAgc29ydEJ5U3RyaW5nID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgc29ydE9ialt4VmFsdWUudG9Mb3dlckNhc2UoKSArIGldID0gcm93c1tpXTsKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgd2hpbGUgKHRhYmxlLmZpcnN0Q2hpbGQpIHsKICAgICAgICAgICAgdGFibGUucmVtb3ZlQ2hpbGQodGFibGUuZmlyc3RDaGlsZCk7CiAgICAgICAgfQogICAgICAgIHZhciBzb3J0VmFsdWVzID0gZ2V0T2JqS2V5cyhzb3J0T2JqKTsKICAgICAgICBpZiAoc29ydEJ5U3RyaW5nID09IHRydWUpIHsKICAgICAgICAgICAgc29ydFZhbHVlcy5zb3J0KCk7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKHNvcnRWYWx1ZXMpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgZnVuY3Rpb24gc29ydEZsb2F0KGEsIGIpIHsKICAgICAgICAgICAgICAgIHJldHVybiBhIC0gYjsKICAgICAgICAgICAgfQogICAgICAgICAgICBzb3J0VmFsdWVzLnNvcnQoc29ydEZsb2F0KTsKICAgICAgICB9CiAgICAgICAgdGFibGUuYXBwZW5kQ2hpbGQodGFibGVIZWFkZXIpOwogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc29ydFZhbHVlcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICB0YWJsZS5hcHBlbmRDaGlsZChzb3J0T2JqW3NvcnRWYWx1ZXNbaV1dKTsKICAgICAgICB9CiAgICB9CiAgICByZXR1cm47Cn0KZnVuY3Rpb24gY3JlYXRlU2VhcmNoT2JqKCkgewogICAgU0VBUkNIX01BUFBJTkcgPSBuZXcgT2JqZWN0KCk7CiAgICB2YXIgZGF0YSA9IFNFUlZFUlsieGVwZyJdWyJlcGdNYXBwaW5nIl07CiAgICB2YXIgY2hhbm5lbHMgPSBnZXRPYmpLZXlzKGRhdGEpOwogICAgdmFyIGNoYW5uZWxLZXlzID0gWyJ4LWFjdGl2ZSIsICJ4LWNoYW5uZWxJRCIsICJ4LW5hbWUiLCAiX2ZpbGUubTN1Lm5hbWUiLCAieC1ncm91cC10aXRsZSIsICJ4LXhtbHR2LWZpbGUiXTsKICAgIGNoYW5uZWxzLmZvckVhY2goZnVuY3Rpb24gKGlkKSB7CiAgICAgICAgY2hhbm5lbEtleXMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgICAgIGlmIChrZXkgPT0gIngtYWN0aXZlIikgewogICAgICAgICAgICAgICAgc3dpdGNoIChkYXRhW2lkXVtrZXldKSB7CiAgICAgICAgICAgICAgICAgICAgY2FzZSB0cnVlOgogICAgICAgICAgICAgICAgICAgICAgICBTRUFSQ0hfTUFQUElOR1tpZF0gPSAib25saW5lICI7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIGNhc2UgZmFsc2U6CiAgICAgICAgICAgICAgICAgICAgICAgIFNFQVJDSF9NQVBQSU5HW2lkXSA9ICJvZmZsaW5lICI7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgaWYgKGtleSA9PSAieC14bWx0di1maWxlIikgewogICAgICAgICAgICAgICAgICAgIHZhciB4bWx0dkZpbGUgPSBnZXRWYWx1ZUZyb21Qcm92aWRlckZpbGUoZGF0YVtpZF1ba2V5XSwgInhtbHR2IiwgIm5hbWUiKTsKICAgICAgICAgICAgICAgICAgICBpZiAoeG1sdHZGaWxlICE9IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgICAgICAgICBTRUFSQ0hfTUFQUElOR1tpZF0gPSBTRUFSQ0hfTUFQUElOR1tpZF0gKyB4bWx0dkZpbGUgKyAiICI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgU0VBUkNIX01BUFBJTkdbaWRdID0gU0VBUkNIX01BUFBJTkdbaWRdICsgZGF0YVtpZF1ba2V5XSArICIgIjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0pOwogICAgfSk7CiAgICByZXR1cm47Cn0KZnVuY3Rpb24gc2VhcmNoSW5NYXBwaW5nKCkgewogICAgdmFyIHNlYXJjaFZhbHVlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNlYXJjaE1hcHBpbmciKS52YWx1ZTsKICAgIHZhciB0cnMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiY29udGVudF90YWJsZSIpLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJUUiIpOwogICAgZm9yICh2YXIgaSA9IDE7IGkgPCB0cnMubGVuZ3RoOyArK2kpIHsKICAgICAgICB2YXIgaWQgPSB0cnNbaV0uZ2V0QXR0cmlidXRlKCJpZCIpOwogICAgICAgIHZhciBlbGVtZW50ID0gU0VBUkNIX01BUFBJTkdbaWRdOwogICAgICAgIHN3aXRjaCAoZWxlbWVudC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHNlYXJjaFZhbHVlLnRvTG93ZXJDYXNlKCkpKSB7CiAgICAgICAgICAgIGNhc2UgdHJ1ZToKICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5zdHlsZS5kaXNwbGF5ID0gIiI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSBmYWxzZToKICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5zdHlsZS5kaXNwbGF5ID0gIm5vbmUiOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuOwp9CmZ1bmN0aW9uIGNhbGN1bGF0ZVdyYXBwZXJIZWlnaHQoKSB7CiAgICBpZiAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJveC13cmFwcGVyIikpIHsKICAgICAgICB2YXIgZWxtID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJveC13cmFwcGVyIik7CiAgICAgICAgdmFyIGRpdnMgPSBuZXcgQXJyYXkoIm15U3RyZWFtc0JveCIsICJjbGllbnRJbmZvIiwgImNvbnRlbnQiKTsKICAgICAgICB2YXIgZWxlbWVudHNIZWlnaHQgPSAwIC0gZWxtLm9mZnNldEhlaWdodDsKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRpdnMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgZWxlbWVudHNIZWlnaHQgPSBlbGVtZW50c0hlaWdodCArIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGRpdnNbaV0pLm9mZnNldEhlaWdodDsKICAgICAgICB9CiAgICAgICAgZWxtLnN0eWxlLmhlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodCAtIGVsZW1lbnRzSGVpZ2h0ICsgInB4IjsKICAgIH0KICAgIHJldHVybjsKfQpmdW5jdGlvbiBjaGFuZ2VDaGFubmVsTnVtYmVyKGVsZW1lbnQpIHsKICAgIHZhciBkYklEID0gZWxlbWVudC5wYXJlbnROb2RlLnBhcmVudE5vZGUuaWQ7CiAgICB2YXIgbmV3TnVtYmVyID0gcGFyc2VGbG9hdChlbGVtZW50LnZhbHVlKTsKICAgIHZhciBjaGFubmVsTnVtYmVycyA9IFtdOwogICAgdmFyIGRhdGEgPSBTRVJWRVJbInhlcGciXVsiZXBnTWFwcGluZyJdOwogICAgdmFyIGNoYW5uZWxzID0gZ2V0T2JqS2V5cyhkYXRhKTsKICAgIGlmIChpc05hTihuZXdOdW1iZXIpKSB7CiAgICAgICAgYWxlcnQoInt7LmFsZXJ0LmludmFsaWRDaGFubmVsTnVtYmVyfX0iKTsKICAgICAgICByZXR1cm47CiAgICB9CiAgICBjaGFubmVscy5mb3JFYWNoKGZ1bmN0aW9uIChpZCkgewogICAgICAgIHZhciBjaGFubmVsTnVtYmVyID0gcGFyc2VGbG9hdChkYXRhW2lkXVsieC1jaGFubmVsSUQiXSk7CiAgICAgICAgY2hhbm5lbE51bWJlcnMucHVzaChjaGFubmVsTnVtYmVyKTsKICAgIH0pOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGFubmVsTnVtYmVycy5sZW5ndGg7IGkrKykgewogICAgICAgIGlmIChjaGFubmVsTnVtYmVycy5pbmRleE9mKG5ld051bWJlcikgPT0gLTEpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmIChNYXRoLmZsb29yKG5ld051bWJlcikgPT0gbmV3TnVtYmVyKSB7CiAgICAgICAgICAgIG5ld051bWJlciA9IG5ld051bWJlciArIDE7CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICBuZXdOdW1iZXIgPSBuZXdOdW1iZXIgKyAwLjE7CiAgICAgICAgICAgIG5ld051bWJlci50b0ZpeGVkKDEpOwogICAgICAgICAgICBuZXdOdW1iZXIgPSBNYXRoLnJvdW5kKG5ld051bWJlciAqIDEwKSAvIDEwOwogICAgICAgIH0KICAgIH0KICAgIGRhdGFbZGJJRF1bIngtY2hhbm5lbElEIl0gPSBuZXdOdW1iZXIudG9TdHJpbmcoKTsKICAgIGVsZW1lbnQudmFsdWUgPSBuZXdOdW1iZXI7CiAgICBjb25zb2xlLmxvZyhkYXRhW2RiSURdWyJ4LWNoYW5uZWxJRCJdKTsKICAgIGlmIChDT0xVTU5fVE9fU09SVCA9PSAxKSB7CiAgICAgICAgQ09MVU1OX1RPX1NPUlQgPSAtMTsKICAgICAgICBzb3J0VGFibGUoMSk7CiAgICB9CiAgICByZXR1cm47Cn0KZnVuY3Rpb24gYmFja3VwKCkgewogICAgdmFyIGRhdGEgPSBuZXcgT2JqZWN0KCk7CiAgICBjb25zb2xlLmxvZygiQmFja3VwIGRhdGEiKTsKICAgIHZhciBjbWQgPSAieHRldmVCYWNrdXAiOwogICAgY29uc29sZS5sb2coIlNFTkQgVE8gU0VSVkVSIik7CiAgICBjb25zb2xlLmxvZyhkYXRhKTsKICAgIHZhciBzZXJ2ZXIgPSBuZXcgU2VydmVyKGNtZCk7CiAgICBzZXJ2ZXIucmVxdWVzdChkYXRhKTsKICAgIHJldHVybjsKfQpmdW5jdGlvbiB0b2dnbGVDaGFubmVsU3RhdHVzKGlkKSB7CiAgICB2YXIgZWxlbWVudDsKICAgIHZhciBzdGF0dXM7CiAgICBpZiAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImFjdGl2ZSIpKSB7CiAgICAgICAgdmFyIGNoZWNrYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImFjdGl2ZSIpOwogICAgICAgIHN0YXR1cyA9IChjaGVja2JveCkuY2hlY2tlZDsKICAgIH0KICAgIHZhciBpZHMgPSBnZXRBbGxTZWxlY3RlZENoYW5uZWxzKCk7CiAgICBpZiAoaWRzLmxlbmd0aCA9PSAwKSB7CiAgICAgICAgaWRzLnB1c2goaWQpOwogICAgfQogICAgaWRzLmZvckVhY2goZnVuY3Rpb24gKGlkKSB7CiAgICAgICAgdmFyIGNoYW5uZWwgPSBTRVJWRVJbInhlcGciXVsiZXBnTWFwcGluZyJdW2lkXTsKICAgICAgICBjaGFubmVsWyJ4LWFjdGl2ZSJdID0gc3RhdHVzOwogICAgICAgIHN3aXRjaCAoY2hhbm5lbFsieC1hY3RpdmUiXSkgewogICAgICAgICAgICBjYXNlIHRydWU6CiAgICAgICAgICAgICAgICBpZiAoY2hhbm5lbFsieC14bWx0di1maWxlIl0gPT0gIi0iIHx8IGNoYW5uZWxbIngtbWFwcGluZyJdID09ICItIikgewogICAgICAgICAgICAgICAgICAgIGlmIChCVUxLX0VESVQgPT0gZmFsc2UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgYWxlcnQoY2hhbm5lbFsieC1uYW1lIl0gKyAiOiBNaXNzaW5nIFhNTFRWIGZpbGUgLyBjaGFubmVsIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrYm94LmNoZWNrZWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2hhbm5lbFsieC1hY3RpdmUiXSA9IGZhbHNlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgZmFsc2U6CiAgICAgICAgICAgICAgICAvLyBjb2RlLi4uCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgaWYgKGNoYW5uZWxbIngtYWN0aXZlIl0gPT0gZmFsc2UpIHsKICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpLmNsYXNzTmFtZSA9ICJub3RBY3RpdmVFUEciOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpLmNsYXNzTmFtZSA9ICJhY3RpdmVFUEciOwogICAgICAgIH0KICAgIH0pOwp9CmZ1bmN0aW9uIHJlc3RvcmUoKSB7CiAgICBpZiAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VwbG9hZCcpKSB7CiAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VwbG9hZCcpLnJlbW92ZSgpOwogICAgfQogICAgdmFyIHJlc3RvcmUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJJTlBVVCIpOwogICAgcmVzdG9yZS5zZXRBdHRyaWJ1dGUoInR5cGUiLCAiZmlsZSIpOwogICAgcmVzdG9yZS5zZXRBdHRyaWJ1dGUoImNsYXNzIiwgIm5vdFZpc2libGUiKTsKICAgIHJlc3RvcmUuc2V0QXR0cmlidXRlKCJuYW1lIiwgIiIpOwogICAgcmVzdG9yZS5pZCA9ICJ1cGxvYWQiOwogICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChyZXN0b3JlKTsKICAgIHJlc3RvcmUuY2xpY2soKTsKICAgIHJlc3RvcmUub25jaGFuZ2UgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIGZpbGVuYW1lID0gcmVzdG9yZS5maWxlc1swXS5uYW1lOwogICAgICAgIHZhciBjaGVjayA9IGNvbmZpcm0oIkZpbGU6ICIgKyBmaWxlbmFtZSArICJcbnt7LmNvbmZpcm0ucmVzdG9yZX19Iik7CiAgICAgICAgaWYgKGNoZWNrID09IHRydWUpIHsKICAgICAgICAgICAgdmFyIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7CiAgICAgICAgICAgIHZhciBmaWxlID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignaW5wdXRbdHlwZT1maWxlXScpLmZpbGVzWzBdOwogICAgICAgICAgICBpZiAoZmlsZSkgewogICAgICAgICAgICAgICAgcmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZSk7CiAgICAgICAgICAgICAgICByZWFkZXIub25sb2FkID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHJlYWRlci5yZXN1bHQpOwogICAgICAgICAgICAgICAgICAgIHZhciBkYXRhID0gbmV3IE9iamVjdCgpOwogICAgICAgICAgICAgICAgICAgIHZhciBjbWQgPSAieHRldmVSZXN0b3JlIjsKICAgICAgICAgICAgICAgICAgICBkYXRhWyJiYXNlNjQiXSA9IHJlYWRlci5yZXN1bHQ7CiAgICAgICAgICAgICAgICAgICAgdmFyIHNlcnZlciA9IG5ldyBTZXJ2ZXIoY21kKTsKICAgICAgICAgICAgICAgICAgICBzZXJ2ZXIucmVxdWVzdChkYXRhKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBhbGVydCgiRmlsZSBjb3VsZCBub3QgYmUgbG9hZGVkIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVzdG9yZS5yZW1vdmUoKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgIH07CiAgICByZXR1cm47Cn0KZnVuY3Rpb24gdXBsb2FkTG9nbygpIHsKICAgIGlmIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndXBsb2FkJykpIHsKICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndXBsb2FkJykucmVtb3ZlKCk7CiAgICB9CiAgICB2YXIgdXBsb2FkID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiSU5QVVQiKTsKICAgIHVwbG9hZC5zZXRBdHRyaWJ1dGUoInR5cGUiLCAiZmlsZSIpOwogICAgdXBsb2FkLnNldEF0dHJpYnV0ZSgiY2xhc3MiLCAibm90VmlzaWJsZSIpOwogICAgdXBsb2FkLnNldEF0dHJpYnV0ZSgibmFtZSIsICIiKTsKICAgIHVwbG9hZC5pZCA9ICJ1cGxvYWQiOwogICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZCh1cGxvYWQpOwogICAgdXBsb2FkLmNsaWNrKCk7CiAgICB1cGxvYWQub25ibHVyID0gZnVuY3Rpb24gKCkgewogICAgICAgIGFsZXJ0KCk7CiAgICB9OwogICAgdXBsb2FkLm9uY2hhbmdlID0gZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBmaWxlbmFtZSA9IHVwbG9hZC5maWxlc1swXS5uYW1lOwogICAgICAgIHZhciByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpOwogICAgICAgIHZhciBmaWxlID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignaW5wdXRbdHlwZT1maWxlXScpLmZpbGVzWzBdOwogICAgICAgIGlmIChmaWxlKSB7CiAgICAgICAgICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGUpOwogICAgICAgICAgICByZWFkZXIub25sb2FkID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgY29uc29sZS5sb2cocmVhZGVyLnJlc3VsdCk7CiAgICAgICAgICAgICAgICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICAgICAgICAgICAgICAgIHZhciBjbWQgPSAidXBsb2FkTG9nbyI7CiAgICAgICAgICAgICAgICBkYXRhWyJiYXNlNjQiXSA9IHJlYWRlci5yZXN1bHQ7CiAgICAgICAgICAgICAgICBkYXRhWyJmaWxlbmFtZSJdID0gZmlsZS5uYW1lOwogICAgICAgICAgICAgICAgdmFyIHNlcnZlciA9IG5ldyBTZXJ2ZXIoY21kKTsKICAgICAgICAgICAgICAgIHNlcnZlci5yZXF1ZXN0KGRhdGEpOwogICAgICAgICAgICAgICAgdmFyIHVwZGF0ZUxvZ28gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndXBkYXRlLWljb24nKTsKICAgICAgICAgICAgICAgIHVwZGF0ZUxvZ28uY2hlY2tlZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgdXBkYXRlTG9nby5jbGFzc05hbWUgPSAiY2hhbmdlZCI7CiAgICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIGVsc2UgewogICAgICAgICAgICBhbGVydCgiRmlsZSBjb3VsZCBub3QgYmUgbG9hZGVkIik7CiAgICAgICAgfQogICAgICAgIHVwbG9hZC5yZW1vdmUoKTsKICAgICAgICByZXR1cm47CiAgICB9Owp9CmZ1bmN0aW9uIGNoZWNrVW5kbyhrZXkpIHsKICAgIHN3aXRjaCAoa2V5KSB7CiAgICAgICAgY2FzZSAiZXBnTWFwcGluZyI6CiAgICAgICAgICAgIGlmIChVTkRPLmhhc093blByb3BlcnR5KGtleSkpIHsKICAgICAgICAgICAgICAgIFNFUlZFUlsieGVwZyJdW2tleV0gPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KFVORE9ba2V5XSkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgVU5ET1trZXldID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShTRVJWRVJbInhlcGciXVtrZXldKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgYnJlYWs7CiAgICB9CiAgICByZXR1cm47Cn0KZnVuY3Rpb24gc29ydFNlbGVjdChlbGVtKSB7CiAgICB2YXIgdG1wQXJ5ID0gW107CiAgICB2YXIgc2VsZWN0ZWRWYWx1ZSA9IGVsZW1bZWxlbS5zZWxlY3RlZEluZGV4XS52YWx1ZTsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZWxlbS5vcHRpb25zLmxlbmd0aDsgaSsrKQogICAgICAgIHRtcEFyeS5wdXNoKGVsZW0ub3B0aW9uc1tpXSk7CiAgICB0bXBBcnkuc29ydChmdW5jdGlvbiAoYSwgYikgeyByZXR1cm4gKGEudGV4dCA8IGIudGV4dCkgPyAtMSA6IDE7IH0pOwogICAgd2hpbGUgKGVsZW0ub3B0aW9ucy5sZW5ndGggPiAwKQogICAgICAgIGVsZW0ub3B0aW9uc1swXSA9IG51bGw7CiAgICB2YXIgbmV3U2VsZWN0ZWRJbmRleCA9IDA7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRtcEFyeS5sZW5ndGg7IGkrKykgewogICAgICAgIGVsZW0ub3B0aW9uc1tpXSA9IHRtcEFyeVtpXTsKICAgICAgICBpZiAoZWxlbS5vcHRpb25zW2ldLnZhbHVlID09IHNlbGVjdGVkVmFsdWUpCiAgICAgICAgICAgIG5ld1NlbGVjdGVkSW5kZXggPSBpOwogICAgfQogICAgZWxlbS5zZWxlY3RlZEluZGV4ID0gbmV3U2VsZWN0ZWRJbmRleDsgLy8gU2V0IG5ldyBzZWxlY3RlZCBpbmRleCBhZnRlciBzb3J0aW5nCiAgICByZXR1cm47Cn0KZnVuY3Rpb24gdXBkYXRlTG9nKCkgewogICAgY29uc29sZS5sb2coIlRPS0VOIik7CiAgICB2YXIgc2VydmVyID0gbmV3IFNlcnZlcigidXBkYXRlTG9nIik7CiAgICBzZXJ2ZXIucmVxdWVzdChuZXcgT2JqZWN0KCkpOwp9Cg==" - webUI["html/js/menu.js"] = "CmZ1bmN0aW9uIHNldE1lbnVJdGVtKCkgewoKICBtZW51ID0gbmV3IE9iamVjdCgpOwogIHN1Yk1lbnUgPSBuZXcgT2JqZWN0KCk7CgogIHZhciBtZW51X20zdSA9IG5ldyBPYmplY3QoKTsKICBtZW51X20zdVsiX21lbnVUeXBlIl0gICAgICAgPSAiaW5wdXRBcnJheSI7CiAgbWVudV9tM3VbIl9lbGVtZW50Il0gICAgICAgID0gIkxJIjsKICBtZW51X20zdVsiX2NvbmZpZ0tleSJdICAgICAgPSAiZmlsZXMubTN1IjsKICBtZW51X20zdVsiX3RleHQiXSAgICAgICAgICAgPSAiUGxheWxpc3QiOwogIG1lbnVfbTN1WyJfaWNvbiJdICAgICAgICAgICA9ICJpbWcvbTN1LnBuZyI7CiAgbWVudV9tM3VbIl9oZWFkbGluZSJdICAgICAgID0gIlBsYXlsaXN0czogTG9jYWwgb3IgcmVtb3RlIjsKICBtZW51X20zdVsiX3VzYWdlIl0gICAgICAgICAgPSAiPGI+SW5mbzwvYj48YnI+QXZhaWxhYmlsaXR5OiBGaWxlIGF2YWlsYWJpbGl0eSBpbiBwZXJjZW50PGJyPlN0cmVhbXM6ICAgICAgTnVtYmVyIG9mIHN0cmVhbXMgaW4gdGhlIGZpbGUuPGJyPmdyb3VwLXRpdGxlOiAgU3RyZWFtcyB0aGF0IGFyZSBhc3NpZ25lZCB0byBhIGdyb3VwLiBTaW1wbGlmaWVzIGZpbHRlcmluZyBzdHJlYW1zPGJyPnR2Zy1pZDogICAgICAgVGhpcyBJRCBpcyB1c2VkIGZvciBhdXRvbWF0aWMgbWFwcGluZywgbXVzdCBtYXRjaCB3aXRoIHRoZSBjaGFubmVsIElEIGluIHRoZSBYTUxUViBmaWxlLjxicj5VbmlxdWUgSUQ6ICAgIFN0cmVhbXMgd2l0aCBhIHVuaXF1ZSBJRCB0byBpZGVudGlmeSB0aGVtLiBBbGxvd3MgY2hhbm5lbCBuYW1lIGNoYW5nZXMgaW4gdGhlIE0zVSB3aXRob3V0IGxvc2luZyB0aGUgWE1MVFYgbWFwcGluZyAoUFBWIC8gbGl2ZSBldmVudHMpLjxicj48YnI+PGI+VXNhZ2UgTTNVOjwvYj48YnI+UmVtb3RlIHBsYXlsaXN0OiBodHRwOi8veW91ci5pcHR2LnByb3ZpZGVyLmNvbS9maWxlLm0zdTxicj5Mb2NhbCAgcGxheWxpc3Q6IC9wYXRoL3RvL2ZpbGUubTN1PGJyPjxicj48Yj5Vc2FnZSBIREhvbWVSdW46PC9iPjxicj5JUDogMTkyLjE2OC4xLjEwOjUwMDQ8YnI+IgogIG1lbnVfbTN1WyJuYW1lIl0gICAgICAgICAgICA9ICJmaWxlIjsKICBtZW51X20zdVsiaWQiXSAgICAgICAgICAgICAgPSAiZmlsZSI7CiAgbWVudV9tM3VbInZhbHVlIl0gICAgICAgICAgID0gbWVudV9tM3VbIm5hbWUiXTsKICBtZW51X20zdVsicGxhY2Vob2xkZXIiXSAgICAgPSAiUGxheWxpc3Q6IGxvY2FsIG9yIHJlbW90ZSI7CiAgbWVudV9tM3VbIm9uY2xpY2siXSAgICAgICAgID0gImphdmFzY3JpcHQ6IHRvZ2dsZU1lbnUodGhpcyk7IjsKICBtZW51X20zdVsiY2xhc3MiXSAgICAgICAgICAgPSAibWVudS1ub3RBY3RpdmUiOwoKCiAgdmFyIG1lbnVfZmlsdGVyID0gbmV3IE9iamVjdCgpOwogIG1lbnVfZmlsdGVyWyJfbWVudVR5cGUiXSAgICA9ICJpbnB1dEFycmF5IjsKICBtZW51X2ZpbHRlclsiX2VsZW1lbnQiXSAgICAgPSAiTEkiOwogIG1lbnVfZmlsdGVyWyJfY29uZmlnS2V5Il0gICA9ICJmaWx0ZXIiOwogIG1lbnVfZmlsdGVyWyJfdGV4dCJdICAgICAgICA9ICJGaWx0ZXIiOwogIG1lbnVfZmlsdGVyWyJfaWNvbiJdICAgICAgICA9ICJpbWcvZmlsdGVyLnBuZyI7CiAgbWVudV9maWx0ZXJbIl9oZWFkbGluZSJdICAgID0gIkZpbHRlciBieSBNM1UgcGFyYW1ldGVycywgZS5nLiBncm91cC10aXRsZSI7CiAgbWVudV9maWx0ZXJbIl91c2FnZSJdICAgICAgID0gIjxiPlVzYWdlOjwvYj48YnI+U3BvcnQgLSBBbGwgc3BvcnRzIGNoYW5uZWxzPGJyPlNwb3J0IHtIRH0gLSBBbGwgSEQgc3BvcnRzIGNoYW5uZWxzPGJyPlNwb3J0IHtIRH0gIXtFUyxERX0gLSBBbGwgSEQgc3BvcnRzIGNoYW5uZWxzLCBidXQgbm8gU3BhbmlzaCBhbmQgR2VybWFuPGJyPjxicj5UbyBmaWx0ZXIgdGhlIHN0cmVhbXMgb2YgYSBIREhvbWVSdW4sIHRoZSBwbGF5bGlzdCBuYW1lIGNhbiBiZSBlbnRlcmVkOjxicj5NeSB0dW5lciB7SER9IgogIC8vbWVudV9maWx0ZXJbIl91c2FnZSJdICAgICAgID0gIjxiPlVzYWdlOjwvYj48YnI+QWxsIHNwb3J0cyBjaGFubmVsczogU3BvcnQ8YnI+QWxsIEhEIHNwb3J0cyBjaGFubmVsczogU3BvcnQge0hEfTxicj5BbGwgSEQgc3BvcnRzIGNoYW5uZWxzLCBidXQgbm8gU3BhbmlzaCBhbmQgR2VybWFuOiBTcG9ydCB7SER9ICF7RVMsREV9IgogIG1lbnVfZmlsdGVyWyJuYW1lIl0gICAgICAgICA9ICJmaWx0ZXIiOwogIG1lbnVfZmlsdGVyWyJpZCJdICAgICAgICAgICA9ICJNM1UiOwogIG1lbnVfZmlsdGVyWyJ2YWx1ZSJdICAgICAgICA9IG1lbnVfZmlsdGVyWyJuYW1lIl07CiAgbWVudV9maWx0ZXJbInBsYWNlaG9sZGVyIl0gID0gIkZpbHRlciBzdHJlYW1zOiBTcG9ydCI7CiAgbWVudV9maWx0ZXJbIm9uY2xpY2siXSAgICAgID0gImphdmFzY3JpcHQ6IHRvZ2dsZU1lbnUodGhpcyk7IjsKICBtZW51X2ZpbHRlclsiY2xhc3MiXSAgICAgICAgPSAibWVudS1ub3RBY3RpdmUiOwoKICB2YXIgbWVudV9pZCA9IG5ldyBPYmplY3QoKTsKICBtZW51X2lkWyJfbWVudVR5cGUiXSAgICAgICAgPSAiaW5wdXRBcnJheSI7CiAgbWVudV9pZFsiX2VsZW1lbnQiXSAgICAgICAgID0gIkxJIjsKICBtZW51X2lkWyJfY29uZmlnS2V5Il0gICAgICAgPSAiaWQiOwogIG1lbnVfaWRbIl90ZXh0Il0gICAgICAgICAgICA9ICJQTVMgSUQiOwogIG1lbnVfaWRbIl9pY29uIl0gICAgICAgICAgICA9ICJpbWcvbnVtYmVyLnBuZyI7CiAgbWVudV9pZFsiX2hlYWRsaW5lIl0gICAgICAgID0gIlNldHVwIFBNUyBndWlkZSBudW1iZXIiOwogIG1lbnVfaWRbIl91c2FnZSJdICAgICAgICAgICA9ICdTb21lIHBsYXlsaXN0cyBoYXZlIHVuaXF1ZSBjaGFubmVsIElEcy48YnI+RW50ZXIgdGhlIGtleXdvcmQgb2YgdGhlIElELiBUaGUgY2hhbm5lbCBhc3NpZ25tZW50IGluIFBNUyB3aWxsIGNoYW5nZSBhcyBhIHJlc3VsdC48YnI+PGJyPmUuZy4gY2hhbm5lbElEPGJyPiNFWFRJTkY6MCB0eXBlPSJzdHJlYW0iIDxiPmNoYW5uZWxJZDwvYj49IjgxIiwgTXkgU3RyZWFtaW5nIENoYW5uZWwgSEQ8YnI+PGJyPk9ubHkgZW50ZXIgaGVyZSBpZiB5b3Uga25vdyB3aGF0IHlvdSBhcmUgZG9pbmchJwogIG1lbnVfaWRbIm5hbWUiXSAgICAgICAgICAgICA9ICJpZCI7CiAgbWVudV9pZFsiaWQiXSAgICAgICAgICAgICAgID0gImlkIjsKICBtZW51X2lkWyJ2YWx1ZSJdICAgICAgICAgICAgPSBtZW51X2lkWyJuYW1lIl07CiAgbWVudV9pZFsicGxhY2Vob2xkZXIiXSAgICAgID0gIlVuaXF1ZSBJRCBmcm9tIHRoZSBNM1UgZmlsZSI7CiAgbWVudV9pZFsib25jbGljayJdICAgICAgICAgID0gImphdmFzY3JpcHQ6IHRvZ2dsZU1lbnUodGhpcyk7IjsKICBtZW51X2lkWyJjbGFzcyJdICAgICAgICAgICAgPSAibWVudS1ub3RBY3RpdmUiOwoKCiAgdmFyIG1lbnVfeG1sdHYgPSBuZXcgT2JqZWN0KCk7CiAgbWVudV94bWx0dlsiX21lbnVUeXBlIl0gICAgID0gImlucHV0QXJyYXkiOwogIG1lbnVfeG1sdHZbIl9lbGVtZW50Il0gICAgICA9ICJMSSI7CiAgbWVudV94bWx0dlsiX2NvbmZpZ0tleSJdICAgID0gImZpbGVzLnhtbHR2IjsKICBtZW51X3htbHR2WyJfdGV4dCJdICAgICAgICAgPSAiWE1MVFYiOwogIG1lbnVfeG1sdHZbIl9pY29uIl0gICAgICAgICA9ICJpbWcveG1sdHYucG5nIjsKICBtZW51X3htbHR2WyJfaGVhZGxpbmUiXSAgICAgPSAiWE1MVFYgZmlsZXM6IExvY2FsIG9yIHJlbW90ZSI7CiAgbWVudV94bWx0dlsiX3VzYWdlIl0gICAgICAgID0gIjxiPkluZm86PC9iPjxicj5BdmFpbGFiaWxpdHk6IEZpbGUgYXZhaWxhYmlsaXR5IGluIHBlcmNlbnQ8YnI+Q2hhbm5lbHM6ICAgICBOdW1iZXIgb2YgY2hhbm5lbHMgaW4gdGhlIGZpbGU8YnI+UHJvZ3JhbXM6ICAgICBOdW1iZXIgb2YgRVBHIGRhdGE8YnI+PGJyPjxiPlVzYWdlOjwvYj48YnI+UmVtb3RlIFhNTFRWIGZpbGU6IGh0dHA6Ly95b3VyLmVwZy5wcm92aWRlci5jb20vZ3VpZGUueG1sPGJyPkxvY2FsICBYTUxUViBmaWxlOiAvcGF0aC90by9ndWlkZS54bWwiCiAgbWVudV94bWx0dlsibmFtZSJdICAgICAgICAgID0gInhtbHR2IjsKICBtZW51X3htbHR2WyJpZCJdICAgICAgICAgICAgPSAieG1sdHYiOwogIG1lbnVfeG1sdHZbInZhbHVlIl0gICAgICAgICA9IG1lbnVfeG1sdHZbIm5hbWUiXTsKICBtZW51X3htbHR2WyJwbGFjZWhvbGRlciJdICAgPSAiWE1MVFYgRmlsZTogbG9jYWwgb3IgcmVtb3RlIjsKICBtZW51X3htbHR2WyJvbmNsaWNrIl0gICAgICAgPSAiamF2YXNjcmlwdDogdG9nZ2xlTWVudSh0aGlzKTsiOwogIG1lbnVfeG1sdHZbImNsYXNzIl0gICAgICAgICA9ICJtZW51LW5vdEFjdGl2ZSI7CgogIG1lbnVfbWFwcGluZyA9IG5ldyBPYmplY3QoKTsKICBtZW51X21hcHBpbmdbIl9lbGVtZW50Il0gICA9ICJMSSI7CiAgbWVudV9tYXBwaW5nWyJfdGV4dCJdICAgICAgPSAiTWFwcGluZyI7CiAgbWVudV9tYXBwaW5nWyJfaWNvbiJdICAgICAgPSAiaW1nL21hcHBpbmcucG5nIjsKICBtZW51X21hcHBpbmdbIl9jb25maWdLZXkiXSA9ICJtYXBwaW5nIjsKICBtZW51X21hcHBpbmdbIl9oZWFkbGluZSJdICA9ICJYTUxUViBhc3NpZ25tZW50IGFuZCBzb3J0aW5nIG9mIGNoYW5uZWxzIjsKICBtZW51X21hcHBpbmdbImlkIl0gICAgICAgICA9ICJtYXBwaW5nIjsKICBtZW51X21hcHBpbmdbIm9uY2xpY2siXSAgICA9ICJqYXZhc2NyaXB0OiB0b2dnbGVNZW51KHRoaXMpOyI7CiAgbWVudV9tYXBwaW5nWyJjbGFzcyJdICAgICAgPSAibWVudS1ub3RBY3RpdmUgcGhvbmUiOwoKICBtZW51X3VzZXJzID0gbmV3IE9iamVjdCgpOwogIG1lbnVfdXNlcnNbIl9lbGVtZW50Il0gICA9ICJMSSI7CiAgbWVudV91c2Vyc1siX3RleHQiXSAgICAgID0gIlVzZXJzIjsKICBtZW51X3VzZXJzWyJfaWNvbiJdICAgICAgPSAiaW1nL3VzZXJzLnBuZyI7CiAgbWVudV91c2Vyc1siX2NvbmZpZ0tleSJdID0gInVzZXJzIjsKICBtZW51X3VzZXJzWyJfaGVhZGxpbmUiXSAgPSAiQWRtaW5pc3RyYXRpb24gb2YgdXNlcnMgYW5kIHBlcm1pc3Npb25zIjsKICBtZW51X3VzZXJzWyJpZCJdICAgICAgICAgPSAidXNlcnMiOwogIG1lbnVfdXNlcnNbIm9uY2xpY2siXSAgICA9ICJqYXZhc2NyaXB0OiB0b2dnbGVNZW51KHRoaXMpOyI7CiAgbWVudV91c2Vyc1siY2xhc3MiXSAgICAgID0gIm1lbnUtbm90QWN0aXZlIjsKICBtZW51X3VzZXJzWyJfdXNhZ2UiXSAgICAgPSAiPGI+QXV0aG9yaXphdGlvbiBncm91cHM6PC9iPjxicj5XRUI6IFVzZXJzIGNhbiBsb2cgaW4gdG8gdGhlIHdlYiBpbnRlcmZhY2U8YnI+UE1TOiBQcm9ncmFtcyBsaWtlIFBsZXggY2FuIGFjY2VzcyB0aGUgY2hhbm5lbCBsaXN0LiBMb2dpbiB2aWEgRFZSIElQOiB1c2VybmFtZTpwYXNzd29yZEB4dGV2ZS5pcDpwb3J0PGJyPk0zVTogQWxsb3dzIGNsaWVudHMgdG8gZG93bmxvYWQgdGhlIE0zVSBwbGF5bGlzdC48YnI+WE1MOiBBbGxvd3MgY2xpZW50cyB0byBkb3dubG9hZCB0aGUgWE1MVFYgZmlsZS48YnI+QVBJOiBBbGxvd3MgY2xpZW50cyB0byB1c2UgdGhlIEFQSSBpbnRlcmZhY2UuPGJyPjxicj4hISEgRm9yIFBNUyBhdXRoZW50aWNhdGlvbiwgb25seSB0aGUgZm9sbG93aW5nIHNwZWNpYWwgY2hhcmFjdGVycyBhcmUgdmFsaWQ6ICEkKCk9LiwtOjs8YnI+PGJyPlRoZSBpbmRpdmlkdWFsIGF1dGhlbnRpY2F0aW9uIGdyb3VwcyBjYW4gYmUgYWN0aXZhdGVkIC8gZGVhY3RpdmF0ZWQgaW4gdGhlIHNldHRpbmdzIG1lbnUuIgogIAogIG1lbnVfc2V0dGluZ3MgPSBuZXcgT2JqZWN0KCk7CiAgbWVudV9zZXR0aW5nc1siX2VsZW1lbnQiXSAgID0gIkxJIjsKICBtZW51X3NldHRpbmdzWyJfdGV4dCJdICAgICAgPSAiU2V0dGluZ3MiOwogIG1lbnVfc2V0dGluZ3NbIl9pY29uIl0gICAgICA9ICJpbWcvc2V0dGluZ3MucG5nIjsKICBtZW51X3NldHRpbmdzWyJfY29uZmlnS2V5Il0gPSAic2V0dGluZ3MiOwogIG1lbnVfc2V0dGluZ3NbIl9oZWFkbGluZSJdICA9ICJTZXR0aW5ncyI7CiAgbWVudV9zZXR0aW5nc1siX3N1Yk1lbnUiXSAgID0gIjcwMSw3MDIsNzAzLDcwNCw3MDUsNzA2LDcwNyw3MDgsNzk5LDcxMCw3MTEsNzEyLDcxMyw3MTQiOwogIG1lbnVfc2V0dGluZ3NbImlkIl0gICAgICAgICA9ICJzZXR0aW5ncyI7CiAgbWVudV9zZXR0aW5nc1sib25jbGljayJdICAgID0gImphdmFzY3JpcHQ6IHRvZ2dsZU1lbnUodGhpcyk7IjsKICBtZW51X3NldHRpbmdzWyJjbGFzcyJdICAgICAgPSAibWVudS1ub3RBY3RpdmUiOwoKICBtZW51X2xvZyA9IG5ldyBPYmplY3QoKTsKICBtZW51X2xvZ1siX2VsZW1lbnQiXSAgICAgICAgPSAiTEkiOwogIG1lbnVfbG9nWyJfdGV4dCJdICAgICAgICAgICA9ICJMb2ciOwogIG1lbnVfbG9nWyJfaWNvbiJdICAgICAgICAgICA9ICJpbWcvbG9nLnBuZyI7CiAgbWVudV9sb2dbIl9oZWFkbGluZSJdICAgICAgID0gIkxvZyI7CiAgbWVudV9sb2dbIl9jb25maWdLZXkiXSAgICAgID0gImxvZyI7CiAgbWVudV9sb2dbImlkIl0gICAgICAgICAgICAgID0gImxvZyI7CiAgbWVudV9sb2dbIm9uY2xpY2siXSAgICAgICAgID0gImphdmFzY3JpcHQ6IHRvZ2dsZU1lbnUodGhpcyk7IjsKICBtZW51X2xvZ1siY2xhc3MiXSAgICAgICAgICAgPSAibWVudS1ub3RBY3RpdmUiOwoKICBtZW51X2xvZ291dCA9IG5ldyBPYmplY3QoKTsKICBtZW51X2xvZ291dFsiX2VsZW1lbnQiXSAgID0gIkxJIjsKICBtZW51X2xvZ291dFsiX3RleHQiXSAgICAgID0gIkxvZ291dCI7CiAgbWVudV9sb2dvdXRbIl9pY29uIl0gICAgICA9ICJpbWcvbG9nb3V0LnBuZyI7CiAgbWVudV9sb2dvdXRbImlkIl0gICAgICAgICA9ICJsb2dvdXQiOwogIG1lbnVfbG9nb3V0WyJvbmNsaWNrIl0gICAgPSAiamF2YXNjcmlwdDogbG9nb3V0KCk7IjsKICBtZW51X2xvZ291dFsiY2xhc3MiXSAgICAgID0gIm1lbnUtbm90QWN0aXZlIjsKCiAgdmFyIG1lbnVfc2NoZWR1bGUgPSBuZXcgT2JqZWN0KCk7CiAgbWVudV9zY2hlZHVsZVsiX21lbnVUeXBlIl0gID0gImlucHV0QXJyYXkiOwogIG1lbnVfc2NoZWR1bGVbIl9lbGVtZW50Il0gICA9ICJMSSI7CiAgbWVudV9zY2hlZHVsZVsiX2NvbmZpZ0tleSJdID0gInVwZGF0ZSI7CiAgbWVudV9zY2hlZHVsZVsiX3RleHQiXSAgICAgID0gIlNjaGVkdWxlIjsKICBtZW51X3NjaGVkdWxlWyJfaWNvbiJdICAgICAgPSAiaW1nL3NjaGVkdWxlLnBuZyI7CiAgbWVudV9zY2hlZHVsZVsiX2hlYWRsaW5lIl0gID0gIlNjaGVkdWxlIGZvciB1cGRhdGluZyBNM1UsIFhNTFRWIGZpbGVzIGFuZCBjcmVhdGluZyBhIGxvY2FsIGJhY2t1cCI7CiAgbWVudV9zY2hlZHVsZVsiX3VzYWdlIl0gICAgID0gIjxiPlVzYWdlOjwvYj48YnI+MDgxNSA9IDg6MTUgYW08YnI+MTkzMCA9IDc6MzAgcG0iCiAgbWVudV9zY2hlZHVsZVsibmFtZSJdICAgICAgID0gInVwZGF0ZSI7CiAgbWVudV9zY2hlZHVsZVsiaWQiXSAgICAgICAgID0gInVwZGF0ZSI7CiAgbWVudV9zY2hlZHVsZVsidmFsdWUiXSAgICAgID0gbWVudV9pZFsibmFtZSJdOwogIG1lbnVfc2NoZWR1bGVbInBsYWNlaG9sZGVyIl09ICJ0aW1lIG9mIGRheSAoMjQtaG91ciBjbG9jaykiOwogIG1lbnVfc2NoZWR1bGVbIm9uY2xpY2siXSAgICA9ICJqYXZhc2NyaXB0OiB0b2dnbGVNZW51KHRoaXMpOyI7CiAgbWVudV9zY2hlZHVsZVsiY2xhc3MiXSAgICAgID0gIm1lbnUtbm90QWN0aXZlIjsKCiAgdmFyIG1lbnVfZmlsZXNVcGRhdGUgPSBuZXcgT2JqZWN0KCk7CiAgbWVudV9maWxlc1VwZGF0ZVsiX2VsZW1lbnQiXSA9ICJMSSI7CiAgbWVudV9maWxlc1VwZGF0ZVsiX21lbnVUeXBlIl0gICAgID0gImNoZWNrYm94IjsKICBtZW51X2ZpbGVzVXBkYXRlWyJfY29uZmlnS2V5Il0gICAgPSAiZmlsZXMudXBkYXRlIjsKICBtZW51X2ZpbGVzVXBkYXRlWyJfbGFiZWwiXSAgICAgICAgPSAiVXBkYXRlIHRoZSBwcm92aWRlciBmaWxlcyBhdCBzeXN0ZW0gc3RhcnR1cCI7CiAgbWVudV9maWxlc1VwZGF0ZVsiX2hlYWRsaW5lIl0gICAgID0gIlVwZGF0ZSB0aGUgcHJvdmlkZXIgZmlsZXMgYXQgc3lzdGVtIHN0YXJ0dXAiOwogIG1lbnVfZmlsZXNVcGRhdGVbIl91c2FnZSJdICAgICAgICA9ICJQbGF5bGlzdHMgYW5kIFhNTFRWIGZpbGVzIGFyZSB1cGRhdGVkIGJ5IHhUZVZlIGF0IHN5c3RlbSBzdGFydHVwLiIKICBtZW51X2ZpbGVzVXBkYXRlWyJuYW1lIl0gICAgICAgICAgPSAiZmlsZXMudXBkYXRlIjsKICBtZW51X2ZpbGVzVXBkYXRlWyJpZCJdICAgICAgICAgICAgPSAiZmlsZXMudXBkYXRlIjsKICBtZW51X2ZpbGVzVXBkYXRlWyJ2YWx1ZSJdICAgICAgICAgPSBtZW51X2ZpbGVzVXBkYXRlWyJuYW1lIl07CiAgbWVudV9maWxlc1VwZGF0ZVsib25jbGljayJdICAgICAgID0gImphdmFzY3JpcHQ6IHRvZ2dsZU1lbnUodGhpcyk7IjsKICBtZW51X2ZpbGVzVXBkYXRlWyJjbGFzcyJdICAgICAgICAgPSAibWVudS1ub3RBY3RpdmUiOwogIAogIHZhciBtZW51X3R1bmVyID0gbmV3IE9iamVjdCgpOwogIG1lbnVfdHVuZXJbIl9lbGVtZW50Il0gICAgICA9ICJMSSI7CiAgbWVudV90dW5lclsiX21lbnVUeXBlIl0gICAgID0gInNlbGVjdCI7CiAgbWVudV90dW5lclsiX2NvbmZpZ0tleSJdICAgID0gInR1bmVyIjsKICBtZW51X3R1bmVyWyJfbGFiZWwiXSAgICAgICAgPSAiQXZhaWxhYmxlIHR1bmVycyI7CiAgbWVudV90dW5lclsiX3RleHQiXSAgICAgICAgID0gIlR1bmVyIjsKICBtZW51X3R1bmVyWyJfaWNvbiJdICAgICAgICAgPSAiaW1nL3R1bmVyLnBuZyI7CiAgbWVudV90dW5lclsiX2hlYWRsaW5lIl0gICAgID0gIk51bWJlciBvZiB0dW5lcnMiOwogIG1lbnVfdHVuZXJbIl91c2FnZSJdICAgICAgICA9ICJUaGlzIHNldHRpbmcgaXMgb25seSB1c2VkIGJ5IFBsZXggYW5kIEVtYnkuPGJyPlRoZSBudW1iZXIgb2YgY29uY3VycmVudCBzdHJlYW1zIGFsbG93ZWQgYnkgdGhlIElQVFYgcHJvdmlkZXIuPGJyPkFmdGVyIGEgY2hhbmdlLCB4VGVWZSBtdXN0IGJlIGRlbGV0ZSBpbiB0aGUgUE1TIERWUiBzZXR0aW5ncyBhbmQgc2V0IHVwIGFnYWluLiIKICBtZW51X3R1bmVyWyJuYW1lIl0gICAgICAgICAgPSAidHVuZXIiOwogIG1lbnVfdHVuZXJbImlkIl0gICAgICAgICAgICA9ICJ0dW5lciI7CiAgbWVudV90dW5lclsidmFsdWUiXSAgICAgICAgID0gbWVudV90dW5lclsibmFtZSJdOwogIG1lbnVfdHVuZXJbInBsYWNlaG9sZGVyIl0gICA9ICJOdW1iZXIgb2YgdHVuZXJzIjsKICBtZW51X3R1bmVyWyJvbmNsaWNrIl0gICAgICAgPSAiamF2YXNjcmlwdDogdG9nZ2xlTWVudSh0aGlzKTsiOwogIG1lbnVfdHVuZXJbImNsYXNzIl0gICAgICAgICA9ICJtZW51LW5vdEFjdGl2ZSI7CgogIHZhciBvcHRpb25WYWx1ZXMgPSBuZXcgQXJyYXkoKTsKICBmb3IgKHZhciBpID0gMTsgaSA8PSAxMDA7IGkrKykgewogICAgb3B0aW9uVmFsdWVzLnB1c2goaSkKICB9CiAgbWVudV90dW5lclsiX29wdGlvblZhbHVlcyJdID0gb3B0aW9uVmFsdWVzOwogIAogIHZhciBtZW51X2VwZyA9IG5ldyBPYmplY3QoKTsKICBtZW51X2VwZ1siX2VsZW1lbnQiXSA9ICJMSSI7CiAgbWVudV9lcGdbIl9tZW51VHlwZSJdICAgICA9ICJzZWxlY3QiOwogIG1lbnVfZXBnWyJfY29uZmlnS2V5Il0gICAgPSAiZXBnU291cmNlIjsKICBtZW51X2VwZ1siX2xhYmVsIl0gICAgICAgID0gIlNlbGVjdGlvbiBvZiB0aGUgRVBHIHNvdXJjZSI7CiAgbWVudV9lcGdbIl90ZXh0Il0gICAgICAgICA9ICJFUEcgc291cmNlIjsKICBtZW51X2VwZ1siX2hlYWRsaW5lIl0gICAgID0gIlNlbGVjdGlvbiBvZiB0aGUgRVBHIHNvdXJjZSI7CiAgbWVudV9lcGdbIl91c2FnZSJdICAgICAgICA9ICJQTVM6ICAgVXNlIEVQRyBkYXRhIGZyb20gUGxleCBvciBFbWJ5Ljxicj5YRVBHOiAgVXNlIG9mIGV4dGVybmFsIEVQRyBkYXRhIChYTUxUVikuPGJyPiAgICAgICBTZXZlcmFsIFhNTFRWIHNvdXJjZXMgcG9zc2libGUuPGJyPiAgICAgICBBbGxvd3MgZWRpdGluZyBhbmQgb3JkZXIgY2hhbm5lbHMuPGJyPiAgICAgICBNM1UgLyBYTUxUViBleHBvcnQgKEhUVFAgbGluayBmb3IgSVBUViBhcHBzKS4iCiAgbWVudV9lcGdbIm5hbWUiXSAgICAgICAgICA9ICJlcGdTb3VyY2UiOwogIG1lbnVfZXBnWyJpZCJdICAgICAgICAgICAgPSAiZXBnU291cmNlIjsKICBtZW51X2VwZ1sidmFsdWUiXSAgICAgICAgID0gbWVudV9lcGdbIm5hbWUiXTsKICBtZW51X2VwZ1sicGxhY2Vob2xkZXIiXSAgID0gIkVQRyBzb3VyY2UiOwogIG1lbnVfZXBnWyJvbmNsaWNrIl0gICAgICAgPSAiamF2YXNjcmlwdDogdG9nZ2xlTWVudSh0aGlzKTsiOwogIG1lbnVfZXBnWyJjbGFzcyJdICAgICAgICAgPSAibWVudS1ub3RBY3RpdmUiOwogIG1lbnVfZXBnWyJfb3B0aW9uVmFsdWVzIl0gPSBuZXcgQXJyYXkoIlBNUyIsICJYRVBHIik7CgogIHZhciBtZW51X3hlcGcgPSBuZXcgT2JqZWN0KCk7CiAgbWVudV94ZXBnWyJfZWxlbWVudCJdID0gIkxJIjsKICBtZW51X3hlcGdbIl9tZW51VHlwZSJdICAgICA9ICJjaGVja2JveCI7CiAgbWVudV94ZXBnWyJfY29uZmlnS2V5Il0gICAgPSAieHRldmVBdXRvVXBkYXRlIjsKICBtZW51X3hlcGdbIl9sYWJlbCJdICAgICAgICA9ICJBdXRvbWF0aWMgdXBkYXRlIG9mIHhUZVZlIjsKICBtZW51X3hlcGdbIl9oZWFkbGluZSJdICAgICA9ICJBdXRvbWF0aWMgdXBkYXRlIG9mIHhUZVZlIjsKICBtZW51X3hlcGdbIl91c2FnZSJdICAgICAgICA9ICJJZiBhIG5ldyB2ZXJzaW9uIG9mIHhUZVZlIGlzIGF2YWlsYWJsZSwgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGluc3RhbGxlZC4iCiAgbWVudV94ZXBnWyJuYW1lIl0gICAgICAgICAgPSAieHRldmVBdXRvVXBkYXRlIjsKICBtZW51X3hlcGdbImlkIl0gICAgICAgICAgICA9ICJ4dGV2ZUF1dG9VcGRhdGUiOwogIG1lbnVfeGVwZ1sidmFsdWUiXSAgICAgICAgID0gbWVudV94ZXBnWyJuYW1lIl07CiAgbWVudV94ZXBnWyJvbmNsaWNrIl0gICAgICAgPSAiamF2YXNjcmlwdDogdG9nZ2xlTWVudSh0aGlzKTsiOwogIG1lbnVfeGVwZ1siY2xhc3MiXSAgICAgICAgID0gIm1lbnUtbm90QWN0aXZlIjsKCiAgdmFyIG1lbnVfYXV0b0JhY2t1cFBhdGggPSBuZXcgT2JqZWN0KCk7CiAgbWVudV9hdXRvQmFja3VwUGF0aFsiX2VsZW1lbnQiXSAgID0gIkxJIjsKICBtZW51X2F1dG9CYWNrdXBQYXRoWyJfbWVudVR5cGUiXSAgPSAic2luZ2xlSW5wdXQiOwogIG1lbnVfYXV0b0JhY2t1cFBhdGhbIl9jb25maWdLZXkiXSA9ICJiYWNrdXAucGF0aCI7CiAgbWVudV9hdXRvQmFja3VwUGF0aFsiX2xhYmVsIl0gICAgID0gIkxvY2F0aW9uIGZvciBhdXRvbWF0aWMgYmFja3VwcyI7CiAgbWVudV9hdXRvQmFja3VwUGF0aFsiX2hlYWRsaW5lIl0gID0gIkxvY2F0aW9uIGZvciBhdXRvbWF0aWMgYmFja3VwcyI7CiAgbWVudV9hdXRvQmFja3VwUGF0aFsiX3VzYWdlIl0gICAgID0gIkJlZm9yZSBhbnkgdXBkYXRlIG9mIHRoZSBwcm92aWRlciBkYXRhIGJ5IHRoZSBzY2hlZHVsZSwgeFRlVmUgY3JlYXRlcyBhIGJhY2t1cC4gVGhlIHBhdGggZm9yIHRoZSBhdXRvbWF0aWMgYmFja3VwcyBjYW4gYmUgY2hhbmdlZC4geFRlVmUgcmVxdWlyZXMgd3JpdGUgcGVybWlzc2lvbiBmb3IgdGhpcyBmb2xkZXIuIgogIG1lbnVfYXV0b0JhY2t1cFBhdGhbIm5hbWUiXSAgICAgICA9ICJiYWNrdXAucGF0aCI7CiAgbWVudV9hdXRvQmFja3VwUGF0aFsiaWQiXSAgICAgICAgID0gImJhY2t1cC5wYXRoIjsKICBtZW51X2F1dG9CYWNrdXBQYXRoWyJ2YWx1ZSJdICAgICAgPSBtZW51X2F1dG9CYWNrdXBQYXRoWyJuYW1lIl07CiAgbWVudV9hdXRvQmFja3VwUGF0aFsib25jbGljayJdICAgID0gImphdmFzY3JpcHQ6IHRvZ2dsZU1lbnUodGhpcyk7IjsKICBtZW51X2F1dG9CYWNrdXBQYXRoWyJjbGFzcyJdICAgICAgPSAibWVudS1ub3RBY3RpdmUiOwoKICB2YXIgbWVudV9hdXRvQmFja3VwS2VlcCA9IG5ldyBPYmplY3QoKTsKICBtZW51X2F1dG9CYWNrdXBLZWVwWyJfZWxlbWVudCJdICAgPSAiTEkiOwogIG1lbnVfYXV0b0JhY2t1cEtlZXBbIl9tZW51VHlwZSJdICA9ICJzZWxlY3QiOwogIG1lbnVfYXV0b0JhY2t1cEtlZXBbIl9jb25maWdLZXkiXSA9ICJiYWNrdXAua2VlcCI7CiAgbWVudV9hdXRvQmFja3VwS2VlcFsiX3RleHQiXSAgICAgID0gIktlZXAiOwogIG1lbnVfYXV0b0JhY2t1cEtlZXBbIl9sYWJlbCJdICAgICA9ICJOdW1iZXIgb2YgYmFja3VwcyB0byBrZWVwIjsKICBtZW51X2F1dG9CYWNrdXBLZWVwWyJfaGVhZGxpbmUiXSAgPSAiTnVtYmVyIG9mIGJhY2t1cHMgdG8ga2VlcCI7CiAgbWVudV9hdXRvQmFja3VwS2VlcFsiX3VzYWdlIl0gICAgID0gIiIKICBtZW51X2F1dG9CYWNrdXBLZWVwWyJuYW1lIl0gICAgICAgPSAiYmFja3VwLmtlZXAiOwogIG1lbnVfYXV0b0JhY2t1cEtlZXBbImlkIl0gICAgICAgICA9ICJiYWNrdXAua2VlcCI7CiAgbWVudV9hdXRvQmFja3VwS2VlcFsidmFsdWUiXSAgICAgID0gbWVudV9hdXRvQmFja3VwS2VlcFsibmFtZSJdOwogIG1lbnVfYXV0b0JhY2t1cEtlZXBbIm9uY2xpY2siXSAgICA9ICJqYXZhc2NyaXB0OiB0b2dnbGVNZW51KHRoaXMpOyI7CiAgbWVudV9hdXRvQmFja3VwS2VlcFsiY2xhc3MiXSAgICAgID0gIm1lbnUtbm90QWN0aXZlIjsKCiAgdmFyIG9wdGlvblZhbHVlcyA9IG5ldyBBcnJheSg1LCAxMCwgMjAsIDMwLCA0MCwgNTApOwogIG1lbnVfYXV0b0JhY2t1cEtlZXBbIl9vcHRpb25WYWx1ZXMiXSA9IG9wdGlvblZhbHVlczsKCgogIHZhciBtZW51X2J1ZmZlciA9IG5ldyBPYmplY3QoKTsKICBtZW51X2J1ZmZlclsiX2VsZW1lbnQiXSA9ICJMSSI7CiAgbWVudV9idWZmZXJbIl9tZW51VHlwZSJdICAgICA9ICJjaGVja2JveCI7CiAgbWVudV9idWZmZXJbIl9jb25maWdLZXkiXSAgICA9ICJidWZmZXIiOwogIG1lbnVfYnVmZmVyWyJfbGFiZWwiXSAgICAgICAgPSAiU3RyZWFtIGJ1ZmZlcmluZyBbRXhwZXJpbWVudGFsXSI7CiAgbWVudV9idWZmZXJbIl9oZWFkbGluZSJdICAgICA9ICJTdHJlYW0gYnVmZmVyaW5nIFtFeHBlcmltZW50YWxdIjsKICBtZW51X2J1ZmZlclsiX3VzYWdlIl0gICAgICAgID0gIldpdGggYWN0aXZhdGVkIGJ1ZmZlciwgc3RyZWFtcyBjYW4gYmUgcGxheWVkIGFuZCByZWNvcmRlZCBtb3JlIGZsdWVudGx5Ljxicj5UaGUgc3RyZWFtIGlzIHBhc3NlZCBmcm9tIHhUZVZlIHRvIFBsZXggLyBFbWJ5IgogIG1lbnVfYnVmZmVyWyJuYW1lIl0gICAgICAgICAgPSAiYnVmZmVyIjsKICBtZW51X2J1ZmZlclsiaWQiXSAgICAgICAgICAgID0gImJ1ZmZlciI7CiAgbWVudV9idWZmZXJbInZhbHVlIl0gICAgICAgICA9IG1lbnVfYnVmZmVyWyJuYW1lIl07CiAgbWVudV9idWZmZXJbIm9uY2xpY2siXSAgICAgICA9ICJqYXZhc2NyaXB0OiB0b2dnbGVNZW51KHRoaXMpOyI7CiAgbWVudV9idWZmZXJbImNsYXNzIl0gICAgICAgICA9ICJtZW51LW5vdEFjdGl2ZSI7CgogIHZhciBtZW51X2FwaSA9IG5ldyBPYmplY3QoKTsKICBtZW51X2FwaVsiX2VsZW1lbnQiXSA9ICJMSSI7CiAgbWVudV9hcGlbIl9tZW51VHlwZSJdICAgICA9ICJjaGVja2JveCI7CiAgbWVudV9hcGlbIl9jb25maWdLZXkiXSAgICA9ICJhcGkiOwogIG1lbnVfYXBpWyJfbGFiZWwiXSAgICAgICAgPSAiQVBJIGludGVyZmFjZSI7CiAgbWVudV9hcGlbIl9oZWFkbGluZSJdICAgICA9ICJBUEkgaW50ZXJmYWNlIjsKICBtZW51X2FwaVsiX3VzYWdlIl0gICAgICAgID0gJ1ZpYSBBUEkgaW50ZXJmYWNlIGl0IGlzIHBvc3NpYmxlIHRvIHNlbmQgY29tbWFuZHMgdG8geFRlVmUuIEFQSSBkb2N1bWVudGF0aW9uIGlzIGF2YWlsYWJsZSA8YSBocmVmPSJodHRwczovL3h0ZXZlLmRlP3Njcm9sbD1hcGkiPmhlcmU8L2E+ICcKICAvL21lbnVfYXBpWyJfdXNhZ2UiXSAgICAgICAgPSAnVmlhIEFQSSBpbnRlcmZhY2UgaXQgaXMgcG9zc2libGUgdG8gc2VuZCBjb21tYW5kcyB0byB4VGVWZS4gQVBJIGRvY3VtZW50YXRpb24gaXMgYXZhaWxhYmxlIDxhIGhyZWY9Imh0dHA6Ly9sb2NhbGhvc3Q6MTMxMz9zY3JvbGw9YXBpIj5oZXJlPC9hPiAnCiAgbWVudV9hcGlbIm5hbWUiXSAgICAgICAgICA9ICJhcGkiOwogIG1lbnVfYXBpWyJpZCJdICAgICAgICAgICAgPSAiYXBpIjsKICBtZW51X2FwaVsidmFsdWUiXSAgICAgICAgID0gbWVudV9hcGlbIm5hbWUiXTsKICBtZW51X2FwaVsib25jbGljayJdICAgICAgID0gImphdmFzY3JpcHQ6IHRvZ2dsZU1lbnUodGhpcyk7IjsKICBtZW51X2FwaVsiY2xhc3MiXSAgICAgICAgID0gIm1lbnUtbm90QWN0aXZlIjsKCiAgdmFyIG1lbnVfYXV0aGVudGljYXRpb25XZWIgPSBuZXcgT2JqZWN0KCk7CiAgbWVudV9hdXRoZW50aWNhdGlvbldlYlsiX2VsZW1lbnQiXSA9ICJMSSI7CiAgbWVudV9hdXRoZW50aWNhdGlvbldlYlsiX21lbnVUeXBlIl0gICAgID0gImNoZWNrYm94IjsKICBtZW51X2F1dGhlbnRpY2F0aW9uV2ViWyJfY29uZmlnS2V5Il0gICAgPSAiYXV0aGVudGljYXRpb24ud2ViIjsKICBtZW51X2F1dGhlbnRpY2F0aW9uV2ViWyJfbGFiZWwiXSAgICAgICAgPSAiVXNlciBhdXRoZW50aWNhdGlvbiI7CiAgbWVudV9hdXRoZW50aWNhdGlvbldlYlsiX2hlYWRsaW5lIl0gICAgID0gIlVzZXIgYXV0aGVudGljYXRpb24iOwogIG1lbnVfYXV0aGVudGljYXRpb25XZWJbIl91c2FnZSJdICAgICAgICA9ICJBY2Nlc3MgdG8geFRlVmUgcmVxdWlyZXMgYXV0aGVudGljYXRpb24uIgogIG1lbnVfYXV0aGVudGljYXRpb25XZWJbIm5hbWUiXSAgICAgICAgICA9ICJhdXRoZW50aWNhdGlvbi53ZWIiOwogIG1lbnVfYXV0aGVudGljYXRpb25XZWJbImlkIl0gICAgICAgICAgICA9ICJhdXRoZW50aWNhdGlvbi53ZWIiOwogIG1lbnVfYXV0aGVudGljYXRpb25XZWJbInZhbHVlIl0gICAgICAgICA9IG1lbnVfYXV0aGVudGljYXRpb25XZWJbIm5hbWUiXTsKICBtZW51X2F1dGhlbnRpY2F0aW9uV2ViWyJvbmNsaWNrIl0gICAgICAgPSAiamF2YXNjcmlwdDogdG9nZ2xlTWVudSh0aGlzKTsiOwogIG1lbnVfYXV0aGVudGljYXRpb25XZWJbImNsYXNzIl0gICAgICAgICA9ICJtZW51LW5vdEFjdGl2ZSI7CiAgCiAgdmFyIG1lbnVfYXV0aGVudGljYXRpb25QbXMgPSBuZXcgT2JqZWN0KCk7CiAgbWVudV9hdXRoZW50aWNhdGlvblBtc1siX2VsZW1lbnQiXSA9ICJMSSI7CiAgbWVudV9hdXRoZW50aWNhdGlvblBtc1siX21lbnVUeXBlIl0gICAgID0gImNoZWNrYm94IjsKICBtZW51X2F1dGhlbnRpY2F0aW9uUG1zWyJfY29uZmlnS2V5Il0gICAgPSAiYXV0aGVudGljYXRpb24ucG1zIjsKICBtZW51X2F1dGhlbnRpY2F0aW9uUG1zWyJfbGFiZWwiXSAgICAgICAgPSAiUGxleCBhdXRoZW50aWNhdGlvbi4iOwogIG1lbnVfYXV0aGVudGljYXRpb25QbXNbIl9oZWFkbGluZSJdICAgICA9ICJQbGV4IGF1dGhlbnRpY2F0aW9uLiI7CiAgbWVudV9hdXRoZW50aWNhdGlvblBtc1siX3VzYWdlIl0gICAgICAgID0gIlBsZXggcmVxdWVzdHMgYXJlIG9ubHkgcG9zc2libGUgd2l0aCBhdXRoZW50aWNhdGlvbi48YnI+V2FybmluZyEhISBBZnRlciBhY3RpdmF0aW5nIHRoaXMgZnVuY3Rpb24geFRlVmUgbXVzdCBiZSBkZWxldGUgaW4gdGhlIFBNUyBEVlIgc2V0dGluZ3MgYW5kIHNldCB1cCBhZ2Fpbi4iCiAgbWVudV9hdXRoZW50aWNhdGlvblBtc1sibmFtZSJdICAgICAgICAgID0gImF1dGhlbnRpY2F0aW9uLnBtcyI7CiAgbWVudV9hdXRoZW50aWNhdGlvblBtc1siaWQiXSAgICAgICAgICAgID0gImF1dGhlbnRpY2F0aW9uLnBtcyI7CiAgbWVudV9hdXRoZW50aWNhdGlvblBtc1sidmFsdWUiXSAgICAgICAgID0gbWVudV9hdXRoZW50aWNhdGlvblBtc1sibmFtZSJdOwogIG1lbnVfYXV0aGVudGljYXRpb25QbXNbIm9uY2xpY2siXSAgICAgICA9ICJqYXZhc2NyaXB0OiB0b2dnbGVNZW51KHRoaXMpOyI7CiAgbWVudV9hdXRoZW50aWNhdGlvblBtc1siY2xhc3MiXSAgICAgICAgID0gIm1lbnUtbm90QWN0aXZlIjsKICAKICB2YXIgbWVudV9hdXRoZW50aWNhdGlvbk0zdSA9IG5ldyBPYmplY3QoKTsKICBtZW51X2F1dGhlbnRpY2F0aW9uTTN1WyJfZWxlbWVudCJdID0gIkxJIjsKICBtZW51X2F1dGhlbnRpY2F0aW9uTTN1WyJfbWVudVR5cGUiXSAgICAgPSAiY2hlY2tib3giOwogIG1lbnVfYXV0aGVudGljYXRpb25NM3VbIl9jb25maWdLZXkiXSAgICA9ICJhdXRoZW50aWNhdGlvbi5tM3UiOwogIG1lbnVfYXV0aGVudGljYXRpb25NM3VbIl9sYWJlbCJdICAgICAgICA9ICJNM1UgYXV0aGVudGljYXRpb24uIjsKICBtZW51X2F1dGhlbnRpY2F0aW9uTTN1WyJfaGVhZGxpbmUiXSAgICAgPSAiTTNVIGF1dGhlbnRpY2F0aW9uLiI7CiAgbWVudV9hdXRoZW50aWNhdGlvbk0zdVsiX3VzYWdlIl0gICAgICAgID0gIkRvd25sb2FkaW5nIHRoZSBNM1UgZmlsZSB2aWEgYW4gSFRUUCByZXF1ZXN0IGlzIG9ubHkgcG9zc2libGUgd2l0aCBhdXRoZW50aWNhdGlvbi4iCiAgbWVudV9hdXRoZW50aWNhdGlvbk0zdVsibmFtZSJdICAgICAgICAgID0gImF1dGhlbnRpY2F0aW9uLm0zdSI7CiAgbWVudV9hdXRoZW50aWNhdGlvbk0zdVsiaWQiXSAgICAgICAgICAgID0gImF1dGhlbnRpY2F0aW9uLm0zdSI7CiAgbWVudV9hdXRoZW50aWNhdGlvbk0zdVsidmFsdWUiXSAgICAgICAgID0gbWVudV9hdXRoZW50aWNhdGlvbk0zdVsibmFtZSJdOwogIG1lbnVfYXV0aGVudGljYXRpb25NM3VbIm9uY2xpY2siXSAgICAgICA9ICJqYXZhc2NyaXB0OiB0b2dnbGVNZW51KHRoaXMpOyI7CiAgbWVudV9hdXRoZW50aWNhdGlvbk0zdVsiY2xhc3MiXSAgICAgICAgID0gIm1lbnUtbm90QWN0aXZlIjsKICAKCiAgdmFyIG1lbnVfYXV0aGVudGljYXRpb25YbWwgPSBuZXcgT2JqZWN0KCk7CiAgbWVudV9hdXRoZW50aWNhdGlvblhtbFsiX2VsZW1lbnQiXSA9ICJMSSI7CiAgbWVudV9hdXRoZW50aWNhdGlvblhtbFsiX21lbnVUeXBlIl0gICAgID0gImNoZWNrYm94IjsKICBtZW51X2F1dGhlbnRpY2F0aW9uWG1sWyJfY29uZmlnS2V5Il0gICAgPSAiYXV0aGVudGljYXRpb24ueG1sIjsKICBtZW51X2F1dGhlbnRpY2F0aW9uWG1sWyJfbGFiZWwiXSAgICAgICAgPSAiWEVQRyBhdXRoZW50aWNhdGlvbiI7CiAgbWVudV9hdXRoZW50aWNhdGlvblhtbFsiX2hlYWRsaW5lIl0gICAgID0gIlhFUEcgYXV0aGVudGljYXRpb24iOwogIG1lbnVfYXV0aGVudGljYXRpb25YbWxbIl91c2FnZSJdICAgICAgICA9ICJEb3dubG9hZGluZyB0aGUgWEVQRyAoWE1MVFYpIGZpbGUgdmlhIGFuIEhUVFAgcmVxdWVzdCBpcyBvbmx5IHBvc3NpYmxlIHdpdGggYXV0aGVudGljYXRpb24uIgogIG1lbnVfYXV0aGVudGljYXRpb25YbWxbIm5hbWUiXSAgICAgICAgICA9ICJhdXRoZW50aWNhdGlvbi54bWwiOwogIG1lbnVfYXV0aGVudGljYXRpb25YbWxbImlkIl0gICAgICAgICAgICA9ICJhdXRoZW50aWNhdGlvbi54bWwiOwogIG1lbnVfYXV0aGVudGljYXRpb25YbWxbInZhbHVlIl0gICAgICAgICA9IG1lbnVfYXV0aGVudGljYXRpb25YbWxbIm5hbWUiXTsKICBtZW51X2F1dGhlbnRpY2F0aW9uWG1sWyJvbmNsaWNrIl0gICAgICAgPSAiamF2YXNjcmlwdDogdG9nZ2xlTWVudSh0aGlzKTsiOwogIG1lbnVfYXV0aGVudGljYXRpb25YbWxbImNsYXNzIl0gICAgICAgICA9ICJtZW51LW5vdEFjdGl2ZSI7CgogIHZhciBtZW51X2F1dGhlbnRpY2F0aW9uQXBpID0gbmV3IE9iamVjdCgpOwogIG1lbnVfYXV0aGVudGljYXRpb25BcGlbIl9lbGVtZW50Il0gPSAiTEkiOwogIG1lbnVfYXV0aGVudGljYXRpb25BcGlbIl9tZW51VHlwZSJdICAgICA9ICJjaGVja2JveCI7CiAgbWVudV9hdXRoZW50aWNhdGlvbkFwaVsiX2NvbmZpZ0tleSJdICAgID0gImF1dGhlbnRpY2F0aW9uLmFwaSI7CiAgbWVudV9hdXRoZW50aWNhdGlvbkFwaVsiX2xhYmVsIl0gICAgICAgID0gIkFQSSBhdXRoZW50aWNhdGlvbiI7CiAgbWVudV9hdXRoZW50aWNhdGlvbkFwaVsiX2hlYWRsaW5lIl0gICAgID0gIkFQSSBhdXRoZW50aWNhdGlvbiI7CiAgbWVudV9hdXRoZW50aWNhdGlvbkFwaVsiX3VzYWdlIl0gICAgICAgID0gIkFjY2VzcyB0byB0aGUgQVBJIGludGVyZmFjZSBpcyBvbmx5IHBvc3NpYmxlIHdpdGggYXV0aGVudGljYXRpb24uIgogIG1lbnVfYXV0aGVudGljYXRpb25BcGlbIm5hbWUiXSAgICAgICAgICA9ICJhdXRoZW50aWNhdGlvbi5hcGkiOwogIG1lbnVfYXV0aGVudGljYXRpb25BcGlbImlkIl0gICAgICAgICAgICA9ICJhdXRoZW50aWNhdGlvbi5hcGkiOwogIG1lbnVfYXV0aGVudGljYXRpb25BcGlbInZhbHVlIl0gICAgICAgICA9IG1lbnVfYXV0aGVudGljYXRpb25BcGlbIm5hbWUiXTsKICBtZW51X2F1dGhlbnRpY2F0aW9uQXBpWyJvbmNsaWNrIl0gICAgICAgPSAiamF2YXNjcmlwdDogdG9nZ2xlTWVudSh0aGlzKTsiOwogIG1lbnVfYXV0aGVudGljYXRpb25BcGlbImNsYXNzIl0gICAgICAgICA9ICJtZW51LW5vdEFjdGl2ZSI7CiAgCiAgCiAgLy8gTWFpbiBtZW51CiAgbWVudVsxMF0gPSBtZW51X20zdTsKCiAgc3dpdGNoKGNvbmZpZ1siZXBnU291cmNlIl0pIHsKICAgIGNhc2UgIlBNUyI6CiAgICAgIG1lbnVbMjBdID0gbWVudV9pZDsKICAgICAgYnJlYWs7CiAgICAKICAgIGNhc2UgIlhNTFRWIjoKICAgICAgbWVudVs0MF0gPSBtZW51X3htbHR2OwogICAgICBicmVhazsKCiAgICBjYXNlICJYRVBHIjoKICAgICAgbWVudVs0MF0gPSBtZW51X3htbHR2OwogICAgICBtZW51WzUwXSA9IG1lbnVfbWFwcGluZzsKICAgICAgYnJlYWs7CiAgfQogIAogIG1lbnVbMzBdID0gbWVudV9maWx0ZXI7CiAgCiAgaWYgKGNvbmZpZ1siYXV0aGVudGljYXRpb24ud2ViIl0gPT0gdHJ1ZSkgewogICAgbWVudVs2MF0gPSBtZW51X3VzZXJzOwogIH0KCiAgbWVudVs3MF0gPSBtZW51X3NldHRpbmdzOwogIG1lbnVbODBdID0gbWVudV9sb2c7CiAgaWYgKGNvbmZpZ1siYXV0aGVudGljYXRpb24ud2ViIl0gPT0gdHJ1ZSkgewogICAgbWVudVsxMDBdID0gbWVudV9sb2dvdXQ7CiAgfSAKICAKCiAgLy8gU3ViLU1lbnUKCiAgc3ViTWVudVs3MDFdID0gbWVudV9zY2hlZHVsZTsKICBzdWJNZW51WzcwMl0gPSBtZW51X2ZpbGVzVXBkYXRlOwogIHN1Yk1lbnVbNzAzXSA9IG1lbnVfdHVuZXI7CiAgc3ViTWVudVs3MDRdID0gbWVudV9lcGc7CiAgc3ViTWVudVs3MDVdID0gbWVudV94ZXBnOwogIHN1Yk1lbnVbNzA2XSA9IG1lbnVfYXV0b0JhY2t1cFBhdGg7CiAgc3ViTWVudVs3MDddID0gbWVudV9hdXRvQmFja3VwS2VlcDsKICBzdWJNZW51WzcwOF0gPSBtZW51X2J1ZmZlcjsKICAKICBzdWJNZW51WzcxMF0gPSBtZW51X2F1dGhlbnRpY2F0aW9uV2ViOwogIAogIGlmIChjb25maWdbImF1dGhlbnRpY2F0aW9uLndlYiJdID09IHRydWUpIHsKICAgIHN1Yk1lbnVbNzExXSA9IG1lbnVfYXV0aGVudGljYXRpb25QbXM7CiAgICBzdWJNZW51WzcxMl0gPSBtZW51X2F1dGhlbnRpY2F0aW9uTTN1OwogICAgc3ViTWVudVs3MTNdID0gbWVudV9hdXRoZW50aWNhdGlvblhtbDsKICAgIHN1Yk1lbnVbNzE0XSA9IG1lbnVfYXV0aGVudGljYXRpb25BcGk7CiAgfQoKICBzdWJNZW51Wzc5OV0gPSBtZW51X2FwaTsKCiAgCgogIHJldHVybgp9CgpmdW5jdGlvbiBjcmVhdGVNZW51KCkgewoKICBzaG93RWxlbWVudCgicG9wdXAiLCBmYWxzZSk7CgogIC8vY29uc29sZS5sb2coY29uZmlnKTsKICBzZXRNZW51SXRlbSgpOwogIHZhciBtZW51SXRlbXMgPSBnZXRPYmpLZXlzKG1lbnUpCiAgdmFyIG5hdiA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJOQVYiKVswXTsKICBuYXYuaW5uZXJIVE1MID0gIiI7CiAgdmFyIG5ld0l0ZW0gPSBuZXcgT2JqZWN0KCk7CgogIGZvciAodmFyIGkgPSAwOyBpIDwgbWVudUl0ZW1zLmxlbmd0aDsgaSsrKSB7CgogICAgCiAgICB2YXIgbmV3SXRlbSA9IG1lbnVbbWVudUl0ZW1zW2ldXTsKICAgIG5ld0l0ZW1bImlkIl0gPSBtZW51SXRlbXNbaV07CgogICAgCiAgICBzd2l0Y2gobmV3SXRlbS5oYXNPd25Qcm9wZXJ0eSgiX2ljb24iKSkgewogICAgICBjYXNlIHRydWU6IAogICAgICAgIHZhciBpdGVtVGV4dCA9IG5ld0l0ZW1bIl90ZXh0Il07CiAgICAgICAgZGVsZXRlIG5ld0l0ZW1bIl90ZXh0Il0KICAgICAgICBuYXYuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdJdGVtKSk7CiAgICAgICAgbmV3SXRlbVsiX3RleHQiXSA9IGl0ZW1UZXh0OwogICAgICAgIHZhciBuZXdJY29uID0gbmV3IE9iamVjdCgpOwogICAgICAgIG5ld0ljb25bIl9lbGVtZW50Il0gPSAiSU1HIjsKICAgICAgICBuZXdJY29uWyJzcmMiXSA9IG5ld0l0ZW1bIl9pY29uIl07CgogICAgICAgIHZhciBjdXJyZW50RWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKG1lbnVJdGVtc1tpXSk7CiAgICAgICAgY3VycmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdJY29uKSk7CgoKICAgICAgICB2YXIgdGV4dCA9IG5ldyBPYmplY3QoKTsKICAgICAgICB0ZXh0WyJfZWxlbWVudCJdID0gIlAiCiAgICAgICAgdGV4dFsiX3RleHQiXSA9IGl0ZW1UZXh0OwogICAgICAgIHRleHRbImNsYXNzIl0gPSAibmF2LXRleHQiCiAgICAgICAgY3VycmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudCh0ZXh0KSk7CiAgICAgICAgYnJlYWs7CgogICAgICBkZWZhdWx0OgogICAgICAgIG5hdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0ljb24pKTsKICAgICAgICBicmVhazsKICAgIH0KCiAgfQogIGlmIChhY3RpdmVNZW51ICE9IHVuZGVmaW5lZCkgewogICAgLy9jb25zb2xlLmxvZyhhY3RpdmVNZW51KTsKICAgIHRvZ2dsZU1lbnUoYWN0aXZlTWVudSk7CiAgfQoKICByZXR1cm4KfQoKZnVuY3Rpb24gdG9nZ2xlTWVudShlbG0pIHsKICAvL3Nob3dTdHJlYW1zKGZhbHNlKTsKICBjbGVhckludGVydmFsKGxvZ0ludGVydmFsKQogIGFjdGl2ZU1lbnUgPSBlbG07CiAgdmFyIGl0ZW0gPSBtZW51W2VsbS5pZF0KICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNldHRpbmdzIik7CiAgZGl2LmlubmVySFRNTCA9ICIiOwogIAogIC8vIFNldCBIZWFkbGluZQogIHZhciBoZWFkbGluZSA9IG5ldyBPYmplY3QoKTsKICBoZWFkbGluZVsiX2VsZW1lbnQiXSA9ICJINCI7CiAgaGVhZGxpbmVbIl90ZXh0Il0gPSBpdGVtWyJfaGVhZGxpbmUiXTsKICBkaXYuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChoZWFkbGluZSkpOwoKICAvLyBTdWItTWVudQogIGlmIChpdGVtLmhhc093blByb3BlcnR5KCJfc3ViTWVudSIpID09IHRydWUpIHsKICAgIG9wZW5TdWJNZW51KGl0ZW0pOwogICAgcmV0dXJuCiAgfQoKICAvLyBNYXBwaW5nLCBVc2VycywgTG9nLCBGaWxlcwogIHN3aXRjaChpdGVtWyJfY29uZmlnS2V5Il0pIHsKICAgIGNhc2UgIm1hcHBpbmciOiAgICAgb3Blbk1hcHBpbmdFZGl0b3IoaXRlbSk7IHJldHVybjsgYnJlYWs7CiAgICBjYXNlICJ1c2VycyI6ICAgICAgIG9wZW5Vc2VycyhpdGVtKTsgcmV0dXJuOyBicmVhazsKICAgIGNhc2UgImxvZyI6ICAgICAgICAgc2hvd0xvZyhpdGVtKTsgcmV0dXJuOyBicmVhazsKICAgIGNhc2UgImZpbGVzLm0zdSI6ICAgb3BlbkZpbGVzKGl0ZW0sICJtM3UiKTsgcmV0dXJuOyBicmVhazsKICAgIGNhc2UgImZpbGVzLnhtbHR2Ijogb3BlbkZpbGVzKGl0ZW0sICJ4bWx0diIpOyByZXR1cm47IGJyZWFrOwoKICAgIGNhc2UgImZpbHRlciI6ICAgICAgc2hvd1N0cmVhbXModHJ1ZSk7IGJyZWFrOwogIH0KCiAKCiAgdmFyIG5ld0hSID0gbmV3IE9iamVjdCgpOwogIG5ld0hSWyJfZWxlbWVudCJdID0gIkhSIgogIGRpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0hSKSk7CiAgCiAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogIG5ld0VudHJ5WyJfZWxlbWVudCJdICA9ICJJTlBVVCI7CiAgbmV3RW50cnlbInR5cGUiXSA9ICJidXR0b24iOwogIC8vbmV3RW50cnlbImNsYXNzIl0gPSAic2F2ZSI7CiAgbmV3RW50cnlbInZhbHVlIl0gPSAiU2F2ZSI7CiAgbmV3RW50cnlbIm9uY2xpY2siXSA9ICJzYXZlRGF0YTIoJ3NldHRpbmdzJykiCiAgZGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKCgogIHZhciBuZXdXcmFwcGVyID0gbmV3IE9iamVjdCgpOwogIG5ld1dyYXBwZXJbIl9lbGVtZW50Il0gID0gIkRJViI7CiAgbmV3V3JhcHBlclsiaWQiXSAgICAgICAgPSAiYm94LXdyYXBwZXIiOwogIGRpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld1dyYXBwZXIpKTsKCiAgZGl2ID0gZGl2Lmxhc3RDaGlsZDsKICAKICBkaXYuYXBwZW5kQ2hpbGQoY3JlYXRlTWVudUl0ZW0oaXRlbSkpCgogIC8vIHVzYWdlIEluZm8gIAogIHN3aXRjaChtZW51W2FjdGl2ZU1lbnUuaWRdLmhhc093blByb3BlcnR5KCJfdXNhZ2UiKSkgewogICAgY2FzZSB0cnVlOiAKICAgICAgdmFyIHVzYWdlSXRlbSA9IG5ldyBPYmplY3QoKTsKICAgICAgdXNhZ2VJdGVtWyJfZWxlbWVudCJdID0gIlBSRSIKICAgICAgdXNhZ2VJdGVtWyJfdGV4dCJdICAgID0gbWVudVthY3RpdmVNZW51LmlkXVsiX3VzYWdlIl07CiAgICAgIGRpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KHVzYWdlSXRlbSkpOwogIH0KICAKICBjYWxjdWxhdGVXcmFwcGVySGVpZ2h0KCk7Cgp9CgpmdW5jdGlvbiBjcmVhdGVNZW51SXRlbShpdGVtKSB7CiAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJESVYiKTsKICBzd2l0Y2goaXRlbVsiX21lbnVUeXBlIl0pIHsKICAgIGNhc2UgImlucHV0QXJyYXkiOgogICAgICBpZiAoY29uZmlnLmhhc093blByb3BlcnR5KGl0ZW1bIl9jb25maWdLZXkiXSkgPT0gdHJ1ZSkgewogICAgICAgIHZhciB2YWx1ZSA9IGNvbmZpZ1tpdGVtWyJfY29uZmlnS2V5Il1dOwogICAgICB9IGVsc2UgewogICAgICAgIHZhciB2YWx1ZSA9IG5ldyBBcnJheSgpOwogICAgICB9CiAgICAgIAogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZhbHVlLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogICAgICAgIG5ld0VudHJ5ID0gaXRlbQogICAgICAgIGRlbGV0ZSBuZXdFbnRyeVsib25jbGljayJdOwogICAgICAgIG5ld0VudHJ5WyJfZWxlbWVudCJdICA9ICJJTlBVVCI7CiAgICAgICAgbmV3RW50cnlbInZhbHVlIl0gICAgID0gdmFsdWVbaV07CiAgICAgICAgbmV3RW50cnlbInR5cGUiXSAgICAgID0gInNlYXJjaCI7CiAgICAgICAgbmV3RW50cnlbImRhdGEtbWVudXR5cGUiXSA9IGl0ZW1bIl9tZW51VHlwZSJdOwogICAgICAgIG5ld0VudHJ5WyJkYXRhLW1lbnVrZXkiXSA9IGl0ZW1bIl9jb25maWdLZXkiXTsKICAgICAgICBlbGVtZW50LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKCiAgICAgIH0KICAgICAgLy8gTmV3IGVudHJ5IGZvciBhcnJheQogICAgICB2YXIgbmV3RW50cnkgPSBuZXcgT2JqZWN0KCk7CiAgICAgIG5ld0VudHJ5WyJfZWxlbWVudCJdICAgICAgPSAiSU5QVVQiOwogICAgICBuZXdFbnRyeVsidHlwZSJdICAgICAgICAgID0gInNlYXJjaCI7CiAgICAgIG5ld0VudHJ5WyJuYW1lIl0gICAgICAgICAgPSBpdGVtWyJuYW1lIl07CiAgICAgIG5ld0VudHJ5WyJwbGFjZWhvbGRlciJdICAgPSBpdGVtWyJwbGFjZWhvbGRlciJdOwogICAgICBuZXdFbnRyeVsidmFsdWUiXSAgICAgICAgID0gIiI7CiAgICAgIG5ld0VudHJ5WyJkYXRhLW1lbnV0eXBlIl0gPSBpdGVtWyJfbWVudVR5cGUiXTsKICAgICAgbmV3RW50cnlbImRhdGEtbWVudWtleSJdICA9IGl0ZW1bIl9jb25maWdLZXkiXTsKICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0VudHJ5KSk7CiAgICAgIGJyZWFrOwogIAogICAgY2FzZSAic2luZ2xlSW5wdXQiOgogICAgICB2YXIgdmFsdWUgPSBjb25maWdbaXRlbVsiX2NvbmZpZ0tleSJdXTsKICAgICAgaWYgKHZhbHVlID09IHVuZGVmaW5lZCkgewogICAgICAgIHZhbHVlID0gIiI7CiAgICAgIH0KICAgICAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogICAgICBuZXdFbnRyeSA9IGl0ZW07CiAgICAgIGRlbGV0ZSBuZXdFbnRyeVsib25jbGljayJdOwogICAgICBuZXdFbnRyeVsiX2VsZW1lbnQiXSAgPSAiSU5QVVQiOwogICAgICBuZXdFbnRyeVsidmFsdWUiXSAgICAgPSB2YWx1ZTsKICAgICAgbmV3RW50cnlbInR5cGUiXSAgICAgID0gInNlYXJjaCI7CiAgICAgIG5ld0VudHJ5WyJkYXRhLW1lbnV0eXBlIl0gPSBpdGVtWyJfbWVudVR5cGUiXTsKICAgICAgbmV3RW50cnlbImRhdGEtbWVudWtleSJdID0gaXRlbVsiX2NvbmZpZ0tleSJdOwogICAgICBlbGVtZW50LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKICAgICAgYnJlYWs7CgogICAgY2FzZSAiY2hlY2tib3giOgogICAgICB2YXIgdmFsdWUgPSBjb25maWdbaXRlbVsiX2NvbmZpZ0tleSJdXTsKICAgICAgaWYgKHZhbHVlID09IHVuZGVmaW5lZCkgewogICAgICAgIHZhbHVlID0gZmFsc2U7CiAgICAgIH0KICAgICAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogICAgICBuZXdFbnRyeSA9IGl0ZW07CiAgICAgIGRlbGV0ZSBuZXdFbnRyeVsib25jbGljayJdOwogICAgICBuZXdFbnRyeVsiX2VsZW1lbnQiXSAgPSAiSU5QVVQiOwogICAgICBuZXdFbnRyeVsidmFsdWUiXSAgICAgPSB2YWx1ZTsKICAgICAgbmV3RW50cnlbInR5cGUiXSAgICAgID0gImNoZWNrYm94IjsKICAgICAgbmV3RW50cnlbImRhdGEtbWVudXR5cGUiXSA9IGl0ZW1bIl9tZW51VHlwZSJdOwogICAgICBuZXdFbnRyeVsiZGF0YS1tZW51a2V5Il0gPSBpdGVtWyJfY29uZmlnS2V5Il07CiAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdFbnRyeSkpOwogICAgICBlbGVtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJJTlBVVCIpWzBdLmNoZWNrZWQgPSB2YWx1ZTsKICAgICAgYnJlYWs7CiAgICAKICAgIGNhc2UgInNlbGVjdCI6CiAgICAgIHZhciB2YWx1ZSA9IGNvbmZpZ1tpdGVtWyJfY29uZmlnS2V5Il1dOwogICAgICB2YXIgbmV3RW50cnkgPSBuZXcgT2JqZWN0KCk7CiAgICAgIG5ld0VudHJ5ID0gaXRlbTsKICAgICAgZGVsZXRlIG5ld0VudHJ5WyJvbmNsaWNrIl0KICAgICAgbmV3RW50cnlbIl9lbGVtZW50Il0gID0gIlNFTEVDVCI7CiAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdFbnRyeSkpOwogICAgICB2YXIgc2VsZWN0RWxlbWVudCA9IGVsZW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlNFTEVDVCIpWzBdOwogICAgICB2YXIgdmFsdWVzID0gaXRlbVsiX29wdGlvblZhbHVlcyJdOwogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZhbHVlcy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBuZXdFbnRyeSA9IG5ldyBPYmplY3Q7CiAgICAgICAgbmV3RW50cnlbIl9lbGVtZW50Il0gID0gIk9QVElPTiI7CiAgICAgICAgbmV3RW50cnlbIl90ZXh0Il0gICAgID0gaXRlbVsiX3RleHQiXSArICI6ICIgKyB2YWx1ZXNbaV07CiAgICAgICAgbmV3RW50cnlbInZhbHVlIl0gICAgID0gdmFsdWVzW2ldOwogICAgICAgIHNlbGVjdEVsZW1lbnQuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdFbnRyeSkpOwogICAgICB9CiAgICAgIHNlbGVjdEVsZW1lbnQudmFsdWUgPSB2YWx1ZTsKICAgICAgYnJlYWs7CiAgICAKICB9CiAgcmV0dXJuIGVsZW1lbnQ7Cn0KCmZ1bmN0aW9uIG9wZW5TdWJNZW51KGl0ZW0pIHsKICB2YXIgZW50cnlzID0gaXRlbVsiX3N1Yk1lbnUiXS5zcGxpdCgiLCIpOwogIHZhciBkaXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgic2V0dGluZ3MiKTsKCiAgdmFyIG5ld0hSID0gbmV3IE9iamVjdCgpOwogIG5ld0hSWyJfZWxlbWVudCJdID0gIkhSIgogIGRpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0hSKSk7CiAgCiAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogIG5ld0VudHJ5WyJfZWxlbWVudCJdICA9ICJJTlBVVCI7CiAgbmV3RW50cnlbInR5cGUiXSA9ICJidXR0b24iOwogIC8vbmV3RW50cnlbImNsYXNzIl0gPSAic2F2ZSI7CiAgbmV3RW50cnlbInZhbHVlIl0gPSAiU2F2ZSI7CiAgbmV3RW50cnlbIm9uY2xpY2siXSA9ICJzYXZlRGF0YTIoJ3NldHRpbmdzJykiCiAgZGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKCiAgaWYgKGl0ZW1bIl9jb25maWdLZXkiXSA9PSAic2V0dGluZ3MiKSB7CiAgICB2YXIgbmV3RW50cnkgPSBuZXcgT2JqZWN0KCk7CiAgICBuZXdFbnRyeVsiX2VsZW1lbnQiXSAgPSAiSU5QVVQiOwogICAgbmV3RW50cnlbInR5cGUiXSA9ICJidXR0b24iOwogICAgLy9uZXdFbnRyeVsiY2xhc3MiXSA9ICJzYXZlIjsKICAgIG5ld0VudHJ5WyJ2YWx1ZSJdID0gIkJhY2t1cCI7CiAgICBuZXdFbnRyeVsib25jbGljayJdID0gInh0ZXZlQmFja3VwKCkiCiAgICBkaXYuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdFbnRyeSkpOwogIH0KCiAgaWYgKGl0ZW1bIl9jb25maWdLZXkiXSA9PSAic2V0dGluZ3MiKSB7CiAgICB2YXIgbmV3RW50cnkgPSBuZXcgT2JqZWN0KCk7CiAgICBuZXdFbnRyeVsiX2VsZW1lbnQiXSAgPSAiSU5QVVQiOwogICAgbmV3RW50cnlbInR5cGUiXSA9ICJidXR0b24iOwogICAgLy9uZXdFbnRyeVsiY2xhc3MiXSA9ICJzYXZlIjsKICAgIG5ld0VudHJ5WyJ2YWx1ZSJdID0gIlJlc3RvcmUiOwogICAgbmV3RW50cnlbIm9uY2xpY2siXSA9ICJ4dGV2ZVJlc3RvcmUodGhpcykiCiAgICBkaXYuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdFbnRyeSkpOwogIH0KCgogIHZhciBuZXdXcmFwcGVyID0gbmV3IE9iamVjdCgpOwogIG5ld1dyYXBwZXJbIl9lbGVtZW50Il0gID0gIkRJViI7CiAgbmV3V3JhcHBlclsiaWQiXSAgICAgICAgPSAiYm94LXdyYXBwZXIiOwogIGRpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld1dyYXBwZXIpKTsKICAKICBkaXYgPSBkaXYubGFzdENoaWxkOwogIAoKICBmb3IgKHZhciBpID0gMDsgaSA8IGVudHJ5cy5sZW5ndGg7IGkrKykgewogICAgdmFyIGl0ZW0gPSBzdWJNZW51W2VudHJ5c1tpXV07CiAgICBpZiAoaXRlbSA9PSB1bmRlZmluZWQpIHsKICAgICAgYnJlYWs7CiAgICB9CiAgICAKICAgIHZhciBjb250YWluZXIgPSBuZXcgT2JqZWN0KCk7CiAgICBjb250YWluZXJbIl9lbGVtZW50Il0gPSAiRElWIjsKICAgIGRpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KGNvbnRhaW5lcikpOwoKICAgIHZhciBkaXZDb250YWluZXIgPSBkaXYubGFzdENoaWxkOwogICAgCiAgICB2YXIgaGVhZGxpbmUgPSBuZXcgT2JqZWN0KCk7CiAgICBoZWFkbGluZVsiX2VsZW1lbnQiXSA9ICJINSI7CiAgICBoZWFkbGluZVsiX3RleHQiXSA9IGl0ZW1bIl9oZWFkbGluZSJdOwogICAgZGl2Q29udGFpbmVyLmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQoaGVhZGxpbmUpKTsKCiAgICBkaXZDb250YWluZXIuYXBwZW5kQ2hpbGQoY3JlYXRlTWVudUl0ZW0oaXRlbSkpCgogICAgc3dpdGNoKGl0ZW0uaGFzT3duUHJvcGVydHkoIl91c2FnZSIpKSB7CiAgICAgIGNhc2UgdHJ1ZTogCiAgICAgICAgdmFyIHVzYWdlSXRlbSA9IG5ldyBPYmplY3QoKTsKICAgICAgICB1c2FnZUl0ZW1bIl9lbGVtZW50Il0gPSAiUFJFIgogICAgICAgIHVzYWdlSXRlbVsiX3RleHQiXSAgICA9IGl0ZW1bIl91c2FnZSJdOwogICAgICAgIGRpdkNvbnRhaW5lci5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KHVzYWdlSXRlbSkpOwogICAgfQoKICAgIHZhciBociA9IG5ldyBPYmplY3QoKTsKICAgIGhyWyJfZWxlbWVudCJdID0gIkhSIjsKICAgIGRpdkNvbnRhaW5lci5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KGhyKSk7CiAgCiAgfQoKICBjYWxjdWxhdGVXcmFwcGVySGVpZ2h0KCk7CiAgcmV0dXJuCn0KCmZ1bmN0aW9uIHNhdmVEYXRhMihlbG0pIHsKICB2YXIgZGl2ICAgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbG0pOwogIHZhciBpbnB1dHMgPSBkaXYuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIklOUFVUIik7CiAgdmFyIHNlbGVjdHMgPSBkaXYuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlNFTEVDVCIpOwogIHZhciB2YWx1ZSwgY29uZmlnS2V5OwogIHZhciBkYXRhID0gbmV3IE9iamVjdCgpOwogIHZhciB2YWx1ZUFyciA9IG5ldyBBcnJheSgpOwogIHZhciBuZXdEYXRhID0gZmFsc2U7CiAgCiAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbnB1dHMubGVuZ3RoOyBpKyspIHsKICAgIGlmIChpbnB1dHNbaV0udHlwZSAhPSAiYnV0dG9uIikgewogICAgICB2YXIgbWVudVR5cGUgPSBpbnB1dHNbaV0uZ2V0QXR0cmlidXRlKCJkYXRhLW1lbnV0eXBlIik7CiAgICAgIAogICAgICAvL2NvbnNvbGUubG9nKG1lbnVUeXBlKTsKICAgICAgc3dpdGNoKG1lbnVUeXBlKSB7CiAgICAgICAgY2FzZSAic2luZ2xlSW5wdXQiOgogICAgICAgICAgdmFsdWUgPSBpbnB1dHNbaV0udmFsdWU7CiAgICAgICAgICBpZiAodmFsdWUgPT0gIiIgfHwgdmFsdWUgPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGRhdGEgPSBuZXcgT2JqZWN0KCk7CiAgICAgICAgICAgIGRhdGFbImRlbGV0ZSJdID0gaW5wdXRzW2ldLm5hbWUKICAgICAgICAgICAgbmV3RGF0YSA9IHRydWU7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBuZXdEYXRhID0gdHJ1ZTsKICAgICAgICAgICAgZGF0YVtpbnB1dHNbaV0ubmFtZV0gPSB2YWx1ZTsKICAgICAgICAgICAgY29uc29sZS5sb2coZGF0YSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJpbnB1dEFycmF5IjogCiAgICAgICAgICB2YWx1ZSA9IGlucHV0c1tpXS52YWx1ZTsKICAgICAgICAgIGlmICh2YWx1ZSAhPSAiIiAmJiB2YWx1ZSAhPSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgbmV3RGF0YSA9IHRydWU7CiAgICAgICAgICAgIHZhbHVlQXJyLnB1c2godmFsdWUpCiAgICAgICAgICAgIGRhdGFbaW5wdXRzW2ldLm5hbWVdID0gdmFsdWVBcnI7CiAgICAgICAgICAgIGNvbmZpZ0tleSA9IGlucHV0c1tpXS5uYW1lOwogICAgICAgICAgfSAKICAgICAgICAgIAogICAgICAgICAgYnJlYWs7CgogICAgICAgIGNhc2UgImNoZWNrYm94IjoKICAgICAgICAgIHZhbHVlID0gaW5wdXRzW2ldLmNoZWNrZWQKICAgICAgICAgIGRhdGFbaW5wdXRzW2ldLm5hbWVdID0gdmFsdWU7CiAgICAgIH0KICAgICAgCiAgICB9CiAgICAKICB9CgoKICAvLyBEZWxldGUgY29uZmlnIGtleQogIGlmICh2YWx1ZUFyci5sZW5ndGggPT0gMCAmJiBuZXdEYXRhID09IGZhbHNlKSB7CiAgICBuZXdEYXRhID0gdHJ1ZTsKICAgIGRhdGEgPSBuZXcgT2JqZWN0KCk7CiAgICBkYXRhWyJkZWxldGUiXSA9IGNvbmZpZ0tleTsKICB9IAoKCiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZWxlY3RzLmxlbmd0aDsgaSsrKSB7CiAgICB2YXIgdmFsdWUgPSBzZWxlY3RzW2ldLm9wdGlvbnNbc2VsZWN0c1tpXS5zZWxlY3RlZEluZGV4XS52YWx1ZTsKICAgIHN3aXRjaChpc05hTih2YWx1ZSkpIHsKICAgICAgY2FzZSBmYWxzZTogdmFsdWUgPSBwYXJzZUludCh2YWx1ZSk7IGJyZWFrOwogICAgfQoKICAgIGRhdGFbc2VsZWN0c1tpXS5uYW1lXSA9IHZhbHVlOwogICAgbmV3RGF0YSA9IHRydWU7CiAgfQoKICAvL2NvbnNvbGUubG9nKGRhdGEsIG5ld0RhdGEpOwoKICBpZiAobmV3RGF0YSA9PSB0cnVlKSB7CiAgICBkYXRhWyJjbWQiXSA9ICJzYXZlQ29uZmlnIjsKICAgIGlmICghZGF0YS5oYXNPd25Qcm9wZXJ0eSgnZmlsdGVyJykpIHsKICAgICAgZGF0YVsiZmlsdGVyIl0gPSBjb25maWdbImZpbHRlciJdCiAgICB9CiAgICB2YXIgc2V0dGluZ3MgPSBuZXcgT2JqZWN0KCk7CiAgICBzZXR0aW5nc1siY21kIl0gPSBkYXRhWyJjbWQiXTsKICAgIHNldHRpbmdzWyJzZXR0aW5ncyJdID0gZGF0YTsKICAgIGNvbnNvbGUubG9nKHNldHRpbmdzKTsKICAgIHhUZVZlKHNldHRpbmdzKTsKICB9Cn0K" - webUI["html/img/BC-QR.jpg"] = "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" - webUI["html/css/base.css"] = "KiB7CiAgLXdlYmtpdC1hcHBlYXJhbmNlOiBub25lOwogIC1tb3otYXBwZWFyYW5jZTogbm9uZTsKICAtbXMtYXBwZWFyYW5jZTogbm9uZTsKICBmb250LWZhbWlseTogIkFyaWFsIiwgc2Fucy1zZXJpZjsKICBsZXR0ZXItc3BhY2luZzogMnB4OyAKfQoKLyoKOjotd2Via2l0LXNjcm9sbGJhciB7IAogICAgZGlzcGxheTogbm9uZTsgCn0KKi8KCjo6LXdlYmtpdC1zY3JvbGxiYXIgewogIHdpZHRoOiAxMnB4OwogIGhlaWdodDogMTJweDsKfQoKIAo6Oi13ZWJraXQtc2Nyb2xsYmFyLXRyYWNrIHsKICAtd2Via2l0LWJveC1zaGFkb3c6IGluc2V0IDAgMCA2cHggcmdiYSgwLDAsMCwwLjMpOyAKICBib3JkZXItcmFkaXVzOiA1cHg7CiAgICAKfQogCjo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWIgewogIGJvcmRlci1yYWRpdXM6IDVweDsKICAtd2Via2l0LWJveC1zaGFkb3c6IGluc2V0IDAgMCA2cHggcmdiYSgwLCAwLCAwLDAuNik7IAogIGJhY2tncm91bmQtY29sb3I6ICM0NDQ7Cn0KCjo6LXdlYmtpdC1zY3JvbGxiYXItdGh1bWI6aG92ZXIgewogIGJhY2tncm91bmQ6ICMzMzM7IAp9Cgo6Oi13ZWJraXQtc2Nyb2xsYmFyLWNvcm5lciB7IAogIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50OyAKfQoKYSB7CiAgY29sb3I6ICMwMEU2RkY7Cn0KCmh0bWwsIGJvZHkgewogIGNvbG9yOiAjZmZmOwogIG1hcmdpbjogMHB4IGF1dG87CiAgaGVpZ2h0OiAxMDAlOwogIGZvbnQtc2l6ZTogMTRweDsKfQoKaDIgewogIGZvbnQtc2l6ZTogMjRweDsKICBsZXR0ZXItc3BhY2luZzogMnB4Owp9CgpoMyB7CiAgZm9udC1zaXplOiAyMnB4OwogIGxldHRlci1zcGFjaW5nOiAxcHg7Cn0KCmg0IHsKICBmb250LXNpemU6IDIwcHg7CiAgbGV0dGVyLXNwYWNpbmc6IDFweDsKICBsaW5lLWhlaWdodDogMS41ZW07Cgp9CgpoNSB7CiAgZm9udC1zaXplOiAxNnB4OwogIGxldHRlci1zcGFjaW5nOiAxcHg7CiAgbGluZS1oZWlnaHQ6IDEuMmVtOwogIG1hcmdpbjogMjVweCAwcHggMTBweCAwcHg7Cn0KCmhyIHsKICBib3JkZXI6IDA7CiAgaGVpZ2h0OiAxcHg7CiAgYmFja2dyb3VuZDogIzMzMzsKICBtYXJnaW46IDEwcHggMHB4Owp9CgpwIHsKICBtYXJnaW46IDJweDsKICBwYWRkaW5nOiAycHggNXB4Owp9CgpwcmUgewogIG1hcmdpbjogMHB4IDBweCA1cHggMHB4OwogIGZvbnQtc2l6ZTogMTJweDsKICBjb2xvcjogI2RkZDsKICBsZXR0ZXItc3BhY2luZzogMXB4OwogIHdoaXRlLXNwYWNlOiBwcmUtd3JhcDsKICBmb250LWZhbWlseTogbW9ub3NwYWNlOyAKICBmb250LXNpemU6IDEycHg7IAogIGZvbnQtc3R5bGU6IG5vcm1hbDsgCiAgZm9udC12YXJpYW50OiBub3JtYWw7IAogIGxpbmUtaGVpZ2h0OiAxLjZlbTsgCn0KCmxhYmVsIHsKICBtYXJnaW4tYm90dG9tOiAyMHB4OwogIGRpc3BsYXk6IGJsb2NrOwp9CgpsaSB7CiAgbGlzdC1zdHlsZS10eXBlOiBub25lOwogIGJhY2tncm91bmQtY29sb3I6ICMxMTE7CiAgcGFkZGluZzogMTBweCAyMHB4OwogIGN1cnNvcjogcG9pbnRlcjsKICBib3JkZXItbGVmdDogc29saWQgMnB4ICMxMTE7CiAgdHJhbnNpdGlvbjogYWxsIDAuMzsKfQoKbGk6aG92ZXIgewogIGJvcmRlci1jb2xvcjogIzAwRTZGRgp9CgpzZWxlY3QgewogIGN1cnNvcjogcG9pbnRlcjsKICB3aWR0aDogY2FsYygxMDAlICsgMnB4KTsKICBib3JkZXI6IHNvbGlkIDBweCAjMDBFNkZGOwogIGJvcmRlci1yYWRpdXM6IDBweDsKICBvdXRsaW5lOiBub25lOwogIGNvbG9yOiAjZmZmOwogIHBhZGRpbmc6IDlweCAxMHB4OwogIGRpc3BsYXk6YmxvY2s7CiAgYmFja2dyb3VuZC1jb2xvcjogIzMzMzsKICBmb250LXNpemU6IDE0cHg7CiAgbWFyZ2luOiA1cHggMHB4IDVweCAwcHg7Cn0KCnNlbGVjdDpmb2N1cyB7CiAgb3V0bGluZTogbm9uZTsKfQoKaW5wdXQgewogIC13ZWJraXQtYXBwZWFyYW5jZTogbm9uZTsKICBtYXJnaW46IDVweCAwcHg7CiAgcGFkZGluZzogMi41cHggMTBweDsKICBvdXRsaW5lOiBub25lOwogIGZvbnQtc2l6ZTogMTRweDsKfQoKaW5wdXRbdHlwZT1idXR0b25dLCBpbnB1dFt0eXBlPXN1Ym1pdF0gewogIGN1cnNvcjogcG9pbnRlcjsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwOwogIG1hcmdpbjogMTBweCAxMHB4OwogIHBhZGRpbmc6IDEwcHggMjVweDsKICBib3JkZXI6IHNvbGlkIDBweDsKICBib3JkZXItY29sb3I6ICMwMDA7CiAgYm9yZGVyLXJhZGl1czogM3B4OwogIG91dGxpbmU6IG5vbmU7CiAgY29sb3I6ICNmZmY7Cn0KCmlucHV0W3R5cGU9YnV0dG9uXTpmb2N1cyB7IAogICBvdXRsaW5lOiBub25lOwp9CgppbnB1dFt0eXBlPWJ1dHRvbl06aG92ZXIgewogIGJhY2tncm91bmQtY29sb3I6ICMwMEU2RkY7CiAgY29sb3I6ICMwMDA7Cn0KCmlucHV0W3R5cGU9YnV0dG9uXTpob3Zlci5kZWxldGUgIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiByZWQ7CiAgY29sb3I6ICNmZmY7Cn0KCmlucHV0W3R5cGU9dGV4dF0sIGlucHV0W3R5cGU9c2VhcmNoXSwgaW5wdXRbdHlwZT1wYXNzd29yZF0gewogIGNvbG9yOiAjZmZmOwogIHdpZHRoOiAtd2Via2l0LWNhbGMoMTAwJSAtIDBweCk7CiAgd2lkdGg6IC1tb3otY2FsYygxMDAlIC0gMHB4KTsKICB3aWR0aDogY2FsYygxMDAlIC0gMHB4KTsKICBvdXRsaW5lOiBub25lOwogIGJvcmRlcjogc29saWQgMXB4IHRyYW5zcGFyZW50OwogIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50OwogIGJvcmRlci1ib3R0b20tY29sb3I6ICM1NTU7CiAgYm9yZGVyLXJhZGl1czogMHB4OwogIHBhZGRpbmc6IDhweCAxMHB4Owp9CgppbnB1dFt0eXBlPSJjaGVja2JveCJdIHsKICBib3JkZXI6IHNvbGlkIDFweCAjMDBFNkZGOwogIGJhY2tncm91bmQtY29sb3I6ICMzMzM7CiAgaGVpZ2h0OiAyNXB4OwogIHdpZHRoOiAyNXB4OwogIGN1cnNvcjogcG9pbnRlcjsKICAvKgogIC13ZWJraXQtYXBwZWFyYW5jZTogY2hlY2tib3g7CiAgKi8KfQoKaW5wdXRbdHlwZT0iY2hlY2tib3giXTpjaGVja2VkIHsKICBjb2xvcjogI2ZmZjsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDBFNkZGOwogIC8qZGlzcGxheTogaW5saW5lLWJsb2NrOyovCn0KCmlucHV0W3R5cGU9ImNoZWNrYm94Il06YmVmb3JlIHsKICBwb3NpdGlvbjogaW5pdGlhbDsKICBsZWZ0OiAwcHg7CiAgbWFyZ2luLWxlZnQ6IC00cHg7CiAgY29udGVudDogIiAiOwp9CgppbnB1dFt0eXBlPSJjaGVja2JveCJdOmNoZWNrZWQ6YmVmb3JlIHsKICBwb3NpdGlvbjogaW5pdGlhbDsKICBsZWZ0OiAwcHg7CiAgbWFyZ2luLWxlZnQ6IC0zcHg7CiAgY29udGVudDogIuKckyI7CiAgY29sb3I6ICMwMDA7Cn0KCgppbnB1dFt0eXBlPWJ1dHRvbl0uY2FuY2VsIHsKICAKICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDsKICBib3JkZXItY29sb3I6IHJlZDsKfQoKaW5wdXRbdHlwZT1idXR0b25dLnNhdmV7CiAgYmFja2dyb3VuZC1jb2xvcjogIzExMTsKICBmbG9hdDogcmlnaHQ7Cn0KCgppbnB1dFt0eXBlPWJ1dHRvbl0uYmxhY2ssIGlucHV0W3R5cGU9c3VibWl0XS5ibGFja3sKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwOwogIGJvcmRlci1jb2xvcjogIzAwMDsKfQoKaW5wdXRbdHlwZT1idXR0b25dLmNlbnRlcnsKICBtYXJnaW4tcmlnaHQ6IGF1dG87CiAgbWFyZ2luLWxlZnQ6IGF1dG87CiAgYmFja2dyb3VuZC1jb2xvcjogIzAwMDsKICBib3JkZXItY29sb3I6ICMwMDA7Cn0KCi5wb2ludGVyIHsKICBjdXJzb3I6IHBvaW50ZXI7Cn0KCi5wb2ludGVyOmhvdmVyIHsKICBjb2xvcjogIzAwRTZGRjsKICBjdXJzb3I6IHBvaW50ZXI7Cn0KCi5zb3J0VGhpcyB7CiAgY29sb3I6ICMwMEU2RkY7Cn0KCi53NDBweCB7CiAgbWF4LXdpZHRoOiA0MHB4Owp9CgoudzUwcHggewogIG1heC13aWR0aDogNTBweDsKfQoKLnc4MHB4IHsKICBtYXgtd2lkdGg6IDgwcHg7Cn0KCi53MTUwcHggewogIG1heC13aWR0aDogMTUwcHg7Cn0KCi53MjAwcHggewogIG1heC13aWR0aDogMjAwcHg7CiAgbWluLXdpZHRoOiAxMDBweDsKICB3aWR0aDogMjAwcHg7CiAgb3ZlcmZsb3cteDogaGlkZGVuOwogIHdoaXRlLXNwYWNlOiBub3dyYXA7CiAgb3ZlcmZsb3c6IGhpZGRlbjsKICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpczsKfQoKLnczMDBweCB7CiAgbWF4LXdpZHRoOiAzMDBweDsKfQoKLncyMjBweCB7CiAgbWF4LXdpZHRoOiAyMjBweDsKICBjdXJzb3I6IGFsaWFzOwp9CgouZm9vdGVyIHsKICBmb250LXNpemU6IDEwcHg7Cn0KCi5jZW50ZXIgewogIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKLnNjcmVlbkxvZ0hpZGRlbiB7CiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoMHB4LCAtMTEwcHgpOwp9CgouYm9yZGVyU3BhY2UgewogIG1hcmdpbi1ib3R0b206IDMwcHg7Cn0KCi5ibG9jayB7Cgp9Cgoubm9uZSB7CiAgZGlzcGxheTogbm9uZTsKfQoKCi5ub3RWaXNpYmxlIHsKICBoZWlnaHQ6IDBweDsKICBkaXNwbGF5OiBub25lOwogIG9wYWNpdHk6IDA7CiAgYm9yZGVyLWJvdHRvbTogIzAwMCBzb2xpZCAwcHg7CiAgCn0KCi52aXNpYmxlIHsKICBvcGFjaXR5OiAxOwogIGRpc3BsYXk6IGJsb2NrOwogIGJvcmRlci1ib3R0b206ICM0NDQgc29saWQgMXB4OyAKICBwYWRkaW5nOiAxMHB4Owp9CgouZmxvYXRSaWdodCB7CiAgZmxvYXQ6IHJpZ2h0Owp9CgouZmxvYXRMZWZ0IHsKICBmbG9hdDogbGVmdDsKfQoKLm1lbnUtYWN0aXZlIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDBFNkZGOwp9CgoubWVudS1ub3RBY3RpdmUgewogIAp9CgojYnJhbmNoIHsKICBkaXNwbGF5OiB0YWJsZTsKICBtYXJnaW46IGF1dG87CiAgY29sb3I6IHJlZDsKfQoKI2ludGVyYWN0aW9uIHsKICBtYXJnaW4tYm90dG9tOiAxMDBweDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgYm9yZGVyLWJvdHRvbTogc29saWQgMHB4ICM3Nzc7Cn0KCgouaGFsZiB7CiAgZGlzcGxheTogYmxvY2s7CiAgd2lkdGg6IDQ1JTsKfQoKLm1lbnUgewogIGJvcmRlcjogc29saWQgMXB4ICMwMEU2RkY7Cn0KCi5pbmZvTXNnIHsKICBjb2xvcjogI2FhYTsKfQoKLmVycm9yTXNnIHsKICBjb2xvcjogcmVkOwp9Cgoud2FybmluZ01zZyB7CiAgY29sb3I6IHllbGxvdzsKfQoKLmRlYnVnTXNnIHsKICBjb2xvcjogbWFnZW50YTsKfQoKLk5ld3MsIC5Nb3ZpZSwgLlNlcmllcywgLlNwb3J0cywgLktpZHMgewogIGJvcmRlci1sZWZ0OiBzb2xpZCAycHgKfQoKLk5ld3MgewogIGJvcmRlci1jb2xvcjogdG9tYXRvCn0KCi5Nb3ZpZSB7CiAgYm9yZGVyLWNvbG9yOiByb3lhbGJsdWU7Cn0KCi5TZXJpZXMgewogIGJvcmRlci1jb2xvcjogZ29sZDsKfQoKLlNwb3J0cyB7CiAgYm9yZGVyLWNvbG9yOiB5ZWxsb3dncmVlbjsKfQoKLktpZHMgewogIGJvcmRlci1jb2xvcjogbWVkaXVtcHVycGxlOwp9CgovKiBMb2FkaW5nICovCiNsb2FkaW5nIHsKICBsZWZ0OiAwcHg7CiAgdG9wOiAwcHg7CiAgei1pbmRleDogMTAwMDA7CiAgcG9zaXRpb246IGFic29sdXRlOwogIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMCwwLDAsIDAuOCk7CiAgbWFyZ2luOiBhdXRvOwogIHdpZHRoOiAxMDAlOwogIGhlaWdodDogMTAwJTsKfQoKCi5sb2FkZXIgewogIGJvcmRlcjogNXB4IHNvbGlkIHRyYW5zcGFyZW50OwogIGJvcmRlci1yYWRpdXM6IDUwJTsKICBib3JkZXItdG9wOiA1cHggc29saWQgIzAwRTZGRjsKICBib3JkZXItYm90dG9tOiA1cHggc29saWQgIzAwRTZGRjsKICB3aWR0aDogNTBweDsKICBoZWlnaHQ6IDUwcHg7CiAgLXdlYmtpdC1hbmltYXRpb246IHNwaW4gMS4ycyBsaW5lYXIgaW5maW5pdGU7CiAgYW5pbWF0aW9uOiBzcGluIDEuMnMgbGluZWFyIGluZmluaXRlOwoKICBwb3NpdGlvbjogZml4ZWQ7CiAgbWFyZ2luOiBhdXRvOwoKICB0b3A6IDA7CiAgcmlnaHQ6IDA7CiAgYm90dG9tOiAwOwogIGxlZnQ6IDA7CiAgCn0KCkAtd2Via2l0LWtleWZyYW1lcyBzcGluIHsKICAwJSB7IC13ZWJraXQtdHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7IH0KICAxMDAlIHsgLXdlYmtpdC10cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpOyB9Cn0KCkBrZXlmcmFtZXMgc3BpbiB7CiAgMCUgeyB0cmFuc2Zvcm06IHJvdGF0ZSgwZGVnKTsgfQogIDEwMCUgeyB0cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpOyB9Cn0K" - webUI["html/img/settings.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0wOC0xMFQxODowODo4OTwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Ckxt87EAAAS7SURBVGgFzZpdiFVVGIbn5N+IMgVhaRLqWI7mQIJoIVRgOhQZNDAhWcbcVuPV3BRE6I14440iQQSaN0p6kz8zI0k5inUhZSSaYOVYODMo5eiMOOPf+LzH2cPMPmvttdbe53jOBy9rr2+938/ae51vr733qaoqgQwPD68B/wDJfXAP3AE94JMShCy+SxJ9CvSDJFlU7MiPFdsh/hrBdIffBsd48HApJjLPI4tnPThBlFJMZI5HBuWZCIt9AmgEzeAJR6JzHeMadnKI8wbYCz4Fkz18JlNwMgf8BCL5j4O3bVaMdUfEhPZqgv1U7HbEbDvoT7HZOPUYNwAlHheV09a4A3RTgMqtj9QY7JdgeM5i3I4+fDIYrQeq/UnyNYOTlBDtS+BwEjk2doz+KyO2OY5bwVCME+/qylTHT4C1D3k+uB33Yul3ov/eMuajlu1RH+II5wtT4hNNSnQ6U/kzbRkfq351bCfF8apAm7kmvq38njWRK0S305SHcSK5XO4U5O9MBmXWbSe3E6YccialdKzH2TTnQEF10XgZ5DdivsxEhkyxjVdERAwu03xmMiqD7hYx19km4cyHq6KyeHKkWpSz+ciVrHVpRYZk/wLHp0H2bULkNKzt4Eq86TKxLq3IECf6nXwV9QPbAfjHQSfoD7SN6L63gYhvbrkiTwKf/dPYpbdPVxKMnigdg0VAG8FQye8AzBl6aIk2A+wPiNoHd63LNZx3wbUAvz/CfTzJb/43AmkGpLfAi0DPE/NALQgtve+xFPdi5xRiNkHa5ySOJ/TR7RrBJdqL4AAxL+p+8ToYAFklNCnF3pM1KPba2L6v8vons5oPsko9ZyZoa0PsOoKezxoY+y5N5DYHWSvDTXzUMJH7IUkRW0tbyyV0CcfDDKmqDMe1KfqnQyehGNgo9q8p4hWYFGsiBY4fsSK/BRkkaPgj5PhMy720BnVFesfnlKo3Das0bw8XYJf196GEuzWRLSDoRypLg2w06FyqTS6Cx7iK1eeqGqrnugmuBgvB8+A5UAuqQYiU+oZ4h2T+BV3gAlDp/pai0U1rFpVGMAv8AHzFd4vShMOQLcoB+DNB/sSbM3ZoMV4BQsW0adSJSbNp1Hu1mY40/YZxpPdJaUSfFzrBMXAjjQNsdvll6cHCWVvKJIphdhcny11pqmolCk5aIDif0BKdZBucgPlO8kh/r8O4HtwClSCbk86HtQqQuUrvKVCf5OARjt0lll4H/WKKmbS0tmJQKZNQ7nq9+w0n2LhTN04E8jKMPpZ1hcli8tGTZYEYJwJrZQGzchTGz3a2ifwdkHc73LYAfpx6DcWXQK1LeiDsdpFGx7UOwUGQJKpmGyIjjvWh50iSQWzsZ/ofgvx+jnYp+B/YpJcB7QXDBKPJ4JDF6+/oCwoBuhoL36R+Jp4RJH16u2IgaxJpHhMehsBY3wTjV2YbOuuumLHrwCW6msbSj74O/DHGgV4Ohl8Jw1nSMmsB+tL6Wnw83odzBrhEr2GtgvFE8A74ADxtJZZygMC25cjQqBwqdg62qpUlziUP45Cq6OGuqqoUE/FJ8i+v7MpJYvEsHl1A5gNty2vLmaN3bBLdAvqB3svqXxLRvyEuc9zs7SiA+ACpw05pJx8SoAAAAABJRU5ErkJggg==" - webUI["html/js/classes_ts.js"] = "dmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkgewogICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikgewogICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwKICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fAogICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTsKICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTsKICAgIH07CiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHsKICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpOwogICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfQogICAgICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTsKICAgIH07Cn0pKCk7CnZhciBNYWluTWVudSA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIE1haW5NZW51KCkgewogICAgICAgIHRoaXMuRG9jdW1lbnRJRCA9ICJtYWluLW1lbnUiOwogICAgICAgIHRoaXMuSFRNTFRhZyA9ICJMSSI7CiAgICB9CiAgICBNYWluTWVudS5wcm90b3R5cGUuY3JlYXRlID0gZnVuY3Rpb24gKCkgewogICAgICAgIGNvbnNvbGUubG9nKHRoaXMuRG9jdW1lbnRJRCk7CiAgICB9OwogICAgcmV0dXJuIE1haW5NZW51Owp9KCkpOwp2YXIgTWFpbk1lbnVJdGVtID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKF9zdXBlcikgewogICAgX19leHRlbmRzKE1haW5NZW51SXRlbSwgX3N1cGVyKTsKICAgIGZ1bmN0aW9uIE1haW5NZW51SXRlbSgpIHsKICAgICAgICByZXR1cm4gX3N1cGVyICE9PSBudWxsICYmIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIHx8IHRoaXM7CiAgICB9CiAgICBNYWluTWVudUl0ZW0ucHJvdG90eXBlLmNyZWF0ZTIgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRoaXMuSFRNTFRhZyk7CiAgICAgICAgZWxlbWVudC5pbm5lclRleHQgPSB0aGlzLlZhbHVlOwogICAgICAgIGNvbnNvbGUubG9nKGVsZW1lbnQpOwogICAgfTsKICAgIHJldHVybiBNYWluTWVudUl0ZW07Cn0oTWFpbk1lbnUpKTsKZnVuY3Rpb24gcGFnZVJlYWR5KCkgewogICAgdmFyIGl0ZW0gPSBuZXcgTWFpbk1lbnVJdGVtKCk7CiAgICBpdGVtLlZhbHVlID0gIlRlc3QiOwogICAgaXRlbS5jcmVhdGUyKCk7Cn0K" - webUI["html/js/data.js"] = "ZnVuY3Rpb24gc2hvd0NvbmZpZyhvYmopIHsKICBjb25maWcgPSBvYmo7CiAgLy9zZXRNZW51SXRlbSgpOwogIGNyZWF0ZU1lbnUoKTsKICAvL2RvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJwYWdlIikuY2xhc3NOYW1lID0gIiI7Cn0KCnNob3dNeVN0cmVhbXMKCmZ1bmN0aW9uIHNob3dNeVN0cmVhbXMoYWxsU3RyZWFtc09iaikgewoKICB2YXIgc3RyZWFtVHlwZUtleXMgPSBnZXRPYmpLZXlzKGFsbFN0cmVhbXNPYmopCgogIGZvciAodmFyIHMgPSAwOyBzIDwgc3RyZWFtVHlwZUtleXMubGVuZ3RoOyBzKyspIHsKICAgIHZhciBzdHJlYW1UeXBlID0gc3RyZWFtVHlwZUtleXNbc107CiAgICB2YXIgb2JqID0gbmV3IE9iamVjdCgpOwogICAgb2JqID0gYWxsU3RyZWFtc09ialtzdHJlYW1UeXBlXTsKICAgIHN3aXRjaChzdHJlYW1UeXBlKSB7CiAgICAgIGNhc2UgImFjdGl2ZVN0cmVhbXMiOiBhY3RpdmVTdHJlYW1zICAgICA9IG9iajsgYnJlYWs7CiAgICB9CgogICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoc3RyZWFtVHlwZSkuaW5uZXJIVE1MID0gIiI7CgogICAgdmFyIHN0cmVhbXNPYmogICAgPSBuZXcgT2JqZWN0KCk7CiAgICB2YXIgc3RyZWFtc05hbWVzICA9IG5ldyBBcnJheSgpOwogICAgCiAgICB2YXIga2V5cyA9IGdldE9iaktleXMob2JqKQogICAgCiAgICAvLyBDcmVhdGUgT2JqZWN0IChzdHJlYW1zT2JqKSBmb3IgdGhlIHN0cmVhbXMgYW5kIHNvcnQgYnkgbmFtZSAoc3RyZWFtc05hbWVzKQogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBuYW1lICAgID0gb2JqW2tleXNbaV1dWyJuYW1lIl07CiAgICAgIHZhciB0bXAgPSBuZXcgT2JqZWN0KCk7CiAgICAgIHZhciBzdHJlYW1LZXkgPSBnZXRPYmpLZXlzKG9ialtrZXlzW2ldXSk7CgogICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHN0cmVhbUtleS5sZW5ndGg7IGorKykgewogICAgICAgIHRtcFtzdHJlYW1LZXlbal1dID0gb2JqW2tleXNbaV1dW3N0cmVhbUtleVtqXV07ICAgICAgCiAgICAgIH0KCiAgICAgIHN0cmVhbXNPYmpbbmFtZV0gPSB0bXA7CiAgICAgIHN0cmVhbXNOYW1lcy5wdXNoKG5hbWUpCiAgICB9CgogICAgc3RyZWFtc05hbWVzLnNvcnQoKTsKICAgIAogICAgLy8gQ3JlYXRlIFRhYmxlIGZvciBhY3RpdmVTdHJlYW1zCiAgICB2YXIgdGFibGUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChzdHJlYW1UeXBlKTsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0cmVhbXNOYW1lcy5sZW5ndGg7IGkrKykgewogICAgICB2YXIgbmV3RW50cnkgPSBuZXcgT2JqZWN0KCk7CiAgICAgIG5ld0VudHJ5WyJfZWxlbWVudCJdID0gIlRSIjsKICAgICAgdGFibGUuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdFbnRyeSkpOwogICAgICB2YXIgbGluZSA9IHRhYmxlLmxhc3RDaGlsZDsKCiAgICAgIHZhciB0bXAgPSBzdHJlYW1zT2JqW3N0cmVhbXNOYW1lc1tpXV0KICAgICAgdmFyIGtleXMgPSBnZXRPYmpLZXlzKHRtcCkKCiAgICAgIHZhciBuZXdLZXkgPSBuZXcgT2JqZWN0KCkKICAgICAgbmV3S2V5WyJfZWxlbWVudCJdICA9ICJURCI7CiAgICAgIC8vbmV3S2V5WyJfdGV4dCJdICAgICA9IHN0cmVhbXNOYW1lc1tpXTsKICAgICAgc3dpdGNoKHN0cmVhbVR5cGUpIHsKICAgICAgICBjYXNlICJhY3RpdmVTdHJlYW1zIjogbmV3S2V5WyJfdGV4dCJdICAgICA9ICJDaGFubmVsICgrKToiOyBicmVhazsKICAgICAgICBjYXNlICJpbmFjdGl2ZVN0cmVhbXMiOiBuZXdLZXlbIl90ZXh0Il0gICA9ICJDaGFubmVsICgtKToiOyBicmVhazsKICAgICAgfQogICAgICAKICAgICAgbmV3S2V5WyJjbGFzcyJdICAgICA9ICJ0ZEtleSI7CiAgICAgIGNvbnNvbGUubG9nKCk7CgoKICAgICAgdmFyIG5ld1ZhbCA9IG5ldyBPYmplY3QoKQogICAgICBuZXdWYWxbIl9lbGVtZW50Il0gID0gIlREIjsKICAgICAgbmV3VmFsWyJfdGV4dCJdICAgICA9IHN0cmVhbXNOYW1lc1tpXTsKICAgICAgbmV3VmFsWyJjbGFzcyJdICAgICA9ICJ0ZFZhbCI7CiAgICAgIC8vbmV3VmFsWyJfdGV4dCJdICAgICA9IHZhbHVlOwogICAgICAKICAgICAgbGluZS5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0tleSkpOwogICAgICBsaW5lLmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3VmFsKSk7CiAgICAgIAogICAgfQoKICB9CgogIHJldHVybgp9CgpmdW5jdGlvbiBzaG93QWN0aXZlU3RyZWFtcyhvYmopIHsKICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiYWN0aXZlU3RyZWFtcyIpLmlubmVySFRNTCA9ICIiOwogIGFjdGl2ZVN0cmVhbXMgICAgID0gb2JqOwogIHZhciBzdHJlYW1zT2JqICAgID0gbmV3IE9iamVjdCgpOwogIHZhciBzdHJlYW1zTmFtZXMgID0gbmV3IEFycmF5KCk7CiAgCiAgdmFyIGtleXMgPSBnZXRPYmpLZXlzKG9iaikKICAKICAvLyBDcmVhdGUgT2JqZWN0IChzdHJlYW1zT2JqKSBmb3IgdGhlIHN0cmVhbXMgYW5kIHNvcnQgYnkgbmFtZSAoc3RyZWFtc05hbWVzKQogIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewogICAgdmFyIG5hbWUgICAgPSBvYmpba2V5c1tpXV1bIm5hbWUiXTsKICAgIHZhciB0bXAgPSBuZXcgT2JqZWN0KCk7CiAgICB2YXIgc3RyZWFtS2V5ID0gZ2V0T2JqS2V5cyhvYmpba2V5c1tpXV0pOwoKICAgIGZvciAodmFyIGogPSAwOyBqIDwgc3RyZWFtS2V5Lmxlbmd0aDsgaisrKSB7CiAgICAgIHRtcFtzdHJlYW1LZXlbal1dID0gb2JqW2tleXNbaV1dW3N0cmVhbUtleVtqXV07ICAgICAgCiAgICB9CgogICAgc3RyZWFtc09ialtuYW1lXSA9IHRtcDsKICAgIHN0cmVhbXNOYW1lcy5wdXNoKG5hbWUpCiAgfQoKICBzdHJlYW1zTmFtZXMuc29ydCgpOwogIAogIC8vIENyZWF0ZSBUYWJsZSBmb3IgYWN0aXZlU3RyZWFtcwogIHZhciB0YWJsZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJhY3RpdmVTdHJlYW1zIik7CgogIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyZWFtc05hbWVzLmxlbmd0aDsgaSsrKSB7CiAgICB2YXIgbmV3RW50cnkgPSBuZXcgT2JqZWN0KCk7CiAgICBuZXdFbnRyeVsiX2VsZW1lbnQiXSA9ICJUUiI7CiAgICB0YWJsZS5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0VudHJ5KSk7CiAgICB2YXIgbGluZSA9IHRhYmxlLmxhc3RDaGlsZDsKCiAgICB2YXIgdG1wID0gc3RyZWFtc09ialtzdHJlYW1zTmFtZXNbaV1dCiAgICB2YXIga2V5cyA9IGdldE9iaktleXModG1wKQoKICAgIHZhciBuZXdLZXkgPSBuZXcgT2JqZWN0KCkKICAgIG5ld0tleVsiX2VsZW1lbnQiXSAgPSAiVEQiOwogICAgLy9uZXdLZXlbIl90ZXh0Il0gICAgID0gc3RyZWFtc05hbWVzW2ldOwogICAgbmV3S2V5WyJfdGV4dCJdICAgICA9ICJDaGFubmVsOiI7CiAgICBuZXdLZXlbImNsYXNzIl0gICAgID0gInRkS2V5IjsKICAgIGNvbnNvbGUubG9nKCk7CgoKICAgIHZhciBuZXdWYWwgPSBuZXcgT2JqZWN0KCkKICAgIG5ld1ZhbFsiX2VsZW1lbnQiXSAgPSAiVEQiOwogICAgbmV3VmFsWyJfdGV4dCJdICAgICA9IHN0cmVhbXNOYW1lc1tpXTsKICAgIG5ld1ZhbFsiY2xhc3MiXSAgICAgPSAidGRWYWwiOwogICAgLy9uZXdWYWxbIl90ZXh0Il0gICAgID0gdmFsdWU7CiAgICAKICAgIGxpbmUuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdLZXkpKTsKICAgIGxpbmUuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdWYWwpKTsKICAgIAogIH0KCn0KCmZ1bmN0aW9uIHBhcnNlTG9ncyhvYmopIHsKICBsb2cgPSBvYmoKICB2YXIga2V5cyA9IGdldE9iaktleXMob2JqKQoKICB2YXIgbXNnVHlwZTsKICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgIHN3aXRjaChrZXlzW2ldKSB7CiAgICAgIGNhc2UgIndhcm5pbmdzIjogIG1zZ1R5cGUgPSAid2FybmluZ01zZyI7IGJyZWFrOwogICAgICBjYXNlICJlcnJvcnMiOiAgICBtc2dUeXBlID0gImVycm9yTXNnIjsgYnJlYWs7CiAgICB9CgogICAgc3dpdGNoKG9ialtrZXlzW2ldXSkgewogICAgICBjYXNlIDA6IG1zZ1R5cGUgPSAidGRWYWwiOyBicmVhazsKICAgICAgZGVmYXVsdDogYnJlYWs7CiAgICB9CgogICAgaWYoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoa2V5c1tpXSkpewogICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChrZXlzW2ldKS5jbGFzc05hbWUgPSBtc2dUeXBlOwogICAgfQogICAgCiAgICAKICB9CiAgcmV0dXJuCn0KCgpmdW5jdGlvbiBjYW5jZWxEYXRhKGVsZW1lbnQpIHsKICBjcmVhdGVNZW51KCk7Cn0KCmZ1bmN0aW9uIHNhdmVEYXRhKGVsZW1lbnQpIHsKICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICB2YXIgZGl2ID0gZWxlbWVudC5wYXJlbnROb2RlLnBhcmVudE5vZGU7CiAgdmFyIGlucHV0cyA9IGRpdi5nZXRFbGVtZW50c0J5VGFnTmFtZSgiSU5QVVQiKTsKICAKICB2YXIgY29uZmlnS2V5ID0gZGl2LmdldEF0dHJpYnV0ZSgiZGF0YS1jb25maWdrZXkiKTsKICB2YXIgbWVudVR5cGUgPSBkaXYuZ2V0QXR0cmlidXRlKCJkYXRhLW1lbnV0eXBlIik7CiAgdmFyIHZhbHVlOwogIHZhciB2YWx1ZUFyciA9IG5ldyBBcnJheSgpOwogIAogIGZvciAodmFyIGkgPSAwOyBpIDwgaW5wdXRzLmxlbmd0aDsgaSsrKSB7CiAgICBpZiAoaW5wdXRzW2ldLnR5cGUgPT0gInRleHQiICYmIGlucHV0c1tpXS52YWx1ZSAhPSB1bmRlZmluZWQgJiYgaW5wdXRzW2ldLnZhbHVlICE9ICIiICkgewogICAgICBjb25zb2xlLmxvZyhpbnB1dHNbaV0udmFsdWUsIG1lbnVUeXBlKQogICAgICBzd2l0Y2gobWVudVR5cGUpIHsKICAgICAgICBjYXNlICJpbnB1dEFycmF5IjogdmFsdWVBcnIucHVzaChpbnB1dHNbaV0udmFsdWUpOyBicmVhazsKICAgICAgICBjYXNlICJzaW5nbGVJbnB1dCI6IHZhbHVlID0gaW5wdXRzW2ldLnZhbHVlOyBicmVhazsKICAgICAgfQogICAgfQogIH0KCiAgc3dpdGNoKG1lbnVUeXBlKSB7CiAgICBjYXNlICJpbnB1dEFycmF5IjogIGRhdGFbY29uZmlnS2V5XSA9IHZhbHVlQXJyOyBicmVhazsKICAgIGNhc2UgInNpbmdsZUlucHV0IjogIAogICAgICBpZiAoaXNOYU4odmFsdWUpID09IGZhbHNlKSB7CiAgICAgICAgdmFsdWUgPSBwYXJzZUludCh2YWx1ZSk7CiAgICAgICAgZGF0YVtjb25maWdLZXldID0gdmFsdWU7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KCiAgICAgIGlmICh2YWx1ZSA9PSB1bmRlZmluZWQpIHsKICAgICAgICBkYXRhWyJkZWxldGUiXSA9IGNvbmZpZ0tleTsgCiAgICAgIH0gZWxzZSB7CiAgICAgICAgZGF0YVtjb25maWdLZXldID0gdmFsdWUKICAgICAgfQoKICAgICAgYnJlYWs7CiAgfQoKICBkYXRhWyJjbWQiXSA9ICJzYXZlQ29uZmlnIjsKICBjb25zb2xlLmxvZyhkYXRhKTsKICB4VGVWZShkYXRhKQp9CgpmdW5jdGlvbiB4VGVWZShkYXRhKSB7CiAgaWYgKHdlYlNvY2tldHMgPT0gZmFsc2UpIHsKICAgIGFsZXJ0KCJZb3VyIGJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBXZWJTb2NrZXRzIik7CiAgICByZXR1cm47CiAgfSBlbHNlIHsKICAgIGlmIChkYXRhWyJjbWQiXSAhPSAiZ2V0TG9nIikgewogICAgICBzaG93TG9hZGluZ1NjcmVlbih0cnVlKQogICAgfQogIH0KICBkZWxldGUgdW5kb1siZXBnTWFwcGluZyJdOwogIAogIHZhciBwcm90b2NvbFdTCiAgc3dpdGNoKHdpbmRvdy5sb2NhdGlvbi5wcm90b2NvbCkgewogICAgY2FzZSAiaHR0cDoiOiAgIHByb3RvY29sV1MgPSAid3M6Ly8iOyBicmVhazsKICAgIGNhc2UgImh0dHBzOiI6ICBwcm90b2NvbFdTID0gIndzczovLyI7IGJyZWFrOwogIH0KCgogIHZhciB3cyA9IG5ldyBXZWJTb2NrZXQocHJvdG9jb2xXUyArIHdpbmRvdy5sb2NhdGlvbi5ob3N0bmFtZSArICI6IiArIHdpbmRvdy5sb2NhdGlvbi5wb3J0ICsgIi9kYXRhLyIgKyAiP1Rva2VuPSIgKyBnZXRDb29raWUoIlRva2VuIikpOwogIHdzLm9ub3BlbiA9IGZ1bmN0aW9uKCkgewogICAgY29uc29sZS5sb2coZGF0YSkKICAgIHdzLnNlbmQoSlNPTi5zdHJpbmdpZnkoZGF0YSkpOwogIH0KCiAgd3Mub25tZXNzYWdlID0gZnVuY3Rpb24gKGUpIHsKICAgIHZhciByZXNwb25zZSA9IEpTT04ucGFyc2UoZS5kYXRhKTsKICAgIGNvbnNvbGUubG9nKHJlc3BvbnNlKTsKICAgIAogICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KCJjbGllbnRJbmZvIikpIHsKICAgICAgY3JlYXRlQ2xpbnRJbmZvKHJlc3BvbnNlWyJjbGllbnRJbmZvIl0pOwogICAgfQoKICAgIGlmIChyZXNwb25zZS5oYXNPd25Qcm9wZXJ0eSgibG9nIikpIHsKICAgICAgY3JlYXRlQ2xpbnRJbmZvKHJlc3BvbnNlWyJsb2ciXSk7CiAgICB9CgogICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KCJzdGF0dXMiKSkgewogICAgICBpZiAocmVzcG9uc2VbInN0YXR1cyJdID09IGZhbHNlKSB7CiAgICAgICAgYWxlcnQocmVzcG9uc2VbImVyciJdKQogICAgICAgIGlmKHJlc3BvbnNlLmhhc093blByb3BlcnR5KCJyZWxvYWQiKSkgewogICAgICAgICAgbG9jYXRpb24ucmVsb2FkKCk7CiAgICAgICAgfQogICAgICAgIC8vY2hlY2tFcnIocmVzcG9uc2UpCiAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2UpOwogICAgICAgIHVwZGF0ZVh0ZXZlU3RhdHVzKHJlc3BvbnNlKTsKICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7IHNob3dMb2FkaW5nU2NyZWVuKGZhbHNlKTsgfSwgMzAwKTsKICAgICAgICAKICAgICAgICByZXR1cm4KICAgICAgfQoKICAgICAgdXBkYXRlWHRldmVTdGF0dXMocmVzcG9uc2UpCgogICAgICAvL2NvbnNvbGUubG9nKGRhdGFbImNtZCJdKTsKICAgICAgc3dpdGNoKGRhdGFbImNtZCJdKSB7CiAgICAgICAgY2FzZSAic2F2ZVVzZXJEYXRhIjogICAgY3JlYXRlTWVudSgpOyBicmVhazsKICAgICAgICBjYXNlICJzYXZlTmV3VXNlciI6ICAgICBjcmVhdGVNZW51KCk7IGJyZWFrOwogICAgICAgIGNhc2UgInNhdmVGaWxlc1hNTFRWIjogIC8vY3JlYXRlTWVudSgpOyBicmVhazsKICAgICAgICBjYXNlICJzYXZlRmlsZXNNM1UiOiAgICAvL2NyZWF0ZU1lbnUoKTsgcmV0dXJuOyBicmVhazsKICAgICAgICBjYXNlICJzYXZlQ29uZmlnIjogICAgCiAgICAgICAgICBkYXRhID0gbmV3IE9iamVjdCgpOwogICAgICAgICAgZGF0YVsiY21kIl0gPSAiY2hlY2tUb2tlbiI7CiAgICAgICAgICB4VGVWZShkYXRhKTsKICAgICAgICAgIGJyZWFrOwoKICAgICAgICBjYXNlICJlbXB0eUxvZyI6IHdyaXRlTG9nSW5EaXYoKTsgYnJlYWs7CiAgICAgICAgY2FzZSAiZ2V0TG9nIjogIHJldHVybjsgYnJlYWs7CiAgICAgIH0KCgogICAgfQoKICAgIGlmIChjb25maWdbImZpbGVzIl0gPT0gdW5kZWZpbmVkIHx8IGNvbmZpZ1siZmlsZXMiXS5sZW5ndGggPT0gMCkgewogICAgICBjcmVhdGVNZW51KCk7CiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKDEwKS5jbGljaygpCiAgICB9CgogICAgc2V0VGltZW91dChmdW5jdGlvbigpeyBzaG93TG9hZGluZ1NjcmVlbihmYWxzZSk7IH0sIDApOwogIH0KICAKfQoKZnVuY3Rpb24gdXBkYXRlWHRldmVTdGF0dXMocmVzcG9uc2UpIHsKICB2YXIga2V5cyA9IGdldE9iaktleXMocmVzcG9uc2UpOwogIC8vY29uc29sZS5sb2coa2V5cyk7CgogIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewogICAgc3dpdGNoKGtleXNbaV0pIHsKICAgICAgY2FzZSAiYWxlcnQiOiAgICAgICAgIGFsZXJ0KHJlc3BvbnNlW2tleXNbaV1dKTsgYnJlYWs7CiAgICAgIGNhc2UgImNvbmZpZyI6ICAgICAgICBzaG93Q29uZmlnKHJlc3BvbnNlW2tleXNbaV1dKTsgYnJlYWs7CiAgICAgIGNhc2UgImxvZyI6ICAgICAgICAgICBwYXJzZUxvZ3MocmVzcG9uc2Vba2V5c1tpXV0pOyBicmVhazsKICAgICAgY2FzZSAibXlTdHJlYW1zIjogICAgIHNob3dNeVN0cmVhbXMocmVzcG9uc2Vba2V5c1tpXV0pOyBicmVhazsKICAgICAgY2FzZSAieEVQRyI6ICAgICAgICAgIHhFUEcgPSByZXNwb25zZVtrZXlzW2ldXTsgYnJlYWs7CiAgICAgIGNhc2UgInVzZXJzIjogICAgICAgICB1c2VycyA9IHJlc3BvbnNlW2tleXNbaV1dOyBicmVhazsKICAgICAgY2FzZSAidG9rZW4iOiAgICAgICAgIGRvY3VtZW50LmNvb2tpZSA9ICJUb2tlbj0iICsgcmVzcG9uc2Vba2V5c1tpXV07IGJyZWFrOwogICAgICBjYXNlICJyZWxvYWQiOiAgICAgICAgbG9jYXRpb24ucmVsb2FkKCk7IGJyZWFrOwogICAgICBjYXNlICJvcGVuTGluayI6ICAgICAgd2luZG93LmxvY2F0aW9uID0gcmVzcG9uc2VbIm9wZW5MaW5rIl07IGJyZWFrOwogICAgICAvL2Nhc2UgInZlcnNpb24iOiB2ZXJzaW9uID0gcmVzcG9uc2Vba2V5c1tpXV07IGJyZWFrOwogICAgfQogIH0KfQoKZnVuY3Rpb24gZ2V0VmFsdWVGcm9tUHJvdmlkZXJGaWxlKHhYbWx0dkZpbGUsIGZpbGVUeXBlLCBrZXkpIHsKCiAgdmFyIGZpbGVJRCA9IHhYbWx0dkZpbGUuc3Vic3RyaW5nKDAsIHhYbWx0dkZpbGUubGFzdEluZGV4T2YoJy4nKSkKCiAgaWYgKGNvbmZpZ1siZmlsZXMiXVtmaWxlVHlwZV0uaGFzT3duUHJvcGVydHkoZmlsZUlEKSA9PSB0cnVlKSB7CiAgICB2YXIgZGF0YSA9IGNvbmZpZ1siZmlsZXMiXVtmaWxlVHlwZV1bZmlsZUlEXTsKICAgIHJldHVybiBkYXRhW2tleV0KICB9Cgp9CgoKCgo=" - webUI["html/js/log.js"] = "dmFyIGxvZ0ludGVydmFsCgoKZnVuY3Rpb24gdXBkYXRlTG9nKCkgewogIHZhciBkYXRhID0gbmV3IE9iamVjdCgpOwogIGRhdGFbImNtZCJdID0gImdldExvZyI7CiAgeFRlVmUoZGF0YSk7CiAgd3JpdGVMb2dJbkRpdigpOwogIHJldHVybgp9CgpmdW5jdGlvbiB3cml0ZUxvZ0luRGl2KCkgewogIHZhciBsb2dzID0gbG9nWyJsb2ciXTsKICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNldHRpbmdzIikubGFzdENoaWxkLmxhc3RDaGlsZDsKICBkaXYuaW5uZXJIVE1MID0gIiI7CgogIHZhciBtYXggPSA1MDsKICAKICAKICBmb3IgKHZhciBpID0gMDsgaSA8IGxvZ3MubGVuZ3RoOyBpKyspIHsKICAgIHZhciBuZXdFbnRyeSA9IG5ldyBPYmplY3QoKTsKICAgIG5ld0VudHJ5WyJfZWxlbWVudCJdICA9ICJQIjsKCiAgICBpZiAobG9nc1tpXS5pbmNsdWRlcygiRVJST1IiKSkgewovLyAgICAgIGNhc2UgIndhcm5pbmdzIjogIG1zZ1R5cGUgPSAid2FybmluZ01zZyI7IGJyZWFrOwogICAgICBuZXdFbnRyeVsiY2xhc3MiXSAgID0gImVycm9yTXNnIjsKICAgIH0KCiAgICBpZiAobG9nc1tpXS5pbmNsdWRlcygiV0FSTklORyIpKSB7Ci8vICAgICAgY2FzZSAid2FybmluZ3MiOiAgbXNnVHlwZSA9ICJ3YXJuaW5nTXNnIjsgYnJlYWs7CiAgICAgIG5ld0VudHJ5WyJjbGFzcyJdICAgPSAid2FybmluZ01zZyI7CiAgICB9CgogICAgbmV3RW50cnlbIl90ZXh0Il0gICAgID0gbG9nc1tpXTsKICAgIAogICAgZGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKICB9CgogIGNhbGN1bGF0ZVdyYXBwZXJIZWlnaHQoKTsKICB2YXIgc2Nyb2xsRGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJveC13cmFwcGVyIik7CiAgc2Nyb2xsRGl2LnNjcm9sbFRvcCA9IHNjcm9sbERpdi5zY3JvbGxIZWlnaHQ7Cn0KCmZ1bmN0aW9uIHNob3dMb2cob2JqKSB7CiAgLy9sb2dJbnRlcnZhbCA9IHNldEludGVydmFsKHVwZGF0ZUxvZywgNTAwMCk7CgogIHZhciBsb2dzID0gbG9nWyJsb2ciXTsKCiAgdmFyIGRpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJzZXR0aW5ncyIpOwoKICB2YXIgbmV3RW50cnkgPSBuZXcgT2JqZWN0KCk7CiAgbmV3RW50cnlbIl9lbGVtZW50Il0gID0gIkhSIjsKICBkaXYuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdFbnRyeSkpOwogIC8vZGl2ID0gZGl2Lmxhc3RDaGlsZDsKCiAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogIG5ld0VudHJ5WyJfZWxlbWVudCJdICAgID0gIklOUFVUIjsKICBuZXdFbnRyeVsidHlwZSJdICAgICAgICA9ICJidXR0b24iOwogIG5ld0VudHJ5WyJjbGFzcyJdICAgICAgID0gImJ1dHRvbiI7CiAgbmV3RW50cnlbInZhbHVlIl0gICAgICAgPSAiRW1wdHkgTG9nIjsKICBuZXdFbnRyeVsib25jbGljayJdICAgICA9ICJlbXB0eUxvZygpIjsKICBkaXYuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdFbnRyeSkpOwoKICB2YXIgbmV3RW50cnkgPSBuZXcgT2JqZWN0KCk7CiAgbmV3RW50cnlbIl9lbGVtZW50Il0gICAgPSAiY29kZSI7CiAgbmV3RW50cnlbIl90ZXh0Il0gICAgICAgID0gIlVwZGF0ZSBMb2c6ICI7CiAgZGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKCiAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogIG5ld0VudHJ5WyJfZWxlbWVudCJdICAgID0gIklOUFVUIjsKICBuZXdFbnRyeVsidHlwZSJdICAgICAgICA9ICJjaGVja2JveCI7CiAgLy9uZXdFbnRyeVsiY2hlY2tlZCJdICAgICA9ICJjaGVja2JveCI7CiAgbmV3RW50cnlbIm9uY2xpY2siXSAgICAgPSAibG9nVXBkYXRlcyh0aGlzKSI7CiAgZGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKCiAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogIG5ld0VudHJ5WyJfZWxlbWVudCJdICA9ICJIUiI7CiAgZGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKCiAgCgoKICAKICB2YXIgbmV3V3JhcHBlciA9IG5ldyBPYmplY3QoKTsKICBuZXdXcmFwcGVyWyJfZWxlbWVudCJdICA9ICJESVYiOwogIG5ld1dyYXBwZXJbImlkIl0gICAgICAgID0gImJveC13cmFwcGVyIjsKICBkaXYuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdXcmFwcGVyKSk7CiAgZGl2ID0gZGl2Lmxhc3RDaGlsZDsKCiAgdmFyIG5ld1ByZSA9IG5ldyBPYmplY3QoKTsKICBuZXdQcmVbIl9lbGVtZW50Il0gID0gIlBSRSI7CiAgbmV3UHJlWyJpZCJdICAgICAgICA9ICJsb2dTY3JlZW4iOwogIGRpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld1ByZSkpOwoKICBkaXYgPSBkaXYubGFzdENoaWxkOwoKICB3cml0ZUxvZ0luRGl2KCkKICByZXR1cm4KfQoKZnVuY3Rpb24gZW1wdHlMb2coKSB7CiAgdmFyIGRhdGEgPSBuZXcgT2JqZWN0KCk7CiAgZGF0YVsiY21kIl0gPSAiZW1wdHlMb2ciOwogIHhUZVZlKGRhdGEpOwogIHJldHVybgp9CgpmdW5jdGlvbiBsb2dVcGRhdGVzKGVsbSkgewogIHN3aXRjaChlbG0uY2hlY2tlZCkgewogICAgY2FzZSBmYWxzZTogY2xlYXJJbnRlcnZhbChsb2dJbnRlcnZhbCk7IGJyZWFrOwogICAgY2FzZSB0cnVlOiBsb2dJbnRlcnZhbCA9IHNldEludGVydmFsKHVwZGF0ZUxvZywgNTAwMCk7IGJyZWFrOwogICAgCiAgfQp9" - webUI["html/js/settings_ts.js"] = "dmFyIF9fZXh0ZW5kcyA9ICh0aGlzICYmIHRoaXMuX19leHRlbmRzKSB8fCAoZnVuY3Rpb24gKCkgewogICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikgewogICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwKICAgICAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fAogICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9OwogICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpOwogICAgfTsKICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikgewogICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7CiAgICAgICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9CiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpOwogICAgfTsKfSkoKTsKdmFyIFNldHRpbmdzQ2F0ZWdvcnkgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7CiAgICBmdW5jdGlvbiBTZXR0aW5nc0NhdGVnb3J5KCkgewogICAgICAgIHRoaXMuRG9jdW1lbnRJRCA9ICJjb250ZW50X3NldHRpbmdzIjsKICAgIH0KICAgIFNldHRpbmdzQ2F0ZWdvcnkucHJvdG90eXBlLmNyZWF0ZUNhdGVnb3J5SGVhZGxpbmUgPSBmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgICB2YXIgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIkg0Iik7CiAgICAgICAgZWxlbWVudC5pbm5lckhUTUwgPSB2YWx1ZTsKICAgICAgICByZXR1cm4gZWxlbWVudDsKICAgIH07CiAgICBTZXR0aW5nc0NhdGVnb3J5LnByb3RvdHlwZS5jcmVhdGVIUiA9IGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIkhSIik7CiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9OwogICAgU2V0dGluZ3NDYXRlZ29yeS5wcm90b3R5cGUuY3JlYXRlU2V0dGluZ3MgPSBmdW5jdGlvbiAoc2V0dGluZ3NLZXkpIHsKICAgICAgICB2YXIgc2V0dGluZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlRSIik7CiAgICAgICAgdmFyIGNvbnRlbnQgPSBuZXcgUG9wdXBDb250ZW50KCk7CiAgICAgICAgdmFyIGRhdGEgPSBTRVJWRVJbInNldHRpbmdzIl1bc2V0dGluZ3NLZXldOwogICAgICAgIHN3aXRjaCAoc2V0dGluZ3NLZXkpIHsKICAgICAgICAgICAgLy8gVGV4dGVpbmdhYmVuCiAgICAgICAgICAgIGNhc2UgInVwZGF0ZSI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MudXBkYXRlLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsICJ1cGRhdGUiLCBkYXRhLnRvU3RyaW5nKCkpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5zZXR0aW5ncy51cGRhdGUucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImJhY2t1cC5wYXRoIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5iYWNrdXBQYXRoLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsICJiYWNrdXAucGF0aCIsIGRhdGEpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5zZXR0aW5ncy5iYWNrdXBQYXRoLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgIHRkUmlnaHQuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ0ZW1wLnBhdGgiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLnRlbXBQYXRoLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsICJ0ZW1wLnBhdGgiLCBkYXRhKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3suc2V0dGluZ3MudG1wUGF0aC5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAidXNlci5hZ2VudCI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MudXNlckFnZW50LnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsICJ1c2VyLmFnZW50IiwgZGF0YSk7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LnNldHRpbmdzLnVzZXJBZ2VudC5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYnVmZmVyLnRpbWVvdXQiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLmJ1ZmZlclRpbWVvdXQudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgImJ1ZmZlci50aW1lb3V0IiwgZGF0YSk7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LnNldHRpbmdzLmJ1ZmZlclRpbWVvdXQucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImZmbXBlZy5wYXRoIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5mZm1wZWdQYXRoLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsICJmZm1wZWcucGF0aCIsIGRhdGEpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5zZXR0aW5ncy5mZm1wZWdQYXRoLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgIHRkUmlnaHQuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJmZm1wZWcub3B0aW9ucyI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuZmZtcGVnT3B0aW9ucy50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCAiZmZtcGVnLm9wdGlvbnMiLCBkYXRhKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3suc2V0dGluZ3MuZmZtcGVnT3B0aW9ucy5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAidmxjLnBhdGgiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLnZsY1BhdGgudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgInZsYy5wYXRoIiwgZGF0YSk7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LnNldHRpbmdzLnZsY1BhdGgucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInZsYy5vcHRpb25zIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy52bGNPcHRpb25zLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsICJ2bGMub3B0aW9ucyIsIGRhdGEpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5zZXR0aW5ncy52bGNPcHRpb25zLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgIHRkUmlnaHQuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAvLyBDaGVja2JveGVuCiAgICAgICAgICAgIGNhc2UgImF1dGhlbnRpY2F0aW9uLndlYiI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuYXV0aGVudGljYXRpb25XRUIudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImF1dGhlbnRpY2F0aW9uLnBtcyI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuYXV0aGVudGljYXRpb25QTVMudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImF1dGhlbnRpY2F0aW9uLm0zdSI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuYXV0aGVudGljYXRpb25NM1UudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImF1dGhlbnRpY2F0aW9uLnhtbCI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuYXV0aGVudGljYXRpb25YTUwudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImF1dGhlbnRpY2F0aW9uLmFwaSI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuYXV0aGVudGljYXRpb25BUEkudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImZpbGVzLnVwZGF0ZSI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuZmlsZXNVcGRhdGUudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImNhY2hlLmltYWdlcyI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuY2FjaGVJbWFnZXMudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInhlcGcucmVwbGFjZS5taXNzaW5nLmltYWdlcyI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MucmVwbGFjZUVtcHR5SW1hZ2VzLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVDaGVja2JveChzZXR0aW5nc0tleSk7CiAgICAgICAgICAgICAgICBpbnB1dC5jaGVja2VkID0gZGF0YTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgIHRkUmlnaHQuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ4dGV2ZUF1dG9VcGRhdGUiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLnh0ZXZlQXV0b1VwZGF0ZS50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGE7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYXBpIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5hcGkudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIC8vIFNlbGVjdAogICAgICAgICAgICBjYXNlICJ0dW5lciI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MudHVuZXIudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgdGV4dCA9IG5ldyBBcnJheSgpOwogICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IG5ldyBBcnJheSgpOwogICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPD0gMTAwOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICB0ZXh0LnB1c2goaSk7CiAgICAgICAgICAgICAgICAgICAgdmFsdWVzLnB1c2goaSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ID0gY29udGVudC5jcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCBkYXRhLCBzZXR0aW5nc0tleSk7CiAgICAgICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChzZWxlY3QpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJlcGdTb3VyY2UiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLmVwZ1NvdXJjZS50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciB0ZXh0ID0gWyJQTVMiLCAiWEVQRyJdOwogICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IFsiUE1TIiwgIlhFUEciXTsKICAgICAgICAgICAgICAgIHZhciBzZWxlY3QgPSBjb250ZW50LmNyZWF0ZVNlbGVjdCh0ZXh0LCB2YWx1ZXMsIGRhdGEsIHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKHNlbGVjdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImJhY2t1cC5rZWVwIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5iYWNrdXBLZWVwLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIHRleHQgPSBbIjUiLCAiMTAiLCAiMjAiLCAiMzAiLCAiNDAiLCAiNTAiXTsKICAgICAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBbIjUiLCAiMTAiLCAiMjAiLCAiMzAiLCAiNDAiLCAiNTAiXTsKICAgICAgICAgICAgICAgIHZhciBzZWxlY3QgPSBjb250ZW50LmNyZWF0ZVNlbGVjdCh0ZXh0LCB2YWx1ZXMsIGRhdGEsIHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKHNlbGVjdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImJ1ZmZlci5zaXplLmtiIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5idWZmZXJTaXplLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIHRleHQgPSBbIjAuNSBNQiIsICIxIE1CIiwgIjIgTUIiLCAiMyBNQiIsICI0IE1CIiwgIjUgTUIiLCAiNiBNQiIsICI3IE1CIiwgIjggTUIiXTsKICAgICAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBbIjUxMiIsICIxMDI0IiwgIjIwNDgiLCAiMzA3MiIsICI0MDk2IiwgIjUxMjAiLCAiNjE0NCIsICI3MTY4IiwgIjgxOTIiXTsKICAgICAgICAgICAgICAgIHZhciBzZWxlY3QgPSBjb250ZW50LmNyZWF0ZVNlbGVjdCh0ZXh0LCB2YWx1ZXMsIGRhdGEsIHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKHNlbGVjdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImJ1ZmZlciI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3Muc3RyZWFtQnVmZmVyaW5nLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIHRleHQgPSBbInt7LnNldHRpbmdzLnN0cmVhbUJ1ZmZlcmluZy5pbmZvX2ZhbHNlfX0iLCAieFRlVmU6ICh7ey5zZXR0aW5ncy5zdHJlYW1CdWZmZXJpbmcuaW5mb194dGV2ZX19KSIsICJGRm1wZWc6ICh7ey5zZXR0aW5ncy5zdHJlYW1CdWZmZXJpbmcuaW5mb19mZm1wZWd9fSkiLCAiVkxDOiAoe3suc2V0dGluZ3Muc3RyZWFtQnVmZmVyaW5nLmluZm9fdmxjfX0pIl07CiAgICAgICAgICAgICAgICB2YXIgdmFsdWVzID0gWyItIiwgInh0ZXZlIiwgImZmbXBlZyIsICJ2bGMiXTsKICAgICAgICAgICAgICAgIHZhciBzZWxlY3QgPSBjb250ZW50LmNyZWF0ZVNlbGVjdCh0ZXh0LCB2YWx1ZXMsIGRhdGEsIHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKHNlbGVjdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInVkcHh5IjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy51ZHB4eS50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCAidWRweHkiLCBkYXRhKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3suc2V0dGluZ3MudWRweHkucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZXR0aW5nOwogICAgfTsKICAgIFNldHRpbmdzQ2F0ZWdvcnkucHJvdG90eXBlLmNyZWF0ZURlc2NyaXB0aW9uID0gZnVuY3Rpb24gKHNldHRpbmdzS2V5KSB7CiAgICAgICAgdmFyIGRlc2NyaXB0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVFIiKTsKICAgICAgICB2YXIgdGV4dDsKICAgICAgICBzd2l0Y2ggKHNldHRpbmdzS2V5KSB7CiAgICAgICAgICAgIGNhc2UgImF1dGhlbnRpY2F0aW9uLndlYiI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmF1dGhlbnRpY2F0aW9uV0VCLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImF1dGhlbnRpY2F0aW9uLm0zdSI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmF1dGhlbnRpY2F0aW9uTTNVLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImF1dGhlbnRpY2F0aW9uLnBtcyI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmF1dGhlbnRpY2F0aW9uUE1TLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImF1dGhlbnRpY2F0aW9uLnhtbCI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmF1dGhlbnRpY2F0aW9uWE1MLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImF1dGhlbnRpY2F0aW9uLmFwaSI6CiAgICAgICAgICAgICAgICBpZiAoU0VSVkVSWyJzZXR0aW5ncyJdWyJhdXRoZW50aWNhdGlvbi53ZWIiXSA9PSB0cnVlKSB7CiAgICAgICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy5hdXRoZW50aWNhdGlvbkFQSS5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ4dGV2ZUF1dG9VcGRhdGUiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy54dGV2ZUF1dG9VcGRhdGUuZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYmFja3VwLmtlZXAiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy5iYWNrdXBLZWVwLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImJhY2t1cC5wYXRoIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MuYmFja3VwUGF0aC5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ0ZW1wLnBhdGgiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy50ZW1wUGF0aC5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJidWZmZXIiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy5zdHJlYW1CdWZmZXJpbmcuZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYnVmZmVyLnNpemUua2IiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy5idWZmZXJTaXplLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImJ1ZmZlci50aW1lb3V0IjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MuYnVmZmVyVGltZW91dC5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ1c2VyLmFnZW50IjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MudXNlckFnZW50LmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImZmbXBlZy5wYXRoIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MuZmZtcGVnUGF0aC5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJmZm1wZWcub3B0aW9ucyI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmZmbXBlZ09wdGlvbnMuZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAidmxjLnBhdGgiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy52bGNQYXRoLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInZsYy5vcHRpb25zIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MudmxjT3B0aW9ucy5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJlcGdTb3VyY2UiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy5lcGdTb3VyY2UuZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAidHVuZXIiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy50dW5lci5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ1cGRhdGUiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy51cGRhdGUuZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYXBpIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MuYXBpLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImZpbGVzLnVwZGF0ZSI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmZpbGVzVXBkYXRlLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImNhY2hlLmltYWdlcyI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmNhY2hlSW1hZ2VzLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInhlcGcucmVwbGFjZS5taXNzaW5nLmltYWdlcyI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLnJlcGxhY2VFbXB0eUltYWdlcy5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ1ZHB4eSI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLnVkcHh5LmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0ZXh0ID0gIiI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICIiOwogICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICB2YXIgcHJlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiUFJFIik7CiAgICAgICAgcHJlLmlubmVySFRNTCA9IHRleHQ7CiAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChwcmUpOwogICAgICAgIGRlc2NyaXB0aW9uLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgZGVzY3JpcHRpb24uYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgcmV0dXJuIGRlc2NyaXB0aW9uOwogICAgfTsKICAgIHJldHVybiBTZXR0aW5nc0NhdGVnb3J5Owp9KCkpOwp2YXIgU2V0dGluZ3NDYXRlZ29yeUl0ZW0gPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoX3N1cGVyKSB7CiAgICBfX2V4dGVuZHMoU2V0dGluZ3NDYXRlZ29yeUl0ZW0sIF9zdXBlcik7CiAgICBmdW5jdGlvbiBTZXR0aW5nc0NhdGVnb3J5SXRlbShoZWFkbGluZSwgc2V0dGluZ3NLZXlzKSB7CiAgICAgICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpczsKICAgICAgICBfdGhpcy5oZWFkbGluZSA9IGhlYWRsaW5lOwogICAgICAgIF90aGlzLnNldHRpbmdzS2V5cyA9IHNldHRpbmdzS2V5czsKICAgICAgICByZXR1cm4gX3RoaXM7CiAgICB9CiAgICBTZXR0aW5nc0NhdGVnb3J5SXRlbS5wcm90b3R5cGUuY3JlYXRlQ2F0ZWdvcnkgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgdmFyIF90aGlzID0gdGhpczsKICAgICAgICB2YXIgaGVhZGxpbmUgPSB0aGlzLmNyZWF0ZUNhdGVnb3J5SGVhZGxpbmUodGhpcy5oZWFkbGluZSk7CiAgICAgICAgdmFyIHNldHRpbmdzS2V5cyA9IHRoaXMuc2V0dGluZ3NLZXlzOwogICAgICAgIHZhciBkb2MgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLkRvY3VtZW50SUQpOwogICAgICAgIGRvYy5hcHBlbmRDaGlsZChoZWFkbGluZSk7CiAgICAgICAgLy8gVGFiZWxsZSBmw7xyIGRpZSBLYXRlZ29yaWUgZXJzdGVsbGVuCiAgICAgICAgdmFyIHRhYmxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEFCTEUiKTsKICAgICAgICB2YXIga2V5cyA9IHNldHRpbmdzS2V5cy5zcGxpdCgiLCIpOwogICAgICAgIGtleXMuZm9yRWFjaChmdW5jdGlvbiAoc2V0dGluZ3NLZXkpIHsKICAgICAgICAgICAgc3dpdGNoIChzZXR0aW5nc0tleSkgewogICAgICAgICAgICAgICAgY2FzZSAiYXV0aGVudGljYXRpb24ucG1zIjoKICAgICAgICAgICAgICAgIGNhc2UgImF1dGhlbnRpY2F0aW9uLm0zdSI6CiAgICAgICAgICAgICAgICBjYXNlICJhdXRoZW50aWNhdGlvbi54bWwiOgogICAgICAgICAgICAgICAgY2FzZSAiYXV0aGVudGljYXRpb24uYXBpIjoKICAgICAgICAgICAgICAgICAgICBpZiAoU0VSVkVSWyJzZXR0aW5ncyJdWyJhdXRoZW50aWNhdGlvbi53ZWIiXSA9PSBmYWxzZSkgewogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgIHZhciBpdGVtID0gX3RoaXMuY3JlYXRlU2V0dGluZ3Moc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgICAgIHZhciBkZXNjcmlwdGlvbiA9IF90aGlzLmNyZWF0ZURlc2NyaXB0aW9uKHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgICAgICB0YWJsZS5hcHBlbmRDaGlsZChpdGVtKTsKICAgICAgICAgICAgICAgICAgICB0YWJsZS5hcHBlbmRDaGlsZChkZXNjcmlwdGlvbik7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgICBkb2MuYXBwZW5kQ2hpbGQodGFibGUpOwogICAgICAgIGRvYy5hcHBlbmRDaGlsZCh0aGlzLmNyZWF0ZUhSKCkpOwogICAgfTsKICAgIHJldHVybiBTZXR0aW5nc0NhdGVnb3J5SXRlbTsKfShTZXR0aW5nc0NhdGVnb3J5KSk7CmZ1bmN0aW9uIHNob3dTZXR0aW5ncygpIHsKICAgIGNvbnNvbGUubG9nKCJTRVRUSU5HUyIpOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZXR0aW5nc0NhdGVnb3J5Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgc2V0dGluZ3NDYXRlZ29yeVtpXS5jcmVhdGVDYXRlZ29yeSgpOwogICAgfQp9CmZ1bmN0aW9uIHNhdmVTZXR0aW5ncygpIHsKICAgIGNvbnNvbGUubG9nKCJTYXZlIFNldHRpbmdzIik7CiAgICB2YXIgY21kID0gInNhdmVTZXR0aW5ncyI7CiAgICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImNvbnRlbnRfc2V0dGluZ3MiKTsKICAgIHZhciBzZXR0aW5ncyA9IGRpdi5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCJjaGFuZ2VkIik7CiAgICB2YXIgbmV3U2V0dGluZ3MgPSBuZXcgT2JqZWN0KCk7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNldHRpbmdzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIG5hbWU7CiAgICAgICAgdmFyIHZhbHVlOwogICAgICAgIHN3aXRjaCAoc2V0dGluZ3NbaV0udGFnTmFtZSkgewogICAgICAgICAgICBjYXNlICJJTlBVVCI6CiAgICAgICAgICAgICAgICBzd2l0Y2ggKHNldHRpbmdzW2ldLnR5cGUpIHsKICAgICAgICAgICAgICAgICAgICBjYXNlICJjaGVja2JveCI6CiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSBzZXR0aW5nc1tpXS5uYW1lOwogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHNldHRpbmdzW2ldLmNoZWNrZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgIG5ld1NldHRpbmdzW25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIGNhc2UgInRleHQiOgogICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gc2V0dGluZ3NbaV0ubmFtZTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBzZXR0aW5nc1tpXS52YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChuYW1lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJ1cGRhdGUiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc3BsaXQoIiwiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLmZpbHRlcihmdW5jdGlvbiAoZSkgeyByZXR1cm4gZTsgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJidWZmZXIudGltZW91dCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBwYXJzZUZsb2F0KHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBuZXdTZXR0aW5nc1tuYW1lXSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJTRUxFQ1QiOgogICAgICAgICAgICAgICAgbmFtZSA9IHNldHRpbmdzW2ldLm5hbWU7CiAgICAgICAgICAgICAgICB2YWx1ZSA9IHNldHRpbmdzW2ldLnZhbHVlOwogICAgICAgICAgICAgICAgLy8gV2VubiBkZXIgV2VydCBlaW5lIFphaGwgaXN0LCB3aXJkIGRpZXNlciBhbHMgWmFobCBnZXNwZWljaGVydAogICAgICAgICAgICAgICAgaWYgKGlzTmFOKHZhbHVlKSkgewogICAgICAgICAgICAgICAgICAgIG5ld1NldHRpbmdzW25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBuZXdTZXR0aW5nc1tuYW1lXSA9IHBhcnNlSW50KHZhbHVlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0KICAgIHZhciBkYXRhID0gbmV3IE9iamVjdCgpOwogICAgZGF0YVsic2V0dGluZ3MiXSA9IG5ld1NldHRpbmdzOwogICAgdmFyIHNlcnZlciA9IG5ldyBTZXJ2ZXIoY21kKTsKICAgIHNlcnZlci5yZXF1ZXN0KGRhdGEpOwp9Cg==" - webUI["html/js/users.js"] = "ZnVuY3Rpb24gb3BlblVzZXJzKGVsbSkgewogIGNvbG9tblNvcnQgPSAwOwoKICB2YXIgbmV3RGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNldHRpbmdzIik7CiAgCiAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogIG5ld0VudHJ5WyJfZWxlbWVudCJdICA9ICJIUiI7CiAgbmV3RGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3RW50cnkpKTsKCiAgdmFyIG5ld0VudHJ5ID0gbmV3IE9iamVjdCgpOwogIG5ld0VudHJ5WyJfZWxlbWVudCJdICA9ICJJTlBVVCI7CiAgbmV3RW50cnlbInR5cGUiXSA9ICJidXR0b24iOwogIG5ld0VudHJ5WyJjbGFzcyJdID0gImJ1dHRvbiI7CiAgbmV3RW50cnlbInZhbHVlIl0gPSAiTmV3IjsKICBuZXdFbnRyeVsib25jbGljayJdID0gInVzZXJEZXRhaWwoMCkiOwogIG5ld0Rpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0VudHJ5KSk7CgogIHZhciBkaXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgic2V0dGluZ3MiKTsKCiAgIC8vIEJ1aWxkIHRhYmxlCiAgdmFyIG5ld1RhYmxlID0gbmV3IE9iamVjdCgpOwogIG5ld1RhYmxlWyJfZWxlbWVudCJdICA9ICJUQUJMRSI7CiAgbmV3VGFibGVbImlkIl0gICAgICAgID0gImlkX21hcHBpbmciOwogIG5ld1RhYmxlWyJjbGFzcyJdICAgICA9ICJ0YWJsZS1tYXBwaW5nIjsKICBkaXYuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdUYWJsZSkpOwoKICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7IAogICAgY3JlYXRlVXNlcnNUYWJsZSgpOyAKICB9LCAxMCk7Cn0KCmZ1bmN0aW9uIGNyZWF0ZVVzZXJzVGFibGUoKSB7CiAgdmFyIHRhYmxlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImlkX21hcHBpbmciKTsKICB0YWJsZS5pbm5lckhUTUwgPSAiIjsKICB2YXIgbmV3VFIgPSBuZXcgT2JqZWN0KCk7CiAgbmV3VFJbIl9lbGVtZW50Il0gPSAiVFIiOwogIG5ld1RSWyJjbGFzcyJdICAgID0gInRhYmxlLW1hcHBpbmctaGVhZGVyIjsKICB0YWJsZS5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld1RSKSk7CgogIHZhciB0ciA9IHRhYmxlLmxhc3RDaGlsZDsKICB2YXIgdHJIZWFkbGluZXMgPSBuZXcgQXJyYXkoIlVzZXJuYW1lIiwgIlBhc3N3b3JkIiwgIldFQiIsICJQTVMiLCAiTTNVIiwgIlhNTCIsICJBUEkiKQoKICBmb3IgKHZhciBpID0gMDsgaSA8IHRySGVhZGxpbmVzLmxlbmd0aDsgaSsrKSB7CiAgICB2YXIgbmV3VEQgPSBuZXcgT2JqZWN0KCk7CiAgICBuZXdURFsiX2VsZW1lbnQiXSA9ICJURCI7CiAgICBuZXdURFsiX3RleHQiXSAgICA9IHRySGVhZGxpbmVzW2ldOwogICAgdHIuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdURCkpOwogIH0KCgogIC8vIFNvcnQgdXNlcnMKICB2YXIgdXNlcklkcyA9IGdldE9iaktleXModXNlcnMpOwoKICB2YXIgdXNlck9iaiA9IG5ldyBPYmplY3QoKTsKCiAgZm9yICh2YXIgaSA9IDA7IGkgPCB1c2VySWRzLmxlbmd0aDsgaSsrKSB7CiAgICB2YXIgdXNlcm5hbWUgPSB1c2Vyc1t1c2VySWRzW2ldXVsiZGF0YSJdWyJ1c2VybmFtZSJdOwogICAgdXNlck9ialt1c2VybmFtZV0gPSB1c2VySWRzW2ldOwogIH0KCiAgdmFyIGFsbFVzZXJzID0gZ2V0T2JqS2V5cyh1c2VyT2JqKTsKICBhbGxVc2Vycy5zb3J0KCk7CiAgLy8gLS0KCiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhbGxVc2Vycy5sZW5ndGg7IGkrKykgewogICAgdmFyIHRhYmxlICAgICA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJpZF9tYXBwaW5nIik7CiAgICB2YXIgdXNlcklEICAgID0gdXNlck9ialthbGxVc2Vyc1tpXV07CiAgICB2YXIgdXNlcm5hbWUgID0gYWxsVXNlcnNbaV07CiAgICB2YXIgaXRlbSAgICAgID0gdXNlcnNbdXNlcklEXVsiZGF0YSJdOwoKICAgIC8vIENyZWF0ZSBUUgogICAgdmFyIG5ld1RSID0gbmV3IE9iamVjdCgpOwogICAgbmV3VFJbIl9lbGVtZW50Il0gICAgICAgPSAiVFIiOwogICAgbmV3VFJbImNsYXNzIl0gICAgICAgICAgPSAiIjsKICAgIG5ld1RSWyJpZCJdICAgICAgICAgICAgID0gdXNlcklEOwogICAgbmV3VFJbIm9uY2xpY2siXSAgICAgICAgPSAnamF2YXNjcmlwdDogdXNlckRldGFpbCgiJyArIHVzZXJJRCArICciKTsnOwogICAgdGFibGUuYXBwZW5kQ2hpbGQoY3JlYXRlRWxlbWVudChuZXdUUikpOwoKICAgIHZhciB0ciA9IHRhYmxlLmxhc3RDaGlsZDsKCiAgICAvLyBDcmVhdGUgdXNlcm5hbWUgVEQKICAgIHZhciBuZXdURCA9IG5ldyBPYmplY3QoKTsKICAgIG5ld1REWyJfZWxlbWVudCJdID0gIlAiOwogICAgbmV3VERbIl90ZXh0Il0gICAgPSB1c2VybmFtZTsKICAgIGNyZWF0ZU5ld1REKG5ld1RELCB0cik7CgogICAgLy8gQ3JlYXRlIHBhc3N3b3JkIFRECiAgICB2YXIgbmV3VEQgPSBuZXcgT2JqZWN0KCk7CiAgICBuZXdURFsiX2VsZW1lbnQiXSA9ICJQIjsKICAgIG5ld1REWyJfdGV4dCJdICAgID0gIi4uLi4uIjsKICAgIGNyZWF0ZU5ld1REKG5ld1RELCB0cik7CgogICAgLy8gQ3JlYXRlIHdlYiBhY2Nlc3MKICAgIHZhciBuZXdURCA9IG5ldyBPYmplY3QoKTsKICAgIG5ld1REWyJfZWxlbWVudCJdID0gIlAiOwogICAgc3dpdGNoKGl0ZW1bImF1dGhlbnRpY2F0aW9uLndlYiJdKXsKICAgICAgY2FzZSB0cnVlOiBuZXdURFsiX3RleHQiXSAgICA9ICLinJMiOyBicmVhazsKICAgICAgZGVmYXVsdDogICBuZXdURFsiX3RleHQiXSAgICA9ICItIjsgYnJlYWs7CiAgICB9CiAgICBjcmVhdGVOZXdURChuZXdURCwgdHIpOwoKICAgIC8vIENyZWF0ZSBQTVMgYWNjZXNzCiAgICB2YXIgbmV3VEQgPSBuZXcgT2JqZWN0KCk7CiAgICBuZXdURFsiX2VsZW1lbnQiXSA9ICJQIjsKICAgIHN3aXRjaChpdGVtWyJhdXRoZW50aWNhdGlvbi5wbXMiXSl7CiAgICAgIGNhc2UgdHJ1ZTogbmV3VERbIl90ZXh0Il0gICAgPSAi4pyTIjsgYnJlYWs7CiAgICAgIGRlZmF1bHQ6ICAgbmV3VERbIl90ZXh0Il0gICAgPSAiLSI7IGJyZWFrOwogICAgfQogICAgY3JlYXRlTmV3VEQobmV3VEQsIHRyKTsKCiAgICAvLyBDcmVhdGUgTTNVIGFjY2VzcwogICAgdmFyIG5ld1REID0gbmV3IE9iamVjdCgpOwogICAgbmV3VERbIl9lbGVtZW50Il0gPSAiUCI7CiAgICBzd2l0Y2goaXRlbVsiYXV0aGVudGljYXRpb24ubTN1Il0pewogICAgICBjYXNlIHRydWU6IG5ld1REWyJfdGV4dCJdICAgID0gIuKckyI7IGJyZWFrOwogICAgICBkZWZhdWx0OiAgIG5ld1REWyJfdGV4dCJdICAgID0gIi0iOyBicmVhazsKICAgIH0KICAgIGNyZWF0ZU5ld1REKG5ld1RELCB0cik7CgogICAgLy8gQ3JlYXRlIFhNTFRWIGFjY2VzcwogICAgdmFyIG5ld1REID0gbmV3IE9iamVjdCgpOwogICAgbmV3VERbIl9lbGVtZW50Il0gPSAiUCI7CiAgICBzd2l0Y2goaXRlbVsiYXV0aGVudGljYXRpb24ueG1sIl0pewogICAgICBjYXNlIHRydWU6IG5ld1REWyJfdGV4dCJdICAgID0gIuKckyI7IGJyZWFrOwogICAgICBkZWZhdWx0OiAgIG5ld1REWyJfdGV4dCJdICAgID0gIi0iOyBicmVhazsKICAgIH0KICAgIGNyZWF0ZU5ld1REKG5ld1RELCB0cik7CgogICAgLy8gQ3JlYXRlIEFQSSBhY2Nlc3MKICAgIHZhciBuZXdURCA9IG5ldyBPYmplY3QoKTsKICAgIG5ld1REWyJfZWxlbWVudCJdID0gIlAiOwoKICAgIHN3aXRjaChpdGVtWyJhdXRoZW50aWNhdGlvbi5hcGkiXSl7CiAgICAgIGNhc2UgdHJ1ZTogbmV3VERbIl90ZXh0Il0gICAgPSAi4pyTIjsgYnJlYWs7CiAgICAgIGRlZmF1bHQ6ICAgbmV3VERbIl90ZXh0Il0gICAgPSAiLSI7IGJyZWFrOwogICAgfQogICAgY3JlYXRlTmV3VEQobmV3VEQsIHRyKTsKCiAgfQoKICAvLyB1c2FnZSBJbmZvICAKICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNldHRpbmdzIik7CiAgc3dpdGNoKG1lbnVbYWN0aXZlTWVudS5pZF0uaGFzT3duUHJvcGVydHkoIl91c2FnZSIpKSB7CiAgICBjYXNlIHRydWU6IAogICAgICB2YXIgdXNhZ2VJdGVtID0gbmV3IE9iamVjdCgpOwogICAgICB1c2FnZUl0ZW1bIl9lbGVtZW50Il0gPSAiUFJFIgogICAgICB1c2FnZUl0ZW1bIl90ZXh0Il0gICAgPSBtZW51W2FjdGl2ZU1lbnUuaWRdWyJfdXNhZ2UiXTsKCiAgICAgIHZhciBuZXdIUiA9IG5ldyBPYmplY3QoKTsKICAgICAgbmV3SFJbIl9lbGVtZW50Il0gPSAiSFIiCiAgICAgIGRpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KG5ld0hSKSk7CiAgICAgIGRpdi5hcHBlbmRDaGlsZChjcmVhdGVFbGVtZW50KHVzYWdlSXRlbSkpOwogIH0KCiAgc29ydFRhYmxlKDApOwp9CgpmdW5jdGlvbiB1c2VyRGV0YWlsKHVzZXJJRCkgewogIHNob3dQb3BVcEVsZW1lbnQoJ3VzZXItZGV0YWlsJyk7CiAgc2V0VGltZW91dChmdW5jdGlvbigpeyAKICAgIHNob3dFbGVtZW50KCJwb3B1cCIsIHRydWUpOwogIH0sIDEwKTsKICB2YXIgZGVmYXVsdFVzZXI7CgogIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJzYXZlVXNlckRldGFpbCIpLnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBzYXZlVXNlckRldGFpbCgiJyArIHVzZXJJRCArICciLCBmYWxzZSknKTsKICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZGVsZXRlVXNlckRldGFpbCIpLnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBzYXZlVXNlckRldGFpbCgiJyArIHVzZXJJRCArICciLCB0cnVlKScpOwoKICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICAKICBzd2l0Y2godXNlcklEKSB7CiAgICBjYXNlIDA6ICAgLy8gTmV3IFVzZXIKICAgICAgZGF0YVsidXNlcm5hbWUiXSA9ICIiOwogICAgICBkYXRhWyJhdXRoZW50aWNhdGlvbi53ZWIiXSA9IGZhbHNlOwogICAgICBkYXRhWyJhdXRoZW50aWNhdGlvbi5wbXMiXSA9IHRydWU7CiAgICAgIGRhdGFbImF1dGhlbnRpY2F0aW9uLnhtbCJdID0gdHJ1ZTsKICAgICAgZGF0YVsiYXV0aGVudGljYXRpb24ubTN1Il0gPSBmYWxzZTsKICAgICAgZGF0YVsiYXV0aGVudGljYXRpb24uYXBpIl0gPSBmYWxzZTsKICAgICAgZGF0YVsiZGVmYXVsdFVzZXIiXSAgICAgICAgPSBmYWxzZTsKICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpeyAKICAgICAgICBzaG93RWxlbWVudCgiZGVsZXRlVXNlckRldGFpbCIsIGZhbHNlKQogICAgICB9LCAxKTsKCiAgICAgIGJyZWFrOyAKICAgIAogICAgZGVmYXVsdDogCiAgICAgIGRhdGEgPSB1c2Vyc1t1c2VySURdWyJkYXRhIl07IAogICAgICBzaG93RWxlbWVudCgiZGVsZXRlVXNlckRldGFpbCIsIHRydWUpICAgCiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJkZWxldGVVc2VyRGV0YWlsIikuY2xhc3NOYW1lID0gImRlbGV0ZSI7CiAgIAogICAgICBicmVhawogIH0KICAKCiAgdmFyIHVzZXJuYW1lID0gZGF0YVsidXNlcm5hbWUiXTsKICBkYXRhWyJwYXNzd29yZCJdID0gIiI7CiAgZGF0YVsiY29uZmlybSJdID0gIiI7CgogIHZhciBrZXlzID0gZ2V0T2JqS2V5cyhkYXRhKTsKICBkZWZhdWx0VXNlciA9IGRhdGFbImRlZmF1bHRVc2VyIl07CiAgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoImRlZmF1bHRVc2VyIikpIHsKICAgIGRlZmF1bHRVc2VyID0gSlNPTi5wYXJzZShkYXRhWyJkZWZhdWx0VXNlciJdKTsKICB9CgogIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewoKICAgIGlmKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGtleXNbaV0pKXsKICAgICAgdmFyIHRkID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoa2V5c1tpXSkKICAgIH0gZWxzZSB7CiAgICAgIHZhciB0ZCA9IHVuZGVmaW5lZDsKICAgIH0KCiAgICB2YXIgbmV3SXRlbSA9IG5ldyBPYmplY3QoKTsKCiAgICBuZXdJdGVtWyJfZWxlbWVudCJdID0gIklOUFVUIjsKICAgIAogICAgbmV3SXRlbVsidmFsdWUiXSAgICA9IGRhdGFba2V5c1tpXV07CiAgICBuZXdJdGVtWyJuYW1lIl0gICAgID0ga2V5c1tpXTsKCgoKCgogICAgc3dpdGNoKGtleXNbaV0uaW5kZXhPZigiYXV0aGVudGljYXRpb24iKSkgewogICAgICBjYXNlIC0xOiAKICAgICAgICBpZiAoa2V5c1tpXSA9PSAicGFzc3dvcmQiIHx8IGtleXNbaV0gPT0gImNvbmZpcm0iKSB7CiAgICAgICAgICBuZXdJdGVtWyJ0eXBlIl0gICAgID0gInBhc3N3b3JkIjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbmV3SXRlbVsidHlwZSJdICAgICA9ICJ0ZXh0IjsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CgogICAgICBkZWZhdWx0OiAKICAgICAgICBuZXdJdGVtWyJ0eXBlIl0gICAgID0gImNoZWNrYm94IjsKICAgICAgICAKICAgICAgICBpZiAoa2V5c1tpXSA9PSAiYXV0aGVudGljYXRpb24ud2ViIiAmJiBkZWZhdWx0VXNlciA9PSB0cnVlKSB7CiAgICAgICAgICBuZXdJdGVtWyJvbmNsaWNrIl0gPSAicmV0dXJuIGZhbHNlIjsgCiAgICAgICAgfQogICAgICAgIAogICAgICAgIGlmIChkYXRhW2tleXNbaV1dID09IHRydWUpIHsgICAgICAgICAgCiAgICAgICAgICBuZXdJdGVtWyJjaGVja2VkIl0gID0gZGF0YVtrZXlzW2ldXTsgIAogICAgICAgIH0KICAgICAgICAKICAgICAgICBicmVhazsKICAgIH0KCiAgICBzd2l0Y2goa2V5c1tpXSkgewogICAgICBjYXNlICJkZWZhdWx0VXNlciI6IAogICAgICAgIC8vaWYgKGRhdGFba2V5c1tpXV0gPT0gdHJ1ZSkgewogICAgICAgIG5ld0l0ZW1bInR5cGUiXSAgICAgPSAiaGlkZGVuIjsKICAgICAgICAvL30KICAgIH0KCgogICAgaWYgKHRkICE9IHVuZGVmaW5lZCkgewogICAgICB0ZC5pbm5lckhUTUwgPSAiIjsKICAgICAgdmFyIGVsZW1lbnQgPSBjcmVhdGVOZXdFbGVtZW50KG5ld0l0ZW0pCiAgICAgIC8vY29uc29sZS5sb2coZWxlbWVudCk7CiAgICAgIHRkLmFwcGVuZENoaWxkKGVsZW1lbnQpOwogICAgfQoKCiAgfQoKCiAgaWYgKGRlZmF1bHRVc2VyID09IHRydWUpIHsKICAgIHNob3dFbGVtZW50KCJkZWxldGVVc2VyRGV0YWlsIiwgZmFsc2UpCiAgfSBlbHNlIHsKICAgIHNob3dFbGVtZW50KCJkZWxldGVVc2VyRGV0YWlsIiwgdHJ1ZSkKICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJkZWxldGVVc2VyRGV0YWlsIikuY2xhc3NOYW1lID0gImRlbGV0ZSI7CiAgfQoKfQoKZnVuY3Rpb24gc2F2ZVVzZXJEZXRhaWwodXNlcklELCBkZWxldGVVc2VyKSB7CgogIHZhciBpbnB1dHMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidXNlci1kZXRhaWwtdGFibGUiKS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiSU5QVVQiKTsKCiAgdmFyIG5ld1VzZXJEYXRhID0gbmV3IE9iamVjdCgpOwogIGZvciAodmFyIGkgPSAwOyBpIDwgaW5wdXRzLmxlbmd0aDsgaSsrKSB7CiAgICBzd2l0Y2goaW5wdXRzW2ldLnR5cGUpIHsKICAgICAgY2FzZSAiY2hlY2tib3giOiAgbmV3VXNlckRhdGFbaW5wdXRzW2ldLm5hbWVdID0gaW5wdXRzW2ldLmNoZWNrZWQ7IGJyZWFrOwogICAgICBkZWZhdWx0OiAgICAgICAgICBuZXdVc2VyRGF0YVtpbnB1dHNbaV0ubmFtZV0gPSBpbnB1dHNbaV0udmFsdWU7IGJyZWFrOwogICAgfQogICAgCiAgICBpZiAoaW5wdXRzWyJ1c2VybmFtZSJdLnZhbHVlLmxlbmd0aCA9PSAwKSB7CiAgICAgIGlucHV0c1sidXNlcm5hbWUiXS5zdHlsZS5ib3JkZXIgPSAic29saWQgMXB4IHJlZCI7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBzd2l0Y2godXNlcklEKSB7CiAgICAgIGNhc2UgIjAiOiAKICAgICAgICBpZiAoaW5wdXRzWyJwYXNzd29yZCJdLnZhbHVlLmxlbmd0aCA9PSAwKSB7CiAgICAgICAgICBjb25zb2xlLmxvZyhpbnB1dHNbInBhc3N3b3JkIl0udmFsdWUubGVuZ3RoKTsKICAgICAgICAgIGlucHV0c1sicGFzc3dvcmQiXS5zdHlsZS5ib3JkZXIgPSAic29saWQgMXB4IHJlZCI7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICB9CgogICAgaWYgKGlucHV0c1sicGFzc3dvcmQiXS52YWx1ZS5sZW5ndGggPiAwKSB7CiAgICAgIGlmIChpbnB1dHNbInBhc3N3b3JkIl0udmFsdWUgIT0gaW5wdXRzWyJjb25maXJtIl0udmFsdWUpIHsKICAgICAgICBpbnB1dHNbInBhc3N3b3JkIl0uc3R5bGUuYm9yZGVyID0gInNvbGlkIDFweCByZWQiOwogICAgICAgIGlucHV0c1siY29uZmlybSJdLnN0eWxlLmJvcmRlciA9ICJzb2xpZCAxcHggcmVkIjsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgIH0KICAgIAogIH0KCiAgdmFyIGRhdGEgPSBuZXcgT2JqZWN0KCk7CiAgCiAgc3dpdGNoKHVzZXJJRCkgewogICAgY2FzZSAiMCI6CiAgICAgIC8vZGF0YSA9IG5ld1VzZXJEYXRhCiAgICAgIGRhdGFbInVzZXJEYXRhIl0gID0gbmV3VXNlckRhdGEKICAgICAgZGF0YVsiY21kIl0gICAgICAgPSAic2F2ZU5ld1VzZXIiOyBicmVhazsKICAgIAogICAgZGVmYXVsdDogIAogICAgICB2YXIgdGhpc1VzZXIgICAgICA9IG5ldyBPYmplY3QoKTsKICAgICAgCiAgICAgIGlmIChkZWxldGVVc2VyID09IHRydWUpIHsKICAgICAgICBpZiAoY29uZmlybSgnRGVsZXRlIHRoZSBzZWxlY3RlZCB1c2VyPycpKSB7CiAgICAgICAgICBkYXRhWyJkZWxldGVVc2VyIl0gPSB0cnVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzaG93RWxlbWVudCgicG9wdXAiLCBmYWxzZSk7CiAgICAgICAgICByZXR1cm4KICAgICAgICB9CiAgICAgIH0KICAgICAgCiAgICAgIHRoaXNVc2VyW3VzZXJJRF0gID0gbmV3VXNlckRhdGE7CgogICAgICBkYXRhWyJ1c2VyRGF0YSJdID0gdGhpc1VzZXI7CiAgICAgIGRhdGFbImNtZCJdID0gInNhdmVVc2VyRGF0YSI7IGJyZWFrOwogIH0KICAKICB4VGVWZShkYXRhKTsKICAvL2NyZWF0ZVVzZXJzVGFibGUoKQogIHNob3dFbGVtZW50KCJwb3B1cCIsIGZhbHNlKTsKfQoKCg==" - webUI["html/.DS_Store"] = "AAAAAUJ1ZDEAABgAAAAIAAAAGAAAABALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAQAAAABAAAQAHNwYmxvYgAAAMticAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAgLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAACAAAAABAAAAQAAAAAEAAACAAAAAAQAAAQAAAAABAAACAAAAAAEAAAQAAAAAAAAAAAEAABAAAAAAAQAAIAAAAAABAABAAAAAAAEAAIAAAAAAAQABAAAAAAABAAIAAAAAAAEABAAAAAAAAQAIAAAAAAABABAAAAAAAAEAIAAAAAAAAQBAAAAAAAABAIAAAAAAAAEBAAAAAAAAAQIAAAAAAAABBAAAAAAAAAEIAAAAAAAAARAAAAAAAAABIAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEERFNEQgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAgAAAAYAAAAAAAAAABAAAAgAAAAAEAAAEAAAAAAQAAAgAAAAABAAAEAAAAAAEAAAgAAAAAAAAAAAEAACAAAAAAAQAAQAAAAAABAACAAAAAAAEAAQAAAAAAAQACAAAAAAABAAQAAAAAAAEACAAAAAAAAQAQAAAAAAABACAAAAAAAAEAQAAAAAAAAQCAAAAAAAABAQAAAAAAAAECAAAAAAAAAQQAAAAAAAABCAAAAAAAAAEQAAAAAAAAASAAAAAAAAABQAAAAAAAAABpZWTUGRobHB0MHw1VaW5kZXhZYXNjZW5kaW5nVXdpZHRoV3Zpc2libGUQBwkRASwI1BkaGxwiDSQNEAgIEMgI1BkaGxwnDSkNEAIIELUI1BkaGxwsDS4MEAMIEGEJ1BkaGxwxDDMNEAUJEGQI1BkaGxw2DDgMEAQJEHMJ1BkaGxw7DD0NEAYJEEsI1BkaGxxADEIMEAAJEQK+CdQZGhscCw0pDAgJIwAAAAAAAAAAI0AoAAAAAAAAVG5hbWUjQDAAAAAAAAAJAAgAHQAyAEQAWABgAHIAewCNAJgAoQC0ALYAtwC4AMsA1ADjAO8A9AD6AP8BBwEMARkBIgEoATIBOAFAAUIBQwFGAUcBUAFSAVMBVQFWAV8BYQFiAWQBZQFuAXABcQFzAXQBfQF/AYABggGDAYwBjgGPAZEBkgGbAZ0BngGgAaEBqgGsAa0BsAGxAboBuwG8AcUBzgHTAdwAAAAAAAACAQAAAAAAAABMAAAAAAAAAAAAAAAAAAAB3QAAAAMAaQBtAGd2U3JubG9uZwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + webUI["html/img/x_white.png"] = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA6ppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0xMS0xNVQxNzoxMToyNTwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6Q29tcHJlc3Npb24+NTwvdGlmZjpDb21wcmVzc2lvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MTQ0PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xNDQ8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4yNTY8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFj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" webUI["html/img/xmltv.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0wNy0yOFQyMDowNzozMzwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Co6j9bsAAAGgSURBVGgF7VqxTsNADL0gYGEon8DOwsbAAH8BYmJn6cYIn8DC3h0+oixISFRiYYCJL0AwMMBAeK5w2rpV6uikxHfYknW98+vds18TK21DWGBlWR7CH+BfcEv2AzLP8HP42gLqkyUATuEp2PWEdQjF9ATs1zF/g29Mrxt+vVcUxR3xWxEktzFPJQmivsv8ZSI9DiQyVnxlIonwn6fpiczXpNuVVXH8O+a3Ys3y9NUyuf/NTTbEHZTjUlGSRzSiPhroUIENwB4AS/vS/susDwDhTpYBER9g7wHh5DWyibV9CiitCZbIafDEYUuJHQI3Nr/9ciWsjK6IFSWYhyvClbAyZqOIlYJG84jq7E1Ot97Zm+TinV1TrWwudk9EI3ebGFekzWprzspGEU2ySWCiOrs/s9dr7M/s9fVJJJrNXcsTsfaJc0WsKZINH+/sf1Jqvl1n1f2ZnStRN/pdq646XcSkIh9dkIg4s+IrE3nCpp8RG7f91ns+cCYR/LD4jcAZB42PN+A7/mcQ8ZxJhBYQvMJwBB/BKTFLVoLMC/wCfgyv7BesTKUC2LKM3wAAAABJRU5ErkJggg==" - webUI["html/js/network_ts.js"] = "dmFyIFNlcnZlciA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIFNlcnZlcihjbWQpIHsKICAgICAgICB0aGlzLmNtZCA9IGNtZDsKICAgIH0KICAgIFNlcnZlci5wcm90b3R5cGUucmVxdWVzdCA9IGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgICAgaWYgKFNFUlZFUl9DT05ORUNUSU9OID09IHRydWUpIHsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBTRVJWRVJfQ09OTkVDVElPTiA9IHRydWU7CiAgICAgICAgY29uc29sZS5sb2coZGF0YSk7CiAgICAgICAgaWYgKHRoaXMuY21kICE9ICJ1cGRhdGVMb2ciKSB7CiAgICAgICAgICAgIHNob3dFbGVtZW50KCJsb2FkaW5nIiwgdHJ1ZSk7CiAgICAgICAgICAgIFVORE8gPSBuZXcgT2JqZWN0KCk7CiAgICAgICAgfQogICAgICAgIHN3aXRjaCAod2luZG93LmxvY2F0aW9uLnByb3RvY29sKSB7CiAgICAgICAgICAgIGNhc2UgImh0dHA6IjoKICAgICAgICAgICAgICAgIHRoaXMucHJvdG9jb2wgPSAid3M6Ly8iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImh0dHBzOiI6CiAgICAgICAgICAgICAgICB0aGlzLnByb3RvY29sID0gIndzczovLyI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdmFyIHVybCA9IHRoaXMucHJvdG9jb2wgKyB3aW5kb3cubG9jYXRpb24uaG9zdG5hbWUgKyAiOiIgKyB3aW5kb3cubG9jYXRpb24ucG9ydCArICIvZGF0YS8iICsgIj9Ub2tlbj0iICsgZ2V0Q29va2llKCJUb2tlbiIpOwogICAgICAgIGRhdGFbImNtZCJdID0gdGhpcy5jbWQ7CiAgICAgICAgdmFyIHdzID0gbmV3IFdlYlNvY2tldCh1cmwpOwogICAgICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgV1NfQVZBSUxBQkxFID0gdHJ1ZTsKICAgICAgICAgICAgY29uc29sZS5sb2coIlJFUVVFU1QgKEpTKToiKTsKICAgICAgICAgICAgY29uc29sZS5sb2coZGF0YSk7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKCJSRVFVRVNUOiAoSlNPTikiKTsKICAgICAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoZGF0YSkpOwogICAgICAgICAgICB0aGlzLnNlbmQoSlNPTi5zdHJpbmdpZnkoZGF0YSkpOwogICAgICAgIH07CiAgICAgICAgd3Mub25lcnJvciA9IGZ1bmN0aW9uIChlKSB7CiAgICAgICAgICAgIGNvbnNvbGUubG9nKCJObyB3ZWJzb2NrZXQgY29ubmVjdGlvbiB0byB4VGVWZSBjb3VsZCBiZSBlc3RhYmxpc2hlZC4gQ2hlY2sgeW91ciBuZXR3b3JrIGNvbmZpZ3VyYXRpb24uIik7CiAgICAgICAgICAgIFNFUlZFUl9DT05ORUNUSU9OID0gZmFsc2U7CiAgICAgICAgICAgIGlmIChXU19BVkFJTEFCTEUgPT0gZmFsc2UpIHsKICAgICAgICAgICAgICAgIGFsZXJ0KCJObyB3ZWJzb2NrZXQgY29ubmVjdGlvbiB0byB4VGVWZSBjb3VsZCBiZSBlc3RhYmxpc2hlZC4gQ2hlY2sgeW91ciBuZXR3b3JrIGNvbmZpZ3VyYXRpb24uIik7CiAgICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIHdzLm9ubWVzc2FnZSA9IGZ1bmN0aW9uIChlKSB7CiAgICAgICAgICAgIFNFUlZFUl9DT05ORUNUSU9OID0gZmFsc2U7CiAgICAgICAgICAgIHNob3dFbGVtZW50KCJsb2FkaW5nIiwgZmFsc2UpOwogICAgICAgICAgICBjb25zb2xlLmxvZygiUkVTUE9OU0U6Iik7CiAgICAgICAgICAgIHZhciByZXNwb25zZSA9IEpTT04ucGFyc2UoZS5kYXRhKTsKICAgICAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2UpOwogICAgICAgICAgICBpZiAocmVzcG9uc2UuaGFzT3duUHJvcGVydHkoInRva2VuIikpIHsKICAgICAgICAgICAgICAgIGRvY3VtZW50LmNvb2tpZSA9ICJUb2tlbj0iICsgcmVzcG9uc2VbInRva2VuIl07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJlc3BvbnNlWyJzdGF0dXMiXSA9PSBmYWxzZSkgewogICAgICAgICAgICAgICAgYWxlcnQocmVzcG9uc2VbImVyciJdKTsKICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5oYXNPd25Qcm9wZXJ0eSgicmVsb2FkIikpIHsKICAgICAgICAgICAgICAgICAgICBsb2NhdGlvbi5yZWxvYWQoKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocmVzcG9uc2UuaGFzT3duUHJvcGVydHkoImxvZ29VUkwiKSkgewogICAgICAgICAgICAgICAgdmFyIGRpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJjaGFubmVsLWljb24iKTsKICAgICAgICAgICAgICAgIGRpdi52YWx1ZSA9IHJlc3BvbnNlWyJsb2dvVVJMIl07CiAgICAgICAgICAgICAgICBkaXYuY2xhc3NOYW1lID0gImNoYW5nZWQiOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN3aXRjaCAoZGF0YVsiY21kIl0pIHsKICAgICAgICAgICAgICAgIGNhc2UgInVwZGF0ZUxvZyI6CiAgICAgICAgICAgICAgICAgICAgU0VSVkVSWyJsb2ciXSA9IHJlc3BvbnNlWyJsb2ciXTsKICAgICAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImNvbnRlbnRfbG9nIikpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc2hvd0xvZ3MoZmFsc2UpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgIFNFUlZFUiA9IG5ldyBPYmplY3QoKTsKICAgICAgICAgICAgICAgICAgICBTRVJWRVIgPSByZXNwb25zZTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocmVzcG9uc2UuaGFzT3duUHJvcGVydHkoIm9wZW5NZW51IikpIHsKICAgICAgICAgICAgICAgIHZhciBtZW51ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocmVzcG9uc2VbIm9wZW5NZW51Il0pOwogICAgICAgICAgICAgICAgbWVudS5jbGljaygpOwogICAgICAgICAgICAgICAgc2hvd0VsZW1lbnQoInBvcHVwIiwgZmFsc2UpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChyZXNwb25zZS5oYXNPd25Qcm9wZXJ0eSgib3BlbkxpbmsiKSkgewogICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uID0gcmVzcG9uc2VbIm9wZW5MaW5rIl07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KCJhbGVydCIpKSB7CiAgICAgICAgICAgICAgICBhbGVydChyZXNwb25zZVsiYWxlcnQiXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KCJyZWxvYWQiKSkgewogICAgICAgICAgICAgICAgbG9jYXRpb24ucmVsb2FkKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KCJ3aXphcmQiKSkgewogICAgICAgICAgICAgICAgY3JlYXRlTGF5b3V0KCk7CiAgICAgICAgICAgICAgICBjb25maWd1cmF0aW9uV2l6YXJkW3Jlc3BvbnNlWyJ3aXphcmQiXV0uY3JlYXRlV2l6YXJkKCk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY3JlYXRlTGF5b3V0KCk7CiAgICAgICAgfTsKICAgIH07CiAgICByZXR1cm4gU2VydmVyOwp9KCkpOwpmdW5jdGlvbiBnZXRDb29raWUobmFtZSkgewogICAgdmFyIHZhbHVlID0gIjsgIiArIGRvY3VtZW50LmNvb2tpZTsKICAgIHZhciBwYXJ0cyA9IHZhbHVlLnNwbGl0KCI7ICIgKyBuYW1lICsgIj0iKTsKICAgIGlmIChwYXJ0cy5sZW5ndGggPT0gMikKICAgICAgICByZXR1cm4gcGFydHMucG9wKCkuc3BsaXQoIjsiKS5zaGlmdCgpOwp9Cg==" - webUI["html/login.html"] = "PCFkb2N0eXBlIGh0bWw+CjxodG1sPgogIDxoZWFkPgogICAgPG1ldGEgY2hhcnNldD0idXRmLTgiPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiIC8+IAogICAgPHRpdGxlPnhUZVZlPC90aXRsZT4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL3NjcmVlbi5jc3MiIHR5cGU9InRleHQvY3NzIj4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL2Jhc2UuY3NzIiB0eXBlPSJ0ZXh0L2NzcyI+CiAgICA8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvbmV0d29ya190cy5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvYXV0aGVudGljYXRpb25fdHMuanMiPjwvc2NyaXB0PgogIDwvaGVhZD4KCiAgICA8Ym9keT4KICAgICAgICAgIAogICAgICA8ZGl2IGlkPSJoZWFkZXIiIGNsYXNzPSJpbWdDZW50ZXIiPjwvZGl2PgoKICAgICAgPGRpdiBpZD0iYm94Ij4KCiAgICAgICAgPGRpdiBpZD0iaGVhZGxpbmUiPgogICAgICAgICAgPGgxIGlkPSJoZWFkLXRleHQiIGNsYXNzPSJjZW50ZXIiPnt7LmxvZ2luLmhlYWRsaW5lfX08L2gxPgogICAgICAgIDwvZGl2PgoKICAgICAgICA8cCBpZD0iZXJyIiBjbGFzcz0iZXJyb3JNc2cgY2VudGVyIj57ey5hdXRoZW50aWNhdGlvbkVycn19PC9wPgoKICAgICAgICA8ZGl2IGlkPSJjb250ZW50Ij4KCiAgICAgICAgICAgIDxmb3JtIGlkPSJhdXRoZW50aWNhdGlvbiIgYWN0aW9uPSIiIG1ldGhvZD0icG9zdCI+CgogICAgICAgICAgICAgIDxoNT57ey5sb2dpbi51c2VybmFtZS50aXRsZX19OjwvaDU+CiAgICAgICAgICAgICAgPGlucHV0IGlkPSJ1c2VybmFtZSIgdHlwZT0idGV4dCIgbmFtZT0idXNlcm5hbWUiIHBsYWNlaG9sZGVyPSJVc2VybmFtZSIgdmFsdWU9IiI+CiAgICAgICAgICAgICAgPGg1Pnt7LmxvZ2luLnBhc3N3b3JkLnRpdGxlfX06PC9oNT4KICAgICAgICAgICAgICA8aW5wdXQgaWQ9InBhc3N3b3JkIiB0eXBlPSJwYXNzd29yZCIgbmFtZT0icGFzc3dvcmQiIHBsYWNlaG9sZGVyPSJQYXNzd29yZCIgdmFsdWU9IiI+CgogICAgICAgICAgICA8L2Zvcm0+CgogICAgICAgIDwvZGl2PgoKICAgICAgICA8ZGl2IGlkPSJib3gtZm9vdGVyIj4KICAgICAgICAgIDxpbnB1dCBpZD0ic3VibWl0IiBjbGFzcz0iIiB0eXBlPSJidXR0b24iIHZhbHVlPSJ7ey5idXR0b24ubG9naW59fSIgb25jbGljaz0iamF2YXNjcmlwdDogbG9naW4oKTsiPgogICAgICAgIDwvZGl2PgogICAgICAgIAogICAgICA8L2Rpdj4KCiAgICA8L2JvZHk+CiAgICAKPC9odG1sPg==" - webUI["html/img/mapping.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0wOC0wMlQxMjowODo5NzwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CpRxQsEAAAJLSURBVGgF7VoxTgMxEMwBHWlAaeABVCEtBcoD+EBewCdCyQsQtLyAPCBvCBSRIBUPCF1ogqBJjlkrezGr6HTrO98lhy1Z9trr2VmvnbMNjUadUhzHLeQB8hw5LS3QOUbubvIf7X3kKXIZibgS51bCZdWgMT6D8nECgArkngagQN0B8dhbkblalVmLIyheCGUthhjuLBq77MihA0xTjHHBEBBOorHLjjghbNOg4Mg2RYO4hIiEiHiaAV5aSwf8hRgjZdHtTTTc2ZFXpZkY+hMx5k3IZYlr7jgudJHp2JElLaF0K1mirYn8nAWgQB3ibM59ERNCA52d6Nghv9isQiUtn0kURe92I9eBcYA6YZxym8dyDuwRuMw82gjQYQbsPdLDdNCROO0US3uEfp3usTZpjf5J2CNtNFwjl7FHvmBnCB5PCQkQoJudJtGvE23sJEFuI39rQArS7dskXK6nlwkAKiB1VxAxLcyUePAH8cQmlbEul4+UM8LkVjPc2ZHcaFUDBEeqjoC0HyIiZ6RqOUSk6ghI+xyRD9mRQTYfIktPylaX16rhzo48KE29QH8kxjxC/hFtZYiGe70OjWVMW7Dx32bA3iO7//iAC8DOPweZFQhH6O+CmkRvW2f28oV8owEoUHdMPPg70rFJZajTkqT7uZ3ObaHEuuHOjnCpsb8vlKUsur2JhruLA94Y5QEOjuSZPR9jQ0R8zGoezNpFhN5RtUm+/bpgaG1u0jd2OSLDTRopbZ/okxcrLUYKvKprbRfHhXr8m5PK/y1V/gWRKLfiNSmxEAAAAABJRU5ErkJggg==" - webUI["html/img/logo_w_600x200.png"] = "iVBORw0KGgoAAAANSUhEUgAAAlgAAADICAYAAAA0n5+2AAAAAXNSR0IArs4c6QAAAAlwSFlzAAAuIwAALiMBeKU/dgAABCZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjMwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MzAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NjAwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4yMDA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAg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" - webUI["html/img/stream-limit.jpg"] = "/9j/4AAQSkZJRgABAQAAAQABAAD/4gJoSUNDX1BST0ZJTEUAAQEAAAJYbGNtcwQwAABtbnRyUkdCIFhZWiAH4wAFABcAFgAuAAphY3NwQVBQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtkZXNjAAABCAAAAEBjcHJ0AAABSAAAAE53dHB0AAABmAAAABRjaGFkAAABrAAAACxyWFlaAAAB2AAAABRiWFlaAAAB7AAAABRnWFlaAAACAAAAABRyVFJDAAACFAAAACBnVFJDAAACFAAAACBiVFJDAAACFAAAACBjaHJtAAACNAAAACRtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACQAAAAcAHMAUgBHAEIAIABJAEUAQwA2ADEAOQA2ADYALQAyAC4AMQAAbWx1YwAAAAAAAAABAAAADGVuVVMAAAAyAAAAHABOAG8AIABjAG8AcAB5AHIAaQBnAGgAdAAsACAAdQBzAGUAIABmAHIAZQBlAGwAeQAAAABYWVogAAAAAAAA9tYAAQAAAADTLXNmMzIAAAAAAAEMSgAABeP///MqAAAHmwAA/Yf///ui///9owAAA9gAAMCUWFlaIAAAAAAAAG+UAAA47gAAA5BYWVogAAAAAAAAJJ0AAA+DAAC2vlhZWiAAAAAAAABipQAAt5AAABjecGFyYQAAAAAAAwAAAAJmZgAA8qcAAA1ZAAAT0AAACltjaHJtAAAAAAADAAAAAKPXAABUewAATM0AAJmaAAAmZgAAD1z/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAQ4B4ADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD/AD/6KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD9PvBf/AARa/wCCrXxF8HeE/iD4G/YM/aL8UeCfHfhrQvGXg/xNpHgia50nxF4W8T6Xa634f13TLkTgXGn6vpN9aahZTgAS21xFIAN1dL/w4o/4LB/9I7/2m/8AwgZ//kiv9b3/AIJp/wDKOX9gH/syf9lX/wBUV4Dr7YoA/wAWr/hxR/wWD/6R3/tN/wDhAz//ACRR/wAOKP8AgsH/ANI7/wBpv/wgZ/8A5Ir/AGlaKAP8Wr/hxR/wWD/6R3/tN/8AhAz/APyRR/w4o/4LB/8ASO/9pv8A8IGf/wCSK/2laKAP8Wr/AIcUf8Fg/wDpHf8AtN/+EDP/APJFH/Dij/gsH/0jv/ab/wDCBn/+SK/2laKAP8Wr/hxR/wAFg/8ApHf+03/4QM//AMkUf8OKP+Cwf/SO/wDab/8ACBn/APkiv9pWigD/ABav+HFH/BYP/pHf+03/AOEDP/8AJFH/AA4o/wCCwf8A0jv/AGm//CBn/wDkiv8AaVooA/xav+HFH/BYP/pHf+03/wCEDP8A/JFH/Dij/gsH/wBI7/2m/wDwgZ//AJIr/aVooA/xav8AhxR/wWD/AOkd/wC03/4QM/8A8kUf8OKP+Cwf/SO/9pv/AMIGf/5Ir/aVooA/xav+HFH/AAWD/wCkd/7Tf/hAz/8AyRR/w4o/4LB/9I7/ANpv/wAIGf8A+SK/2laKAP8AFq/4cUf8Fg/+kd/7Tf8A4QM//wAkUf8ADij/AILB/wDSO/8Aab/8IGf/AOSK/wBpWigD/Fq/4cUf8Fg/+kd/7Tf/AIQM/wD8kUf8OKP+Cwf/AEjv/ab/APCBn/8Akiv9pWigD/Fq/wCHFH/BYP8A6R3/ALTf/hAz/wDyRR/w4o/4LB/9I7/2m/8AwgZ//kiv9pWigD/E88f/APBGT/gqj8K/AnjT4nfEX9hL9ofwf8P/AIdeFPEPjnxz4t1zwTNaaL4X8IeE9Ju9d8SeIdXujORbaZo2j2F5qN9OQRDa20shB24r8yq/28f+Ctf/ACit/wCClX/ZhH7Xv/rP/wAQK/xDqACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA+j/ANmj9kL9pr9snxbrvgL9lr4K+Ovjn408M+HH8X6/4Y+H2ljWdZ0vwvFqen6NLr1zYrNHMNMh1XVtL0+a7RWihu9RsoZSj3MIf7U/4cUf8Fg/+kd/7Tf/AIQM/wD8kV2v/BAD9sj/AIYi/wCCrf7K/wATNW1X+yvh98QPFw+AHxWklm+z6f8A8IJ8aWg8HjU9Xl3Ls0rwd4wufCPxAuz82B4RQlJACjf7MFAH+LV/w4o/4LB/9I7/ANpv/wAIGf8A+SKP+HFH/BYP/pHf+03/AOEDP/8AJFf7StFAH+LV/wAOKP8AgsH/ANI7/wBpv/wgZ/8A5Io/4cUf8Fg/+kd/7Tf/AIQM/wD8kV/tK0UAf4tX/Dij/gsH/wBI7/2m/wDwgZ//AJIo/wCHFH/BYP8A6R3/ALTf/hAz/wDyRX+0rRQB/gx/HT4CfGb9mT4n+Ivgt+0B8NfFnwj+K3hJNHl8SeA/G2lzaP4i0iLxBomneI9Emu7KbJWLU9C1bTtTs5UZ45rW7idWySB5HX9yX/B69+yL/wAIr8eP2V/22/D2meXpfxb8Da18BfiPd2sOy3i8afDG9k8U+BdR1OXbiXVPFHg/xZrukWzB2P8AZnw0jjZIxEjS/wANtABRRRQAUUUUAFFFFABRRRQAUUUUAPRHldIokeSSR1SONFLu7uQqIiKCzOzEKqqCWJAAJNfq8n/BCv8A4LBSIki/8E7/ANp3a6q67vh/dI21gGG5HnV0bB5V1VlPDAEEVv8A/BBj9kX/AIbU/wCCrf7Ivwo1PTP7T8DeGPiFb/Gz4nRTQ+fpzeAvgpE3xDv9L1hQrEaZ4w1nRdD8BSkAFp/FdvH5kO/zo/8AZ4oA/wAWr/hxR/wWD/6R3/tN/wDhAz//ACRR/wAOKP8AgsH/ANI7/wBpv/wgZ/8A5Ir/AGlaKAP8Wr/hxR/wWD/6R3/tN/8AhAz/APyRR/w4o/4LB/8ASO/9pv8A8IGf/wCSK/2laKAP8Wr/AIcUf8Fg/wDpHf8AtN/+EDP/APJFH/Dij/gsH/0jv/ab/wDCBn/+SK/2laKAP8Kz9p39iX9rL9i7UfCOkftV/AT4ifAfVPHtlq+o+DtO+IejjRb3xDp+gz2Ntq97p1s00k0lrY3GpWUEs7IkbSz+XGztHKI/lqv6F/8Ag5+/bI/4a5/4K2/HDTNF1X+0fh7+y5aaZ+y74KEU261GofDq61K8+KVz5UbG3N0fi9r3jnSTexl5bzSdE0USybLeCGD+eigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD/cg/4Jp/8o5f2Af+zJ/2Vf8A1RXgOvtivif/AIJp/wDKOX9gH/syf9lX/wBUV4Dr7YoAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD8+P8AgrX/AMorf+ClX/ZhH7Xv/rP/AMQK/wAQ6v8Abx/4K1/8orf+ClX/AGYR+17/AOs//ECv8Q6gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAHI7xOkkbtHJGyvHIjFHR0IZXRlIZWVgGVlIIIBBBFf7Z//BIH9sRP28f+Cbv7J37St5qS6n4x8VfC/TPDXxTmMqvc/wDC3PhxNcfD/wCJdxdQ5Mtp/bPi7w3qfiLT7e4zK2jazplyHnhuIrib/Eur/QW/4Mm/2yPteh/tZfsE+JNV3T6PeaT+1D8KNPml3yNp2pDRvht8YrW381t0NrYahB8JtRtLK33Rtda5r980cUjzyzgH98VFFFABRRRQAUUUUAfhR/wcifsif8Ngf8Eif2ndD0vTP7T8dfAvSbH9p74ehYvPuINW+DCXur+MUs4FUzXF/qvwjvfiRoFhb25E819q9skazn/R5v8AHer/AH6NW0rTdd0rU9D1mxtdU0fWdPvNK1bTL6FLmy1HTdRtpLS+sby3kDRz2t3azS29xDIrJLFI6OCrEV/hv/8ABQv9lrUv2J/23/2ov2V9Riuo4Pgv8Y/GHhbwzPe7/tWqeAJdQbWfhrr83mfPu8R/D7VPDOvjcWO3Uh88n32APjeiiigAooooAKKKKACiiigAooooA/0D/wDgyU/ZE+z6T+19+3Xr+mYl1G70D9lz4Y6lJFtdbSwTSfif8YfKaRd0lvd3Vz8HreC4g2xifS9VtneSRHSD++mvyl/4Ih/sif8ADEf/AAS3/ZB+B2o6X/ZXjV/hhYfE/wCKEEsPlahH8S/jDNN8SfFmmaq21WnvfCl14ki8EpKw+Ww8M2MCExQxmv1aoAKKKKACiiigAr5A/b+/ao0X9iP9iv8AaZ/as1xrRk+Cfwi8V+LdCsr5gtrrfjk2R0j4c+GZWLKF/wCEq8f6n4a8NodwxJqqdeh+v6/ib/4PTP2yP+EA/Za/Z5/Yk8N6r5WvftCfEG7+LPxGtLWb98nww+Dogh8OaVqtvuA+weKviT4g03W9Nk2uWvvhfdrujEZEoB/nB+IfEGteLPEGueKvEup3eteIvE2san4g1/WL+Uz32ra1rN7PqOq6nezNzNd399cz3VzKeZJpXc8mseiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD/cg/4Jp/8AKOX9gH/syf8AZV/9UV4Dr7Yr4n/4Jp/8o5f2Af8Asyf9lX/1RXgOvtigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAPz4/4K1/8orf+ClX/AGYR+17/AOs//ECv8Q6v9vH/AIK1/wDKK3/gpV/2YR+17/6z/wDECv8AEOoAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAr9V/+CJP7ZH/DCn/BT39k348anqv9leA2+Itp8Mvi1NNN5Onp8LPi3FJ8P/F+qaou5RPaeEbfXYPHcMLMB/aXhXT5R80Sg/lRRQB/v8UV+TP/AAQ5/bI/4bo/4JdfsnfG7VNV/tXx9p/w+tfhN8WpZZvO1Fvid8IJG8A+JNV1f5m8u/8AGUWi6d8QFjDECx8W2TgRh/LT9ZqACiiigAooooAK/wA07/g9I/ZE/wCFcftj/AD9sXQNM8jQP2lfhZdfD7xtd28O5H+KPwOnsbO31HUp1A8q41z4a+KvBmkaXDN808HgPUnhZ1tplh/0sa/nd/4Oi/2RP+Gq/wDgkT8cNZ0fS/7R8dfsuapoP7T/AITMUO64TS/ACahpXxSVp0Bnjsbf4ReJvHOuz26hoLi+0HS2nQG3iuLcA/yKaKKKACiiigAooooAKKKKACv02/4I3fsi/wDDcf8AwUy/ZC/Z3vtM/tXwfr3xX0nxh8TrWSLfaS/Cr4XQ3PxJ+IlleyMGhto9d8L+FtQ8NWk04MbaprWn2yxzz3EUEv5k1/eL/wAGTH7In9reP/2uf259f0zdZ+D9A0H9mf4Z6hND5sEmveK7jTviL8VprV3Gy21LQ9E0b4YWSTwlp207xnqVsWhgnkS5AP8AQzooooAKKKKACiiigAr/AB3f+DkD9sj/AIbN/wCCtf7SWvaRqv8Aanw9+BGpWv7MPw1aOf7RaJovwcudR0zxfd2E6MYLnT9d+LV/8RfEWm3dsPJuNM1axZJJ1VbiX/Ux/wCCnv7XVn+wl+wF+1T+1TLdW1trXws+E2vXHgJbsRtBe/FTxOYPBnwo02aKQMJbe/8AiN4h8MW16qxysti9zN5UixMp/wAQK+vr3U7281LUru5v9R1C6uL6/vryaS5u729u5XuLq7uriZnlnubieR5p5pXaSWV2d2ZmJIBVooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA/sa/Z9/4PGv2mv2ffgJ8EPgJo37HXwJ8QaP8EPhD8NfhDpOv6n43+IFtqWt6b8NfBmi+DLHV9Qt7QfZbe+1K10WK9u4bb/R4riaSOH92q169/xG8ftWf9GRfs9/+F98R/8ACv4h6KAP7eP+I3j9qz/oyL9nv/wvviP/AIUf8RvH7Vn/AEZF+z3/AOF98R/8K/iHooA/t4/4jeP2rP8AoyL9nv8A8L74j/4Uf8RvH7Vn/RkX7Pf/AIX3xH/wr+IeigD+3j/iN4/as/6Mi/Z7/wDC++I/+FH/ABG8ftWf9GRfs9/+F98R/wDCv4h6KAP9GT/gmX/wdhftE/t2/t3fs3/skeLv2T/gt4E8N/G/xpf+F9W8XeHPGPjnUNb0O3tPCviHxCt1p9lqY+wXEzzaNFbslz8gimkYfOq1/cpX+NT/AMG73/KaX9gD/srmtf8AqtPHVf7K1ABRRRQAUUUUAFFFFAH8KH/BRT/g7X/aN/Yq/bf/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WOj6BoOn3Gq6xql5Jg+Xaafp1pcXdw+DshhdsHGKAP8AN2/4PR/2yP8AhY37XHwD/Yq8N6r53h/9m34dT/Er4g2dtNiP/hanxqFlcaTpmqW4Yh7rw38MdB8M6zpUzhWitviTqKICJmJ/itr6y/bt/ah179tX9sf9pP8Aaq8RG6juvjh8XfF/jbS7C9fzLjQfCN1qUln4D8LF98m6Lwl4IsvD/hm2Jkc/ZtJiBdj8x+TaACiiigAooooAK/2Hv+DZvSf7G/4Id/sIWe3Z53hv40atjGM/29+0r8Ztc3f8D/tHfnvuzzmv8eGv9kD/AINw7+HUv+CJ37A1xAqqkfw58c2DBOhm0r40fEvTLhj/ALb3FnKz/wC2WoA/biiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAr/JJ/4Ow/+U2X7Q//AGTv9nj/ANUr4Nr/AFtq/wAkn/g7D/5TZftD/wDZO/2eP/VK+DaAP5vaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKK6vwJ4G8W/E3xn4X+HngLQdQ8UeNPGmu6b4a8L+HtLi86/1fWtXuo7OwsrdCVRTLPKoeaZ47e3iD3FzLFBFJIt06dSrUhSpQnUq1Zwp06dOMp1KlSpOMKdOEIKUpznOcIQhGMpSlKMYpuST58Xi8LgMJisfjsTh8FgcDhsRjcbjcXXpYXCYPB4OhWxWLxeKxOIqUaGHw2Fw2GxGIxGIr1aVGhQoVq1WpTp0pzj9Y/sAfsT+O/27/wBofw38HvC32vSfCtqY/EXxU8cx2/nWvgfwDZ3MMep6gDIpgm13VHkTR/C2myZ+361dwPcCLSrTVL2z/wBHr4T/AAs8CfBD4beC/hL8MtAtPDHgPwBoNl4c8NaJZj5LWwskOZriZv3t7qV/cvPqOr6ndNJe6rqt3eal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gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAr+z7/ggp/wTT/4VH4Psf20vjV4f8r4n/ELRXX4K+HtVtsXPgT4d6zbFJvGk8E6brXxN8QbCXZpbIqz6X4Hn/17P4t1GysPyI/4Ip/8E13/AGxfjB/wuX4r6G837N3wa1q0m1S1voD9h+KPxAtlg1HSvAMXmL5V3oOmRyWmt+O8ear6bNpfh14h/wAJK95p/wDedHGkSJFEiRxxoscccahEjRAFRERQFVFUBVVQAoAAAAr+o/AXw29vUpcdZ3h/3FGclw3ha0NK1eDlTq5zOE1rTw8lOjlzaaniFXxkbxw+Hkf4Nfta/psf2Tg8d9FLwvzi2aZlh6E/GrPctxHv5dleIhRxeC8NsPiKFS8Mbm1KWFzPjSMKkZ4bKJZTw5VUKub5vRT6KKK/rU/55AooooAKKKr3d3a2Frc319c29lY2VvNd3l5dzR21raWttG01xc3NxMyQwW8EKPLNNK6RxRozuyqpIG0k22kkm220kkk2222kkkm220kk22km04xlOUYQjKc5yjCEIRlOc5zlGMIQhGMpSnKUoxjGMZSlKUYxjKUoxlYoqlpuo6frGn2Gr6TfWeqaVqlla6jpmp6fcw3un6jp99AlzZX1jeWzyW93Z3dtLHcW1zBJJDPDIksTsjqxu0k1JKUWnFpNNNNNNJppptNNNNNNpppptNNucJ0pzp1ITp1Kc506lOpCdOpTqU5zp1KdSnUjCpTqU6lOdOpTqQhOE4ThOEJwnCBRRRTJCiiigD8if+Cvv/BOiw/bq+A0ms+CNNtIv2i/hFZalrXwv1HENtN4u00p9q1z4X6pdvsRrXxCIRc+Gp7yRIdI8Vw2j/arDS9W8QPcf59Ooaff6Tf32larZXem6npl5c6fqWnX9vNZ31hf2Uz215ZXtpcJHPa3drcRyQXNvPGk0E0bxSIrqyj/AFjK/kJ/4L+/8E2P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/DSP/BUjUvgr4f1X7d4A/Y18AaL8IbSK3m87TpviZ4mSHx78VtVhBYmPULa61fw18PtYjCoEvPh1sCsVMsoB/LfRRRQAUUUUAFFFFABRRRQAUUUUAFf6lH/BsR/wW/h/bw+Ddn+xj+0n4qib9sH4C+E7ePwt4i1m7Vb/APaF+D2gQwWFp4kW4nYPqXxM8BWv2TS/H9u5k1LxFpA03x8kmp3U3jWXRP8ALXr0j4P/ABg+J3wA+J/gf4z/AAY8b6/8OPil8N/EFl4o8E+NvDF61jrWg61YMTFcW8oDxT288TzWWpabew3OmavplzeaVqtneabeXVrMAf72FFfzsf8ABCH/AIL2fCb/AIKr/DKw+GXxPvvDPwy/bk8CaKg8e/DJbqLTdK+K+nadbZuvil8HrW8nM9/pc8cL3fi7wbBJeav4DvTKZvtnhqfStbu/6J6ACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA+HP8Agp3/AMo1v+Chf/Zjn7WX/qhPH9f4dVf7iv8AwU7/AOUa3/BQv/sxz9rL/wBUJ4/r/DqoAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKtWNje6ne2em6bZ3WoajqF1b2NhYWNvLd3t9e3cqQWtnaWsCST3N1czyRw29vCjyzSukcaM7AFpNtJJttpJJNtttJJJJtttpJJNttJJtpOZzhThKpUlGEIRlOc5yjCEIQjKc5znOUIQhCEJznOc4QhCE5znGMZSj7x+y5+zX8Sf2t/jj4G+BHwr0/7V4l8ZaksdzqVxHK2keFPDtpifxB4v8AEM0SsbbRPD+nCW8uiM3F5MLbStOjudV1CxtLj/SQ/ZX/AGZ/ht+yJ8DPA/wH+Flh9n8O+D9PAvtWniiTV/F3iW8CzeIfGHiGWIYuNZ1+/wB9zMNxgsLUWej6ctvpWm2FrB+fv/BHj/gnDZfs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FABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRX+iL/wb7f8ABCH/AIJY/tyf8Eufgl+0f+0/+zPc/En4yeMPFvxm0vxD4tj+Nn7QHgxL+x8JfFfxZ4Z0CEeH/AXxT8MeGbT7DommWNmZLLRreW6MP2m8e4upJZ3AP87qiv8AXt/4hZ/+CF//AEZZe/8AiS37WX/z86/zu/8AgvN/wS9n/wCCWX7eXjL4WeEdM1OL9nP4pWsnxW/Zq1a+ub/VBF4A1e9mg1P4f3etahNeXeoa38LfEKXnhW4k1LUb7XdQ8Op4U8U6zL5/iiNnAPxWor239mfwf4e+IX7R/wCz/wCAPF1gdV8J+OPjb8KfB/ifSxd3tgdS8PeJvHeg6LrVgL7Tbi01GyN5pt7c24u7C7tb23MnnWtxDOkci/6wH/ELP/wQv/6Msvf/ABJb9rL/AOfnQB/kJUV+yP8AwX3/AGUPgJ+xH/wVT/aN/Zr/AGZfA7/Dn4L+AdJ+Cdz4U8ISeKPF/jJ9Ln8X/Ar4ceM/ELnxD4717xN4ovvt/iTX9W1ALqGtXaWguhZ2S29jBb20X43UAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRW74X0mLX/E3h3QppZIIda13SNJlniCtLDFqOoW9nJLGr/K0kazF0DfKWAB4zQBhUV/pDf8AEET+yX/0ex+0V/4RHw0/+R6/kG/4Lj/8Ez/AP/BKP9tHTf2X/hx8SvF/xV8PX3wU8DfFJ/E/jbTNF0rWU1HxZrvjTSLnS1tdCRLE2VpF4Xt5oJSPPd7qYSHaiUAfjlRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAEscE82fJhll243eXG8m3OcZ2g4zg4z1wakNleAEm0uQAMkmCUAAdSTs4Ar/AEFv+DGz/kUf+ClP/Yx/sn/+mz9oev7R/wBsv/k0D9qz/s2345/+qw8UUAf4TQBJAAJJIAAGSSeAAByST0FWfsN7/wA+d1/4Dy//ABFe8/sk/wDJ1f7Mv/ZwfwY/9WP4br/d1oA/wCpI5Im2SxvG+AdsisjYPQ7WAOD24plf01/8Hcf/ACmc+J3/AGRL4Cf+oUtfzKUAFFFFABRRRQBZWzu3UMtrcsrAMrLBKVYEZBBCkEEcgjgio5IJ4cedDLFuzt8yN492MZxuAzjIzjpketf7bH/BHz/lFH/wTb/7Mc/Zd/8AVNeD6/kr/wCD5n/kHf8ABMX/AK/f2yv/AER+yzQB/n7UUUUAFWFtLt1Dpa3DowyrLDIysPUMFII+hqvX+zb/AMG/P/KGb/gn1/2QyH/1LfFFAH+MxJbzwgGaCaIMcAyRugJ9AWUZP0qGv9Hn/g96/wCTXP2Hf+y+/Eb/ANV3a1/nDUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAV/rff8GoX/AChI/Zt/7Hz9on/1evjuv8kGv9b7/g1C/wCUJH7Nv/Y+ftE/+r18d0Af0dV+D3/Bw/8A8EwY/wDgpl+wB4v0XwRoKal+0r+z5/avxj/Z4mt4Fk1bXNX03Tf+K2+FNtIF82SH4qeGLP8AszT7ES29tL480nwHqF/MtnpMqtR/4L7/APBQXxh/wTL+GH7CH7U3h46jfeE9G/4KA+AvCHxo8I6fJtfx38FPFvwG/aGs/H3hwQtJFBcalaWsFp4r8KLdSLaW/jbw14avrkPBaSRv+4XgDx54P+KfgXwZ8TPh74g07xZ4C+IfhXw/438FeKNIm8/SvEfhTxTpVprnh/XNOmKqZLLVdKvrS9tnZUYwzpvRWyoAP8Mv9jiKWD9sX9laGaOSGaH9pf4HRSxSo0csUsfxR8LpJHJG4DJIjAq6MAysCCAQRX+7DX+ZZ/wXb/4Jef8ADEH/AAWj/ZY/aQ+GHh3+zv2c/wBs/wDai+Ffj3TotOtfK0jwL8coPit4Svfiz4JCQKYNOsvEN3qFv8SPC8D/AGSCSHxF4j0LRbMWHguZk/006AP8iL/g6k/5Tj/te/8AYC/Zu/8AWYvg/X8/GiaHrXibWdJ8OeG9I1TxB4h1/UrHRtC0HRNPu9W1nWtY1O5istN0nSdLsIri+1LUtQvJ4bSxsbOCa6u7maKC3iklkRD/AED/APB1J/ynH/a9/wCwF+zd/wCsxfB+v6cf+DR3/gkR4C+HfwE0v/gpx8b/AAfZa/8AGn4x3GvWP7N1t4j021vI/hX8JtI1C68O3vxB0K2vI3k07xx8TNYsdbtrTXliS9sPh1Zab/YN9HYeOdfiuwD+fT9kv/g0k/4KsftI+GtI8bfETSfhV+yX4a1m1W/tdM+PfiXW0+JklnKv+jvN8N/AvhzxbqWgXkjH9/o3jrUPB2tWUaubrTopfKgl+5PEP/Bkb+2LbaSZvCn7Z37NGta79mkcab4g8MfFHwxpJvArGKA61p2jeLbwW7sFV7r+wTJGpZls5SoVv7xv29/28v2ev+Cb/wCzd4r/AGn/ANpXX9R0jwL4fvLLQNG0bw/p39seL/HvjjWYL6bw74D8GaS09pb3viLXE02/mibUL/TNH0zTtP1LWtc1TTNG0y/vrf8AnO/ZU/4PHv2Gfj18c/DPwi+LPwP+LX7NXhnxt4gtvDfh34v+KvEHhfxl4N0q+1Fkt9In+IlroUVjqvg/S77UJI9Pn1fTofFWmaM88Goa5d6fokeparpwB/DF/wAFBv8Agij/AMFEv+CZ8A8RftKfBG4l+FUt3b2Np8dPhhqK/EL4Pve3lx9ksrLVvE2m21vf+C7/AFG6It9K074gaJ4S1DWJDjSrW9AYj8oq/wB83x14F8F/E7wd4m+HnxG8KeHvHXgPxpot/wCHPF3g7xZpFjr/AIa8S6Dqtu9rqOj63o2pwXNhqWn3tvI8Vxa3UEsUiNyuQCP8eH/gvh/wTBtv+CWX7fHiz4TeBotUm/Z9+Kei2/xi/Z7v9TklvLiw8E6/qF/Yav4BvdTkeZ77Uvhv4p07VvDcU93cTatqHhdfCniHVyt5rzbgD8UKKKKAPuL/AIJ/f8E9P2jv+CmHxw1T9nv9l7TvCOqfEbSPh7r3xOvLbxp4qtvCGkDwt4c1nw1oOpyx6rdW9zHJfLqHizSFhsxGHlie4lDAQEH9nv8AiEL/AOCyP/Qnfs+/+H10b/5UV6j/AMGZn/KWXx//ANmWfF//ANWj8Ca/1J6AP8XT/gnN/wAESv2+/wDgp9res/8ADPHw303RPhl4X1mbQPFPx6+KupX3g74O6TrNrcCC80fT9et9I1rWvGet2Q/faho3gTw74mv9IhktJdch0uLULCS5/aX4o/8ABlr/AMFF/CXgm88RfDj48fstfFvxVp+nvdyfD+11vx/4J1TWbpD/AMgrwzr3inwXF4YubyUYME3ijVPB+nE7hcX1uArP/YJ8Q/8Agvt/wQ+/Yk8UaV+y6P2m/hx4Th+HjjwhJ4U+Avwq8f8Ajr4YfDCGwDKdHfV/g54D17wNa/YLozWWoaL4VvNX1PR9TW6t9Z02wuY7jb+2fgDx/wCCfir4H8I/Ev4beKdE8b/D/wAe+HdI8W+DPGHhvUINV0DxL4a16xh1LR9a0jULZ3gu7HULG4huLeaNuUcBgrBlAB/hF/GH4HfF79n/AOLHi74F/Gf4d+Kfhz8XvAmvyeGPFXgDxJpk1p4g0zWVaPyLdLZPNTULbUoZ7a90TU9LlvdL17TLyx1XRby/02+tLqb+jL9jH/g0q/4Ke/tU+A9F+J/xD/4Vd+yR4T8R2Vlqmg6J8dNT8St8VdS0rUIvPttQm+G3g/w7r154WzHgzaR4/wBX8H+Jrdnj87QVRzIv+h3+1p+z9/wTF+D3xs0f/gqn+2R4f+DPgn4mfBDwLZ+A/D/x3+LGoRW2meHbW01TU9d8OyaL4evZpNK8Q/FS1ubvVLLwLqmn6HrPxGhgnk0bwgwbybdfMv2Qf+C9H/BK/wDbo+NkH7O/7Of7TcHiP4u6sNWl8IeFvFPw4+Kfw3Pj220OyfUdSk8Gap8QPBnhzSdWvYbCK5v4/Dsl7aeK7qwsdR1C10Gax0+9uYAD/Om/4KFf8Gyn/BSr/gnx8Mta+OGt6R8Of2ivg54Z+1Xni/xZ+ztq3i3xPrXgHQLWEzyeJ/HXgfxN4M8J+JNO8PW8Mc82r674dg8V6F4ctreW98R6rpVjsun/AJ46/wB+3UNPsNWsL3StVsrTU9M1O0udP1HTtQtobyw1CwvIXtryyvbO5SS3u7S7t5JILm2njkhnhkeKVGRmU/4lv/BXX9l3wl+xf/wUq/bF/Zq+H9ldaZ4A+G/xg1M+AdJvJmuJ9H8DeMtM0rx/4O0X7TIPNuoNH8N+KtM0y1u5y9zdWtrDcXMkk8kkjAHwl4C8AeOvip4y8N/Dr4ZeDfFHxC8f+MdWtdC8JeCfBWg6n4n8V+JtavW2WmlaF4f0W1vdU1XULhgRFaWVrNM4DME2qxH9RP7M3/Bnv/wVJ+NvhzTPFvxZ1j4E/ss6dqllDew+GPib4v1nxT8SYY7oCS2F94X+Gvh/xToGlym3IlurDV/Gmn6zp8rx2d9pUF4t3Baf1Gf8Gtv/AASH8A/sefsg+BP20vih4PstR/ax/aq8IWXjfTNa13TbWfU/hD8D/EsL3vgPwf4SluI5LrRdR8e+GbjTvG3j2+gNlf3w1nRvCV/AIPChlv8A9mv+Cm//AAVC/Zo/4JT/AABi+Ov7Rd7r+oyeItafwn8Mfhp4KsbfUvHXxN8YLYzajJpGiQ3tzY6VpemaXYQvqPiLxNruoWGj6NZ+RAJb3XNT0LRNXAP4efGn/Bkn+2rpuj3Fz8P/ANsD9mLxbrUVqZYNJ8UaL8UfA9nc3SqGNour6d4d8ctEr/MkNxLpqqz7POS3Rnkj/nE/b5/4JN/t4/8ABNLXLKx/av8AgZrXhTwnrV+NM8LfFrw1c23jP4QeK794JrqLTtK8faC1xpdlrk1tbXdzH4W8SDQfFhtLS5vToQsojcH/AEK/+CfH/B2f+xX+23+0T4M/Zs8c/CH4mfsxeLfil4htfCHwr8UeMdd8PeNfAnifxhrOo22meFfCGs6voNvpmpeFPEHi29u4NP0VrvRb7w6dWki0298RWkl1ZyXP9LHx0+Bfwj/aX+E3jn4GfHXwF4e+Jfwq+I+hXXh7xf4O8TWMd9pupWFyA0c8JbFxpur6ZdJBqeha7ps1prOgazaWOs6NfWOp2NrdQgH+DBX78fsnf8G1n/BTv9tH9nj4YftP/BDwx8Gb74VfF3R7/XPB114k+Lml+HtbmsNN17VvDd02oaNPps0tjKNT0W+RI3lcvCscwOJAB8W/8Fbf+Cfev/8ABMn9u/40fsp395qmueDvD9/Y+Lvg94v1aKKO98ZfB/xpA2q+C9Xu3t44La51bS4/t3g/xRc2lta2Uni/wx4g+xW0NosCD/Uf/wCDcr/lCh+wL/2TTxj/AOrh+I9AH+Zd/wAFE/8AgiR+3T/wS6+HngL4n/tWaF8NNK8K/EnxpP4C8MS+B/iJYeM76XxDb6HfeIZI7yytLK1e0tf7O065ZblmZTMEi25cGvYv2TP+Dbz/AIK5/tgeDdK+JHgz9mt/hh8Pdftob3w/4p+P/inR/hI+uWNzbrdWmp6X4O1t5viNcaPf20sFzpmunwYmiarbXENzpmoXcBaRP9af4yfswfAX9oTxN8G/Fnxs+Gfhv4man8AfG118SfhNb+LbU6tovhT4gXGj3Og2/jBNBuHbR9T1zR9OvLs+H7nWLK/TQdSmi13SorXXtP0vUrHU1X9o/wDZ50LxAPCet/Hn4MaP4qMiwjwzqvxR8D6f4gMryeUkQ0a71yHUTI0v7tU+zbmk+QAtxQB/hrftF/AXx/8AsufHf4tfs6fFSLSIfiP8FfHniL4c+NotA1IaxosfiTwvqE2m6oul6qsNuNQsRcwv9nuvIh86PDGNCdo++f8Agn5/wRM/4KL/APBSy1XxL+zf8Drq3+FIuZ7Sb45/FHUV+HfwhN1aXTWV7baN4k1S3m1Dxtd6fdpJbarZfD7RPFt5pE0bR6rb2bYB/cf4Gf8ABK/Rf+Crf/ByZ/wUM0j4hJd3v7LXwH/ad+Kvxa+Od5pE7rbeMbKf4i3tn4E+E9vrdjKHsH+Jmq22oyX97ZzQ3n/CD+GPGsmj31jrMem3kX+iv8QPHHwJ/Yt/Zy8U+PvEaeFvg5+z1+zp8M77W72z0DSLHQ/DHgvwD4H0dng0bw14c0mC1tIhFZ2sGk+HPDej2qzX9/NYaPpVrLd3VvA4B/nyeHP+DI39sa60pZvF37Zv7NGh62bZHbTvDvhj4o+KdLW8KqZLcaxqWi+D7prZGLKl3/YYkkVVY2cZYqvw1+17/wAGlH/BVP8AZm8Lav47+HmmfC39rbwtotu19faZ8A/EGvSfE+3sIY2a5uF+Gnjjw34V1LxBcRuoWLR/AOpeNddu1kje30xyLhLf9ZviL/wfA6/B8UL9fhN+wPo2p/Bey1W5g02T4hfGm/0X4m+JNEjlC2ep3kfh3wVrnhbwXqd3ArTXGiwt47trCSRbdNd1BYTczf2gf8E+P26vg7/wUf8A2Ufhn+1p8EBqth4T8fwapZar4V8RGxHinwH4y8N6lcaN4q8GeJYtOubu1XUNJ1K2aazuopRDrOg3mjeILWOOz1a2UAH+HJfWN7pd7eaZqdndadqOnXVxY6hp99bzWl7Y3tpM9vd2d5aXCRz211bTxyQXFvPGk0MyPHIiurKKtf3U/wDB5N/wTR8C/C/xP8JP+Cknwj8NWPhr/hc/jOX4N/tIWGk28Vpp+s/E1vDmo+Jvhx8SPsNvHsTXPFPhvwt4x0LxtqX7i3v73w54Tv5o5td1rWL6/wD4VqACiiv6nf8Ag1A/4JtfCz9uj9t/x78XPjx4a0vx18JP2OvCXhbx0vgDXLSDUfDvi74teOtY1XT/AIYW/izSrqGW01jwvoNr4U8a+K7jR7j/AEXUtf0Lw3aanb6hoUmr6beAHxl+wt/wbnf8FT/2+PC+i/Eb4ffBXSvhB8I/EdrBfeHfit+0Z4gn+GXhvxDYXJVrbU/Dvhy30jxH8Ttf0W7t2+12HiLSPAN54c1G2xJY6vcGSJX/AF8k/wCDJP8AbmGitPF+11+ye/iIKuzS5LX4vx6KzbSWDa8vgOW+RQ+FVh4bcspLFUI2H/R8+IPjnw38LfAHjf4l+MLmew8IfDnwf4l8c+KLy0srrUbiy8N+ENFvdf1u5ttNsIp72+nttL0+5lhsrKCa6upEWC3ikldEP8Tnj7/g99/Z50vxidP+GX7B/wAYfGngNLm4ibxT4z+MPg74d+JpLaOTbb3Nv4K0jwf8SNOc3EY81oLjxtavBlULO24qAfz1ftL/APBqB/wWC/Z30G48TeH/AIafC/8Aac0ixSabUU/Zr+Ik/iTxDZW0Qys0Xgv4jeG/hf4z1+WY4SKw8IaB4j1IsSWtFjUyD4//AOCY/wDwRh/bj/4KM6v408Y/s6eF/A4079nj4oeDvDfxQsfiL40g8B65o2tXFzcaodPi0jUrCW6nubWDRNRhvYXWCa0vIfsssayEgf6Mn/BOv/g5S/4Jrf8ABQzxHovww0zxp4g/Zw+OuuvbWejfCr9oODRfDEfi7V5xsOmfD74g6XrGreB/E17LcGO20rRNR1Xw34z12WZF0rwlcMs6w/ym/wDBDL/gtp+yN/wSx+JH7fvwx/aL8K/HTxHr/wAf/wBrb+1fBN18IvCHgvxNpFpa6Rr3jTw/c/8ACQ3Xif4j+CbmykkvdZtJLcafZaqj2qzSM8cipFIAf6W1fwz/APBxP/wQO/4KD/8ABSn9v3SP2if2YfD/AMKdU+G9n+z78OvhzPc+M/ibp/hHWB4l8M+JPiBqeqRLpV1YXMjWa2viLTWhuxJsmd5kCgxHP9zFfg5/wUh/4OIv2Gf+CXP7Qtn+zT+0T4J/aU8Q+P734d+G/ibDf/CfwH8PvEnhYeH/ABTqfiHStOt5NR8T/FjwVqQ1WO58M6g13bro7W0UMlq0V7O8kqQgH+ch+33/AMEDf+ChH/BNf4F237RP7Tvh/wCFOmfDa68deH/h1Dc+DPibp3i7WD4l8TWGualpcTaVa2FtKtm1t4e1Ez3Zk2wusKFSZRj0/wDZL/4Nr/8Agp1+2r+zv8Mf2ofgd4Z+DN98Kvi5pWp6z4Ou/Evxc0vw9rk1lpPiLWPC94dQ0afTZpbGRdV0K/SON5XMkCxTAhZAB+s//Bf/AP4OI/2Gf+Co37CWm/s0fs7eCf2lPD/j+z+O/wAPviZLf/FjwH8PvDfhY+H/AAroPjnS9Rt01Hwx8WfGupHVZLjxJYNaW7aOttLFHdNLeQPHGk39cP8Awbgf8oTP2B/+yeePP/V2fE2gD/M5/wCCif8AwRF/br/4Jd/DjwJ8U/2rNC+GeleE/iN43k+H/hqXwP8AEWw8Z38viKLQtS8RNHeWVpZWr2lp/ZulXbC6ZmUzCOHblwR65+yX/wAG3/8AwVy/bC8G6V8SPBX7Nb/DL4ea/bQ3vh/xX8fvFGj/AAkOu2F1brd2ep6V4Q1ySX4jXWjX9rLBc6Zry+DV0PVba4huNM1G7gLSL/rVfGb9mD4C/tDeI/g74o+Nvwz8N/E3UPgF45n+JvwotfFtqdW0Twt8QpNFvPD9r4wXQLh20fVNa0bTtQvT4fn1mz1CLQtTmh17TIbbXtO0rUrHU1b9o/8AZ50HxAPCeu/Hn4MaL4qMiwjw1q3xR8D6d4gMzSeUsQ0a81yHUTI0v7tU+zbjJ8gG7igD/DZ/aP8AgF8QP2WPjx8Wv2cvitFpEPxI+C3jrX/h541i8P6kNZ0RPEXhu9ksNSXS9VENsL+y8+NvIuvs8PmphjGh4H3p/wAE/f8Agif/AMFFv+CllsPEn7NvwNu4fhUtzcWc/wAc/ifqC/Dv4QfarS5Nle2uj+JtVt5b7xreaddq9tqth8PtF8W3+kTIyapbWZxn9yvg3/wSx0f/AIKuf8HKX/BQbQ/H63d3+y58DP2lfib8XPjrf6PcOlv4u01/HU1l4H+FNrrdjKHsJfiZq8N99uvbOaG9XwR4b8az6Pe2WswaddR/6K/jvxn8CP2Lv2c/E/jnX4/Cnwa/Z5/Z0+GV/rd5Z6BpFjoXhfwT4A8DaM8sWkeHPDukQW1rEsFlaRaZ4f8ADuj2onv76Wx0nS7Wa8ureBwD/Pj8N/8ABkb+2NdaUs3i/wDbN/Zo0LWzbRu+neHPDPxR8VaWt4VUyW41jUtF8H3TW6MWVLv+xFkkADGzjLFV+Hf2u/8Ag0m/4Kpfsz+FtX8d/DrTfhX+1t4X0a3a9vdL+AniHXn+J8FhDGzXNwnw18ceG/CuoeILiNlCw6P4D1Txpr12skb22luVnSD9ZPiP/wAHwOvW/wAUb9PhH+wRo2qfBex1a5g0yb4ifGi+0T4m+JdEjlC2mp3kXhzwXrvhfwVqd3CGmn0WKTx5bWDyLbprmoCI3Ev9nn/BPX9u34Of8FIv2UPhr+1n8EF1XT/CvjyLVNP1jwn4iaw/4SnwF408NajNo/irwZ4kj065u7UX+l6hb/abC7ikWLWvD1/oviC3hhtNWt41AP8ADov7C+0q+vdL1Syu9N1PTbu5sNR06/tprO+sL6zme3u7K9tLhI7i1u7W4jkgubaeOOaCaN4pUV1ZR+jv/BPT/gkp+3J/wVCv/HUP7IXwy0PxfonwvvPDNj8SPFvif4heCPA3h/wdceMI9Zm8OJexeI9btPEOrnUovD2syKnhbQNfltksXN7Hb+dbCf8AqJ/4PJ/+CaPgX4Z+IPhL/wAFJvhH4asfDUnxh8aN8Gf2krHSYI7Wx1v4jyeHNS8S/Db4lNY28YWPW/Efh3wr4v8ADvjbVCYbfULvQfB13LHJrmratfaj4r/wam/8FKv2JP8AgnT8Gf8AgoF4k/bB+PPhz4SDxX4o/Z7u/Bfh2407xD4m8aeN10DRvjDFqyeE/B3hHSNc8Q6wLC51bSba+vIrBNM02XU7J9UvrG3l89QDlPBP/BlN/wAFHNWS3n8d/tHfsa+DIplR5LbRvEvxl8ZapabgC0VxA/wc8M6W08ZyCLXWbmBiPkuSDkWvG/8AwZRf8FEtK82X4f8A7S/7HPjKGIFki8Ra58ZfBGo3AHRYYLX4ReMdPEzcfLcatbxAZzPwAf19+LX/AAez/sX+HdYubD4L/sjftGfFLTLa9a2Gu+NfEPw++Ettf20cmx9Q02ysb34nak1vMoM1nDqltpF5JGYxeW1hMzxRfff/AATJ/wCDoX9iH/go58b/AAx+zPP4A+Kv7OPxw8dtfw/D7SviE/hvxH4B8c6rYWb6gPC2h+OvDmoLd2niy7sLbUbuw07xH4T0HS9RFj/Z+m65e67e6fpF0Af51H7fP/BGf/gol/wTYhTXv2oPgDq2l/DO51BNM0341eA9T074ifCO8u551trG3vvFnhqa6bwffarOTFo+j/EDT/COuasUlbTtLuUjdx+XFf73vxP+GPw++NPw88Z/Cb4r+ENC8ffDb4h+HdT8J+NfBviaxi1LQ/EXh7WLZ7TUNN1C0mBV45YnJjljMdxazrFdWs0F1DDMn+Id/wAFEf2YIP2Lv25v2qv2WbC9utS0L4J/Gvxv4O8JalfyLLqWo+BYdVlv/Ad/qsiRQRtq954NvtCudW8mJYBqMtysG6EIzAH6Sfsi/wDBtr/wU3/bc/Z0+Gf7UnwK8M/Bq++FHxa0/WtT8H3fib4t6X4d1ya10DxRrng/UDqGiz6bPNYuus+HtSSJHlcy26wzghZQB49+3t/wQk/4KD/8E4vBXwy8c/tEeC/A13p/xf8AibY/CHwBpHws8bR/EjxTrvjzVNH1TWtN0a18O6Npi6jPLf22kXUFkltHcT3V+9tZwQSTXCCv9J7/AINrf+UIf7Bf/YmfFP8A9aB+LVfpH+1l8bv2Qv2Y/A2j/tF/th+M/hL8N/CPwo1q51PwZ8QPihDplxqHhvxfq+iano8q/DW3ms9R8SXnjzV/DlzrelW+m+BLC98W6polzrNhaWtxYXGoQuAf5tP7Kf8AwZ+/8FNvj94D0j4hfFjxF8Fv2UrTX7K11DTPA3xV1bxRrvxWhs7yD7TbzeIPCHgrw7q+leF53ieHz9F13xXZ+KNMnaWz1rQNMvbaW2Hx7/wUl/4Nvv8Agor/AME1vh9qPxs8aaN4D+O3wG0PyG8V/FP4DavrmvweAIbqVoLa7+IPhDxL4e8MeL9A0ppQsdx4msNK1zwfpkk9lb6t4jsLu/s7ab/SX/Yp/wCC4/8AwTG/4KDfFq8+BX7L/wC0hB4s+LcWna3rWk+CPFHw/wDiV8NtU8W6F4eVJtV1TwbN8QfCXhzT/Eb2tk0mrTaDYXr+LLbRLTUdavPD9tpWl6jd2v6m+J/DPh7xr4a8Q+DfF2i6b4k8KeLdD1bwz4n8O6zaQ6ho+v8Ah7XrC40rWtF1WwuFe3vdN1TTbu5sb60nR4bm1nlhlVkdgQD/AA3P2MP2E/2qv+Cgnxctvgn+yZ8Itf8Air42NqNT1uWyez0nwp4L0ESeXJ4j8deMtbuLDw14S0VZAYLe51nUrabVb8xaRolvqes3Vnp1x/TPH/wZS/8ABRaTwTFq5/aR/Y6h8dyQQ3D+C59f+MQ0eDfAJZbOTxlb/CS5ZtQhkP2YrD4al06SYFk1T7Ptnb+tPU/2yf8AghX/AMG+vg3TP2S9N8f/AA++A+rl4Ne134X/AA90Dxv8Y/jJrOpahHBIvi34xal4T0nxh4lttYvdOuobrSLn4naxpU03h5bex8G2Z0O00/Tof1s/ZJ/bF/Zq/bq+DOk/tAfspfFXRPi98KdY1PVNCj8Q6VZa5ot7pniDRJI49W8PeJPC/inS9C8V+FteskuLS8fSPEeiaZfTaVqGla1awz6Pq2mX92Af4t/7cv8AwT9/at/4JzfGS7+CP7V/wu1TwB4mdLq+8K+IIW/tbwD8R/D9tMkP/CUfDrxlaxjSvFGjEy24u0geHWNCuZ00vxNpOiayk+mw/GFf61f/AAdX/sm+A/2iP+CSPxg+Ker6L9o+Jn7Juq+FPjH8LdftkjW+02DUfGHhjwT8S9FuZ/LaeTw7rfgPXdR1TUNOjkiin17wv4U1ScudFiQ/wu/8G1X/AATo+HX/AAUX/wCCkWh+GPjbo9t4l+B/wA8Aav8AtAfEXwdfqH0v4gy+HfEPhjwz4M8BavGySx3Oh6v4u8VaZq/iXTJ0+za54V8Pa7oUzxLqYcAHhf7BH/BBD/gpt/wUW0DTfH/wQ+Ba+Efg5q+46Z8bvjbrSfDL4c6vEG2C78MfbbTUPGnjjTDIJYW1nwJ4O8T6NDc21xaXN/BdxGCv22s/+DJT9uh9FafUP2uf2TrXxF5MbLpdnb/GC+0U3BUGWJtfn8A6dfLCj5WO4HhtpJFwzW0ROwf6TtraaZoOlW1jp9naaVo2jafDaWOn6daR2tjpumadbLDbWdjY2cSRW9pZ2sKQWtpawrHDDGkMEQVVUfxM/Gf/AIPbP2Y/CXju/wBA+Cf7Ffxh+LfgvTdav9Nbxx4z+J3hn4QXWqWFlcTW8Wt6H4Sg8IfEq9e11HykubKy8Qaj4c1OO0mj/tK00+9WaxjAP59P2h/+DR3/AIK+fAzw9eeJfCPhb4HftM2dj5s11pXwC+KN3N4qhsYl3tdR+HPi74T+Et5q8235RpXhp9e1aaUGO0srobWb+a7xp4M8W/Dnxj4r+Hvj7w1rngzx14E8Sa54O8aeD/E2mXei+I/Cvizwzqd1oviLw5r+j38UF9pWtaJq9leaZqmm3sMN1Y31tPbXEUcsTqP9Yf8A4J//APB0t/wTQ/bg8TaH8MfFeu+Kv2SPjBr89vp+j+Gvj/8A2FYeA/Eus3Uoig0nwt8XNF1O88Km7uHkht7K38cw+AL/AFW/lTT9GsNRunhSb/NT/wCCscsc3/BUz/gpPNDIksMv7e/7X8sUsTrJHJHJ+0F8QmSSN1JV0dSGR1JVlIIJBoA/P6iiigD9ff8Agnl/wQy/4KIf8FOvBF98Vf2Yvht4Ml+D+l+M9S+HuqfFP4gfE7wd4Q8O2HjDR9N0TWNV0dtCGoap8Q7xrHS/Eei3k17pngm+01lvlggvJbqKe3i/bbwd/wAGTn/BQTUBG3j39qX9jzwsrgM6eFtR+M/jaeLIzsddT+FHgaBpF6OI7l4852SuuGP11/wbf/8ABYj/AIJ7f8E2P+CUXj7Qv2q/j1p/hb4jXv7WXxV8VaD8H/DGg+IPG/xS8RaJqHw3+DVjpmoWPhrw7p13Fpem6ne6Nq1nY654q1Hw74elu9Nu7dtXSaIpX0v49/4Pdv2T9N1tbb4ZfsTftCeMfDouJEk1fxv47+HPw61b7MpYR3EOg6GPibaySSYUm3l1+3CBjmYsu0gH5EeO/wDgyu/4KV6Glzc+BPj9+xr48t4VdorS98YfGDwfrl3tBKJBaXfwa1fREkkxt/0rxJbxozLmUpudf55/24/+CY37cn/BOTxLp3h79rz4A+KvhjZa/cy2vhTx1DNpfi34YeMJ4klnNr4b+I3hK+1nwle6stnC1/ceGptUtfFWm2TRz6todgrgV/qM/wDBJ/8A4OGf2MP+CsPjfV/gx8PvD3xJ+Cnx/wBF8M3Xi8fC/wCKVroM9r4t0DTZ0i1u/wDh74w8M6vqVh4gbw8lzY3GsaZrWn+FNeW1u3v9L0jVNL03V9QsP1Q/bF/ZM+Dv7cX7N3xW/Zg+Onh2z8QeAPin4W1HQ5pZ7O1utT8K669tKfDfjvwtNdRyLpvi7wXrJtPEHhzUowGt9RsolmEtpLc28wB/jFf8E+/+Cd/7Qv8AwUw+NGtfAH9mQ/D65+Jmi+AdX+JDaR8QPGlr4It9U8N6FrGg6Lq39i317a3MGpapZXHiTTrqTSott22mLfajGj2unXrw/sv/AMQhf/BZH/oTv2ff/D66N/8AKivzE/4JzftF+Iv+CXH/AAVU+CfxU8T332K3/Z+/aE1T4Y/Gv7C80ltc/Dy81fVvhL8Z44YCim9+zeFNS8Rano8VzDhdWsNLu9kVxbxSRf7Vttc297b295Z3EN3aXcMVza3VtLHPb3NvPGssFxbzxM0U0M0TLJFLGzRyRsroxUg0Af4HHjvwT4m+Gnjjxl8OPGulzaJ4y+H/AIr8ReCfFui3OPtGkeJvCur3mha9pc+3I87T9VsLq0lwSN8TY4r3L9jj9kL42/t3/tF/D39lr9nfQ9O8QfFn4lv4i/4R2z1rVYdB0OC28K+Fta8Za7qGs65cxyW2lWFjoWgajObiZSJbhbeyhWS6uoIn/Yr/AIOk/wBkv/hlz/gr18b9c0nTP7P8E/tR6N4b/ad8LGOLEEmqeOxfaJ8Ty86ARSX138W/CvjjX7iHCzwWmvac86sJ4ri4/Wf/AIMnv2Tf+Ep+P/7V37aOvabv034R/D3QPgT8P7q5h3wS+MPipqS+KvGmoaZLtIj1Pwz4S8EaNpN0xZSNN+IzRqkgndogD88f+IQv/gsj/wBCd+z7/wCH10b/AOVFfinp/wDwT9/aZ8Tftwav/wAE7vh34X8O/E79qTSfiV4x+En/AAiXg3xx4VTw7qHjn4e2WtX/AI20ux8c+KtT8MeFEi8NQ+G/EKalfajqen2i3GjXtvBLNKIFm/2Yv+CgX7VuhfsO/sVftL/tX6+bRo/gp8J/E3inQbG+bba6547nt10P4beF5m3JtHiv4g6t4Z8NqwYFX1VWAJGD/kz/APBDH9o3wJ8J/wDgsr+yz+0r+0z8U9F8FeENO8d/Gbxl8Ufit4/1VLDS7fUvFnwY+LNvcazr2qTDBvNd8T67bWyEK017qupwW8MbzXCIQD9NPhh/wZpf8FWvG2nWmp+N/HH7I3wbM203Wg+Lvin458S+J7IEAkGL4b/Crxl4VuHUkqwh8YFCQdsjLhj7zrn/AAZKft0W+lxTeGv2uf2TtW1oxkz6frlv8YPD2lxzc7Ui1iw8A+J7uaMjGZX0OBhziFsZP7s/tMf8Hjf/AATH+D2uX3hr4IeEPjx+1TeWXmoPFXg7wvp3w3+G1zPE3lm3ttc+J2oaJ42uP3gYfa7f4bzabLEFns767jkQnwX4Jf8AB6/+xh4w8XaRoXxy/ZS+PXwV8Oandw2d1428NeJfCHxf07w/9onjiGp63o0Vt4C199Gs43e51GTw/Ya/rUcMTLp2g6pcMkLAH8un7W//AAa6f8Fdf2S/CWqePX+D/g79o3wboFnNqHiDVv2X/GF58RdX0mzgJ33H/CvfEXh3wN8UdbjSNWuJ28LeB9eWytVe5vzawRSyJ/PHLFJDJJDNG8U0TvFLFKjRyRyRsVeORGAZHRgVdGAZWBBAIr/fO8E+M/CvxH8GeEfiH4F13T/FPgjx54Y0Hxn4N8TaRN9p0nxH4V8UaVaa54e13TLgBRPp+r6RfWeoWU2B5ttcRPgbsV/mPf8AB4V+wl8N/wBmL9t/4SftJfCnw7pnhDQv20PBnjXX/HHh7RrWCw0qb40fCvVvDlj488XWWn2cFvZ2MnjLQfHfgPVddSFGl1TxeviXxNfSy6hr91IwB+Qf/BKj/gnh/wAFFf8AgoJf/G3Rv2AvGr+E5/hbaeANT+KMTfGvV/g9Bfw+LpvF9r4Rkzpk8S6/LbP4d8RriYM2mpP+7IF84P6dfG//AIIA/wDBf34OfBf4vfF34nfF4z/Db4V/C/x/8R/iFBB+2J4p1yebwP4H8Kat4n8WRQ6K95s1iWTQdL1BI9Lb5dQci0biY1+kX/Bjf/yPP/BSL/sU/wBlr/08fHuv7Rv+CnP/ACjY/wCChX/Zjv7WX/qhfH1AH+LZ+yT/AMnV/sy/9nB/Bj/1Y/huv93Wv8Ir9kn/AJOr/Zl/7OD+DH/qx/Ddf7utAH+Tl/wdx/8AKZz4nf8AZEvgJ/6hS1+e/wDwTv8A+CJ//BQT/gqD4Y1/4g/srfDTwnqfwt8J+NZ/h34o+Jnjn4l+C/BnhzRPGVrouh+I7nRZdIu9UuvHmpSW+h+JNF1Ga70Lwbq2npHfxwfa/tavbr+hH/B3H/ymc+J3/ZEvgJ/6hS1+qf8AwbI/8FbP2Av+CbX/AATU/aGsf2tfj3pHgXxrrP7X3i3xb4X+F2j6L4i8Z/E3xXoV18FPglpFjqWjeE/DGl6lcwaXfavoOsaXBr2uzaN4dS/066gu9YtmiYgA+bvBv/Bk9/wUL1Hyn8e/tP8A7HXhSOQK0kfhnVvjP41u4AcEq8d/8JPBVq0q9GWK+ki3D5Z2X5qx/HP/AAZVf8FI9GE8/gP9ob9jXxxbRB2jt9U8VfGLwZrN0ACUWG1f4N+INIWR+hFzr8Eakj96Rkj9d/iL/wAHuX7I+k60bX4U/sXftD+OtBS7kifWPHPjT4c/DO/ktEZlW7tdF0WT4oxyNKArpbXOrWbBH/eSRupSv1h/4JTf8HHH7Ff/AAVS+Jz/AAA8I+Ffib8Cv2hJNA1bxLonw7+J0Ph/UNG8daZoEEl/ryeAPGnhnVbyDWNV0LSIpNZ1XRte0XwrqR0qC+1DSLfWLLStWuLEA/zHv27P+CVf7eX/AATd1nT7H9rf4AeJfh/4e129fT/C3xL0q60vxr8KfFN4EuJo7HSPiF4SvdX8OQ63PaWs9+nhXWrvSPF0VhE95daBbwKzj886/wB4H9pv9mz4QftffAb4nfs3/HjwnY+Mvhd8WPC2peFvEmlXcFtJc2gvIW/s/wAQ6BdXNvc/2P4r8Maktrr/AIV8QW0f27QfEGnafqtk6XNrGw/w2Pj58JdY+AXx1+NXwJ8Q3UV7r/wV+LXxH+EuuXkCNHBd6x8OPGOs+DtSuoY3JaOK4vdGmljRiWVHCk5BoA/2g/8Agj5/yij/AOCbf/Zjn7Lv/qmvB9fyx/8AB6f8MviJ8ZfFX/BJ34X/AAm8D+KviT8RvGviL9sLQ/CXgfwRoWpeJfFPiPVrmD9lsxWGkaJpNvdX97OUV5ZBDAywwRS3EzRwRSSL/U5/wR8/5RR/8E2/+zHP2Xf/AFTXg+m/8FDf+CiH7Bv/AATW0LwD8cf2yfFuieFvFWpWnjnwv8FYNP8ABNz41+L3ia2nfwbefEjw98OINM0251PT9IuHt/AV142ubrVNA8KtNa+Eh4g1IXSaHGQD+BT4Cf8ABmd/wUp+Jng/TvFXxe+KP7OH7O+oaparcp4B8Q+IvFPxA8caS0kCyx2/iEeAvDWo+CLOYu4ikTSPG+vNAUlMqq6rG/wV/wAFHP8Ag24/4KPf8E4PAWr/ABn8X+HfA/x5+BPh6MXXir4o/AHVte8SReA9PK5Op/EDwf4i8OeGfGHh7RoSsn27xLZaTrfhHSV8k6x4isJLq2ik/v4/Ya/4OYf+CX37enxv0D9nj4feLPip8Jvij411GTRfh3pXx98EaL4K0v4ia+Zo4dO8O+F/Efhzxl420JPEWvmQr4b0PxDf6DqevXgTR9MtbnXbuw0u7/fXV9I0nxBpOp6Dr2mafreh63p97pGs6Nq9lbalpOr6TqVtLZ6jpmp6deRTWd/p9/ZzTWt7ZXcMttdW0ssE8UkUjKQD/AXr/Zt/4N+f+UM3/BPr/shkP/qW+KK/zDP+C6n7Bui/8E6f+CmH7QHwB8EWMun/AAi1W90j4ufBO1kYstj8MvidZnXbDw7bM5aaSy8C+Ix4m+HtlcXTyXd5a+Eor25llmuXkb/Tz/4N+f8AlDN/wT6/7IZD/wCpb4ooA/Av/g96/wCTXP2Hf+y+/Eb/ANV3a1/nDV/o8/8AB71/ya5+w7/2X34jf+q7ta/nz/4NjP8AgkR4U/4KT/tYeJfit8ffD7a7+yv+ymnhvxJ4w8M3ttv0b4tfE/Xbq6m8A/DDVvOKRXnhSK30bV/Fnj+0hF39r0rTNG8K6lbQ2HjcXsAB8Wf8E/v+CBv/AAUv/wCCj2g2Hj74JfBe28EfBvVNp0v44fHTV7j4a/DbXI2maA3XhN5NL1jxl4702KWK5juNY8CeD/Euj2txaXFjdX8N+qWsn7paV/wZFfteTaU02uftqfs36drflIV0/SvB/wATtZ0ozEfvI21i80/QbtYlbISYaGzuOWgjPyj+/D9qL9pT4FfsEfsvfEb9on4v3Vv4J+CfwG8Ew31zpvhvTdPhna0szZaB4Q8B+B9AWfStMk1vxDq9zovg7wboYudL01tT1HTbOW702wEt1b/w+3//AAfC+LR8T2k0v/gn94df4MJq7wLaX/x01OP4n3Wgi+CR6o2oW/w+l8KWGryaYGuX0EaZqNnDfOLJfEk9vGb+UA/Gz9tn/g1e/wCCqH7HXhHXfiTofhHwD+1R8OvDtvdalrWpfs4a5rviHxpomiWkDzz6nqnww8VeGvCnjHUFgjjd7uDwNZ+N2s4Qbu5kjtI554f5uWUqSrAqykqysCCpBwQQeQQeCDyDX+7R+yH+1R8J/wBtv9mn4O/tVfBDUL3UPhl8afCFt4q8PLqsVrb63o9wl1daR4i8KeI7WxvNQsbTxP4N8T6ZrPhPxNaWOoahZW2vaNqENnqF9apFdzf51H/B3z/wTR8C/ss/tO/DL9s34LeGrHwt4A/a+bxVZ/FHw5o0EVpo2j/H7wj/AGfqOr+JbKxgigtdNi+KfhvWINau7K1ST7R4u8M+NfEF1Ik2vrGAD+O2iiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACv9b7/g1C/wCUJH7Nv/Y+ftE/+r18d1/kg1/rff8ABqF/yhI/Zt/7Hz9on/1evjugD4q/4PW/+UZP7Ov/AGfb4B/9Z/8A2ka8Y/4M7v8AgqD/AMLW+DPi/wD4Jp/FrxF53j74C2Wo/EX9nW61S6BuvEPwV1bVlfxj4EtpbhvMurz4Y+LtXTV9KtvNmuX8IeMfsOn2tvovgSVo/Z/+D1v/AJRk/s6/9n2+Af8A1n/9pGv87H9jT9qz4nfsP/tQ/BX9qv4P3ptfHfwX8b6b4qsbOS4mt7DxJo4EuneK/BWtvB++Ph7xx4VvtZ8Ja+kOJ20jWbz7O8dwIpUAP9pn9uL9jL4a/tzfBWx+E/xDijtb3wh8Tfhl8a/hl4qFql1feCPil8JfFlh4q8Ma9YqzIRDqMFtqng/xDHE6TXnhHxR4hsIJYZ7qKeL7Er5//ZV/aV+GP7Yn7Ofwc/ae+Deq/wBrfDf41eBtH8beHZZHha+0038TQ6x4a1pIHlitfEfhHXrfVPC3iawWR/7P8QaPqViXZrck/QFAH+RF/wAHUn/Kcf8Aa9/7AX7N3/rMXwfr/Uw/YR+HekfCP9iT9kD4X6FZxWGk+AP2ZPgV4TtLaHBULofwx8MWEs0jjme5up4Zbq7uXLS3V1NNczO8sru3+Wf/AMHUn/Kcf9r3/sBfs3f+sxfB+v8ATh/4JWfHTQv2k/8Agm7+xD8Z9Au4byHxZ+zT8KLXWTb3CXUdl4z8JeFNP8F/EDRzcIzCSXQvHPh3xFos5fZMJrCQTxQzB4kAP4/f+D4n4oaur/8ABPL4LWep30GgzL+0N8UPEWjJNIum6nq9sfhT4T8GancW4IhlvtDsrrx5a2czBpLeDxDfohRbmTzP4Ba/0XP+D239mvxn4t+CX7Fv7VfhzR5L/wAI/Bnxp8VfhN8TL61ilnuNIX4x2fgPWvh7qd8sUbC00KLVfht4o0W41G4ZLaPW/Evh7Tt32nVbZJf87rw/oGueK9e0Twt4Z0nUNf8AEniTV9N0Dw/oWk2k1/quta3rF5Dp+laTpljbpJcXmoajfXEFpZ2sCPNcXE0cUaM7qCAf7cf/AASm+KGsfGf/AIJm/sDfE7xJqd7rfifxZ+yL8AbvxXrepTSXGoa14ss/hp4d0rxTrF7PL+8nutU8QWGo388zlmkkuGcs2dx/lM/4Pgvh1pF38Hf2Bfi0LOJde8P/ABL+NPw6OoJhJ5tI8YeF/BniVbO4xhp4ra88DvPab9wtHu77ythvZt/9fv7BPwK1r9mD9iD9kL9nTxMtkviv4I/s1fBP4YeMG02dbnT5fGXgz4deHtD8X3NjcoAtxaXXiWz1S5t5lGJYpUfndmv4tP8Ag+A+OehySfsGfs1WF3DP4ls0+L/xy8U2IuE+0abomonwt4C8B3UlqrGTytavtL+I0UU8qxoH0CWOAzFrgQAH8A1FFFAH9aP/AAZmf8pZfH//AGZZ8X//AFaPwJr/AFJ6/wAtj/gzM/5Sy+P/APsyz4v/APq0fgTX+pPQB/gSeKP+Rm8Rf9h3V/8A04XFf69X/BsJ4n1PxV/wQ6/YiutXvJb690mz+O/hhJ5jl00zwz+0x8ZNG0GzH/TLTtAtNL06AdoLWMHkGv8AIV8Uf8jN4i/7Dur/APpwuK/1wf8Ag1b/AOUG/wCyB/2HP2kv/Wn/AIw0AfHP/B5//wAoovhX/wBnxfCT/wBU3+0RX+ff/wAElfEup+Ef+CpP/BObXNJu5bK5i/bf/Zd06eaI4aTStd+NPgzQdds29YdR0TUtQ0+4HBaC5kUEE5r/AEEP+Dz/AP5RRfCv/s+L4Sf+qb/aIr/PK/4Jif8AKSn/AIJ6f9nx/sm/+r78AUAf7itf5IX/AAc1+F4/E/8AwX7/AGl/C9qqW83i++/ZQ0aSWMJGz3Otfs5fBDR1uHYjaZAjwrvfPEa7sgV/re1/kaf8HReq3ehf8F3/ANqjW7B/LvtGtP2YNVsnOcJd6f8As1/Bq7tnO0g/LNCh4IPHBB5oA/1sPDPhzRfB3hvw/wCEfDdhDpXh3wtomk+HNB0u3BW303RdDsLfTNLsIASSIbOxtYLeIEkhI1Ga/wA2T/g9l+KGsax+3f8AspfBt9TvZvDngD9k8fEOz0hppDptl4i+Kfxb+IXh/W72C2J8pb+/0n4T+GIry4Rd0ttZWETOfJ2r/ov/AAH+L/hf9oL4I/CD47eCbiG68IfGX4ZeBvih4amguI7uM6L478M6Z4m0+M3EXySSwW2pRwT4ClJ45EdEdWQfwB/8Htv7NfjO0+Of7H/7X9ppEl38PvEPwk1f9nHXNdtopXj0Lxd4J8Z+KfiV4a03WJvLENv/AMJPpHxE8T3Hh9RK73J8K+I96RC3iM4B/DVpGrapoGq6ZruiaheaTrWi6hZatpGq6dcS2eoaZqmnXMd5YahY3cDJPa3lldwxXNrcQuksE8aSxsrqCP8AeR+A3jqX4ofA34M/EydzJN8RPhR8O/HU0hQRmSXxb4Q0fX5HMaqioWfUC2xUULnaFUDA/wAK74JfB3x9+0L8YPhj8CvhXok3iP4j/F7x34X+HXgrRYQ/+neI/FusWmi6YtxJHHL9lsIbi7S41K/kT7Pp+nw3N9cslvbyuv8Au5/DXwba/Dn4c+APh7ZOkll4E8FeFfBtpJGhjjktfC+hWGiW7pGeURorFGVDyqkL2oA/zzP+D374daRpf7Rv7CHxZgs4o9d8b/BT4tfDzU79cebdaV8L/HPhzxHotrIOuyyu/i7rssRPU30gH3eP6tf+Dcr/AJQofsC/9k08Y/8Aq4fiPX8ff/B638c9D8ZftwfsvfATSLuC9v8A4H/s9ar4r8UG3uEl/srXvjP4zmkg0G9hUlrXUovDHw78OeIHSQAy6Z4l0mZcq4x/YJ/wblf8oUP2Bf8AsmnjH/1cPxHoA/JX/g8++KPxM+Hf7DP7M+mfD/4ieOfA2m+PP2jNU8O+ONP8HeLdf8M2XjLw/F8MPFN9HoXiu10XULKDxDoyXsUV4ul6ul5YrdRRXAg86NHX/Mkr/Sh/4Pb/APkyf9jz/s6XV/8A1U3i2v8ANeoA/wBLv/gya+GWjaP+wT+1Z8YIrJIvEnxA/a2k+Huo34x5t34d+FXwg+HOv+HrdiBnyrLVfi54uaIFjiS7nwq5y/8AVJ+2L+yZ8J/25v2cPiR+yv8AHP8A4SlvhR8V4PDlp4xg8GeIZfCviG7s/DHi/wAP+NrC0tNdt7e5ns7e41nw1psepRxRH7dppu9OlP2e7mB/kR/4Mjfj1oGq/sz/ALZv7ML3kUPinwJ8dPDHx4trCa5jWfUfD/xX8A6N8Pry60+0YiWaHRNS+DNjFq9xEHjtZPEOixzmNry383+p/wD4KYfCX9oL44/sH/tN/DT9lH4geNfhh+0lrPw4udU+Cvi/4eeOdS+Gvi6H4g+ENV0zxloHh/TPG+l6jpFxoEXjW50D/hCtTuptSs9Ok0nxDfW2rTx6ZNdsAD8ZP+IQn/gjh/0KX7Qv/h9dV/8AlLX7O/8ABPv/AIJ5fs7f8Ezfghq/7Pf7MNv43s/hvrPxF134oT2fjvxdceMtTtvE3iPQvC/h/VEsNSubW0ktdKktPCWmXEenrGyR382oXQcteMq/5FvjD/gqr/wWI+HvizxL4E8df8FAf2+/B/jTwbrmqeGfFnhTxJ+0b8btH8QeHPEWiXs2naxomtaVf+KoL3TtT0y/t57S9srqGOe3uIpIpEVlIrnP+Hwv/BV7/pJH+3D/AOJP/GP/AOa+gD/SS/4OyfDljrf/AARR+Pup3cUMk/g/4mfs9eI9MeWNXeC+uvjD4W8JSS27MCYZjpvinUIGkQqxt5p4idkrK3+ShX7g/tRaV/wXX8TfsAr+0l+2h8Y/2ytQ/Yq+JXxH8E/D7S/D/wC0b8c/iFdWnxK8RX1vqnjzwhrdh8H/ABx4ln1rWPClnL4NOtaN4z1Hw7BoNxqFtp134dv9Qkiee1/D6gAr+u//AIM8/wBuP4Zfsz/tx/Fz9nb4reJLDwdpX7Y/gXwj4e8CeINa1Oz0vQbj4v8Awv1fXtT8GeEdQur+S3tLe+8Y6J4y8Z6X4ZlkuRLqHipdG8L2Ntd6l4lskT+RCvtr9mr/AIJ5/tf/ALXXwc+Pnx3/AGZfhHr/AMX/AAx+zDeeAv8Aha+jeBWXV/iJo9l8QIfF1zomv+H/AANZ7vEfizTdOHgrVpNdPhe01PU9FgNvqc+nf2VFqOoaeAf7jFzbW95bz2l3BDdWl1DLbXVrcxJPb3NvOjRTQTwyq0c0M0bNHLFIrJIjMjqVJFfzsftRf8GsX/BH39pjVtW8S6b8FfFn7NfijWfMku9T/Zl8aN4D0RLpy7JPYfDjxHpPjX4W6JHGWA+x+HfBOjWbooDQ+Z+9r+G79jT/AIOjv+Csn7Gmj6f8PfEHxB8LftP+BvDzRaZa+Gv2otA1vxZ4u0Oysh9ln02z+JegeIPCPxImuIUjWG3HjTXvF1vpbwJFBpyW6y2sn9Xv/BK3/g7Q+Fn7df7Qvwq/ZQ+O/wCzB4j+BHxV+MXiGHwX4B8ceBPG1r8Sfhlq3i26sbu706x8Safq2jeEPFvgiHWrq1Gi6TJYJ8QYf7WvdPOq3WlaZJe6lp4B+H3/AAUk/wCDPP8AaL/Zy8D+KfjH+w78V5/2sPCHhXTbnW9Z+DPiHwwPDHx/i0uzLSXX/CER6FLqXhX4rX1pZJJfzaTaReCPEt+I207wx4a8S6vLa2Nz/H/8PY5IfiP4HhmjeKWLxt4ZjlikVkkjkTXbJXjkRgGR0YFWVgGVgQQCK/3wq/xr/wDgt/8ADf4f/AH/AILeftjeFPBVtpOh+B9L/aL8MeP2s9Hh+z6Ro1z8RPDvgf4reLbW0tIlEdnDpviHxZrcLWNpGlrZtC9pYwxWsMMSgH+yhX+WF/weRf8AKXHw9/2aF8Gv/U0+Llf6naOkqJJG6yRyKrxyIwdHRwGV0ZSVZWUhlZSQQQQSDX+Xj/wed+CvEWh/8FSfhb4yvtNuYvDfjn9j74cr4f1jypfsN9feGPiR8XNN1/TI7kosLajpX2jSrq+tI3kktrPWtIuJdi30IIB/IvX+x7/wbgf8oTP2B/8Asnnjz/1dnxNr/HCr/Y9/4NwP+UJn7A//AGTzx5/6uz4m0AflL/wed/FH4mfDr9hH9m3Tvh98RPHXgXT/AB3+0nd+G/HFj4N8W6/4YtPGXh1PhZ4zv10DxVbaJqFjD4h0Rb6CC9Glaul3YC7ghufs/nRRuv8AmOV/pU/8Htv/ACY7+yF/2dbe/wDqofHFf5q1AH+ln/wZLfDLRtI/YS/az+MUNkkfiLx9+1lH8OdSv+PNu9B+FHwg+H/iTQLZuN3lWWpfGLxTJFkkb72faAQxb+q79sL9k/4Uftxfs4/Er9lj44/8JS3wp+LFr4esfGMPgzxBL4W8Q3Vl4b8XaB40srS0123guZ7K3udX8N6fDqSRxH7dpj3mnyEQ3cuf5B/+DIv49aBqf7OP7aP7MEl5FB4o8EfG3wn8ebOwmuY1n1PQPil4E0v4e6jd6faEiWaLQtR+D+lw6xcxho7Z/EWhxTFGuoPM/qs/4KVfCX4//HH9hL9pv4Z/sq/EDxn8MP2kNb+Gt7qPwU8YfD7xxqPw28WwfETwlqOneMfDmhab440vUdJufD0PjO90BPBmq3kupWenPo/iC/ttWmTS57ygD8X/APiEJ/4I4f8AQpftC/8Ah9dV/wDlLX7N/wDBPn/gnf8As6f8Ey/glrf7Pv7MFt43svhxrvxH1z4pXVn488XXHjPUrfxR4i0Dwr4c1MWGpXNraSWulS2Pg/Sp49OWNo47+TULsPvvZAP8jHxl/wAFU/8AgsV8OvFvibwF49/b/wD2/PB3jbwZruqeGPFvhPxL+0b8btG8QeG/EWiXs2naxomtaVf+KoLzTtT02+t57S9s7qGOaCeJ45EDKRXNf8Phf+Cr3/SSP9uH/wASf+Mf/wA19AH+k1/wdh+HLHW/+CJn7RGp3cUMk/g/4ifs8eI9MeWNXeC+uvjX4M8JSS27MCYZjpvinUIGkQqxt5p4idkrK3+fN/wSO/4Id/taf8FdPFWt3fwufR/hX8AfAusWui/Ej9oXx3Z3t34a0jV7i2S/PhXwV4espLXUfiJ45i06WDUbrQtPvtK0nRbO80ybxX4m8ODXNB/tXpP2ndL/AOC7Hir/AIJ/yftJ/tmfGT9svUP2J/iR8RPA/wAP9P0D9o345/EO5sviZ4gvk1Dx14Q1nTvhB448Sz6zrfhSyufBya3o/jPUPD0OgXGo22nXfh3UNRlgkmtP9N7/AIIc/BTwb8Bv+CSH/BP7wh4KsLKys/Ev7Mfws+MGvzWbxz/2p42+OXhiw+L3jTU7m9TJvpZvEfjPUIIJnklWDT7ay0+2cWNlaxoAfjx8AP8AgzX/AOCYfw30rTn+N3jn9ov9o/xSttGmszal410z4V+Brq7UfvJ9F8LfD7R7bxbo9vIcn7LqXxL8RyJwBdnGT+pv7PH/AAb+f8EiP2WPiH4G+LnwV/Y+0Xw78UPht4j0jxf4L8c6z8U/jl421rQvFGhXUd7pet2SeNfibr+lxXVrdQpKsSactm2DG9q0TvG35hf8HYn/AAU3/at/4J//ALP37NfgD9lHxhq3wo8RftOeKPirZeMfi/4es7N/FHhjwx8MNK8CS/8ACM+Fdau0uG8K654tvPH8d0viDTbaPXbTT/DN/Ho2pabPLLOf4ff+CWX7S/7UXx8/4K5f8E8Z/i38fvj18ZtQ1L9s/wCAN/qz/EP4pfEH4g3V7Ba/EjQb3Uru+/4SLXNWkmt7Wxt7i6vJZg0NvZwSzTFIInZQD/ZRr/G6/wCDjYAf8Fr/ANvoAAD/AIWX4NPAxyfg78OCT9SSST3JJPNf7Itf43f/AAcb/wDKa/8Ab6/7KV4M/wDVO/DegD/R5/4Nrf8AlCH+wX/2JnxT/wDWgfi1X5F/8HtH/JhH7J//AGd7F/6pn4nV+un/AAbW/wDKEP8AYL/7Ez4p/wDrQPxar8i/+D2j/kwj9k//ALO9i/8AVM/E6gD+LH/gg94o1Pwh/wAFiP8Agnjq2k3ktjdXf7SfgzwvLNEcO+meN0vvBet2ZP8Azy1DRtfv7CYd4bmQd6/2ja/xSf8Agif/AMpcf+Cc3/Z3nwU/9TLTa/2tqAP8cP8A4OQP+U2f7fH/AGULwD/6pL4Y1/VT/wAGQHiXU7r9nb9vLwdLeSvo2hfGn4Q+JbCwJ/c22p+LPA3ifS9WvIx2lvrXwXosMp7pp8I7V/Kt/wAHIH/KbP8Ab4/7KF4B/wDVJfDGv6g/+DHX/kk//BRD/sof7Ov/AKjfxboA/py/4LbW8Fz/AMEi/wDgoxHcRRzRr+yR8ZbhUkUOontPCd9dW0oBBAkguYYp4m6pLGjqQyg1/nPf8GrX7cXwz/Ys/wCCoFhZfGbxHYeD/hv+038J/Ef7Pc3i7XNTtNI8L+EvHGreKPBvjf4f634l1C9kit7PTtR1jwXN4DjvZ5YrTT73xvbahqE1tp1rd3MP+jP/AMFr/wDlEd/wUa/7NC+Nv/qF6lX+Qp+yX+wB+1b+3NpPxy1D9lf4Xaj8X9V/Z88D6X8RPHngvwzc20/ju98MaprDaMkvgrwq7pqPjXVradJbiXw74fS88QXdtEy6TpupXjRWkgB/uWAggEHIPII5BB6EGvwK/a6/4Nnf+CRf7X/iPXPHOt/ALVPgd8QPElze32ueMf2bfFc/wwOo6jfzPdXOqTeBp7HxH8KF1Sa7lnu7nUYvh/Heahczyy6nNenZs/gB/Ys/4OPf+Cs3/BPLTrX4Ox/EWw+MfgDwG0Xhe1+Dv7VvhfW/GNx4Eh0E/wBlv4Y0rxJb614P+LHhuDRbe1TSLHwveeL59A8OJZQ2lj4dtI4ZbeT+pb/gnZ/weK/D39pT42fCb9nn9qX9lDVvg/4m+L3jzwb8MfDHxR+EvjhPHfgiPxf4616w8M6HJ4q8F+J9K8N+I/CnhsavqNnHe6tpPiXx7e2sE7TNpBhtpZWAPzp/4KB/8GZHxd+Ffg/xH8S/2APjvP8AtAweHtOv9Wn+BPxc0jTPCvxX1WzsUef7F4F8ceHvK8E+NPEdxFxBoet+H/hxFO0DpY6rfX93aaW38R+u6FrfhfW9Z8M+JtH1Tw94j8O6rqOheINA1ywutK1rQ9b0i7m0/VdH1jS76KC+03VNMv7eey1CwvIIbqzu4Jre4ijmjdB/vx1/kTf8HTXwp8E/Cr/gtF+0mPA1jpek2nxH8PfCb4reItJ0iEW8Fr428Y/D3RG8X31zCoCDVPFOtWFz401eZcm91LxJc38pM91LQB/PBRRT40MsiRqUDSOqAyOkaAuwUF5JCqRoCcs7sqKMsxABNAH9Dv8AwR6/4Nzf2rP+CrWhx/Gm+8TaZ+zd+yjHq1/o9t8ZPFfh+68T+IviBqWj3AtdZsfhP8PodS0B/Etlpd4JdL1XxdrHiDw94Ws9Vgv9M0y98Q63omt6LYf2W/BX/gzy/wCCSfw4020T4mf8NFftCayIYDqV546+LLeDNImu1VftDaXpHwh0PwBf6dYTOGMVpf8AiDW7yBG2Nqk7AS1/SP8As7fBjwZ+zn8Bfg18BPh3p9ppfgf4OfDHwT8N/DFpZBTCNJ8H+HtP0S2uXlCq13dX4szf31/NuudRvrm4v7qSS5uJZG/i+/4O3P8AgrH+2t+yP8XPgL+yH+y18VPGf7P/AIV8e/BY/Gf4gfEv4cXT+GvHvim91Px54u8F6T4P0L4gWMieI/Cll4bi8FT6xrA8K3Wi6lqL+JdKjvNTnsYTZMAf0q/sl/8ABE7/AIJf/sM/E3QfjP8AsufsqaD8M/ir4Ysta0/Q/HknxB+MHjbxBYWniPR73QNcgjuPiH8QvFcRj1PSNQvLO4R4GRUnLwrFLHE8f6oV/lC/8Gyfxr+PPxm/4Lj/ALLl/wDFD4t/F34rvF4b/aO1XWL3x9498ZeOnjEn7O/xQtl1HUrnxDquqFA+pXlnALy6cbr67tohIbieJW/1eqAP8MP/AIKCgD9vb9t0AAAfteftKAADAAHxm8aAAAcAAdBX+rh/wbl/tn/8Nr/8Em/2bvE+s6r/AGp8Rvgfpc/7MnxReSb7ReDxF8HLTTdK8L3+oTsxnutR8R/Cu9+HvinU7udRLcarrd+XeZkaeT/KQ/4KDf8AJ+/7b3/Z3v7Sn/q5vGlf1Mf8GXX7Z/8Awrj9rL48fsR+JtV8nw7+0l4Ai+Jvw4s7mbMa/Ff4MxXk+t6XpVuWAW68UfC/V/EGtarMA7PbfDHTYyFCZoA/Ur/g9R/ZL/4T39kn9m/9sXQdM87W/wBnv4qaj8L/ABtdW0OJV+HHxssLeXTdT1OcL89loHxB8F+H9G06N2BhvPiDdNEpFxMR+r3/AAbK/sm/8Mo/8EgP2cF1PTP7N8aftFLrX7UfjTdF5Ul0fi0bJvh5OwZVmz/wprQ/hqsiS8pdC52AIwFfqD+3p+yJ4M/bz/Y/+Pf7I3j2+k0nw98bPA83h2PXYbaO9m8N+I9N1LT/ABN4L8UQ2kpVLqXwx4y0PQdeS28yI3B07yVmhZxKn034V8L6D4I8L+G/BfhXTLbRfC/hDQNH8L+G9Gs1KWmk6DoGnW+laPplqhJK21hp9pb2sCkkrFEoJOM0AfxNf8HqX7aH/CF/s/fs4fsJ+GNW8rXPjb4vu/jl8UrO1nK3EXw3+GLSaL4E0nVIC2JNL8XfELVtQ1yzYIzLqXwoBLxgbZv4Iv2RP2Qv2gf26Pjz4M/Zu/Zn8BXvxB+KXjaa4ez0+KaHT9H0LRdOjE+t+LPFuvXjR6b4b8K6DakXGqaxqEyRh3ttPso73V9Q03Trz9Af+C/v7aP/AA3N/wAFVf2oPifpGrf2t8Ofh94o/wCFAfCKWKf7Rp5+H/waluvC39q6PKWO7SfGnjJPGHxDs+E+Xxe37uP7i/1Vf8GQ3wU8G2/wk/bf/aLksLK5+IWq/Eb4ffBSz1SR45NS0bwb4f8ADMnjrUrC0j/1tnZeJdb8TaTcai5/d6lP4T0tVw2lNkA7D9kP/gyl/Z08N+H9J1r9t/8Aab+JvxR8cywWd3qXgf8AZ+i0X4a/DjSL0xr9u0WbxX4w8P8Ai/xr4309JN4t9bstO+F15Mu0vpMG0h/1+8Df8GuX/BEPwQIZZf2Prrxrfwbcah45+Ov7QOsGTb1M2kWfxO0vw3LvIBbfohHZQqEqf0e/4Kb/ALTPjT9jb/gn9+1v+098ONFt9f8AiB8G/gr4t8V+CbG+szqOlweK/syaZoGta3p4ntW1Dw/4b1TUbXxF4gsUuraS80XS7+3juIXkWRf8dj4//wDBTb/goR+1H4g1XxF8df2yf2ifHcur3l7eyaDP8U/Fmi+BtNe/mae4tvD3w88OalpHgXwxpxZtsemeH/D2m2EMSRwx26xxoqgH+2x8Mfhp4G+DPw58C/CT4Y+HbTwh8OPhn4T0DwL4E8KafLdzaf4a8I+FtMttG8PaDYSX9zd3hsdJ0qztbCzW4uZ5I7aCKMyEKK/hQ/4PlwP7F/4JlHAyNU/bBAOOQDafsxkgHrgkDI74HoK/rE/4I6DUx/wSm/4J2nWhfjVZP2OvgDNfnVBcDUHuJ/hzoMzy3Zu/9JaabeJWebLyb95J3ZP8nn/B8t/yBP8AgmX/ANhX9sD/ANJP2ZKAPPv+DG//AJHn/gpF/wBin+y1/wCnj491/aN/wU5/5Rsf8FCv+zHf2sv/AFQvj6v4uf8Agxv/AOR5/wCCkX/Yp/stf+nj491/aN/wU5/5Rsf8FCv+zHf2sv8A1Qvj6gD/ABbP2Sf+Tq/2Zf8As4P4Mf8Aqx/Ddf7utf4RX7JP/J1f7Mv/AGcH8GP/AFY/huv93WgD/Jy/4O4/+UznxO/7Il8BP/UKWvDf+CPf/BvZ+1f/AMFZ7a4+KNhruk/s+fssaRrd5oGofHbxlod54hvfFWtaYY01bRPhR4BttQ0S58cXWkTSx22s6zf6/wCGPCOm3S3unJ4hvvEGm3mgp7l/wdx/8pnPid/2RL4Cf+oUtf6cn7DXwU8G/s5fsbfsvfA7wBYWWn+FPhp8Cvhl4a09NPeOWC+uLbwnpk2sa5Jcw/u76+8R63PqPiDVNRGTqWpand37kvcsSAfz3/BD/gzq/wCCUHw402yHxU1D9oz9ofXvs8H9q3XjD4oQ+BPDs16ir9ok0fQvhRoXg3WNLsJmBMdnqXi3xDdwKxU6pMQrj9V/2Vf+CG//AASv/Yn+KPhL42/s0/sm6F8PPi54F/tdvCnxBuPiN8ZvG3iPRn8QeH9U8K649pcfED4jeKbdDqvh7W9X0m8jFt5L2eoXMKRRqwC/z9/8Hbv/AAVX/bK/Yx1j9m39mP8AZT+JPir4DaZ8X/AfjD4j/Ej4qeBnXR/HeuRaX4msPD3h/wAGeEPHEDDW/BiaRJZ6lrPie78NS6ZreoprPhy0j1m301NUsNS/ms/4N3Pjv+0J8bf+C5P7EV58VPjL8Zfi5O/iP416prF18QPiH438fSsB+zn8YTJqOpT+I9Y1Z2AupYC93dMQLiSLdJ5jpkA/1ua/xCv+Cs4A/wCCp/8AwUqAAA/4b6/bC4HA/wCThPiHX+3rX+IX/wAFaP8AlKh/wUq/7P6/bB/9aD+IVAH+uz/wR8/5RR/8E2/+zHP2Xf8A1TXg+v5K/wDg+Z/5B3/BMX/r9/bK/wDRH7LNf1qf8EfP+UUf/BNv/sxz9l3/ANU14Pr+Sv8A4Pmf+Qd/wTF/6/f2yv8A0R+yzQB/A74J8ZeJvh14z8I/EHwXq934f8Y+BPE+geMvCevWEnlX2ieJvDGq2mt6Dq9lLz5d3puqWNreW0mPkmhRu1f72nhbXIvE/hnw74lgieCDxDoWka5DBKrLJDFq2n29/HFIrhXV40uAjqyqwYEMAciv8PD/AIJ/fsXfFL/goB+1t8F/2XfhXoOtanffEPxpoNp4x1/S9KvdTsPh18Nl1exj8dfEjxNJaRsmneHvCOhTXOoXFzdy28d3eix0e0kk1TVLC2n/ANya3t4bWCC1tokgt7aGO3t4IlCRwwwoscUUaDhUjjVURRwqgAcCgD/NB/4PYvA8Gmf8FAf2W/iHF5SSeMf2Q7LwvcohUSPN4E+MXxP1BbqZB826S28dW9skrj547JY1JEBC/wBnP/Bvz/yhm/4J9f8AZDIf/Ut8UV/DH/weRfHvQ/ih/wAFSPB/wn8P3treL+zh+zb4E8GeK1gnE8ll478c6/4r+KF/Yz7GKQtH4L8U+AJvII86OSeYyth0ji/uc/4N+f8AlDN/wT6/7IZD/wCpb4ooA/Av/g96/wCTXP2Hf+y+/Eb/ANV3a19s/wDBnn8MtG8Ff8Eik8aWVkkWr/GL9pP4xeMdbvzta4vP+Edi8LfDTTYPMxvSzsrbwQ7W9ruMcVzd39yiq97MW+Jv+D3r/k1z9h3/ALL78Rv/AFXdrX0f/wAGZvx50Dx//wAE0fiX8DkvIh4w/Z9/aP8AFbalpX2hJZ4/BnxX0LQ/FnhPW2hBEttBqfiOx+IelQoyGOSXw5czRyu0ksUAB/RP+3d+wp8Cf+Ci/wAAdQ/Zp/aOTxpcfC3VvFPhrxdqlh4G8VT+ENV1DUvCdxPe6Nb3WqW9rdySabDfyx38tl5YWW7s7KUuPIAb8Rf+IQn/AII4f9Cl+0L/AOH11X/5S1+mH/Bab4Rftb/GT/gnP8eNE/YV+IPxU+Hn7VHhaHwx8Q/hbd/B3x5r3w78a+KZPB3iXTtR8X+BbHW/Dup6Tf3k/irwGfFFjo+gvdrb6x4oHh+2dfM8qSP/ACg9R/4K6f8ABW3R9QvtJ1b/AIKK/t26Xqul3lzp2p6ZqP7SvxpstQ07ULKZ7a8sb6zufFcVzaXlpcRSW9zbXEcc0E0bxSojoygA/wBhn9iD9ir4J/8ABPr9nbwp+y7+zzF4ttvhP4K1XxVq/h2x8aeJZvFesWNx4z8Rah4q1yEavcW9rI9nLrmq6hewW5ixA11KAxDcfzqf8Hnnh2y1b/glR8Ltamih+3eFf21fhXfWVyY1NwsWp/Cf47aLeWsc2N6Q3H2+3uJ4gwjlksbZ3DPDEV/gJh/4K/8A/BWO4mit7f8A4KPftyzzzyJDBBD+038ZZZpppWCRxRRp4uZ5JJHZUREUs7EKoJIFfQ/7dvhL/gtvZ/sd/CL4x/8ABRT4pfta3/7N3xm+Ja2Pwu8BftMfGrxxr2rav4t0Dw1qer6b4yl+D3jXxFf674btf7EutZTw94h8Q6HpF3fWl1cXGlRzaTqdre3oB+K9Ff0e/wDBHD/g3b8e/wDBX79nv4jfH/wp+1B4Q+B9j8PPjLqfweuPDXiH4Zaz41u9Uu9N8EeCPGja5DqWm+L/AA9DbW8sPjWGwWxe0mkSTT5ZzcMs6xxfT/8AwUR/4NQvid/wT5/Yy+OP7Ymu/tm+A/ibpPwT0fw1q954G0n4O+IPDWo+IE8R+OvC3geOC21u88eatbWDWs3iePUHeXTrkSxWj26qjyrKgB/JHRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFf633/BqF/wAoSP2bf+x8/aJ/9Xr47r/JBr2zwZ+0t+0b8OPD9p4S+Hnx/wDjZ4C8K2El1NY+GfBnxV8d+F/D9lNfXMl5ey2mjaHr1jp1vJeXc011dPDbI1xcyyTyl5XZiAf6Pv8Awet/8oyf2df+z7fAP/rP/wC0jX+YtXrnj/8AaA+PPxY0i10D4p/G34ufErQbHUY9YstE8f8AxJ8ZeMtIs9Xhtruyh1S103xFrOo2dvqMVnf31pHfQwpcx215dwLKIriZH8joA/uq/wCDOP8A4Kg/8IV8QPGv/BMH4t+IvL8M/E241r4r/swXOp3WIdK+Iunad9s+J3wxspJmcx2/jTw5po8d+HrCNrWwtdd8LeMSi3Os+M4Uk/0Tq/wH/D3iLxB4S1zS/E3hTXdY8M+JNDvYNS0TxB4e1O90XXNH1G1cSW1/perabPbX+n3tvIA8F1aXEM8TgNHIrDNe/f8ADaH7Yn/R2H7S3/h9vij/APNTQB+wv/B1J/ynH/a9/wCwF+zd/wCsxfB+vvz/AINif+C9fgX9hK51P9hr9sXxI/h39mP4heLpvE/wl+LF5HJc6Z8DviN4jktLXxBo/jN1Z59P+FHjWWC31SXWrWGS18C+LhqGtava/wBgeKvEWv8Ahr+RDxl438afEXxDfeLviD4v8UeOvFmpraJqXifxlr+q+J/EOoJYWcGn2K32ta3d32pXa2Vha21jaLcXMgt7O3gtoQkMMaLy9AH+9ZqWm/B/9oz4U3mlanbfDz43/BP4seFpbS8tZh4e+Ifw1+Ifg3XbcpIjbTq3hvxP4f1S2f5XRryxuYyHjZsKw+JP2ev+CPX/AATH/ZU+KkXxu+AH7GHwY+HfxWtLm4vNH8a2mkalrmq+F7q7tXsrm58FL4o1XXLPwPPLZyzWjS+ELXRH+zXF1ACI7q4WX/Hj/Z0/b1/bW/ZGDwfsy/tU/Hn4I6ZLNNcXXhz4e/E3xVoXhC/uJzmW41PwZBqR8KapcM3zifUNGuZUk/eI6yfNX2N4h/4L5/8ABZDxPpLaLqX/AAUK/aDtrNraS0M3h7XdH8I6t5UisrOuv+FNE0XXVuQGJjvV1IXkTBXinR0VgAf6yH7fX/BSH9kn/gmv8HdW+MP7UXxO0nwykdhdT+DPhvpl5p2o/Ff4qatD+7g8P/DjwO99a6jrt3PdvDbXmrSmy8MeHo5v7R8Ua7oulRT30f8Ajuf8FIP28/in/wAFKP2wPiv+1p8V4YdI1Hx1qFtpvg7wXY3Ml3pPw5+G3hyH+zPBHgXS55Eh+0jR9JRZ9Z1Rbaz/AOEg8T3+veJJbK0uNYmt4/k/4ifE34k/F7xVqHjr4s/EHxx8UPG+rbP7U8Y/ETxZr3jXxVqXllin9oeIfEt/qer3mwu5T7ReSbSzYxuOeHoAKKKKAP60f+DMz/lLL4//AOzLPi//AOrR+BNf6k9f4HngP4lfEX4V61L4k+GHj7xr8OPEU1hPpU2v+A/FWu+ENal0u6mtri502XVfD1/p19JYXFxZ2k89m85t5ZrW2lkjZ4ImX2H/AIbQ/bE/6Ow/aW/8Pt8Uf/mpoA8G8Uf8jN4i/wCw7q//AKcLiv8AXB/4NW/+UG/7IH/Yc/aS/wDWn/jDX+RG7vI7SSMzyOzO7uxZ3diWZmZiWZmYksxJJJJJzXtvg39pn9pD4deHbHwh8Pv2gvjf4F8J6W12+m+GPBvxX8eeGPDunPf3k+oXzWOi6Jr1jpto17f3VzfXbW9tGbi8uJ7mYvNNI7AH+lT/AMHn/wDyii+Ff/Z8Xwk/9U3+0RX+eV/wTE/5SU/8E9P+z4/2Tf8A1ffgCvnzx7+0L8ffirosPhv4ofHH4wfEjw7bajBq9voPj34l+NPGGiwatbQXVrbapDpfiHWtRsYtRt7W+vbaC9SBbmKC8uoY5VjuJVfzDSNX1bw/q2l69oOqajomu6JqNlq+i61pF7c6bq2katptzFe6dqml6jZSw3lhqNheQw3dle2k0Vza3MUU8EscsaOAD/fnr/Ii/wCDqT/lOP8Ate/9gL9m7/1mL4P1+PX/AA2h+2J/0dh+0t/4fb4o/wDzU14j4y8b+NPiL4hvvF3xB8X+KPHXizU1tE1LxP4y1/VfE/iHUEsLODT7Fb7Wtbu77UrtbKwtbaxtFuLmQW9nbwW0ISGGNFAP7lP+DYD/AIOBfhb8DPh/oH/BOD9uHx1p/wAP/BWjaxe/8Mv/AB18V3cNh4N8N2niXVL7WdX+EfxP8SXk8dv4Y0eLxBqF1qvgHxhrDLoOnQ6rqXhfX9V0TStM8LK398fxQ+FPwV/ac+FOr/Dj4t+B/APxt+DfxF0iyk1Twx4r0rSPGfgrxTpMxt9U0nUI4LlLzT7tY5Us9W0TV7J/PtLqKz1TS7uG5ht7hP8ABgr7Y/Z2/wCCkf7fX7JemR6B+zh+2D+0J8IvC0IcQ+C/CnxP8TxeA4meVp3mj8B3t/eeD0uTK8j/AGpdEFz++nAl2zyhwD/YZ/ZY/wCCUv8AwTq/Yn8b6h8S/wBl39kj4TfCX4iajbalYv460vTtT1zxbYafrBX+1dM0HxD4t1TxBqvhrStQRFhu9L8O3Wl6fPbKLWS2a2HlV5//AMFPv+CuX7I//BK74Pav46+OPjbStb+Kd9pNxL8Kv2ePDWsadP8AFX4na3JFcJpYt9EEs134a8ErewlfEXxD1y0i8PaJaxyw2zax4iuNH8Oav/ld+M/+C8X/AAWH8e6RcaHr3/BQv9o21sLq0NlM/hHxZbfD7UjAVCts1vwDpvhnWoZ2UYe6hv47pwW3THc2fy18W+MPF3j/AMR6r4w8d+KfEfjXxbrtz9s1vxT4t1vU/EniPWbvYkf2rVdb1i6vNT1C58uNI/Pu7qaXYiLu2qAAD2j9rb9qL4q/tp/tJfGH9qX42anBqnxL+NHjG98WeIDYxyw6VpUJht9N0DwxoNvPNcz2vhzwh4bsNI8LeHLW4ubq4ttD0ewhuLq6nSS4k/1uv+Dcr/lCh+wL/wBk08Y/+rh+I9f43Ve7eFf2pP2mvAvh/TfCfgn9ov47eDvC2ixSW+j+GvCvxd+IHh7w/pMEs8t1LDpujaR4htNOsYpLmee4kjtbaJHnmlmZTJI7EA/0K/8Ag9v/AOTJ/wBjz/s6XV//AFU3i2v816vV/iD8efjl8WtPsdJ+Knxm+K/xM0rS7xtR0zTPiD8RPF/jPT9O1BoHtmvrGz8R6xqVtaXjW0slu11bxxzmCR4i/luynyigD9C/+CX3/BRb4t/8Euv2vPAn7U/wotYPEEOmW934R+J3w8v7yaw0n4ofCnxDc2EvirwXf3sCSvp13JLpum674a1n7PeR6F4u0PQNYudO1azsrnSb7/Xb/wCCfn/BVD9ij/gpf8OdN8c/sw/GDQtY8RNpy3ni34L+Jr7TPD/xu+HVyixC8tPGHw8k1C41RLO1uJPs0HirQ21rwVrEkcp0LxJqSRSmP/EZrZ8PeI/EPhHWtO8SeFNe1nwx4i0i4W70nX/D2qX2i61pd0qsq3Onarps9tfWVwqsyrNbTxSBWYBsE0Af7iH7SP8AwTp/YS/a/wBVg8Q/tNfslfAb40eKLazGn2/jHxr8OvD1/wCNodPVVSOwj8aQ2lt4qWxhVF+z2Y1f7PbkboI42JJ4X4E/8EnP+Caf7M/iCw8XfA/9h/8AZv8AAvjHSmV9J8Zw/DLw/rvjPSJVdXE2keLfFFtrfiPSp9yqTPp+p28zBQGcqAK/ySvAn/BaX/grN8NtOstI8K/8FDf2sE03ToxDY2fiH4w+KvGsNrAvEdvCPGt74gKW0K4SC3B8iCMLFDGkaqow/iV/wWC/4Km/F3S7jQ/H3/BQP9rPVtEvNy32i6f8bPHHhfSNQjcENb6jpvhTVtEstQtTnP2S8gntgwVxEGVSAD+8X/g8t+NXwe/4d0+BfgYPin8PX+NVz+1N8LvGUXwki8Y+H5fiT/wiGk+Avi1aal4pk8ExX7+I4PDtnd6xpNpPrU+nR6al1qVjb/afOuoUf/Mcq1fX17qd5dajqV5dahqF9cTXd7fX1xLd3l5dXEjSz3N1dTvJPcXE8rNJNNM7ySSMzuzMSaq0AFf3rf8ABkp8ZPhF4Iuf28/hp40+KPw88I/ET4l67+zPcfDnwL4n8Z+HdA8X+PofD1l8c4NffwX4c1XUbTVvFI0SbXNFj1YaHaXzac2raaLsQ/bbbzP4KaVWZGVlYqykMrKSGVgchlIwQQRkEcg8igD/AG3v2of+CRn/AATT/bN1658W/tI/safBb4g+NL5pn1Px5a6DdeBPiBrLzkF313x78OdQ8I+MNddDlrdtX1q9a1Z5WtTC00pfm/2Uf+CMP/BL79iLxtpfxL/Zn/Y7+G3gH4j6Ct8ugfEDVr/xr8TPG3h5tSt5bO+n8PeKvit4p8b65oN1dWU9zYS3mkX1ldHT7q7sFmFndXEEn+Rx8MP+Cpv/AAUp+DFpp+mfDH9vb9rzwjomlQwW2m+GrH9oL4oXPhOytrZFjt7e38J6j4lvfDccEESLFFEul+WkSiJVEY216l47/wCC2n/BW74j6Vc6J4o/4KG/tUjTLyPybuDwz8Vdf8CPcwbSj28114Fn8OXclvMhKXNu05hukZkuElViCAf6q/8AwVE/4LEfsff8Er/hTrnib4y+OtG8SfGi60O5ufhd+zd4X1ixu/il8QtaliKaQ11pUL3E/gvwSbpkl1rx74kt7XR7PT4LyPR08QeIf7O8O6l/jlftGfHr4hftSfHr4wftG/Fe/h1L4jfGz4ieK/iV4vntElh06HWPFmr3WrTado9rNNcSWOhaQlxHpOg6aZ5V03RrKxsI3aO3SvLdd17XPFGs6n4i8Tazq3iLxBrV5PqOsa7ruo3mr6zq2oXLmS5vtT1PUJri9v7y4kJee6up5Z5XJaR2Yk1k0Af7Nv8AwRN/4Ke/A/8A4KTfsWfCHxB4R8a6Efj18N/hz4P8GftD/CafVbZfG3g3x14a0ey8P6p4lk0KadtUuPAnje+sZPEHg7xPEl1pt1Z6gdFur9fEuja7pth99/tKfsffss/tjeFtM8F/tTfAD4U/Hrw5oV1eX3h2y+Jng3R/E1x4Yv8AUYIrXUNQ8K6re2zav4X1C+toYLe8vtAv9Ou7qCGGKeZ0ijVf8L7wd428Z/DrxFp3i/4feLvE/gXxbpEjy6T4o8Ha/qvhjxFpcskbRSSadreiXdjqdlI8TvG721zEzRsyMSrEH7s0H/grv/wVR8M6OdB0X/gox+2xa6VhVitpP2mPi9fPaRoCFi0+6v8AxZdXmnQAE/uLC4toc/MU3AGgD+3n/g6M/YN/Yu/Y7/4JDaSn7L37L3wQ+B95d/tZfBy01DXvAHw98PaP4t1W0k8H/FPfa6z4zWyk8WazbEwQnyNV1q8iDRqwQHmv2x/4NwP+UJn7A/8A2Tzx5/6uz4m1/kg/Gj9rD9qX9pBoX/aG/aS+Pfx2NtPHc2o+MXxf+IPxLS1uIo3hhmtY/GfiHWo7aSGGSSKFoFjMUTvHHtRipreFf2o/2mvAvh/TfCfgj9or47eDfCujRSQaP4Z8K/Fz4geHvD+lQTXE13NDpujaR4gs9OsYpbq4nuZI7W2iR7ieaZgZJHZgD/Qz/wCD23/kx39kL/s629/9VD44r/NWr1j4gfHr45/FnTrHSPip8Z/ix8TNJ0y9OpabpfxA+Ivi/wAZ6dp+omCS1N/Y2XiPWNStrS9NtNLbm6gijnMEskRk8t2U+T0AfoP/AMEwv+Cifxc/4Je/teeAv2qPhNbQa+ukQXnhP4l/D3ULyaw0j4ofCrxDcWL+K/BOo3sCSyafcTvp2na54c1j7PeJoXi7Q/D+tT6dqtrYT6Xe/wCu5/wT6/4Kp/sUf8FMPh1pnjf9mP4v6FqviVtOW88W/BXxPf6X4f8Ajd8O7lFiF5aeLfh7JqFxqYsbaeT7PB4r0Jtb8FavIkh0XxHqAhn8r/EcrZ8P+IvEHhLWtO8SeFdd1nwz4i0i4W70nXvD+p3uja1pd2gZVutO1TTp7a+srhVZlWa2nikAZgGwTQB/uJftI/8ABOv9hP8AbA1W38QftN/sl/Af40+J7W0Gn23jDxt8OvD1/wCNoNPVVVNPi8aRWdv4qSxiCL5Fmuri2gI3QxI2TXA/An/gk1/wTR/Zo8QWHi74I/sPfs3eB/GGkssmkeMovhl4f17xlo8qurifSPFvim21zxFpVxuVc3Gn6lbTMAFaQqMV/kl+A/8AgtJ/wVl+G2m2WkeFP+Chv7WEemadGIbGy8QfGHxX41htYE4jtoV8a33iApbQrhILYHyIIgsUMaRqqjF+JX/BYP8A4KnfF3SrnQvH3/BQP9rPVdEvdy32jad8bPG/hfSdQjcENb6jpvhPVtDs7+1Oc/ZLyGe23BXEW9VYAH95f/B5R8avg8v/AATl8G/Aw/FP4et8ab39p/4WeMbf4SJ4x8PyfEl/CWk+C/ilbal4obwTHft4ji8O2Vzq2l21xrU2nR6bHc6jZW5ufOuoUf1L/g1f/wCCrfwf/af/AGJPhn+xL4y8WeHfCn7UP7K/h/8A4V5o/gfVtbtbTV/iv8HdCjnuvBfjbwLp1/Ol3rLeFdAI8JeNdI0o6hcaC/h6y8Q3aWOk+JdOt7b/ACzr6/vtUvbvUtTvLvUdRv7ia7vr++uJru9vbu4kaW4uru6uHknuLieVmkmmmkeSWRmd2ZiTWj4Z8T+JfBXiHRfF3g3xDrnhLxX4b1K01nw94n8M6tf6D4h0HV7CZbix1XRda0q4tdS0vUrK4RJ7S+sbmC6tpkWWGVHUMAD/AHTP2o/2QP2Zf21/hqfhD+1V8FvBHxv+Hiatb6/ZaB4z0+SZ9F1+1trqyt9f8N61YXFhr/hfXY7G+v8ATxrPh3VdM1I6ff31g10bO8uYJfzH8IfCb/giZ/wRn+MXwT+Hnwp+EnwZ+Cf7S/7VPxC8FfBP4TeGvDf9pfEX9oTxO3xN8X2PhpbxdY8b+IvE/jzwx8KrHULgXnizX7zW9J8LNDpS6XarrPiJdD0C7/zD7L/gtd/wVv0/wvF4Ptv+Ci/7Xf8AZEIZY7i5+NXjK98SKrII9p8Z3uo3HjBlRVAiVtdZYT80QRiSfz91b4rfFHX/AIgt8Wtd+JPj7Wviq+tW/iR/ibq3jHxFqPxBfxFaSxz2uvN4zvNRm8RtrVtPFFNb6odSN9DLHHJHOropAB/vdV/jd/8ABxv/AMpr/wBvr/spXgz/ANU78N6/OH/htD9sT/o7D9pb/wAPt8Uf/mprwnxV4t8VeOvEGpeLPG/ibxB4x8U6zLHPrHiXxVrOo+IfEGrTxQRWsU2pazq9zeajfSx2sEFtHJdXMrpBDFCpEcaKAD/YN/4Nrf8AlCH+wX/2JnxT/wDWgfi1X5F/8HtH/JhH7J//AGd7F/6pn4nV/ndeE/2of2mPAXh7TfCXgb9on46eDPCmjRzRaR4Z8J/Fvx/4d8PaVFcXM97cR6bouj+ILPTbGOe8ubm7mS1tollubiedw0ssjtifED49/HT4s6bZaN8VPjT8WfiXo+m339p6dpXxA+I3jDxlpthqQt5rX+0LKx8R6zqVra332W4ntvtcEUdx9nnmh8zy5XVgD7p/4In/APKXH/gnN/2d58FP/Uy02v8Aa2r/AAH/AA/4h1/wnreleJvCuuax4a8SaFfW+p6J4g8P6ne6Nrej6laSCW11DStV06e2v9PvraVVkt7u0uIZ4ZAHjkVgDXv3/DaH7Yn/AEdh+0t/4fb4o/8AzU0AfpN/wcgf8ps/2+P+yheAf/VJfDGv6g/+DHX/AJJP/wAFEP8Asof7Ov8A6jfxbr/Ph8VeLfFfjvxBqXizxv4m8Q+MvFWsyxT6x4m8Va1qXiHxBqs0NvDaQzalrOr3N5qN9LFa28FtFJdXMrx28EMKkRxIq9f8PPjf8afhHBqlt8KPi98UPhjba5Laz61b/Dzx/wCK/BcGrz2KTx2U2qReG9W02PUJbOO5uUtZLtZnt0uJ1iKCWQMAf7M//Ba//lEd/wAFGv8As0L42/8AqF6lX8P/APwZf/GT4RfC79rj9q/QfiZ8Ufh58PNa+I/wY8B6F8PdL8c+M/DvhO/8c67YePJ7u80Pwhba9qNhL4k1q3tJo7uTSdHW81BbXdc/Z/IjkdP5RvEH7V/7UvizRNV8M+Kf2lfj94l8Oa7Y3Gma34f8QfGP4iazomsabdxmK60/VdK1HxHc2GoWNzEzR3FpdwTW80bFJI2UkV4DQB/uC/tT/wDBLz/gnv8AtsX41v8Aah/ZG+DHxY8UhVjbxzqPhhfD/wARZbeOEW8VncfEfwdP4d8dXNjBEFFvYXHiGSyt2VZIYEkVXHh/7Nn/AAQw/wCCTf7I/j/QPin8B/2Kfhp4b+IvhPWU8ReFPGPinWPiD8WNc8K6/C7S2eteGbz4u+MvHTeH9V0yZhPpGoaQLO70i5jhutMmtbmCKVP8kP4S/wDBSn/gob8CNM0vQvg5+3H+1j8OfDeiwRWuleE/C3x/+KOm+DrG1g4htbfwfH4nPhlbaEEiK3/sowxgsEQBiD714s/4Lif8FefGmkzaJrX/AAUR/amgsJ7dbSU+Gvidq/gq/eAKFI/tfwadA1cO6jbNMt8JpwXE0j733AH+s3/wUL/4Kg/se/8ABMr4T6n8S/2mvihpGk63JpV7eeAvg9od9p+qfGD4qanbxuttpPgjwULuK/nt57wRWV94p1T+zfB3h954pfEGvabE8Zk/xx/27f2wfiJ+3x+1x8c/2ufijDb2Hiz40eM5deGg2VxPd6f4S8M6bYWXh3wR4L026uAs11YeDvBuj6F4btryWOKa+TTPt08ST3Mq183eL/GfjD4heI9V8Y+PvFfiXxx4u125N5rnirxfruqeJfEes3jKFa61XXNaur3U9RuWVVUz3d1NKVUAtgCuaoAKKKKAP9jP/gg9/wAFW/g//wAFLP2LvhdHB4s8Pab+098H/AugeBfj98I5dbtW8W2Wr+ELGx8ORfE7TNGuZxq994C+IMUNjr1hrUUF1YaTrOp3/g+91K51bRZ5rj78/bC/4J7/ALF37fmgeHPDf7YH7PPgT44WPg6fUJ/CN94ij1bSvE/hU6uLQaxD4b8aeFNU0DxhodlrB0/T31fT9M121sdUl07Tpb+3uJbCzeH/ABCfhv8AFD4l/BvxjpPxE+EPxD8c/Cv4gaA88mheOfhv4t1/wP4x0V7mCS1uX0nxN4Y1DS9a05ri2llt52s72EywSyQyFo3ZT+gWtf8ABaf/AIK0+IfCq+DNV/4KJftbS6ELGbTZfs3xn8YabrN3Z3CPHPFqHijTdQs/E+pNLHI8ck2oaxcztGxQy7eKAP8AUu/Z4sP+CQf/AATa/ag+G3/BPz9lHwD8HfhV+1D+0XaeI7i5+H/wws/+Er+J1v4T+HXw98SfEuTXfjf441jVta8Z6L4bfSfD9zF4P0/xh4gutR17W9WivPD2h3WnL4i1zS/2Pr/A/wBC+JvxJ8L+NG+JHhn4heOPDvxEe51K8bx7oXizXtI8aNd6zBcW2r3TeKdPv7fXDc6rbXl3b6lOb4y30F1cRXTSxzyq3r3/AA2h+2J/0dh+0t/4fb4o/wDzU0AdP/wUG/5P3/be/wCzvf2lP/VzeNKx/wBiL9p3xL+xf+13+zp+1R4T+0y6p8Dfiz4P8eXOnWkohl8QeG9N1OKLxl4TeUsmy18YeELjXfC96fMjJstXuAJIyQ6/NGp6nqWt6lqGs6zqF9q+savfXep6rqup3dxf6lqepX9xJdX2oahfXUkt1e317dSy3N3d3Mstxc3Esk00jyOzGjQB/vo+CfGXhr4i+DfCXxB8Gatba94P8deGNB8ZeE9dsmL2eteGvE+lWmt6Fq1oxALW2o6XfWt5AxAJimQkDOK/OH/gs/8Atnr+wR/wTR/aq/aH07VBpXj2w+Hl54B+EMscwivf+FufFGWPwJ4E1DT48q91L4W1XXP+E3vbeNlc6N4Y1OXfGsTOv+Ofon7Wv7VfhrRtJ8O+HP2mv2g9A8P6Dptlo+h6Fonxn+I+laNo2kabbR2enaVpOmWPiSCy07TdPs4YbWysbOCG1tbaKOCCKOJFUc748/aH+P8A8U9Fj8NfE745fGH4j+HYb+DVYdA8efEzxr4v0WLVLWG4t7bUo9K8Qa3qNil/bwXl3BBeLALiGG6uI45FSeVWAPH2ZmYsxLMxLMzElmYnJJJ5JJ5JPJPJr+uP/g0y/wCCqnwm/Ye/aO+LH7MP7RfibQvh/wDCH9rVPB934a+KfirV4NG8LfD74v8Aw/h8R2+iaf4o1K/mt9K0Xw38R9G8SXejXfiPUZ0t9L8SaD4Otrp7XStT1TUrD+RuigD/AH2tc0Twz458Mav4b8R6Tofi/wAG+MNCv9E13QtZsbDXvDXifw1r+ny2Op6Tqum3sV1pms6HrWl3c9nfWN3Dc2Oo2FzLBPFNbzMrfiH47/4JLf8ABA79g6HxB+2R8Vf2WP2Y/gvofgW7i8S3/jj4oan4k1nwFoesW1xLqWlx+Gfh1408UeIPBH/CRzX0e3wv4b8IeDJdc1HUI7PTfDmlXN4llaj/AC4fgj/wVZ/4KUfs4eFrLwL8E/25P2m/AXgXStMj0bQ/BGn/ABb8W6h4M8OaXFGIobPwv4U1zUdU0DwxFDGFSH+wNP014lVRGy7Vx4H+0B+1p+1B+1drll4j/aY/aE+Mnx51nS42h0e7+LHxF8VeOV0SBxiS30K18QanfWeh28hy0lvpNvZwyOzyOjO7sQD/AHDv2dvjn4D/AGm/gT8JP2hvhd/ax+HHxo8AeGfiR4FfXtOXR9Yl8KeK9Mg1bQptR0pbi6/s26n065t5pLJp3ktt/ky7JUdF/h+/4Plv+QJ/wTL/AOwr+2B/6SfsyV/DboH7WP7U3hXRNK8NeF/2lvj/AOG/DmhWFtpWiaBoHxk+Iuj6Jo2mWUSwWenaVpWneI7ex0+wtIESG2s7SCG3giRY4o0RQBxvxE+NXxk+Ly6QnxY+LXxN+J6aA182gr8RPHninxquiNqYtBqTaQviXVdTGmtqI0+wF8bMQm7FlaC48z7NDsAP7g/+DG//AJHn/gpF/wBin+y1/wCnj491/aN/wU5/5Rsf8FCv+zHf2sv/AFQvj6v8TH4efGT4vfCKTVZvhP8AFT4kfDCbXks4tcl+HnjjxP4Kk1mPTmuW0+PVX8N6ppjaili15eNZpeGZbVru5MAQzy7u91f9rn9q7xBpOqaDr37Tv7Qut6HrenXuka1our/Gn4kalpOr6TqVtLZ6jpeqadeeJZrO/wBOv7Oaa0vbK7hltrq2llgnikikZSAN/ZJ/5Or/AGZf+zg/gx/6sfw3X+7rX+AjZXt7pl7aajp13dafqGn3Vve2F/ZXEtre2V7aypPa3dpdQPHPbXVtPGk1vcQuksMqJJG6uoI+jP8AhtD9sT/o7D9pb/w+3xR/+amgD91f+DuP/lM58Tv+yJfAT/1Clr+4H/g3d/4Kt/B//goN+w38IPhtdeLPDui/tU/s5/Drwz8Kfi58KrzW7VfFmtaX8O9F0nwtoPxj8P6TdzrqmteEvGukQaRfa5qdnbSWnhvxrdax4bvHjii0e81X/JB8beP/AB38S9em8VfEfxt4u+IHii4t7a0uPEnjbxJrPivXp7Wyj8qztptY129v9Qlt7SL91bQvcNHBH8kSovFO8A/EPx/8KfF2i/ED4XeOPGHw28eeG7l7zw7428A+Jta8HeLtAu5IJbaS60XxJ4evdO1nSrl7aea3eexvYJWgmliLGOR1IB/uIftd/sGfsfft6eEdC8D/ALXnwC8C/HHQPC19eal4VPii31Gy1/wpealHaxarL4W8X+HNQ0Txd4bXWI7Cwj1mHRNcsINXTT9PXUoroWNqIfhj4HeGv+COf/BLT9pb4RfsUfsz/Dn4OfCL9qj9qe41LQNJ8B/Dy3m8Z/GS48K+E/BPif4lz678WPGXiLWdf8c+Hvh+um+FL1tDHi3xDt8Ra/cWx8OaRqptdYv9K/y5b7/gtZ/wVt1HwtH4Ou/+Ci37XLaNHazWZli+NPjG18QzW86GOVbvxha6jD4uvZGRionvNcnnTOUkU81+fOn/ABO+JWk+Oj8UNK+IXjnTPiYb++1Q/ETT/Fmv2Xjo6nqlvcWmp6ifFttqEevm/wBRtby7tr68OofaLu3uriG4kkjnlVgD/e/r/EL/AOCtH/KVD/gpV/2f1+2D/wCtB/EKvEf+G0P2xP8Ao7D9pb/w+3xR/wDmpr581rW9Z8S6zq3iLxHq2p6/4g17Ur7Wdd13Wr+61XWda1jVLqW91PVtW1O+lnvdR1LUb2ea7vr68nmuru6mluLiWSWR3IB/tlf8EfP+UUf/AATb/wCzHP2Xf/VNeD69r/aT+EP7EX7RGsfD/wCCX7Wvw7/Zl+MXibX7fxXr/wAJvhl8d/Dvw08ZeK9St9E/sFPHGufDPwz42tr7XnGlLeeGY/FWq+EbUNZR3WjR6tcRxz2at/icaH+1n+1T4Y0XSvDnhr9pj9oHw94e0HTrPSND0HQ/jN8RtJ0XRtJ063jtdP0vStLsPElvY6dp1jaxRW1nZWcENtbW8ccMMSRoqjkPGPxx+NfxD1jw94i8f/GD4peOfEHhGXz/AAprvjH4geLPE2seGJjcwXnneHtT1rV7290WX7Xa2t15mmz2z/abaCfPmwxsoB/uS/Ab9k79l39lrTb/AEj9mv8AZ1+CPwDsNWitYdai+EHwu8F/DyTXUsWlazbX7nwro2l3Wuy27zzvFPq897Osk0ziTfK7N8I/8Fav+Cw37Mf/AASg+B+teL/iR4k0Txd8e9d0O6b4J/s56VrFo3jr4ga7OJ7XS9W1jT4JXvvCvwz07UInl8T+ONSgisorWzu9L0Fda8UzaboV7/k96L/wVl/4Ki+HNAk8L6J/wUU/bb03Q5FSNLK3/ag+M4NnEgIEOmXb+MmvdJhIY7odMubSJzy6MQDXw54s8X+LPHviLVfF/jrxR4i8aeLNdunvtc8UeLNb1LxH4i1m9kAEl5qut6xc3mpajdOAA9xd3M0rADLnFAHcfHn43/Ej9pX40fFD4/8Axg1+TxR8T/jB438Q/EDxvrjxrbx3mv8AiTUJtRvEsrOM+Rp2lWZmWw0fSrUJZ6TpVtZ6bZRxWtrDGv8AsJ/8G/P/AChm/wCCfX/ZDIf/AFLfFFf4yVe8+Gf2qP2nvBWg6Z4V8G/tHfHnwl4Y0S3Fno3hzwz8X/iDoOg6RaB3lFrpmj6V4htNPsLcSSSSCC1t4ot7u+3czEgH+gB/we9f8mufsO/9l9+I3/qu7Wv47f8AgjZ/wVW+I/8AwSU/a40v45+HdKufGvwo8Z6bB4B/aA+F0VykEnjX4cz6pa6g194fkuZYrGy8feDr2Aa34M1O7aOBpjqfh2+ubbRPEusufzs+IPx1+N3xbs9O074q/GP4qfE3T9IuZb3SbH4g/ELxd4zs9LvJ4hBPd6dbeI9X1KCyuZoAIZZ7ZIpZIgI3coMV5XQB/uRfsS/8FD/2Pf8Agob8NNO+J37KXxr8JfEazm023v8AxF4LXUbTTfih8PbiYrFNpPxE+Hd1cDxN4Tv7a7LWi3F7ZNourbVv/DurazpFzZajc5P7RX/BML/gnn+1p4juPGf7Rn7G/wCz98VvG95Atre+O/EPw60KHx3fW8Y2ww3/AI20m303xTfR265Fqt3q8wtAzi28oO+7/EZ8H+NfGXw88Q2Hi3wB4t8TeB/FelO0ml+JvB+var4Z8Q6bI6lGksNa0W7stSs3ZCVZre5jYqSpJBxX6R+D/wDgtx/wVy8C6fbaZoP/AAUR/atlsrOAW1tH4l+LPiLxtLHAqlUj+1eNLjxBdMI0wkRedmhRUSIoqIFAP9cT9nv/AIJh/wDBPL9lPXLbxV+z1+xl+zv8LvGFkI1sfHGg/DHw3P47sVjJZRY+ONXstS8WWQZiHlFrrEQndI3m8xooyn8nv/B638a/g9r/AOz/APsp/BbQfin8Pdc+L/hb4/a94q8U/C/RvGOgap4+8L+G5PhzrWlQa54k8J2N/PrmgaXdaldQ2NneatZWcN7cmSK0eZ4JxH/F78Vf+Cs3/BTj43aVPoHxP/b2/av8T+HrtZEvfDh+N/j3RvDmoJKu149S0Dw/rWlaPqUe0sqR31lcJEryCJUEj7vz6lllnlkmmkkmmmkeWWWV2klllkYvJJJI5LPI7Es7sSzMSSSSTQB/pp/8GT//ACjh/aY/7Pb8U/8AqiPgPX6sf8HJ/wDyhF/b0/7Er4X/APq/vhPX+RX8P/j98d/hPpV3oXws+Nfxb+Gmh6hqD6tf6N8P/iR4x8G6Ve6rJbW1nJqd3p3h3WdNtLnUJLSzs7V72aF7lra1toGkMUESrteK/wBqL9pjx54f1Lwl45/aJ+OvjPwrrMcMOr+GfFfxc8f+IvD+qxW9zDewRalour+ILzTb6OC8tre7hS6tpVjubeGdAssSOoB4VRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAH//Z" - webUI["html/lang/en.json"] = "ewogICJtYWluTWVudSI6CiAgewogICAgIml0ZW0iOgogICAgewogICAgICAicGxheWxpc3QiOiAiUGxheWxpc3QiLAogICAgICAicG1zSUQiOiAiUE1TIElEIiwKICAgICAgImZpbHRlciI6ICJGaWx0ZXIiLAogICAgICAieG1sdHYiOiAiWE1MVFYiLAogICAgICAibWFwcGluZyI6ICJNYXBwaW5nIiwKICAgICAgInVzZXJzIjogIlVzZXJzIiwKICAgICAgInNldHRpbmdzIjogIlNldHRpbmdzIiwKICAgICAgImxvZyI6ICJMb2ciLAogICAgICAibG9nb3V0IjogIkxvZ291dCIKICAgIH0sCiAgICAiaGVhZGxpbmUiOgogICAgewogICAgICAicGxheWxpc3QiOiAiTG9jYWwgb3IgcmVtb3RlIHBsYXlsaXN0cyIsCiAgICAgICJmaWx0ZXIiOiAiRmlsdGVyIHBsYXlsaXN0IiwKICAgICAgInhtbHR2IjogIkxvY2FsIG9yIHJlbW90ZSBYTUxUViBmaWxlcyIsCiAgICAgICJtYXBwaW5nIjogIk1hcCBwbGF5bGlzdCBjaGFubmVscyB0byBFUEcgY2hhbm5lbHMiLAogICAgICAidXNlcnMiOiAiVXNlciBtYW5hZ2VtZW50IiwKICAgICAgInNldHRpbmdzIjogIlNldHRpbmdzIiwKICAgICAgImxvZyI6ICJMb2ciLAogICAgICAibG9nb3V0IjogIkxvZ291dCIKICAgIH0KICB9LAogICJjb25maXJtIjoKICB7CiAgICAicmVzdG9yZSI6ICJBbGwgZGF0YSB3aWxsIGJlIHJlcGxhY2VkIHdpdGggdGhvc2UgZnJvbSB0aGUgYmFja3VwLiBTaG91bGQgdGhlIGZpbGVzIGJlIHJlc3RvcmVkPyIKICB9LAogICJhbGVydCI6CiAgewogICAgImZpbGVMb2FkaW5nRXJyb3IiOiAiRmlsZSBjb3VsZG4ndCBiZSBsb2FkZWQiLAogICAgImludmFsaWRDaGFubmVsTnVtYmVyIjogIkludmFsaWQgY2hhbm5lbCBudW1iZXIiLAogICAgIm1pc3NpbmdJbnB1dCI6ICJNaXNzaW5nIGlucHV0IgogIH0sCiAgImJ1dHRvbiI6CiAgewogICAgImJhY2siOiAiQmFjayIsCiAgICAiYmFja3VwIjogIkJhY2t1cCIsCiAgICAiYnVsa0VkaXQiOiAiQnVsayBFZGl0IiwKICAgICJjYW5jZWwiOiAiQ2FuY2VsIiwKICAgICJkZWxldGUiOiAiRGVsZXRlIiwKICAgICJkb25lIjogIkRvbmUiLAogICAgImxvZ2luIjogIkxvZ2luIiwKICAgICJuZXciOiAiTmV3IiwKICAgICJuZXh0IjogIk5leHQiLAogICAgInJlc3RvcmUiOiAiUmVzdG9yZSIsCiAgICAic2F2ZSI6ICJTYXZlIiwKICAgICJzZWFyY2giOiAiU2VhcmNoIiwKICAgICJ1cGRhdGUiOiAiVXBkYXRlIiwKICAgICJjcmFldGVBY2NvdW50IjogIkNyZWF0ZSBBY2NvdW50IiwKICAgICJyZXNldExvZ3MiOiAiUmVzZXQgTG9ncyIsCiAgICAidXBsb2FkTG9nbyI6ICJVcGxvYWQgTG9nbyIKICB9LAogICJmaWx0ZXIiOgogIHsKICAgICJ0YWJsZSI6CiAgICB7CiAgICAgICJuYW1lIjogIkZpbHRlciBOYW1lIiwKICAgICAgInR5cGUiOiAiRmlsdGVyIFR5cGUiLAogICAgICAiZmlsdGVyIjogIkZpbHRlciIKICAgIH0sCiAgICAiY3VzdG9tIjogIkN1c3RvbSIsCiAgICAiZ3JvdXAiOiAiR3JvdXAiLAogICAgIm5hbWUiOgogICAgewogICAgICAidGl0bGUiOiAiRmlsdGVyIE5hbWUiLAogICAgICAicGxhY2Vob2xkZXIiOiAiRmlsdGVyIG5hbWUiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJkZXNjcmlwdGlvbiI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJEZXNjcmlwdGlvbiIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJEZXNjcmlwdGlvbiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgInR5cGUiOgogICAgewogICAgICAidGl0bGUiOiAiVHlwZSIsCiAgICAgICJncm91cFRpdGxlIjogIkdyb3VwIFRpdGxlIiwKICAgICAgImN1c3RvbUZpbHRlciI6ICJDdXN0b20gRmlsdGVyIgogICAgfSwKICAgICJjYXNlU2Vuc2l0aXZlIjoKICAgIHsKICAgICAgInRpdGxlIjogIkNhc2UgU2Vuc2l0aXZlIiwKICAgICAgInBsYWNlaG9sZGVyIjogIiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImZpbHRlclJ1bGUiOgogICAgewogICAgICAidGl0bGUiOiAiRmlsdGVyIFJ1bGUiLAogICAgICAicGxhY2Vob2xkZXIiOiAiU3BvcnQge0hEfSAhe0VTLElUfSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImZpbHRlckdyb3VwIjoKICAgIHsKICAgICAgInRpdGxlIjogIkdyb3VwIFRpdGxlIiwKICAgICAgInBsYWNlaG9sZGVyIjogIiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJTZWxlY3QgYSBNM1UgZ3JvdXAuIChDb3VudGVyKTxicj5DaGFuZ2luZyB0aGUgZ3JvdXAgdGl0bGUgaW4gdGhlIE0zVSBpbnZhbGlkYXRlcyB0aGUgZmlsdGVyLiIKICAgIH0sCiAgICAiaW5jbHVkZSI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJJbmNsdWRlIiwKICAgICAgInBsYWNlaG9sZGVyIjogIkZIRCxVSEQiLAogICAgICAiZGVzY3JpcHRpb24iOiAiQ2hhbm5lbCBuYW1lIG11c3QgaW5jbHVkZS48YnI+KENvbW1hIHNlcGFyYXRlZCkgQ29tbWEgbWVhbnMgb3IiCiAgICB9LAogICAgImV4Y2x1ZGUiOgogICAgewogICAgICAidGl0bGUiOiAiRXhjbHVkZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJFUyxJVCIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJDaGFubmVsIG5hbWUgbXVzdCBub3QgY29udGFpbi48YnI+KENvbW1hIHNlcGFyYXRlZCkgQ29tbWEgbWVhbnMgb3IiCiAgICB9CgogIH0sCiAgInBsYXlsaXN0IjoKICB7CiAgICAidGFibGUiOgogICAgewogICAgICAicGxheWxpc3QiOiAiUGxheWxpc3QiLAogICAgICAidHVuZXIiOiAiVHVuZXIiLAogICAgICAibGFzdFVwZGF0ZSI6ICJMYXN0IFVwZGF0ZSIsCiAgICAgICJhdmFpbGFiaWxpdHkiOiAiQXZhaWxhYmlsaXR5IiwKICAgICAgInR5cGUiOiAiVHlwZSIsCiAgICAgICJzdHJlYW1zIjogIlN0cmVhbXMiLAogICAgICAiZ3JvdXBUaXRsZSI6ICJncm91cC10aXRsZSIsCiAgICAgICJ0dmdJRCI6ICJ0dmctaWQiLAogICAgICAidW5pcXVlSUQiOiAiVW5pcXVlIElEIgogICAgfSwKICAgICJwbGF5bGlzdFR5cGUiOgogICAgewogICAgICAidGl0bGUiOiAiUGxheWxpc3QgdHlwZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ0eXBlIjoKICAgIHsKICAgICAgInRpdGxlIjogIlR5cGUiLAogICAgICAicGxhY2Vob2xkZXIiOiAiIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0sCiAgICAibmFtZSI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJOYW1lIiwKICAgICAgInBsYWNlaG9sZGVyIjogIlBsYXlsaXN0IG5hbWUiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJkZXNjcmlwdGlvbiI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJEZXNjcmlwdGlvbiIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJEZXNjcmlwdGlvbiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImZpbGVNM1UiOgogICAgewogICAgICAidGl0bGUiOiAiTTNVIEZpbGUiLAogICAgICAicGxhY2Vob2xkZXIiOiAiRmlsZSBwYXRoIG9yIFVSTCBvZiB0aGUgTTNVIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0sCiAgICAiZmlsZUhESFIiOgogICAgewogICAgICAidGl0bGUiOiAiSERIb21lUnVuIElQIiwKICAgICAgInBsYWNlaG9sZGVyIjogIklQIGFkZHJlc3MgYW5kIHBvcnQgKDE5Mi4xNjguMS4xMDo1MDA0KSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgInR1bmVyIjoKICAgIHsKICAgICAgInRpdGxlIjogIlR1bmVyIC8gU3RyZWFtcyIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiTnVtYmVyIG9mIHBhcmFsbGVsIGNvbm5lY3Rpb25zIHRoYXQgY2FuIGJlIGVzdGFibGlzaGVkIHRvIHRoZSBwcm92aWRlci4gPGJyPk9ubHkgYXZhaWxhYmxlIHdpdGggYWN0aXZhdGVkIGJ1ZmZlci48YnI+TmV3IHNldHRpbmdzIHdpbGwgb25seSBiZSBhcHBsaWVkIGFmdGVyIHF1aXR0aW5nIGFsbCBzdHJlYW1zLiIKICAgIH0KICB9LAogICJ4bWx0diI6CiAgewogICAgInRhYmxlIjoKICAgIHsKICAgICAgImd1aWRlIjogIkd1aWRlIiwKICAgICAgImxhc3RVcGRhdGUiOiAiTGFzdCBVcGRhdGUiLAogICAgICAiYXZhaWxhYmlsaXR5IjogIkF2YWlsYWJpbGl0eSIsCiAgICAgICJjaGFubmVscyI6ICJDaGFubmVscyIsCiAgICAgICJwcm9ncmFtcyI6ICJQcm9ncmFtcyIKICAgIH0sCiAgICAibmFtZSI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJOYW1lIiwKICAgICAgInBsYWNlaG9sZGVyIjogIkd1aWRlIG5hbWUiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJkZXNjcmlwdGlvbiI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJEZXNjcmlwdGlvbiIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJEZXNjcmlwdGlvbiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImZpbGVYTUxUViI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJYTUxUViBGaWxlIiwKICAgICAgInBsYWNlaG9sZGVyIjogIkZpbGUgcGF0aCBvciBVUkwgb2YgdGhlIFhNTFRWIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0KICB9LAogICJtYXBwaW5nIjoKICB7CiAgICAidGFibGUiOgogICAgewogICAgICAiY2hObyI6ICJDaC4gTm8uIiwKICAgICAgImxvZ28iOiAiTG9nbyIsCiAgICAgICJjaGFubmVsTmFtZSI6ICJDaGFubmVsIE5hbWUiLAogICAgICAicGxheWxpc3QiOiAiUGxheWxpc3QiLAogICAgICAiZ3JvdXBUaXRsZSI6ICJHcm91cCBUaXRsZSIsCiAgICAgICJ4bWx0dkZpbGUiOiAiWE1MVFYgRmlsZSIsCiAgICAgICJ4bWx0dklEIjogIlhNTFRWIElEIgogICAgfSwKICAgICJhY3RpdmUiOgogICAgewogICAgICAidGl0bGUiOiAiQWN0aXZlIiwKICAgICAgInBsYWNlaG9sZGVyIjogIiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImNoYW5uZWxOYW1lIjoKICAgIHsKICAgICAgInRpdGxlIjogIkNoYW5uZWwgTmFtZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJkZXNjcmlwdGlvbiI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJDaGFubmVsIERlc2NyaXB0aW9uIiwKICAgICAgInBsYWNlaG9sZGVyIjogIlVzZWQgYnkgdGhlIER1bW15IGFzIGFuIFhNTCBkZXNjcmlwdGlvbiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgInVwZGF0ZUNoYW5uZWxOYW1lIjoKICAgIHsKICAgICAgInRpdGxlIjogIlVwZGF0ZSBDaGFubmVsIE5hbWUiLAogICAgICAicGxhY2Vob2xkZXIiOiAiIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0sCiAgICAiY2hhbm5lbExvZ28iOgogICAgewogICAgICAidGl0bGUiOiAiTG9nbyBVUkwiLAogICAgICAicGxhY2Vob2xkZXIiOiAiIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0sCiAgICAidXBkYXRlQ2hhbm5lbExvZ28iOgogICAgewogICAgICAidGl0bGUiOiAiVXBkYXRlIENoYW5uZWwgTG9nbyIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJlcGdDYXRlZ29yeSI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJFUEcgQ2F0ZWdvcnkiLAogICAgICAicGxhY2Vob2xkZXIiOiAiIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0sCiAgICAibTN1R3JvdXBUaXRsZSI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJHcm91cCBUaXRsZSAoeHRldmUubTN1KSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ4bWx0dkZpbGUiOgogICAgewogICAgICAidGl0bGUiOiAiWE1MVFYgRmlsZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ4bWx0dkNoYW5uZWwiOgogICAgewogICAgICAidGl0bGUiOiAiWE1MVFYgQ2hhbm5lbCIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfQogIH0sCiAgInVzZXJzIjoKICB7CiAgICAidGFibGUiOgogICAgewogICAgICAidXNlcm5hbWUiOiAiVXNlcm5hbWUiLAogICAgICAicGFzc3dvcmQiOiAiUGFzc3dvcmQiLAogICAgICAid2ViIjogIldFQiIsCiAgICAgICJwbXMiOiAiUE1TIiwKICAgICAgIm0zdSI6ICJNM1UiLAogICAgICAieG1sIjogIlhNTCIsCiAgICAgICJhcGkiOiAiQVBJIgogICAgfSwKICAgICJ1c2VybmFtZSI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJVc2VybmFtZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJVc2VybmFtZSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgInBhc3N3b3JkIjoKICAgIHsKICAgICAgInRpdGxlIjogIlBhc3N3b3JkIiwKICAgICAgInBsYWNlaG9sZGVyIjogIlBhc3N3b3JkIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0sCiAgICAiY29uZmlybSI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJDb25maXJtIiwKICAgICAgInBsYWNlaG9sZGVyIjogIlBhc3N3b3JkIGNvbmZpcm0iLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ3ZWIiOgogICAgewogICAgICAidGl0bGUiOiAiV2ViIEFjY2VzcyIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJwbXMiOgogICAgewogICAgICAidGl0bGUiOiAiUE1TIEFjY2VzcyIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJtM3UiOgogICAgewogICAgICAidGl0bGUiOiAiTTNVIEFjY2VzcyIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ4bWwiOgogICAgewogICAgICAidGl0bGUiOiAiWE1MIEFjY2VzcyIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJhcGkiOgogICAgewogICAgICAidGl0bGUiOiAiQVBJIEFjY2VzcyIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfQogIH0sCiAgInNldHRpbmdzIjoKICB7CiAgICAiY2F0ZWdvcnkiOgogICAgewogICAgICAiZ2VuZXJhbCI6ICJHZW5lcmFsIiwKICAgICAgImZpbGVzIjogIkZpbGVzIiwKICAgICAgInN0cmVhbWluZyI6ICJTdHJlYW1pbmciLAogICAgICAiYmFja3VwIjogIkJhY2t1cCIsCiAgICAgICJhdXRoZW50aWNhdGlvbiI6ICJBdXRoZW50aWNhdGlvbiIKICAgIH0sCiAgICAidXBkYXRlIjoKICAgIHsKICAgICAgInRpdGxlIjogIlNjaGVkdWxlIGZvciB1cGRhdGluZyAoUGxheWxpc3QsIFhNTFRWLCBCYWNrdXApIiwKICAgICAgInBsYWNlaG9sZGVyIjogIjAwMDAsMTAwMCwyMDAwIiwKICAgICAgImRlc2NyaXB0aW9uIjogIlRpbWUgaW4gMjQgaG91ciBmb3JtYXQgKDA4MDAgPSA4OjAwIGFtKS4gTW9yZSB0aW1lcyBjYW4gYmUgZW50ZXJlZCBjb21tYSBzZXBhcmF0ZWQuIExlYXZlIHRoaXMgZmllbGQgZW1wdHkgaWYgbm8gdXBkYXRlcyBhcmUgdG8gYmUgY2FycmllZCBvdXQuIgogICAgfSwKICAgICJhcGkiOgogICAgewogICAgICAidGl0bGUiOiAiQVBJIEludGVyZmFjZSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJWaWEgQVBJIGludGVyZmFjZSBpdCBpcyBwb3NzaWJsZSB0byBzZW5kIGNvbW1hbmRzIHRvIHhUZVZlLiBBUEkgZG9jdW1lbnRhdGlvbiBpcyA8YSBocmVmPSdodHRwczovL2dpdGh1Yi5jb20veHRldmUtcHJvamVjdC94VGVWZS1Eb2N1bWVudGF0aW9uL2Jsb2IvbWFzdGVyL2VuL2NvbmZpZ3VyYXRpb24ubWQjYXBpJz5oZXJlPC9hPiIKICAgIH0sCiAgICAiZXBnU291cmNlIjoKICAgIHsKICAgICAgInRpdGxlIjogIkVQRyBTb3VyY2UiLAogICAgICAiZGVzY3JpcHRpb24iOiAiUE1TOjxicj4tIFVzZSBFUEcgZGF0YSBmcm9tIFBsZXggb3IgRW1ieSA8YnI+PGJyPlhFUEc6PGJyPi0gVXNlIG9mIG9uZSBvciBtb3JlIFhNTFRWIGZpbGVzPGJyPi0gQ2hhbm5lbCBtYW5hZ2VtZW50PGJyPi0gTTNVIC8gWE1MVFYgZXhwb3J0IChIVFRQIGxpbmsgZm9yIElQVFYgYXBwcykiCiAgICB9LAogICAgInR1bmVyIjoKICAgIHsKICAgICAgInRpdGxlIjogIk51bWJlciBvZiBUdW5lcnMiLAogICAgICAiZGVzY3JpcHRpb24iOiAiTnVtYmVyIG9mIHBhcmFsbGVsIGNvbm5lY3Rpb25zIHRoYXQgY2FuIGJlIGVzdGFibGlzaGVkIHRvIHRoZSBwcm92aWRlci48YnI+QXZhaWxhYmxlIGZvcjogUGxleCwgRW1ieSAoSERIUiksIE0zVSAod2l0aCBhY3RpdmUgYnVmZmVyKS48YnI+QWZ0ZXIgYSBjaGFuZ2UsIHhUZVZlIG11c3QgYmUgZGVsZXRlIGluIHRoZSBQbGV4IC8gRW1ieSBEVlIgc2V0dGluZ3MgYW5kIHNldCB1cCBhZ2Fpbi4iCiAgICB9LAogICAgImZpbGVzVXBkYXRlIjoKICAgIHsKICAgICAgInRpdGxlIjogIlVwZGF0ZXMgYWxsIGZpbGVzIGF0IHN0YXJ0dXAiLAogICAgICAiZGVzY3JpcHRpb24iOiAiVXBkYXRlcyBhbGwgcGxheWxpc3RzLCB0dW5lciBhbmQgWE1MVFYgZmlsZXMgYXQgc3RhcnR1cC4iCiAgICB9LAogICAgImNhY2hlSW1hZ2VzIjoKICAgIHsKICAgICAgInRpdGxlIjogIkltYWdlIENhY2hpbmciLAogICAgICAiZGVzY3JpcHRpb24iOiAiQWxsIGltYWdlcyBmcm9tIHRoZSBYTUxUViBmaWxlIGFyZSBjYWNoZWQsIGFsbG93aW5nIGZhc3RlciByZW5kZXJpbmcgb2YgdGhlIGdyaWQgaW4gdGhlIGNsaWVudC48YnI+RG93bmxvYWRpbmcgdGhlIGltYWdlcyBtYXkgdGFrZSBhIHdoaWxlIGFuZCB3aWxsIGJlIGRvbmUgaW4gdGhlIGJhY2tncm91bmQuIgogICAgfSwKICAgICJyZXBsYWNlRW1wdHlJbWFnZXMiOgogICAgewogICAgICAidGl0bGUiOiAiUmVwbGFjZSBtaXNzaW5nIHByb2dyYW0gaW1hZ2VzIiwKICAgICAgImRlc2NyaXB0aW9uIjogIklmIHRoZSBwb3N0ZXIgaW4gdGhlIFhNTFRWIHByb2dyYW0gaXMgbWlzc2luZywgdGhlIGNoYW5uZWwgbG9nbyB3aWxsIGJlIHVzZWQuIgogICAgfSwKICAgICJ4dGV2ZUF1dG9VcGRhdGUiOgogICAgewogICAgICAidGl0bGUiOiAiQXV0b21hdGljIHVwZGF0ZSBvZiB4VGVWZSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJJZiBhIG5ldyB2ZXJzaW9uIG9mIHhUZVZlIGlzIGF2YWlsYWJsZSwgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGluc3RhbGxlZC4gVGhlIHVwZGF0ZXMgYXJlIGRvd25sb2FkZWQgZnJvbSBHaXRIdWIuIgogICAgfSwKICAgICJzdHJlYW1CdWZmZXJpbmciOgogICAgewogICAgICAidGl0bGUiOiAiU3RyZWFtIEJ1ZmZlciIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJGdW5jdGlvbnMgb2YgdGhlIGJ1ZmZlcjo8YnI+LSBUaGUgc3RyZWFtIGlzIHBhc3NlZCBmcm9tIHhUZVZlLCBGRm1wZWcgb3IgVkxDIHRvIFBsZXgsIEVtYnkgb3IgTTNVIFBsYXllcjxicj4tIFNtYWxsIGplcmtpbmcgb2YgdGhlIHN0cmVhbXMgY2FuIGJlIGNvbXBlbnNhdGVkPGJyPi0gSExTIC8gTTNVOCBzdXBwb3J0PGJyPi0gUlRQIC8gUlRQUyBzdXBwb3J0IChvbmx5IEZGbXBlZyBvciBWTEMpPGJyPi0gUmUtc3RyZWFtaW5nPGJyPi0gU2VwYXJhdGUgdHVuZXIgbGltaXQgZm9yIGVhY2ggcGxheWxpc3QiLAogICAgICAiaW5mb19mYWxzZSI6ICJObyBCdWZmZXIgKENsaWVudCBjb25uZWN0cyB0byB0aGUgc3RyZWFtaW5nIHNlcnZlcikiLAogICAgICAiaW5mb194dGV2ZSI6ICJ4VGVWZSBjb25uZWN0cyB0byB0aGUgc3RyZWFtaW5nIHNlcnZlciIsCiAgICAgICJpbmZvX2ZmbXBlZyI6ICJGRm1wZWcgY29ubmVjdHMgdG8gdGhlIHN0cmVhbWluZyBzZXJ2ZXIiLAogICAgICAiaW5mb192bGMiOiAiVkxDIGNvbm5lY3RzIHRvIHRoZSBzdHJlYW1pbmcgc2VydmVyIgoKICAgIH0sCiAgICAidWRweHkiOgogICAgewogICAgICAidGl0bGUiOiAiVURQeHkgYWRkcmVzcyIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJUaGUgYWRkcmVzcyBvZiB5b3VyIFVEUHh5IHNlcnZlci4gSWYgc2V0LCBhbmQgdGhlIGNoYW5uZWwgVVJMcyBpbiB0aGUgbTN1IGlzIG11bHRpY2FzdCwgeFRlVmUgd2lsbCByZXdyaXRlIGl0IHNvIHRoYXQgaXQgaXMgYWNjZXNzZWQgdmlhIHRoZSBVRFB4eSBzZXJ2aWNlLiIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJob3N0OnBvcnQiCiAgICB9LAogICAgImZmbXBlZ1BhdGgiOgogICAgewogICAgICAidGl0bGUiOiAiRkZtcGVnIEJpbmFyeSBQYXRoIiwKICAgICAgImRlc2NyaXB0aW9uIjogIlBhdGggdG8gRkZtcGVnIGJpbmFyeS4iLAogICAgICAicGxhY2Vob2xkZXIiOiAiL3BhdGgvdG8vZmZtcGVnIgogICAgfSwKICAgICJmZm1wZWdPcHRpb25zIjoKICAgIHsKICAgICAgInRpdGxlIjogIkZGbXBlZyBPcHRpb25zIiwKICAgICAgImRlc2NyaXB0aW9uIjogIkZGbXBlZyBvcHRpb25zLjxicj5Pbmx5IGNoYW5nZSBpZiB5b3Uga25vdyB3aGF0IHlvdSBhcmUgZG9pbmcuPGJyPkxlYXZlIGJsYW5rIHRvIHNldCBkZWZhdWx0IHNldHRpbmdzLiIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJMZWF2ZSBibGFuayB0byBzZXQgZGVmYXVsdCBzZXR0aW5ncyIKICAgIH0sCiAgICAidmxjUGF0aCI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJWTEMgLyBDVkxDIEJpbmFyeSBQYXRoIiwKICAgICAgImRlc2NyaXB0aW9uIjogIlBhdGggdG8gVkxDIC8gQ1ZMQyBiaW5hcnkuIiwKICAgICAgInBsYWNlaG9sZGVyIjogIi9wYXRoL3RvL2N2bGMiCiAgICB9LAogICAgInZsY09wdGlvbnMiOgogICAgewogICAgICAidGl0bGUiOiAiVkxDIC8gQ1ZMQyBPcHRpb25zIiwKICAgICAgImRlc2NyaXB0aW9uIjogIlZMQyAvIENWTEMgb3B0aW9ucy48YnI+T25seSBjaGFuZ2UgaWYgeW91IGtub3cgd2hhdCB5b3UgYXJlIGRvaW5nLjxicj5MZWF2ZSBibGFuayB0byBzZXQgZGVmYXVsdCBzZXR0aW5ncy4iLAogICAgICAicGxhY2Vob2xkZXIiOiAiTGVhdmUgYmxhbmsgdG8gc2V0IGRlZmF1bHQgc2V0dGluZ3MiCiAgICB9LAogICAgImJ1ZmZlclNpemUiOgogICAgewogICAgICAidGl0bGUiOiAiQnVmZmVyIFNpemUiLAogICAgICAiZGVzY3JpcHRpb24iOiAiQnVmZmVyIHNpemUgaW4gTUIuPGJyPk0zVTg6IElmIHRoZSBUUyBzZWdtZW50IHNtYWxsZXIgdGhlbiB0aGUgYnVmZmVyIHNpemUsIHRoZSBmaWxlIHNpemUgb2YgdGhlIHNlZ21lbnQgaXMgdXNlZC4iCiAgICB9LAogICAgImJ1ZmZlclRpbWVvdXQiOgogICAgewogICAgICAidGl0bGUiOiAiVGltZW91dCBmb3IgbmV3IGNsaWVudCBjb25uZWN0aW9ucyIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJUaGUgeFRlVmUgYnVmZmVyIHdhaXRzIHVudGlsIG5ldyBjbGllbnQgY29ubmVjdGlvbnMgYXJlIGVzdGFibGlzaGVkLiBIZWxwZnVsIGZvciBmYXN0IGNoYW5uZWwgc3dpdGNoaW5nLiBWYWx1ZSBpbiBtaWxsaXNlY29uZHMuIiwKICAgICAgInBsYWNlaG9sZGVyIjogIjEwMCIKICAgIH0sCiAgICAidXNlckFnZW50IjoKICAgIHsKICAgICAgInRpdGxlIjogIlVzZXIgQWdlbnQiLAogICAgICAiZGVzY3JpcHRpb24iOiAiVXNlciBBZ2VudCBmb3IgSFRUUCByZXF1ZXN0cy4gRm9yIGV2ZXJ5IEhUVFAgY29ubmVjdGlvbiwgdGhpcyB2YWx1ZSBpcyB1c2VkIGZvciB0aGUgdXNlciBhZ2VudC4gU2hvdWxkIG9ubHkgYmUgY2hhbmdlZCBpZiB4VGVWZSBpcyBibG9ja2VkLiIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJ4VGVWZSIKICAgIH0sCiAgICAiYmFja3VwUGF0aCI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJMb2NhdGlvbiBmb3IgYXV0b21hdGljIGJhY2t1cHMiLAogICAgICAicGxhY2Vob2xkZXIiOiAiL21udC9kYXRhL2JhY2t1cC94dGV2ZS8iLAogICAgICAiZGVzY3JpcHRpb24iOiAiQmVmb3JlIGFueSB1cGRhdGUgb2YgdGhlIHByb3ZpZGVyIGRhdGEgYnkgdGhlIHNjaGVkdWxlLCB4VGVWZSBjcmVhdGVzIGEgYmFja3VwLiBUaGUgcGF0aCBmb3IgdGhlIGF1dG9tYXRpYyBiYWNrdXBzIGNhbiBiZSBjaGFuZ2VkLiB4VGVWZSByZXF1aXJlcyB3cml0ZSBwZXJtaXNzaW9uIGZvciB0aGlzIGZvbGRlci4iCiAgICB9LAogICAgInRlbXBQYXRoIjoKICAgIHsKICAgICAgInRpdGxlIjogIkxvY2F0aW9uIGZvciB0aGUgdGVtcG9yYXJ5IGZpbGVzIiwKICAgICAgInBsYWNlaG9sZGVyIjogIi90bXAveHRldmUvIiwKICAgICAgImRlc2NyaXB0aW9uIjogIkxvY2F0aW9uIGZvciB0aGUgYnVmZmVyIGZpbGVzLiIKICAgIH0sCiAgICAiYmFja3VwS2VlcCI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJOdW1iZXIgb2YgYmFja3VwcyB0byBrZWVwIiwKICAgICAgImRlc2NyaXB0aW9uIjogIk51bWJlciBvZiBiYWNrdXBzIHRvIGtlZXAuIE9sZGVyIGJhY2t1cHMgYXJlIGF1dG9tYXRpY2FsbHkgZGVsZXRlZC4iCiAgICB9LAogICAgImF1dGhlbnRpY2F0aW9uV0VCIjoKICAgIHsKICAgICAgInRpdGxlIjogIldFQiBBdXRoZW50aWNhdGlvbiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJBY2Nlc3MgdG8gdGhlIHdlYiBpbnRlcmZhY2Ugb25seSBwb3NzaWJsZSB3aXRoIGNyZWRlbnRpYWxzLiIKICAgIH0sCiAgICAiYXV0aGVudGljYXRpb25QTVMiOgogICAgewogICAgICAidGl0bGUiOiAiUE1TIEF1dGhlbnRpY2F0aW9uIiwKICAgICAgImRlc2NyaXB0aW9uIjogIlBsZXggcmVxdWVzdHMgYXJlIG9ubHkgcG9zc2libGUgd2l0aCBhdXRoZW50aWNhdGlvbi4gPGJyPjxiPldhcm5pbmchISE8L2I+IEFmdGVyIGFjdGl2YXRpbmcgdGhpcyBmdW5jdGlvbiB4VGVWZSBtdXN0IGJlIGRlbGV0ZSBpbiB0aGUgUE1TIERWUiBzZXR0aW5ncyBhbmQgc2V0IHVwIGFnYWluLiIKICAgIH0sCiAgICAiYXV0aGVudGljYXRpb25NM1UiOgogICAgewogICAgICAidGl0bGUiOiAiTTNVIEF1dGhlbnRpY2F0aW9uIiwKICAgICAgImRlc2NyaXB0aW9uIjogIkRvd25sb2FkaW5nIHRoZSB4dGV2ZS5tM3UgZmlsZSB2aWEgYW4gSFRUUCByZXF1ZXN0IGlzIG9ubHkgcG9zc2libGUgd2l0aCBhdXRoZW50aWNhdGlvbi4iCiAgICB9LAogICAgImF1dGhlbnRpY2F0aW9uWE1MIjoKICAgIHsKICAgICAgInRpdGxlIjogIlhNTCBBdXRoZW50aWNhdGlvbiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJEb3dubG9hZGluZyB0aGUgeHRldmUueG1sIGZpbGUgdmlhIGFuIEhUVFAgcmVxdWVzdCBpcyBvbmx5IHBvc3NpYmxlIHdpdGggYXV0aGVudGljYXRpb24iCiAgICB9LAogICAgImF1dGhlbnRpY2F0aW9uQVBJIjoKICAgIHsKICAgICAgInRpdGxlIjogIkFQSSBBdXRoZW50aWNhdGlvbiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJBY2Nlc3MgdG8gdGhlIEFQSSBpbnRlcmZhY2UgaXMgb25seSBwb3NzaWJsZSB3aXRoIGF1dGhlbnRpY2F0aW9uLiIKICAgIH0KICB9LAogICJ3aXphcmQiOgogIHsKICAgICJlcGdTb3VyY2UiOgogICAgewogICAgICAidGl0bGUiOiAiRVBHIFNvdXJjZSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJQTVM6PGJyPi0gVXNlIEVQRyBkYXRhIGZyb20gUGxleCBvciBFbWJ5IDxicj48YnI+WEVQRzo8YnI+LSBVc2Ugb2Ygb25lIG9yIG1vcmUgWE1MVFYgZmlsZXM8YnI+LSBDaGFubmVsIG1hbmFnZW1lbnQ8YnI+LSBNM1UgLyBYTUxUViBleHBvcnQgKEhUVFAgbGluayBmb3IgSVBUViBhcHBzKSIKICAgIH0sCiAgICAidHVuZXIiOgogICAgewogICAgICAidGl0bGUiOiAiTnVtYmVyIG9mIHR1bmVycyIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJOdW1iZXIgb2YgcGFyYWxsZWwgY29ubmVjdGlvbnMgdGhhdCBjYW4gYmUgZXN0YWJsaXNoZWQgdG8gdGhlIHByb3ZpZGVyLjxicj5BdmFpbGFibGUgZm9yOiBQbGV4LCBFbWJ5IChIREhSKSwgTTNVICh3aXRoIGFjdGl2ZSBidWZmZXIpLjxicj5BZnRlciBhIGNoYW5nZSwgeFRlVmUgbXVzdCBiZSBkZWxldGUgaW4gdGhlIFBsZXggLyBFbWJ5IERWUiBzZXR0aW5ncyBhbmQgc2V0IHVwIGFnYWluLiIKICAgIH0sCiAgICAibTN1IjoKICAgIHsKICAgICAgInRpdGxlIjogIk0zVSBQbGF5bGlzdCIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJGaWxlIHBhdGggb3IgVVJMIG9mIHRoZSBNM1UiLAogICAgICAiZGVzY3JpcHRpb24iOiAiTG9jYWwgb3IgcmVtb3RlIHBsYXlsaXN0cyIKICAgIH0sCiAgICAieG1sdHYiOgogICAgewogICAgICAidGl0bGUiOiAiWE1MVFYgRmlsZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJGaWxlIHBhdGggb3IgVVJMIG9mIHRoZSBYTUxUViIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJMb2NhbCBvciByZW1vdGUgWE1MVFYgZmlsZSIKICAgIH0KICB9LAogICJsb2dpbiI6CiAgewogICAgImZhaWxlZCI6ICJVc2VyIGF1dGhlbnRpY2F0aW9uIGZhaWxlZCIsCiAgICAiaGVhZGxpbmUiOiAiTG9naW4iLAogICAgInVzZXJuYW1lIjoKICAgIHsKICAgICAgInRpdGxlIjogIlVzZXJuYW1lIiwKICAgICAgInBsYWNlaG9sZGVyIjogIlVzZXJuYW1lIgogICAgfSwKICAgICJwYXNzd29yZCI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJQYXNzd29yZCIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJQYXNzd29yZCIKICAgIH0KICB9LAogICJhY2NvdW50IjoKICB7CiAgICAiZmFpbGVkIjogIlBhc3N3b3JkIGRvZXMgbm90IG1hdGNoIiwKICAgICJoZWFkbGluZSI6ICJDcmVhdGUgdXNlciBhY2NvdW50IiwKICAgICJ1c2VybmFtZSI6CiAgICB7CiAgICAgICJ0aXRsZSI6ICJVc2VybmFtZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJVc2VybmFtZSIKICAgIH0sCiAgICAicGFzc3dvcmQiOgogICAgewogICAgICAidGl0bGUiOiAiUGFzc3dvcmQiLAogICAgICAicGxhY2Vob2xkZXIiOiAiUGFzc3dvcmQiCiAgICB9LAogICAgImNvbmZpcm0iOgogICAgewogICAgICAidGl0bGUiOiAiQ29uZmlybSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJDb25maXJtIgogICAgfQogIH0KfQ==" + webUI["html/index.html"] = "PCFkb2N0eXBlIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KCjxoZWFkPgogIDxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCIgLz4KICA8dGl0bGU+eFRlVmU8L3RpdGxlPgogIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL3NjcmVlbi5jc3MiIHR5cGU9InRleHQvY3NzIj4KICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9ImNzcy9iYXNlLmNzcyIgdHlwZT0idGV4dC9jc3MiPgoKICA8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvbmV0d29ya190cy5qcyI+PC9zY3JpcHQ+CiAgPHNjcmlwdCBsYW5ndWFnZT0iamF2YXNjcmlwdCIgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImpzL21lbnVfdHMuanMiPjwvc2NyaXB0PgogIDxzY3JpcHQgbGFuZ3VhZ2U9ImphdmFzY3JpcHQiIHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJqcy9zZXR0aW5nc190cy5qcyI+PC9zY3JpcHQ+CiAgPHNjcmlwdCBsYW5ndWFnZT0iamF2YXNjcmlwdCIgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImpzL2xvZ3NfdHMuanMiPjwvc2NyaXB0PgogIDxzY3JpcHQgbGFuZ3VhZ2U9ImphdmFzY3JpcHQiIHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJqcy9iYXNlX3RzLmpzIj48L3NjcmlwdD4KCjwvaGVhZD4KCjxib2R5IG9ubG9hZD0iamF2YXNjcmlwdDogUGFnZVJlYWR5KCk7Ij4KCiAgPGRpdiBpZD0ibG9hZGluZyIgY2xhc3M9Im5vbmUiPgogICAgPGRpdiBjbGFzcz0ibG9hZGVyIj48L2Rpdj4KICA8L2Rpdj4KCiAgPGRpdiBpZD0icG9wdXAiIGNsYXNzPSJub25lIj4KICAgIDxkaXYgaWQ9InBvcHVwLWN1c3RvbSI+PC9kaXY+CiAgPC9kaXY+CgogIDxkaXYgaWQ9ImxheW91dCI+CgogICAgPCEtLQogICAgICAgIDxkaXYgaWQ9Im5vdGlmaWNhdGlvbiI+CiAgICAgICAgICA8ZGl2IGNsYXNzPSJlbGVtZW50Ij4KICAgICAgICAgICAgPGg1PlhFUEc8L2g1PgogICAgICAgICAgICA8cHJlPjExLjA1LjIwMTkgLSAyMDoyMTwvcHJlPgogICAgICAgICAgICA8aHI+CiAgICAgICAgICAgIDxwPkhhbGxvIGRhcyBpc3QgZWluIFRlc3QuIFVuZCBub2NoIG1laHIgVGV4dC48L3A+CiAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KICAgICAgLS0+CgogICAgPGRpdiBpZD0ibWVudS13cmFwcGVyIiBjbGFzcz0ibGF5b3V0LWxlZnQiPgogICAgICA8ZGl2IGlkPSJicmFuY2giPjwvZGl2PgogICAgICA8ZGl2IGlkPSJsb2dvIj48L2Rpdj4KICAgICAgPG5hdiBpZD0ibWFpbi1tZW51Ij48L25hdj4KICAgIDwvZGl2PgoKICAgIDxkaXYgY2xhc3M9ImxheW91dC1yaWdodCI+CgogICAgICA8dGFibGUgaWQ9ImNsaWVudEluZm8iIGNsYXNzPSIiPgoKICAgICAgICA8dHI+CiAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij54VGVWZTo8L3RkPgogICAgICAgICAgPHRkIGlkPSJ2ZXJzaW9uIiBjbGFzcz0idGRWYWwiPiZuYnNwOzwvdGQ+CiAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij5PUzo8L3RkPgogICAgICAgICAgPHRkIGlkPSJvcyIgY2xhc3M9InRkVmFsIj4mbmJzcDs8L3RkPgogICAgICAgICAgPHRkIGNsYXNzPSJ0ZEtleSBwaG9uZSI+RFZSIElQOjwvdGQ+CiAgICAgICAgICA8dGQgaWQ9IkRWUiIgY2xhc3M9InRkVmFsTGluayBwaG9uZSI+Jm5ic3A7PC90ZD4KICAgICAgICA8L3RyPgoKICAgICAgICA8dHI+CiAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij5VVUlEOjwvdGQ+CiAgICAgICAgICA8dGQgaWQ9InV1aWQiIGNsYXNzPSJ0ZFZhbCI+Jm5ic3A7PC90ZD4KICAgICAgICAgIDx0ZCBjbGFzcz0idGRLZXkiPkFyY2g6PC90ZD4KICAgICAgICAgIDx0ZCBpZD0iYXJjaCIgY2xhc3M9InRkVmFsIj4mbmJzcDs8L3RkPgogICAgICAgICAgPHRkIGNsYXNzPSJ0ZEtleSBwaG9uZSI+TTNVIFVSTDo8L3RkPgogICAgICAgICAgPHRkIGlkPSJtM3UtdXJsIiBjbGFzcz0idGRWYWxMaW5rIHBob25lIj4mbmJzcDs8L3RkPgogICAgICAgIDwvdHI+CgogICAgICAgIDx0cj4KICAgICAgICAgIDx0ZCBjbGFzcz0idGRLZXkiPkF2YWlsYWJsZSBTdHJlYW1zOjwvdGQ+CiAgICAgICAgICA8dGQgaWQ9InN0cmVhbXMiIGNsYXNzPSJ0ZFZhbCI+Jm5ic3A7PC90ZD4KICAgICAgICAgIDx0ZCBjbGFzcz0idGRLZXkiPkVQRyBTb3VyY2U6PC90ZD4KICAgICAgICAgIDx0ZCBpZD0iZXBnU291cmNlIiBjbGFzcz0idGRWYWwiPiZuYnNwOzwvdGQ+CiAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5IHBob25lIj5YRVBHIFVSTDo8L3RkPgogICAgICAgICAgPHRkIGlkPSJ4ZXBnLXVybCIgY2xhc3M9InRkVmFsTGluayBwaG9uZSI+Jm5ic3A7PC90ZD4KICAgICAgICA8L3RyPgoKICAgICAgICA8dHI+CiAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij5YRVBHIENoYW5uZWxzOjwvdGQ+CiAgICAgICAgICA8dGQgaWQ9InhlcGciIGNsYXNzPSJ0ZFZhbCI+Jm5ic3A7PC90ZD4KICAgICAgICAgIDx0ZCBjbGFzcz0idGRLZXkiPkVycm9yczo8L3RkPgogICAgICAgICAgPHRkIGlkPSJlcnJvcnMiIGNsYXNzPSJ0ZFZhbCI+Jm5ic3A7PC90ZD4KICAgICAgICAgIDx0ZCBjbGFzcz0idGRLZXkiPldhcm5pbmdzOjwvdGQ+CiAgICAgICAgICA8dGQgaWQ9Indhcm5pbmdzIiBjbGFzcz0idGRWYWwiPiZuYnNwOzwvdGQ+CiAgICAgICAgPC90cj4KCiAgICAgIDwvdGFibGU+CgogICAgICA8ZGl2IGlkPSJteVN0cmVhbXNCb3giIGNsYXNzPSJub3RWaXNpYmxlIj4KCiAgICAgICAgPGRpdiBpZD0iYWxsU3RyZWFtcyI+CiAgICAgICAgICA8dGFibGUgaWQ9ImFjdGl2ZVN0cmVhbXMiPjwvdGFibGU+CiAgICAgICAgICA8dGFibGUgaWQ9ImluYWN0aXZlU3RyZWFtcyI+PC90YWJsZT4KICAgICAgICA8L2Rpdj4KCiAgICAgIDwvZGl2PgoKICAgICAgPGRpdiBpZD0iY29udGVudCIgY2xhc3M9IiI+PC9kaXY+CgogICAgPC9kaXY+CgogIDwvZGl2PgoKPC9ib2R5PgoKPC9odG1sPg==" + webUI["html/js/authentication_ts.js"] = "ZnVuY3Rpb24gbG9naW4oKSB7CiAgICB2YXIgZXJyID0gZmFsc2U7CiAgICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICAgIHZhciBkaXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiY29udGVudCIpOwogICAgdmFyIGZvcm0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiYXV0aGVudGljYXRpb24iKTsKICAgIHZhciBpbnB1dHMgPSBkaXYuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIklOUFVUIik7CiAgICBmb3IgKHZhciBpID0gaW5wdXRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgICAgdmFyIGtleSA9IGlucHV0c1tpXS5uYW1lOwogICAgICAgIHZhciB2YWx1ZSA9IGlucHV0c1tpXS52YWx1ZTsKICAgICAgICBpZiAodmFsdWUubGVuZ3RoID09IDApIHsKICAgICAgICAgICAgaW5wdXRzW2ldLnN0eWxlLmJvcmRlckNvbG9yID0gInJlZCI7CiAgICAgICAgICAgIGVyciA9IHRydWU7CiAgICAgICAgfQogICAgICAgIGRhdGFba2V5XSA9IHZhbHVlOwogICAgfQogICAgaWYgKGVyciA9PSB0cnVlKSB7CiAgICAgICAgZGF0YSA9IG5ldyBPYmplY3QoKTsKICAgICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eSgiY29uZmlybSIpKSB7CiAgICAgICAgaWYgKGRhdGFbImNvbmZpcm0iXSAhPSBkYXRhWyJwYXNzd29yZCJdKSB7CiAgICAgICAgICAgIGFsZXJ0KCJzZGFmc2QiKTsKICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3Bhc3N3b3JkJykuc3R5bGUuYm9yZGVyQ29sb3IgPSAicmVkIjsKICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2NvbmZpcm0nKS5zdHlsZS5ib3JkZXJDb2xvciA9ICJyZWQiOwogICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiZXJyIikuaW5uZXJIVE1MID0gInt7LmFjY291bnQuZmFpbGVkfX0iOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgfQogICAgZm9ybS5zdWJtaXQoKTsKfQo=" + webUI["html/js/base_ts.js"] = "dmFyIFNFUlZFUiA9IG5ldyBPYmplY3QoKTsKdmFyIEJVTEtfRURJVCA9IGZhbHNlOwp2YXIgQ09MVU1OX1RPX1NPUlQ7CnZhciBTRUFSQ0hfTUFQUElORyA9IG5ldyBPYmplY3QoKTsKdmFyIFVORE8gPSBuZXcgT2JqZWN0KCk7CnZhciBTRVJWRVJfQ09OTkVDVElPTiA9IGZhbHNlOwp2YXIgV1NfQVZBSUxBQkxFID0gZmFsc2U7Ci8vIE1lbnUKdmFyIG1lbnVJdGVtcyA9IG5ldyBBcnJheSgpOwptZW51SXRlbXMucHVzaChuZXcgTWFpbk1lbnVJdGVtKCJwbGF5bGlzdCIsICJ7ey5tYWluTWVudS5pdGVtLnBsYXlsaXN0fX0iLCAibTN1LnBuZyIsICJ7ey5tYWluTWVudS5oZWFkbGluZS5wbGF5bGlzdH19IikpOwptZW51SXRlbXMucHVzaChuZXcgTWFpbk1lbnVJdGVtKCJmaWx0ZXIiLCAie3subWFpbk1lbnUuaXRlbS5maWx0ZXJ9fSIsICJmaWx0ZXIucG5nIiwgInt7Lm1haW5NZW51LmhlYWRsaW5lLmZpbHRlcn19IikpOwptZW51SXRlbXMucHVzaChuZXcgTWFpbk1lbnVJdGVtKCJ4bWx0diIsICJ7ey5tYWluTWVudS5pdGVtLnhtbHR2fX0iLCAieG1sdHYucG5nIiwgInt7Lm1haW5NZW51LmhlYWRsaW5lLnhtbHR2fX0iKSk7Cm1lbnVJdGVtcy5wdXNoKG5ldyBNYWluTWVudUl0ZW0oIm1hcHBpbmciLCAie3subWFpbk1lbnUuaXRlbS5tYXBwaW5nfX0iLCAibWFwcGluZy5wbmciLCAie3subWFpbk1lbnUuaGVhZGxpbmUubWFwcGluZ319IikpOwptZW51SXRlbXMucHVzaChuZXcgTWFpbk1lbnVJdGVtKCJ1c2VycyIsICJ7ey5tYWluTWVudS5pdGVtLnVzZXJzfX0iLCAidXNlcnMucG5nIiwgInt7Lm1haW5NZW51LmhlYWRsaW5lLnVzZXJzfX0iKSk7Cm1lbnVJdGVtcy5wdXNoKG5ldyBNYWluTWVudUl0ZW0oInNldHRpbmdzIiwgInt7Lm1haW5NZW51Lml0ZW0uc2V0dGluZ3N9fSIsICJzZXR0aW5ncy5wbmciLCAie3subWFpbk1lbnUuaGVhZGxpbmUuc2V0dGluZ3N9fSIpKTsKbWVudUl0ZW1zLnB1c2gobmV3IE1haW5NZW51SXRlbSgibG9nIiwgInt7Lm1haW5NZW51Lml0ZW0ubG9nfX0iLCAibG9nLnBuZyIsICJ7ey5tYWluTWVudS5oZWFkbGluZS5sb2d9fSIpKTsKbWVudUl0ZW1zLnB1c2gobmV3IE1haW5NZW51SXRlbSgibG9nb3V0IiwgInt7Lm1haW5NZW51Lml0ZW0ubG9nb3V0fX0iLCAibG9nb3V0LnBuZyIsICJ7ey5tYWluTWVudS5oZWFkbGluZS5sb2dvdXR9fSIpKTsKLy8gU2V0dGluZ3MgY2F0ZWdvcmllcwp2YXIgc2V0dGluZ3NDYXRlZ29yeSA9IG5ldyBBcnJheSgpOwpzZXR0aW5nc0NhdGVnb3J5LnB1c2gobmV3IFNldHRpbmdzQ2F0ZWdvcnlJdGVtKCJ7ey5zZXR0aW5ncy5jYXRlZ29yeS5nZW5lcmFsfX0iLCAidGxzTW9kZSx4dGV2ZUF1dG9VcGRhdGUsaG9zdElQLGhvc3ROYW1lLHR1bmVyLGVwZ1NvdXJjZSxkaXNhbGxvd1VSTER1cGxpY2F0ZXMsY2xlYXJYTUxUVkNhY2hlLGFwaSIpKTsKc2V0dGluZ3NDYXRlZ29yeS5wdXNoKG5ldyBTZXR0aW5nc0NhdGVnb3J5SXRlbSgie3suc2V0dGluZ3MuY2F0ZWdvcnkubWFwcGluZ319IiwgImRlZmF1bHRNaXNzaW5nRVBHLGVuYWJsZU1hcHBlZENoYW5uZWxzIikpOwpzZXR0aW5nc0NhdGVnb3J5LnB1c2gobmV3IFNldHRpbmdzQ2F0ZWdvcnlJdGVtKCJ7ey5zZXR0aW5ncy5jYXRlZ29yeS5maWxlc319IiwgInVwZGF0ZSxmaWxlcy51cGRhdGUsdGVtcC5wYXRoLGNhY2hlLmltYWdlcyx4ZXBnLnJlcGxhY2UubWlzc2luZy5pbWFnZXMiKSk7CnNldHRpbmdzQ2F0ZWdvcnkucHVzaChuZXcgU2V0dGluZ3NDYXRlZ29yeUl0ZW0oInt7LnNldHRpbmdzLmNhdGVnb3J5LnN0cmVhbWluZ319IiwgImJ1ZmZlcix1ZHB4eSxidWZmZXIuc2l6ZS5rYixzdG9yZUJ1ZmZlckluUkFNLGJ1ZmZlci50aW1lb3V0LHVzZXIuYWdlbnQsZmZtcGVnLnBhdGgsZmZtcGVnLm9wdGlvbnMsdmxjLnBhdGgsdmxjLm9wdGlvbnMiKSk7CnNldHRpbmdzQ2F0ZWdvcnkucHVzaChuZXcgU2V0dGluZ3NDYXRlZ29yeUl0ZW0oInt7LnNldHRpbmdzLmNhdGVnb3J5LmJhY2t1cH19IiwgImJhY2t1cC5wYXRoLGJhY2t1cC5rZWVwIikpOwpzZXR0aW5nc0NhdGVnb3J5LnB1c2gobmV3IFNldHRpbmdzQ2F0ZWdvcnlJdGVtKCJ7ey5zZXR0aW5ncy5jYXRlZ29yeS5hdXRoZW50aWNhdGlvbn19IiwgImF1dGhlbnRpY2F0aW9uLndlYixhdXRoZW50aWNhdGlvbi5wbXMsYXV0aGVudGljYXRpb24ubTN1LGF1dGhlbnRpY2F0aW9uLnhtbCxhdXRoZW50aWNhdGlvbi5hcGkiKSk7CmZ1bmN0aW9uIHNob3dQb3BVcEVsZW1lbnQoZWxtKSB7CiAgICB2YXIgYWxsRWxlbWVudHMgPSBuZXcgQXJyYXkoInBvcHVwLWN1c3RvbSIpOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhbGxFbGVtZW50cy5sZW5ndGg7IGkrKykgewogICAgICAgIHNob3dFbGVtZW50KGFsbEVsZW1lbnRzW2ldLCBmYWxzZSk7CiAgICB9CiAgICBzaG93RWxlbWVudChlbG0sIHRydWUpOwogICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7CiAgICAgICAgc2hvd0VsZW1lbnQoInBvcHVwIiwgdHJ1ZSk7CiAgICB9LCAxMCk7CiAgICByZXR1cm47Cn0KZnVuY3Rpb24gc2hvd0VsZW1lbnQoZWxtSUQsIHR5cGUpIHsKICAgIHZhciBjc3NDbGFzczsKICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgIGNhc2UgdHJ1ZToKICAgICAgICAgICAgY3NzQ2xhc3MgPSAiYmxvY2siOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIGZhbHNlOgogICAgICAgICAgICBjc3NDbGFzcyA9ICJub25lIjsKICAgICAgICAgICAgYnJlYWs7CiAgICB9CiAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbG1JRCkuY2xhc3NOYW1lID0gY3NzQ2xhc3M7Cn0KZnVuY3Rpb24gY2hhbmdlQnV0dG9uQWN0aW9uKGVsZW1lbnQsIGJ1dHRvbklELCBhdHRyaWJ1dGUpIHsKICAgIHZhciB2YWx1ZSA9IGVsZW1lbnQub3B0aW9uc1tlbGVtZW50LnNlbGVjdGVkSW5kZXhdLnZhbHVlOwogICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoYnV0dG9uSUQpLnNldEF0dHJpYnV0ZShhdHRyaWJ1dGUsIHZhbHVlKTsKfQpmdW5jdGlvbiBnZXRMb2NhbERhdGEoZGF0YVR5cGUsIGlkKSB7CiAgICBsZXQgZGF0YSA9IHt9OwogICAgc3dpdGNoIChkYXRhVHlwZSkgewogICAgICAgIGNhc2UgIm0zdSI6CiAgICAgICAgICAgIGRhdGEgPSBTRVJWRVJbInNldHRpbmdzIl1bImZpbGVzIl1bZGF0YVR5cGVdW2lkXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiaGRociI6CiAgICAgICAgICAgIGRhdGEgPSBTRVJWRVJbInNldHRpbmdzIl1bImZpbGVzIl1bZGF0YVR5cGVdW2lkXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZmlsdGVyIjoKICAgICAgICBjYXNlICJjdXN0b20tZmlsdGVyIjoKICAgICAgICBjYXNlICJncm91cC10aXRsZSI6CiAgICAgICAgICAgIGlmIChpZCA9PSAtMSkgewogICAgICAgICAgICAgICAgZGF0YVsiYWN0aXZlIl0gPSB0cnVlOwogICAgICAgICAgICAgICAgZGF0YVsiY2FzZVNlbnNpdGl2ZSJdID0gZmFsc2U7CiAgICAgICAgICAgICAgICBkYXRhWyJkZXNjcmlwdGlvbiJdID0gIiI7CiAgICAgICAgICAgICAgICBkYXRhWyJleGNsdWRlIl0gPSAiIjsKICAgICAgICAgICAgICAgIGRhdGFbImZpbHRlciJdID0gIiI7CiAgICAgICAgICAgICAgICBkYXRhWyJpbmNsdWRlIl0gPSAiIjsKICAgICAgICAgICAgICAgIGRhdGFbIm5hbWUiXSA9ICIiOwogICAgICAgICAgICAgICAgZGF0YVsidHlwZSJdID0gImdyb3VwLXRpdGxlIjsKICAgICAgICAgICAgICAgIGRhdGFbInByZXNlcnZlTWFwcGluZyJdID0gdHJ1ZTsKICAgICAgICAgICAgICAgIGRhdGFbInN0YXJ0aW5nQ2hhbm5lbCJdID0gU0VSVkVSWyJzZXR0aW5ncyJdWyJtYXBwaW5nLmZpcnN0LmNoYW5uZWwiXTsKICAgICAgICAgICAgICAgIFNFUlZFUlsic2V0dGluZ3MiXVsiZmlsdGVyIl1baWRdID0gZGF0YTsKICAgICAgICAgICAgfQogICAgICAgICAgICBkYXRhID0gU0VSVkVSWyJzZXR0aW5ncyJdWyJmaWx0ZXIiXVtpZF07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInhtbHR2IjoKICAgICAgICAgICAgZGF0YSA9IFNFUlZFUlsic2V0dGluZ3MiXVsiZmlsZXMiXVtkYXRhVHlwZV1baWRdOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJ1c2VycyI6CiAgICAgICAgICAgIGRhdGEgPSBTRVJWRVJbInVzZXJzIl1baWRdWyJkYXRhIl07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm1hcHBpbmciOgogICAgICAgICAgICBkYXRhID0gU0VSVkVSWyJ4ZXBnIl1bImVwZ01hcHBpbmciXVtpZF07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm0zdUdyb3VwcyI6CiAgICAgICAgICAgIGRhdGEgPSBTRVJWRVJbImRhdGEiXVsicGxheWxpc3QiXVsibTN1Il1bImdyb3VwcyJdOwogICAgICAgICAgICBicmVhazsKICAgIH0KICAgIHJldHVybiBkYXRhOwp9CmZ1bmN0aW9uIGdldE93bk9ialByb3BzKG9iamVjdCkgewogICAgcmV0dXJuIG9iamVjdCA/IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKG9iamVjdCkgOiBbXTsKfQpmdW5jdGlvbiBnZXRBbGxTZWxlY3RlZENoYW5uZWxzKCkgewogICAgdmFyIGNoYW5uZWxzID0gbmV3IEFycmF5KCk7CiAgICBpZiAoQlVMS19FRElUID09IGZhbHNlKSB7CiAgICAgICAgcmV0dXJuIGNoYW5uZWxzOwogICAgfQogICAgdmFyIHRycyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJjb250ZW50X3RhYmxlIikuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlRSIik7CiAgICBmb3IgKHZhciBpID0gMTsgaSA8IHRycy5sZW5ndGg7IGkrKykgewogICAgICAgIGlmICh0cnNbaV0uc3R5bGUuZGlzcGxheSAhPSAibm9uZSIpIHsKICAgICAgICAgICAgaWYgKHRyc1tpXS5maXJzdENoaWxkLmZpcnN0Q2hpbGQuY2hlY2tlZCA9PSB0cnVlKSB7CiAgICAgICAgICAgICAgICBjaGFubmVscy5wdXNoKHRyc1tpXS5pZCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICByZXR1cm4gY2hhbm5lbHM7Cn0KZnVuY3Rpb24gc2VsZWN0QWxsQ2hhbm5lbHMoKSB7CiAgICB2YXIgYnVsayA9IGZhbHNlOwogICAgdmFyIHRycyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJjb250ZW50X3RhYmxlIikuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlRSIik7CiAgICBpZiAodHJzWzBdLmZpcnN0Q2hpbGQuZmlyc3RDaGlsZC5jaGVja2VkID09IHRydWUpIHsKICAgICAgICBidWxrID0gdHJ1ZTsKICAgIH0KICAgIGZvciAodmFyIGkgPSAxOyBpIDwgdHJzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgaWYgKHRyc1tpXS5zdHlsZS5kaXNwbGF5ICE9ICJub25lIikgewogICAgICAgICAgICBzd2l0Y2ggKGJ1bGspIHsKICAgICAgICAgICAgICAgIGNhc2UgdHJ1ZToKICAgICAgICAgICAgICAgICAgICB0cnNbaV0uZmlyc3RDaGlsZC5maXJzdENoaWxkLmNoZWNrZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSBmYWxzZToKICAgICAgICAgICAgICAgICAgICB0cnNbaV0uZmlyc3RDaGlsZC5maXJzdENoaWxkLmNoZWNrZWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KICAgIHJldHVybjsKfQpmdW5jdGlvbiBidWxrRWRpdCgpIHsKICAgIEJVTEtfRURJVCA9ICFCVUxLX0VESVQ7CiAgICB2YXIgY2xhc3NOYW1lOwogICAgdmFyIHJvd3MgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCJidWxrIik7CiAgICBzd2l0Y2ggKEJVTEtfRURJVCkgewogICAgICAgIGNhc2UgdHJ1ZToKICAgICAgICAgICAgY2xhc3NOYW1lID0gImJ1bGsgc2hvd0J1bGsiOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIGZhbHNlOgogICAgICAgICAgICBjbGFzc05hbWUgPSAiYnVsayBoaWRlQnVsayI7CiAgICAgICAgICAgIGJyZWFrOwogICAgfQogICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3dzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgcm93c1tpXS5jbGFzc05hbWUgPSBjbGFzc05hbWU7CiAgICAgICAgcm93c1tpXS5jaGVja2VkID0gZmFsc2U7CiAgICB9CiAgICByZXR1cm47Cn0KZnVuY3Rpb24gc29ydFRhYmxlKGNvbHVtbikgewogICAgaWYgKGNvbHVtbiA9PSBDT0xVTU5fVE9fU09SVCkgewogICAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHRhYmxlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImNvbnRlbnRfdGFibGUiKTsKICAgIGNvbnN0IHRhYmxlSGVhZCA9IHRhYmxlLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJUUiIpWzBdOwogICAgY29uc3QgdGFibGVJdGVtcyA9IHRhYmxlSGVhZC5nZXRFbGVtZW50c0J5VGFnTmFtZSgiVEQiKTsKICAgIGNvbnN0IHNvcnRBcnIgPSBbXTsKICAgIGxldCB4VmFsdWU7CiAgICBpZiAoY29sdW1uID49IDAgJiYgQ09MVU1OX1RPX1NPUlQgPj0gMCkgewogICAgICAgIHRhYmxlSXRlbXNbQ09MVU1OX1RPX1NPUlRdLmNsYXNzTmFtZSA9ICJwb2ludGVyIjsKICAgICAgICB0YWJsZUl0ZW1zW2NvbHVtbl0uY2xhc3NOYW1lID0gInNvcnRUaGlzIjsKICAgIH0KICAgIENPTFVNTl9UT19TT1JUID0gY29sdW1uOwogICAgY29uc3Qgcm93cyA9IHRhYmxlLnJvd3M7CiAgICBpZiAocm93c1sxXSAhPSB1bmRlZmluZWQpIHsKICAgICAgICBjb25zdCB0YWJsZUhlYWRlciA9IHJvd3NbMF07CiAgICAgICAgbGV0IHggPSByb3dzWzFdLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJURCIpW2NvbHVtbl07CiAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCByb3dzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIHggPSByb3dzW2ldLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJURCIpW2NvbHVtbl07CiAgICAgICAgICAgIHN3aXRjaCAoeC5jaGlsZE5vZGVzWzBdLnRhZ05hbWUudG9Mb3dlckNhc2UoKSkgewogICAgICAgICAgICAgICAgY2FzZSAiaW5wdXQiOgogICAgICAgICAgICAgICAgICAgIHhWYWx1ZSA9IHguZ2V0RWxlbWVudHNCeVRhZ05hbWUoIklOUFVUIilbMF0udmFsdWUudG9Mb3dlckNhc2UoKTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgInAiOgogICAgICAgICAgICAgICAgICAgIHhWYWx1ZSA9IHguZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlAiKVswXS5pbm5lclRleHQudG9Mb3dlckNhc2UoKTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc29ydEFyci5wdXNoKHsga2V5OiB4VmFsdWUgPyB4VmFsdWUgOiBpLCByb3c6IHJvd3NbaV0gfSk7CiAgICAgICAgfQogICAgICAgIHdoaWxlICh0YWJsZS5maXJzdENoaWxkKSB7CiAgICAgICAgICAgIHRhYmxlLnJlbW92ZUNoaWxkKHRhYmxlLmZpcnN0Q2hpbGQpOwogICAgICAgIH0KICAgICAgICBzb3J0QXJyLnNvcnQoKHNlMSwgc2UyKSA9PiB7CiAgICAgICAgICAgIGNvbnN0IHNlMUtleU51bSA9IHBhcnNlRmxvYXQoU3RyaW5nKHNlMS5rZXkpKTsKICAgICAgICAgICAgY29uc3Qgc2UyS2V5TnVtID0gcGFyc2VGbG9hdChTdHJpbmcoc2UyLmtleSkpOwogICAgICAgICAgICBpZiAoIWlzTmFOKHNlMUtleU51bSkgJiYgIWlzTmFOKHNlMktleU51bSkpIHsKICAgICAgICAgICAgICAgIHJldHVybiBzZTFLZXlOdW0gLSBzZTJLZXlOdW07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHNlMS5rZXkgPCBzZTIua2V5KSB7CiAgICAgICAgICAgICAgICByZXR1cm4gLTE7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHNlMS5rZXkgPiBzZTIua2V5KSB7CiAgICAgICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICB9KTsKICAgICAgICB0YWJsZS5hcHBlbmRDaGlsZCh0YWJsZUhlYWRlcik7CiAgICAgICAgc29ydEFyci5mb3JFYWNoKChzZSkgPT4gewogICAgICAgICAgICB0YWJsZS5hcHBlbmRDaGlsZChzZS5yb3cpOwogICAgICAgIH0pOwogICAgfQogICAgcmV0dXJuOwp9CmZ1bmN0aW9uIGNyZWF0ZVNlYXJjaE9iaigpIHsKICAgIFNFQVJDSF9NQVBQSU5HID0gbmV3IE9iamVjdCgpOwogICAgdmFyIGRhdGEgPSBTRVJWRVJbInhlcGciXVsiZXBnTWFwcGluZyJdOwogICAgdmFyIGNoYW5uZWxzID0gZ2V0T3duT2JqUHJvcHMoZGF0YSk7CiAgICB2YXIgY2hhbm5lbEtleXMgPSBbIngtYWN0aXZlIiwgIngtY2hhbm5lbElEIiwgIngtbmFtZSIsICJ1cGRhdGVDaGFubmVsTmFtZVJlZ2V4IiwgIl9maWxlLm0zdS5uYW1lIiwgIngtZ3JvdXAtdGl0bGUiLCAieC14bWx0di1maWxlIl07CiAgICBjaGFubmVscy5mb3JFYWNoKGlkID0+IHsKICAgICAgICBjaGFubmVsS2V5cy5mb3JFYWNoKGtleSA9PiB7CiAgICAgICAgICAgIGlmIChrZXkgPT0gIngtYWN0aXZlIikgewogICAgICAgICAgICAgICAgc3dpdGNoIChkYXRhW2lkXVtrZXldKSB7CiAgICAgICAgICAgICAgICAgICAgY2FzZSB0cnVlOgogICAgICAgICAgICAgICAgICAgICAgICBTRUFSQ0hfTUFQUElOR1tpZF0gPSAib25saW5lICI7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIGNhc2UgZmFsc2U6CiAgICAgICAgICAgICAgICAgICAgICAgIFNFQVJDSF9NQVBQSU5HW2lkXSA9ICJvZmZsaW5lICI7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgaWYgKGtleSA9PSAieC14bWx0di1maWxlIikgewogICAgICAgICAgICAgICAgICAgIHZhciB4bWx0dkZpbGUgPSBnZXRWYWx1ZUZyb21Qcm92aWRlckZpbGUoZGF0YVtpZF1ba2V5XSwgInhtbHR2IiwgIm5hbWUiKTsKICAgICAgICAgICAgICAgICAgICBpZiAoeG1sdHZGaWxlICE9IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgICAgICAgICBTRUFSQ0hfTUFQUElOR1tpZF0gPSBTRUFSQ0hfTUFQUElOR1tpZF0gKyB4bWx0dkZpbGUgKyAiICI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgU0VBUkNIX01BUFBJTkdbaWRdID0gU0VBUkNIX01BUFBJTkdbaWRdICsgZGF0YVtpZF1ba2V5XSArICIgIjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0pOwogICAgfSk7CiAgICByZXR1cm47Cn0KZnVuY3Rpb24gc2VhcmNoSW5NYXBwaW5nKCkgewogICAgdmFyIHNlYXJjaFZhbHVlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNlYXJjaE1hcHBpbmciKS52YWx1ZTsKICAgIHZhciB0cnMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiY29udGVudF90YWJsZSIpLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJUUiIpOwogICAgZm9yICh2YXIgaSA9IDE7IGkgPCB0cnMubGVuZ3RoOyArK2kpIHsKICAgICAgICB2YXIgaWQgPSB0cnNbaV0uZ2V0QXR0cmlidXRlKCJpZCIpOwogICAgICAgIHZhciBlbGVtZW50ID0gU0VBUkNIX01BUFBJTkdbaWRdOwogICAgICAgIHN3aXRjaCAoZWxlbWVudC50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHNlYXJjaFZhbHVlLnRvTG93ZXJDYXNlKCkpKSB7CiAgICAgICAgICAgIGNhc2UgdHJ1ZToKICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5zdHlsZS5kaXNwbGF5ID0gIiI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSBmYWxzZToKICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5zdHlsZS5kaXNwbGF5ID0gIm5vbmUiOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuOwp9CmZ1bmN0aW9uIGNhbGN1bGF0ZVdyYXBwZXJIZWlnaHQoKSB7CiAgICBpZiAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJveC13cmFwcGVyIikpIHsKICAgICAgICB2YXIgZWxtID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJveC13cmFwcGVyIik7CiAgICAgICAgdmFyIGRpdnMgPSBuZXcgQXJyYXkoIm15U3RyZWFtc0JveCIsICJjbGllbnRJbmZvIiwgImNvbnRlbnQiKTsKICAgICAgICB2YXIgZWxlbWVudHNIZWlnaHQgPSAwIC0gZWxtLm9mZnNldEhlaWdodDsKICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRpdnMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgZWxlbWVudHNIZWlnaHQgPSBlbGVtZW50c0hlaWdodCArIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGRpdnNbaV0pLm9mZnNldEhlaWdodDsKICAgICAgICB9CiAgICAgICAgZWxtLnN0eWxlLmhlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodCAtIGVsZW1lbnRzSGVpZ2h0ICsgInB4IjsKICAgIH0KICAgIHJldHVybjsKfQpmdW5jdGlvbiBjaGFuZ2VDaGFubmVsTnVtYmVyKGVsZW1lbnQpIHsKICAgIHZhciBkYklEID0gZWxlbWVudC5wYXJlbnROb2RlLnBhcmVudE5vZGUuaWQ7CiAgICB2YXIgbmV3TnVtYmVyID0gcGFyc2VGbG9hdChlbGVtZW50LnZhbHVlKTsKICAgIHZhciBjaGFubmVsTnVtYmVycyA9IFtdOwogICAgdmFyIGRhdGEgPSBTRVJWRVJbInhlcGciXVsiZXBnTWFwcGluZyJdOwogICAgdmFyIGNoYW5uZWxzID0gZ2V0T3duT2JqUHJvcHMoZGF0YSk7CiAgICBpZiAoaXNOYU4obmV3TnVtYmVyKSkgewogICAgICAgIGFsZXJ0KCJ7ey5hbGVydC5pbnZhbGlkQ2hhbm5lbE51bWJlcn19Iik7CiAgICAgICAgcmV0dXJuOwogICAgfQogICAgY2hhbm5lbHMuZm9yRWFjaChpZCA9PiB7CiAgICAgICAgdmFyIGNoYW5uZWxOdW1iZXIgPSBwYXJzZUZsb2F0KGRhdGFbaWRdWyJ4LWNoYW5uZWxJRCJdKTsKICAgICAgICBjaGFubmVsTnVtYmVycy5wdXNoKGNoYW5uZWxOdW1iZXIpOwogICAgfSk7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoYW5uZWxOdW1iZXJzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgaWYgKGNoYW5uZWxOdW1iZXJzLmluZGV4T2YobmV3TnVtYmVyKSA9PSAtMSkgewogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgaWYgKE1hdGguZmxvb3IobmV3TnVtYmVyKSA9PSBuZXdOdW1iZXIpIHsKICAgICAgICAgICAgbmV3TnVtYmVyID0gbmV3TnVtYmVyICsgMTsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIG5ld051bWJlciA9IG5ld051bWJlciArIDAuMTsKICAgICAgICAgICAgbmV3TnVtYmVyLnRvRml4ZWQoMSk7CiAgICAgICAgICAgIG5ld051bWJlciA9IE1hdGgucm91bmQobmV3TnVtYmVyICogMTApIC8gMTA7CiAgICAgICAgfQogICAgfQogICAgZGF0YVtkYklEXVsieC1jaGFubmVsSUQiXSA9IG5ld051bWJlci50b1N0cmluZygpOwogICAgZWxlbWVudC52YWx1ZSA9IG5ld051bWJlcjsKICAgIGlmIChDT0xVTU5fVE9fU09SVCA9PSAxKSB7CiAgICAgICAgQ09MVU1OX1RPX1NPUlQgPSAtMTsKICAgICAgICBzb3J0VGFibGUoMSk7CiAgICB9CiAgICByZXR1cm47Cn0KZnVuY3Rpb24gYmFja3VwKCkgewogICAgdmFyIGRhdGEgPSBuZXcgT2JqZWN0KCk7CiAgICB2YXIgY21kID0gInh0ZXZlQmFja3VwIjsKICAgIHZhciBzZXJ2ZXIgPSBuZXcgU2VydmVyKGNtZCk7CiAgICBzZXJ2ZXIucmVxdWVzdChkYXRhKTsKICAgIHJldHVybjsKfQpmdW5jdGlvbiB0b2dnbGVDaGFubmVsU3RhdHVzKGlkKSB7CiAgICB2YXIgZWxlbWVudDsKICAgIHZhciBzdGF0dXM7CiAgICBpZiAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImFjdGl2ZSIpKSB7CiAgICAgICAgdmFyIGNoZWNrYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImFjdGl2ZSIpOwogICAgICAgIHN0YXR1cyA9IChjaGVja2JveCkuY2hlY2tlZDsKICAgIH0KICAgIHZhciBpZHMgPSBnZXRBbGxTZWxlY3RlZENoYW5uZWxzKCk7CiAgICBpZiAoaWRzLmxlbmd0aCA9PSAwKSB7CiAgICAgICAgaWRzLnB1c2goaWQpOwogICAgfQogICAgaWRzLmZvckVhY2goaWQgPT4gewogICAgICAgIHZhciBjaGFubmVsID0gU0VSVkVSWyJ4ZXBnIl1bImVwZ01hcHBpbmciXVtpZF07CiAgICAgICAgY2hhbm5lbFsieC1hY3RpdmUiXSA9IHN0YXR1czsKICAgICAgICBzd2l0Y2ggKGNoYW5uZWxbIngtYWN0aXZlIl0pIHsKICAgICAgICAgICAgY2FzZSB0cnVlOgogICAgICAgICAgICAgICAgaWYgKGNoYW5uZWxbIngteG1sdHYtZmlsZSJdID09ICItIiB8fCBjaGFubmVsWyJ4LW1hcHBpbmciXSA9PSAiLSIpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoQlVMS19FRElUID09IGZhbHNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGFsZXJ0KGNoYW5uZWxbIngtbmFtZSJdICsgIjogTWlzc2luZyBYTUxUViBmaWxlIC8gY2hhbm5lbCIpOwogICAgICAgICAgICAgICAgICAgICAgICBjaGVja2JveC5jaGVja2VkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNoYW5uZWxbIngtYWN0aXZlIl0gPSBmYWxzZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIGZhbHNlOgogICAgICAgICAgICAgICAgLy8gY29kZS4uLgogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmIChjaGFubmVsWyJ4LWFjdGl2ZSJdID09IGZhbHNlKSB7CiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jbGFzc05hbWUgPSAibm90QWN0aXZlRVBHIjsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jbGFzc05hbWUgPSAiYWN0aXZlRVBHIjsKICAgICAgICB9CiAgICB9KTsKfQpmdW5jdGlvbiB0b2dnbGVHcm91cFVwZGF0ZUNiKHhlcGdJZCwgdGFyZ2V0KSB7CiAgICB0YXJnZXQuY2xhc3NOYW1lID0gJ2NoYW5nZWQnOwogICAgY29uc3QgZ3JvdXBJbnB1dCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2lucHV0W25hbWU9IngtZ3JvdXAtdGl0bGUiXScpOwogICAgY29uc3QgbWFwcGluZyA9IGdldExvY2FsRGF0YSgnbWFwcGluZycsIHhlcGdJZCk7CiAgICBpZiAodGFyZ2V0LmNoZWNrZWQpIHsKICAgICAgICBncm91cElucHV0LmRhdGFzZXQub2xkVmFsdWUgPSBncm91cElucHV0LnZhbHVlOwogICAgICAgIGdyb3VwSW5wdXQudmFsdWUgPSBtYXBwaW5nWydncm91cC10aXRsZSddOwogICAgICAgIGdyb3VwSW5wdXQuZGlzYWJsZWQgPSB0cnVlOwogICAgfQogICAgZWxzZSB7CiAgICAgICAgZ3JvdXBJbnB1dC52YWx1ZSA9IGdyb3VwSW5wdXQuZGF0YXNldC5vbGRWYWx1ZTsKICAgICAgICBncm91cElucHV0LmRpc2FibGVkID0gZmFsc2U7CiAgICB9CiAgICBncm91cElucHV0LmNsYXNzTmFtZSA9ICdjaGFuZ2VkJzsKfQpmdW5jdGlvbiByZXN0b3JlKCkgewogICAgaWYgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd1cGxvYWQnKSkgewogICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd1cGxvYWQnKS5yZW1vdmUoKTsKICAgIH0KICAgIHZhciByZXN0b3JlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiSU5QVVQiKTsKICAgIHJlc3RvcmUuc2V0QXR0cmlidXRlKCJ0eXBlIiwgImZpbGUiKTsKICAgIHJlc3RvcmUuc2V0QXR0cmlidXRlKCJjbGFzcyIsICJub3RWaXNpYmxlIik7CiAgICByZXN0b3JlLnNldEF0dHJpYnV0ZSgibmFtZSIsICIiKTsKICAgIHJlc3RvcmUuaWQgPSAidXBsb2FkIjsKICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQocmVzdG9yZSk7CiAgICByZXN0b3JlLmNsaWNrKCk7CiAgICByZXN0b3JlLm9uY2hhbmdlID0gZnVuY3Rpb24gKCkgewogICAgICAgIHZhciBmaWxlbmFtZSA9IHJlc3RvcmUuZmlsZXNbMF0ubmFtZTsKICAgICAgICB2YXIgY2hlY2sgPSBjb25maXJtKCJGaWxlOiAiICsgZmlsZW5hbWUgKyAiXG57ey5jb25maXJtLnJlc3RvcmV9fSIpOwogICAgICAgIGlmIChjaGVjayA9PSB0cnVlKSB7CiAgICAgICAgICAgIHZhciByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpOwogICAgICAgICAgICB2YXIgZmlsZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2lucHV0W3R5cGU9ZmlsZV0nKS5maWxlc1swXTsKICAgICAgICAgICAgaWYgKGZpbGUpIHsKICAgICAgICAgICAgICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGUpOwogICAgICAgICAgICAgICAgcmVhZGVyLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICAgICAgICAgICAgICAgICAgICB2YXIgY21kID0gInh0ZXZlUmVzdG9yZSI7CiAgICAgICAgICAgICAgICAgICAgZGF0YVsiYmFzZTY0Il0gPSByZWFkZXIucmVzdWx0OwogICAgICAgICAgICAgICAgICAgIHZhciBzZXJ2ZXIgPSBuZXcgU2VydmVyKGNtZCk7CiAgICAgICAgICAgICAgICAgICAgc2VydmVyLnJlcXVlc3QoZGF0YSk7CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgYWxlcnQoIkZpbGUgY291bGQgbm90IGJlIGxvYWRlZCIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJlc3RvcmUucmVtb3ZlKCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICB9OwogICAgcmV0dXJuOwp9CmZ1bmN0aW9uIHVwbG9hZExvZ28oKSB7CiAgICBpZiAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VwbG9hZCcpKSB7CiAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VwbG9hZCcpLnJlbW92ZSgpOwogICAgfQogICAgdmFyIHVwbG9hZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIklOUFVUIik7CiAgICB1cGxvYWQuc2V0QXR0cmlidXRlKCJ0eXBlIiwgImZpbGUiKTsKICAgIHVwbG9hZC5zZXRBdHRyaWJ1dGUoImNsYXNzIiwgIm5vdFZpc2libGUiKTsKICAgIHVwbG9hZC5zZXRBdHRyaWJ1dGUoIm5hbWUiLCAiIik7CiAgICB1cGxvYWQuaWQgPSAidXBsb2FkIjsKICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodXBsb2FkKTsKICAgIHVwbG9hZC5jbGljaygpOwogICAgdXBsb2FkLm9uYmx1ciA9IGZ1bmN0aW9uICgpIHsKICAgICAgICBhbGVydCgpOwogICAgfTsKICAgIHVwbG9hZC5vbmNoYW5nZSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICB2YXIgZmlsZW5hbWUgPSB1cGxvYWQuZmlsZXNbMF0ubmFtZTsKICAgICAgICB2YXIgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTsKICAgICAgICB2YXIgZmlsZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2lucHV0W3R5cGU9ZmlsZV0nKS5maWxlc1swXTsKICAgICAgICBpZiAoZmlsZSkgewogICAgICAgICAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlKTsKICAgICAgICAgICAgcmVhZGVyLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgIHZhciBkYXRhID0gbmV3IE9iamVjdCgpOwogICAgICAgICAgICAgICAgdmFyIGNtZCA9ICJ1cGxvYWRMb2dvIjsKICAgICAgICAgICAgICAgIGRhdGFbImJhc2U2NCJdID0gcmVhZGVyLnJlc3VsdDsKICAgICAgICAgICAgICAgIGRhdGFbImZpbGVuYW1lIl0gPSBmaWxlLm5hbWU7CiAgICAgICAgICAgICAgICB2YXIgc2VydmVyID0gbmV3IFNlcnZlcihjbWQpOwogICAgICAgICAgICAgICAgc2VydmVyLnJlcXVlc3QoZGF0YSk7CiAgICAgICAgICAgICAgICB2YXIgdXBkYXRlTG9nbyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd1cGRhdGUtaWNvbicpOwogICAgICAgICAgICAgICAgdXBkYXRlTG9nby5jaGVja2VkID0gZmFsc2U7CiAgICAgICAgICAgICAgICB1cGRhdGVMb2dvLmNsYXNzTmFtZSA9ICJjaGFuZ2VkIjsKICAgICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGFsZXJ0KCJGaWxlIGNvdWxkIG5vdCBiZSBsb2FkZWQiKTsKICAgICAgICB9CiAgICAgICAgdXBsb2FkLnJlbW92ZSgpOwogICAgICAgIHJldHVybjsKICAgIH07Cn0KZnVuY3Rpb24gY2hlY2tVbmRvKGtleSkgewogICAgc3dpdGNoIChrZXkpIHsKICAgICAgICBjYXNlICJlcGdNYXBwaW5nIjoKICAgICAgICAgICAgaWYgKFVORE8uaGFzT3duUHJvcGVydHkoa2V5KSkgewogICAgICAgICAgICAgICAgU0VSVkVSWyJ4ZXBnIl1ba2V5XSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoVU5ET1trZXldKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBVTkRPW2tleV0gPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KFNFUlZFUlsieGVwZyJdW2tleV0pKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICBicmVhazsKICAgIH0KICAgIHJldHVybjsKfQpmdW5jdGlvbiB1cGRhdGVMb2coKSB7CiAgICB2YXIgc2VydmVyID0gbmV3IFNlcnZlcigidXBkYXRlTG9nIik7CiAgICBzZXJ2ZXIucmVxdWVzdChuZXcgT2JqZWN0KCkpOwp9Cg==" + webUI["html/js/configuration_ts.js"] = "Y2xhc3MgV2l6YXJkQ2F0ZWdvcnkgewogICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgdGhpcy5Eb2N1bWVudElEID0gImNvbnRlbnQiOwogICAgfQogICAgY3JlYXRlQ2F0ZWdvcnlIZWFkbGluZSh2YWx1ZSkgewogICAgICAgIHZhciBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiSDQiKTsKICAgICAgICBlbGVtZW50LmlubmVySFRNTCA9IHZhbHVlOwogICAgICAgIHJldHVybiBlbGVtZW50OwogICAgfQp9CmNsYXNzIFdpemFyZEl0ZW0gZXh0ZW5kcyBXaXphcmRDYXRlZ29yeSB7CiAgICBjb25zdHJ1Y3RvcihrZXksIGhlYWRsaW5lKSB7CiAgICAgICAgc3VwZXIoKTsKICAgICAgICB0aGlzLmhlYWRsaW5lID0gaGVhZGxpbmU7CiAgICAgICAgdGhpcy5rZXkgPSBrZXk7CiAgICB9CiAgICBjcmVhdGVXaXphcmQoKSB7CiAgICAgICAgdmFyIGhlYWRsaW5lID0gdGhpcy5jcmVhdGVDYXRlZ29yeUhlYWRsaW5lKHRoaXMuaGVhZGxpbmUpOwogICAgICAgIHZhciBrZXkgPSB0aGlzLmtleTsKICAgICAgICB2YXIgY29udGVudCA9IG5ldyBQb3B1cENvbnRlbnQoKTsKICAgICAgICB2YXIgZGVzY3JpcHRpb247CiAgICAgICAgdmFyIGRvYyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuRG9jdW1lbnRJRCk7CiAgICAgICAgZG9jLmlubmVySFRNTCA9ICIiOwogICAgICAgIGRvYy5hcHBlbmRDaGlsZChoZWFkbGluZSk7CiAgICAgICAgc3dpdGNoIChrZXkpIHsKICAgICAgICAgICAgY2FzZSAidHVuZXIiOgogICAgICAgICAgICAgICAgdmFyIHRleHQgPSBuZXcgQXJyYXkoKTsKICAgICAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBuZXcgQXJyYXkoKTsKICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDw9IDEwMDsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgdGV4dC5wdXNoKGkpOwogICAgICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKGkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFyIHNlbGVjdCA9IGNvbnRlbnQuY3JlYXRlU2VsZWN0KHRleHQsIHZhbHVlcywgIjEiLCBrZXkpOwogICAgICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgiY2xhc3MiLCAid2l6YXJkIik7CiAgICAgICAgICAgICAgICBzZWxlY3QuaWQgPSBrZXk7CiAgICAgICAgICAgICAgICBkb2MuYXBwZW5kQ2hpbGQoc2VsZWN0KTsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uID0gInt7LndpemFyZC50dW5lci5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJlcGdTb3VyY2UiOgogICAgICAgICAgICAgICAgdmFyIHRleHQgPSBbIlBNUyIsICJYRVBHIl07CiAgICAgICAgICAgICAgICB2YXIgdmFsdWVzID0gWyJQTVMiLCAiWEVQRyJdOwogICAgICAgICAgICAgICAgdmFyIHNlbGVjdCA9IGNvbnRlbnQuY3JlYXRlU2VsZWN0KHRleHQsIHZhbHVlcywgIlhFUEciLCBrZXkpOwogICAgICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgiY2xhc3MiLCAid2l6YXJkIik7CiAgICAgICAgICAgICAgICBzZWxlY3QuaWQgPSBrZXk7CiAgICAgICAgICAgICAgICBkb2MuYXBwZW5kQ2hpbGQoc2VsZWN0KTsKICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uID0gInt7LndpemFyZC5lcGdTb3VyY2UuZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAibTN1IjoKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBrZXksICIiKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3sud2l6YXJkLm0zdS5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoImNsYXNzIiwgIndpemFyZCIpOwogICAgICAgICAgICAgICAgaW5wdXQuaWQgPSBrZXk7CiAgICAgICAgICAgICAgICBkb2MuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gPSAie3sud2l6YXJkLm0zdS5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ4bWx0diI6CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0Iiwga2V5LCAiIik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LndpemFyZC54bWx0di5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoImNsYXNzIiwgIndpemFyZCIpOwogICAgICAgICAgICAgICAgaW5wdXQuaWQgPSBrZXk7CiAgICAgICAgICAgICAgICBkb2MuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgZGVzY3JpcHRpb24gPSAie3sud2l6YXJkLnhtbHR2LmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdmFyIHByZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlBSRSIpOwogICAgICAgIHByZS5pbm5lckhUTUwgPSBkZXNjcmlwdGlvbjsKICAgICAgICBkb2MuYXBwZW5kQ2hpbGQocHJlKTsKICAgIH0KfQpmdW5jdGlvbiByZWFkeUZvckNvbmZpZ3VyYXRpb24od2l6YXJkKSB7CiAgICB2YXIgc2VydmVyID0gbmV3IFNlcnZlcigiZ2V0U2VydmVyQ29uZmlnIik7CiAgICBzZXJ2ZXIucmVxdWVzdChuZXcgT2JqZWN0KCkpOwogICAgc2hvd0VsZW1lbnQoImxvYWRpbmciLCBmYWxzZSk7CiAgICBjb25maWd1cmF0aW9uV2l6YXJkW3dpemFyZF0uY3JlYXRlV2l6YXJkKCk7Cn0KZnVuY3Rpb24gc2F2ZVdpemFyZCgpIHsKICAgIHZhciBjbWQgPSAic2F2ZVdpemFyZCI7CiAgICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImNvbnRlbnQiKTsKICAgIHZhciBjb25maWcgPSBkaXYuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgid2l6YXJkIik7CiAgICB2YXIgd2l6YXJkID0gbmV3IE9iamVjdCgpOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb25maWcubGVuZ3RoOyBpKyspIHsKICAgICAgICB2YXIgbmFtZTsKICAgICAgICB2YXIgdmFsdWU7CiAgICAgICAgc3dpdGNoIChjb25maWdbaV0udGFnTmFtZSkgewogICAgICAgICAgICBjYXNlICJTRUxFQ1QiOgogICAgICAgICAgICAgICAgbmFtZSA9IGNvbmZpZ1tpXS5uYW1lOwogICAgICAgICAgICAgICAgdmFsdWUgPSBjb25maWdbaV0udmFsdWU7CiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgdmFsdWUgaXMgYSBudW1iZXIsIHN0b3JlIGl0IGFzIGEgbnVtYmVyCiAgICAgICAgICAgICAgICBpZiAoaXNOYU4odmFsdWUpKSB7CiAgICAgICAgICAgICAgICAgICAgd2l6YXJkW25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB3aXphcmRbbmFtZV0gPSBwYXJzZUludCh2YWx1ZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiSU5QVVQiOgogICAgICAgICAgICAgICAgc3dpdGNoIChjb25maWdbaV0udHlwZSkgewogICAgICAgICAgICAgICAgICAgIGNhc2UgInRleHQiOgogICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gY29uZmlnW2ldLm5hbWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gY29uZmlnW2ldLnZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUubGVuZ3RoID09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBtc2cgPSBuYW1lLnRvVXBwZXJDYXNlKCkgKyAiOiAiICsgInt7LmFsZXJ0Lm1pc3NpbmdJbnB1dH19IjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsZXJ0KG1zZyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgd2l6YXJkW25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAvLyBjb2RlLi4uCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9CiAgICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICAgIGRhdGFbIndpemFyZCJdID0gd2l6YXJkOwogICAgdmFyIHNlcnZlciA9IG5ldyBTZXJ2ZXIoY21kKTsKICAgIHNlcnZlci5yZXF1ZXN0KGRhdGEpOwp9Ci8vIFdpemFyZAp2YXIgY29uZmlndXJhdGlvbldpemFyZCA9IG5ldyBBcnJheSgpOwpjb25maWd1cmF0aW9uV2l6YXJkLnB1c2gobmV3IFdpemFyZEl0ZW0oInR1bmVyIiwgInt7LndpemFyZC50dW5lci50aXRsZX19IikpOwpjb25maWd1cmF0aW9uV2l6YXJkLnB1c2gobmV3IFdpemFyZEl0ZW0oImVwZ1NvdXJjZSIsICJ7ey53aXphcmQuZXBnU291cmNlLnRpdGxlfX0iKSk7CmNvbmZpZ3VyYXRpb25XaXphcmQucHVzaChuZXcgV2l6YXJkSXRlbSgibTN1IiwgInt7LndpemFyZC5tM3UudGl0bGV9fSIpKTsKY29uZmlndXJhdGlvbldpemFyZC5wdXNoKG5ldyBXaXphcmRJdGVtKCJ4bWx0diIsICJ7ey53aXphcmQueG1sdHYudGl0bGV9fSIpKTsK" + webUI["html/js/logs_ts.js"] = "Y2xhc3MgTG9nIHsKICAgIGNyZWF0ZUxvZyhlbnRyeSkgewogICAgICAgIHZhciBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiUFJFIik7CiAgICAgICAgZW50cnkgPSBTdHJpbmcoZW50cnkpOwogICAgICAgIGlmIChlbnRyeS5pbmRleE9mKCJXQVJOSU5HIikgIT0gLTEpIHsKICAgICAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgPSAid2FybmluZ01zZyI7CiAgICAgICAgfQogICAgICAgIGlmIChlbnRyeS5pbmRleE9mKCJFUlJPUiIpICE9IC0xKSB7CiAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gImVycm9yTXNnIjsKICAgICAgICB9CiAgICAgICAgaWYgKGVudHJ5LmluZGV4T2YoIkRFQlVHIikgIT0gLTEpIHsKICAgICAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgPSAiZGVidWdNc2ciOwogICAgICAgIH0KICAgICAgICBlbGVtZW50LmlubmVySFRNTCA9IGVudHJ5OwogICAgICAgIHJldHVybiBlbGVtZW50OwogICAgfQp9CmZ1bmN0aW9uIHNob3dMb2dzKGJvdHRvbSkgewogICAgdmFyIGxvZyA9IG5ldyBMb2coKTsKICAgIHZhciBsb2dzID0gU0VSVkVSWyJsb2ciXVsibG9nIl07CiAgICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImNvbnRlbnRfbG9nIik7CiAgICBkaXYuaW5uZXJIVE1MID0gIiI7CiAgICB2YXIga2V5cyA9IGdldE93bk9ialByb3BzKGxvZ3MpOwogICAga2V5cy5mb3JFYWNoKGxvZ0lEID0+IHsKICAgICAgICB2YXIgZW50cnkgPSBsb2cuY3JlYXRlTG9nKGxvZ3NbbG9nSURdKTsKICAgICAgICBkaXYuYXBwZW5kKGVudHJ5KTsKICAgIH0pOwogICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7CiAgICAgICAgaWYgKGJvdHRvbSA9PSB0cnVlKSB7CiAgICAgICAgICAgIHZhciB3cmFwcGVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImJveC13cmFwcGVyIik7CiAgICAgICAgICAgIHdyYXBwZXIuc2Nyb2xsVG9wID0gd3JhcHBlci5zY3JvbGxIZWlnaHQ7CiAgICAgICAgfQogICAgfSwgMTApOwp9CmZ1bmN0aW9uIHJlc2V0TG9ncygpIHsKICAgIHZhciBjbWQgPSAicmVzZXRMb2dzIjsKICAgIHZhciBkYXRhID0gbmV3IE9iamVjdCgpOwogICAgdmFyIHNlcnZlciA9IG5ldyBTZXJ2ZXIoY21kKTsKICAgIHNlcnZlci5yZXF1ZXN0KGRhdGEpOwp9Cg==" + webUI["html/js/menu_ts.js"] = "Y2xhc3MgTWFpbk1lbnUgewogICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgdGhpcy5Eb2N1bWVudElEID0gIm1haW4tbWVudSI7CiAgICAgICAgdGhpcy5IVE1MVGFnID0gIkxJIjsKICAgICAgICB0aGlzLkltYWdlUGF0aCA9ICJpbWcvIjsKICAgIH0KICAgIGNyZWF0ZUlNRyhzcmMpIHsKICAgICAgICBsZXQgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIklNRyIpOwogICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCJzcmMiLCB0aGlzLkltYWdlUGF0aCArIHNyYyk7CiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoImFsdCIsIHNyYyk7CiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9CiAgICBjcmVhdGVWYWx1ZSh2YWx1ZSkgewogICAgICAgIGxldCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiUCIpOwogICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gdmFsdWU7CiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9Cn0KY2xhc3MgTWFpbk1lbnVJdGVtIGV4dGVuZHMgTWFpbk1lbnUgewogICAgY29uc3RydWN0b3IobWVudUtleSwgdmFsdWUsIGltYWdlLCBoZWFkbGluZSkgewogICAgICAgIHN1cGVyKCk7CiAgICAgICAgdGhpcy5tZW51S2V5ID0gbWVudUtleTsKICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7CiAgICAgICAgdGhpcy5pbWdTcmMgPSBpbWFnZTsKICAgICAgICB0aGlzLmhlYWRsaW5lID0gaGVhZGxpbmU7CiAgICB9CiAgICBjcmVhdGVJdGVtKCkgewogICAgICAgIGxldCBpdGVtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiTEkiKTsKICAgICAgICBpdGVtLnNldEF0dHJpYnV0ZSgib25jbGljayIsICJqYXZhc2NyaXB0OiBvcGVuVGhpc01lbnUodGhpcykiKTsKICAgICAgICBpdGVtLnNldEF0dHJpYnV0ZSgiaWQiLCB0aGlzLmlkKTsKICAgICAgICBsZXQgaW1nID0gdGhpcy5jcmVhdGVJTUcodGhpcy5pbWdTcmMpOwogICAgICAgIGxldCB2YWx1ZSA9IHRoaXMuY3JlYXRlVmFsdWUodGhpcy52YWx1ZSk7CiAgICAgICAgaXRlbS5hcHBlbmRDaGlsZChpbWcpOwogICAgICAgIGl0ZW0uYXBwZW5kQ2hpbGQodmFsdWUpOwogICAgICAgIGxldCBkb2MgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLkRvY3VtZW50SUQpOwogICAgICAgIGRvYy5hcHBlbmRDaGlsZChpdGVtKTsKICAgICAgICBzd2l0Y2ggKHRoaXMubWVudUtleSkgewogICAgICAgICAgICBjYXNlICJwbGF5bGlzdCI6CiAgICAgICAgICAgICAgICB0aGlzLnRhYmxlSGVhZGVyID0gWyJ7ey5wbGF5bGlzdC50YWJsZS5wbGF5bGlzdH19IiwgInt7LnBsYXlsaXN0LnRhYmxlLnR1bmVyfX0iLCAie3sucGxheWxpc3QudGFibGUubGFzdFVwZGF0ZX19IiwgInt7LnBsYXlsaXN0LnRhYmxlLmF2YWlsYWJpbGl0eX19ICUiLCAie3sucGxheWxpc3QudGFibGUudHlwZX19IiwgInt7LnBsYXlsaXN0LnRhYmxlLnN0cmVhbXN9fSIsICJ7ey5wbGF5bGlzdC50YWJsZS5ncm91cFRpdGxlfX0gJSIsICJ7ey5wbGF5bGlzdC50YWJsZS50dmdJRH19ICUiLCAie3sucGxheWxpc3QudGFibGUudW5pcXVlSUR9fSAlIl07CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAieG1sdHYiOgogICAgICAgICAgICAgICAgdGhpcy50YWJsZUhlYWRlciA9IFsie3sueG1sdHYudGFibGUuZ3VpZGV9fSIsICJ7ey54bWx0di50YWJsZS5sYXN0VXBkYXRlfX0iLCAie3sueG1sdHYudGFibGUuYXZhaWxhYmlsaXR5fX0gJSIsICJ7ey54bWx0di50YWJsZS5jaGFubmVsc319IiwgInt7LnhtbHR2LnRhYmxlLnByb2dyYW1zfX0iXTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJmaWx0ZXIiOgogICAgICAgICAgICAgICAgdGhpcy50YWJsZUhlYWRlciA9IFsie3suZmlsdGVyLnRhYmxlLnN0YXJ0aW5nQ2hhbm5lbH19IiwgInt7LmZpbHRlci50YWJsZS5uYW1lfX0iLCAie3suZmlsdGVyLnRhYmxlLnR5cGV9fSIsICJ7ey5maWx0ZXIudGFibGUuZmlsdGVyfX0iXTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ1c2VycyI6CiAgICAgICAgICAgICAgICB0aGlzLnRhYmxlSGVhZGVyID0gWyJ7ey51c2Vycy50YWJsZS51c2VybmFtZX19IiwgInt7LnVzZXJzLnRhYmxlLnBhc3N3b3JkfX0iLCAie3sudXNlcnMudGFibGUud2VifX0iLCAie3sudXNlcnMudGFibGUucG1zfX0iLCAie3sudXNlcnMudGFibGUubTN1fX0iLCAie3sudXNlcnMudGFibGUueG1sfX0iLCAie3sudXNlcnMudGFibGUuYXBpfX0iXTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJtYXBwaW5nIjoKICAgICAgICAgICAgICAgIHRoaXMudGFibGVIZWFkZXIgPSBbIkJVTEsiLCAie3subWFwcGluZy50YWJsZS5jaE5vfX0iLCAie3subWFwcGluZy50YWJsZS5sb2dvfX0iLCAie3subWFwcGluZy50YWJsZS5jaGFubmVsTmFtZX19IiwgInt7Lm1hcHBpbmcudGFibGUudXBkYXRlQ2hhbm5lbE5hbWVSZWdleH19IiwgInt7Lm1hcHBpbmcudGFibGUucGxheWxpc3R9fSIsICJ7ey5tYXBwaW5nLnRhYmxlLmdyb3VwVGl0bGV9fSIsICJ7ey5tYXBwaW5nLnRhYmxlLnhtbHR2RmlsZX19IiwgInt7Lm1hcHBpbmcudGFibGUueG1sdHZJRH19IiwgInt7Lm1hcHBpbmcudGFibGUudGltZXNoaWZ0fX0iXTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0KfQpjbGFzcyBDb250ZW50IHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgIHRoaXMuRG9jdW1lbnRJRCA9ICJjb250ZW50IjsKICAgICAgICB0aGlzLlRhYmxlSUQgPSAiY29udGVudF90YWJsZSI7CiAgICAgICAgdGhpcy5oZWFkZXJDbGFzcyA9ICJjb250ZW50X3RhYmxlX2hlYWRlciI7CiAgICAgICAgdGhpcy5pbnRlcmFjdGlvbklEID0gImNvbnRlbnQtaW50ZXJhY3Rpb24iOwogICAgfQogICAgY3JlYXRlSGVhZGxpbmUodmFsdWUpIHsKICAgICAgICBsZXQgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIkgzIik7CiAgICAgICAgZWxlbWVudC5pbm5lckhUTUwgPSB2YWx1ZTsKICAgICAgICByZXR1cm4gZWxlbWVudDsKICAgIH0KICAgIGNyZWF0ZUhSKCkgewogICAgICAgIHJldHVybiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJIUiIpOwogICAgfQogICAgY3JlYXRlSW50ZXJhY3Rpb24oKSB7CiAgICAgICAgbGV0IGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJESVYiKTsKICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgiaWQiLCB0aGlzLmludGVyYWN0aW9uSUQpOwogICAgICAgIHJldHVybiBlbGVtZW50OwogICAgfQogICAgY3JlYXRlRElWKCkgewogICAgICAgIGxldCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiRElWIik7CiAgICAgICAgZWxlbWVudC5pZCA9IHRoaXMuRGl2SUQ7CiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9CiAgICBjcmVhdGVUQUJMRSgpIHsKICAgICAgICBsZXQgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlRBQkxFIik7CiAgICAgICAgZWxlbWVudC5pZCA9IHRoaXMuVGFibGVJRDsKICAgICAgICByZXR1cm4gZWxlbWVudDsKICAgIH0KICAgIGNyZWF0ZVRhYmxlUm93KCkgewogICAgICAgIGxldCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVFIiKTsKICAgICAgICBlbGVtZW50LmNsYXNzTmFtZSA9IHRoaXMuaGVhZGVyQ2xhc3M7CiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9CiAgICBjcmVhdGVUYWJsZUNvbnRlbnQobWVudUtleSkgewogICAgICAgIGxldCBkYXRhID0ge307CiAgICAgICAgbGV0IHJvd3MgPSBbXTsKICAgICAgICBsZXQgZmlsZVR5cGVzID0gW107CiAgICAgICAgc3dpdGNoIChtZW51S2V5KSB7CiAgICAgICAgICAgIGNhc2UgInBsYXlsaXN0IjoKICAgICAgICAgICAgICAgIGZpbGVUeXBlcyA9IFsibTN1IiwgImhkaHIiXTsKICAgICAgICAgICAgICAgIGZpbGVUeXBlcy5mb3JFYWNoKGZpbGVUeXBlID0+IHsKICAgICAgICAgICAgICAgICAgICBkYXRhID0gU0VSVkVSWyJzZXR0aW5ncyJdWyJmaWxlcyJdW2ZpbGVUeXBlXTsKICAgICAgICAgICAgICAgICAgICB2YXIga2V5cyA9IGdldE93bk9ialByb3BzKGRhdGEpOwogICAgICAgICAgICAgICAgICAgIGtleXMuZm9yRWFjaChrZXkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJUUiIpOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5pZCA9IGtleTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuc2V0QXR0cmlidXRlKCdvbmNsaWNrJywgJ2phdmFzY3JpcHQ6IG9wZW5Qb3BVcCgiJyArIGZpbGVUeXBlICsgJyIsIHRoaXMpJyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJuYW1lIl07CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChTRVJWRVJbInNldHRpbmdzIl1bImJ1ZmZlciJdICE9ICItIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsidHVuZXIiXTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSAiLSI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsibGFzdC51cGRhdGUiXTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsicHJvdmlkZXIuYXZhaWxhYmlsaXR5Il07CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bInR5cGUiXS50b1VwcGVyQ2FzZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJjb21wYXRpYmlsaXR5Il1bInN0cmVhbXMiXTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsiY29tcGF0aWJpbGl0eSJdWyJncm91cC50aXRsZSJdOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJjb21wYXRpYmlsaXR5Il1bInR2Zy5pZCJdOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJjb21wYXRpYmlsaXR5Il1bInN0cmVhbS5pZCJdOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJvd3MucHVzaCh0cik7CiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJmaWx0ZXIiOgogICAgICAgICAgICAgICAgZGVsZXRlIFNFUlZFUlsic2V0dGluZ3MiXVsiZmlsdGVyIl1bLTFdOwogICAgICAgICAgICAgICAgZGF0YSA9IFNFUlZFUlsic2V0dGluZ3MiXVsiZmlsdGVyIl07CiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IGdldE93bk9ialByb3BzKGRhdGEpOwogICAgICAgICAgICAgICAga2V5cy5mb3JFYWNoKGtleSA9PiB7CiAgICAgICAgICAgICAgICAgICAgdmFyIHRyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVFIiKTsKICAgICAgICAgICAgICAgICAgICB0ci5pZCA9IGtleTsKICAgICAgICAgICAgICAgICAgICB0ci5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogb3BlblBvcFVwKCInICsgZGF0YVtrZXldWyJ0eXBlIl0gKyAnIiwgdGhpcyknKTsKICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsic3RhcnRpbmdDaGFubmVsIl07CiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJuYW1lIl07CiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGRhdGFba2V5XVsidHlwZSJdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgImN1c3RvbS1maWx0ZXIiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9ICJ7ey5maWx0ZXIuY3VzdG9tfX0iOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgImdyb3VwLXRpdGxlIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSAie3suZmlsdGVyLmdyb3VwfX0iOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJmaWx0ZXIiXTsKICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgcm93cy5wdXNoKHRyKTsKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInhtbHR2IjoKICAgICAgICAgICAgICAgIGZpbGVUeXBlcyA9IG5ldyBBcnJheSgieG1sdHYiKTsKICAgICAgICAgICAgICAgIGZpbGVUeXBlcy5mb3JFYWNoKGZpbGVUeXBlID0+IHsKICAgICAgICAgICAgICAgICAgICBkYXRhID0gU0VSVkVSWyJzZXR0aW5ncyJdWyJmaWxlcyJdW2ZpbGVUeXBlXTsKICAgICAgICAgICAgICAgICAgICB2YXIga2V5cyA9IGdldE93bk9ialByb3BzKGRhdGEpOwogICAgICAgICAgICAgICAgICAgIGtleXMuZm9yRWFjaChrZXkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJUUiIpOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5pZCA9IGtleTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuc2V0QXR0cmlidXRlKCdvbmNsaWNrJywgJ2phdmFzY3JpcHQ6IG9wZW5Qb3BVcCgiJyArIGZpbGVUeXBlICsgJyIsIHRoaXMpJyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJuYW1lIl07CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bImxhc3QudXBkYXRlIl07CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bInByb3ZpZGVyLmF2YWlsYWJpbGl0eSJdOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJjb21wYXRpYmlsaXR5Il1bInhtbHR2LmNoYW5uZWxzIl07CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bImNvbXBhdGliaWxpdHkiXVsieG1sdHYucHJvZ3JhbXMiXTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICByb3dzLnB1c2godHIpOwogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAidXNlcnMiOgogICAgICAgICAgICAgICAgZmlsZVR5cGVzID0gbmV3IEFycmF5KCJ1c2VycyIpOwogICAgICAgICAgICAgICAgZmlsZVR5cGVzLmZvckVhY2goZmlsZVR5cGUgPT4gewogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBTRVJWRVJbZmlsZVR5cGVdOwogICAgICAgICAgICAgICAgICAgIHZhciBrZXlzID0gZ2V0T3duT2JqUHJvcHMoZGF0YSk7CiAgICAgICAgICAgICAgICAgICAga2V5cy5mb3JFYWNoKGtleSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0ciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlRSIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmlkID0ga2V5OwogICAgICAgICAgICAgICAgICAgICAgICB0ci5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogb3BlblBvcFVwKCInICsgZmlsZVR5cGUgKyAnIiwgdGhpcyknKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bImRhdGEiXVsidXNlcm5hbWUiXTsKICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9ICIqKioqKioiOwogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YVtrZXldWyJkYXRhIl1bImF1dGhlbnRpY2F0aW9uLndlYiJdID09IHRydWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSAi4pyTIjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSAiLSI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFba2V5XVsiZGF0YSJdWyJhdXRoZW50aWNhdGlvbi5wbXMiXSA9PSB0cnVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gIuKckyI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gIi0iOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhW2tleV1bImRhdGEiXVsiYXV0aGVudGljYXRpb24ubTN1Il0gPT0gdHJ1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9ICLinJMiOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9ICItIjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YVtrZXldWyJkYXRhIl1bImF1dGhlbnRpY2F0aW9uLnhtbCJdID09IHRydWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSAi4pyTIjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSAiLSI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFba2V5XVsiZGF0YSJdWyJhdXRoZW50aWNhdGlvbi5hcGkiXSA9PSB0cnVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gIuKckyI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gIi0iOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgcm93cy5wdXNoKHRyKTsKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgIm1hcHBpbmciOgogICAgICAgICAgICAgICAgQlVMS19FRElUID0gZmFsc2U7CiAgICAgICAgICAgICAgICBjcmVhdGVTZWFyY2hPYmooKTsKICAgICAgICAgICAgICAgIGNoZWNrVW5kbygiZXBnTWFwcGluZyIpOwogICAgICAgICAgICAgICAgZGF0YSA9IFNFUlZFUlsieGVwZyJdWyJlcGdNYXBwaW5nIl07CiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IGdldE93bk9ialByb3BzKGRhdGEpOwogICAgICAgICAgICAgICAga2V5cy5mb3JFYWNoKGtleSA9PiB7CiAgICAgICAgICAgICAgICAgICAgdmFyIHRyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVFIiKTsKICAgICAgICAgICAgICAgICAgICB0ci5pZCA9IGtleTsKICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGRhdGFba2V5XVsieC1hY3RpdmUiXSkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIHRydWU6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ci5jbGFzc05hbWUgPSAiYWN0aXZlRVBHIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIGZhbHNlOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHIuY2xhc3NOYW1lID0gIm5vdEFjdGl2ZUVQRyI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgLy8gQnVsawogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJCVUxLIjsKICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQoY2VsbC5jcmVhdGVDZWxsKCkpOwogICAgICAgICAgICAgICAgICAgIC8vIENoYW5uZWwgbnVtYmVyCiAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIklOUFVUQ0hBTk5FTCI7CiAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGRhdGFba2V5XVsieC1jaGFubmVsSUQiXTsKICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZChjZWxsLmNyZWF0ZUNlbGwoKSk7CiAgICAgICAgICAgICAgICAgICAgLy8gTG9nbwogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJJTUciOwogICAgICAgICAgICAgICAgICAgIGNlbGwuaW1hZ2VVUkwgPSBkYXRhW2tleV1bInR2Zy1sb2dvIl07CiAgICAgICAgICAgICAgICAgICAgdmFyIHRkID0gY2VsbC5jcmVhdGVDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgdGQuc2V0QXR0cmlidXRlKCdvbmNsaWNrJywgJ2phdmFzY3JpcHQ6IG9wZW5Qb3BVcCgibWFwcGluZyIsIHRoaXMpJyk7CiAgICAgICAgICAgICAgICAgICAgdGQuaWQgPSBrZXk7CiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQodGQpOwogICAgICAgICAgICAgICAgICAgIC8vIENoYW5uZWwgbmFtZQogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNsYXNzTmFtZSA9IGRhdGFba2V5XVsieC1jYXRlZ29yeSJdOwogICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bIngtbmFtZSJdOwogICAgICAgICAgICAgICAgICAgIHZhciB0ZCA9IGNlbGwuY3JlYXRlQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgIHRkLnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoIm1hcHBpbmciLCB0aGlzKScpOwogICAgICAgICAgICAgICAgICAgIHRkLmlkID0ga2V5OwogICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKHRkKTsKICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgY2hhbm5lbCBuYW1lIHJlZ2V4CiAgICAgICAgICAgICAgICAgICAgdmFyIGNlbGwgPSBuZXcgQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIlAiOwogICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bInVwZGF0ZS1jaGFubmVsLW5hbWUtcmVnZXgiXTsKICAgICAgICAgICAgICAgICAgICB2YXIgdGQgPSBjZWxsLmNyZWF0ZUNlbGwoKTsKICAgICAgICAgICAgICAgICAgICB0ZC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogb3BlblBvcFVwKCJtYXBwaW5nIiwgdGhpcyknKTsKICAgICAgICAgICAgICAgICAgICB0ZC5pZCA9IGtleTsKICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZCh0ZCk7CiAgICAgICAgICAgICAgICAgICAgLy8gUGxheWxpc3QKICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGdldFZhbHVlRnJvbVByb3ZpZGVyRmlsZShkYXRhW2tleV1bIl9maWxlLm0zdS5pZCJdLCAibTN1IiwgIm5hbWUiKTsKICAgICAgICAgICAgICAgICAgICB2YXIgdGQgPSBjZWxsLmNyZWF0ZUNlbGwoKTsKICAgICAgICAgICAgICAgICAgICB0ZC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogb3BlblBvcFVwKCJtYXBwaW5nIiwgdGhpcyknKTsKICAgICAgICAgICAgICAgICAgICB0ZC5pZCA9IGtleTsKICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZCh0ZCk7CiAgICAgICAgICAgICAgICAgICAgLy8gR3JvdXAgKGdyb3VwLXRpdGxlKQogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJ4LWdyb3VwLXRpdGxlIl07CiAgICAgICAgICAgICAgICAgICAgdmFyIHRkID0gY2VsbC5jcmVhdGVDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgdGQuc2V0QXR0cmlidXRlKCdvbmNsaWNrJywgJ2phdmFzY3JpcHQ6IG9wZW5Qb3BVcCgibWFwcGluZyIsIHRoaXMpJyk7CiAgICAgICAgICAgICAgICAgICAgdGQuaWQgPSBrZXk7CiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQodGQpOwogICAgICAgICAgICAgICAgICAgIC8vIFhNTFRWIGZpbGUKICAgICAgICAgICAgICAgICAgICB2YXIgY2VsbCA9IG5ldyBDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFba2V5XVsieC14bWx0di1maWxlIl0gIT0gIi0iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBnZXRWYWx1ZUZyb21Qcm92aWRlckZpbGUoZGF0YVtrZXldWyJ4LXhtbHR2LWZpbGUiXSwgInhtbHR2IiwgIm5hbWUiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudmFsdWUgPSBkYXRhW2tleV1bIngteG1sdHYtZmlsZSJdOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB2YXIgdGQgPSBjZWxsLmNyZWF0ZUNlbGwoKTsKICAgICAgICAgICAgICAgICAgICB0ZC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogb3BlblBvcFVwKCJtYXBwaW5nIiwgdGhpcyknKTsKICAgICAgICAgICAgICAgICAgICB0ZC5pZCA9IGtleTsKICAgICAgICAgICAgICAgICAgICB0ci5hcHBlbmRDaGlsZCh0ZCk7CiAgICAgICAgICAgICAgICAgICAgLy8gWE1MVFYgQ2hhbm5lbAogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBkYXRhW2tleV1bIngtbWFwcGluZyJdOwogICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZS5sZW5ndGggPiAyMCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGRhdGFba2V5XVsieC1tYXBwaW5nIl0uc3Vic3RyaW5nKDAsIDIwKSArICIuLi4iOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgdmFyIHRkID0gY2VsbC5jcmVhdGVDZWxsKCk7CiAgICAgICAgICAgICAgICAgICAgdGQuc2V0QXR0cmlidXRlKCdvbmNsaWNrJywgJ2phdmFzY3JpcHQ6IG9wZW5Qb3BVcCgibWFwcGluZyIsIHRoaXMpJyk7CiAgICAgICAgICAgICAgICAgICAgdGQuaWQgPSBrZXk7CiAgICAgICAgICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQodGQpOwogICAgICAgICAgICAgICAgICAgIC8vIFRpbWVTaGlmdAogICAgICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjZWxsLmNoaWxkVHlwZSA9ICJQIjsKICAgICAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZGF0YVtrZXldWyJ4LXRpbWVzaGlmdCJdOwogICAgICAgICAgICAgICAgICAgIHZhciB0ZCA9IGNlbGwuY3JlYXRlQ2VsbCgpOwogICAgICAgICAgICAgICAgICAgIHRkLnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoIm1hcHBpbmciLCB0aGlzKScpOwogICAgICAgICAgICAgICAgICAgIHRkLmlkID0ga2V5OwogICAgICAgICAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKHRkKTsKICAgICAgICAgICAgICAgICAgICByb3dzLnB1c2godHIpOwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAic2V0dGluZ3MiOgogICAgICAgICAgICAgICAgYWxlcnQoKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHJldHVybiByb3dzOwogICAgfQp9CmNsYXNzIENlbGwgewogICAgY3JlYXRlQ2VsbCgpIHsKICAgICAgICBsZXQgdGQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgIGlmICh0aGlzLmNoaWxkID09IHRydWUpIHsKICAgICAgICAgICAgdmFyIGVsZW1lbnQ7CiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5jaGlsZFR5cGUpIHsKICAgICAgICAgICAgICAgIGNhc2UgIlAiOgogICAgICAgICAgICAgICAgICAgIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRoaXMuY2hpbGRUeXBlKTsKICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmlubmVySFRNTCA9IHRoaXMudmFsdWU7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgPSB0aGlzLmNsYXNzTmFtZTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgIklOUFVUIjoKICAgICAgICAgICAgICAgICAgICBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0aGlzLmNoaWxkVHlwZSk7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC52YWx1ZSA9IHRoaXMudmFsdWU7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC50eXBlID0gInRleHQiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiSU5QVVRDSEFOTkVMIjoKICAgICAgICAgICAgICAgICAgICBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiSU5QVVQiKTsKICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2c2NyaXB0OiBjaGFuZ2VDaGFubmVsTnVtYmVyKHRoaXMpIik7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC52YWx1ZSA9IHRoaXMudmFsdWU7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC50eXBlID0gInRleHQiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiQlVMSyI6CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIklOUFVUIik7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5jaGVja2VkID0gdGhpcy52YWx1ZTsKICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnR5cGUgPSAiY2hlY2tib3giOwogICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gImJ1bGsgaGlkZUJ1bGsiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiQlVMS19IRUFEIjoKICAgICAgICAgICAgICAgICAgICBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiSU5QVVQiKTsKICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmNoZWNrZWQgPSB0aGlzLnZhbHVlOwogICAgICAgICAgICAgICAgICAgIGVsZW1lbnQudHlwZSA9ICJjaGVja2JveCI7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgPSAiYnVsayBoaWRlQnVsayI7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAiamF2YXNjcmlwdDogc2VsZWN0QWxsQ2hhbm5lbHMoKSIpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiSU1HIjoKICAgICAgICAgICAgICAgICAgICBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0aGlzLmNoaWxkVHlwZSk7CiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoInNyYyIsIHRoaXMuaW1hZ2VVUkwpOwogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmltYWdlVVJMICE9ICIiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCJvbmVycm9yIiwgImphdmFzY3JpcHQ6IHRoaXMub25lcnJvcj1udWxsO3RoaXMuc3JjPScnIik7CiAgICAgICAgICAgICAgICAgICAgICAgIC8vb25lcnJvcj0idGhpcy5vbmVycm9yPW51bGw7dGhpcy5zcmM9J21pc3NpbmcuZ2lmJzsiCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHRkLmFwcGVuZENoaWxkKGVsZW1lbnQpOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgdGQuaW5uZXJIVE1MID0gdGhpcy52YWx1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKHRoaXMub25jbGljayA9PSB0cnVlKSB7CiAgICAgICAgICAgIHRkLnNldEF0dHJpYnV0ZSgib25jbGljayIsIHRoaXMub25jbGlja0Z1bmN0aW9uKTsKICAgICAgICAgICAgdGQuY2xhc3NOYW1lID0gInBvaW50ZXIiOwogICAgICAgIH0KICAgICAgICBpZiAodGhpcy50ZENsYXNzTmFtZSAhPSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgdGQuY2xhc3NOYW1lID0gdGhpcy50ZENsYXNzTmFtZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRkOwogICAgfQp9CmNsYXNzIFNob3dDb250ZW50IGV4dGVuZHMgQ29udGVudCB7CiAgICBjb25zdHJ1Y3RvcihtZW51SUQpIHsKICAgICAgICBzdXBlcigpOwogICAgICAgIHRoaXMubWVudUlEID0gbWVudUlEOwogICAgfQogICAgY3JlYXRlSW5wdXQodHlwZSwgbmFtZSwgdmFsdWUpIHsKICAgICAgICBsZXQgaW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJJTlBVVCIpOwogICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgidHlwZSIsIHR5cGUpOwogICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgibmFtZSIsIG5hbWUpOwogICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgcmV0dXJuIGlucHV0OwogICAgfQogICAgc2hvdygpIHsKICAgICAgICBDT0xVTU5fVE9fU09SVCA9IC0xOwogICAgICAgIC8vIERlbGV0ZSBvbGQgY29udGVudAogICAgICAgIGxldCBkb2MgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLkRvY3VtZW50SUQpOwogICAgICAgIGRvYy5pbm5lckhUTUwgPSAiIjsKICAgICAgICBzaG93UHJldmlldyhmYWxzZSk7CiAgICAgICAgLy8gSGVhZGxpbmUKICAgICAgICBsZXQgaGVhZGxpbmUgPSBtZW51SXRlbXNbdGhpcy5tZW51SURdLmhlYWRsaW5lOwogICAgICAgIGxldCBtZW51S2V5ID0gbWVudUl0ZW1zW3RoaXMubWVudUlEXS5tZW51S2V5OwogICAgICAgIGxldCBoID0gdGhpcy5jcmVhdGVIZWFkbGluZShoZWFkbGluZSk7CiAgICAgICAgZG9jLmFwcGVuZENoaWxkKGgpOwogICAgICAgIGxldCBociA9IHRoaXMuY3JlYXRlSFIoKTsKICAgICAgICBkb2MuYXBwZW5kQ2hpbGQoaHIpOwogICAgICAgIC8vIEludGVyYWN0aW9uCiAgICAgICAgbGV0IGRpdiA9IHRoaXMuY3JlYXRlSW50ZXJhY3Rpb24oKTsKICAgICAgICBkb2MuYXBwZW5kQ2hpbGQoZGl2KTsKICAgICAgICBsZXQgaW50ZXJhY3Rpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmludGVyYWN0aW9uSUQpOwogICAgICAgIHN3aXRjaCAobWVudUtleSkgewogICAgICAgICAgICBjYXNlICJwbGF5bGlzdCI6CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLmNyZWF0ZUlucHV0KCJidXR0b24iLCBtZW51S2V5LCAie3suYnV0dG9uLm5ld319Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoImlkIiwgIi0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoInBsYXlsaXN0IiknKTsKICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJmaWx0ZXIiOgogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcy5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgbWVudUtleSwgInt7LmJ1dHRvbi5uZXd9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJpZCIsIC0xKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoImZpbHRlciIsIHRoaXMpJyk7CiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAieG1sdHYiOgogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcy5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgbWVudUtleSwgInt7LmJ1dHRvbi5uZXd9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJpZCIsICJ4bWx0diIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IG9wZW5Qb3BVcCgieG1sdHYiKScpOwogICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24uYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInVzZXJzIjoKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMuY3JlYXRlSW5wdXQoImJ1dHRvbiIsIG1lbnVLZXksICJ7ey5idXR0b24ubmV3fX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgiaWQiLCAidXNlcnMiKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoInVzZXJzIiknKTsKICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJtYXBwaW5nIjoKICAgICAgICAgICAgICAgIHNob3dFbGVtZW50KCJsb2FkaW5nIiwgdHJ1ZSk7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLmNyZWF0ZUlucHV0KCJidXR0b24iLCBtZW51S2V5LCAie3suYnV0dG9uLnNhdmV9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHNhdmVQb3B1cERhdGEoIm1hcHBpbmciLCAiIiwgIiIpJyk7CiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLmNyZWF0ZUlucHV0KCJidXR0b24iLCBtZW51S2V5LCAie3suYnV0dG9uLmJ1bGtFZGl0fX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBidWxrRWRpdCgpJyk7CiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLmNyZWF0ZUlucHV0KCJzZWFyY2giLCAic2VhcmNoIiwgIiIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJpZCIsICJzZWFyY2hNYXBwaW5nIik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LmJ1dHRvbi5zZWFyY2h9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuY2xhc3NOYW1lID0gInNlYXJjaCI7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgJ2phdmFzY3JpcHQ6IHNlYXJjaEluTWFwcGluZygpJyk7CiAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbi5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAic2V0dGluZ3MiOgogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcy5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgbWVudUtleSwgInt7LmJ1dHRvbi5zYXZlfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBzYXZlU2V0dGluZ3MoKTsnKTsKICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMuY3JlYXRlSW5wdXQoImJ1dHRvbiIsIG1lbnVLZXksICJ7ey5idXR0b24uYmFja3VwfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBiYWNrdXAoKTsnKTsKICAgICAgICAgICAgICAgIGludGVyYWN0aW9uLmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IHRoaXMuY3JlYXRlSW5wdXQoImJ1dHRvbiIsIG1lbnVLZXksICJ7ey5idXR0b24ucmVzdG9yZX19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogcmVzdG9yZSgpOycpOwogICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24uYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgdmFyIHdyYXBwZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJESVYiKTsKICAgICAgICAgICAgICAgIHdyYXBwZXIuc2V0QXR0cmlidXRlKCJpZCIsICJib3gtd3JhcHBlciIpOwogICAgICAgICAgICAgICAgZG9jLmFwcGVuZENoaWxkKHdyYXBwZXIpOwogICAgICAgICAgICAgICAgdGhpcy5EaXZJRCA9ICJjb250ZW50X3NldHRpbmdzIjsKICAgICAgICAgICAgICAgIHZhciBzZXR0aW5ncyA9IHRoaXMuY3JlYXRlRElWKCk7CiAgICAgICAgICAgICAgICB3cmFwcGVyLmFwcGVuZENoaWxkKHNldHRpbmdzKTsKICAgICAgICAgICAgICAgIHNob3dTZXR0aW5ncygpOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICBjYXNlICJsb2ciOgogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gdGhpcy5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgbWVudUtleSwgInt7LmJ1dHRvbi5yZXNldExvZ3N9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHJlc2V0TG9ncygpOycpOwogICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24uYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgdmFyIHdyYXBwZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJESVYiKTsKICAgICAgICAgICAgICAgIHdyYXBwZXIuc2V0QXR0cmlidXRlKCJpZCIsICJib3gtd3JhcHBlciIpOwogICAgICAgICAgICAgICAgZG9jLmFwcGVuZENoaWxkKHdyYXBwZXIpOwogICAgICAgICAgICAgICAgdGhpcy5EaXZJRCA9ICJjb250ZW50X2xvZyI7CiAgICAgICAgICAgICAgICB2YXIgbG9ncyA9IHRoaXMuY3JlYXRlRElWKCk7CiAgICAgICAgICAgICAgICB3cmFwcGVyLmFwcGVuZENoaWxkKGxvZ3MpOwogICAgICAgICAgICAgICAgc2hvd0xvZ3ModHJ1ZSk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIGNhc2UgImxvZ291dCI6CiAgICAgICAgICAgICAgICBsb2NhdGlvbi5yZWxvYWQoKTsKICAgICAgICAgICAgICAgIGRvY3VtZW50LmNvb2tpZSA9ICJUb2tlbj0gOyBleHBpcmVzID0gVGh1LCAwMSBKYW4gMTk3MCAwMDowMDowMCBHTVQiOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgLy8gQ3JlYXRlIHRhYmxlIChpZiBuZWVkZWQpCiAgICAgICAgdmFyIHRhYmxlSGVhZGVyID0gbWVudUl0ZW1zW3RoaXMubWVudUlEXS50YWJsZUhlYWRlcjsKICAgICAgICBpZiAodGFibGVIZWFkZXIubGVuZ3RoID4gMCkgewogICAgICAgICAgICB2YXIgd3JhcHBlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIkRJViIpOwogICAgICAgICAgICBkb2MuYXBwZW5kQ2hpbGQod3JhcHBlcik7CiAgICAgICAgICAgIHdyYXBwZXIuc2V0QXR0cmlidXRlKCJpZCIsICJib3gtd3JhcHBlciIpOwogICAgICAgICAgICB2YXIgdGFibGUgPSB0aGlzLmNyZWF0ZVRBQkxFKCk7CiAgICAgICAgICAgIHdyYXBwZXIuYXBwZW5kQ2hpbGQodGFibGUpOwogICAgICAgICAgICB2YXIgaGVhZGVyID0gdGhpcy5jcmVhdGVUYWJsZVJvdygpOwogICAgICAgICAgICB0YWJsZS5hcHBlbmRDaGlsZChoZWFkZXIpOwogICAgICAgICAgICAvLyBUYWJsZSBoZWFkZXIKICAgICAgICAgICAgdGFibGVIZWFkZXIuZm9yRWFjaChlbGVtZW50ID0+IHsKICAgICAgICAgICAgICAgIHZhciBjZWxsID0gbmV3IENlbGwoKTsKICAgICAgICAgICAgICAgIGNlbGwuY2hpbGQgPSB0cnVlOwogICAgICAgICAgICAgICAgY2VsbC5jaGlsZFR5cGUgPSAiUCI7CiAgICAgICAgICAgICAgICBjZWxsLnZhbHVlID0gZWxlbWVudDsKICAgICAgICAgICAgICAgIGlmIChlbGVtZW50ID09ICJCVUxLIikgewogICAgICAgICAgICAgICAgICAgIGNlbGwuY2hpbGRUeXBlID0gIkJVTEtfSEVBRCI7CiAgICAgICAgICAgICAgICAgICAgY2VsbC52YWx1ZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKG1lbnVLZXkgPT0gIm1hcHBpbmciKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQgPT0gInt7Lm1hcHBpbmcudGFibGUuY2hOb319IikgewogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2sgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2tGdW5jdGlvbiA9ICJqYXZhc2NyaXB0OiBzb3J0VGFibGUoMSk7IjsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC50ZENsYXNzTmFtZSA9ICJzb3J0VGhpcyI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50ID09ICJ7ey5tYXBwaW5nLnRhYmxlLmNoYW5uZWxOYW1lfX0iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwub25jbGljayA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwub25jbGlja0Z1bmN0aW9uID0gImphdmFzY3JpcHQ6IHNvcnRUYWJsZSgzKTsiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCA9PSAie3subWFwcGluZy50YWJsZS51cGRhdGVDaGFubmVsTmFtZVJlZ2V4fX0iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwub25jbGljayA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwub25jbGlja0Z1bmN0aW9uID0gImphdmFzY3JpcHQ6IHNvcnRUYWJsZSg0KTsiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCA9PSAie3subWFwcGluZy50YWJsZS5wbGF5bGlzdH19IikgewogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2sgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2tGdW5jdGlvbiA9ICJqYXZhc2NyaXB0OiBzb3J0VGFibGUoNSk7IjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQgPT0gInt7Lm1hcHBpbmcudGFibGUuZ3JvdXBUaXRsZX19IikgewogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2sgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2tGdW5jdGlvbiA9ICJqYXZhc2NyaXB0OiBzb3J0VGFibGUoNik7IjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQgPT0gInt7Lm1hcHBpbmcudGFibGUudGltZXNoaWZ0fX0iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwub25jbGljayA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwub25jbGlja0Z1bmN0aW9uID0gImphdmFzY3JpcHQ6IHNvcnRUYWJsZSg5KTsiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChtZW51S2V5ID09ICJmaWx0ZXIiKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQgPT0gInt7LmZpbHRlci50YWJsZS5zdGFydGluZ0NoYW5uZWx9fSIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5vbmNsaWNrID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5vbmNsaWNrRnVuY3Rpb24gPSAiamF2YXNjcmlwdDogc29ydFRhYmxlKDApOyI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbGwudGRDbGFzc05hbWUgPSAic29ydFRoaXMiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCA9PSAie3suZmlsdGVyLnRhYmxlLm5hbWV9fSIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5vbmNsaWNrID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5vbmNsaWNrRnVuY3Rpb24gPSAiamF2YXNjcmlwdDogc29ydFRhYmxlKDEpOyI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50ID09ICJ7ey5maWx0ZXIudGFibGUudHlwZX19IikgewogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2sgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjZWxsLm9uY2xpY2tGdW5jdGlvbiA9ICJqYXZhc2NyaXB0OiBzb3J0VGFibGUoMik7IjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQgPT0gInt7LmZpbHRlci50YWJsZS5maWx0ZXJ9fSIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5vbmNsaWNrID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY2VsbC5vbmNsaWNrRnVuY3Rpb24gPSAiamF2YXNjcmlwdDogc29ydFRhYmxlKDMpOyI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaGVhZGVyLmFwcGVuZENoaWxkKGNlbGwuY3JlYXRlQ2VsbCgpKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIHRhYmxlLmFwcGVuZENoaWxkKGhlYWRlcik7CiAgICAgICAgICAgIC8vIENvbnRlbnQgb2YgdGhlIHRhYmxlCiAgICAgICAgICAgIHZhciByb3dzID0gdGhpcy5jcmVhdGVUYWJsZUNvbnRlbnQobWVudUtleSk7CiAgICAgICAgICAgIHJvd3MuZm9yRWFjaCh0ciA9PiB7CiAgICAgICAgICAgICAgICB0YWJsZS5hcHBlbmRDaGlsZCh0cik7CiAgICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICBzd2l0Y2ggKG1lbnVLZXkpIHsKICAgICAgICAgICAgY2FzZSAibWFwcGluZyI6CiAgICAgICAgICAgICAgICBzb3J0VGFibGUoMSk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiZmlsdGVyIjoKICAgICAgICAgICAgICAgIHNob3dQcmV2aWV3KHRydWUpOwogICAgICAgICAgICAgICAgc29ydFRhYmxlKDApOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBDT0xVTU5fVE9fU09SVCA9IC0xOwogICAgICAgICAgICAgICAgc29ydFRhYmxlKDApOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHNob3dFbGVtZW50KCJsb2FkaW5nIiwgZmFsc2UpOwogICAgfQp9CmZ1bmN0aW9uIFBhZ2VSZWFkeSgpIHsKICAgIGxldCBzZXJ2ZXIgPSBuZXcgU2VydmVyKCJnZXRTZXJ2ZXJDb25maWciKTsKICAgIHNlcnZlci5yZXF1ZXN0KHt9KTsKICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJyZXNpemUiLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgY2FsY3VsYXRlV3JhcHBlckhlaWdodCgpOwogICAgfSwgdHJ1ZSk7CiAgICBzZXRJbnRlcnZhbChmdW5jdGlvbiAoKSB7CiAgICAgICAgdXBkYXRlTG9nKCk7CiAgICB9LCAxMDAwMCk7CiAgICByZXR1cm47Cn0KZnVuY3Rpb24gY3JlYXRlTGF5b3V0KCkgewogICAgLy8gQ2xpZW50IEluZm8KICAgIGxldCBvYmogPSBTRVJWRVJbImNsaWVudEluZm8iXTsKICAgIGxldCBrZXlzID0gZ2V0T3duT2JqUHJvcHMob2JqKTsKICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewogICAgICAgIGlmIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZChrZXlzW2ldKSkgewogICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChrZXlzW2ldKS5pbm5lckhUTUwgPSBvYmpba2V5c1tpXV07CiAgICAgICAgICAgIGlmIChsb2NhdGlvbi5wcm90b2NvbCA9PT0gJ2h0dHBzOicpIHsKICAgICAgICAgICAgICAgIGlmIChrZXlzW2ldID09PSAieGVwZy11cmwiIHx8IGtleXNbaV0gPT09ICJtM3UtdXJsIiB8fCBrZXlzW2ldID09PSAiRFZSIikgewogICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGtleXNbaV0pLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldDsKICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQodGFyZ2V0LmlubmVyVGV4dC5zcGxpdCgiICIpWzBdKS50aGVuKCgpID0+IHsgfSk7CiAgICAgICAgICAgICAgICAgICAgfSwgZmFsc2UpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgaWYgKCFkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgibWFpbi1tZW51IikpIHsKICAgICAgICByZXR1cm47CiAgICB9CiAgICAvLyBDcmVhdGUgbWVudQogICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm1haW4tbWVudSIpLmlubmVySFRNTCA9ICIiOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtZW51SXRlbXMubGVuZ3RoOyBpKyspIHsKICAgICAgICBtZW51SXRlbXNbaV0uaWQgPSBpOwogICAgICAgIHN3aXRjaCAobWVudUl0ZW1zW2ldWyJtZW51S2V5Il0pIHsKICAgICAgICAgICAgY2FzZSAidXNlcnMiOgogICAgICAgICAgICBjYXNlICJsb2dvdXQiOgogICAgICAgICAgICAgICAgaWYgKFNFUlZFUlsic2V0dGluZ3MiXVsiYXV0aGVudGljYXRpb24ud2ViIl0gPT0gdHJ1ZSkgewogICAgICAgICAgICAgICAgICAgIG1lbnVJdGVtc1tpXS5jcmVhdGVJdGVtKCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAibWFwcGluZyI6CiAgICAgICAgICAgIGNhc2UgInhtbHR2IjoKICAgICAgICAgICAgICAgIGlmIChTRVJWRVJbImNsaWVudEluZm8iXVsiZXBnU291cmNlIl0gPT0gIlhFUEciKSB7CiAgICAgICAgICAgICAgICAgICAgbWVudUl0ZW1zW2ldLmNyZWF0ZUl0ZW0oKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgbWVudUl0ZW1zW2ldLmNyZWF0ZUl0ZW0oKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybjsKfQpmdW5jdGlvbiBvcGVuVGhpc01lbnUoZWxlbWVudCkgewogICAgbGV0IGlkID0gZWxlbWVudC5pZDsKICAgIGxldCBjb250ZW50ID0gbmV3IFNob3dDb250ZW50KGlkKTsKICAgIGNvbnRlbnQuc2hvdygpOwogICAgY2FsY3VsYXRlV3JhcHBlckhlaWdodCgpOwogICAgcmV0dXJuOwp9CmNsYXNzIFBvcHVwV2luZG93IHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgIHRoaXMuRG9jdW1lbnRJRCA9ICJwb3B1cC1jdXN0b20iOwogICAgICAgIHRoaXMuSW50ZXJhY3Rpb25JRCA9ICJpbnRlcmFjdGlvbiI7CiAgICAgICAgdGhpcy5kb2MgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLkRvY3VtZW50SUQpOwogICAgfQogICAgY3JlYXRlVGl0bGUodGl0bGUpIHsKICAgICAgICBsZXQgdGQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgIHRkLmNsYXNzTmFtZSA9ICJsZWZ0IjsKICAgICAgICB0ZC5pbm5lckhUTUwgPSB0aXRsZSArICI6IjsKICAgICAgICByZXR1cm4gdGQ7CiAgICB9CiAgICBjcmVhdGVDb250ZW50KGVsZW1lbnQpIHsKICAgICAgICBsZXQgdGQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgIHRkLmFwcGVuZENoaWxkKGVsZW1lbnQpOwogICAgICAgIHJldHVybiB0ZDsKICAgIH0KICAgIGNyZWF0ZUludGVyYWN0aW9uKCkgewogICAgICAgIGxldCBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYiKTsKICAgICAgICBkaXYuc2V0QXR0cmlidXRlKCJpZCIsICJwb3B1cC1pbnRlcmFjdGlvbiIpOwogICAgICAgIGRpdi5jbGFzc05hbWUgPSAiaW50ZXJhY3Rpb24iOwogICAgICAgIHRoaXMuZG9jLmFwcGVuZENoaWxkKGRpdik7CiAgICB9Cn0KY2xhc3MgUG9wdXBDb250ZW50IGV4dGVuZHMgUG9wdXBXaW5kb3cgewogICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTsKICAgICAgICB0aGlzLnRhYmxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEFCTEUiKTsKICAgIH0KICAgIGNyZWF0ZUhlYWRsaW5lKGhlYWRsaW5lKSB7CiAgICAgICAgdGhpcy5kb2MuaW5uZXJIVE1MID0gIiI7CiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJIMyIpOwogICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gaGVhZGxpbmUudG9VcHBlckNhc2UoKTsKICAgICAgICB0aGlzLmRvYy5hcHBlbmRDaGlsZChlbGVtZW50KTsKICAgICAgICAvLyBDcmVhdGUgdGFibGUKICAgICAgICB0aGlzLnRhYmxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEFCTEUiKTsKICAgICAgICB0aGlzLmRvYy5hcHBlbmRDaGlsZCh0aGlzLnRhYmxlKTsKICAgIH0KICAgIGFwcGVuZFJvdyh0aXRsZSwgZWxlbWVudCkgewogICAgICAgIGxldCB0ciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlRSIik7CiAgICAgICAgLy8gVGl0bGUKICAgICAgICBpZiAodGl0bGUubGVuZ3RoICE9IDApIHsKICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQodGhpcy5jcmVhdGVUaXRsZSh0aXRsZSkpOwogICAgICAgIH0KICAgICAgICAvLyBDb250ZW50CiAgICAgICAgdHIuYXBwZW5kQ2hpbGQodGhpcy5jcmVhdGVDb250ZW50KGVsZW1lbnQpKTsKICAgICAgICB0aGlzLnRhYmxlLmFwcGVuZENoaWxkKHRyKTsKICAgIH0KICAgIGNyZWF0ZUlucHV0KHR5cGUsIG5hbWUsIHZhbHVlKSB7CiAgICAgICAgbGV0IGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiSU5QVVQiKTsKICAgICAgICBpZiAodmFsdWUgPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIHZhbHVlID0gIiI7CiAgICAgICAgfQogICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgidHlwZSIsIHR5cGUpOwogICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgibmFtZSIsIG5hbWUpOwogICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgidmFsdWUiLCB2YWx1ZSk7CiAgICAgICAgcmV0dXJuIGlucHV0OwogICAgfQogICAgY3JlYXRlQ2hlY2tib3gobmFtZSkgewogICAgICAgIGxldCBpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIklOUFVUIik7CiAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJ0eXBlIiwgImNoZWNrYm94Iik7CiAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJuYW1lIiwgbmFtZSk7CiAgICAgICAgcmV0dXJuIGlucHV0OwogICAgfQogICAgLy8gQ3JlYXRlcyBhIHNlbGVjdGlvbiBvZiBtdWx0aXBsZSBvcHRpb25zIHZhbHVlcyB3aXRoIHRleHQgZGVzY3JpcHRpb25zCiAgICBjcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCBzZXQsIGRiS2V5KSB7CiAgICAgICAgbGV0IHNlbGVjdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlNFTEVDVCIpOwogICAgICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoIm5hbWUiLCBkYktleSk7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0ZXh0Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGxldCBvcHRpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJPUFRJT04iKTsKICAgICAgICAgICAgb3B0aW9uLnNldEF0dHJpYnV0ZSgidmFsdWUiLCB2YWx1ZXNbaV0pOwogICAgICAgICAgICBvcHRpb24uaW5uZXJUZXh0ID0gdGV4dFtpXTsKICAgICAgICAgICAgc2VsZWN0LmFwcGVuZENoaWxkKG9wdGlvbik7CiAgICAgICAgfQogICAgICAgIGlmIChzZXQgIT0gIiIpIHsKICAgICAgICAgICAgc2VsZWN0LnZhbHVlID0gc2V0OwogICAgICAgIH0KICAgICAgICBpZiAoc2V0ID09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBzZWxlY3QudmFsdWUgPSB2YWx1ZXNbMF07CiAgICAgICAgfQogICAgICAgIHJldHVybiBzZWxlY3Q7CiAgICB9CiAgICBzZWxlY3RPcHRpb24oc2VsZWN0LCB2YWx1ZSkgewogICAgICAgIC8vc2VsZWN0LnNlbGVjdGVkT3B0aW9ucyA9IHZhbHVlCiAgICAgICAgbGV0IHMgPSBzZWxlY3Q7CiAgICAgICAgcy5vcHRpb25zW3Muc2VsZWN0ZWRJbmRleF0udmFsdWUgPSB2YWx1ZTsKICAgICAgICByZXR1cm4gc2VsZWN0OwogICAgfQogICAgZGVzY3JpcHRpb24odmFsdWUpIHsKICAgICAgICBsZXQgdHIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJUUiIpOwogICAgICAgIGxldCB0ZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgbGV0IHNwYW4gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJQUkUiKTsKICAgICAgICBzcGFuLmlubmVySFRNTCA9IHZhbHVlOwogICAgICAgIHRyLmFwcGVuZENoaWxkKHRkKTsKICAgICAgICB0ci5hcHBlbmRDaGlsZCh0aGlzLmNyZWF0ZUNvbnRlbnQoc3BhbikpOwogICAgICAgIHRoaXMudGFibGUuYXBwZW5kQ2hpbGQodHIpOwogICAgfQogICAgLy8gSW50ZXJhY3Rpb24KICAgIGFkZEludGVyYWN0aW9uKGVsZW1lbnQpIHsKICAgICAgICBsZXQgaW50ZXJhY3Rpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgicG9wdXAtaW50ZXJhY3Rpb24iKTsKICAgICAgICBpbnRlcmFjdGlvbi5hcHBlbmRDaGlsZChlbGVtZW50KTsKICAgIH0KfQpmdW5jdGlvbiBvcGVuUG9wVXAoZGF0YVR5cGUsIGVsZW1lbnQpIHsKICAgIGxldCBkYXRhID0ge307CiAgICBsZXQgaWQ7CiAgICBzd2l0Y2ggKGVsZW1lbnQpIHsKICAgICAgICBjYXNlIHVuZGVmaW5lZDoKICAgICAgICAgICAgc3dpdGNoIChkYXRhVHlwZSkgewogICAgICAgICAgICAgICAgY2FzZSAiZ3JvdXAtdGl0bGUiOgogICAgICAgICAgICAgICAgICAgIGlmIChpZCA9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWQgPSAtMTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGdldExvY2FsRGF0YSgiZmlsdGVyIiwgaWQpOwogICAgICAgICAgICAgICAgICAgIGRhdGFbInR5cGUiXSA9ICJncm91cC10aXRsZSI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJjdXN0b20tZmlsdGVyIjoKICAgICAgICAgICAgICAgICAgICBpZiAoaWQgPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlkID0gLTE7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBnZXRMb2NhbERhdGEoImZpbHRlciIsIGlkKTsKICAgICAgICAgICAgICAgICAgICBkYXRhWyJ0eXBlIl0gPSAiY3VzdG9tLWZpbHRlciI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgIGRhdGFbImlkLnByb3ZpZGVyIl0gPSAiLSI7CiAgICAgICAgICAgICAgICAgICAgZGF0YVsidHlwZSJdID0gZGF0YVR5cGU7CiAgICAgICAgICAgICAgICAgICAgaWQgPSAiLSI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgaWQgPSBlbGVtZW50LmlkOwogICAgICAgICAgICBkYXRhID0gZ2V0TG9jYWxEYXRhKGRhdGFUeXBlLCBpZCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgfQogICAgbGV0IGNvbnRlbnQgPSBuZXcgUG9wdXBDb250ZW50KCk7CiAgICBzd2l0Y2ggKGRhdGFUeXBlKSB7CiAgICAgICAgY2FzZSAicGxheWxpc3QiOgogICAgICAgICAgICBjb250ZW50LmNyZWF0ZUhlYWRsaW5lKCJ7ey5wbGF5bGlzdC5wbGF5bGlzdFR5cGUudGl0bGV9fSIpOwogICAgICAgICAgICAvLyBUeXBlCiAgICAgICAgICAgIHZhciB0ZXh0ID0gWyJNM1UiLCAiSERIb21lUnVuIl07CiAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBbImphdmFzY3JpcHQ6IG9wZW5Qb3BVcCgnbTN1JykiLCAiamF2YXNjcmlwdDogb3BlblBvcFVwKCdoZGhyJykiXTsKICAgICAgICAgICAgdmFyIHNlbGVjdCA9IGNvbnRlbnQuY3JlYXRlU2VsZWN0KHRleHQsIHZhbHVlcywgIiIsICJ0eXBlIik7CiAgICAgICAgICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoImlkIiwgInR5cGUiKTsKICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAnamF2YXNjcmlwdDogY2hhbmdlQnV0dG9uQWN0aW9uKHRoaXMsICJuZXh0IiwgIm9uY2xpY2siKScpOyAvLyBjaGFuZ2VCdXR0b25BY3Rpb24KICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnBsYXlsaXN0LnR5cGUudGl0bGV9fSIsIHNlbGVjdCk7CiAgICAgICAgICAgIC8vIEludGVyYWN0aW9uCiAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSW50ZXJhY3Rpb24oKTsKICAgICAgICAgICAgLy8gQWJvcnQKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgImNhbmNlbCIsICJ7ey5idXR0b24uY2FuY2VsfX0iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHNob3dFbGVtZW50KCJwb3B1cCIsIGZhbHNlKTsnKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIC8vIE5leHQKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgIm5leHQiLCAie3suYnV0dG9uLm5leHR9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogb3BlblBvcFVwKCJtM3UiKScpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoImlkIiwgJ25leHQnKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm0zdSI6CiAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSGVhZGxpbmUoZGF0YVR5cGUpOwogICAgICAgICAgICAvLyBOYW1lCiAgICAgICAgICAgIHZhciBkYktleSA9ICJuYW1lIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3sucGxheWxpc3QubmFtZS5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5wbGF5bGlzdC5uYW1lLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIERlc2NyaXB0aW9uCiAgICAgICAgICAgIHZhciBkYktleSA9ICJkZXNjcmlwdGlvbiI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LnBsYXlsaXN0LmRlc2NyaXB0aW9uLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnBsYXlsaXN0LmRlc2NyaXB0aW9uLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIFVSTAogICAgICAgICAgICB2YXIgZGJLZXkgPSAiZmlsZS5zb3VyY2UiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5wbGF5bGlzdC5maWxlTTNVLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnBsYXlsaXN0LmZpbGVNM1UudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gVHVuZXIKICAgICAgICAgICAgaWYgKFNFUlZFUlsic2V0dGluZ3MiXVsiYnVmZmVyIl0gIT0gIi0iKSB7CiAgICAgICAgICAgICAgICB2YXIgdGV4dCA9IFtdOwogICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IFtdOwogICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPD0gMTAwOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICB0ZXh0LnB1c2goaS50b1N0cmluZygpKTsKICAgICAgICAgICAgICAgICAgICB2YWx1ZXMucHVzaChpLnRvU3RyaW5nKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFyIGRiS2V5ID0gInR1bmVyIjsKICAgICAgICAgICAgICAgIHZhciBzZWxlY3QgPSBjb250ZW50LmNyZWF0ZVNlbGVjdCh0ZXh0LCB2YWx1ZXMsIGRhdGFbZGJLZXldLCBkYktleSk7CiAgICAgICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJvbmZvY3VzIiwgImphdmFzY3JpcHQ6IHJldHVybjsiKTsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5wbGF5bGlzdC50dW5lci50aXRsZX19Iiwgc2VsZWN0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHZhciBkYktleSA9ICJ0dW5lciI7CiAgICAgICAgICAgICAgICBpZiAoZGF0YVtkYktleV0gPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgZGF0YVtkYktleV0gPSAxOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInJlYWRvbmx5IiwgInRydWUiKTsKICAgICAgICAgICAgICAgIGlucHV0LmNsYXNzTmFtZSA9ICJub3RBdmFpbGFibGUiOwogICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnBsYXlsaXN0LnR1bmVyLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29udGVudC5kZXNjcmlwdGlvbigie3sucGxheWxpc3QudHVuZXIuZGVzY3JpcHRpb259fSIpOwogICAgICAgICAgICAvLyBJbnRlcmF0aW9uCiAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSW50ZXJhY3Rpb24oKTsKICAgICAgICAgICAgLy8gRGVsZXRlCiAgICAgICAgICAgIGlmIChkYXRhWyJpZC5wcm92aWRlciJdICE9ICItIikgewogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgImRlbGV0ZSIsICJ7ey5idXR0b24uZGVsZXRlfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LmNsYXNzTmFtZSA9ICJkZWxldGUiOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCdvbmNsaWNrJywgJ2phdmFzY3JpcHQ6IHNhdmVQb3B1cERhdGEoIm0zdSIsICInICsgaWQgKyAnIiwgdHJ1ZSwgMCknKTsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgImJhY2siLCAie3suYnV0dG9uLmJhY2t9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IG9wZW5Qb3BVcCgicGxheWxpc3QiKScpOwogICAgICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gQWJvcnQKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgImNhbmNlbCIsICJ7ey5idXR0b24uY2FuY2VsfX0iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHNob3dFbGVtZW50KCJwb3B1cCIsIGZhbHNlKTsnKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIC8vIFVwZGF0ZQogICAgICAgICAgICBpZiAoZGF0YVsiaWQucHJvdmlkZXIiXSAhPSAiLSIpIHsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJ1cGRhdGUiLCAie3suYnV0dG9uLnVwZGF0ZX19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogc2F2ZVBvcHVwRGF0YSgibTN1IiwgIicgKyBpZCArICciLCBmYWxzZSwgMSknKTsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIFNhdmUKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgInNhdmUiLCAie3suYnV0dG9uLnNhdmV9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogc2F2ZVBvcHVwRGF0YSgibTN1IiwgIicgKyBpZCArICciLCBmYWxzZSwgMCknKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImhkaHIiOgogICAgICAgICAgICBjb250ZW50LmNyZWF0ZUhlYWRsaW5lKGRhdGFUeXBlKTsKICAgICAgICAgICAgLy8gTmFtZQogICAgICAgICAgICB2YXIgZGJLZXkgPSAibmFtZSI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LnBsYXlsaXN0Lm5hbWUucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3sucGxheWxpc3QubmFtZS50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAvLyBEZXNjcmlwdGlvbgogICAgICAgICAgICB2YXIgZGJLZXkgPSAiZGVzY3JpcHRpb24iOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5wbGF5bGlzdC5kZXNjcmlwdGlvbi5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5wbGF5bGlzdC5kZXNjcmlwdGlvbi5wbGFjZWhvbGRlcn19IiwgaW5wdXQpOwogICAgICAgICAgICAvLyBVUkwKICAgICAgICAgICAgdmFyIGRiS2V5ID0gImZpbGUuc291cmNlIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3sucGxheWxpc3QuZmlsZUhESFIucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3sucGxheWxpc3QuZmlsZUhESFIudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gVHVuZXIKICAgICAgICAgICAgaWYgKFNFUlZFUlsic2V0dGluZ3MiXVsiYnVmZmVyIl0gIT0gIi0iKSB7CiAgICAgICAgICAgICAgICB2YXIgdGV4dCA9IFtdOwogICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IFtdOwogICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPD0gMTAwOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICB0ZXh0LnB1c2goaS50b1N0cmluZygpKTsKICAgICAgICAgICAgICAgICAgICB2YWx1ZXMucHVzaChpLnRvU3RyaW5nKCkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFyIGRiS2V5ID0gInR1bmVyIjsKICAgICAgICAgICAgICAgIHZhciBzZWxlY3QgPSBjb250ZW50LmNyZWF0ZVNlbGVjdCh0ZXh0LCB2YWx1ZXMsIGRhdGFbZGJLZXldLCBkYktleSk7CiAgICAgICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJvbmZvY3VzIiwgImphdmFzY3JpcHQ6IHJldHVybjsiKTsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5wbGF5bGlzdC50dW5lci50aXRsZX19Iiwgc2VsZWN0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgIHZhciBkYktleSA9ICJ0dW5lciI7CiAgICAgICAgICAgICAgICBpZiAoZGF0YVtkYktleV0gPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgZGF0YVtkYktleV0gPSAxOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInJlYWRvbmx5IiwgInRydWUiKTsKICAgICAgICAgICAgICAgIGlucHV0LmNsYXNzTmFtZSA9ICJub3RBdmFpbGFibGUiOwogICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnBsYXlsaXN0LnR1bmVyLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29udGVudC5kZXNjcmlwdGlvbigie3sucGxheWxpc3QudHVuZXIuZGVzY3JpcHRpb259fSIpOwogICAgICAgICAgICAvLyBJbnRlcmFjdGlvbgogICAgICAgICAgICBjb250ZW50LmNyZWF0ZUludGVyYWN0aW9uKCk7CiAgICAgICAgICAgIC8vIERlbGV0ZQogICAgICAgICAgICBpZiAoZGF0YVsiaWQucHJvdmlkZXIiXSAhPSAiLSIpIHsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJkZWxldGUiLCAie3suYnV0dG9uLmRlbGV0ZX19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogc2F2ZVBvcHVwRGF0YSgiaGRociIsICInICsgaWQgKyAnIiwgdHJ1ZSwgMCknKTsKICAgICAgICAgICAgICAgIGlucHV0LmNsYXNzTmFtZSA9ICJkZWxldGUiOwogICAgICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAiYmFjayIsICJ7ey5idXR0b24uYmFja319Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogb3BlblBvcFVwKCJwbGF5bGlzdCIpJyk7CiAgICAgICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBBYm9ydAogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAiY2FuY2VsIiwgInt7LmJ1dHRvbi5jYW5jZWx9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogc2hvd0VsZW1lbnQoInBvcHVwIiwgZmFsc2UpOycpOwogICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgLy8gVXBkYXRlCiAgICAgICAgICAgIGlmIChkYXRhWyJpZC5wcm92aWRlciJdICE9ICItIikgewogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgInVwZGF0ZSIsICJ7ey5idXR0b24udXBkYXRlfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBzYXZlUG9wdXBEYXRhKCJoZGhyIiwgIicgKyBpZCArICciLCBmYWxzZSwgMSknKTsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIFNhdmUKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgInNhdmUiLCAie3suYnV0dG9uLnNhdmV9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogc2F2ZVBvcHVwRGF0YSgiaGRociIsICInICsgaWQgKyAnIiwgZmFsc2UsIDApJyk7CiAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJmaWx0ZXIiOgogICAgICAgICAgICBjb250ZW50LmNyZWF0ZUhlYWRsaW5lKGRhdGFUeXBlKTsKICAgICAgICAgICAgLy8gVHlwZQogICAgICAgICAgICB2YXIgZGJLZXkgPSAidHlwZSI7CiAgICAgICAgICAgIHZhciB0ZXh0ID0gWyJNM1U6ICIgKyAie3suZmlsdGVyLnR5cGUuZ3JvdXBUaXRsZX19IiwgInhUZVZlOiAiICsgInt7LmZpbHRlci50eXBlLmN1c3RvbUZpbHRlcn19Il07CiAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBbImphdmFzY3JpcHQ6IG9wZW5Qb3BVcCgnZ3JvdXAtdGl0bGUnKSIsICJqYXZhc2NyaXB0OiBvcGVuUG9wVXAoJ2N1c3RvbS1maWx0ZXInKSJdOwogICAgICAgICAgICB2YXIgc2VsZWN0ID0gY29udGVudC5jcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCAiamF2YXNjcmlwdDogb3BlblBvcFVwKCdncm91cC10aXRsZScpIiwgZGJLZXkpOwogICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJpZCIsIGlkKTsKICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAnamF2YXNjcmlwdDogY2hhbmdlQnV0dG9uQWN0aW9uKHRoaXMsICJuZXh0IiwgIm9uY2xpY2siKTsnKTsgLy8gY2hhbmdlQnV0dG9uQWN0aW9uCiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5maWx0ZXIudHlwZS50aXRsZX19Iiwgc2VsZWN0KTsKICAgICAgICAgICAgLy8gSW50ZXJhY3Rpb24KICAgICAgICAgICAgY29udGVudC5jcmVhdGVJbnRlcmFjdGlvbigpOwogICAgICAgICAgICAvLyBBYm9ydAogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAiY2FuY2VsIiwgInt7LmJ1dHRvbi5jYW5jZWx9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogc2hvd0VsZW1lbnQoInBvcHVwIiwgZmFsc2UpOycpOwogICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgLy8gTmV4dAogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAibmV4dCIsICJ7ey5idXR0b24ubmV4dH19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBvcGVuUG9wVXAoImdyb3VwLXRpdGxlIiknKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJpZCIsICduZXh0Jyk7CiAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJjdXN0b20tZmlsdGVyIjoKICAgICAgICBjYXNlICJncm91cC10aXRsZSI6CiAgICAgICAgICAgIHN3aXRjaCAoZGF0YVR5cGUpIHsKICAgICAgICAgICAgICAgIGNhc2UgImN1c3RvbS1maWx0ZXIiOgogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSGVhZGxpbmUoInt7LmZpbHRlci5jdXN0b219fSIgKyAiIEZpbHRlciIpOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAiZ3JvdXAtdGl0bGUiOgogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSGVhZGxpbmUoInt7LmZpbHRlci5ncm91cH19IiArICIgRmlsdGVyIik7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gTmFtZSAgICAgIAogICAgICAgICAgICB2YXIgZGJLZXkgPSAibmFtZSI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LmZpbHRlci5uYW1lLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LmZpbHRlci5uYW1lLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIERlc2NyaXB0aW9uCiAgICAgICAgICAgIHZhciBkYktleSA9ICJkZXNjcmlwdGlvbiI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LmZpbHRlci5kZXNjcmlwdGlvbi5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5maWx0ZXIuZGVzY3JpcHRpb24udGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gVHlwZQogICAgICAgICAgICB2YXIgZGJLZXkgPSAidHlwZSI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImhpZGRlbiIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCIiLCBpbnB1dCk7CiAgICAgICAgICAgIHZhciBmaWx0ZXJUeXBlID0gZGF0YVtkYktleV07CiAgICAgICAgICAgIHN3aXRjaCAoZmlsdGVyVHlwZSkgewogICAgICAgICAgICAgICAgY2FzZSAiY3VzdG9tLWZpbHRlciI6CiAgICAgICAgICAgICAgICAgICAgLy8gQ2FzZSBzZW5zaXRpdmUKICAgICAgICAgICAgICAgICAgICB2YXIgZGJLZXkgPSAiY2FzZVNlbnNpdGl2ZSI7CiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVDaGVja2JveChkYktleSk7CiAgICAgICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGFbZGJLZXldOwogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5maWx0ZXIuY2FzZVNlbnNpdGl2ZS50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAgICAgICAgIC8vIEZpbHRlciBSdWxlIChDdXN0b20pCiAgICAgICAgICAgICAgICAgICAgdmFyIGRiS2V5ID0gImZpbHRlciI7CiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5maWx0ZXIuZmlsdGVyUnVsZS5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LmZpbHRlci5maWx0ZXJSdWxlLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgICAgICAgICAgLy8gU3RhcnRpbmcgQ2hhbm5lbCBOdW1iZXIgTWFwcGluZwogICAgICAgICAgICAgICAgICAgIHZhciBkYktleSA9ICJzdGFydGluZ0NoYW5uZWwiOwogICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3suZmlsdGVyLnN0YXJ0aW5nQ2hhbm5lbC5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LmZpbHRlci5zdGFydGluZ0NoYW5uZWwudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgImdyb3VwLXRpdGxlIjoKICAgICAgICAgICAgICAgICAgICAvL2FsZXJ0KGRiS2V5ICsgIiAiICsgZmlsdGVyVHlwZSkKICAgICAgICAgICAgICAgICAgICAvLyBGaWx0ZXIgYmFzZWQgb24gdGhlIGdyb3VwcyBpbiB0aGUgTTNVCiAgICAgICAgICAgICAgICAgICAgdmFyIGRiS2V5ID0gImZpbHRlciI7CiAgICAgICAgICAgICAgICAgICAgdmFyIGdyb3Vwc00zVSA9IGdldExvY2FsRGF0YSgibTN1R3JvdXBzIiwgIiIpOwogICAgICAgICAgICAgICAgICAgIHZhciB0ZXh0ID0gZ3JvdXBzTTNVWyJ0ZXh0Il07CiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IGdyb3Vwc00zVVsidmFsdWUiXTsKICAgICAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ID0gY29udGVudC5jcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCBkYXRhW2RiS2V5XSwgZGJLZXkpOwogICAgICAgICAgICAgICAgICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LmZpbHRlci5maWx0ZXJHcm91cC50aXRsZX19Iiwgc2VsZWN0KTsKICAgICAgICAgICAgICAgICAgICBjb250ZW50LmRlc2NyaXB0aW9uKCJ7ey5maWx0ZXIuZmlsdGVyR3JvdXAuZGVzY3JpcHRpb259fSIpOwogICAgICAgICAgICAgICAgICAgIC8vIENhc2Ugc2Vuc2V0aXZlCiAgICAgICAgICAgICAgICAgICAgdmFyIGRiS2V5ID0gImNhc2VTZW5zaXRpdmUiOwogICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goZGJLZXkpOwogICAgICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhW2RiS2V5XTsKICAgICAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3suZmlsdGVyLmNhc2VTZW5zaXRpdmUudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgICAgICAgICB2YXIgZGJLZXkgPSAiaW5jbHVkZSI7CiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5maWx0ZXIuaW5jbHVkZS5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LmZpbHRlci5pbmNsdWRlLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgICAgICAgICAgY29udGVudC5kZXNjcmlwdGlvbigie3suZmlsdGVyLmluY2x1ZGUuZGVzY3JpcHRpb259fSIpOwogICAgICAgICAgICAgICAgICAgIHZhciBkYktleSA9ICJleGNsdWRlIjsKICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LmZpbHRlci5leGNsdWRlLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3suZmlsdGVyLmV4Y2x1ZGUudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgICAgICAgICBjb250ZW50LmRlc2NyaXB0aW9uKCJ7ey5maWx0ZXIuZXhjbHVkZS5kZXNjcmlwdGlvbn19Iik7CiAgICAgICAgICAgICAgICAgICAgLy8gUHJlc2VydmUgTTNVIFBsYXlsaXN0IENoYW5uZWwgTWFwcGluZwogICAgICAgICAgICAgICAgICAgIHZhciBkYktleSA9ICJwcmVzZXJ2ZU1hcHBpbmciOwogICAgICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goZGJLZXkpOwogICAgICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhW2RiS2V5XTsKICAgICAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3suZmlsdGVyLnByZXNlcnZlTWFwcGluZy50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAgICAgICAgIC8vIFN0YXJ0aW5nIENoYW5uZWwgTnVtYmVyIE1hcHBpbmcKICAgICAgICAgICAgICAgICAgICB2YXIgZGJLZXkgPSAic3RhcnRpbmdDaGFubmVsIjsKICAgICAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LmZpbHRlci5zdGFydGluZ0NoYW5uZWwucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5maWx0ZXIuc3RhcnRpbmdDaGFubmVsLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIEludGVyYWN0aW9uCiAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSW50ZXJhY3Rpb24oKTsKICAgICAgICAgICAgLy8gRGVsZXRlCiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJkZWxldGUiLCAie3suYnV0dG9uLmRlbGV0ZX19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBzYXZlUG9wdXBEYXRhKCJmaWx0ZXIiLCAiJyArIGlkICsgJyIsIHRydWUsIDApJyk7CiAgICAgICAgICAgIGlucHV0LmNsYXNzTmFtZSA9ICJkZWxldGUiOwogICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgLy8gQWJvcnQKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgImNhbmNlbCIsICJ7ey5idXR0b24uY2FuY2VsfX0iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHNob3dFbGVtZW50KCJwb3B1cCIsIGZhbHNlKTsnKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIC8vIFNhdmUKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgInNhdmUiLCAie3suYnV0dG9uLnNhdmV9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogc2F2ZVBvcHVwRGF0YSgiZmlsdGVyIiwgIicgKyBpZCArICciLCBmYWxzZSwgMCknKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInhtbHR2IjoKICAgICAgICAgICAgY29udGVudC5jcmVhdGVIZWFkbGluZShkYXRhVHlwZSk7CiAgICAgICAgICAgIC8vIE5hbWUKICAgICAgICAgICAgdmFyIGRiS2V5ID0gIm5hbWUiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey54bWx0di5uYW1lLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnhtbHR2Lm5hbWUudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gRGVzY3JpcHRpb24KICAgICAgICAgICAgdmFyIGRiS2V5ID0gImRlc2NyaXB0aW9uIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3sueG1sdHYuZGVzY3JpcHRpb24ucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3sueG1sdHYuZGVzY3JpcHRpb24udGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gVVJMCiAgICAgICAgICAgIHZhciBkYktleSA9ICJmaWxlLnNvdXJjZSI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LnhtbHR2LmZpbGVYTUxUVi5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey54bWx0di5maWxlWE1MVFYudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gSW50ZXJhY3Rpb24KICAgICAgICAgICAgY29udGVudC5jcmVhdGVJbnRlcmFjdGlvbigpOwogICAgICAgICAgICAvLyBEZWxldGUKICAgICAgICAgICAgaWYgKGRhdGFbImlkLnByb3ZpZGVyIl0gIT0gIi0iKSB7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAiZGVsZXRlIiwgInt7LmJ1dHRvbi5kZWxldGV9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCdvbmNsaWNrJywgJ2phdmFzY3JpcHQ6IHNhdmVQb3B1cERhdGEoInhtbHR2IiwgIicgKyBpZCArICciLCB0cnVlLCAwKScpOwogICAgICAgICAgICAgICAgaW5wdXQuY2xhc3NOYW1lID0gImRlbGV0ZSI7CiAgICAgICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBBYm9ydAogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAiY2FuY2VsIiwgInt7LmJ1dHRvbi5jYW5jZWx9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2xpY2siLCAnamF2YXNjcmlwdDogc2hvd0VsZW1lbnQoInBvcHVwIiwgZmFsc2UpOycpOwogICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgLy8gVXBkYXRlCiAgICAgICAgICAgIGlmIChkYXRhWyJpZC5wcm92aWRlciJdICE9ICItIikgewogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgiYnV0dG9uIiwgInVwZGF0ZSIsICJ7ey5idXR0b24udXBkYXRlfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgnb25jbGljaycsICdqYXZhc2NyaXB0OiBzYXZlUG9wdXBEYXRhKCJ4bWx0diIsICInICsgaWQgKyAnIiwgZmFsc2UsIDEpJyk7CiAgICAgICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBTYXZlCiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJzYXZlIiwgInt7LmJ1dHRvbi5zYXZlfX0iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCdvbmNsaWNrJywgJ2phdmFzY3JpcHQ6IHNhdmVQb3B1cERhdGEoInhtbHR2IiwgIicgKyBpZCArICciLCBmYWxzZSwgMCknKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInVzZXJzIjoKICAgICAgICAgICAgY29udGVudC5jcmVhdGVIZWFkbGluZSgie3subWFpbk1lbnUuaXRlbS51c2Vyc319Iik7CiAgICAgICAgICAgIC8vIFVzZXIgbmFtZQogICAgICAgICAgICB2YXIgZGJLZXkgPSAidXNlcm5hbWUiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey51c2Vycy51c2VybmFtZS5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey51c2Vycy51c2VybmFtZS50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAvLyBOZXcgUGFyc3N3b3JkCiAgICAgICAgICAgIHZhciBkYktleSA9ICJwYXNzd29yZCI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInBhc3N3b3JkIiwgZGJLZXksICIiKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey51c2Vycy5wYXNzd29yZC5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey51c2Vycy5wYXNzd29yZC50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAvLyBDb25maXJtYXRpb24KICAgICAgICAgICAgdmFyIGRiS2V5ID0gImNvbmZpcm0iOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJwYXNzd29yZCIsIGRiS2V5LCAiIik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3sudXNlcnMuY29uZmlybS5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey51c2Vycy5jb25maXJtLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIEF1dGhlbnRpY2F0aW9uIFdFQgogICAgICAgICAgICB2YXIgZGJLZXkgPSAiYXV0aGVudGljYXRpb24ud2ViIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVDaGVja2JveChkYktleSk7CiAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhW2RiS2V5XTsKICAgICAgICAgICAgaWYgKGRhdGFbImRlZmF1bHRVc2VyIl0gPT0gdHJ1ZSkgewogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgImphdmFzY3JpcHQ6IHJldHVybiBmYWxzZSIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey51c2Vycy53ZWIudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gQXV0aGVudGljYXRpb24gUE1TCiAgICAgICAgICAgIHZhciBkYktleSA9ICJhdXRoZW50aWNhdGlvbi5wbXMiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KGRiS2V5KTsKICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGFbZGJLZXldOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3sudXNlcnMucG1zLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIEF1dGhlbnRpY2F0aW9uIE0zVQogICAgICAgICAgICB2YXIgZGJLZXkgPSAiYXV0aGVudGljYXRpb24ubTN1IjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVDaGVja2JveChkYktleSk7CiAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhW2RiS2V5XTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7LnVzZXJzLm0zdS50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAvLyBBdXRoZW50aWNhdGlvbiBYTUwKICAgICAgICAgICAgdmFyIGRiS2V5ID0gImF1dGhlbnRpY2F0aW9uLnhtbCI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goZGJLZXkpOwogICAgICAgICAgICBpbnB1dC5jaGVja2VkID0gZGF0YVtkYktleV07CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey51c2Vycy54bWwudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gQXV0aGVudGljYXRpb24gQVBJCiAgICAgICAgICAgIHZhciBkYktleSA9ICJhdXRoZW50aWNhdGlvbi5hcGkiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KGRiS2V5KTsKICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGFbZGJLZXldOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3sudXNlcnMuYXBpLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIC8vIEludGVyYWN0aW9uCiAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSW50ZXJhY3Rpb24oKTsKICAgICAgICAgICAgLy8gRGVsZXRlCiAgICAgICAgICAgIGlmIChkYXRhWyJkZWZhdWx0VXNlciJdICE9IHRydWUgJiYgaWQgIT0gIi0iKSB7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAiZGVsZXRlIiwgInt7LmJ1dHRvbi5kZWxldGV9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuY2xhc3NOYW1lID0gImRlbGV0ZSI7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ29uY2xpY2snLCAnamF2YXNjcmlwdDogc2F2ZVBvcHVwRGF0YSgiJyArIGRhdGFUeXBlICsgJyIsICInICsgaWQgKyAnIiwgdHJ1ZSwgMCknKTsKICAgICAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIEFib3J0CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJjYW5jZWwiLCAie3suYnV0dG9uLmNhbmNlbH19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBzaG93RWxlbWVudCgicG9wdXAiLCBmYWxzZSk7Jyk7CiAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICAvLyBTYXZlCiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJzYXZlIiwgInt7LmJ1dHRvbi5zYXZlfX0iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHNhdmVQb3B1cERhdGEoIicgKyBkYXRhVHlwZSArICciLCAiJyArIGlkICsgJyIsICJmYWxzZSIpOycpOwogICAgICAgICAgICBjb250ZW50LmFkZEludGVyYWN0aW9uKGlucHV0KTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibWFwcGluZyI6CiAgICAgICAgICAgIGNvbnRlbnQuY3JlYXRlSGVhZGxpbmUoInt7Lm1haW5NZW51Lml0ZW0ubWFwcGluZ319Iik7CiAgICAgICAgICAgIC8vIEFjdGl2ZQogICAgICAgICAgICB2YXIgZGJLZXkgPSAieC1hY3RpdmUiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KGRiS2V5KTsKICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGFbZGJLZXldOwogICAgICAgICAgICBpbnB1dC5pZCA9ICJhY3RpdmUiOwogICAgICAgICAgICAvL2lucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKQogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRvZ2dsZUNoYW5uZWxTdGF0dXMoJyIgKyBpZCArICInLCB0aGlzKSIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3subWFwcGluZy5hY3RpdmUudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gQ2hhbm5lbCBuYW1lCiAgICAgICAgICAgIHZhciBkYktleSA9ICJ4LW5hbWUiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICBpZiAoQlVMS19FRElUID09IHRydWUpIHsKICAgICAgICAgICAgICAgIGlucHV0LnN0eWxlLmJvcmRlciA9ICJzb2xpZCAxcHggcmVkIjsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicmVhZG9ubHkiLCAidHJ1ZSIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5tYXBwaW5nLmNoYW5uZWxOYW1lLnRpdGxlfX0iLCBpbnB1dCk7CiAgICAgICAgICAgIGNvbnRlbnQuZGVzY3JpcHRpb24oZGF0YVsibmFtZSJdKTsKICAgICAgICAgICAgLy8gRGVzY3JpcHRpb24KICAgICAgICAgICAgdmFyIGRiS2V5ID0gIngtZGVzY3JpcHRpb24iOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5tYXBwaW5nLmRlc2NyaXB0aW9uLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3subWFwcGluZy5kZXNjcmlwdGlvbi50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGNoYW5uZWwgeC1uYW1lCiAgICAgICAgICAgIGlmIChkYXRhLmhhc093blByb3BlcnR5KCJfdXVpZC5rZXkiKSkgewogICAgICAgICAgICAgICAgaWYgKGRhdGFbIl91dWlkLmtleSJdICE9ICIiKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIGRiS2V5ID0gIngtdXBkYXRlLWNoYW5uZWwtbmFtZSI7CiAgICAgICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVDaGVja2JveChkYktleSk7CiAgICAgICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhW2RiS2V5XTsKICAgICAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3subWFwcGluZy51cGRhdGVDaGFubmVsTmFtZS50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIENoYW5uZWwgbmFtZSByZWdleCBmb3IgdXBkYXRpbmcgdGhlIGNoYW5uZWwgbmFtZQogICAgICAgICAgICB2YXIgZGJLZXkgPSAidXBkYXRlLWNoYW5uZWwtbmFtZS1yZWdleCI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7Lm1hcHBpbmcudXBkYXRlQ2hhbm5lbE5hbWVSZWdleC5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7Lm1hcHBpbmcudXBkYXRlQ2hhbm5lbE5hbWVSZWdleC50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICBjb250ZW50LmRlc2NyaXB0aW9uKCJ7ey5tYXBwaW5nLnVwZGF0ZUNoYW5uZWxOYW1lUmVnZXguZGVzY3JpcHRpb259fSIpOwogICAgICAgICAgICAvLyBDaGFubmVsIGdyb3VwIHJlZ2V4IGZvciB1cGRhdGluZyB0aGUgY2hhbm5lbCBuYW1lCiAgICAgICAgICAgIHZhciBkYktleSA9ICJ1cGRhdGUtY2hhbm5lbC1uYW1lLWJ5LWdyb3VwLXJlZ2V4IjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3subWFwcGluZy51cGRhdGVDaGFubmVsTmFtZUJ5R3JvdXBSZWdleC5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7Lm1hcHBpbmcudXBkYXRlQ2hhbm5lbE5hbWVCeUdyb3VwUmVnZXgudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgY29udGVudC5kZXNjcmlwdGlvbigie3subWFwcGluZy51cGRhdGVDaGFubmVsTmFtZUJ5R3JvdXBSZWdleC5kZXNjcmlwdGlvbn19Iik7CiAgICAgICAgICAgIC8vIExvZ28gVVJMIChDaGFubmVsKSAKICAgICAgICAgICAgdmFyIGRiS2V5ID0gInR2Zy1sb2dvIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsIGRiS2V5LCBkYXRhW2RiS2V5XSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJpZCIsICJjaGFubmVsLWljb24iKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coInt7Lm1hcHBpbmcuY2hhbm5lbExvZ28udGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gQ2hhbm5lbCBsb2dvIHVwZGF0ZQogICAgICAgICAgICB2YXIgZGJLZXkgPSAieC11cGRhdGUtY2hhbm5lbC1pY29uIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVDaGVja2JveChkYktleSk7CiAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhW2RiS2V5XTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJpZCIsICJ1cGRhdGUtaWNvbiIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnOyBjaGFuZ2VDaGFubmVsTG9nbygnIiArIGlkICsgIicpOyIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3subWFwcGluZy51cGRhdGVDaGFubmVsTG9nby50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICAvLyBFeHBhbmQgRVBHIGNhdGVnb3J5CiAgICAgICAgICAgIHZhciBkYktleSA9ICJ4LWNhdGVnb3J5IjsKICAgICAgICAgICAgdmFyIHRleHQgPSBbIi0iLCAiS2lkcyAoRW1ieSBvbmx5KSIsICJOZXdzIiwgIk1vdmllIiwgIlNlcmllcyIsICJTcG9ydHMiXTsKICAgICAgICAgICAgdmFyIHZhbHVlcyA9IFsiIiwgIktpZHMiLCAiTmV3cyIsICJNb3ZpZSIsICJTZXJpZXMiLCAiU3BvcnRzIl07CiAgICAgICAgICAgIHZhciBzZWxlY3QgPSBjb250ZW50LmNyZWF0ZVNlbGVjdCh0ZXh0LCB2YWx1ZXMsIGRhdGFbZGJLZXldLCBkYktleSk7CiAgICAgICAgICAgIHNlbGVjdC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5tYXBwaW5nLmVwZ0NhdGVnb3J5LnRpdGxlfX0iLCBzZWxlY3QpOwogICAgICAgICAgICAvLyBNM1UgZ3JvdXAgdGl0bGUKICAgICAgICAgICAgdmFyIGRiS2V5ID0gIngtZ3JvdXAtdGl0bGUiOwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgZGJLZXksIGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICBpbnB1dC5kYXRhc2V0Lm9sZFZhbHVlID0gZGF0YVtkYktleV07CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5tYXBwaW5nLm0zdUdyb3VwVGl0bGUudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgaWYgKGRhdGFbImdyb3VwLXRpdGxlIl0gIT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICBjb250ZW50LmRlc2NyaXB0aW9uKGRhdGFbImdyb3VwLXRpdGxlIl0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChkYXRhWyJ4LXVwZGF0ZS1jaGFubmVsLWdyb3VwIl0gPT0gdHJ1ZSkgewogICAgICAgICAgICAgICAgaW5wdXQuZGlzYWJsZWQgPSB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIC8vIFVwZGF0ZSBjaGFubmVsIGdyb3VwIGNoZWNrYm94CiAgICAgICAgICAgIHZhciBkYktleSA9ICJ4LXVwZGF0ZS1jaGFubmVsLWdyb3VwIjsKICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVDaGVja2JveChkYktleSk7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdG9nZ2xlR3JvdXBVcGRhdGVDYignIiArIGlkICsgIicsIHRoaXMpOyIpOwogICAgICAgICAgICBpbnB1dC5jaGVja2VkID0gZGF0YVtkYktleV07CiAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kUm93KCJ7ey5tYXBwaW5nLnVwZGF0ZUNoYW5uZWxHcm91cC50aXRsZX19IiwgaW5wdXQpOwogICAgICAgICAgICBjb250ZW50LmRlc2NyaXB0aW9uKCJ7ey5tYXBwaW5nLnVwZGF0ZUNoYW5uZWxHcm91cC5kZXNjcmlwdGlvbn19Iik7CiAgICAgICAgICAgIC8vIFhNTFRWIGZpbGUKICAgICAgICAgICAgdmFyIGRiS2V5ID0gJ3gteG1sdHYtZmlsZSc7CiAgICAgICAgICAgIGNvbnN0IHhtbFR2RmlsZSA9IGRhdGFbZGJLZXldOwogICAgICAgICAgICB2YXIgeG1sVHYgPSBuZXcgWE1MVFZGaWxlKCk7CiAgICAgICAgICAgIGNvbnN0IHhtbFR2RmlsZVNlbGVjdCA9IHhtbFR2LmdldEZpbGVzKGRhdGFbZGJLZXldKTsKICAgICAgICAgICAgeG1sVHZGaWxlU2VsZWN0LnNldEF0dHJpYnV0ZSgnbmFtZScsIGRiS2V5KTsKICAgICAgICAgICAgeG1sVHZGaWxlU2VsZWN0LnNldEF0dHJpYnV0ZSgnaWQnLCAncG9wdXAteG1sdHYnKTsKICAgICAgICAgICAgeG1sVHZGaWxlU2VsZWN0LnNldEF0dHJpYnV0ZSgnb25jaGFuZ2UnLCBgamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCc7IHNldFhtbHR2Q2hhbm5lbCgnJHtpZH0nLCB0aGlzKTtgKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coJ3t7Lm1hcHBpbmcueG1sdHZGaWxlLnRpdGxlfX0nLCB4bWxUdkZpbGVTZWxlY3QpOwogICAgICAgICAgICAvLyBYTUxUViBNYXBwaW5nCiAgICAgICAgICAgIHZhciBkYktleSA9ICd4LW1hcHBpbmcnOwogICAgICAgICAgICB2YXIgeG1sVHYgPSBuZXcgWE1MVFZGaWxlKCk7CiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRYbWxUdklkID0gZGF0YVtkYktleV07CiAgICAgICAgICAgIGNvbnN0IFt4bWxUdklkQ29udGFpbmVyLCB4bWxUdklkSW5wdXQsIHhtbFR2SWREYXRhbGlzdF0gPSB4bWxUdi5uZXdYbWxUdklkUGlja2VyKHhtbFR2RmlsZSwgY3VycmVudFhtbFR2SWQpOwogICAgICAgICAgICB4bWxUdklkQ29udGFpbmVyLnNldEF0dHJpYnV0ZSgnaWQnLCAneG1sdHYtaWQtcGlja2VyLWNvbnRhaW5lcicpOwogICAgICAgICAgICB4bWxUdklkSW5wdXQuc2V0QXR0cmlidXRlKCdsaXN0JywgJ3htbHR2LWlkLXBpY2tlci1kYXRhbGlzdCcpOwogICAgICAgICAgICB4bWxUdklkSW5wdXQuc2V0QXR0cmlidXRlKCduYW1lJywgJ3gtbWFwcGluZycpOyAvLyBTaG91bGQgc3RheSB4LW1hcHBpbmcgYXMgaXQgd2lsbCBiZSB1c2VkIGluIGRvbmVQb3B1cERhdGEgdG8gbWFrZSBhIHNlcnZlciByZXF1ZXN0CiAgICAgICAgICAgIHhtbFR2SWRJbnB1dC5zZXRBdHRyaWJ1dGUoJ2lkJywgJ3htbHR2LWlkLXBpY2tlci1pbnB1dCcpOwogICAgICAgICAgICB4bWxUdklkSW5wdXQuc2V0QXR0cmlidXRlKCdvbmNoYW5nZScsIGBqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJzsgY2hlY2tYbWx0dkNoYW5uZWwoJyR7aWR9JywgdGhpcy52YWx1ZSwgJyR7eG1sVHZGaWxlfScpO2ApOwogICAgICAgICAgICB4bWxUdklkRGF0YWxpc3Quc2V0QXR0cmlidXRlKCdpZCcsICd4bWx0di1pZC1waWNrZXItZGF0YWxpc3QnKTsKICAgICAgICAgICAgY29udGVudC5hcHBlbmRSb3coJ3t7Lm1hcHBpbmcueG1sdHZDaGFubmVsLnRpdGxlfX0nLCB4bWxUdklkQ29udGFpbmVyKTsKICAgICAgICAgICAgLy8gVGltZXNoaWZ0CiAgICAgICAgICAgIHZhciBkYktleSA9ICJ4LXRpbWVzaGlmdCI7CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCBkYktleSwgZGF0YVtkYktleV0pOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3subWFwcGluZy50aW1lc2hpZnQucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoImlkIiwgInRpbWVzaGlmdCIpOwogICAgICAgICAgICBjb250ZW50LmFwcGVuZFJvdygie3subWFwcGluZy50aW1lc2hpZnQudGl0bGV9fSIsIGlucHV0KTsKICAgICAgICAgICAgLy8gSW50ZXJhY3Rpb24KICAgICAgICAgICAgY29udGVudC5jcmVhdGVJbnRlcmFjdGlvbigpOwogICAgICAgICAgICAvLyBVcGxvYWQgbG9nbwogICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJidXR0b24iLCAiY2FuY2VsIiwgInt7LmJ1dHRvbi51cGxvYWRMb2dvfX0iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IHVwbG9hZExvZ28oKTsnKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIC8vIEFib3J0CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJjYW5jZWwiLCAie3suYnV0dG9uLmNhbmNlbH19Iik7CiAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jbGljayIsICdqYXZhc2NyaXB0OiBzaG93RWxlbWVudCgicG9wdXAiLCBmYWxzZSk7Jyk7CiAgICAgICAgICAgIGNvbnRlbnQuYWRkSW50ZXJhY3Rpb24oaW5wdXQpOwogICAgICAgICAgICAvLyBGaW5pc2hlZAogICAgICAgICAgICB2YXIgaWRzID0gW107CiAgICAgICAgICAgIGlkcyA9IGdldEFsbFNlbGVjdGVkQ2hhbm5lbHMoKTsKICAgICAgICAgICAgaWYgKGlkcy5sZW5ndGggPT0gMCkgewogICAgICAgICAgICAgICAgaWRzLnB1c2goaWQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoImJ1dHRvbiIsICJzYXZlIiwgInt7LmJ1dHRvbi5kb25lfX0iKTsKICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNsaWNrIiwgJ2phdmFzY3JpcHQ6IGRvbmVQb3B1cERhdGEoIicgKyBkYXRhVHlwZSArICciLCAiJyArIGlkcyArICciLCAiZmFsc2UiKTsnKTsKICAgICAgICAgICAgY29udGVudC5hZGRJbnRlcmFjdGlvbihpbnB1dCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIGJyZWFrOwogICAgfQogICAgc2hvd1BvcFVwRWxlbWVudCgncG9wdXAtY3VzdG9tJyk7Cn0KY2xhc3MgWE1MVFZGaWxlIHsKICAgIGdldEZpbGVzKHNldCkgewogICAgICAgIGxldCBmaWxlSURzID0gZ2V0T3duT2JqUHJvcHMoU0VSVkVSWyJ4ZXBnIl1bInhtbHR2TWFwIl0pOwogICAgICAgIGxldCB2YWx1ZXMgPSBuZXcgQXJyYXkoIi0iKTsKICAgICAgICBsZXQgdGV4dCA9IG5ldyBBcnJheSgiLSIpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmlsZUlEcy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICBpZiAoZmlsZUlEc1tpXSAhPSAieFRlVmUgRHVtbXkiKSB7CiAgICAgICAgICAgICAgICB2YWx1ZXMucHVzaChnZXRWYWx1ZUZyb21Qcm92aWRlckZpbGUoZmlsZUlEc1tpXSwgInhtbHR2IiwgImZpbGUueHRldmUiKSk7CiAgICAgICAgICAgICAgICB0ZXh0LnB1c2goZ2V0VmFsdWVGcm9tUHJvdmlkZXJGaWxlKGZpbGVJRHNbaV0sICJ4bWx0diIsICJuYW1lIikpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdmFsdWVzLnB1c2goZmlsZUlEc1tpXSk7CiAgICAgICAgICAgICAgICB0ZXh0LnB1c2goZmlsZUlEc1tpXSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbGV0IHNlbGVjdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlNFTEVDVCIpOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGV4dC5sZW5ndGg7IGkrKykgewogICAgICAgICAgICB2YXIgb3B0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiT1BUSU9OIik7CiAgICAgICAgICAgIG9wdGlvbi5zZXRBdHRyaWJ1dGUoInZhbHVlIiwgdmFsdWVzW2ldKTsKICAgICAgICAgICAgb3B0aW9uLmlubmVyVGV4dCA9IHRleHRbaV07CiAgICAgICAgICAgIHNlbGVjdC5hcHBlbmRDaGlsZChvcHRpb24pOwogICAgICAgIH0KICAgICAgICBpZiAoc2V0ICE9ICIiKSB7CiAgICAgICAgICAgIHNlbGVjdC52YWx1ZSA9IHNldDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHNlbGVjdDsKICAgIH0KICAgIC8qKgogICAgICogQHBhcmFtIHhtbFR2RmlsZSBYTUwgZmlsZSBwYXRoIHRvIGdldCBFUEcgZnJvbS4KICAgICAqIEBwYXJhbSBjdXJyZW50WG1sVHZJZCBDdXJyZW50IFhNTFRWIElEIHRvIHNldCBpbml0aWFsIGlucHV0IHZhbHVlIHRvLgogICAgICogQHJldHVybnMgQXJyYXkgb2YsIHNlcXVlbnRpYWxseToKICAgICAqIDEpIENvbnRhaW5lciBvZiB0aGUgcGlja2VyLgogICAgICogMikgSW5wdXQgZmllbGQgdG8gdHlwZSBhdCBhbmQgZ2V0IGNob2ljZSBmcm9tLgogICAgICogMykgRGF0YWxpc3QgY29udGFpbmluZyBldmVyeSBvcHRpb24uCiAgICAgKi8KICAgIG5ld1htbFR2SWRQaWNrZXIoeG1sVHZGaWxlLCBjdXJyZW50WG1sVHZJZCkgewogICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogICAgICAgIGNvbnN0IGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKTsKICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ3R5cGUnLCAndGV4dCcpOwogICAgICAgIC8vIEluaXRpYWxseSwgc2V0IHZhbHVlIHRvICctJyBpZiBpbnB1dCBpcyBlbXB0eQogICAgICAgIGlucHV0LnZhbHVlID0gKGN1cnJlbnRYbWxUdklkKSA/IGN1cnJlbnRYbWxUdklkIDogJy0nOwogICAgICAgIC8vIFdoZW4gaW5wdXQgaXMgZm9jdXNlZCwgcmVtb3ZlICctJyBmcm9tIGl0CiAgICAgICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCAoZXZ0KSA9PiB7CiAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IGV2dC50YXJnZXQ7CiAgICAgICAgICAgIHRhcmdldC52YWx1ZSA9ICh0YXJnZXQudmFsdWUgPT09ICctJykgPyAnJyA6IHRhcmdldC52YWx1ZTsKICAgICAgICB9KTsKICAgICAgICAvLyBXaGVuIGlucHV0IGxvc2UgZm9jdXMgb3IgdGFrZSBhIHZhbHVlLCBpZiBpdCdzIGVtcHR5LCBzZXQgdmFsdWUgdG8gJy0nCiAgICAgICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignYmx1cicsIHNldEZhbGxiYWNrVmFsdWUpOwogICAgICAgIGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIHNldEZhbGxiYWNrVmFsdWUpOwogICAgICAgIGZ1bmN0aW9uIHNldEZhbGxiYWNrVmFsdWUoZXZ0KSB7CiAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IGV2dC50YXJnZXQ7CiAgICAgICAgICAgIHRhcmdldC52YWx1ZSA9ICh0YXJnZXQudmFsdWUpID8gdGFyZ2V0LnZhbHVlIDogJy0nOwogICAgICAgIH0KICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgIGNvbnN0IGRhdGFsaXN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGF0YWxpc3QnKTsKICAgICAgICBjb25zdCBvcHRpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdvcHRpb24nKTsKICAgICAgICBvcHRpb24uc2V0QXR0cmlidXRlKCd2YWx1ZScsICctJyk7CiAgICAgICAgb3B0aW9uLmlubmVyVGV4dCA9ICctJzsKICAgICAgICBkYXRhbGlzdC5hcHBlbmRDaGlsZChvcHRpb24pOwogICAgICAgIGNvbnN0IGVwZyA9IFNFUlZFUlsneGVwZyddWyd4bWx0dk1hcCddW3htbFR2RmlsZV07CiAgICAgICAgaWYgKGVwZykgewogICAgICAgICAgICBjb25zdCBwcm9ncmFtSWRzID0gZ2V0T3duT2JqUHJvcHMoZXBnKTsKICAgICAgICAgICAgcHJvZ3JhbUlkcy5mb3JFYWNoKChwcm9ncmFtSWQpID0+IHsKICAgICAgICAgICAgICAgIGNvbnN0IHByb2dyYW0gPSBlcGdbcHJvZ3JhbUlkXTsKICAgICAgICAgICAgICAgIGlmIChwcm9ncmFtLmhhc093blByb3BlcnR5KCdkaXNwbGF5LW5hbWVzJykpIHsKICAgICAgICAgICAgICAgICAgICBwcm9ncmFtWydkaXNwbGF5LW5hbWVzJ10uZm9yRWFjaCgoZGlzcGxheU5hbWUpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3B0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnb3B0aW9uJyk7CiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbi5zZXRBdHRyaWJ1dGUoJ3ZhbHVlJywgcHJvZ3JhbUlkKTsKICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uLmlubmVyVGV4dCA9IGRpc3BsYXlOYW1lWydWYWx1ZSddOwogICAgICAgICAgICAgICAgICAgICAgICBkYXRhbGlzdC5hcHBlbmRDaGlsZChvcHRpb24pOwogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3B0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnb3B0aW9uJyk7CiAgICAgICAgICAgICAgICAgICAgb3B0aW9uLnNldEF0dHJpYnV0ZSgndmFsdWUnLCBwcm9ncmFtSWQpOwogICAgICAgICAgICAgICAgICAgIG9wdGlvbi5pbm5lclRleHQgPSAnLSc7CiAgICAgICAgICAgICAgICAgICAgZGF0YWxpc3QuYXBwZW5kQ2hpbGQob3B0aW9uKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChkYXRhbGlzdCk7CiAgICAgICAgcmV0dXJuIFtjb250YWluZXIsIGlucHV0LCBkYXRhbGlzdF07CiAgICB9Cn0KZnVuY3Rpb24gZ2V0VmFsdWVGcm9tUHJvdmlkZXJGaWxlKGZpbGUsIGZpbGVUeXBlLCBrZXkpIHsKICAgIGlmIChmaWxlID09ICJ4VGVWZSBEdW1teSIpIHsKICAgICAgICByZXR1cm4gZmlsZTsKICAgIH0KICAgIGxldCBmaWxlSUQ7CiAgICBsZXQgaW5kaWNhdG9yID0gZmlsZS5jaGFyQXQoMCk7CiAgICBzd2l0Y2ggKGluZGljYXRvcikgewogICAgICAgIGNhc2UgIk0iOgogICAgICAgICAgICBmaWxlVHlwZSA9ICJtM3UiOwogICAgICAgICAgICBmaWxlSUQgPSBmaWxlOwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJIIjoKICAgICAgICAgICAgZmlsZVR5cGUgPSAiaGRociI7CiAgICAgICAgICAgIGZpbGVJRCA9IGZpbGU7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlgiOgogICAgICAgICAgICBmaWxlVHlwZSA9ICJ4bWx0diI7CiAgICAgICAgICAgIGZpbGVJRCA9IGZpbGUuc3Vic3RyaW5nKDAsIGZpbGUubGFzdEluZGV4T2YoJy4nKSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgfQogICAgaWYgKFNFUlZFUlsic2V0dGluZ3MiXVsiZmlsZXMiXVtmaWxlVHlwZV0uaGFzT3duUHJvcGVydHkoZmlsZUlEKSA9PSB0cnVlKSB7CiAgICAgICAgdmFyIGRhdGEgPSBTRVJWRVJbInNldHRpbmdzIl1bImZpbGVzIl1bZmlsZVR5cGVdW2ZpbGVJRF07CiAgICAgICAgcmV0dXJuIGRhdGFba2V5XTsKICAgIH0KICAgIHJldHVybjsKfQpmdW5jdGlvbiBzZXRYbWx0dkNoYW5uZWwoZXBnTWFwSWQsIHhtbFR2RmlsZVNlbGVjdCkgewogICAgY29uc3QgeG1sVHYgPSBuZXcgWE1MVFZGaWxlKCk7CiAgICBjb25zdCBuZXdYbWxUdkZpbGUgPSB4bWxUdkZpbGVTZWxlY3QudmFsdWU7CiAgICAvLyBSZW1vdmUgb2xkIFhNTFRWIElEIHNlbGVjdGlvbiBib3gKICAgIGNvbnN0IHhtbFR2SWRQaWNrZXJQYXJlbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneG1sdHYtaWQtcGlja2VyLWNvbnRhaW5lcicpLnBhcmVudEVsZW1lbnQ7CiAgICB4bWxUdklkUGlja2VyUGFyZW50LmlubmVySFRNTCA9ICcnOwogICAgLy8gQ3JlYXRlIG5ldyBYTUxUViBJRCBzZWxlY3Rpb24gYm94CiAgICBjb25zdCB0dmdJZCA9IFNFUlZFUlsneGVwZyddWydlcGdNYXBwaW5nJ11bZXBnTWFwSWRdWyd0dmctaWQnXTsKICAgIGNvbnN0IFt4bWxUdklkQ29udGFpbmVyLCB4bWxUdklkSW5wdXQsIHhtbFR2SWREYXRhbGlzdF0gPSB4bWxUdi5uZXdYbWxUdklkUGlja2VyKG5ld1htbFR2RmlsZSwgdHZnSWQpOwogICAgeG1sVHZJZENvbnRhaW5lci5zZXRBdHRyaWJ1dGUoJ2lkJywgJ3htbHR2LWlkLXBpY2tlci1jb250YWluZXInKTsKICAgIHhtbFR2SWRJbnB1dC5zZXRBdHRyaWJ1dGUoJ2xpc3QnLCAneG1sdHYtaWQtcGlja2VyLWRhdGFsaXN0Jyk7CiAgICB4bWxUdklkSW5wdXQuc2V0QXR0cmlidXRlKCduYW1lJywgJ3gtbWFwcGluZycpOyAvLyBTaG91bGQgc3RheSB4LW1hcHBpbmcgYXMgaXQgd2lsbCBiZSB1c2VkIGluIGRvbmVQb3B1cERhdGEgdG8gbWFrZSBhIHNlcnZlciByZXF1ZXN0CiAgICB4bWxUdklkSW5wdXQuc2V0QXR0cmlidXRlKCdpZCcsICd4bWx0di1pZC1waWNrZXItaW5wdXQnKTsKICAgIHhtbFR2SWRJbnB1dC5zZXRBdHRyaWJ1dGUoJ29uY2hhbmdlJywgYGphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnOyBjaGVja1htbHR2Q2hhbm5lbCgnJHtlcGdNYXBJZH0nLCB0aGlzLnZhbHVlLCAnJHtuZXdYbWxUdkZpbGV9Jyk7YCk7CiAgICB4bWxUdklkSW5wdXQuY2xhc3NMaXN0LmFkZCgnY2hhbmdlZCcpOwogICAgeG1sVHZJZERhdGFsaXN0LnNldEF0dHJpYnV0ZSgnaWQnLCAneG1sdHYtaWQtcGlja2VyLWRhdGFsaXN0Jyk7CiAgICAvLyBBZGQgbmV3IFhNTFRWIElEIHNlbGVjdGlvbiBib3ggdG8gaXQncyBwYXJlbnQKICAgIHhtbFR2SWRQaWNrZXJQYXJlbnQuYXBwZW5kQ2hpbGQoeG1sVHZJZENvbnRhaW5lcik7CiAgICBjaGVja1htbHR2Q2hhbm5lbChlcGdNYXBJZCwgeG1sVHZJZElucHV0LnZhbHVlLCBuZXdYbWxUdkZpbGUpOwp9CmZ1bmN0aW9uIGNoZWNrWG1sdHZDaGFubmVsKGVwZ01hcElkLCBuZXdYbWxUdklkLCB4bWxUdkZpbGUpIHsKICAgIGNvbnN0IGNoYW5uZWxBY3RpdmVDYiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhY3RpdmUnKTsKICAgIGNvbnN0IGNoYW5uZWxBY3RpdmUgPSBuZXdYbWxUdklkICE9ICctJzsKICAgIGNoYW5uZWxBY3RpdmVDYi5jaGVja2VkID0gY2hhbm5lbEFjdGl2ZTsKICAgIGNoYW5uZWxBY3RpdmVDYi5jbGFzc05hbWUgPSAnY2hhbmdlZCc7CiAgICBpZiAoeG1sVHZGaWxlICE9ICd4VGVWZSBEdW1teScgJiYgY2hhbm5lbEFjdGl2ZSA9PSB0cnVlKSB7CiAgICAgICAgY2hhbmdlQ2hhbm5lbExvZ28oZXBnTWFwSWQpOwogICAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh4bWxUdkZpbGUgPT0gJ3hUZVZlIER1bW15JykgewogICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd1cGRhdGUtaWNvbicpLmNoZWNrZWQgPSBmYWxzZTsKICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndXBkYXRlLWljb24nKS5jbGFzc05hbWUgPSAnY2hhbmdlZCc7CiAgICB9Cn0KZnVuY3Rpb24gY2hhbmdlQ2hhbm5lbExvZ28oZXBnTWFwSWQpIHsKICAgIGNvbnN0IGNoYW5uZWwgPSBTRVJWRVJbJ3hlcGcnXVsnZXBnTWFwcGluZyddW2VwZ01hcElkXTsKICAgIGNvbnN0IHhtbFR2RmlsZVNlbGVjdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwb3B1cC14bWx0dicpOwogICAgY29uc3QgeG1sVHZGaWxlID0geG1sVHZGaWxlU2VsZWN0Lm9wdGlvbnNbeG1sVHZGaWxlU2VsZWN0LnNlbGVjdGVkSW5kZXhdLnZhbHVlOwogICAgY29uc3QgeG1sVHZJZElucHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3htbHR2LWlkLXBpY2tlci1pbnB1dCcpOwogICAgY29uc3QgbmV3WG1sVHZJZCA9IHhtbFR2SWRJbnB1dC52YWx1ZTsKICAgIGNvbnN0IHVwZGF0ZUxvZ28gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndXBkYXRlLWljb24nKS5jaGVja2VkOwogICAgbGV0IGxvZ287CiAgICBpZiAodXBkYXRlTG9nbyA9PSB0cnVlICYmIHhtbFR2RmlsZSAhPSAneFRlVmUgRHVtbXknKSB7CiAgICAgICAgaWYgKFNFUlZFUlsneGVwZyddWyd4bWx0dk1hcCddW3htbFR2RmlsZV0uaGFzT3duUHJvcGVydHkobmV3WG1sVHZJZCkpIHsKICAgICAgICAgICAgbG9nbyA9IFNFUlZFUlsneGVwZyddWyd4bWx0dk1hcCddW3htbFR2RmlsZV1bbmV3WG1sVHZJZF1bJ2ljb24nXTsKICAgICAgICB9CiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGxvZ28gPSBjaGFubmVsWyd0dmctbG9nbyddOwogICAgICAgIH0KICAgICAgICB2YXIgbG9nb0lucHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2NoYW5uZWwtaWNvbicpOwogICAgICAgIGxvZ29JbnB1dC52YWx1ZSA9IGxvZ287CiAgICAgICAgaWYgKEJVTEtfRURJVCA9PSBmYWxzZSkgewogICAgICAgICAgICBsb2dvSW5wdXQuY2xhc3NOYW1lID0gJ2NoYW5nZWQnOwogICAgICAgIH0KICAgIH0KfQpmdW5jdGlvbiBzYXZlUG9wdXBEYXRhKGRhdGFUeXBlLCBpZCwgcmVtb3ZlLCBvcHRpb24pIHsKICAgIGlmIChkYXRhVHlwZSA9PSAibWFwcGluZyIpIHsKICAgICAgICBsZXQgZGF0YSA9IHt9OwogICAgICAgIGxldCBjbWQgPSAic2F2ZUVwZ01hcHBpbmciOwogICAgICAgIGRhdGFbImVwZ01hcHBpbmciXSA9IFNFUlZFUlsieGVwZyJdWyJlcGdNYXBwaW5nIl07CiAgICAgICAgbGV0IHNlcnZlciA9IG5ldyBTZXJ2ZXIoY21kKTsKICAgICAgICBzZXJ2ZXIucmVxdWVzdChkYXRhKTsKICAgICAgICBkZWxldGUgVU5ET1siZXBnTWFwcGluZyJdOwogICAgICAgIHJldHVybjsKICAgIH0KICAgIGxldCBkaXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgicG9wdXAtY3VzdG9tIik7CiAgICBsZXQgaW5wdXRzID0gZGl2LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJUQUJMRSIpWzBdLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJJTlBVVCIpOwogICAgbGV0IHNlbGVjdHMgPSBkaXYuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlRBQkxFIilbMF0uZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlNFTEVDVCIpOwogICAgbGV0IGlucHV0ID0ge307CiAgICBsZXQgY29uZmlybU1zZzsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0cy5sZW5ndGg7IGkrKykgewogICAgICAgIHZhciBuYW1lOwogICAgICAgIG5hbWUgPSBzZWxlY3RzW2ldLm5hbWU7CiAgICAgICAgdmFyIHZhbHVlID0gc2VsZWN0c1tpXS52YWx1ZTsKICAgICAgICBzd2l0Y2ggKG5hbWUpIHsKICAgICAgICAgICAgY2FzZSAidHVuZXIiOgogICAgICAgICAgICAgICAgaW5wdXRbbmFtZV0gPSBwYXJzZUludCh2YWx1ZSk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIGlucHV0W25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0cy5sZW5ndGg7IGkrKykgewogICAgICAgIHN3aXRjaCAoaW5wdXRzW2ldLnR5cGUpIHsKICAgICAgICAgICAgY2FzZSAiY2hlY2tib3giOgogICAgICAgICAgICAgICAgbmFtZSA9IGlucHV0c1tpXS5uYW1lOwogICAgICAgICAgICAgICAgaW5wdXRbbmFtZV0gPSBpbnB1dHNbaV0uY2hlY2tlZDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ0ZXh0IjoKICAgICAgICAgICAgY2FzZSAiaGlkZGVuIjoKICAgICAgICAgICAgY2FzZSAicGFzc3dvcmQiOgogICAgICAgICAgICAgICAgbmFtZSA9IGlucHV0c1tpXS5uYW1lOwogICAgICAgICAgICAgICAgc3dpdGNoIChuYW1lKSB7CiAgICAgICAgICAgICAgICAgICAgY2FzZSAidHVuZXIiOgogICAgICAgICAgICAgICAgICAgICAgICBpbnB1dFtuYW1lXSA9IHBhcnNlSW50KGlucHV0c1tpXS52YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0W25hbWVdID0gaW5wdXRzW2ldLnZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0KICAgIGxldCBkYXRhID0ge307CiAgICBsZXQgY21kOwogICAgaWYgKHJlbW92ZSA9PSB0cnVlKSB7CiAgICAgICAgaW5wdXRbImRlbGV0ZSJdID0gdHJ1ZTsKICAgIH0KICAgIHN3aXRjaCAoZGF0YVR5cGUpIHsKICAgICAgICBjYXNlICJ1c2VycyI6CiAgICAgICAgICAgIGNvbmZpcm1Nc2cgPSAiRGVsZXRlIHRoaXMgdXNlcj8iOwogICAgICAgICAgICBpZiAoaWQgPT0gIi0iKSB7CiAgICAgICAgICAgICAgICBjbWQgPSAic2F2ZU5ld1VzZXIiOwogICAgICAgICAgICAgICAgZGF0YVsidXNlckRhdGEiXSA9IGlucHV0OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgY21kID0gInNhdmVVc2VyRGF0YSI7CiAgICAgICAgICAgICAgICBsZXQgZCA9IHt9OwogICAgICAgICAgICAgICAgZFtpZF0gPSBpbnB1dDsKICAgICAgICAgICAgICAgIGRhdGFbInVzZXJEYXRhIl0gPSBkOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm0zdSI6CiAgICAgICAgICAgIGNvbmZpcm1Nc2cgPSAiRGVsZXRlIHRoaXMgcGxheWxpc3Q/IjsKICAgICAgICAgICAgc3dpdGNoIChvcHRpb24pIHsKICAgICAgICAgICAgICAgIC8vIFBvcHVwOiBTYXZlCiAgICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICAgICAgY21kID0gInNhdmVGaWxlc00zVSI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAvLyBQb3B1cDogVXBkYXRlCiAgICAgICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgICAgICAgY21kID0gInVwZGF0ZUZpbGVNM1UiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRhdGFbImZpbGVzIl0gPSB7fTsKICAgICAgICAgICAgZGF0YVsiZmlsZXMiXVtkYXRhVHlwZV0gPSB7fTsKICAgICAgICAgICAgZGF0YVsiZmlsZXMiXVtkYXRhVHlwZV1baWRdID0gaW5wdXQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImhkaHIiOgogICAgICAgICAgICBjb25maXJtTXNnID0gIkRlbGV0ZSB0aGlzIEhESG9tZVJ1biB0dW5lcj8iOwogICAgICAgICAgICBzd2l0Y2ggKG9wdGlvbikgewogICAgICAgICAgICAgICAgLy8gUG9wdXA6IFNhdmUKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgICBjbWQgPSAic2F2ZUZpbGVzSERIUiI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAvLyBQb3B1cDogVXBkYXRlCiAgICAgICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgICAgICAgY21kID0gInVwZGF0ZUZpbGVIREhSIjsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBkYXRhWyJmaWxlcyJdID0ge307CiAgICAgICAgICAgIGRhdGFbImZpbGVzIl1bZGF0YVR5cGVdID0ge307CiAgICAgICAgICAgIGRhdGFbImZpbGVzIl1bZGF0YVR5cGVdW2lkXSA9IGlucHV0OwogICAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJ4bWx0diI6CiAgICAgICAgICAgIGNvbmZpcm1Nc2cgPSAiRGVsZXRlIHRoaXMgWE1MVFYgZmlsZT8iOwogICAgICAgICAgICBzd2l0Y2ggKG9wdGlvbikgewogICAgICAgICAgICAgICAgLy8gUG9wdXA6IFNhdmUKICAgICAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICAgICAgICBjbWQgPSAic2F2ZUZpbGVzWE1MVFYiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgLy8gUG9wdXA6IFVwZGF0ZQogICAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgICAgIGNtZCA9ICJ1cGRhdGVGaWxlWE1MVFYiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRhdGFbImZpbGVzIl0gPSB7fTsKICAgICAgICAgICAgZGF0YVsiZmlsZXMiXVtkYXRhVHlwZV0gPSB7fTsKICAgICAgICAgICAgZGF0YVsiZmlsZXMiXVtkYXRhVHlwZV1baWRdID0gaW5wdXQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImZpbHRlciI6CiAgICAgICAgICAgIGNvbmZpcm1Nc2cgPSAiRGVsZXRlIHRoaXMgZmlsdGVyPyI7CiAgICAgICAgICAgIGNtZCA9ICJzYXZlRmlsdGVyIjsKICAgICAgICAgICAgZGF0YVsiZmlsdGVyIl0gPSB7fTsKICAgICAgICAgICAgZGF0YVsiZmlsdGVyIl1baWRdID0gaW5wdXQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChyZW1vdmUgPT0gdHJ1ZSkgewogICAgICAgIGlmICghY29uZmlybShjb25maXJtTXNnKSkgewogICAgICAgICAgICBzaG93RWxlbWVudCgicG9wdXAiLCBmYWxzZSk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICB9CiAgICBsZXQgc2VydmVyID0gbmV3IFNlcnZlcihjbWQpOwogICAgc2VydmVyLnJlcXVlc3QoZGF0YSk7Cn0KZnVuY3Rpb24gZG9uZVBvcHVwRGF0YShkYXRhVHlwZSwgaWRzU3RyKSB7CiAgICBsZXQgaWRzID0gaWRzU3RyLnNwbGl0KCcsJyk7CiAgICBsZXQgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInBvcHVwLWN1c3RvbSIpOwogICAgbGV0IGlucHV0cyA9IGRpdi5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCJjaGFuZ2VkIik7CiAgICBpZHMuZm9yRWFjaChpZCA9PiB7CiAgICAgICAgbGV0IGlucHV0OwogICAgICAgIGlucHV0ID0gU0VSVkVSWyJ4ZXBnIl1bImVwZ01hcHBpbmciXVtpZF07CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dHMubGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgbGV0IG5hbWU7CiAgICAgICAgICAgIGxldCB2YWx1ZTsKICAgICAgICAgICAgc3dpdGNoIChpbnB1dHNbaV0udGFnTmFtZSkgewogICAgICAgICAgICAgICAgY2FzZSAiSU5QVVQiOgogICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoaW5wdXRzW2ldLnR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiY2hlY2tib3giOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9IGlucHV0c1tpXS5uYW1lOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBpbnB1dHNbaV0uY2hlY2tlZDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0W25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAidGV4dCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gaW5wdXRzW2ldLm5hbWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGlucHV0c1tpXS52YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0W25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJTRUxFQ1QiOgogICAgICAgICAgICAgICAgICAgIG5hbWUgPSBpbnB1dHNbaV0ubmFtZTsKICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGlucHV0c1tpXS52YWx1ZTsKICAgICAgICAgICAgICAgICAgICBpbnB1dFtuYW1lXSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN3aXRjaCAobmFtZSkgewogICAgICAgICAgICAgICAgY2FzZSAidHZnLWxvZ28iOgogICAgICAgICAgICAgICAgICAgIC8vKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jaGlsZE5vZGVzWzJdLmZpcnN0Q2hpbGQgYXMgSFRNTEVsZW1lbnQpLnNldEF0dHJpYnV0ZSgic3JjIiwgdmFsdWUpCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJ4LW5hbWUiOgogICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jaGlsZE5vZGVzWzNdLmZpcnN0Q2hpbGQuaW5uZXJIVE1MID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJ4LWNhdGVnb3J5IjoKICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCkuY2hpbGROb2Rlc1szXS5maXJzdENoaWxkLmNsYXNzTmFtZSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAidXBkYXRlLWNoYW5uZWwtbmFtZS1yZWdleCI6CiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpLmNoaWxkTm9kZXNbNF0uZmlyc3RDaGlsZC5pbm5lckhUTUwgPSB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgIngtZ3JvdXAtdGl0bGUiOgogICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jaGlsZE5vZGVzWzZdLmZpcnN0Q2hpbGQuaW5uZXJIVE1MID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJ4LXhtbHR2LWZpbGUiOgogICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSAhPSAieFRlVmUgRHVtbXkiICYmIHZhbHVlICE9ICItIikgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGdldFZhbHVlRnJvbVByb3ZpZGVyRmlsZSh2YWx1ZSwgInhtbHR2IiwgIm5hbWUiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlID09ICItIikgewogICAgICAgICAgICAgICAgICAgICAgICBpbnB1dFsieC1hY3RpdmUiXSA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCkuY2hpbGROb2Rlc1s3XS5maXJzdENoaWxkLmlubmVySFRNTCA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAieC1tYXBwaW5nIjoKICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgPT0gIi0iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0WyJ4LWFjdGl2ZSJdID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKS5jaGlsZE5vZGVzWzhdLmZpcnN0Q2hpbGQuaW5uZXJIVE1MID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJ4LXRpbWVzaGlmdCI6CiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpLmNoaWxkTm9kZXNbOV0uZmlyc3RDaGlsZC5pbm5lckhUTUwgPSB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY3JlYXRlU2VhcmNoT2JqKCk7CiAgICAgICAgICAgIHNlYXJjaEluTWFwcGluZygpOwogICAgICAgIH0KICAgICAgICBpZiAoaW5wdXRbIngtYWN0aXZlIl0gPT0gZmFsc2UpIHsKICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpLmNsYXNzTmFtZSA9ICJub3RBY3RpdmVFUEciOwogICAgICAgIH0KICAgICAgICBlbHNlIHsKICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpLmNsYXNzTmFtZSA9ICJhY3RpdmVFUEciOwogICAgICAgIH0KICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCkuY2hpbGROb2Rlc1syXS5maXJzdENoaWxkLnNldEF0dHJpYnV0ZSgic3JjIiwgaW5wdXRbInR2Zy1sb2dvIl0pOwogICAgfSk7CiAgICBzaG93RWxlbWVudCgicG9wdXAiLCBmYWxzZSk7CiAgICByZXR1cm47Cn0KZnVuY3Rpb24gc2hvd1ByZXZpZXcoZWxlbWVudCkgewogICAgbGV0IGRpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJteVN0cmVhbXNCb3giKTsKICAgIHN3aXRjaCAoZWxlbWVudCkgewogICAgICAgIGNhc2UgZmFsc2U6CiAgICAgICAgICAgIGRpdi5jbGFzc05hbWUgPSAibm90VmlzaWJsZSI7CiAgICAgICAgICAgIHJldHVybjsKICAgIH0KICAgIGxldCBzdHJlYW1zID0gWyJhY3RpdmVTdHJlYW1zIiwgImluYWN0aXZlU3RyZWFtcyJdOwogICAgc3RyZWFtcy5mb3JFYWNoKHByZXZpZXcgPT4gewogICAgICAgIGxldCB0YWJsZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHByZXZpZXcpOwogICAgICAgIHRhYmxlLmlubmVySFRNTCA9ICIiOwogICAgICAgIGxldCBvYmogPSBTRVJWRVJbImRhdGEiXVsiU3RyZWFtUHJldmlld1VJIl1bcHJldmlld107CiAgICAgICAgb2JqLmZvckVhY2goY2hhbm5lbCA9PiB7CiAgICAgICAgICAgIGxldCB0ciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlRSIik7CiAgICAgICAgICAgIGxldCB0ZEtleSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgIGxldCB0ZFZhbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgIHRkS2V5LmNsYXNzTmFtZSA9ICJ0ZEtleSI7CiAgICAgICAgICAgIHRkVmFsLmNsYXNzTmFtZSA9ICJ0ZFZhbCI7CiAgICAgICAgICAgIHN3aXRjaCAocHJldmlldykgewogICAgICAgICAgICAgICAgY2FzZSAiYWN0aXZlU3RyZWFtcyI6CiAgICAgICAgICAgICAgICAgICAgdGRLZXkuaW5uZXJUZXh0ID0gIkNoYW5uZWw6ICgrKSI7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlICJpbmFjdGl2ZVN0cmVhbXMiOgogICAgICAgICAgICAgICAgICAgIHRkS2V5LmlubmVyVGV4dCA9ICJDaGFubmVsOiAoLSkiOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRkVmFsLmlubmVyVGV4dCA9IGNoYW5uZWw7CiAgICAgICAgICAgIHRyLmFwcGVuZENoaWxkKHRkS2V5KTsKICAgICAgICAgICAgdHIuYXBwZW5kQ2hpbGQodGRWYWwpOwogICAgICAgICAgICB0YWJsZS5hcHBlbmRDaGlsZCh0cik7CiAgICAgICAgfSk7CiAgICB9KTsKICAgIHNob3dFbGVtZW50KCJsb2FkaW5nIiwgZmFsc2UpOwogICAgZGl2LmNsYXNzTmFtZSA9ICJ2aXNpYmxlIjsKICAgIHJldHVybjsKfQo=" + webUI["html/js/network_ts.js"] = "Y2xhc3MgU2VydmVyIHsKICAgIGNvbnN0cnVjdG9yKGNtZCkgewogICAgICAgIHRoaXMuY21kID0gY21kOwogICAgfQogICAgcmVxdWVzdChkYXRhKSB7CiAgICAgICAgaWYgKFNFUlZFUl9DT05ORUNUSU9OID09IHRydWUpIHsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBTRVJWRVJfQ09OTkVDVElPTiA9IHRydWU7CiAgICAgICAgaWYgKHRoaXMuY21kICE9ICJ1cGRhdGVMb2ciKSB7CiAgICAgICAgICAgIHNob3dFbGVtZW50KCJsb2FkaW5nIiwgdHJ1ZSk7CiAgICAgICAgICAgIFVORE8gPSBuZXcgT2JqZWN0KCk7CiAgICAgICAgfQogICAgICAgIHN3aXRjaCAod2luZG93LmxvY2F0aW9uLnByb3RvY29sKSB7CiAgICAgICAgICAgIGNhc2UgImh0dHA6IjoKICAgICAgICAgICAgICAgIHRoaXMucHJvdG9jb2wgPSAid3M6Ly8iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImh0dHBzOiI6CiAgICAgICAgICAgICAgICB0aGlzLnByb3RvY29sID0gIndzczovLyI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdmFyIHVybCA9IHRoaXMucHJvdG9jb2wgKyB3aW5kb3cubG9jYXRpb24uaG9zdG5hbWUgKyAiOiIgKyB3aW5kb3cubG9jYXRpb24ucG9ydCArICIvZGF0YS8iICsgIj9Ub2tlbj0iICsgZ2V0Q29va2llKCJUb2tlbiIpOwogICAgICAgIGRhdGFbImNtZCJdID0gdGhpcy5jbWQ7CiAgICAgICAgdmFyIHdzID0gbmV3IFdlYlNvY2tldCh1cmwpOwogICAgICAgIHdzLm9ub3BlbiA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgV1NfQVZBSUxBQkxFID0gdHJ1ZTsKICAgICAgICAgICAgdGhpcy5zZW5kKEpTT04uc3RyaW5naWZ5KGRhdGEpKTsKICAgICAgICB9OwogICAgICAgIHdzLm9uZXJyb3IgPSBmdW5jdGlvbiAod3NFcnJFdnQpIHsKICAgICAgICAgICAgY29uc29sZS5sb2coIk5vIHdlYnNvY2tldCBjb25uZWN0aW9uIHRvIHhUZVZlIGNvdWxkIGJlIGVzdGFibGlzaGVkLiBDaGVjayB5b3VyIG5ldHdvcmsgY29uZmlndXJhdGlvbi4iKTsKICAgICAgICAgICAgU0VSVkVSX0NPTk5FQ1RJT04gPSBmYWxzZTsKICAgICAgICAgICAgaWYgKFdTX0FWQUlMQUJMRSA9PSBmYWxzZSkgewogICAgICAgICAgICAgICAgYWxlcnQoIk5vIHdlYnNvY2tldCBjb25uZWN0aW9uIHRvIHhUZVZlIGNvdWxkIGJlIGVzdGFibGlzaGVkLiBDaGVjayB5b3VyIG5ldHdvcmsgY29uZmlndXJhdGlvbi4iKTsKICAgICAgICAgICAgfQogICAgICAgIH07CiAgICAgICAgd3Mub25tZXNzYWdlID0gZnVuY3Rpb24gKHdzTWVzc2FnZUV2dCkgewogICAgICAgICAgICBTRVJWRVJfQ09OTkVDVElPTiA9IGZhbHNlOwogICAgICAgICAgICBzaG93RWxlbWVudCgibG9hZGluZyIsIGZhbHNlKTsKICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBKU09OLnBhcnNlKHdzTWVzc2FnZUV2dC5kYXRhKTsKICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KCJ0b2tlbiIpKSB7CiAgICAgICAgICAgICAgICBkb2N1bWVudC5jb29raWUgPSAiVG9rZW49IiArIHJlc3BvbnNlWyJ0b2tlbiJdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChyZXNwb25zZVsic3RhdHVzIl0gPT0gZmFsc2UpIHsKICAgICAgICAgICAgICAgIGFsZXJ0KHJlc3BvbnNlWyJlcnIiXSk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KCdvcGVuTGluaycpKSB7CiAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24gPSByZXNwb25zZVsnb3BlbkxpbmsnXTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocmVzcG9uc2UuaGFzT3duUHJvcGVydHkoInJlbG9hZCIpKSB7CiAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KCJhbGVydCIpKSB7CiAgICAgICAgICAgICAgICBhbGVydChyZXNwb25zZVsiYWxlcnQiXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KCJsb2dvVVJMIikpIHsKICAgICAgICAgICAgICAgIHZhciBkaXYgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiY2hhbm5lbC1pY29uIik7CiAgICAgICAgICAgICAgICBkaXYudmFsdWUgPSByZXNwb25zZVsibG9nb1VSTCJdOwogICAgICAgICAgICAgICAgZGl2LmNsYXNzTmFtZSA9ICJjaGFuZ2VkIjsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBzd2l0Y2ggKGRhdGFbImNtZCJdKSB7CiAgICAgICAgICAgICAgICBjYXNlICJ1cGRhdGVMb2ciOgogICAgICAgICAgICAgICAgICAgIFNFUlZFUlsibG9nIl0gPSByZXNwb25zZVsibG9nIl07CiAgICAgICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJjb250ZW50X2xvZyIpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dMb2dzKGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICBTRVJWRVIgPSBuZXcgT2JqZWN0KCk7CiAgICAgICAgICAgICAgICAgICAgU0VSVkVSID0gcmVzcG9uc2U7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KCJvcGVuTWVudSIpKSB7CiAgICAgICAgICAgICAgICB2YXIgbWVudSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHJlc3BvbnNlWyJvcGVuTWVudSJdKTsKICAgICAgICAgICAgICAgIG1lbnUuY2xpY2soKTsKICAgICAgICAgICAgICAgIHNob3dFbGVtZW50KCJwb3B1cCIsIGZhbHNlKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocmVzcG9uc2UuaGFzT3duUHJvcGVydHkoInJlbG9hZCIpKSB7CiAgICAgICAgICAgICAgICBsb2NhdGlvbi5yZWxvYWQoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocmVzcG9uc2UuaGFzT3duUHJvcGVydHkoIndpemFyZCIpKSB7CiAgICAgICAgICAgICAgICBjcmVhdGVMYXlvdXQoKTsKICAgICAgICAgICAgICAgIGNvbmZpZ3VyYXRpb25XaXphcmRbcmVzcG9uc2VbIndpemFyZCJdXS5jcmVhdGVXaXphcmQoKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBjcmVhdGVMYXlvdXQoKTsKICAgICAgICB9OwogICAgfQp9CmZ1bmN0aW9uIGdldENvb2tpZShuYW1lKSB7CiAgICB2YXIgdmFsdWUgPSAiOyAiICsgZG9jdW1lbnQuY29va2llOwogICAgdmFyIHBhcnRzID0gdmFsdWUuc3BsaXQoIjsgIiArIG5hbWUgKyAiPSIpOwogICAgaWYgKHBhcnRzLmxlbmd0aCA9PSAyKSB7CiAgICAgICAgcmV0dXJuIHBhcnRzLnBvcCgpLnNwbGl0KCI7Iikuc2hpZnQoKTsKICAgIH0KfQo=" + webUI["html/js/settings_ts.js"] = "Y2xhc3MgU2V0dGluZ3NDYXRlZ29yeSB7CiAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICB0aGlzLkRvY3VtZW50SUQgPSAiY29udGVudF9zZXR0aW5ncyI7CiAgICB9CiAgICBjcmVhdGVDYXRlZ29yeUhlYWRsaW5lKHZhbHVlKSB7CiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJINCIpOwogICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gdmFsdWU7CiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9CiAgICBjcmVhdGVIUigpIHsKICAgICAgICB2YXIgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIkhSIik7CiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9CiAgICBjcmVhdGVTZXR0aW5ncyhzZXR0aW5nc0tleSkgewogICAgICAgIHZhciBzZXR0aW5nID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVFIiKTsKICAgICAgICB2YXIgY29udGVudCA9IG5ldyBQb3B1cENvbnRlbnQoKTsKICAgICAgICB2YXIgZGF0YSA9IFNFUlZFUlsic2V0dGluZ3MiXVtzZXR0aW5nc0tleV07CiAgICAgICAgc3dpdGNoIChzZXR0aW5nc0tleSkgewogICAgICAgICAgICAvLyBUZXh0IGlucHV0cwogICAgICAgICAgICBjYXNlICJ1cGRhdGUiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLnVwZGF0ZS50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCAidXBkYXRlIiwgZGF0YS50b1N0cmluZygpKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3suc2V0dGluZ3MudXBkYXRlLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgIHRkUmlnaHQuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJiYWNrdXAucGF0aCI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuYmFja3VwUGF0aC50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCAiYmFja3VwLnBhdGgiLCBkYXRhKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3suc2V0dGluZ3MuYmFja3VwUGF0aC5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAidGVtcC5wYXRoIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy50ZW1wUGF0aC50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCAidGVtcC5wYXRoIiwgZGF0YSk7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LnNldHRpbmdzLnRtcFBhdGgucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInVzZXIuYWdlbnQiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLnVzZXJBZ2VudC50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCAidXNlci5hZ2VudCIsIGRhdGEpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5zZXR0aW5ncy51c2VyQWdlbnQucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImJ1ZmZlci50aW1lb3V0IjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5idWZmZXJUaW1lb3V0LnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsICJidWZmZXIudGltZW91dCIsIGRhdGEpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5zZXR0aW5ncy5idWZmZXJUaW1lb3V0LnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgIHRkUmlnaHQuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJmZm1wZWcucGF0aCI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuZmZtcGVnUGF0aC50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCAiZmZtcGVnLnBhdGgiLCBkYXRhKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3suc2V0dGluZ3MuZmZtcGVnUGF0aC5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiZmZtcGVnLm9wdGlvbnMiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLmZmbXBlZ09wdGlvbnMudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgImZmbXBlZy5vcHRpb25zIiwgZGF0YSk7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LnNldHRpbmdzLmZmbXBlZ09wdGlvbnMucGxhY2Vob2xkZXJ9fSIpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInZsYy5wYXRoIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy52bGNQYXRoLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsICJ2bGMucGF0aCIsIGRhdGEpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5zZXR0aW5ncy52bGNQYXRoLnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgIHRkUmlnaHQuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ2bGMub3B0aW9ucyI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MudmxjT3B0aW9ucy50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlSW5wdXQoInRleHQiLCAidmxjLm9wdGlvbnMiLCBkYXRhKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgicGxhY2Vob2xkZXIiLCAie3suc2V0dGluZ3MudmxjT3B0aW9ucy5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgLy8gQ2hlY2tib3hlcwogICAgICAgICAgICBjYXNlICJ0bHNNb2RlIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy50bHNNb2RlLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVDaGVja2JveChzZXR0aW5nc0tleSk7CiAgICAgICAgICAgICAgICBpbnB1dC5jaGVja2VkID0gZGF0YTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgIHRkUmlnaHQuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJkaXNhbGxvd1VSTER1cGxpY2F0ZXMiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLmRpc2FsbG93VVJMRHVwbGljYXRlcy50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGE7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYXV0aGVudGljYXRpb24ud2ViIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5hdXRoZW50aWNhdGlvbldFQi50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGE7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYXV0aGVudGljYXRpb24ucG1zIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5hdXRoZW50aWNhdGlvblBNUy50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGE7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYXV0aGVudGljYXRpb24ubTN1IjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5hdXRoZW50aWNhdGlvbk0zVS50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGE7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYXV0aGVudGljYXRpb24ueG1sIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5hdXRoZW50aWNhdGlvblhNTC50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGE7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYXV0aGVudGljYXRpb24uYXBpIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5hdXRoZW50aWNhdGlvbkFQSS50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGE7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiZmlsZXMudXBkYXRlIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5maWxlc1VwZGF0ZS50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGE7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiY2FjaGUuaW1hZ2VzIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5jYWNoZUltYWdlcy50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGE7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAieGVwZy5yZXBsYWNlLm1pc3NpbmcuaW1hZ2VzIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5yZXBsYWNlRW1wdHlJbWFnZXMudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInN0b3JlQnVmZmVySW5SQU0iOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLnN0b3JlQnVmZmVySW5SQU0udGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInh0ZXZlQXV0b1VwZGF0ZSI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MueHRldmVBdXRvVXBkYXRlLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVDaGVja2JveChzZXR0aW5nc0tleSk7CiAgICAgICAgICAgICAgICBpbnB1dC5jaGVja2VkID0gZGF0YTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgIHRkUmlnaHQuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJjbGVhclhNTFRWQ2FjaGUiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLmNsZWFyWE1MVFZDYWNoZS50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGE7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYXBpIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5hcGkudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUNoZWNrYm94KHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgIGlucHV0LmNoZWNrZWQgPSBkYXRhOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChpbnB1dCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgICAgICAgICBzZXR0aW5nLmFwcGVuZENoaWxkKHRkUmlnaHQpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImVuYWJsZU1hcHBlZENoYW5uZWxzIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5lbmFibGVNYXBwZWRDaGFubmVscy50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciBpbnB1dCA9IGNvbnRlbnQuY3JlYXRlQ2hlY2tib3goc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgaW5wdXQuY2hlY2tlZCA9IGRhdGE7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgLy8gU2VsZWN0CiAgICAgICAgICAgIGNhc2UgImhvc3RJUCI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuaG9zdElQLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIHRleHQgPSBTRVJWRVJbImlwQWRkcmVzc2VzVjRIb3N0Il07CiAgICAgICAgICAgICAgICB2YXIgdmFsdWVzID0gU0VSVkVSWyJpcEFkZHJlc3Nlc1Y0SG9zdCJdOwogICAgICAgICAgICAgICAgdmFyIHNlbGVjdCA9IGNvbnRlbnQuY3JlYXRlU2VsZWN0KHRleHQsIHZhbHVlcywgZGF0YSwgc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgIHRkUmlnaHQuYXBwZW5kQ2hpbGQoc2VsZWN0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiaG9zdE5hbWUiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLmhvc3ROYW1lLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIGlucHV0ID0gY29udGVudC5jcmVhdGVJbnB1dCgidGV4dCIsICJob3N0TmFtZSIsIGRhdGEpOwogICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCJwbGFjZWhvbGRlciIsICJ7ey5zZXR0aW5ncy5ob3N0TmFtZS5wbGFjZWhvbGRlcn19Iik7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoIm9uY2hhbmdlIiwgImphdmFzY3JpcHQ6IHRoaXMuY2xhc3NOYW1lID0gJ2NoYW5nZWQnIik7CiAgICAgICAgICAgICAgICB0ZFJpZ2h0LmFwcGVuZENoaWxkKGlucHV0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAidHVuZXIiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLnR1bmVyLnRpdGxlfX0iICsgIjoiOwogICAgICAgICAgICAgICAgdmFyIHRkUmlnaHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdmFyIHRleHQgPSBuZXcgQXJyYXkoKTsKICAgICAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBuZXcgQXJyYXkoKTsKICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDw9IDEwMDsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgdGV4dC5wdXNoKGkpOwogICAgICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKGkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFyIHNlbGVjdCA9IGNvbnRlbnQuY3JlYXRlU2VsZWN0KHRleHQsIHZhbHVlcywgZGF0YSwgc2V0dGluZ3NLZXkpOwogICAgICAgICAgICAgICAgc2VsZWN0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgIHRkUmlnaHQuYXBwZW5kQ2hpbGQoc2VsZWN0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRMZWZ0KTsKICAgICAgICAgICAgICAgIHNldHRpbmcuYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiZXBnU291cmNlIjoKICAgICAgICAgICAgICAgIHZhciB0ZExlZnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJURCIpOwogICAgICAgICAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICJ7ey5zZXR0aW5ncy5lcGdTb3VyY2UudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgdGV4dCA9IFsiUE1TIiwgIlhFUEciXTsKICAgICAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBbIlBNUyIsICJYRVBHIl07CiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ID0gY29udGVudC5jcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCBkYXRhLCBzZXR0aW5nc0tleSk7CiAgICAgICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChzZWxlY3QpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJkZWZhdWx0TWlzc2luZ0VQRyI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuZGVmYXVsdE1pc3NpbmdFUEcudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgdGV4dCA9IFsKICAgICAgICAgICAgICAgICAgICAiLSIsICIzMCBNaW51dGVzICgzMF9NaW51dGVzKSIsICI2MCBNaW51dGVzICg2MF9NaW51dGVzKSIsICI5MCBNaW51dGVzICg5MF9NaW51dGVzKSIsCiAgICAgICAgICAgICAgICAgICAgIjEyMCBNaW51dGVzICgxMjBfTWludXRlcykiLCAiMTgwIE1pbnV0ZXMgKDE4MF9NaW51dGVzKSIsICIyNDAgTWludXRlcyAoMjQwX01pbnV0ZXMpIiwgIjM2MCBNaW51dGVzICgzNjBfTWludXRlcykiCiAgICAgICAgICAgICAgICBdOwogICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IFsKICAgICAgICAgICAgICAgICAgICAiLSIsICIzMF9NaW51dGVzIiwgIjYwX01pbnV0ZXMiLCAiOTBfTWludXRlcyIsICIxMjBfTWludXRlcyIsICIxODBfTWludXRlcyIsICIyNDBfTWludXRlcyIsICIzNjBfTWludXRlcyIKICAgICAgICAgICAgICAgIF07CiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ID0gY29udGVudC5jcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCBkYXRhLCBzZXR0aW5nc0tleSk7CiAgICAgICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChzZWxlY3QpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJiYWNrdXAua2VlcCI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuYmFja3VwS2VlcC50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciB0ZXh0ID0gWyI1IiwgIjEwIiwgIjIwIiwgIjMwIiwgIjQwIiwgIjUwIl07CiAgICAgICAgICAgICAgICB2YXIgdmFsdWVzID0gWyI1IiwgIjEwIiwgIjIwIiwgIjMwIiwgIjQwIiwgIjUwIl07CiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ID0gY29udGVudC5jcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCBkYXRhLCBzZXR0aW5nc0tleSk7CiAgICAgICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChzZWxlY3QpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJidWZmZXIuc2l6ZS5rYiI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MuYnVmZmVyU2l6ZS50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciB0ZXh0ID0gWyIwLjUgTUIiLCAiMSBNQiIsICIyIE1CIiwgIjMgTUIiLCAiNCBNQiIsICI1IE1CIiwgIjYgTUIiLCAiNyBNQiIsICI4IE1CIl07CiAgICAgICAgICAgICAgICB2YXIgdmFsdWVzID0gWyI1MTIiLCAiMTAyNCIsICIyMDQ4IiwgIjMwNzIiLCAiNDA5NiIsICI1MTIwIiwgIjYxNDQiLCAiNzE2OCIsICI4MTkyIl07CiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ID0gY29udGVudC5jcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCBkYXRhLCBzZXR0aW5nc0tleSk7CiAgICAgICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChzZWxlY3QpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJidWZmZXIiOgogICAgICAgICAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB0ZExlZnQuaW5uZXJIVE1MID0gInt7LnNldHRpbmdzLnN0cmVhbUJ1ZmZlcmluZy50aXRsZX19IiArICI6IjsKICAgICAgICAgICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHZhciB0ZXh0ID0gWyJ7ey5zZXR0aW5ncy5zdHJlYW1CdWZmZXJpbmcuaW5mb19mYWxzZX19IiwgInhUZVZlOiAoe3suc2V0dGluZ3Muc3RyZWFtQnVmZmVyaW5nLmluZm9feHRldmV9fSkiLCAiRkZtcGVnOiAoe3suc2V0dGluZ3Muc3RyZWFtQnVmZmVyaW5nLmluZm9fZmZtcGVnfX0pIiwgIlZMQzogKHt7LnNldHRpbmdzLnN0cmVhbUJ1ZmZlcmluZy5pbmZvX3ZsY319KSJdOwogICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IFsiLSIsICJ4dGV2ZSIsICJmZm1wZWciLCAidmxjIl07CiAgICAgICAgICAgICAgICB2YXIgc2VsZWN0ID0gY29udGVudC5jcmVhdGVTZWxlY3QodGV4dCwgdmFsdWVzLCBkYXRhLCBzZXR0aW5nc0tleSk7CiAgICAgICAgICAgICAgICBzZWxlY3Quc2V0QXR0cmlidXRlKCJvbmNoYW5nZSIsICJqYXZhc2NyaXB0OiB0aGlzLmNsYXNzTmFtZSA9ICdjaGFuZ2VkJyIpOwogICAgICAgICAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChzZWxlY3QpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ1ZHB4eSI6CiAgICAgICAgICAgICAgICB2YXIgdGRMZWZ0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICAgICAgICAgIHRkTGVmdC5pbm5lckhUTUwgPSAie3suc2V0dGluZ3MudWRweHkudGl0bGV9fSIgKyAiOiI7CiAgICAgICAgICAgICAgICB2YXIgdGRSaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgICAgICAgICB2YXIgaW5wdXQgPSBjb250ZW50LmNyZWF0ZUlucHV0KCJ0ZXh0IiwgInVkcHh5IiwgZGF0YSk7CiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoInBsYWNlaG9sZGVyIiwgInt7LnNldHRpbmdzLnVkcHh5LnBsYWNlaG9sZGVyfX0iKTsKICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgib25jaGFuZ2UiLCAiamF2YXNjcmlwdDogdGhpcy5jbGFzc05hbWUgPSAnY2hhbmdlZCciKTsKICAgICAgICAgICAgICAgIHRkUmlnaHQuYXBwZW5kQ2hpbGQoaW5wdXQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZExlZnQpOwogICAgICAgICAgICAgICAgc2V0dGluZy5hcHBlbmRDaGlsZCh0ZFJpZ2h0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICByZXR1cm4gc2V0dGluZzsKICAgIH0KICAgIGNyZWF0ZURlc2NyaXB0aW9uKHNldHRpbmdzS2V5KSB7CiAgICAgICAgdmFyIGRlc2NyaXB0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVFIiKTsKICAgICAgICB2YXIgdGV4dDsKICAgICAgICBzd2l0Y2ggKHNldHRpbmdzS2V5KSB7CiAgICAgICAgICAgIGNhc2UgInRsc01vZGUiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy50bHNNb2RlLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImRpc2FsbG93VVJMRHVwbGljYXRlcyI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmRpc2FsbG93VVJMRHVwbGljYXRlcy5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJhdXRoZW50aWNhdGlvbi53ZWIiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy5hdXRoZW50aWNhdGlvbldFQi5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJhdXRoZW50aWNhdGlvbi5tM3UiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy5hdXRoZW50aWNhdGlvbk0zVS5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJhdXRoZW50aWNhdGlvbi5wbXMiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy5hdXRoZW50aWNhdGlvblBNUy5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJhdXRoZW50aWNhdGlvbi54bWwiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy5hdXRoZW50aWNhdGlvblhNTC5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJhdXRoZW50aWNhdGlvbi5hcGkiOgogICAgICAgICAgICAgICAgaWYgKFNFUlZFUlsic2V0dGluZ3MiXVsiYXV0aGVudGljYXRpb24ud2ViIl0gPT0gdHJ1ZSkgewogICAgICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MuYXV0aGVudGljYXRpb25BUEkuZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAieHRldmVBdXRvVXBkYXRlIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MueHRldmVBdXRvVXBkYXRlLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImJhY2t1cC5rZWVwIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MuYmFja3VwS2VlcC5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJiYWNrdXAucGF0aCI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmJhY2t1cFBhdGguZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAidGVtcC5wYXRoIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MudGVtcFBhdGguZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYnVmZmVyIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3Muc3RyZWFtQnVmZmVyaW5nLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImJ1ZmZlci5zaXplLmtiIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MuYnVmZmVyU2l6ZS5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJzdG9yZUJ1ZmZlckluUkFNIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3Muc3RvcmVCdWZmZXJJblJBTS5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJidWZmZXIudGltZW91dCI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmJ1ZmZlclRpbWVvdXQuZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAidXNlci5hZ2VudCI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLnVzZXJBZ2VudC5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJmZm1wZWcucGF0aCI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmZmbXBlZ1BhdGguZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiZmZtcGVnLm9wdGlvbnMiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy5mZm1wZWdPcHRpb25zLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInZsYy5wYXRoIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MudmxjUGF0aC5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ2bGMub3B0aW9ucyI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLnZsY09wdGlvbnMuZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiZXBnU291cmNlIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MuZXBnU291cmNlLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImhvc3RJUCI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmhvc3RJUC5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJob3N0TmFtZSI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmhvc3ROYW1lLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInR1bmVyIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MudHVuZXIuZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAidXBkYXRlIjoKICAgICAgICAgICAgICAgIHRleHQgPSAie3suc2V0dGluZ3MudXBkYXRlLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImNsZWFyWE1MVFZDYWNoZSI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmNsZWFyWE1MVFZDYWNoZS5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJhcGkiOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy5hcGkuZGVzY3JpcHRpb259fSI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiZGVmYXVsdE1pc3NpbmdFUEciOgogICAgICAgICAgICAgICAgdGV4dCA9ICJ7ey5zZXR0aW5ncy5kZWZhdWx0TWlzc2luZ0VQRy5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJlbmFibGVNYXBwZWRDaGFubmVscyI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmVuYWJsZU1hcHBlZENoYW5uZWxzLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImZpbGVzLnVwZGF0ZSI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmZpbGVzVXBkYXRlLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImNhY2hlLmltYWdlcyI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLmNhY2hlSW1hZ2VzLmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgInhlcGcucmVwbGFjZS5taXNzaW5nLmltYWdlcyI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLnJlcGxhY2VFbXB0eUltYWdlcy5kZXNjcmlwdGlvbn19IjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ1ZHB4eSI6CiAgICAgICAgICAgICAgICB0ZXh0ID0gInt7LnNldHRpbmdzLnVkcHh5LmRlc2NyaXB0aW9ufX0iOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICB0ZXh0ID0gIiI7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdmFyIHRkTGVmdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlREIik7CiAgICAgICAgdGRMZWZ0LmlubmVySFRNTCA9ICIiOwogICAgICAgIHZhciB0ZFJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiVEQiKTsKICAgICAgICB2YXIgcHJlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiUFJFIik7CiAgICAgICAgcHJlLmlubmVySFRNTCA9IHRleHQ7CiAgICAgICAgdGRSaWdodC5hcHBlbmRDaGlsZChwcmUpOwogICAgICAgIGRlc2NyaXB0aW9uLmFwcGVuZENoaWxkKHRkTGVmdCk7CiAgICAgICAgZGVzY3JpcHRpb24uYXBwZW5kQ2hpbGQodGRSaWdodCk7CiAgICAgICAgcmV0dXJuIGRlc2NyaXB0aW9uOwogICAgfQp9CmNsYXNzIFNldHRpbmdzQ2F0ZWdvcnlJdGVtIGV4dGVuZHMgU2V0dGluZ3NDYXRlZ29yeSB7CiAgICBjb25zdHJ1Y3RvcihoZWFkbGluZSwgc2V0dGluZ3NLZXlzKSB7CiAgICAgICAgc3VwZXIoKTsKICAgICAgICB0aGlzLmhlYWRsaW5lID0gaGVhZGxpbmU7CiAgICAgICAgdGhpcy5zZXR0aW5nc0tleXMgPSBzZXR0aW5nc0tleXM7CiAgICB9CiAgICBjcmVhdGVDYXRlZ29yeSgpIHsKICAgICAgICB2YXIgaGVhZGxpbmUgPSB0aGlzLmNyZWF0ZUNhdGVnb3J5SGVhZGxpbmUodGhpcy5oZWFkbGluZSk7CiAgICAgICAgdmFyIHNldHRpbmdzS2V5cyA9IHRoaXMuc2V0dGluZ3NLZXlzOwogICAgICAgIHZhciBkb2MgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLkRvY3VtZW50SUQpOwogICAgICAgIGRvYy5hcHBlbmRDaGlsZChoZWFkbGluZSk7CiAgICAgICAgLy8gQ3JlYXRlIGEgdGFibGUgZm9yIHRoZSBjYXRlZ29yeQogICAgICAgIHZhciB0YWJsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIlRBQkxFIik7CiAgICAgICAgdmFyIGtleXMgPSBzZXR0aW5nc0tleXMuc3BsaXQoIiwiKTsKICAgICAgICBrZXlzLmZvckVhY2goc2V0dGluZ3NLZXkgPT4gewogICAgICAgICAgICBzd2l0Y2ggKHNldHRpbmdzS2V5KSB7CiAgICAgICAgICAgICAgICBjYXNlICJhdXRoZW50aWNhdGlvbi5wbXMiOgogICAgICAgICAgICAgICAgY2FzZSAiYXV0aGVudGljYXRpb24ubTN1IjoKICAgICAgICAgICAgICAgIGNhc2UgImF1dGhlbnRpY2F0aW9uLnhtbCI6CiAgICAgICAgICAgICAgICBjYXNlICJhdXRoZW50aWNhdGlvbi5hcGkiOgogICAgICAgICAgICAgICAgICAgIGlmIChTRVJWRVJbInNldHRpbmdzIl1bImF1dGhlbnRpY2F0aW9uLndlYiJdID09IGZhbHNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW0gPSB0aGlzLmNyZWF0ZVNldHRpbmdzKHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgICAgICB2YXIgZGVzY3JpcHRpb24gPSB0aGlzLmNyZWF0ZURlc2NyaXB0aW9uKHNldHRpbmdzS2V5KTsKICAgICAgICAgICAgICAgICAgICB0YWJsZS5hcHBlbmRDaGlsZChpdGVtKTsKICAgICAgICAgICAgICAgICAgICB0YWJsZS5hcHBlbmRDaGlsZChkZXNjcmlwdGlvbik7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgICBkb2MuYXBwZW5kQ2hpbGQodGFibGUpOwogICAgICAgIGRvYy5hcHBlbmRDaGlsZCh0aGlzLmNyZWF0ZUhSKCkpOwogICAgfQp9CmZ1bmN0aW9uIHNob3dTZXR0aW5ncygpIHsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3NDYXRlZ29yeS5sZW5ndGg7IGkrKykgewogICAgICAgIHNldHRpbmdzQ2F0ZWdvcnlbaV0uY3JlYXRlQ2F0ZWdvcnkoKTsKICAgIH0KfQpmdW5jdGlvbiBzYXZlU2V0dGluZ3MoKSB7CiAgICB2YXIgY21kID0gInNhdmVTZXR0aW5ncyI7CiAgICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoImNvbnRlbnRfc2V0dGluZ3MiKTsKICAgIHZhciBzZXR0aW5ncyA9IGRpdi5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCJjaGFuZ2VkIik7CiAgICB2YXIgbmV3U2V0dGluZ3MgPSBuZXcgT2JqZWN0KCk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNldHRpbmdzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdmFyIG5hbWU7CiAgICAgICAgdmFyIHZhbHVlOwogICAgICAgIHN3aXRjaCAoc2V0dGluZ3NbaV0udGFnTmFtZSkgewogICAgICAgICAgICBjYXNlICJJTlBVVCI6CiAgICAgICAgICAgICAgICBzd2l0Y2ggKHNldHRpbmdzW2ldLnR5cGUpIHsKICAgICAgICAgICAgICAgICAgICBjYXNlICJjaGVja2JveCI6CiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSBzZXR0aW5nc1tpXS5uYW1lOwogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHNldHRpbmdzW2ldLmNoZWNrZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgIG5ld1NldHRpbmdzW25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIGNhc2UgInRleHQiOgogICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gc2V0dGluZ3NbaV0ubmFtZTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBzZXR0aW5nc1tpXS52YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChuYW1lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJ1cGRhdGUiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc3BsaXQoIiwiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLmZpbHRlcihmdW5jdGlvbiAoZSkgeyByZXR1cm4gZTsgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJidWZmZXIudGltZW91dCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBwYXJzZUZsb2F0KHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBuZXdTZXR0aW5nc1tuYW1lXSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJTRUxFQ1QiOgogICAgICAgICAgICAgICAgbmFtZSA9IHNldHRpbmdzW2ldLm5hbWU7CiAgICAgICAgICAgICAgICB2YWx1ZSA9IHNldHRpbmdzW2ldLnZhbHVlOwogICAgICAgICAgICAgICAgLy8gSWYgdGhlIHZhbHVlIGlzIGEgbnVtYmVyLCBzdG9yZSBpdCBhcyBhIG51bWJlcgogICAgICAgICAgICAgICAgaWYgKGlzTmFOKHZhbHVlKSkgewogICAgICAgICAgICAgICAgICAgIG5ld1NldHRpbmdzW25hbWVdID0gdmFsdWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgICBuZXdTZXR0aW5nc1tuYW1lXSA9IHBhcnNlSW50KHZhbHVlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0KICAgIHZhciBkYXRhID0gbmV3IE9iamVjdCgpOwogICAgZGF0YVsic2V0dGluZ3MiXSA9IG5ld1NldHRpbmdzOwogICAgdmFyIHNlcnZlciA9IG5ldyBTZXJ2ZXIoY21kKTsKICAgIHNlcnZlci5yZXF1ZXN0KGRhdGEpOwp9Cg==" + webUI["html/lang/en.json"] = "ewogICJtYWluTWVudSI6IHsKICAgICJpdGVtIjogewogICAgICAicGxheWxpc3QiOiAiUGxheWxpc3QiLAogICAgICAicG1zSUQiOiAiUE1TIElEIiwKICAgICAgImZpbHRlciI6ICJGaWx0ZXIiLAogICAgICAieG1sdHYiOiAiWE1MVFYiLAogICAgICAibWFwcGluZyI6ICJNYXBwaW5nIiwKICAgICAgInVzZXJzIjogIlVzZXJzIiwKICAgICAgInNldHRpbmdzIjogIlNldHRpbmdzIiwKICAgICAgImxvZyI6ICJMb2ciLAogICAgICAibG9nb3V0IjogIkxvZ291dCIKICAgIH0sCiAgICAiaGVhZGxpbmUiOiB7CiAgICAgICJwbGF5bGlzdCI6ICJMb2NhbCBvciByZW1vdGUgcGxheWxpc3RzIiwKICAgICAgImZpbHRlciI6ICJGaWx0ZXIgcGxheWxpc3QiLAogICAgICAieG1sdHYiOiAiTG9jYWwgb3IgcmVtb3RlIFhNTFRWIGZpbGVzIiwKICAgICAgIm1hcHBpbmciOiAiTWFwIHBsYXlsaXN0IGNoYW5uZWxzIHRvIEVQRyBjaGFubmVscyIsCiAgICAgICJ1c2VycyI6ICJVc2VyIG1hbmFnZW1lbnQiLAogICAgICAic2V0dGluZ3MiOiAiU2V0dGluZ3MiLAogICAgICAibG9nIjogIkxvZyIsCiAgICAgICJsb2dvdXQiOiAiTG9nb3V0IgogICAgfQogIH0sCiAgImNvbmZpcm0iOiB7CiAgICAicmVzdG9yZSI6ICJBbGwgZGF0YSB3aWxsIGJlIHJlcGxhY2VkIHdpdGggdGhvc2UgZnJvbSB0aGUgYmFja3VwLiBTaG91bGQgdGhlIGZpbGVzIGJlIHJlc3RvcmVkPyIKICB9LAogICJhbGVydCI6IHsKICAgICJmaWxlTG9hZGluZ0Vycm9yIjogIkZpbGUgY291bGRuJ3QgYmUgbG9hZGVkIiwKICAgICJpbnZhbGlkQ2hhbm5lbE51bWJlciI6ICJJbnZhbGlkIGNoYW5uZWwgbnVtYmVyIiwKICAgICJtaXNzaW5nSW5wdXQiOiAiTWlzc2luZyBpbnB1dCIKICB9LAogICJidXR0b24iOiB7CiAgICAiYmFjayI6ICJCYWNrIiwKICAgICJiYWNrdXAiOiAiQmFja3VwIiwKICAgICJidWxrRWRpdCI6ICJCdWxrIEVkaXQiLAogICAgImNhbmNlbCI6ICJDYW5jZWwiLAogICAgImRlbGV0ZSI6ICJEZWxldGUiLAogICAgImRvbmUiOiAiRG9uZSIsCiAgICAibG9naW4iOiAiTG9naW4iLAogICAgIm5ldyI6ICJOZXciLAogICAgIm5leHQiOiAiTmV4dCIsCiAgICAicmVzdG9yZSI6ICJSZXN0b3JlIiwKICAgICJzYXZlIjogIlNhdmUiLAogICAgInNlYXJjaCI6ICJTZWFyY2giLAogICAgInVwZGF0ZSI6ICJVcGRhdGUiLAogICAgImNyYWV0ZUFjY291bnQiOiAiQ3JlYXRlIEFjY291bnQiLAogICAgInJlc2V0TG9ncyI6ICJSZXNldCBMb2dzIiwKICAgICJ1cGxvYWRMb2dvIjogIlVwbG9hZCBMb2dvIgogIH0sCiAgImZpbHRlciI6IHsKICAgICJ0YWJsZSI6IHsKICAgICAgInN0YXJ0aW5nQ2hhbm5lbCI6ICJTdGFydGluZyBDaC4gTm8uIiwKICAgICAgIm5hbWUiOiAiRmlsdGVyIE5hbWUiLAogICAgICAidHlwZSI6ICJGaWx0ZXIgVHlwZSIsCiAgICAgICJmaWx0ZXIiOiAiRmlsdGVyIgogICAgfSwKICAgICJjdXN0b20iOiAiQ3VzdG9tIiwKICAgICJncm91cCI6ICJNM1UgR3JvdXAiLAogICAgIm5hbWUiOiB7CiAgICAgICJ0aXRsZSI6ICJGaWx0ZXIgTmFtZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJGaWx0ZXIgbmFtZSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImRlc2NyaXB0aW9uIjogewogICAgICAidGl0bGUiOiAiRGVzY3JpcHRpb24iLAogICAgICAicGxhY2Vob2xkZXIiOiAiRGVzY3JpcHRpb24iLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ0eXBlIjogewogICAgICAidGl0bGUiOiAiVHlwZSIsCiAgICAgICJncm91cFRpdGxlIjogIkdyb3VwIFRpdGxlIiwKICAgICAgImN1c3RvbUZpbHRlciI6ICJDdXN0b20gRmlsdGVyIgogICAgfSwKICAgICJjYXNlU2Vuc2l0aXZlIjogewogICAgICAidGl0bGUiOiAiQ2FzZSBTZW5zaXRpdmUiLAogICAgICAicGxhY2Vob2xkZXIiOiAiIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0sCiAgICAiZmlsdGVyUnVsZSI6IHsKICAgICAgInRpdGxlIjogIkZpbHRlciBSdWxlIiwKICAgICAgInBsYWNlaG9sZGVyIjogIlNwb3J0IHtIRH0gIXtFUyxJVH0iLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJmaWx0ZXJHcm91cCI6IHsKICAgICAgInRpdGxlIjogIkdyb3VwIFRpdGxlIiwKICAgICAgInBsYWNlaG9sZGVyIjogIiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJTZWxlY3QgYSBNM1UgZ3JvdXAuIChDb3VudGVyKTxicj5DaGFuZ2luZyB0aGUgZ3JvdXAgdGl0bGUgaW4gdGhlIE0zVSBpbnZhbGlkYXRlcyB0aGUgZmlsdGVyLiIKICAgIH0sCiAgICAiaW5jbHVkZSI6IHsKICAgICAgInRpdGxlIjogIkluY2x1ZGUiLAogICAgICAicGxhY2Vob2xkZXIiOiAiRkhELFVIRCIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJDaGFubmVsIG5hbWUgbXVzdCBpbmNsdWRlLjxicj4oQ29tbWEgc2VwYXJhdGVkKSBDb21tYSBtZWFucyBvciIKICAgIH0sCiAgICAiZXhjbHVkZSI6IHsKICAgICAgInRpdGxlIjogIkV4Y2x1ZGUiLAogICAgICAicGxhY2Vob2xkZXIiOiAiRVMsSVQiLAogICAgICAiZGVzY3JpcHRpb24iOiAiQ2hhbm5lbCBuYW1lIG11c3Qgbm90IGNvbnRhaW4uPGJyPihDb21tYSBzZXBhcmF0ZWQpIENvbW1hIG1lYW5zIG9yIgogICAgfSwKICAgICJwcmVzZXJ2ZU1hcHBpbmciOiB7CiAgICAgICJ0aXRsZSI6ICJQcmVzZXJ2ZSBFeGlzdGluZyBNM1U8YnI+Q2hhbm5lbCBOdW1iZXJzIiwKICAgICAgInBhbGNlaG9sZGVyIjogIiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJQcmVzZXJ2ZSBleGlzdGluZyBNM1UgcGxheWxpc3QgY2hhbm5lbCBudW1iZXJzPyIKICAgIH0sCiAgICAic3RhcnRpbmdDaGFubmVsIjogewogICAgICAidGl0bGUiOiAiU3RhcnRpbmcgQ2hhbm5lbCBOdW1iZXIiLAogICAgICAicGxhY2Vob2xkZXIiOiAiIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0KICB9LAogICJwbGF5bGlzdCI6IHsKICAgICJ0YWJsZSI6IHsKICAgICAgInBsYXlsaXN0IjogIlBsYXlsaXN0IiwKICAgICAgInR1bmVyIjogIlR1bmVyIiwKICAgICAgImxhc3RVcGRhdGUiOiAiTGFzdCBVcGRhdGUiLAogICAgICAiYXZhaWxhYmlsaXR5IjogIkF2YWlsYWJpbGl0eSIsCiAgICAgICJ0eXBlIjogIlR5cGUiLAogICAgICAic3RyZWFtcyI6ICJTdHJlYW1zIiwKICAgICAgImdyb3VwVGl0bGUiOiAiZ3JvdXAtdGl0bGUiLAogICAgICAidHZnSUQiOiAidHZnLWlkIiwKICAgICAgInVuaXF1ZUlEIjogIlVuaXF1ZSBJRCIKICAgIH0sCiAgICAicGxheWxpc3RUeXBlIjogewogICAgICAidGl0bGUiOiAiUGxheWxpc3QgdHlwZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ0eXBlIjogewogICAgICAidGl0bGUiOiAiVHlwZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJuYW1lIjogewogICAgICAidGl0bGUiOiAiTmFtZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJQbGF5bGlzdCBuYW1lIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0sCiAgICAiZGVzY3JpcHRpb24iOiB7CiAgICAgICJ0aXRsZSI6ICJEZXNjcmlwdGlvbiIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJEZXNjcmlwdGlvbiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImZpbGVNM1UiOiB7CiAgICAgICJ0aXRsZSI6ICJNM1UgRmlsZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJGaWxlIHBhdGggb3IgVVJMIG9mIHRoZSBNM1UiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJmaWxlSERIUiI6IHsKICAgICAgInRpdGxlIjogIkhESG9tZVJ1biBJUCIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJJUCBhZGRyZXNzIGFuZCBwb3J0ICgxOTIuMTY4LjEuMTA6NTAwNCkiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ0dW5lciI6IHsKICAgICAgInRpdGxlIjogIlR1bmVyIC8gU3RyZWFtcyIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiTnVtYmVyIG9mIHBhcmFsbGVsIGNvbm5lY3Rpb25zIHRoYXQgY2FuIGJlIGVzdGFibGlzaGVkIHRvIHRoZSBwcm92aWRlci4gPGJyPk9ubHkgYXZhaWxhYmxlIHdpdGggYWN0aXZhdGVkIGJ1ZmZlci48YnI+TmV3IHNldHRpbmdzIHdpbGwgb25seSBiZSBhcHBsaWVkIGFmdGVyIHF1aXR0aW5nIGFsbCBzdHJlYW1zLiIKICAgIH0KICB9LAogICJ4bWx0diI6IHsKICAgICJ0YWJsZSI6IHsKICAgICAgImd1aWRlIjogIkd1aWRlIiwKICAgICAgImxhc3RVcGRhdGUiOiAiTGFzdCBVcGRhdGUiLAogICAgICAiYXZhaWxhYmlsaXR5IjogIkF2YWlsYWJpbGl0eSIsCiAgICAgICJjaGFubmVscyI6ICJDaGFubmVscyIsCiAgICAgICJwcm9ncmFtcyI6ICJQcm9ncmFtcyIKICAgIH0sCiAgICAibmFtZSI6IHsKICAgICAgInRpdGxlIjogIk5hbWUiLAogICAgICAicGxhY2Vob2xkZXIiOiAiR3VpZGUgbmFtZSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImRlc2NyaXB0aW9uIjogewogICAgICAidGl0bGUiOiAiRGVzY3JpcHRpb24iLAogICAgICAicGxhY2Vob2xkZXIiOiAiRGVzY3JpcHRpb24iLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJmaWxlWE1MVFYiOiB7CiAgICAgICJ0aXRsZSI6ICJYTUxUViBGaWxlIiwKICAgICAgInBsYWNlaG9sZGVyIjogIkZpbGUgcGF0aCBvciBVUkwgb2YgdGhlIFhNTFRWIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0KICB9LAogICJtYXBwaW5nIjogewogICAgInRhYmxlIjogewogICAgICAiY2hObyI6ICJDaC4gTm8uIiwKICAgICAgImxvZ28iOiAiTG9nbyIsCiAgICAgICJjaGFubmVsTmFtZSI6ICJDaGFubmVsIE5hbWUiLAogICAgICAidXBkYXRlQ2hhbm5lbE5hbWVSZWdleCI6ICJVcGQuIFJ4LiIsCiAgICAgICJwbGF5bGlzdCI6ICJQbGF5bGlzdCIsCiAgICAgICJncm91cFRpdGxlIjogIkdyb3VwIFRpdGxlIiwKICAgICAgInhtbHR2RmlsZSI6ICJYTUxUViBGaWxlIiwKICAgICAgInhtbHR2SUQiOiAiWE1MVFYgSUQiLAogICAgICAidGltZXNoaWZ0IjogIlRpbWVzaGlmdCIKICAgIH0sCiAgICAiYWN0aXZlIjogewogICAgICAidGl0bGUiOiAiQWN0aXZlIiwKICAgICAgInBsYWNlaG9sZGVyIjogIiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImNoYW5uZWxOYW1lIjogewogICAgICAidGl0bGUiOiAiQ2hhbm5lbCBOYW1lIiwKICAgICAgInBsYWNlaG9sZGVyIjogIiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImRlc2NyaXB0aW9uIjogewogICAgICAidGl0bGUiOiAiQ2hhbm5lbCBEZXNjcmlwdGlvbiIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJVc2VkIGJ5IHRoZSBEdW1teSBhcyBhbiBYTUwgZGVzY3JpcHRpb24iLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ1cGRhdGVDaGFubmVsTmFtZSI6IHsKICAgICAgInRpdGxlIjogIlVwZGF0ZSBDaGFubmVsIE5hbWUiLAogICAgICAicGxhY2Vob2xkZXIiOiAiIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0sCiAgICAidXBkYXRlQ2hhbm5lbE5hbWVSZWdleCI6IHsKICAgICAgInRpdGxlIjogIkNoYW5uZWwgbmFtZSB1cGRhdGUgcmVnZXgiLAogICAgICAicGxhY2Vob2xkZXIiOiAiRm9yIGV4YW1wbGUgXlBQVlsgXFxcXC1fXT8xLioiLAogICAgICAiZGVzY3JpcHRpb24iOiAiT24gdXBkYXRlLCBpZiBhbnkgbmV3IGNoYW5uZWwgbmFtZSBtYXRjaGVzIHRoaXMgcmVnZXgsIHJlbmFtZSBjdXJyZW50IGNoYW5uZWwgdG8gdGhlIGZpcnN0IG1hdGNoaW5nIG5hbWUiCiAgICB9LAogICAgInVwZGF0ZUNoYW5uZWxOYW1lQnlHcm91cFJlZ2V4IjogewogICAgICAidGl0bGUiOiAiT25seSBieSBncm91cCByZWdleCIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiUmVuYW1lIHRoaXMgY2hhbm5lbCBvbmx5IGlmIGN1cnJlbnQgdXNlci1kZWZpbmVkIGdyb3VwIG1hdGNoZXMgdGhpcyByZWdleCIKICAgIH0sCiAgICAidXBkYXRlQ2hhbm5lbEdyb3VwIjogewogICAgICAidGl0bGUiOiAiVXBkYXRlIENoYW5uZWwgR3JvdXAiLAogICAgICAicGxhY2Vob2xkZXIiOiAiIiwKICAgICAgImRlc2NyaXB0aW9uIjogIklmIGNoZWNrZWQsIHVzZSBncm91cCBmcm9tIHRoZSBkYXRhYmFzZSIKICAgIH0sCiAgICAiY2hhbm5lbExvZ28iOiB7CiAgICAgICJ0aXRsZSI6ICJMb2dvIFVSTCIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ1cGRhdGVDaGFubmVsTG9nbyI6IHsKICAgICAgInRpdGxlIjogIlVzZSBsb2dvIGZyb20gTTNVIiwKICAgICAgInBsYWNlaG9sZGVyIjogIiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImVwZ0NhdGVnb3J5IjogewogICAgICAidGl0bGUiOiAiRVBHIENhdGVnb3J5IiwKICAgICAgInBsYWNlaG9sZGVyIjogIiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgIm0zdUdyb3VwVGl0bGUiOiB7CiAgICAgICJ0aXRsZSI6ICJHcm91cCBUaXRsZSAoeHRldmUubTN1KSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ4bWx0dkZpbGUiOiB7CiAgICAgICJ0aXRsZSI6ICJYTUxUViBGaWxlIiwKICAgICAgInBsYWNlaG9sZGVyIjogIiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgInhtbHR2Q2hhbm5lbCI6IHsKICAgICAgInRpdGxlIjogIlhNTFRWIENoYW5uZWwiLAogICAgICAicGxhY2Vob2xkZXIiOiAiIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0sCiAgICAidGltZXNoaWZ0IjogewogICAgICAidGl0bGUiOiAiVGltZXNoaWZ0IiwKICAgICAgInBsYWNlaG9sZGVyIjogIjAiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfQogIH0sCiAgInVzZXJzIjogewogICAgInRhYmxlIjogewogICAgICAidXNlcm5hbWUiOiAiVXNlcm5hbWUiLAogICAgICAicGFzc3dvcmQiOiAiUGFzc3dvcmQiLAogICAgICAid2ViIjogIldFQiIsCiAgICAgICJwbXMiOiAiUE1TIiwKICAgICAgIm0zdSI6ICJNM1UiLAogICAgICAieG1sIjogIlhNTCIsCiAgICAgICJhcGkiOiAiQVBJIgogICAgfSwKICAgICJ1c2VybmFtZSI6IHsKICAgICAgInRpdGxlIjogIlVzZXJuYW1lIiwKICAgICAgInBsYWNlaG9sZGVyIjogIlVzZXJuYW1lIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0sCiAgICAicGFzc3dvcmQiOiB7CiAgICAgICJ0aXRsZSI6ICJQYXNzd29yZCIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJQYXNzd29yZCIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImNvbmZpcm0iOiB7CiAgICAgICJ0aXRsZSI6ICJDb25maXJtIiwKICAgICAgInBsYWNlaG9sZGVyIjogIlBhc3N3b3JkIGNvbmZpcm0iLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ3ZWIiOiB7CiAgICAgICJ0aXRsZSI6ICJXZWIgQWNjZXNzIiwKICAgICAgInBsYWNlaG9sZGVyIjogIiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgInBtcyI6IHsKICAgICAgInRpdGxlIjogIlBNUyBBY2Nlc3MiLAogICAgICAicGxhY2Vob2xkZXIiOiAiIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0sCiAgICAibTN1IjogewogICAgICAidGl0bGUiOiAiTTNVIEFjY2VzcyIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIiLAogICAgICAiZGVzY3JpcHRpb24iOiAiIgogICAgfSwKICAgICJ4bWwiOiB7CiAgICAgICJ0aXRsZSI6ICJYTUwgQWNjZXNzIiwKICAgICAgInBsYWNlaG9sZGVyIjogIiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICIiCiAgICB9LAogICAgImFwaSI6IHsKICAgICAgInRpdGxlIjogIkFQSSBBY2Nlc3MiLAogICAgICAicGxhY2Vob2xkZXIiOiAiIiwKICAgICAgImRlc2NyaXB0aW9uIjogIiIKICAgIH0KICB9LAogICJzZXR0aW5ncyI6IHsKICAgICJjYXRlZ29yeSI6IHsKICAgICAgImdlbmVyYWwiOiAiR2VuZXJhbCIsCiAgICAgICJtYXBwaW5nIjogIk1hcHBpbmciLAogICAgICAiZmlsZXMiOiAiRmlsZXMiLAogICAgICAic3RyZWFtaW5nIjogIlN0cmVhbWluZyIsCiAgICAgICJiYWNrdXAiOiAiQmFja3VwIiwKICAgICAgImF1dGhlbnRpY2F0aW9uIjogIkF1dGhlbnRpY2F0aW9uIgogICAgfSwKICAgICJ1cGRhdGUiOiB7CiAgICAgICJ0aXRsZSI6ICJTY2hlZHVsZSBmb3IgdXBkYXRpbmcgKFBsYXlsaXN0LCBYTUxUViwgQmFja3VwKSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIwMDAwLDEwMDAsMjAwMCIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJUaW1lIGluIDI0IGhvdXIgZm9ybWF0ICgwODAwID0gODowMCBhbSkuIE1vcmUgdGltZXMgY2FuIGJlIGVudGVyZWQgY29tbWEgc2VwYXJhdGVkLiBMZWF2ZSB0aGlzIGZpZWxkIGVtcHR5IGlmIG5vIHVwZGF0ZXMgYXJlIHRvIGJlIGNhcnJpZWQgb3V0LiIKICAgIH0sCiAgICAiYXBpIjogewogICAgICAidGl0bGUiOiAiQVBJIEludGVyZmFjZSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJWaWEgQVBJIGludGVyZmFjZSBpdCBpcyBwb3NzaWJsZSB0byBzZW5kIGNvbW1hbmRzIHRvIHhUZVZlLiBBUEkgZG9jdW1lbnRhdGlvbiBpcyA8YSBocmVmPSdodHRwczovL2dpdGh1Yi5jb20veHRldmUtcHJvamVjdC94VGVWZS1Eb2N1bWVudGF0aW9uL2Jsb2IvbWFzdGVyL2VuL2NvbmZpZ3VyYXRpb24ubWQjYXBpJz5oZXJlPC9hPiIKICAgIH0sCiAgICAiY2xlYXJYTUxUVkNhY2hlIjogewogICAgICAidGl0bGUiOiAiQ2xlYXIgWE1MVFYgY2FjaGUiLAogICAgICAiZGVzY3JpcHRpb24iOiAiSWYgY2hlY2tlZCwgZG8gbm90IGtlZXAgWE1MVFYgY2FjaGUgaW4gbWVtb3J5Ljxicj5TaWduaWZpY2FsbHkgcmVkdWNlcyBSQU0gdXNhZ2UgaW4gaWRsZSBtb2RlLDxicj5idXQgc2lnbmlmaWNhbGx5IHNsb3dpbmcgZG93biBldmVyeSBzdWJzZXF1ZW50IHVwZGF0ZSBpbiBYRVBHIGRhdGFiYXNlLiIKICAgIH0sCiAgICAiZGVmYXVsdE1pc3NpbmdFUEciOiB7CiAgICAgICJ0aXRsZSI6ICJGaWxsIE1pc3NpbmcgRVBHIERhdGEiLAogICAgICAiZGVzY3JpcHRpb24iOiAiV2hlbiB0aGVyZSBpcyBubyBtYXRjaGluZyBFUEcgZGF0YSBmb3IgY2hhbm5lbCwgPGJyPmF1dG9maWxsIHdpdGggeFRlVmUgZHVtbXkgRVBHIGRhdGE/IgogICAgfSwKICAgICJlbmFibGVNYXBwZWRDaGFubmVscyI6IHsKICAgICAgInRpdGxlIjogIkVuYWJsZSBtYXBwZWQgY2hhbm5lbHMiLAogICAgICAiZGVzY3JpcHRpb24iOiAiQXV0b21hdGljYWxseSBlbmFibGUgY2hhbm5lbHMgd2l0aCBhc3NpZ25lZCBFUEcgZGF0YSIKICAgIH0sCiAgICAiZGlzYWxsb3dVUkxEdXBsaWNhdGVzIjogewogICAgICAidGl0bGUiOiAiRGlzYWxsb3cgVVJMIGR1cGxpY2F0ZXMiLAogICAgICAiZGVzY3JpcHRpb24iOiAiSWYgY2hlY2tlZCwgZG8gbm90IGFkZCBhIG5ldyBjaGFubmVsIGZyb20gcGxheWxpc3QgaWYgY2hhbm5lbCB3aXRoIHN1Y2ggVVJMIGFscmVhZHkgZXhpc3RzIgogICAgfSwKICAgICJlcGdTb3VyY2UiOiB7CiAgICAgICJ0aXRsZSI6ICJFUEcgU291cmNlIiwKICAgICAgImRlc2NyaXB0aW9uIjogIlBNUzo8YnI+LSBVc2UgRVBHIGRhdGEgZnJvbSBQbGV4IG9yIEVtYnkgPGJyPjxicj5YRVBHOjxicj4tIFVzZSBvZiBvbmUgb3IgbW9yZSBYTUxUViBmaWxlczxicj4tIENoYW5uZWwgbWFuYWdlbWVudDxicj4tIE0zVSAvIFhNTFRWIGV4cG9ydCAoSFRUUCBsaW5rIGZvciBJUFRWIGFwcHMpIgogICAgfSwKICAgICJ0dW5lciI6IHsKICAgICAgInRpdGxlIjogIk51bWJlciBvZiBUdW5lcnMiLAogICAgICAiZGVzY3JpcHRpb24iOiAiTnVtYmVyIG9mIHBhcmFsbGVsIGNvbm5lY3Rpb25zIHRoYXQgY2FuIGJlIGVzdGFibGlzaGVkIHRvIHRoZSBwcm92aWRlci48YnI+QXZhaWxhYmxlIGZvcjogUGxleCwgRW1ieSAoSERIUiksIE0zVSAod2l0aCBhY3RpdmUgYnVmZmVyKS48YnI+QWZ0ZXIgYSBjaGFuZ2UsIHhUZVZlIG11c3QgYmUgZGVsZXRlIGluIHRoZSBQbGV4IC8gRW1ieSBEVlIgc2V0dGluZ3MgYW5kIHNldCB1cCBhZ2Fpbi4iCiAgICB9LAogICAgImhvc3RJUCI6IHsKICAgICAgInRpdGxlIjogIkhvc3QgSVAiLAogICAgICAiZGVzY3JpcHRpb24iOiAiSVAgYWRkcmVzcyB4VGVWZSB3aWxsIHVzZSB0byBmb3JtIE0zVSBhbmQgWE1MVFYgZmlsZXMiCiAgICB9LAogICAgImhvc3ROYW1lIjogewogICAgICAidGl0bGUiOiAiSG9zdCBOYW1lIE92ZXJyaWRlIiwKICAgICAgImRlc2NyaXB0aW9uIjogIkhvc3RuYW1lIHhUZVZlIHdpbGwgdXNlIHRvIGZvcm0gTTNVIGFuZCBYTUxUViBmaWxlcy4gVGhpcyB3aWxsIG92ZXJyaWRlIEhvc3QgSVAgaWYgc2V0IgogICAgfSwKICAgICJ0bHNNb2RlIjogewogICAgICAidGl0bGUiOiAiVExTIChIVFRQUykgbW9kZSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJDaGFuZ2VzIHdlYiBzZXJ2ZXIgcHJvdG9jb2wgdG8gSFRUUFMuPGJyPkZvciBkZXRhaWxzLCBzZWUgPGE+aHR0cHM6Ly9naXRodWIuY29tL1NlbmV4Q3JlbnNoYXcveFRlVmUjdGxzLW1vZGU8L2E+IgogICAgfSwKICAgICJmaWxlc1VwZGF0ZSI6IHsKICAgICAgInRpdGxlIjogIlVwZGF0ZXMgYWxsIGZpbGVzIGF0IHN0YXJ0dXAiLAogICAgICAiZGVzY3JpcHRpb24iOiAiVXBkYXRlcyBhbGwgcGxheWxpc3RzLCB0dW5lciBhbmQgWE1MVFYgZmlsZXMgYXQgc3RhcnR1cC4iCiAgICB9LAogICAgImNhY2hlSW1hZ2VzIjogewogICAgICAidGl0bGUiOiAiSW1hZ2UgQ2FjaGluZyIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJBbGwgaW1hZ2VzIGZyb20gdGhlIFhNTFRWIGZpbGUgYXJlIGNhY2hlZCwgYWxsb3dpbmcgZmFzdGVyIHJlbmRlcmluZyBvZiB0aGUgZ3JpZCBpbiB0aGUgY2xpZW50Ljxicj5Eb3dubG9hZGluZyB0aGUgaW1hZ2VzIG1heSB0YWtlIGEgd2hpbGUgYW5kIHdpbGwgYmUgZG9uZSBpbiB0aGUgYmFja2dyb3VuZC4iCiAgICB9LAogICAgInJlcGxhY2VFbXB0eUltYWdlcyI6IHsKICAgICAgInRpdGxlIjogIlJlcGxhY2UgbWlzc2luZyBwcm9ncmFtIGltYWdlcyIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJJZiB0aGUgcG9zdGVyIGluIHRoZSBYTUxUViBwcm9ncmFtIGlzIG1pc3NpbmcsIHRoZSBjaGFubmVsIGxvZ28gd2lsbCBiZSB1c2VkLiIKICAgIH0sCiAgICAieHRldmVBdXRvVXBkYXRlIjogewogICAgICAidGl0bGUiOiAiQXV0b21hdGljIHVwZGF0ZSBvZiB4VGVWZSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJJZiBhIG5ldyB2ZXJzaW9uIG9mIHhUZVZlIGlzIGF2YWlsYWJsZSwgaXQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGluc3RhbGxlZC4gVGhlIHVwZGF0ZXMgYXJlIGRvd25sb2FkZWQgZnJvbSBHaXRIdWIuIgogICAgfSwKICAgICJzdHJlYW1CdWZmZXJpbmciOiB7CiAgICAgICJ0aXRsZSI6ICJTdHJlYW0gQnVmZmVyIiwKICAgICAgImRlc2NyaXB0aW9uIjogIkZ1bmN0aW9ucyBvZiB0aGUgYnVmZmVyOjxicj4tIFRoZSBzdHJlYW0gaXMgcGFzc2VkIGZyb20geFRlVmUsIEZGbXBlZyBvciBWTEMgdG8gUGxleCwgRW1ieSBvciBNM1UgUGxheWVyPGJyPi0gU21hbGwgamVya2luZyBvZiB0aGUgc3RyZWFtcyBjYW4gYmUgY29tcGVuc2F0ZWQ8YnI+LSBITFMgLyBNM1U4IHN1cHBvcnQ8YnI+LSBSVFAgLyBSVFBTIHN1cHBvcnQgKG9ubHkgRkZtcGVnIG9yIFZMQyk8YnI+LSBSZS1zdHJlYW1pbmc8YnI+LSBTZXBhcmF0ZSB0dW5lciBsaW1pdCBmb3IgZWFjaCBwbGF5bGlzdCIsCiAgICAgICJpbmZvX2ZhbHNlIjogIk5vIEJ1ZmZlciAoQ2xpZW50IGNvbm5lY3RzIHRvIHRoZSBzdHJlYW1pbmcgc2VydmVyKSIsCiAgICAgICJpbmZvX3h0ZXZlIjogInhUZVZlIGNvbm5lY3RzIHRvIHRoZSBzdHJlYW1pbmcgc2VydmVyIiwKICAgICAgImluZm9fZmZtcGVnIjogIkZGbXBlZyBjb25uZWN0cyB0byB0aGUgc3RyZWFtaW5nIHNlcnZlciIsCiAgICAgICJpbmZvX3ZsYyI6ICJWTEMgY29ubmVjdHMgdG8gdGhlIHN0cmVhbWluZyBzZXJ2ZXIiCiAgICB9LAogICAgInVkcHh5IjogewogICAgICAidGl0bGUiOiAiVURQeHkgYWRkcmVzcyIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJUaGUgYWRkcmVzcyBvZiB5b3VyIFVEUHh5IHNlcnZlci4gSWYgc2V0LCBhbmQgdGhlIGNoYW5uZWwgVVJMcyBpbiB0aGUgbTN1IGlzIG11bHRpY2FzdCwgeFRlVmUgd2lsbCByZXdyaXRlIGl0IHNvIHRoYXQgaXQgaXMgYWNjZXNzZWQgdmlhIHRoZSBVRFB4eSBzZXJ2aWNlLiIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJob3N0OnBvcnQiCiAgICB9LAogICAgImZmbXBlZ1BhdGgiOiB7CiAgICAgICJ0aXRsZSI6ICJGRm1wZWcgQmluYXJ5IFBhdGgiLAogICAgICAiZGVzY3JpcHRpb24iOiAiUGF0aCB0byBGRm1wZWcgYmluYXJ5LiIsCiAgICAgICJwbGFjZWhvbGRlciI6ICIvcGF0aC90by9mZm1wZWciCiAgICB9LAogICAgImZmbXBlZ09wdGlvbnMiOiB7CiAgICAgICJ0aXRsZSI6ICJGRm1wZWcgT3B0aW9ucyIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJGRm1wZWcgb3B0aW9ucy48YnI+T25seSBjaGFuZ2UgaWYgeW91IGtub3cgd2hhdCB5b3UgYXJlIGRvaW5nLjxicj5MZWF2ZSBibGFuayB0byBzZXQgZGVmYXVsdCBzZXR0aW5ncy4iLAogICAgICAicGxhY2Vob2xkZXIiOiAiTGVhdmUgYmxhbmsgdG8gc2V0IGRlZmF1bHQgc2V0dGluZ3MiCiAgICB9LAogICAgInZsY1BhdGgiOiB7CiAgICAgICJ0aXRsZSI6ICJWTEMgLyBDVkxDIEJpbmFyeSBQYXRoIiwKICAgICAgImRlc2NyaXB0aW9uIjogIlBhdGggdG8gVkxDIC8gQ1ZMQyBiaW5hcnkuIiwKICAgICAgInBsYWNlaG9sZGVyIjogIi9wYXRoL3RvL2N2bGMiCiAgICB9LAogICAgInZsY09wdGlvbnMiOiB7CiAgICAgICJ0aXRsZSI6ICJWTEMgLyBDVkxDIE9wdGlvbnMiLAogICAgICAiZGVzY3JpcHRpb24iOiAiVkxDIC8gQ1ZMQyBvcHRpb25zLjxicj5Pbmx5IGNoYW5nZSBpZiB5b3Uga25vdyB3aGF0IHlvdSBhcmUgZG9pbmcuPGJyPkxlYXZlIGJsYW5rIHRvIHNldCBkZWZhdWx0IHNldHRpbmdzLiIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJMZWF2ZSBibGFuayB0byBzZXQgZGVmYXVsdCBzZXR0aW5ncyIKICAgIH0sCiAgICAiYnVmZmVyU2l6ZSI6IHsKICAgICAgInRpdGxlIjogIkJ1ZmZlciBTaXplIiwKICAgICAgImRlc2NyaXB0aW9uIjogIkJ1ZmZlciBzaXplIGluIE1CLjxicj5NM1U4OiBJZiB0aGUgVFMgc2VnbWVudCBzbWFsbGVyIHRoZW4gdGhlIGJ1ZmZlciBzaXplLCB0aGUgZmlsZSBzaXplIG9mIHRoZSBzZWdtZW50IGlzIHVzZWQuIgogICAgfSwKICAgICJzdG9yZUJ1ZmZlckluUkFNIjogewogICAgICAidGl0bGUiOiAiU3RvcmUgYnVmZmVyIGluIFJBTSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJJZiBjaGVja2VkLCB3cml0ZSBidWZmZXIgdG8gUkFNIGluc3RlYWQgb2Ygd3JpdGluZyB0byBkaXNrIgogICAgfSwKICAgICJidWZmZXJUaW1lb3V0IjogewogICAgICAidGl0bGUiOiAiVGltZW91dCBmb3IgbmV3IGNsaWVudCBjb25uZWN0aW9ucyIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJUaGUgeFRlVmUgYnVmZmVyIHdhaXRzIHVudGlsIG5ldyBjbGllbnQgY29ubmVjdGlvbnMgYXJlIGVzdGFibGlzaGVkLiBIZWxwZnVsIGZvciBmYXN0IGNoYW5uZWwgc3dpdGNoaW5nLiBWYWx1ZSBpbiBtaWxsaXNlY29uZHMuIiwKICAgICAgInBsYWNlaG9sZGVyIjogIjEwMCIKICAgIH0sCiAgICAidXNlckFnZW50IjogewogICAgICAidGl0bGUiOiAiVXNlciBBZ2VudCIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJVc2VyIEFnZW50IGZvciBIVFRQIHJlcXVlc3RzLiBGb3IgZXZlcnkgSFRUUCBjb25uZWN0aW9uLCB0aGlzIHZhbHVlIGlzIHVzZWQgZm9yIHRoZSB1c2VyIGFnZW50LiBTaG91bGQgb25seSBiZSBjaGFuZ2VkIGlmIHhUZVZlIGlzIGJsb2NrZWQuIiwKICAgICAgInBsYWNlaG9sZGVyIjogInhUZVZlIgogICAgfSwKICAgICJiYWNrdXBQYXRoIjogewogICAgICAidGl0bGUiOiAiTG9jYXRpb24gZm9yIGF1dG9tYXRpYyBiYWNrdXBzIiwKICAgICAgInBsYWNlaG9sZGVyIjogIi9tbnQvZGF0YS9iYWNrdXAveHRldmUvIiwKICAgICAgImRlc2NyaXB0aW9uIjogIkJlZm9yZSBhbnkgdXBkYXRlIG9mIHRoZSBwcm92aWRlciBkYXRhIGJ5IHRoZSBzY2hlZHVsZSwgeFRlVmUgY3JlYXRlcyBhIGJhY2t1cC4gVGhlIHBhdGggZm9yIHRoZSBhdXRvbWF0aWMgYmFja3VwcyBjYW4gYmUgY2hhbmdlZC4geFRlVmUgcmVxdWlyZXMgd3JpdGUgcGVybWlzc2lvbiBmb3IgdGhpcyBmb2xkZXIuIgogICAgfSwKICAgICJ0ZW1wUGF0aCI6IHsKICAgICAgInRpdGxlIjogIkxvY2F0aW9uIGZvciB0aGUgdGVtcG9yYXJ5IGZpbGVzIiwKICAgICAgInBsYWNlaG9sZGVyIjogIi90bXAveHRldmUvIiwKICAgICAgImRlc2NyaXB0aW9uIjogIkxvY2F0aW9uIGZvciB0aGUgYnVmZmVyIGZpbGVzLiIKICAgIH0sCiAgICAiYmFja3VwS2VlcCI6IHsKICAgICAgInRpdGxlIjogIk51bWJlciBvZiBiYWNrdXBzIHRvIGtlZXAiLAogICAgICAiZGVzY3JpcHRpb24iOiAiTnVtYmVyIG9mIGJhY2t1cHMgdG8ga2VlcC4gT2xkZXIgYmFja3VwcyBhcmUgYXV0b21hdGljYWxseSBkZWxldGVkLiIKICAgIH0sCiAgICAiYXV0aGVudGljYXRpb25XRUIiOiB7CiAgICAgICJ0aXRsZSI6ICJXRUIgQXV0aGVudGljYXRpb24iLAogICAgICAiZGVzY3JpcHRpb24iOiAiQWNjZXNzIHRvIHRoZSB3ZWIgaW50ZXJmYWNlIG9ubHkgcG9zc2libGUgd2l0aCBjcmVkZW50aWFscy4iCiAgICB9LAogICAgImF1dGhlbnRpY2F0aW9uUE1TIjogewogICAgICAidGl0bGUiOiAiUE1TIEF1dGhlbnRpY2F0aW9uIiwKICAgICAgImRlc2NyaXB0aW9uIjogIlBsZXggcmVxdWVzdHMgYXJlIG9ubHkgcG9zc2libGUgd2l0aCBhdXRoZW50aWNhdGlvbi4gPGJyPjxiPldhcm5pbmchISE8L2I+IEFmdGVyIGFjdGl2YXRpbmcgdGhpcyBmdW5jdGlvbiB4VGVWZSBtdXN0IGJlIGRlbGV0ZSBpbiB0aGUgUE1TIERWUiBzZXR0aW5ncyBhbmQgc2V0IHVwIGFnYWluLiIKICAgIH0sCiAgICAiYXV0aGVudGljYXRpb25NM1UiOiB7CiAgICAgICJ0aXRsZSI6ICJNM1UgQXV0aGVudGljYXRpb24iLAogICAgICAiZGVzY3JpcHRpb24iOiAiRG93bmxvYWRpbmcgdGhlIHh0ZXZlLm0zdSBmaWxlIHZpYSBhbiBIVFRQIHJlcXVlc3QgaXMgb25seSBwb3NzaWJsZSB3aXRoIGF1dGhlbnRpY2F0aW9uLiIKICAgIH0sCiAgICAiYXV0aGVudGljYXRpb25YTUwiOiB7CiAgICAgICJ0aXRsZSI6ICJYTUwgQXV0aGVudGljYXRpb24iLAogICAgICAiZGVzY3JpcHRpb24iOiAiRG93bmxvYWRpbmcgdGhlIHh0ZXZlLnhtbCBmaWxlIHZpYSBhbiBIVFRQIHJlcXVlc3QgaXMgb25seSBwb3NzaWJsZSB3aXRoIGF1dGhlbnRpY2F0aW9uIgogICAgfSwKICAgICJhdXRoZW50aWNhdGlvbkFQSSI6IHsKICAgICAgInRpdGxlIjogIkFQSSBBdXRoZW50aWNhdGlvbiIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJBY2Nlc3MgdG8gdGhlIEFQSSBpbnRlcmZhY2UgaXMgb25seSBwb3NzaWJsZSB3aXRoIGF1dGhlbnRpY2F0aW9uLiIKICAgIH0KICB9LAogICJ3aXphcmQiOiB7CiAgICAiZXBnU291cmNlIjogewogICAgICAidGl0bGUiOiAiRVBHIFNvdXJjZSIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJQTVM6PGJyPi0gVXNlIEVQRyBkYXRhIGZyb20gUGxleCBvciBFbWJ5IDxicj48YnI+WEVQRzo8YnI+LSBVc2Ugb2Ygb25lIG9yIG1vcmUgWE1MVFYgZmlsZXM8YnI+LSBDaGFubmVsIG1hbmFnZW1lbnQ8YnI+LSBNM1UgLyBYTUxUViBleHBvcnQgKEhUVFAgbGluayBmb3IgSVBUViBhcHBzKSIKICAgIH0sCiAgICAidHVuZXIiOiB7CiAgICAgICJ0aXRsZSI6ICJOdW1iZXIgb2YgdHVuZXJzIiwKICAgICAgImRlc2NyaXB0aW9uIjogIk51bWJlciBvZiBwYXJhbGxlbCBjb25uZWN0aW9ucyB0aGF0IGNhbiBiZSBlc3RhYmxpc2hlZCB0byB0aGUgcHJvdmlkZXIuPGJyPkF2YWlsYWJsZSBmb3I6IFBsZXgsIEVtYnkgKEhESFIpLCBNM1UgKHdpdGggYWN0aXZlIGJ1ZmZlcikuPGJyPkFmdGVyIGEgY2hhbmdlLCB4VGVWZSBtdXN0IGJlIGRlbGV0ZSBpbiB0aGUgUGxleCAvIEVtYnkgRFZSIHNldHRpbmdzIGFuZCBzZXQgdXAgYWdhaW4uIgogICAgfSwKICAgICJtM3UiOiB7CiAgICAgICJ0aXRsZSI6ICJNM1UgUGxheWxpc3QiLAogICAgICAicGxhY2Vob2xkZXIiOiAiRmlsZSBwYXRoIG9yIFVSTCBvZiB0aGUgTTNVIiwKICAgICAgImRlc2NyaXB0aW9uIjogIkxvY2FsIG9yIHJlbW90ZSBwbGF5bGlzdHMiCiAgICB9LAogICAgInhtbHR2IjogewogICAgICAidGl0bGUiOiAiWE1MVFYgRmlsZSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJGaWxlIHBhdGggb3IgVVJMIG9mIHRoZSBYTUxUViIsCiAgICAgICJkZXNjcmlwdGlvbiI6ICJMb2NhbCBvciByZW1vdGUgWE1MVFYgZmlsZSIKICAgIH0KICB9LAogICJsb2dpbiI6IHsKICAgICJmYWlsZWQiOiAiVXNlciBhdXRoZW50aWNhdGlvbiBmYWlsZWQiLAogICAgImhlYWRsaW5lIjogIkxvZ2luIiwKICAgICJ1c2VybmFtZSI6IHsKICAgICAgInRpdGxlIjogIlVzZXJuYW1lIiwKICAgICAgInBsYWNlaG9sZGVyIjogIlVzZXJuYW1lIgogICAgfSwKICAgICJwYXNzd29yZCI6IHsKICAgICAgInRpdGxlIjogIlBhc3N3b3JkIiwKICAgICAgInBsYWNlaG9sZGVyIjogIlBhc3N3b3JkIgogICAgfQogIH0sCiAgImFjY291bnQiOiB7CiAgICAiZmFpbGVkIjogIlBhc3N3b3JkIGRvZXMgbm90IG1hdGNoIiwKICAgICJoZWFkbGluZSI6ICJDcmVhdGUgdXNlciBhY2NvdW50IiwKICAgICJ1c2VybmFtZSI6IHsKICAgICAgInRpdGxlIjogIlVzZXJuYW1lIiwKICAgICAgInBsYWNlaG9sZGVyIjogIlVzZXJuYW1lIgogICAgfSwKICAgICJwYXNzd29yZCI6IHsKICAgICAgInRpdGxlIjogIlBhc3N3b3JkIiwKICAgICAgInBsYWNlaG9sZGVyIjogIlBhc3N3b3JkIgogICAgfSwKICAgICJjb25maXJtIjogewogICAgICAidGl0bGUiOiAiQ29uZmlybSIsCiAgICAgICJwbGFjZWhvbGRlciI6ICJDb25maXJtIgogICAgfQogIH0KfQ==" + webUI["html/login.html"] = "PCFkb2N0eXBlIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KCjxoZWFkPgogIDxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCIgLz4KICA8dGl0bGU+eFRlVmU8L3RpdGxlPgogIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL3NjcmVlbi5jc3MiIHR5cGU9InRleHQvY3NzIj4KICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9ImNzcy9iYXNlLmNzcyIgdHlwZT0idGV4dC9jc3MiPgogIDxzY3JpcHQgbGFuZ3VhZ2U9ImphdmFzY3JpcHQiIHR5cGU9InRleHQvamF2YXNjcmlwdCIgc3JjPSJqcy9uZXR3b3JrX3RzLmpzIj48L3NjcmlwdD4KICA8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvYXV0aGVudGljYXRpb25fdHMuanMiPjwvc2NyaXB0Pgo8L2hlYWQ+Cgo8Ym9keT4KCiAgPGRpdiBpZD0iaGVhZGVyIiBjbGFzcz0iaW1nQ2VudGVyIj48L2Rpdj4KCiAgPGRpdiBpZD0iYm94Ij4KCiAgICA8ZGl2IGlkPSJoZWFkbGluZSI+CiAgICAgIDxoMSBpZD0iaGVhZC10ZXh0IiBjbGFzcz0iY2VudGVyIj57ey5sb2dpbi5oZWFkbGluZX19PC9oMT4KICAgIDwvZGl2PgoKICAgIDxwIGlkPSJlcnIiIGNsYXNzPSJlcnJvck1zZyBjZW50ZXIiPnt7LmF1dGhlbnRpY2F0aW9uRXJyfX08L3A+CgogICAgPGRpdiBpZD0iY29udGVudCI+CgogICAgICA8Zm9ybSBpZD0iYXV0aGVudGljYXRpb24iIGFjdGlvbj0iIiBtZXRob2Q9InBvc3QiPgoKICAgICAgICA8aDU+e3subG9naW4udXNlcm5hbWUudGl0bGV9fTo8L2g1PgogICAgICAgIDxpbnB1dCBpZD0idXNlcm5hbWUiIHR5cGU9InRleHQiIG5hbWU9InVzZXJuYW1lIiBwbGFjZWhvbGRlcj0iVXNlcm5hbWUiIHZhbHVlPSIiPgogICAgICAgIDxoNT57ey5sb2dpbi5wYXNzd29yZC50aXRsZX19OjwvaDU+CiAgICAgICAgPGlucHV0IGlkPSJwYXNzd29yZCIgdHlwZT0icGFzc3dvcmQiIG5hbWU9InBhc3N3b3JkIiBwbGFjZWhvbGRlcj0iUGFzc3dvcmQiIHZhbHVlPSIiPgoKICAgICAgPC9mb3JtPgoKICAgIDwvZGl2PgoKICAgIDxkaXYgaWQ9ImJveC1mb290ZXIiPgogICAgICA8aW5wdXQgaWQ9InN1Ym1pdCIgY2xhc3M9IiIgdHlwZT0iYnV0dG9uIiB2YWx1ZT0ie3suYnV0dG9uLmxvZ2lufX0iIG9uY2xpY2s9ImphdmFzY3JpcHQ6IGxvZ2luKCk7Ij4KICAgIDwvZGl2PgoKICA8L2Rpdj4KCjwvYm9keT4KCjwvaHRtbD4=" + webUI["html/maintenance.html"] = "PCFkb2N0eXBlIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KCjxoZWFkPgogIDxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCIgLz4KICA8dGl0bGU+eFRlVmU8L3RpdGxlPgogIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL3NjcmVlbi5jc3MiIHR5cGU9InRleHQvY3NzIj4KICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9ImNzcy9iYXNlLmNzcyIgdHlwZT0idGV4dC9jc3MiPgo8L2hlYWQ+Cgo8Ym9keT4KCiAgPGRpdiBpZD0iaGVhZGVyIiBjbGFzcz0iaW1nQ2VudGVyIj48L2Rpdj4KCiAgPGRpdiBpZD0iYm94Ij4KCiAgICA8ZGl2IGlkPSJoZWFkbGluZSI+CiAgICAgIDxoMSBpZD0iaGVhZC10ZXh0IiBjbGFzcz0iY2VudGVyIj5NYWludGVuYW5jZTwvaDE+CiAgICA8L2Rpdj4KCiAgICA8ZGl2IGlkPSJjb250ZW50Ij4KICAgICAgeFRlVmUgaXMgdXBkYXRpbmcgdGhlIGRhdGFiYXNlLCBwbGVhc2UgdHJ5IGFnYWluIGxhdGVyLgogICAgPC9kaXY+CgogICAgPGRpdiBpZD0iYm94LWZvb3RlciI+PC9kaXY+CgogIDwvZGl2PgoKPC9ib2R5PgoKPC9odG1sPg==" webUI["html/video/stream-limit.ts"] = "R0AREABC8CUAAcEAAP8B/wAB/IAUSBIBBkZGbXBlZwlTZXJ2aWNlMDF3fEPK//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9HQAAQAACwDQABwQAAAAHwACqxBLL//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0dQABAAArASAAHBAADhAPAAG+EA8AAVvU1W////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////R0EAMAdQAAB7DH4AAAAB4AAAgMAKMQAJEKERAAfYYQAAAAEJ8AAAAAFnZAAorNlAeAIn5cBEAAADAAQAAAMAyDxgxlgAAAABaOvjyyLAAAABBgX//6rcRem95tlIt5Ys2CDZI+7veDI2NCAtIGNvcmUgMTUyIHIyODU0IGU5YTU5MDMgLSBILjI2NC9NUEVHLTQgQVZDIGNvZGVjIC0gQ29weWxlZnQgMjAwMy0yMDE3IC0gaHR0cDovL3dHAQARd3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTMgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MzoweDExMyBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MSBjcW09MCBkZUcBABJhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0xIGNocm9tYV9xcF9vZmZzZXQ9LTIgdGhyZWFkcz02IGxvb2thaGVhZF90aHJlYWRzPTEgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MyBiX3B5cmFtaWQ9MiBiX2FkRwEAE2FwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MiBrZXlpbnQ9MjUwIGtleWludF9taW49MjUgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD00MCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIzLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD1HAQAUNCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAABZYiEADv//vdOvwKbVMIqA5JXCvbKpCZZuVJrAfKmAAADAAADAAADAAADAAADAq7aiiFafTJvTQAAAwAAAwAAF1AAAAVUAAADAiYAAAMBNwAAAwDUAAADAMkAAAMA4gAAAwD+AAADATIAAAMCGgAABAQAAAYoAAAOwAAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAA0cBABUAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAA2F55UwH3zADgCn7Xsg5urkZA62Mq62dWKwprJak9U0cjT1Yh9J7WRISuxmagZEf3SG5hJ5glLK+m1DQRdCFD2mN6YZGjkCTKwYyDxKlNHkaW8fuatJR0sAtCoVfOjRr2/NS+bw85zMQI7VFu7+JhD/Go1Q5RgMv5bIq0gpxJKRnF31ojI62CwCRiJ1dHa6nIwcU00zURwEAFhyu6/UdOQ6gXR/Fn3SkmUwkQsjmQF0XEAAAAwAAQkN8C3guxx7g23xd3I1uQvL9Dh+C+fpNfOmVma2q7DiUF3VD8o51I57iYniPq7fe7f2YnPwRwynt2WAsZSjTMgHnGbk5zsyy+rXIMy1p3notBIJkpSBHSuogn9FDL99PItYMLSYCXzbB1ngJo9jnaTgI0b904RmkSjuZtpKyt0ofkYfxNRrztwDGURi3JRPkpuouCWX8KWcxn8NHAQAXWrAsVbXQ0f+vby6QN9oHh0jRsBw7+79AAAsCUlIAAAMAAIGTVQt7SJOBNtpTiAsB1/AzhYzJ8lMVgRENWBT0VBkiPo9+OyjWfg6dlrISORs+GKnEy5aUKA1M9uXDtedogUi7S7uVd54Gj1Qb5NTw4Jix5w1Ejl/de0xvxERyv4b3rmZdsU72FOcfnbK1K8lG4wnxVzYPGiElBGSrNsWNXskCT++8dTbAQv4ejltKQDN2z2xpw5g1CkcBABjFGRM3p9Rp9BGLQ/gaCYSE37IZAAADAFsvgUK7rSLf56T0ZOVulX2oYo74ASEKbonCVfRcGAke05L38QhPtmJ8xRmebFR5/801CbQAWvnAOc2AWgY1coPTdBTZIfsBwU94Gu+qjaoR4dfBX9u8RZXmrbLBCqJ8wTgvf9kJu7/27gcTx8SsJfq40cjhNaRNiof2e8CF4imWObVdvBDpPRxSiR1tsORfA0r+gqjURLyvIwDsE+O9NkeiRwEAGZMG5kW8doFnKjj4QW/OIpFfzF+53Eb4LrnRmrkHqYA/RnqVvBWNpUSFdATxWKzy0MBYRpY4IoUCpCeWwgQ/9Ny0Yi1iQ++wmh1ay/SnYR5B8k+FpDYbWDODuSuCMmrTDKXjicAStFseuB4peB1Ufu7fitj0L0uZzCgGY5zkzbBp3bfXJQEGCnSwEtW+TY50gbhenVCesUfJKjvG6PshP5ScKPdVkZltrS4wx1CntFR+srvN3MjP6p1HAQAaM8+T4dTA6o28g/ki3+J9b5WD8oY+fVgTsb1jfV2GWWd2Hh8JK00uloyX94k2QHGzhbuiS1YKiEdCLz9Pt3RuxuTNm9XSlLwQvyRvfY6sKD8KIinvSq3XP//Kx5Ni82QOXvrn5eEmFlTGuT36Yax5OR4BI3UhdWSGGa0YoqeD7zcvWv64AAANbhz0PNupTjTGu6vxaQq6PcgarV8F7NT0zHSQCZ8KuEFdideJmx4581/BCMYXuJt5cEcBABufpZ3Gzdy5JLw0J2eg1hz70uf/nD82aqNxy/HUvEd6+w5woyIYb7nzl1eo/+ACzPidfiSKydCNxKh9e7tKjNNTJYRX+1f5A398n+2wKJPX7dRmPk4C0j/auaYtAMF+Ft5g6ZqxQuA071fEmj4uiYMR7F+JbZ7CjA98DObmNy/ZWoJQvMrvR3ep5XAmNFkqs1Ma20JWsiikVsr/jblTK0PBVnLul36knafsXUW38/19lMQo0HUcMvrmRwEAHI2OaNsvRTodm5RGcpDEKfXIqXsLfH53r0F3K+sfRvbk3u2ilZd/c5zH95TBbceTvFEt5mD6oPEhxHX3gId6ZBsNNUKUnWDxoX7MaYE38/ELMyIVzRxDCIEkf+q7aY6tcZEMrPBa352hxE6SJ+2y/zlDc8X4jSYerSPRgLBiUm/TSHdm/sHP7d/kl2fmIUNKBbeaghigfwmfDnaZ3wPkRi3oXIp3YypbLYpeup62X805+oYMAgynQd1HAQAdHLgV5nC45givqz8G4AAB0pcgXQpZhwRtJ0wE/aFEPMXugXV9NeZnpzJeXaijTBtaFonT4e+hZZXjLHhxTugKb085RNFOoT0GAB6b2twqc++PKcb796IKMKtNpGaUWjoFvBDGh4HrRguoZWCbLy2RFxUX8SmNUb7qfDXwIi4nY4i89/TcrSc0q64NPWA3SPmQ5D5/ZFbRzBtFuMVVmbEF0cxv9RoqLyW/VGkp+bBAmoMhAw82eI9VskcBAB7bidwIeUDbJvHb2Z8Ep/avJccAh157ZUytHDDW9DhmdbdBzT1TpsJFsFWe8FOQfaNpJVfj2nGqShY4+DhxRYxOpzXw2VF7hQpp6PqFUtyi4ib3VHETkSuHz+2uom/bMRbhw+hQ05xdXOHcFVpih+k58QKrhN+txmOmV3ULdeiVLUplf35jQJTUIZltXjTCZhljRc0sdqOZHDZjy58Sc6hmq8D6lztRR5jN6ifzzKdZbHOpMvK28A4ZRwEAHwyCdGDG4LksEyABPYPnzVuaVJHpUiKgtb3006VleBPo2EZenL5/vyGrjLMas0C6R0iyXZjr0xqvCfaFfxVO/+DQUMKaj0XLNNIrLqXxwzxzy2ENSUjNNySzfvDkpjuJVywa0uwsg60r6EURKgU15gAtbm3Kx4tjb3pRMM8SZHnsN075ztW98+aTrdbRryY9XR74p76dkImiqWIVRQAAAwAAerbiggDgwfd5iHYwqlkEXOqApTuXEhFHAQAQ1PUugOrA4HsFQsLzVf2RjOkhWvlC/kwNqqDXkwlUM6egLoIdgXAyBFgSXuM59iSh6DSi4LwFa/FhyGMrxPV0UF8QD9dGgSeXBUvExQHAGOHz98Mbwm3lBdIzxkzeGLDhi0wZ5SurQPpWomKoDW7t0a+GpQkmCEgVO7iBc/JrOFIt8BBRW1E3EOMv6Wpc5Bw9M2A1XVVaNSFyVkr4bJmsPdNLXAJ4UeKO9R1lUBhl+OhrxoG4RKVHp0cBABF4Om4vKIyHfOkDd6zL8NOXPLL7gS3TIX2EFGJwyyOzsp3WEnvyFp3pujaaLMn/lubQO3uY99+DKi2Io2lBhymLAR6LDBeQ7AhVrgnfiNz91OxGGiYYLcV2yR4f5zrcwMQZNJDrBZZB5gHIDL20vdPnM5RCWlhx/pWX/VbNt2slYDgCwcQp6S/f+sYDWW8d6kKnv4kberk4wmAhuvG6Y9SNfBDQ5l9qn/Obo+/QByc1yiGJRu8Gf6MCRwEAEoe8DYkkVe/6Ixqln5QQ/EQgnqBdcH9XhmfrybwZkozmwKLLqqVJH8KoMeYLCfFbfUaJbcR1M2fwEHGq8BQXjRJFgtHh3lCD2NBLo+9F2kwxA+U6o3SQoAiESygbnYzTRsRmJbxNCRKSLcIhfuhjjCaAi0Icfv4rxjBMuDTA3ZANJ/jmVtzwWUFolUII47bYNLfdylQl/XdlhiHX3vln9Ji8cLEbSL8BMxJ2EI8GBsnrIBeQBPJc+UNHAQATIY6b3+HKasi+GNJ2c21SbezgAtkzMWLCJOnux4sNbrOiNHjom7p+U1hZN9Nr5wuzsM8+1NBBB2pfg3/QKiCYs6b9pduydYs2HEo8FbJJO9uH/yhvTL9d6RHrHf9srnZkSZKhJ7J7mApu4eNNCFusU8sNmfV7H97V1FOBXT/6JShgEQxdnwWdgxDvO8PxjkwuGrYPamKBNG/zRiG5AbW+ikv3OBftfBdhuifSSqoWx0W/XRtyk55S8kcBABTW3x1rkDAHFUfqPG8dZSQWAtnA0fS2fwfdqEGWrbQvYFwWWVcRma+zWJHw2/lVzPD/mSdMieWiX8i5DWTg51gGKy0ftdjOBgAAAwAC/KwTiIpM5clRTlEEi87aAOb87wCHqn1gnPnLGPfQQiw2QYxiClSodV7wEhhJw6ToIwyUjyxYDwVnF2+7eRq7fijw2kLyk5C88BvU1OTdlPGHyBmiT3UXo3I7308/Mn49t3tnXLB8MdaOaVwaRwEAFbiVrH5lksx9oY9DCw61tAqU07scxCL86wtgcyZCmy2ZZ/2W79DRKs2QCu0op9Lw2QYj/OgOj6apaZTOtksj8+VKlTlQQnkV9sFudGr7gpsQoaxBjmrhVk1adbYaFkKCEUYRbDRJpZQDbv1RIRFlY/KmWweiUOZDX+3fplGzJs5LvbvgiM7THIlybfPIXTjS2SPmFm+rQ6T4X9BQocVCjzQvz6g2kp58j9jXT5sBBuu9tC7iTFfMEzZHAQAW0QFraUkCV6gEC2C8wvr2E+hXgJwCskVL+063JAWE9yhGOTyWD/fLQiiuxJ/88Zes8sHmBC+quRzE8SHNO8OIMMptzSvx1i2D8aBb0ksDLYEqwCXN8Lsz+71HkS8SdC0nDGQZqAm7DYd3/uBgR/J4FAOc0jvOUci0tSUbSVn2z+H03GNfHcZ+XgduswjjsUodtsUtRn4nXpryhElgMI3kr2OyFXf92YxZPgbhGubgcNlo+sZ4Z/ApNUcBABeS+kT7jvDiaynYNz51Kc4yccGFoXKWRhGdSRtXJFDck0iJWKT4opQng0gcHiUFaL9bf4jSqm56kxLcQ5YAgHkDZ0UGYh6QEEPPAfCpoDLCF9mL+/OEuHWZ9NOnW7TcJlKbhJOZEKkoE4KW3fDydJ3a3l4IOByTPx5LJAjAZoV1BtKInfF7g5OQU0G5EXJGhFWUsr8Sf48Q9LVjnWvDuawWdWPiS+BcWfUZoGIkK6NoPQR/qL1AIJhcRwEAGAOEUaznr61uMAnNb33549uKjSRk1nM/fUR2BA7+39FhNrmR3taY6qgM804qoHgCSbYS+YIKj8U9vxfATvknbWEZv4JF5hoFJaAN0bNc36f9VcnxAkGsb3r74Yko3jVackXvVrdcN76rT9izohLnH2yQem0zb5wOq7EtjPnGn2t4t4/9JDKIfVb2QikijBu8gHlSjvgVRWSYDIRCi2Zle5MtFyXOaIGwCRAv6PFD6mmJBUT2XimID7tHAQAZOkCES5EDxQ08m+f8cpxKkoyHem8Ex4m8xZ2DA4d39JDH02xtTRRfSfDrC/TqpIjzCtcVv/zzgSflzEbq/UKFH/Z7CbtsrVS2+ll2/CGSNsmOHGi5yrhPM/JSClEmt6IRtyk0FZ3r5cdREJwAKoXP4tNLpfjWSZbATEIGmr+OxqYxQMlzf/93+QrgM/g1HvmPFBPard2U8aKbHTEH3r/kFdkNmlE0EQi5b8TOCYIa/mpuWq/yMn7by0cBABrkhq6Rldw6p3qQyVsZsBpoW3OLgDe/7/pMx+iijZdk9jE9T0fcFh77YVfpjYex2//dcNszIlWr2vl65Z1+0cQQShk/R5GP20mU4dc78l3iyti4DcDCi6PdIU4nzdwZIpGFX9xIuPAHaNfyP4Nyr1K0j9h5STEAHsYX21+iN6CKiuWoWOm3ev+GGzt1NNmtc1W0OYicTiPoIVr1TGzQC+1Nd7izII3tPWn1PEtqM9+fXo32ibSZUvGsRwEAG28xtoQMOBX+QWzc6MLY+xdighCBxpzLcNRK09DBzvBjyt59TqRxzLpeKgJMb4hkrGZnI7ZB7k4WSdssIdlyXiqQOLW68TKxOi/m2l4eAg3OCdiWnrmhOdRSMVLPALUNPDXtBJE5hOD/rtb0FHxtGQKnmP64bBNEEEJCWqJO6W+Gy5Bj/1OPVO5Lb/mGT6SfZVe2RtKnX3ZVDyDZb1jHV0Y6RKS8+Ww1Ya57NIcyPDo3g06Ef4Vi2RpHAQAcWH+V9i+eiLHkvPKkSHT97ZZGFxrcu9T++hegAGupHOjZYoxGWV+zfmemcnV4Qc0p0Sb+bCBN/WYAmY2PsHr+MIroPJIqRxQacYxgv0Eh/ahn4Y8AHjDPnPRprvdugL71ZtfrhmqiLml/RA0I8xMa/JZ4jrmIOqM+Z+fLjB67UYM71w0xjsBG/PgXRORM5Qqkfa6vscWkOW3l2RaUeeyDnUES4bdGUahzOYND5CZ11DaxBi7FZpSS2kcBAB1UDuNag/7CUCi13BGNTDCy03A2H45ho7AAABa85YSo2ddxRWSmP/8M1+fhrnv2TvJk7zHcA5z9BfW6MKcG/ehOV8RoJWUXPPQvUS5U0mqa69CuPBPy9cA1FwAI3ipau/UmVf9WS+R7+XREZCdpkNc5acRUaY6VieEi58Gy3p/q3E9lT4f4oYx563YFbu2Mjwq/dN/ncWug4Nun06Ap71zELPDKDaexmC+kEhaf6dReVEeK+uZfg42ZRwEAHq4bLzMgvrZQb5Neabro0F+gcFiL7UdLm0y8LR7TPvIQ+Kevu6d1BghMMTKxPVSrBVH6F6mATlcYYyhZ6fc7mnHFrpCznzCepMqz3ro5tOUnl9iNq+BQQPFZZlKIVl/GEtg5jzNU88j4KpNvVAoa6Cb/P9X3gWXF7KWmnzgUsZM5mR4GvWJWIcg+IDfe/2FtphXajgL5wfiIK1jzzOr3tQ5xYrVpBvuyKmtdCfIrHoFt4i/42TRgGMJHAQAfCTLHw8EYKGd4hzY41zaYLjR4E4nuBnCtxuCX9FhYm/YnBE6exCJDSBtf1sfFAv5pgAOcF+CZrALrM4tRCUKQs0t0o0+8+ZU1dyyuCLBTtC+vJydoSGmMBg+XNyIPtNEtN7qGS9WWA81qcbxxzsc40CIJf78S26nBKAJuyPu+iX9ANPAyMrgOAVc95U6bJlSjLkP6CXXR2dJRvUv3raWkoAAOjJ71lTFvacoQwhCErx3cbavuczBzJ0cBABB+z7EDY6atdC4NZwX22iBmtZsaHUa3NaBIO7aD08FA7Kd0ugfbomTYomPBMuWwk/b3KMR0uhkyeHKC1RjYo4d/mMo97xS4ix+t+38cwQHmkYQH5Cm1BO6ezuTSevjTojq1hlXD39LxF8a/93o4Tojo+ZmPPJix6BuKlBIwjtpZb0M+nOEX8jPyyd96ytD4eWjOAt/heOiSF9hvmiN50BmkUiITCBF39iClDPO2k/Fag4BqTBbtubcLRwEAEUNMr0m0/lLKJ5ks1W5j+cRzJ3kSK0mRkjrPrr0eWASIwI6LNyATeQMrpq3uWQlAQ+9SdeWmTu5uHTgt+d8sFZe8JXcU+1JnZRSZ9yaoEC0i+bOkGfWyMpA85qtvAlKTBMOm6ub/5NMaKU/VAW9lEvkA9PprSonQVMnG4+BlH2JOh8TsTKkBZPVgILxDM8mFjQXm0TBsezlo4ABKvPWcftdHUaGyF7gP1XbV0exXEHfsSASfYRd0OZZHAQASC+/t5TafeJT36YiEZXYeQH2+IoK6ZxRnFgTmKOGcCCYd3KzwxTJp8XFrSbvg7LzTDnvjGYOaazdnbZt4/Jn3krhhlSRWjhWRqAyxMNVF8n18FXqTzJB1PKNbd7ax8R0AjZfFVC/ycdg6wATRrdRJSofJHpjwYHGQO+L2neTkvCrH/gUPD1U+SjdMlUvLS6vMXop0yzDX/L7HQcLXjKsR2lGDYBlM1UB2WHnq/qPBycWFFtPYyTlN90cBABPvVe8f0oNTNwJhtM/kLJBEZI3ZwCEWYk/wv9hIIWr3A4qkehY4+ptgTX/1///4JZ6dscO9HKuG6puRV3lR4ETvMwdKnHPSHjJF2aQeuvoGeA7yVT+AaeDi7V8ZlVYMc4uVncx1liUQapUssjXpK+2MxWQ7Cb5GU97Drj7W/oPo2Ptldofr3uIe6fvheMu/6aViZagqUWfdOTc0YXVHZzPFok9FEQJUWdUPZiJlfllKLIy/6aAyw8HuRwEAFKEU8CS7kA5ZslGAnKoBbCTNOXl4p9BBgCPqieSBknZibS3PcR/LjWgGifTDu5u2Wj+eAMmSM7P3HMAAAC+T9jKtui2s4cFmXoWX8va4/qVAzxWGs3w547v+Tmac4FyXAqNj0/rFe9k3Egw/P9Q1LxzxwDOEbknnvYdCGAAp8Ivp0KW4t+inn46uKR4RHHa3/VSY8znvIUPdudc1/K0jIEI/Q3pEL9pzjQZxtgqbGfHOMo5yI2dWIDlHAQAV/YbUhbsIYEjAICdYv/AE36OWoooY0Nf/2lmJx7BftLoE1dLDfZKeiAdmrhnpvihEEfTo0MaKnEoSfryZ2OAN9yMb5+fcL8FTpHFFCfvfivNdZyTFOvrxIc3hv+2TavaVMjhtrDqlErqEd/XPoVqKmAeHo/ORSn73CZ/cWNXX0JQ1pRuP8VvL2QwfnG2vq9nTXfiQrMzEeEpNIaeqZS29MfFP8+VCiKyM9p1vNhZC1NItrJ+gsFzJsEcBABbEKpgjE+ovbWLdj0EXyH8KO2Jmn2vTLCKigPqQhq3uaL/6o+uZWDa8dvkxNep66qHmLO7/821Audrn3I6tmZZWSE51J3/XYBVjpW9Fw0Bkr6GpAeDT7ybMGYdKJsd7/WZPZV+Db7zD1ZmulDiRnfN9EmSFStYYD0lEfqrCbP+xQuwtYvfYJsqIvl31t7RBZk/QV2ENWfDLEpMHt5tlrAv5w+3dl1lg2WcrFP2A/7e4sIIyRJo4HsLGRwEAFz/AGCMZq1GUNbPZoNkM+R2je+8sB+Gh/lgSXtAQZK4CwsR8tHn5hyV9QoAAAGJ3xJ/ZGmyBFBfvFt3Yyf/NFoecJXk49dlUxZvTtB0WRCewg6hn1yl3AH406dFPGEk44wMT7vPKyYJW4OT7kiDQvBsdpaU9TmUUKyup1MsILviQKXWAv+kecpWRTY51BniLudSBH3vmnE2l4hUOm7AVWQ3O8V048//RRvDBX7tSPIiWu+MxSSGZfLdHQAARAACwDQABwQAAAAHwACqxBLL//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0dQABEAArASAAHBAADhAPAAG+EA8AAVvU1W////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////RwEAGO10tGlFAwyE91Tzg8923ovJk1dv2xh1gVlYQFtWdZ6NSQ8vgHM7/tMfIZPsqgCU856rdBJJRMDaor/oWA7pkvSmC2aqaC5fd/mkWUPTuG8fRhGqOY1rKxLNSI3HtTQAcuVBxRM0NfMw0ky/JMJYZiCgXcNsxpxl+khr/9fKtO5Fg2VNBti92xcZimHUZDJMQTBOY6vSR9L1N2O/kJQCpdfuc9bkcUTMjH/es/lAySxvbiislkohqkpHAQAZVatwHI0t9eHCUfDyWUEtuCNyDwQFOVMtaYEQJrTrhQX0VduT86F0u0wN9ag0uPsrmX6Rid/x5S7KI1SkS+qP6cdmgSP57uiF4dG6IKsWNfGBLY09H/CFlrg73WINQkkp2diKkdEmtZetn8+ZAKzR5eXN5FebiKt6pIkNLuSofjosypEs2o6boKsfpmbtOV0idOeWDM9C8EIcn3aZwk1s2KBDvt1DlY+i2Cuvhk3XoKLT+pq/bOC5QkcBABolcOXneZXLoQw9W1PH1f/of92Ytjj8okrWijcQAKlE5l8XoTb9qrOiZnDOhqwcMlB9H9rorq041I89hChohYoSkJElcM8V+r8WYN5axD1BNyfwaHAOm4UN2/VEYOkNSfMjmx2S0WW/F2ha8Jj4fc4QgqcXr+TnnbwqLkLTValK4Qa1pcv7PIbDq6zCUfxe04guZ8xEhPQjp17/G6IB/6uq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wnibxQ/cXEblVnM47wbCN3iy4eHjYB5MoIICrSYmd8nt4V0toLs084KJlmnur5FbApYM4W79ff4oZkW88Cg8Fv8TnWhh1Hqc4UlhMbRKm2QxDgfBxar3U7BwNR6prrXXjqfR7ja3tPli+H7Jez/xcTg32QpHAQAdTa7pSSgBvmOqzz175NAFIhwE9p3d71F9jLvhaPv8q1iKopL0kizwzEWElnXWmNhfLkl/Au8KujnoKUaxVdTe+zAZm2dOkejnpNVtVj0Aw9wKcG3ZQ1iRZrUFRIoPKYlmR+oi0LrupuhYABtgPbdCbDtezGTr0nw9wVd/rZ6V+1wcoJ6+8VAVueIdwI3brqm6EoFHiI8L6lER+9SefB8fHo4NYgr/I8jSxaa/2PLX2K/DjrlY6bN8fEcBAB7DXsuh8DITF6CYWj2HTFvqfzlic3QHXnHtvsTFNpyVY1LY8y/fRK2mwALN6IB5W3OuyoKiA3K0lJdQUv2gYhHWvPTV218HYrD0rkbMxRH0SiEEkrHDeOt5T1HtWD13D2/QvMu535fsfZyeaFDjdCE9M0Xi8Lfc7Xj1ZNGend7Jo7/cEiczFkc1vB4z2JpFGZreV2EdquyEzC2STFJtfimyx8QlLngEuR1cxH+lWEcFX+mvBa/eqktIRwEAH6VazFLPNsnHZqsI66TVoArQuUUGFAzr8MT8GZ9V6qpZa5D0jA/4eGi6Kq0smUgRExnqIbSMLWqDf/Pk2YT3MpHTu9VE3Dn9blgB6KsVIkWnB98Y2n/6DrZDcF94Ndu0Ka4U/RZwdV5O5KcO+lU2ZiIOYTYZ6Ie0d+tApxYxJ+YmxaDoCyRNe6crw/yzR5SflT8ddi/E2BM+l+nwVDiKZ/714fmrBxFKWuqLiQNHV19o1cZ8Ubun+ZtHQAASAACwDQABwQAAAAHwACqxBLL//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0dQABIAArASAAHBAADhAPAAG+EA8AAVvU1W////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////RwEAEH1s3BdtHdF1ln55B24wdACF/ggcRtPmB4IUB6cZJ+m32I4R48ZkdhAFBulgWcsv0wZwH0o1yi3i4qm3rJ98AUKdB9PsNyG9gURV0bTw4myAj6g5Dgodfv6w9bsbOxsGUWkvgAJ3rrR010BvZbIa6CMRCQRjxkCfRF77ansRJZT0JzhtYeSS/ZJob8Rr2jrng3W2rkmHtE+rdqlPiHxmwkRZvYGhBxwiJO2L6f+l/cABsfs09rA+A0pHAQAREZay3TBUIAfMWhApE+LaPgeyOYtaPFONA9aC0h4QrFkaLZfb86678MK+zLgqDBsDoj50eZHMVcczRjs4sYlv7RG8RIWKb5lB9Kn/8+CkxiiA11cHH1yzLX2SKCmhsak/+P/zYQ1EDvEj33bl9e3Jd62cTI+Qw99KrsWnUMN8hFNeXzoGHA3aec+Li4NFboF8sa6lCPR6Csxsvxw8DJaWCnER5Z0p+nKhXavF/eNHQ0DX47ohycc87UcBABKsYHCHXXe3vK1cFYDWO6rhwM6hxCdJ+/X+VB1akQejL6iBMdUPuadUqBnbprwJM0dWpSSn9uuZZeqe46iZOGIJUo69d8x+ZSvPcBH/dK1Y0LJnoWdgWH51SQg7eYqcwjQW3BOy7ZF02Hn1EhTuhsN7ms8zv3WIeEBDBq0T3Idl+Tmw9iJU9skVYiwygHG2+0XwrLa6y+uiQPwMzrnEr1kuf24XoAqrJTZQiVH3aQF4d94yDreWu2KPRwEAE2FsynHZaUcBXEFbeX0nSxZ7sRcRjJvc7RYOny6N8QFwKDVO7jpRWWYM55kuepBOyZ+7BFYeG+FU1kR+ZfmqyDNkD4D1IPwNh6u9JQxDymfN/aMcQC3WxdvCKquPsAut6dugpGkOFtIe+W3ayc4V/J978P+h1EDFMbFjxRPuXht0K2dBQZCJ0ybISUDqWzhPuep8CdxSU4MvMVfdXh7FLl/BqKJUTT+vM+Pz3XnqCQQmH5TjQ4CK55VHAQAUEtgfkBwIYgtwHkhjmtLw7HNTeJeMfTjATEKcyuKzItSeYxHBmGzQ/+G2otpPCOkVAXJ9mfx7LxrW4joZ0ttTRQJ/wqMUK1IN349LiJoo8y/+FwN4jPNDwIleJG697riqnmLOweFW8spHKLBfnHcyC1pG6EIxFpTqUQ0KHqXD/KXIHKioJNAOVwQ1Gfloxebo/Tdtd00dpHP3gcsAOnV75APCYOjVIlwm2X6ViDeZw6Btdb/Br/+yokcBABU3+eOESLlneGbR5SLiL8wPkoRaZ5X7xFlMTMvsv9yHk26bVdmsubSdbYS1Hy64n0+NnL7C1aLD7aJxOudMjVW5goZbfO2KxBQkCD4HFA284wbaB5vOL7mRilCn6YEs1kiwf22+fBLNUmXDb2p353wrD/ygTDhlki66USvUmd/ZAs9uzAddegEzy7Xn00YysWTu/hegYyZtWFC+X5dhLubWJ7n96y5wjrP7PAOXoQQtFUH9j/rBiP/7RwEAFnL/wYKYuj80mPGtimSbF/E9K7XwjwBz8yHZubmVMTCmwkZBM4h0FR1thnUGiSjqjJT6SfunWCZ/dZDQplrzS00UKcUP399SyM+nNG1br8Za0ZYwWch8nyLHYXSRuxdnrfUUespsOQo1cWSLGf0pV2HIcHoiAAEKwPU6irB5BSoFvB1qKVjgEk+QwAEYAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAABHAQA3pAD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AwAAAwAAAwAAAwAAAwAAAwBbwUdBABgAAAHgAACAwAoxAAmBIREAB/SBAAAAAQnwAAAAAUGaJGxDv/6plgAAAwAAAwAAAwAAAwAAAwAAAwAAAwAKCKB0AIhy1ftwLNISWucTFC7xeBcaIzP3oZjZo8uT9hqZVstWGnrPz+vjaA5FuCO+K2w7/o39LygDO7aL+0zSrN90LW7r133x8+f+PEKk8d7pd2fj4RYuMOXOYunzFzRX/4IvR1XsK5WJYwVkOca3yfo7DTvUBP9rgSiTRwEAGQD6CFK1PBC4qYCa+coLVnX+jgODNrau5YJXIekDI4+wUNV+5T5HE4e2t5EGAjn77+kC1Vghmvx8KqPnylVUvsaTofheggxHsPuxn1zQt6nA59UglrRUMn8b4pmrvfqTBSqU949+AcNAI6M/eAqz6r0RG5KNeBhx8R2f0x2kujwHU3pc3rlPb6ZrFM/2HiG97eEIezrvWFG7YAAAAwAAAwAE1KRo1VfbdZQ/tOpNGxFmTcQoFidyD2tHAQAapTTIErUKA2Rc9uIzGJu+oW0uNOxRyl6oJNUNJp5L9TIshNS1CmUKgdCaE3LkLwdE8iUkUnIGfWLiWpWmjzsINYC8dnDaSptB53yJkBu0SsR00oo1PZ0pl4ZzoXGSYQJTPaVCbj6FNqm5wcnUqKTB/rgHdPdnDj0K8asLABeo/n3XCXrDorI+LYSD1FBgmV9O7RZdjfL0NnXOQkiq/ZGirwVV0cUF1aHtZx1yHlAAZKuuu7TqB13CAUcBADuRAP///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////yj/IrOvAEoXDNGy+nrxWN0l8cmuqWYaUJpuM9XgAAADAAADAAKmR0EAPAcQAACJHH4AAAAB4AAAgMAKMQAJSOERAAkQoQAAAAEJ8AAAAAFBnkJ4hf8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAC/BmhyuvLmkCgKTgACEXfOVvHRHdpBEEmTTz9pIZCa2FD0CXukzDCakOHekTpJQSdsfd7a/jjM1/5lBtKCAGQ6zOCSQ6DeKtyw+CugDuuglGipwmvQW+FIDjnZ6HRd0uaSOGy6VB3h9MI1o4nqaCqVwwIgubYZFHAQA9XgD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////WcZrO6BEiqf8pCxYwlz2mkdUzY/ipM/TIHS4m5xQAAAMAAAMAAA5sVm90p14dlvWgBgY7XQ9KVOJKLtaMAN5KiffVQtNuzW5DfL+RewZpAAADAAADAAAQMUdBAB4AAAHgAACAgAUhAAkswQAAAAEJ8AAAAAEBnmF0Qr8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAABJfBjP2+4+W7ZybyT130+Ma4WSqICfd/dS4YtjrLlmh5VBlfrtwJqdN1PBTYDkwGOOONqZQeFN6lLGJoDzvuh3kv1aDBLqug+JhvrSeu5ebnvcrtQzb2REwJL3h9mvtkr0WfDu4AAADAAADAAs32Y4C/6Ns79oCGj6oqLltY3T4I0/QRwEAP5wA//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8BeoWLRnKQmVgO/RBoBfcK85AAAAMAAAMACFhHQQAwBxAAAJcsfgAAAAHgAACAwAoxAAllAREACUjhAAAAAQnwAAAAAQGeY2pCvwAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAEmDKfLGXsvBBQPNYXlEd6WueJ4deApfcHESlG+7V6u0AiWQqJvNZYM+3Js3Lj9Ldc9yYIHqruVwfMtCYGlX3wMavI/DrhMuJw+RreIF8SKsJD8CMccAAAAMAAAMACrFZOBgEqaP/8EyWsAHV6CgcAgfyox/roEcBADGuAP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAADAAADAHTBR0EAEgAAAeAAAIDACjEACfGhEQAJZQEAAAABCfAAAAABQZpoSahBaJlMCHf//qmWAAADAAADAAADAAADAAADAAADAAADAAALf8A2bry6lUyIAQGNFfVK2Cd7h4qDqmqpvmXfkfTwo2Ab79AHhajxJ4MPWIgAAA84xLRIx7I2CrWjWe96OvgkzgS9mtvhuxdzAgpuIOJI3DEY9mviDDZz8XSAAAADAAADAB7AZkj9AAHHGvk+Pzlku8UkWa5HAQAzogD//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6HjAkbF/gsWuvw4QAAAAwAAAwAccUdBADQHEAAApTx+AAAAAeAAAIDACjEACblhEQAJgSEAAAABCfAAAAABQZ6GRREsL/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAA3URJB/3lMHSmOd0GYZnfpoR80WdqxlyHzPX+V81VUMeXIGrRgq5agd+ACdjoGI036yQ/rmpGw0CmMBrKwpI+nwFo3SP0s1rI2yHBZaiPJjSUgw33rBkxXcq55kfLf2sAAAAwAAAwACBWolidWDnIeQAAADRwEANbEA//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AAAMADulHQQA2NAD///////////////////////////////////////////////////////////////////8AAAHgAACAgAUhAAmdQQAAAAEJ8AAAAAEBnqV0Qr8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAABJXNihCnx11JUosH2hBE53O/YN+GPHqcnJiQBIf3maTAAj5iRt+7GYUKBAU9iCXTiouCjGYgAAAAwAAAwA9p4HQBg2cAAADAAADAADGgUdBADc4EAAAs0x+AP////////////////////////////////////////////////////////////////8AAAHgAACAwAoxAAnVgREACblhAAAAAQnwAAAAAQGep2pCvwAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwBR6/L83y+ZevtMZ0FW4lp8qV7fVXQAhLAWlS6mDxvpaSUgChorvgTMXtxJEIAAAAMAAAMACqFCAAADAAADAAADAAz4R0EAOCsA////////////////////////////////////////////////////////AAAB4AAAgMAKMQALYiERAAnVgQAAAAEJ8AAAAAFBmqxJqEFsmUwId//+qZYAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAApQTq0hABLvkcWCYrAaRRPNDrECJGlF/11BYvG9+JJ9Y86nxnmQzPxtAAe1UgOsXAAADAAADAAADAAADAAADAAADAAADA/JHQQA5JhAAAMFcfgD/////////////////////////////////////////AAAB4AAAgMAKMQALKeERAAnxoQAAAAEJ8AAAAAFBnspFFSwv/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAADdRFmvrVE0KXDOGwWddlwYa1foib7tXZKmkua6R4APb4b8+tXwdSNNqgf2IVNwGTohgQAcMvp6SiQxpiQym4AAADAAADAANUNUAAAAMAAAMAAAMBN0dBADo8AP//////////////////////////////////////////////////////////////////////////////AAAB4AAAgIAFIQALDcEAAAABCfAAAAABAZ7pdEK/AAADAAADAAADAAADAAADAAADAAADAAADAFHTAfujIUaaLSuklb9y0/so9AEtQAqkAxOviALQZ5jNt/iOkABrCOZ4md0iUnFwAAADAAADAALwckAAAAMAAAMAAATcR0EAO0IQAADPbH4A//////////////////////////////////////////////////////////////////////////////8AAAHgAACAwAoxAAtGAREACynhAAAAAQnwAAAAAQGe62pCvwAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwBR6/L83y+WryR9gmVKPGbIhJpkgAFgHCej3gB6rAHPgHHAAAADAAADAAAYIV0AAAMAAAMAAAMABnxHQQA8UQD//////////////////////////////////////////////////////////////////////////////////////////////////////////wAAAeAAAIDACjEAC9KhEQALRgEAAAABCfAAAAABQZrwSahBbJlMCG///qeEAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAADAAAZ8UdBAD00EAAA3Xx+AP///////////////////////////////////////////////////////////wAAAeAAAIDACjEAC5phEQALYiEAAAABCfAAAAABQZ8ORRUsL/8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAA3URZr61RNClwzhI2ZXdRHYLZWc1yTgKRhTIXBNABHQKIIyYNyc+AaEn1jhATEAAAMAAAMAAAMAckkIAAADAAADAAADAEbBR0EAPkYA////////////////////////////////////////////////////////////////////////////////////////////AAAB4AAAgIAFIQALfkEAAAABCfAAAAABAZ8tdEK/AAADAAADAAADAAADAAADAAADAAADAAADAFHTAfujIUAYRtY0f/43cIs2OjxACR2hMR1QBGYX+34JGAAAAwAAAwAAAwKEJ6AAAAMAAAMAAAMA3oFHQQA/QhAAAOuMfgD//////////////////////////////////////////////////////////////////////////////wAAAeAAAIDACjEAC7aBEQALmmEAAAABCfAAAAABAZ8vakK/AAADAAADAAADAAADAAADAAADAAADAAADAFHr8vzfL5avJH2CZUo8ZsiEmmSAAWAcJ6PeAHqsAc+AccAAAAMAAAMAABghXQAAAwAAAwAAAwAGfEdBADBRAP//////////////////////////////////////////////////////////////////////////////////////////////////////////AAAB4AAAgMAKMQANQyERAAu2gQAAAAEJ8AAAAAFBmzRJqEFsmUwIZ//+nhAAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAGVAR0EAMTQQAAD5nH4A////////////////////////////////////////////////////////////AAAB4AAAgMAKMQANCuERAAvSoQAAAAEJ8AAAAAFBn1JFFSwv/wAAAwAAAwAAAwAAAwAAAwAAAwAAAwAADdRFmvrVE0KXDOEjZld1EdgtlZzXJOApGFMhcE0AEdAogjJg3Jz4BoSfWOEBMQAAAwAAAwAAAwBySQgAAAMAAAMAAAMARsFHQQAyRgD///////////////////////////////////////////////////////////////////////////////////////////8AAAHgAACAgAUhAAvuwQAAAAEJ8AAAAAEBn3F0Qr8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAUdMB+6MhQBhG1jR//jdwizY6PEAJHaExHVAEZhf7fgkYAAADAAADAAADAoQnoAAAAwAAAwAAAwDegEdBADNCEAABB6x+AP//////////////////////////////////////////////////////////////////////////////AAAB4AAAgMAKMQANJwERAA0K4QAAAAEJ8AAAAAEBn3NqQr8AAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAUevy/N8vlq8kfYJlSjxmyISaZIABYBwno94AeqwBz4BxwAAAAwAAAwAAGCFdAAADAAADAAADAAZ8R0EANFIA////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAB4AAAgMAKMQANs6ERAA0nAQAAAAEJ8AAAAAFBm3hJqEFsmUwIV//+OEAAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAAMAAYtHQQA1NBAAARW8fgD///////////////////////////////////////////////////////////8AAAHgAACAwAoxAA17YREADUMhAAAAAQnwAAAAAUGflkUVLC//AAADAAADAAADAAADAAADAAADAAADAAAN1EWa+tUTQpcM4SNmV3UR2C2VnNck4CkYUyFwTQAR0CiCMmDcnPgGhJ9Y4QExAAADAAADAAADAHJJCAAAAwAAAwAAAwBGwEdBADZGAP///////////////////////////////////////////////////////////////////////////////////////////wAAAeAAAICABSEADV9BAAAAAQnwAAAAAQGftXRCvwAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwBR0wH7oyFAGEbWNH/+N3CLNjo8QAkdoTEdUARmF/t+CRgAAAMAAAMAAAMChCegAAADAAADAAADAN6BR0EAN0IQAAEjzH4A//////////////////////////////////////////////////////////////////////////////8AAAHgAACAwAoxAA2XgREADXthAAAAAQnwAAAAAQGft2pCvwAAAwAAAwAAAwAAAwAAAwAAAwAAAwAAAwBR6/L83y+WryR9gmVKPGbIhJpkgAFgHCej3gB6rAHPgHHAAAADAAADAAAYIV0AAAMAAAMAAAMABn0=" - webUI["html/configuration.html"] = "PCFkb2N0eXBlIGh0bWw+CjxodG1sPgogIDxoZWFkPgogICAgPG1ldGEgY2hhcnNldD0idXRmLTgiPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiIC8+IAogICAgPHRpdGxlPnhUZVZlPC90aXRsZT4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL3NjcmVlbi5jc3MiIHR5cGU9InRleHQvY3NzIj4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL2Jhc2UuY3NzIiB0eXBlPSJ0ZXh0L2NzcyI+CiAgICA8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvY29uZmlndXJhdGlvbl90cy5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvbmV0d29ya190cy5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvbWVudV90cy5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvc2V0dGluZ3NfdHMuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBsYW5ndWFnZT0iamF2YXNjcmlwdCIgdHlwZT0idGV4dC9qYXZhc2NyaXB0IiBzcmM9ImpzL2Jhc2VfdHMuanMiPjwvc2NyaXB0PgogIDwvaGVhZD4KCiAgICA8Ym9keSBvbmxvYWQ9ImphdmFzY3JpcHQ6IHJlYWR5Rm9yQ29uZmlndXJhdGlvbigwKTsiPgogICAgICAgICAgCiAgICAgIDxkaXYgaWQ9ImxvYWRpbmciIGNsYXNzPSJibG9jayI+CiAgICAgICAgPGRpdiBjbGFzcz0ibG9hZGVyIj48L2Rpdj4KICAgICAgPC9kaXY+CgogICAgICA8ZGl2IGlkPSJoZWFkZXIiIGNsYXNzPSJpbWdDZW50ZXIiPjwvZGl2PgogICAgICA8ZGl2IGlkPSJib3giPgogICAgICAgIAogICAgICAgIDx0YWJsZSBpZD0iY2xpZW50SW5mbyIgY2xhc3M9InZpc2libGUiPgogICAgICAgICAgPHRyPgogICAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij5WZXJzaW9uOjwvdGQ+CiAgICAgICAgICAgIDx0ZCBpZD0idmVyc2lvbiIgY2xhc3M9InRkVmFsIj4mbmJzcDs8L3RkPgogICAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij5PUzo8L3RkPgogICAgICAgICAgICA8dGQgaWQ9Im9zIiBjbGFzcz0idGRWYWwiPiZuYnNwOzwvdGQ+CiAgICAgICAgICA8L3RyPgogICAgICAgICAgPHRyPgogICAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij5VVUlEOjwvdGQ+CiAgICAgICAgICAgIDx0ZCBpZD0idXVpZCIgY2xhc3M9InRkVmFsIj4mbmJzcDs8L3RkPgogICAgICAgICAgICA8dGQgY2xhc3M9InRkS2V5Ij5BcmNoOjwvdGQ+CiAgICAgICAgICAgIDx0ZCBpZD0iYXJjaCIgY2xhc3M9InRkVmFsIj4mbmJzcDs8L3RkPgogICAgICAgICAgPC90cj4KICAgICAgICAgIDx0cj4KICAgICAgICAgICAgPHRkIGNsYXNzPSJ0ZEtleSI+U3RyZWFtczo8L3RkPgogICAgICAgICAgICA8dGQgaWQ9InN0cmVhbXMiIGNsYXNzPSJ0ZFZhbCI+Jm5ic3A7PC90ZD4KICAgICAgICAgICAgPHRkIGNsYXNzPSJ0ZEtleSI+RFZSOjwvdGQ+CiAgICAgICAgICAgIDx0ZCBpZD0iRFZSIiBjbGFzcz0idGRWYWwiPiZuYnNwOzwvdGQ+CiAgICAgICAgICA8L3RyPgogICAgICAgIDwvdGFibGU+CiAgICAgICAgCiAgICAgICAgPGRpdiBpZD0iaGVhZGxpbmUiPgogICAgICAgICAgPGgxIGlkPSJoZWFkLXRleHQiIGNsYXNzPSJjZW50ZXIiPkNvbmZpZ3VyYXRpb248L2gxPiAgICAgIAogICAgICAgIDwvZGl2PgogICAgICAgIDxwIGlkPSJlcnIiIGNsYXNzPSJlcnJvck1zZyBjZW50ZXIiPjwvcD4gICAKICAgICAgICA8ZGl2IGlkPSJjb250ZW50Ij4KICAgICAgICAgICAgCiAgICAgICAgPC9kaXY+CiAgICAgICAgPGRpdiBpZD0iYm94LWZvb3RlciI+CiAgICAgICAgICA8aW5wdXQgaWQ9Im5leHQiIGNsYXNzPSIiIHR5cGU9ImJ1dHRvbiIgbmFtZT0ibmV4dCIgdmFsdWU9Ik5leHQiIG9uY2xpY2s9ImphdmFzY3JpcHQ6IHNhdmVXaXphcmQoKTsiPgogICAgICAgIDwvZGl2PgogICAgICA8L2Rpdj4KICAgIDwvYm9keT4KPC9odG1sPg==" - webUI["html/img/log.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0xMC0xNFQxMToxMDo0MjwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CkP32mEAAANASURBVGgF7ZlPiE1RHMffw1AYhiL5k1HEijJiYaFZiHoyFspW2RFRkkSZGgtFWJIwi9FYmo0VOywkKTbKgjSlWcifRCPX51dv6s2d33md77vvXjfmV9859/7u93x/v98959x73p1KRbAkSargAhgDH0E/qIYkuHYEvAPGvwbmNOEerXM/0Q6BRSFuZj/ix0DaDnvCkGppIucDAe4OhzvkcUO+GaELAf8ux7/b8Zlrr+Pvc3zm6nX8NccXdKmFLHaUPJ/Ruhyu5zNap8Nd6PiCLrUQTyi0Rjy/5/M0Zd+smB7M32XwtgBr07aC6yfSTs7XO77OALfH4VbgHsD/HLytVquJx4nyIdQFBsHftscksK5Z0sGhpuN8Or4Aa5sJFHjtO7G2MjKvvZjN1sglOpSlCMt9LrDZ4S4Hd0Qg24vrK+gAZbPtjMqTdFKhEdkIsYxFWP720JlioUK6pzDL41jtpRIqxOOWxecuB3fhRGT8E85YBK8VygI6GSRTCxlH3TaJgyw4O2678aCxO94LbNPovYDdmOrUukIBN/MqwjJEOwGPOHR31W4VONVCLEBR9lAJpBbSrYhn5K5R+quFnGUOr1ICtMIlxjz6XVb6qot9JeKvCPSAdlQJJHDtd8hOIN0wtRDLxx6Ntr0ulalTq1TJNyYzXUjj3SjD8X87Iva7uR8s5+2bi6FtX1oOgi8g2tSn1g2yPx+t3gIR/c90s1+C1vuO/YkxdWrdjxFtE2dE0VELWaqIZ+QuUfqrhZxmyKUvgEoyE1xizOR4YOI8plXXyAZEbYsyTJvXFsUW+x6wGUSbWogJ237rZHSEgojq1CooLT3MdCH6Pcu3xz8zIq0s9lvc2+sgz6dWH/rnQPB/jlybZGoh99hCHJqk0P6TD0jaI/4b7dVYeXVq2bemokyKpRZiHwWKMimWWshxhryjoEpOKXHUNbIN8WcUc5s2r8Vue7l9oAaiTS3EhDeB6EUYnUlGojq1MobLr3uokB/5hcys7OYWKuRl5nD5Cbi5uYXw0ntPHoay2S8Seuol5RZSJ0r/n/DEc/BdrN9kTZrH7BkwDspgwyQxW6uggU3nHnAXvAG/QZE2SrARsL8hJffwDxM0mNDPvT8IAAAAAElFTkSuQmCC" - webUI["html/img/m3u.png"] = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAsSwAALEsBpT2WqQAABCRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjI4ODwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+Mjg4PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NTA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjUwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0wNy0yOFQxOTowNzozMTwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CumjVbcAAAGWSURBVGgF7VoxTgJRFGTFaGKBFnbEcABjb0fiBego7D2ABYmn8ARKRWFNQ6gx4QRQGWJJoY2VhXGdl7Dkh7Dsx3ns3yXvJ5P97L6d92bmhwYqlcWK43gK5L2enP51NP8F7pN721wPnOITZx9qG6HxI8QIZO+9XCHeL+VQKKm8QMyxb6+iCpH528AQYs58xIQWknV8mhDxCjEXWWJCC8maT55fAmOIudpUXAYhMn8dGEHMTZqYsgiR+U+BAcTcrhNTJiEy/xHQg5jOqpjD1RsBP3+id8u3P8TUoij6SuoLIwRDfWOofjLYtteyHa1UfcvvcUT1jqpGauVuHnyAdragjv/TAkley3uhj9Y5ZhDQa2+Olgmhz4IygSWibChNZ4nQFioTWCLKhtJ0lghtoTKBJaJsKE1nidAWKhNYIsqG0nSWCG2hMoElomwoTWeJ0BYqE1giyobSdJYIbaEygSWibChNZ4nQFioTWCLKhtJ0biJzmi1/guXMrpDn/OegO3bXMuAH0TtgAvwARV3y57Q34AGoJkL+AErKZ9cqbH7AAAAAAElFTkSuQmCC" - webUI["html/img/x_white.png"] = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAA6ppVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxOC0xMS0xNVQxNzoxMToyNTwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjM8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6Q29tcHJlc3Npb24+NTwvdGlmZjpDb21wcmVzc2lvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MTQ0PC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xNDQ8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4yNTY8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFj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" - webUI["html/js/base.js"] = "dmFyIGNvbmZpZyAgICAgICAgPSBuZXcgT2JqZWN0KCk7CnZhciBtZW51ICAgICAgICAgID0gbmV3IE9iamVjdCgpOwp2YXIgc3ViTWVudSAgICAgICA9IG5ldyBPYmplY3QoKTsKdmFyIGFjdGl2ZVN0cmVhbXMgPSBuZXcgT2JqZWN0KCk7CnZhciB4RVBHICAgICAgICAgID0gbmV3IE9iamVjdCgpOwp2YXIgdXNlcnMgICAgICAgICA9IG5ldyBPYmplY3QoKTsKdmFyIGxvZyAgICAgICAgICAgPSBuZXcgT2JqZWN0KCk7CnZhciB1bmRvICAgICAgICAgID0gbmV3IE9iamVjdCgpOwp2YXIgd2ViU29ja2V0cyAgICA9IHRydWU7CnZhciBjbG9zZUxvZywgdmVyc2lvbiwgYWN0aXZlTWVudTsKdmFyIGNvbHVtblRvU29ydCAgPSAwCgoKaWYgKHdpbmRvdy5XZWJTb2NrZXQgPT09IHVuZGVmaW5lZCkgewogIGFsZXJ0KCJZb3VyIGJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBXZWJTb2NrZXRzIik7CiAgd2ViU29ja2V0cyA9IGZhbHNlOwp9IAoKZnVuY3Rpb24gcGFnZVJlYWR5KCkgewogIHZhciBkYXRhID0gbmV3IE9iamVjdCgpOwogIGRhdGFbImNtZCJdID0gImdldFNlcnZlckNvbmZpZyI7CiAgeFRlVmUoZGF0YSk7CiAgLy9zaG93TG9hZGluZ1NjcmVlbihmYWxzZSk7CgogIHZhciByZXNpemVIYW5kbGUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgib3BlblN0cmVhbXMiKTsKICB2YXIgYm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm15U3RyZWFtc0JveCIpOwogIHJlc2l6ZUhhbmRsZS5hZGRFdmVudExpc3RlbmVyKCJtb3VzZWRvd24iLCBpbml0aWFsaXNlUmVzaXplLCBmYWxzZSk7CgogIGZ1bmN0aW9uIGluaXRpYWxpc2VSZXNpemUoZSkgewogICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoIm1vdXNlbW92ZSIsIHN0YXJ0UmVzaXppbmcsIGZhbHNlKTsKICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJtb3VzZXVwIiwgc3RvcFJlc2l6aW5nLCBmYWxzZSk7CiAgfQoKICBmdW5jdGlvbiBzdGFydFJlc2l6aW5nKGUpIHsKICAgIGJveC5zdHlsZS5oZWlnaHQgPSAoZS5jbGllbnRZIC0gYm94Lm9mZnNldFRvcCkgKyAicHgiOwogICAgICAKICAgIHZhciBlbG0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiYWxsU3RyZWFtcyIpOwogICAgaWYgKGUuY2xpZW50WSA+IDEyMCkgewogICAgICBlbG0uY2xhc3NOYW1lID0gInZpc2libGUiOyAKICAgIH0gZWxzZSB7CiAgICAgIGVsbS5jbGFzc05hbWUgPSAibm90VmlzaWJsZSI7IAogICAgfQoKICAgIGNhbGN1bGF0ZVdyYXBwZXJIZWlnaHQoKTsKCiAgfQogIGZ1bmN0aW9uIHN0b3BSZXNpemluZyhlKSB7CiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBzdGFydFJlc2l6aW5nLCBmYWxzZSk7CiAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgc3RvcFJlc2l6aW5nLCBmYWxzZSk7CiAgICAgIGNhbGN1bGF0ZVdyYXBwZXJIZWlnaHQoKTsKICB9CgogIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCJyZXNpemUiLCBmdW5jdGlvbigpewogICAgY2FsY3VsYXRlV3JhcHBlckhlaWdodCgpOwogIH0sIHRydWUpOwp9CgoKZnVuY3Rpb24gZ2V0T2JqS2V5cyhvYmopIHsKICB2YXIga2V5cyA9IG5ldyBBcnJheSgpOwoKICBmb3IgKHZhciBpIGluIG9iaikgewogICAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eShpKSkgewogICAgICBrZXlzLnB1c2goaSk7CiAgICB9CiAgfQoKICByZXR1cm4ga2V5czsKfQoKCmZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQoaXRlbSkgewogIC8vY29uc29sZS5sb2coaXRlbSk7CiAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KGl0ZW1bIl9lbGVtZW50Il0pOwogIGlmIChpdGVtLmhhc093blByb3BlcnR5KCJfdGV4dCIpKSB7CiAgICAvL2VsZW1lbnQuaW5uZXJIVE1MID0gIjxwPiIgKyBpdGVtWyJfdGV4dCJdICsgIjwvcD4iOwogICAgZWxlbWVudC5pbm5lckhUTUwgPSBpdGVtWyJfdGV4dCJdOwogIH0KCiAgdmFyIGtleXMgPSBnZXRPYmpLZXlzKGl0ZW0pOwogIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewogICAgaWYgKGtleXNbaV0uY2hhckF0KDApICE9ICJfIikgewogICAgICAvL2NvbnNvbGUubG9nKGtleXNbaV0sIGl0ZW1ba2V5c1tpXV0pOwogICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShrZXlzW2ldLCBpdGVtW2tleXNbaV1dKTsKICAgIH0KICB9CgogIC8vY29uc29sZS5sb2coZWxlbWVudCk7CiAgcmV0dXJuIGVsZW1lbnQ7Cn0KCmZ1bmN0aW9uIG1vZGlmeU9wdGlvbihpZCwgb3B0aW9ucywgdmFsdWVzKSB7CiAgdmFyIHNlbGVjdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKTsKICBzZWxlY3QuaW5uZXJIVE1MID0gIiI7CgogIGZvciAodmFyIGkgPSAwOyBpIDwgb3B0aW9ucy5sZW5ndGg7IGkrKykgewogIAogICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJPUFRJT04iKQogIAogICAgZWxlbWVudC52YWx1ZSA9IHZhbHVlc1tpXTsKICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gb3B0aW9uc1tpXTsKCiAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCkuYXBwZW5kQ2hpbGQoZWxlbWVudCk7CiAgCiAgfQoKfQoKCmZ1bmN0aW9uIHN0YXJ0V2ViU29ja2V0KCkgewogIGlmICh3ZWJTb2NrZXRzID09IGZhbHNlKSB7CiAgICByZXR1cm47CiAgfQoKICAvL3dzLnNlbmQoJ3siY21kIjogImdldFNlcnZlckNvbmZpZzEifScpOwoKfQoKZnVuY3Rpb24gY2hlY2tFcnIob2JqKSB7CiAgLy9hbGVydChvYmpbImVyciJdKQogIC8vc2NyZWVuTG9nKG9ialsiZXJyIl0sICJlcnJvciIpCiAgY29uc29sZS5sb2cob2JqKTsKICB2YXIgbmV3T2JqID0gbmV3IE9iamVjdCgpOwogIHZhciBuZXdFcnIgPSBuZXcgT2JqZWN0KCk7CiAgbmV3RXJyWyJrZXkiXSAgID0gIkVycm9yIjsKICBuZXdFcnJbInZhbHVlIl0gPSBvYmpbImVyciJdOwogIG5ld0VyclsidHlwZSJdICA9ICJlcnJvciI7CgogIG5ld09ialswXSA9IG5ld0VycgogIHNob3dMb2cobmV3T2JqKTsKICByZXR1cm4KfQoKZnVuY3Rpb24gc2NyZWVuTG9nKG1zZywgbXNnVHlwZSwgc2hvdykgewogIHJldHVybgogIGNsZWFyVGltZW91dChjbG9zZUxvZykKICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNjcmVlbkxvZyIpOwogIHZhciBuZXdNc2cgPSBuZXcgT2JqZWN0KCk7CiAgCiAgbmV3TXNnWyJfZWxlbWVudCJdID0gIlAiOwogIAogIHN3aXRjaChtc2dUeXBlKSB7CiAgICBjYXNlICJlcnJvciI6ICAgbmV3TXNnWyJjbGFzcyJdID0gImVycm9yTXNnIjsgYnJlYWs7CiAgICBjYXNlICJ3YXJuaW5nIjogbmV3TXNnWyJjbGFzcyJdID0gIndhcm5pbmdNc2ciOyBicmVhazsKICAgIC8vZGVmYXVsdDogICAgICBuZXdNc2dbImNsYXNzIl0gPSAiaW5mb01zZyIKICB9CgogIG5ld01zZ1siX3RleHQiXSA9IG1zZzsKCiAgZGl2LmFwcGVuZENoaWxkKGNyZWF0ZUVsZW1lbnQobmV3TXNnKSk7CgogIGRpdi5zY3JvbGxUb3AgPSBkaXYuc2Nyb2xsSGVpZ2h0OwoKICBpZiAoc2hvdyA9PSBmYWxzZSkgewogICAgcmV0dXJuOwogIH0KCiAgZGl2LmNsYXNzTmFtZSA9ICIiCiAgY2xvc2VMb2cgPSBzZXRUaW1lb3V0KGNsb3NlU2NyZWVuTG9nLCAxMDAwMCk7Cn0KCgpmdW5jdGlvbiBjbG9zZVNjcmVlbkxvZygpIHsKICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNjcmVlbkxvZyIpOwogIGRpdi5jbGFzc05hbWUgPSAic2NyZWVuTG9nSGlkZGVuIgp9CgpmdW5jdGlvbiBzaG93U2NyZWVuTG9nKCkgewogIGNsZWFyVGltZW91dChjbG9zZUxvZykKICB2YXIgZGl2ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNjcmVlbkxvZyIpOwogIHZhciBjdXJyZW50Q2xhc3MgPSBkaXYuY2xhc3NOYW1lOwogIGRpdi5jbGFzc05hbWUgPSAic2NyZWVuTG9nSGlkZGVuIgoKICBzd2l0Y2goY3VycmVudENsYXNzKSB7CiAgICBjYXNlICJzY3JlZW5Mb2dIaWRkZW4iOiAgZGl2LmNsYXNzTmFtZSA9ICIiOyBicmVhazsgCiAgICBjYXNlICIiOiBkaXYuY2xhc3NOYW1lID0gInNjcmVlbkxvZ0hpZGRlbiI7IGJyZWFrOwogIH0KfQoKZnVuY3Rpb24gc2hvd0xvYWRpbmdTY3JlZW4oZWxtKSB7CiAgdmFyIGRpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJsb2FkaW5nIik7CiAgc3dpdGNoKGVsbSkgewogICAgY2FzZSB0cnVlOiBkaXYuY2xhc3NOYW1lID0gImJsb2NrIjsgYnJlYWs7CiAgICBjYXNlIGZhbHNlOiBkaXYuY2xhc3NOYW1lID0gIm5vbmUiOyBicmVhazsKCiAgICAvKgogICAgY2FzZSB0cnVlOiBkaXYuc3R5bGUuZGlzcGxheSA9ICJibG9jayI7IGJyZWFrOwogICAgY2FzZSBmYWxzZTogZGl2LnN0eWxlLmRpc3BsYXkgPSAibm9uZSI7IGJyZWFrOwogICAgKi8KICB9Cn0KCmZ1bmN0aW9uIGNyZWF0ZUNsaW50SW5mbyhvYmopIHsKICAvL2NvbnNvbGUubG9nKG9iaik7CiAgdmFyIGtleXMgPSBnZXRPYmpLZXlzKG9iaik7CiAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7CiAgICBpZihkb2N1bWVudC5nZXRFbGVtZW50QnlJZChrZXlzW2ldKSl7CiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGtleXNbaV0pLmlubmVySFRNTCA9IG9ialtrZXlzW2ldXTsKICAgIH0KICB9CiAgLy9kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiY2xpZW50SW5mbyIpLmNsYXNzTmFtZSA9ICJ2aXNpYmxlIjsKfQoKZnVuY3Rpb24gc2hvd0VsZW1lbnQoZWxtSUQsIHR5cGUpIHsKICBzd2l0Y2godHlwZSkgewogICAgY2FzZSB0cnVlOiAgY3NzQ2xhc3MgPSAiYmxvY2siOyBicmVhazsKICAgIGNhc2UgZmFsc2U6IGNzc0NsYXNzID0gIm5vbmUiOyBicmVhazsKICB9CgogIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGVsbUlEKS5jbGFzc05hbWUgPSBjc3NDbGFzczsKfSAKCmZ1bmN0aW9uIHNob3dQb3BVcEVsZW1lbnQoZWxtKSB7CiAgdmFyIGFsbEVsZW1lbnRzID0gbmV3IEFycmF5KCJkZWxldGVVc2VyRGV0YWlsIiwgIm1hcHBpbmctZGV0YWlsIiwgInVzZXItZGV0YWlsIiwgImZpbGUtZGV0YWlsIik7CgogIGZvciAodmFyIGkgPSAwOyBpIDwgYWxsRWxlbWVudHMubGVuZ3RoOyBpKyspIHsKICAgIHNob3dFbGVtZW50KGFsbEVsZW1lbnRzW2ldLCBmYWxzZSkKICB9CgogIHNob3dFbGVtZW50KGVsbSwgdHJ1ZSkKCiAgc2V0VGltZW91dChmdW5jdGlvbigpeyAKICAgIHNob3dFbGVtZW50KCJwb3B1cCIsIHRydWUpOwogIH0sIDEwKTsKfQoKICAvLyBib2R5Li4uCgpmdW5jdGlvbiBzaG93U3RyZWFtcyhmb3JjZSkgewoKICB2YXIgZWxtQm94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm15U3RyZWFtc0JveCIpOwogIHZhciBlbG0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiYWxsU3RyZWFtcyIpOwogIC8vY29uc29sZS5sb2coZWxtKTsKICBzaG93ID0gZWxtLmNsYXNzTmFtZTsKCiAgc3dpdGNoKGZvcmNlKSB7CiAgICBjYXNlIHRydWU6IHNob3cgPSAibm90VmlzaWJsZSI7IGJyZWFrOwogICAgY2FzZSBmYWxzZTogc2hvdyA9ICJ2aXNpYmxlIjsgYnJlYWs7CiAgfQoKICBzd2l0Y2goc2hvdykgewogICAgY2FzZSAibm90VmlzaWJsZSI6IAogICAgICBlbG0uY2xhc3NOYW1lID0gInZpc2libGUiOyAKICAgICAgZWxtQm94LnN0eWxlLmhlaWdodCA9ICIxMDBweCI7CiAgICAgIGJyZWFrOwoKICAgIGRlZmF1bHQ6IAogICAgICBlbG0uY2xhc3NOYW1lID0gIm5vdFZpc2libGUiOyAKICAgICAgZWxtQm94LnN0eWxlLmhlaWdodCA9ICIyMHB4IjsKICAgICAgYnJlYWs7CiAgfQoKICB2YXIgc2hvdyA9IGVsbS5zdHlsZS5kaXNwbGF5OyB7CiAgICAvL2NvbnNvbGUubG9nKGVsbS5zdHlsZS5kaXNwbGF5KTsKICB9CiAgCiAgY2FsY3VsYXRlV3JhcHBlckhlaWdodCgpOwp9CgpmdW5jdGlvbiB4dGV2ZUJhY2t1cCgpIHsKICBjb25zb2xlLmxvZygieHRldmVCYWNrdXAiKTsKICB2YXIgZGF0YSA9IG5ldyBPYmplY3QoKTsKICBkYXRhWyJjbWQiXSA9ICJ4dGV2ZUJhY2t1cCI7CgogIHhUZVZlKGRhdGEpOwp9CgpmdW5jdGlvbiB4dGV2ZVJlc3RvcmUoZWxtKSB7CiAgdmFyIHJlc3RvcmUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJJTlBVVCIpOwogIHJlc3RvcmUuc2V0QXR0cmlidXRlKCJ0eXBlIiwgImZpbGUiKTsKICByZXN0b3JlLnNldEF0dHJpYnV0ZSgiY2xhc3MiLCAibm90VmlzaWJsZSIpOwogIHJlc3RvcmUuc2V0QXR0cmlidXRlKCJuYW1lIiwgIiIpOwogIHJlc3RvcmUuaWQgPSAidXBsb2FkIjsKCiAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChyZXN0b3JlKTsKICByZXN0b3JlLmNsaWNrKCk7CgogIHJlc3RvcmUub25jaGFuZ2UgPSBmdW5jdGlvbigpIHsKICAgIHZhciBmaWxlbmFtZSA9IHJlc3RvcmUuZmlsZXNbMF0ubmFtZQogICAgLy9jb25zb2xlLmxvZyhyZXN0b3JlLnNyY0VsZW1lbnQuZmlsZXNbMF0pOwogICAgdmFyIGNoZWNrID0gY29uZmlybSgiRmlsZTogIiArIGZpbGVuYW1lICsgIlxuQWxsIGRhdGEgd2lsbCBiZSByZXBsYWNlZCB3aXRoIHRob3NlIGZyb20gdGhlIGJhY2t1cC5cblNob3VsZCB0aGUgZmlsZXMgYmUgcmVzdG9yZWQ/Iik7IAogICAgaWYgKGNoZWNrID09IHRydWUpIHsKICAgICAgdmFyIHJlYWRlciAgPSBuZXcgRmlsZVJlYWRlcigpOwogICAgICB2YXIgZmlsZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2lucHV0W3R5cGU9ZmlsZV0nKS5maWxlc1swXTsKICAgICAgaWYgKGZpbGUpIHsKICAgICAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlKTsKICAgICAgICByZWFkZXIub25sb2FkID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICBjb25zb2xlLmxvZyhyZWFkZXIucmVzdWx0KTsKICAgICAgICAgIHZhciBkYXRhID0gbmV3IE9iamVjdCgpOwogICAgICAgICAgZGF0YVsiY21kIl0gICAgID0gInh0ZXZlUmVzdG9yZSIKICAgICAgICAgIGRhdGFbImJhc2U2NCJdICA9IHJlYWRlci5yZXN1bHQKCiAgICAgICAgICB4VGVWZShkYXRhKTsKICAgICAgICAgIHJldHVybgogICAgICAgIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYWxlcnQoIkZpbGUgY291bGQgbm90IGJlIGxvYWRlZCIpCiAgICAgIH0KICAgIH0KICB9Owp9CgpmdW5jdGlvbiBnZXRCYXNlNjQoZmlsZSkgewogICB2YXIgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTsKICAgcmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZSk7CiAgIHJlYWRlci5vbmxvYWQgPSBmdW5jdGlvbigpIHsKICAgICBjb25zb2xlLmxvZyhyZWFkZXIucmVzdWx0KTsKICAgfTsKICAgcmVhZGVyLm9uZXJyb3IgPSBmdW5jdGlvbihlcnJvcikgewogICAgIGNvbnNvbGUubG9nKCdFcnJvcjogJywgZXJyb3IpOwogICB9Owp9CgpmdW5jdGlvbiBsb2dvdXQoKSB7CiAgZG9jdW1lbnQuY29va2llLnNwbGl0KCc7JykuZm9yRWFjaChmdW5jdGlvbihjKSB7CiAgICBkb2N1bWVudC5jb29raWUgPSBjLnRyaW0oKS5zcGxpdCgnPScpWzBdICsgJz07JyArICdleHBpcmVzPVRodSwgMDEgSmFuIDE5NzAgMDA6MDA6MDAgVVRDOyc7CiAgfSk7CiAgbG9jYXRpb24ucmVsb2FkKCk7Cn0KCmZ1bmN0aW9uIGdldENvb2tpZShuYW1lKSB7CiAgdmFyIHZhbHVlID0gIjsgIiArIGRvY3VtZW50LmNvb2tpZTsKICB2YXIgcGFydHMgPSB2YWx1ZS5zcGxpdCgiOyAiICsgbmFtZSArICI9Iik7CiAgaWYgKHBhcnRzLmxlbmd0aCA9PSAyKSByZXR1cm4gcGFydHMucG9wKCkuc3BsaXQoIjsiKS5zaGlmdCgpOwp9CgpmdW5jdGlvbiBzZXRDb29raWUodG9rZW4pIHsKICAvL2NvbnNvbGUubG9nKHRva2VuKTsKICBkb2N1bWVudC5jb29raWUgPSAiVG9rZW49IiArIHRva2VuCn0KCg==" - webUI["html/js/logs_ts.js"] = "dmFyIExvZyA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHsKICAgIGZ1bmN0aW9uIExvZygpIHsKICAgIH0KICAgIExvZy5wcm90b3R5cGUuY3JlYXRlTG9nID0gZnVuY3Rpb24gKGVudHJ5KSB7CiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJQUkUiKTsKICAgICAgICBpZiAoZW50cnkuaW5kZXhPZigiV0FSTklORyIpICE9IC0xKSB7CiAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gIndhcm5pbmdNc2ciOwogICAgICAgIH0KICAgICAgICBpZiAoZW50cnkuaW5kZXhPZigiRVJST1IiKSAhPSAtMSkgewogICAgICAgICAgICBlbGVtZW50LmNsYXNzTmFtZSA9ICJlcnJvck1zZyI7CiAgICAgICAgfQogICAgICAgIGlmIChlbnRyeS5pbmRleE9mKCJERUJVRyIpICE9IC0xKSB7CiAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gImRlYnVnTXNnIjsKICAgICAgICB9CiAgICAgICAgZWxlbWVudC5pbm5lckhUTUwgPSBlbnRyeTsKICAgICAgICByZXR1cm4gZWxlbWVudDsKICAgIH07CiAgICByZXR1cm4gTG9nOwp9KCkpOwpmdW5jdGlvbiBzaG93TG9ncyhib3R0b20pIHsKICAgIHZhciBsb2cgPSBuZXcgTG9nKCk7CiAgICB2YXIgbG9ncyA9IFNFUlZFUlsibG9nIl1bImxvZyJdOwogICAgdmFyIGRpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJjb250ZW50X2xvZyIpOwogICAgZGl2LmlubmVySFRNTCA9ICIiOwogICAgdmFyIGtleXMgPSBnZXRPYmpLZXlzKGxvZ3MpOwogICAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChsb2dJRCkgewogICAgICAgIHZhciBlbnRyeSA9IGxvZy5jcmVhdGVMb2cobG9nc1tsb2dJRF0pOwogICAgICAgIGRpdi5hcHBlbmQoZW50cnkpOwogICAgfSk7CiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsKICAgICAgICBpZiAoYm90dG9tID09IHRydWUpIHsKICAgICAgICAgICAgdmFyIHdyYXBwZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiYm94LXdyYXBwZXIiKTsKICAgICAgICAgICAgd3JhcHBlci5zY3JvbGxUb3AgPSB3cmFwcGVyLnNjcm9sbEhlaWdodDsKICAgICAgICB9CiAgICB9LCAxMCk7Cn0KZnVuY3Rpb24gcmVzZXRMb2dzKCkgewogICAgdmFyIGNtZCA9ICJyZXNldExvZ3MiOwogICAgdmFyIGRhdGEgPSBuZXcgT2JqZWN0KCk7CiAgICB2YXIgc2VydmVyID0gbmV3IFNlcnZlcihjbWQpOwogICAgc2VydmVyLnJlcXVlc3QoZGF0YSk7Cn0K" - webUI["html/maintenance.html"] = "PCFkb2N0eXBlIGh0bWw+CjxodG1sPgogIDxoZWFkPgogICAgPG1ldGEgY2hhcnNldD0idXRmLTgiPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiIC8+IAogICAgPHRpdGxlPnhUZVZlPC90aXRsZT4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL3NjcmVlbi5jc3MiIHR5cGU9InRleHQvY3NzIj4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL2Jhc2UuY3NzIiB0eXBlPSJ0ZXh0L2NzcyI+CiAgPC9oZWFkPgoKICAgIDxib2R5PgogICAgICAgICAgCiAgICAgIDxkaXYgaWQ9ImhlYWRlciIgY2xhc3M9ImltZ0NlbnRlciI+PC9kaXY+CgogICAgICA8ZGl2IGlkPSJib3giPgoKICAgICAgICA8ZGl2IGlkPSJoZWFkbGluZSI+CiAgICAgICAgICA8aDEgaWQ9ImhlYWQtdGV4dCIgY2xhc3M9ImNlbnRlciI+TWFpbnRlbmFuY2U8L2gxPiAgICAgIAogICAgICAgIDwvZGl2PiAgCgogICAgICAgIDxkaXYgaWQ9ImNvbnRlbnQiPgogICAgICAgICAgeFRlVmUgaXMgdXBkYXRpbmcgdGhlIGRhdGFiYXNlLCBwbGVhc2UgdHJ5IGFnYWluIGxhdGVyLgogICAgICAgIDwvZGl2PgoKICAgICAgICA8ZGl2IGlkPSJib3gtZm9vdGVyIj48L2Rpdj4KICAgICAgICAKICAgICAgPC9kaXY+CgogICAgPC9ib2R5Pgo8L2h0bWw+" - webUI["html/create-first-user.html"] = "PCFkb2N0eXBlIGh0bWw+CjxodG1sPgogIDxoZWFkPgogICAgPG1ldGEgY2hhcnNldD0idXRmLTgiPgogICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjAiIC8+IAogICAgPHRpdGxlPnhUZVZlPC90aXRsZT4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL3NjcmVlbi5jc3MiIHR5cGU9InRleHQvY3NzIj4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL2Jhc2UuY3NzIiB0eXBlPSJ0ZXh0L2NzcyI+CiAgICA8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvbmV0d29ya190cy5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IGxhbmd1YWdlPSJqYXZhc2NyaXB0IiB0eXBlPSJ0ZXh0L2phdmFzY3JpcHQiIHNyYz0ianMvYXV0aGVudGljYXRpb25fdHMuanMiPjwvc2NyaXB0PgogIDwvaGVhZD4KCiAgICA8Ym9keT4KICAgICAgICAgIAogICAgICA8ZGl2IGlkPSJoZWFkZXIiIGNsYXNzPSJpbWdDZW50ZXIiPjwvZGl2PgoKICAgICAgPGRpdiBpZD0iYm94Ij4KCiAgICAgICAgPGRpdiBpZD0iaGVhZGxpbmUiPgogICAgICAgICAgPGgxIGlkPSJoZWFkLXRleHQiIGNsYXNzPSJjZW50ZXIiPnt7LmFjY291bnQuaGVhZGxpbmV9fTwvaDE+CiAgICAgICAgPC9kaXY+CgogICAgICAgIDxwIGlkPSJlcnIiIGNsYXNzPSJlcnJvck1zZyBjZW50ZXIiPjwvcD4KCiAgICAgICAgPGRpdiBpZD0iY29udGVudCI+CgogICAgICAgICAgICA8Zm9ybSBpZD0iYXV0aGVudGljYXRpb24iIGFjdGlvbj0iIiBtZXRob2Q9InBvc3QiPgoKICAgICAgICAgICAgICA8aDU+e3suYWNjb3VudC51c2VybmFtZS50aXRsZX19OjwvaDU+CiAgICAgICAgICAgICAgPGlucHV0IGlkPSJ1c2VybmFtZSIgdHlwZT0idGV4dCIgbmFtZT0idXNlcm5hbWUiIHBsYWNlaG9sZGVyPSJVc2VybmFtZSIgdmFsdWU9IiI+CiAgICAgICAgICAgICAgPGg1Pnt7LmFjY291bnQucGFzc3dvcmQudGl0bGV9fTo8L2g1PgogICAgICAgICAgICAgIDxpbnB1dCBpZD0icGFzc3dvcmQiIHR5cGU9InBhc3N3b3JkIiBuYW1lPSJwYXNzd29yZCIgcGxhY2Vob2xkZXI9IlBhc3N3b3JkIiB2YWx1ZT0iIj4KICAgICAgICAgICAgICA8aDU+e3suYWNjb3VudC5jb25maXJtLnRpdGxlfX06PC9oNT4KICAgICAgICAgICAgICA8aW5wdXQgaWQ9ImNvbmZpcm0iICB0eXBlPSJwYXNzd29yZCIgbmFtZT0iY29uZmlybSIgIHBsYWNlaG9sZGVyPSJDb25maXJtIiB2YWx1ZT0iIj4KICAgICAgICAgICAgICAKICAgICAgICAgICAgPC9mb3JtPgoKICAgICAgICA8L2Rpdj4KICAgICAgICAKICAgICAgICA8ZGl2IGlkPSJib3gtZm9vdGVyIj4KICAgICAgICAgIDxpbnB1dCBpZD0ic3VibWl0IiBjbGFzcz0iIiB0eXBlPSJidXR0b24iIHZhbHVlPSJ7ey5idXR0b24uY3JhZXRlQWNjb3VudH19IiBvbmNsaWNrPSJqYXZhc2NyaXB0OiBsb2dpbigpOyI+CiAgICAgICAgPC9kaXY+CiAgICAgIAogICAgICAgIAogICAgICA8L2Rpdj4KICAgIDwvYm9keT4KPC9odG1sPg==" } diff --git a/src/webserver.go b/src/webserver.go index 9e519cb..436c2df 100644 --- a/src/webserver.go +++ b/src/webserver.go @@ -1,6 +1,7 @@ package src import ( + "context" "encoding/json" "errors" "fmt" @@ -9,16 +10,20 @@ import ( "os" "strconv" "strings" + "time" "xteve/src/internal/authentication" "github.com/gorilla/websocket" + "github.com/samber/lo" ) -// StartWebserver : Startet den Webserver -func StartWebserver() (err error) { +// webAlerts channel to send to client +var webAlerts = make(chan string, 3) +var restartWebserver = make(chan bool, 1) - var port = Settings.Port +// StartWebserver : Start the Webserver +func StartWebserver() (err error) { http.HandleFunc("/", Index) http.HandleFunc("/stream/", Stream) @@ -30,31 +35,70 @@ func StartWebserver() (err error) { http.HandleFunc("/api/", API) http.HandleFunc("/images/", Images) http.HandleFunc("/data_images/", DataImages) + // http.HandleFunc("/auto/", Auto) - //http.HandleFunc("/auto/", Auto) + for { - showInfo("DVR IP:" + System.IPAddress + ":" + Settings.Port) + showInfo("Web server:" + "Starting") - var ips = len(System.IPAddressesV4) + len(System.IPAddressesV6) - 1 - switch ips { + showInfo("DVR IP:" + Settings.HostIP + ":" + Settings.Port) - case 0: - showHighlight(fmt.Sprintf("Web Interface:%s://%s:%s/web/", System.ServerProtocol.WEB, System.IPAddress, Settings.Port)) + var ips = len(System.IPAddressesV4) + len(System.IPAddressesV6) - 1 + switch ips { - case 1: - showHighlight(fmt.Sprintf("Web Interface:%s://%s:%s/web/ | xTeVe is also available via the other %d IP.", System.ServerProtocol.WEB, System.IPAddress, Settings.Port, ips)) + case 0: + showHighlight(fmt.Sprintf("Web Interface:%s://%s:%s/web/", System.ServerProtocol.WEB, Settings.HostIP, Settings.Port)) - default: - showHighlight(fmt.Sprintf("Web Interface:%s://%s:%s/web/ | xTeVe is also available via the other %d IP's.", System.ServerProtocol.WEB, System.IPAddress, Settings.Port, len(System.IPAddressesV4)+len(System.IPAddressesV6)-1)) + case 1: + showHighlight(fmt.Sprintf("Web Interface:%s://%s:%s/web/ | xTeVe is also available via the other %d IP.", System.ServerProtocol.WEB, Settings.HostIP, Settings.Port, ips)) - } + default: + showHighlight(fmt.Sprintf("Web Interface:%s://%s:%s/web/ | xTeVe is also available via the other %d IP's.", System.ServerProtocol.WEB, Settings.HostIP, Settings.Port, len(System.IPAddressesV4)+len(System.IPAddressesV6)-1)) - if err = http.ListenAndServe(":"+port, nil); err != nil { - ShowError(err, 1001) - return + } + + var port = Settings.Port + server := http.Server{Addr: ":" + port} + + go func() { + var err error + + if Settings.TLSMode { + if !allFilesExist(System.File.ServerCertPrivKey, System.File.ServerCert) { + if err = genCertFiles(); err != nil { + ShowError(err, 7000) + } + } + + err = server.ListenAndServeTLS(System.File.ServerCert, System.File.ServerCertPrivKey) + if err != nil && err != http.ErrServerClosed { + ShowError(err, 1017) + err = server.ListenAndServe() + } + } else { + err = server.ListenAndServe() + } + + if err != nil && err != http.ErrServerClosed { + ShowError(err, 1001) + return + } + }() + + <-restartWebserver + showInfo("Web server:" + "Restarting") + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + if err = server.Shutdown(ctx); err != nil { + ShowError(err, 1016) + return + } + + <-ctx.Done() + showInfo("Web server:" + "Stopped") } - return } // Index : Web Server / @@ -71,6 +115,11 @@ func Index(w http.ResponseWriter, r *http.Request) { showDebug(debug, 2) switch path { + case "/favicon.ico": + if value, ok := webUI["html"+path].(string); ok { + response = []byte(GetHTMLString(value)) + w.Header().Set("Content-Type", "image/x-icon") + } case "/discover.json": response, err = getDiscover() @@ -81,7 +130,7 @@ func Index(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") case "/lineup.json": - if Settings.AuthenticationPMS == true { + if Settings.AuthenticationPMS { _, err := basicAuth(r, "authentication.pms") if err != nil { @@ -114,7 +163,6 @@ func Index(w http.ResponseWriter, r *http.Request) { httpStatusError(w, r, 500) - return } // Stream : Web Server /stream/ @@ -142,12 +190,12 @@ func Stream(w http.ResponseWriter, r *http.Request) { showInfo(fmt.Sprintf("Buffer:false [%s]", Settings.Buffer)) case "xteve": - if strings.Index(streamInfo.URL, "rtsp://") != -1 || strings.Index(streamInfo.URL, "rtp://") != -1 { + if strings.Contains(streamInfo.URL, "rtsp://") || strings.Contains(streamInfo.URL, "rtp://") { err = errors.New("RTSP and RTP streams are not supported") ShowError(err, 2004) showInfo("Streaming URL:" + streamInfo.URL) - http.Redirect(w, r, streamInfo.URL, 302) + http.Redirect(w, r, streamInfo.URL, http.StatusFound) showInfo("Streaming Info:URL was passed to the client") return @@ -167,12 +215,12 @@ func Stream(w http.ResponseWriter, r *http.Request) { showInfo(fmt.Sprintf("Channel Name:%s", streamInfo.Name)) showInfo(fmt.Sprintf("Client User-Agent:%s", r.Header.Get("User-Agent"))) - // Prüfen ob der Buffer verwendet werden soll + // Check whether the Buffer should be used switch Settings.Buffer { case "-": showInfo("Streaming URL:" + streamInfo.URL) - http.Redirect(w, r, streamInfo.URL, 302) + http.Redirect(w, r, streamInfo.URL, http.StatusFound) showInfo("Streaming Info:URL was passed to the client.") showInfo("Streaming Info:xTeVe is no longer involved, the client connects directly to the streaming server.") @@ -182,10 +230,9 @@ func Stream(w http.ResponseWriter, r *http.Request) { } - return } -// Auto : HDHR routing (wird derzeit nicht benutzt) +// Auto : HDHR routing (is currently not used) func Auto(w http.ResponseWriter, r *http.Request) { var channelID = strings.Replace(r.RequestURI, "/auto/v", "", 1) @@ -207,10 +254,9 @@ func Auto(w http.ResponseWriter, r *http.Request) { } */ - return } -// xTeVe : Web Server /xmltv/ und /m3u/ +// xTeVe : Web Server /xmltv/ and /m3u/ func xTeVe(w http.ResponseWriter, r *http.Request) { var requestType, groupTitle, file, content, contentType string @@ -220,7 +266,7 @@ func xTeVe(w http.ResponseWriter, r *http.Request) { setGlobalDomain(r.Host) - // XMLTV Datei + // XMLTV File if strings.Contains(path, "xmltv/") { requestType = "xml" @@ -235,15 +281,15 @@ func xTeVe(w http.ResponseWriter, r *http.Request) { } - // M3U Datei + // M3U File if strings.Contains(path, "m3u/") { requestType = "m3u" groupTitle = r.URL.Query().Get("group-title") - if System.Dev == false { - // false: Dateiname wird im Header gesetzt - // true: M3U wird direkt im Browser angezeigt + if !System.Dev { + // false: File name is set in the header + // true: M3U is displayed directly in the browser w.Header().Set("Content-Disposition", "attachment; filename="+getFilenameFromPath(path)) } @@ -258,7 +304,7 @@ func xTeVe(w http.ResponseWriter, r *http.Request) { } - // Authentifizierung überprüfen + // Check Authentication err = urlAuth(r, requestType) if err != nil { ShowError(err, 000) @@ -277,7 +323,6 @@ func xTeVe(w http.ResponseWriter, r *http.Request) { w.Write([]byte(content)) } - return } // Images : Image Cache /images/ @@ -297,10 +342,9 @@ func Images(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) w.Write(content) - return } -// DataImages : Image Pfad für Logos / Bilder die hochgeladen wurden /data_images/ +// DataImages : Image path for Logos / Images that have been uploaded / data_images / func DataImages(w http.ResponseWriter, r *http.Request) { var path = strings.TrimPrefix(r.URL.Path, "/") @@ -317,7 +361,6 @@ func DataImages(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) w.Write(content) - return } // WS : Web Sockets /ws/ @@ -329,31 +372,40 @@ func WS(w http.ResponseWriter, r *http.Request) { var newToken string - /* - if r.Header.Get("Origin") != "http://"+r.Host { - httpStatusError(w, r, 403) - return - } - */ + // if r.Header.Get("Origin") != "http://" + r.Host { + // httpStatusError(w, r, 403) + // return + // } + + u := websocket.Upgrader{ReadBufferSize: 1024, WriteBufferSize: 1024} + + conn, err := u.Upgrade(w, r, w.Header()) - conn, err := websocket.Upgrade(w, r, w.Header(), 1024, 1024) if err != nil { ShowError(err, 0) http.Error(w, "Could not open websocket connection", http.StatusBadRequest) return } + defer conn.Close() setGlobalDomain(r.Host) for { + select { + case response.Alert = <-webAlerts: + // + default: + // + } + err = conn.ReadJSON(&request) if err != nil { return } - if System.ConfigurationWizard == false { + if !System.ConfigurationWizard { switch Settings.AuthenticationWEB { @@ -392,77 +444,116 @@ func WS(w http.ResponseWriter, r *http.Request) { } switch request.Cmd { - // Daten lesen + // Read Data case "getServerConfig": - //response.Config = Settings + // response.Config = Settings case "updateLog": response = setDefaultResponseData(response, false) if err = conn.WriteJSON(response); err != nil { ShowError(err, 1022) - } else { - return - break } return case "loadFiles": - //response.Response = Settings.Files + // response.Response = Settings.Files - // Daten schreiben + // Save Data case "saveSettings": var authenticationUpdate = Settings.AuthenticationWEB + var previousTLSMode = Settings.TLSMode + var previousHostIP = Settings.HostIP + var previousHostName = Settings.HostName + var previousStoreBufferInRAM = Settings.StoreBufferInRAM + var previousClearXMLTVCache = Settings.ClearXMLTVCache + response.Settings, err = updateServerSettings(request) if err == nil { - response.OpenMenu = strconv.Itoa(indexOfString("settings", System.WEB.Menu)) + response.OpenMenu = strconv.Itoa(lo.IndexOf(System.WEB.Menu, "settings")) - if Settings.AuthenticationWEB == true && authenticationUpdate == false { + if Settings.AuthenticationWEB && !authenticationUpdate { response.Reload = true } + if Settings.TLSMode != previousTLSMode { + showInfo("Web server:" + "Toggling TLS mode") + + reinitialize() + + response.OpenLink = System.URLBase + "/web/" + restartWebserver <- true + } + + if Settings.HostIP != previousHostIP { + showInfo("Web server:" + fmt.Sprintf("Changing host IP to %s", Settings.HostIP)) + + reinitialize() + + response.OpenLink = System.URLBase + "/web/" + restartWebserver <- true + } + + if Settings.HostName != previousHostName { + Settings.HostIP = previousHostName + showInfo("Web server:" + fmt.Sprintf("Changing host name to %s", Settings.HostName)) + + reinitialize() + + response.OpenLink = System.URLBase + "/web/" + restartWebserver <- true + } + + if Settings.StoreBufferInRAM != previousStoreBufferInRAM { + initBufferVFS(Settings.StoreBufferInRAM) + } + + if Settings.ClearXMLTVCache && !previousClearXMLTVCache { + clearXMLTVCache() + } + } case "saveFilesM3U": err = saveFiles(request, "m3u") if err == nil { - response.OpenMenu = strconv.Itoa(indexOfString("playlist", System.WEB.Menu)) + response.OpenMenu = strconv.Itoa(lo.IndexOf(System.WEB.Menu, "playlist")) } case "updateFileM3U": err = updateFile(request, "m3u") if err == nil { - response.OpenMenu = strconv.Itoa(indexOfString("playlist", System.WEB.Menu)) + response.OpenMenu = strconv.Itoa(lo.IndexOf(System.WEB.Menu, "playlist")) } case "saveFilesHDHR": err = saveFiles(request, "hdhr") if err == nil { - response.OpenMenu = strconv.Itoa(indexOfString("playlist", System.WEB.Menu)) + response.OpenMenu = strconv.Itoa(lo.IndexOf(System.WEB.Menu, "playlist")) } case "updateFileHDHR": err = updateFile(request, "hdhr") if err == nil { - response.OpenMenu = strconv.Itoa(indexOfString("playlist", System.WEB.Menu)) + response.OpenMenu = strconv.Itoa(lo.IndexOf(System.WEB.Menu, "playlist")) } case "saveFilesXMLTV": err = saveFiles(request, "xmltv") if err == nil { - response.OpenMenu = strconv.Itoa(indexOfString("xmltv", System.WEB.Menu)) + response.OpenMenu = strconv.Itoa(lo.IndexOf(System.WEB.Menu, "xmltv")) } case "updateFileXMLTV": err = updateFile(request, "xmltv") if err == nil { - response.OpenMenu = strconv.Itoa(indexOfString("xmltv", System.WEB.Menu)) + response.OpenMenu = strconv.Itoa(lo.IndexOf(System.WEB.Menu, "xmltv")) } case "saveFilter": response.Settings, err = saveFilter(request) if err == nil { - response.OpenMenu = strconv.Itoa(indexOfString("filter", System.WEB.Menu)) + response.OpenMenu = strconv.Itoa(lo.IndexOf(System.WEB.Menu, "filter")) } case "saveEpgMapping": @@ -471,20 +562,20 @@ func WS(w http.ResponseWriter, r *http.Request) { case "saveUserData": err = saveUserData(request) if err == nil { - response.OpenMenu = strconv.Itoa(indexOfString("users", System.WEB.Menu)) + response.OpenMenu = strconv.Itoa(lo.IndexOf(System.WEB.Menu, "users")) } case "saveNewUser": err = saveNewUser(request) if err == nil { - response.OpenMenu = strconv.Itoa(indexOfString("users", System.WEB.Menu)) + response.OpenMenu = strconv.Itoa(lo.IndexOf(System.WEB.Menu, "users")) } case "resetLogs": WebScreenLog.Log = make([]string, 0) WebScreenLog.Errors = 0 WebScreenLog.Warnings = 0 - response.OpenMenu = strconv.Itoa(indexOfString("log", System.WEB.Menu)) + response.OpenMenu = strconv.Itoa(lo.IndexOf(System.WEB.Menu, "log")) case "xteveBackup": file, errNew := xteveBackup() @@ -550,17 +641,16 @@ func WS(w http.ResponseWriter, r *http.Request) { } - /* - case "wizardCompleted": - System.ConfigurationWizard = false - response.Reload = true - */ + // case "wizardCompleted": + // System.ConfigurationWizard = false + // response.Reload = true + default: fmt.Println("+ + + + + + + + + + +", request.Cmd) var requestMap = make(map[string]interface{}) // Debug _ = requestMap - if System.Dev == true { + if System.Dev { fmt.Println(mapToJSON(requestMap)) } @@ -573,7 +663,7 @@ func WS(w http.ResponseWriter, r *http.Request) { } response = setDefaultResponseData(response, true) - if System.ConfigurationWizard == true { + if System.ConfigurationWizard { response.ConfigurationWizard = System.ConfigurationWizard } @@ -585,7 +675,6 @@ func WS(w http.ResponseWriter, r *http.Request) { } - return } // Web : Web Server /web/ @@ -601,7 +690,7 @@ func Web(w http.ResponseWriter, r *http.Request) { setGlobalDomain(r.Host) - if System.Dev == true { + if System.Dev { lang, err = loadJSONFileToMap(fmt.Sprintf("html/lang/%s.json", Settings.Language)) if err != nil { @@ -665,7 +754,7 @@ func Web(w http.ResponseWriter, r *http.Request) { confirm = r.FormValue("confirm") } - // Erster Benutzer wird angelegt (Passwortbestätigung ist vorhanden) + // First user is created (Password confirmation is available) if len(confirm) > 0 { var token, err = createFirstUserForAuthentication(username, password) @@ -673,14 +762,14 @@ func Web(w http.ResponseWriter, r *http.Request) { httpStatusError(w, r, 429) return } - // Redirect, damit die Daten aus dem Browser gelöscht werden. + // Redirect so that the Data is deleted from the Browser. w = authentication.SetCookieToken(w, token) - http.Redirect(w, r, "/web", 301) + http.Redirect(w, r, "/web", http.StatusMovedPermanently) return } - // Benutzername und Passwort vorhanden, wird jetzt überprüft + // Username and Password available, will now be checked if len(username) > 0 && len(password) > 0 { var token, err = authentication.UserAuthentication(username, password) @@ -691,11 +780,11 @@ func Web(w http.ResponseWriter, r *http.Request) { } w = authentication.SetCookieToken(w, token) - http.Redirect(w, r, "/web", 301) // Redirect, damit die Daten aus dem Browser gelöscht werden. + http.Redirect(w, r, "/web", http.StatusMovedPermanently) // Redirect so that the Data is deleted from the Browser. } else { w = authentication.SetCookieToken(w, "-") - http.Redirect(w, r, "/web", 301) // Redirect, damit die Daten aus dem Browser gelöscht werden. + http.Redirect(w, r, "/web", http.StatusMovedPermanently) // Redirect so that the Data is deleted from the Browser. } return @@ -724,7 +813,7 @@ func Web(w http.ResponseWriter, r *http.Request) { return } - if len(allUserData) == 0 && Settings.AuthenticationWEB == true { + if len(allUserData) == 0 && Settings.AuthenticationWEB { file = requestFile + "create-first-user.html" } @@ -732,9 +821,9 @@ func Web(w http.ResponseWriter, r *http.Request) { requestFile = file - if value, ok := webUI[requestFile]; ok { + if _, ok := webUI[requestFile]; ok { - content = GetHTMLString(value.(string)) + //content = GetHTMLString(value.(string)) if contentType == "text/plain" { w.Header().Set("Content-Disposition", "attachment; filename="+getFilenameFromPath(requestFile)) @@ -749,7 +838,6 @@ func Web(w http.ResponseWriter, r *http.Request) { } if value, ok := webUI[requestFile].(string); ok { - content = GetHTMLString(value) contentType = getContentType(requestFile) @@ -764,8 +852,8 @@ func Web(w http.ResponseWriter, r *http.Request) { contentType = getContentType(requestFile) - if System.Dev == true { - // Lokale Webserver Dateien werden geladen, nur für die Entwicklung + if System.Dev { + // Local web server Files are loaded, only for Development content, _ = readStringFromFile(requestFile) } @@ -783,37 +871,37 @@ func Web(w http.ResponseWriter, r *http.Request) { func API(w http.ResponseWriter, r *http.Request) { /* - API Bedingungen (ohne Authentifizierung): - - API muss in den Einstellungen aktiviert sein + API conditions (without Authentication): + - API must be activated in the Settings - Beispiel API Request mit curl + Example API Request with curl Status: curl -X POST -H "Content-Type: application/json" -d '{"cmd":"status"}' http://localhost:34400/api/ - - - - - - API Bedingungen (mit Authentifizierung): - - API muss in den Einstellungen aktiviert sein - - API muss bei den Authentifizierungseinstellungen aktiviert sein - - Benutzer muss die Berechtigung API haben + API conditions (with Authentication): + - API must be activated in the Settings + - API must be activated in the Authentication Settings + - User must have API authorization - Nach jeder API Anfrage wird ein Token generiert, dieser ist einmal in 60 Minuten gültig. - In jeder Antwort ist ein neuer Token enthalten + A Token is generated after each API request, which is valid once every 60 minutes. + A new Token is included in every answer - Beispiel API Request mit curl - Login: + Example API Request with curl + Login request: curl -X POST -H "Content-Type: application/json" -d '{"cmd":"login","username":"plex","password":"123"}' http://localhost:34400/api/ - Antwort: + Response: { "status": true, "token": "U0T-NTSaigh-RlbkqERsHvUpgvaaY2dyRGuwIIvv" } - Status mit Verwendung eines Tokens: + Status Request using a Token: curl -X POST -H "Content-Type: application/json" -d '{"cmd":"status","token":"U0T-NTSaigh-RlbkqERsHvUpgvaaY2dyRGuwIIvv"}' http://localhost:4400/api/ - Antwort: + Response: { "epg.source": "XEPG", "status": true, @@ -840,13 +928,12 @@ func API(w http.ResponseWriter, r *http.Request) { response.Status = false response.Error = err.Error() w.Write([]byte(mapToJSON(response))) - return } response.Status = true - if Settings.API == false { + if !Settings.API { httpStatusError(w, r, 423) return } @@ -872,7 +959,7 @@ func API(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/json") - if Settings.AuthenticationAPI == true { + if Settings.AuthenticationAPI { var token string switch len(request.Token) { case 0: @@ -884,7 +971,7 @@ func API(w http.ResponseWriter, r *http.Request) { } } else { - err = errors.New("Login incorrect") + err = errors.New("login incorrect") if err != nil { responseAPIError(err) return @@ -912,7 +999,7 @@ func API(w http.ResponseWriter, r *http.Request) { } switch request.Cmd { - case "login": // Muss nichts übergeben werden + case "login": // Nothing has to be handed over case "status": @@ -926,6 +1013,13 @@ func API(w http.ResponseWriter, r *http.Request) { response.URLM3U = System.ServerProtocol.M3U + "://" + System.Domain + "/m3u/xteve.m3u" response.URLXepg = System.ServerProtocol.XML + "://" + System.Domain + "/xmltv/xteve.xml" + BufferInformation.Range(func(k, v interface{}) bool { + playlist := v.(Playlist) + response.TunerActive += int64(len(playlist.Streams)) + response.TunerAll += int64(playlist.Tuner) + return true + }) + case "update.m3u": err = getProviderData("m3u", "") if err != nil { @@ -969,10 +1063,9 @@ func API(w http.ResponseWriter, r *http.Request) { w.Write([]byte(mapToJSON(response))) - return } -// Download : Datei Download +// Download : File Download func Download(w http.ResponseWriter, r *http.Request) { var path = r.URL.Path @@ -987,14 +1080,14 @@ func Download(w http.ResponseWriter, r *http.Request) { os.RemoveAll(System.Folder.Temp + getFilenameFromPath(path)) w.Write([]byte(content)) - return + } func setDefaultResponseData(response ResponseStruct, data bool) (defaults ResponseStruct) { defaults = response - // Folgende Daten immer an den Client übergeben + // Always transfer the following Data to the Client defaults.ClientInfo.ARCH = System.ARCH defaults.ClientInfo.EpgSource = Settings.EpgSource defaults.ClientInfo.DVR = System.Addresses.DVR @@ -1005,13 +1098,15 @@ func setDefaultResponseData(response ResponseStruct, data bool) (defaults Respon defaults.ClientInfo.UUID = Settings.UUID defaults.ClientInfo.Errors = WebScreenLog.Errors defaults.ClientInfo.Warnings = WebScreenLog.Warnings + defaults.IPAddressesV4Host = System.IPAddressesV4Host + defaults.Settings.HostIP = Settings.HostIP defaults.Notification = System.Notification defaults.Log = WebScreenLog switch System.Branch { case "master": - defaults.ClientInfo.Version = fmt.Sprintf("%s", System.Version) + defaults.ClientInfo.Version = System.Version default: defaults.ClientInfo.Version = fmt.Sprintf("%s (%s)", System.Version, System.Build) @@ -1019,7 +1114,7 @@ func setDefaultResponseData(response ResponseStruct, data bool) (defaults Respon } - if data == true { + if data { defaults.Users, _ = authentication.GetAllUserData() //defaults.DVR = System.DVRAddress @@ -1060,7 +1155,7 @@ func setDefaultResponseData(response ResponseStruct, data bool) (defaults Respon func httpStatusError(w http.ResponseWriter, r *http.Request, httpStatusCode int) { http.Error(w, fmt.Sprintf("%s [%d]", http.StatusText(httpStatusCode), httpStatusCode), httpStatusCode) - return + } func getContentType(filename string) (contentType string) { diff --git a/src/xepg.go b/src/xepg.go index 97c7734..0f42dd8 100644 --- a/src/xepg.go +++ b/src/xepg.go @@ -7,6 +7,7 @@ import ( "fmt" "io/ioutil" "path" + "regexp" "runtime" "sort" @@ -17,9 +18,11 @@ import ( "time" "xteve/src/internal/imgcache" + + "github.com/samber/lo" ) -// Provider XMLTV Datei überprüfen +// Check provider XMLTV File func checkXMLCompatibility(id string, body []byte) (err error) { var xmltv XMLTV @@ -38,7 +41,7 @@ func checkXMLCompatibility(id string, body []byte) (err error) { return } -// XEPG Daten erstellen +// Create XEPG Data func buildXEPG(background bool) { if System.ScanInProgress == 1 { @@ -69,9 +72,9 @@ func buildXEPG(background bool) { createXMLTVFile() createM3UFile() - showInfo("XEPG:" + fmt.Sprintf("Ready to use")) + showInfo("XEPG:" + "Ready to use") - if Settings.CacheImages == true && System.ImageCachingInProgress == 0 { + if Settings.CacheImages && System.ImageCachingInProgress == 0 { go func() { @@ -93,12 +96,9 @@ func buildXEPG(background bool) { System.ScanInProgress = 0 - // Cache löschen - /* - Data.Cache.XMLTV = make(map[string]XMLTV) - Data.Cache.XMLTV = nil - */ - runtime.GC() + if Settings.ClearXMLTVCache { + clearXMLTVCache() + } }() @@ -114,7 +114,7 @@ func buildXEPG(background bool) { createXMLTVFile() createM3UFile() - if Settings.CacheImages == true && System.ImageCachingInProgress == 0 { + if Settings.CacheImages && System.ImageCachingInProgress == 0 { go func() { @@ -134,14 +134,13 @@ func buildXEPG(background bool) { } - showInfo("XEPG:" + fmt.Sprintf("Ready to use")) + showInfo("XEPG:" + "Ready to use") System.ScanInProgress = 0 - // Cache löschen - //Data.Cache.XMLTV = make(map[string]XMLTV) - //Data.Cache.XMLTV = nil - runtime.GC() + if Settings.ClearXMLTVCache { + clearXMLTVCache() + } }() @@ -156,54 +155,7 @@ func buildXEPG(background bool) { } -// XEPG Daten aktualisieren -func updateXEPG(background bool) { - - if System.ScanInProgress == 1 { - return - } - - System.ScanInProgress = 1 - - if Settings.EpgSource == "XEPG" { - - switch background { - - case false: - - createXEPGDatabase() - mapping() - cleanupXEPG() - - go func() { - - createXMLTVFile() - createM3UFile() - showInfo("XEPG:" + fmt.Sprintf("Ready to use")) - - System.ScanInProgress = 0 - - }() - - case true: - System.ScanInProgress = 0 - - } - - } else { - - System.ScanInProgress = 0 - - } - - // Cache löschen - //Data.Cache.XMLTV = nil //make(map[string]XMLTV) - //Data.Cache.XMLTV = make(map[string]XMLTV) - - return -} - -// Mapping Menü für die XMLTV Dateien erstellen +// Create Mapping Menu for the XMLTV Files func createXEPGMapping() { Data.XMLTV.Files = getLocalProviderFiles("xmltv") @@ -211,20 +163,6 @@ func createXEPGMapping() { var tmpMap = make(map[string]interface{}) - var friendlyDisplayName = func(channel Channel) (displayName string) { - var dn = channel.DisplayName - displayName = dn[0].Value - - switch len(dn) { - case 1: - displayName = dn[0].Value - default: - displayName = fmt.Sprintf("%s (%s)", dn[1].Value, dn[0].Value) - } - - return - } - if len(Data.XMLTV.Files) > 0 { for i := len(Data.XMLTV.Files) - 1; i >= 0; i-- { @@ -235,7 +173,6 @@ func createXEPGMapping() { var fileID = strings.TrimSuffix(getFilenameFromPath(file), path.Ext(getFilenameFromPath(file))) showInfo("XEPG:" + "Parse XMLTV file: " + getProviderParameter(fileID, "xmltv", "name")) - //xmltv, err = getLocalXMLTV(file) var xmltv XMLTV err = getLocalXMLTV(file, &xmltv) @@ -246,17 +183,17 @@ func createXEPGMapping() { ShowError(err, 000) } - // XML Parsen (Provider Datei) + // XML Parsing (Provider File) if err == nil { - // Daten aus der XML Datei in eine temporäre Map schreiben + // Write Data from the XML File to a temporary Map var xmltvMap = make(map[string]interface{}) for _, c := range xmltv.Channel { var channel = make(map[string]interface{}) channel["id"] = c.ID - channel["display-name"] = friendlyDisplayName(*c) + channel["display-names"] = c.DisplayNames channel["icon"] = c.Icon.Src xmltvMap[c.ID] = channel @@ -271,42 +208,40 @@ func createXEPGMapping() { } Data.XMLTV.Mapping = tmpMap - tmpMap = make(map[string]interface{}) } else { - if System.ConfigurationWizard == false { + if !System.ConfigurationWizard { showWarning(1007) } } - // Auswahl für den Dummy erstellen + // Create selection for the Dummy var dummy = make(map[string]interface{}) var times = []string{"30", "60", "90", "120", "180", "240", "360"} for _, i := range times { - var dummyChannel = make(map[string]string) - dummyChannel["display-name"] = i + " Minutes" + var dummyChannel = make(map[string]interface{}) + dummyChannel["display-names"] = []DisplayName{{Value: i + " Minutes"}} dummyChannel["id"] = i + "_Minutes" dummyChannel["icon"] = "" - dummy[dummyChannel["id"]] = dummyChannel + dummy[dummyChannel["id"].(string)] = dummyChannel } Data.XMLTV.Mapping["xTeVe Dummy"] = dummy - return } -// XEPG Datenbank erstellen / aktualisieren +// Create / update XEPG Database func createXEPGDatabase() (err error) { - var allChannelNumbers = make([]float64, 0, System.UnfilteredChannelLimit) - Data.Cache.Streams.Active = make([]string, 0, System.UnfilteredChannelLimit) - Data.XEPG.Channels = make(map[string]interface{}, System.UnfilteredChannelLimit) + var allChannelNumbers = make([]float64, 0) + Data.Cache.Streams.Active = make([]string, 0) + Data.XEPG.Channels = make(map[string]interface{}) Data.XEPG.Channels, err = loadJSONFileToMap(System.File.XEPG) if err != nil { @@ -316,7 +251,7 @@ func createXEPGDatabase() (err error) { var createNewID = func() (xepg string) { - var firstID = 0 //len(Data.XEPG.Channels) + var firstID = 0 newXEPGID: @@ -329,15 +264,21 @@ func createXEPGDatabase() (err error) { return } - var getFreeChannelNumber = func() (xChannelID string) { + var getFreeChannelNumber = func(startingChannel ...string) (xChannelID string) { sort.Float64s(allChannelNumbers) var firstFreeNumber float64 = Settings.MappingFirstChannel + if startingChannel != nil { + var startingChannel, _ = strconv.ParseFloat(startingChannel[0], 64) + if startingChannel > 0 { + firstFreeNumber = startingChannel + } + } for { - if indexOfFloat64(firstFreeNumber, allChannelNumbers) == -1 { + if lo.IndexOf(allChannelNumbers, firstFreeNumber) == -1 { xChannelID = fmt.Sprintf("%g", firstFreeNumber) allChannelNumbers = append(allChannelNumbers, firstFreeNumber) return @@ -347,17 +288,16 @@ func createXEPGDatabase() (err error) { } - return } - var generateHashForChannel = func(m3uID string, groupTitle string, tvgID string, tvgName string, uuidKey string, uuidValue string) string { - hash := md5.Sum([]byte(m3uID + groupTitle + tvgID + tvgName + uuidKey + uuidValue)) + var generateHashForChannel = func(m3uID string, name string, groupTitle string, tvgID string, tvgName string, uuidKey string, uuidValue string) string { + hash := md5.Sum([]byte(m3uID + name + groupTitle + tvgID + tvgName + uuidKey + uuidValue)) return hex.EncodeToString(hash[:]) } showInfo("XEPG:" + "Update database") - // Kanal mit fehlenden Kanalnummern löschen. Delete channel with missing channel numbers + // Delete Channel with missing Channel Numbers. for id, dxc := range Data.XEPG.Channels { var xepgChannel XEPGChannelStruct @@ -377,22 +317,22 @@ func createXEPGDatabase() (err error) { } // Make a map of the db channels based on their previously downloaded attributes -- filename, group, title, etc - var xepgChannelsValuesMap = make(map[string]XEPGChannelStruct, System.UnfilteredChannelLimit) + var xepgChannelsValuesMap = make(map[string]XEPGChannelStruct) for _, v := range Data.XEPG.Channels { var channel XEPGChannelStruct err = json.Unmarshal([]byte(mapToJSON(v)), &channel) if err != nil { return } - channelHash := generateHashForChannel(channel.FileM3UID, channel.GroupTitle, channel.TvgID, channel.TvgName, channel.UUIDKey, channel.UUIDValue) + channelHash := generateHashForChannel(channel.FileM3UID, channel.Name, channel.GroupTitle, channel.TvgID, channel.TvgName, channel.UUIDKey, channel.UUIDValue) xepgChannelsValuesMap[channelHash] = channel } for _, dsa := range Data.Streams.Active { - var channelExists = false // Entscheidet ob ein Kanal neu zu Datenbank hinzugefügt werden soll. Decides whether a channel should be added to the database - var channelHasUUID = false // Überprüft, ob der Kanal (Stream) eindeutige ID's besitzt. Checks whether the channel (stream) has unique IDs - var currentXEPGID string // Aktuelle Datenbank ID (XEPG). Wird verwendet, um den Kanal in der Datenbank mit dem Stream der M3u zu aktualisieren. Current database ID (XEPG) Used to update the channel in the database with the stream of the M3u + var channelExists = false // Decides whether a Channel should be added to the Database + var channelHasUUID = false // Checks whether the Channel (Stream) has Unique IDs + var currentXEPGID string // Current Database ID (XEPG) Used to update the Channel in the Database with the Stream of the M3U var m3uChannel M3UChannelStructXEPG @@ -403,8 +343,8 @@ func createXEPGDatabase() (err error) { Data.Cache.Streams.Active = append(Data.Cache.Streams.Active, m3uChannel.Name+m3uChannel.FileM3UID) - // Try to find the channel based on matching all known values. If that fails, then move to full channel scan - m3uChannelHash := generateHashForChannel(m3uChannel.FileM3UID, m3uChannel.GroupTitle, m3uChannel.TvgID, m3uChannel.TvgName, m3uChannel.UUIDKey, m3uChannel.UUIDValue) + // Try to find the channel based on matching all known values. If that fails, then move to full channel scan + m3uChannelHash := generateHashForChannel(m3uChannel.FileM3UID, m3uChannel.Name, m3uChannel.GroupTitle, m3uChannel.TvgID, m3uChannel.TvgName, m3uChannel.UUIDKey, m3uChannel.UUIDValue) if val, ok := xepgChannelsValuesMap[m3uChannelHash]; ok { channelExists = true currentXEPGID = val.XEPG @@ -413,7 +353,7 @@ func createXEPGDatabase() (err error) { } } else { - // XEPG Datenbank durchlaufen um nach dem Kanal zu suchen. Run through the XEPG database to search for the channel (full scan) + // Run through the XEPG Database to search for the Channel (full scan) for _, dxc := range xepgChannelsValuesMap { if m3uChannel.FileM3UID == dxc.FileM3UID { @@ -421,7 +361,7 @@ func createXEPGDatabase() (err error) { dxc.FileM3UID = m3uChannel.FileM3UID dxc.FileM3UName = m3uChannel.FileM3UName - // Vergleichen des Streams anhand einer UUID in der M3U mit dem Kanal in der Databank. Compare the stream using a UUID in the M3U with the channel in the database + // Compare the Stream using a UUID in the M3U with the Channel in the Database if len(dxc.UUIDValue) > 0 && len(m3uChannel.UUIDValue) > 0 { if dxc.UUIDValue == m3uChannel.UUIDValue && dxc.UUIDKey == m3uChannel.UUIDKey { @@ -434,7 +374,8 @@ func createXEPGDatabase() (err error) { } } else { - // Vergleichen des Streams mit dem Kanal in der Databank anhand des Kanalnamens. Compare the stream to the channel in the database using the channel name + + // Compare the Stream to the Channel in the Database using the Channel Name if dxc.Name == m3uChannel.Name { channelExists = true currentXEPGID = dxc.XEPG @@ -443,6 +384,41 @@ func createXEPGDatabase() (err error) { } + // Rename the Channel if it's update regex matches new channel name + if len(dxc.UpdateChannelNameRegex) == 0 { + continue + } + // Guard against the situation when both channels have UUIDValue, they are different, but names are the same + if dxc.Name == m3uChannel.Name { + continue + } + nameRx, err := regexp.Compile(dxc.UpdateChannelNameRegex) + if err != nil { + ShowError(err, 1018) + continue + } + if !nameRx.MatchString(m3uChannel.Name) { + continue + } + if len(dxc.UpdateChannelNameByGroupRegex) > 0 { + groupRx, err := regexp.Compile(dxc.UpdateChannelNameByGroupRegex) + if err != nil { + ShowError(err, 1018) + continue + } + if !groupRx.MatchString(dxc.XGroupTitle) { + // Found the channel name to update but it has wrong group + continue + } + } + showInfo("XEPG:" + fmt.Sprintf("Renaming the channel '%v' to '%v'", dxc.Name, m3uChannel.Name)) + channelExists = true + // dxc.Name will be assigned later in channelExists switch + dxc.XName = m3uChannel.Name + currentXEPGID = dxc.XEPG + Data.XEPG.Channels[currentXEPGID] = dxc + break + } } @@ -451,38 +427,50 @@ func createXEPGDatabase() (err error) { switch channelExists { case true: - // Bereits vorhandener Kanal + // Existing Channel var xepgChannel XEPGChannelStruct err = json.Unmarshal([]byte(mapToJSON(Data.XEPG.Channels[currentXEPGID])), &xepgChannel) if err != nil { return } - // Streaming URL aktualisieren + // Update Streaming URL xepgChannel.URL = m3uChannel.URL - // Name aktualisieren, anhand des Names wird überprüft ob der Kanal noch in einer Playlist verhanden. Funktion: cleanupXEPG + // Update Name, the Name is used to check whether the Channel is still available in a Playlist. Function: cleanupXEPG xepgChannel.Name = m3uChannel.Name - // Kanalname aktualisieren, nur mit Kanal ID's möglich - if channelHasUUID == true { - if xepgChannel.XUpdateChannelName == true { + // Update Channel Name, only possible with Channel ID's + if channelHasUUID { + if xepgChannel.XUpdateChannelName { xepgChannel.XName = m3uChannel.Name } } - // Kanallogo aktualisieren. Wird bei vorhandenem Logo in der XMLTV Datei wieder überschrieben - if xepgChannel.XUpdateChannelIcon == true { + // Update GroupTitle + xepgChannel.GroupTitle = m3uChannel.GroupTitle + + if xepgChannel.XUpdateChannelGroup { + xepgChannel.XGroupTitle = m3uChannel.GroupTitle + } + + // Update Channel Logo. Will be overwritten again if the Logo is present in the XMLTV file + if xepgChannel.XUpdateChannelIcon { xepgChannel.TvgLogo = m3uChannel.TvgLogo } Data.XEPG.Channels[currentXEPGID] = xepgChannel case false: - // Neuer Kanal + // New Channel var xepg = createNewID() - var xChannelID = getFreeChannelNumber() - + xChannelID := func() string { + if m3uChannel.PreserveMapping == "true" { + return getFreeChannelNumber(m3uChannel.UUIDValue) + } else { + return getFreeChannelNumber(m3uChannel.StartingChannel) + } + }() var newChannel XEPGChannelStruct newChannel.FileM3UID = m3uChannel.FileM3UID newChannel.FileM3UName = m3uChannel.FileM3UName @@ -493,6 +481,11 @@ func createXEPGDatabase() (err error) { newChannel.TvgID = m3uChannel.TvgID newChannel.TvgLogo = m3uChannel.TvgLogo newChannel.TvgName = m3uChannel.TvgName + if m3uChannel.TvgShift == "" { + newChannel.TvgShift = "0" + } else { + newChannel.TvgShift = m3uChannel.TvgShift + } newChannel.URL = m3uChannel.URL newChannel.XmltvFile = "" newChannel.XMapping = "" @@ -506,6 +499,7 @@ func createXEPGDatabase() (err error) { newChannel.XGroupTitle = m3uChannel.GroupTitle newChannel.XEPG = xepg newChannel.XChannelID = xChannelID + newChannel.XTimeshift = newChannel.TvgShift Data.XEPG.Channels[xepg] = newChannel @@ -521,7 +515,7 @@ func createXEPGDatabase() (err error) { return } -// Kanäle automatisch zuordnen und das Mapping überprüfen +// Automatically assign Channels and check the Mapping func mapping() (err error) { showInfo("XEPG:" + "Map channels") @@ -533,20 +527,27 @@ func mapping() (err error) { return } - // Automatische Mapping für neue Kanäle. Wird nur ausgeführt, wenn der Kanal deaktiviert ist und keine XMLTV Datei und kein XMLTV Kanal zugeordnet ist. - if xepgChannel.XActive == false { + // Automatic mapping for new Channels. Is only executed if the Channel is deactivated and no XMLTV file and no XMLTV Channel is assigned. + if !xepgChannel.XActive { - // Werte kann "-" sein, deswegen len < 1 - if len(xepgChannel.XmltvFile) < 1 && len(xepgChannel.XmltvFile) < 1 { + // Values can be "-", therefore len <= 1 + // If either XmltvFile (XMLTV file / EPG source) or XMapping (XMLTV Channel / EPG program) is "-" or null, then look for a matching EPG program. + if len(xepgChannel.XmltvFile) <= 1 || len(xepgChannel.XMapping) <= 1 { var tvgID = xepgChannel.TvgID - // Default für neuen Kanal setzen - xepgChannel.XmltvFile = "-" - xepgChannel.XMapping = "-" + // Set default for new Channel + if Settings.DefaultMissingEPG != "-" { + xepgChannel.XmltvFile = "xTeVe Dummy" + xepgChannel.XMapping = Settings.DefaultMissingEPG + } else { + xepgChannel.XmltvFile = "-" + xepgChannel.XMapping = "-" + } Data.XEPG.Channels[xepg] = xepgChannel + xmltvMapLoop: for file, xmltvChannels := range Data.XMLTV.Mapping { if channel, ok := xmltvChannels.(map[string]interface{})[tvgID]; ok { @@ -555,9 +556,8 @@ func mapping() (err error) { xepgChannel.XmltvFile = file xepgChannel.XMapping = channelID - xepgChannel.XActive = true - // Falls in der XMLTV Datei ein Logo existiert, wird dieses verwendet. Falls nicht, dann das Logo aus der M3U Datei + // If there is a Logo in the XMLTV file, this will be used. If not, then the Logo from the M3U file if icon, ok := channel.(map[string]interface{})["icon"].(string); ok { if len(icon) > 0 { xepgChannel.TvgLogo = icon @@ -569,6 +569,36 @@ func mapping() (err error) { } + } else { + + // Search for the proper XEPG channel ID by comparing it's name with every alias in XML file + for _, xmltvChannel := range xmltvChannels.(map[string]interface{}) { + xmltvNames := xmltvChannel.(map[string]interface{})["display-names"].([]DisplayName) + + for _, xmltvName := range xmltvNames { + xmltvNameSolid := strings.ReplaceAll(xmltvName.Value, " ", "") + xepgNameSolid := strings.ReplaceAll(xepgChannel.Name, " ", "") + + if !strings.EqualFold(xmltvNameSolid, xepgNameSolid) { + continue + } + + xepgChannel.XmltvFile = file + xepgChannel.XMapping = xmltvChannel.(map[string]interface{})["id"].(string) + + // If there is a Logo in the XMLTV file, this will be used. + // If not, then the Logo from the M3U file. + if icon, ok := xmltvChannel.(map[string]interface{})["icon"].(string); ok { + if len(icon) > 0 { + xepgChannel.TvgLogo = icon + } + } + + Data.XEPG.Channels[xepg] = xepgChannel + break xmltvMapLoop + } + } + } } @@ -577,8 +607,12 @@ func mapping() (err error) { } - // Überprüfen, ob die zugeordneten XMLTV Dateien und Kanäle noch existieren. - if xepgChannel.XActive == true { + if Settings.EnableMappedChannels && (xepgChannel.XmltvFile != "-" || xepgChannel.XMapping != "-") { + xepgChannel.XActive = true + } + + // Check whether the assigned XMLTV Files and Channels still exist. + if xepgChannel.XActive { var mapping = xepgChannel.XMapping var file = xepgChannel.XmltvFile @@ -589,10 +623,10 @@ func mapping() (err error) { if channel, ok := value[mapping].(map[string]interface{}); ok { - // Kanallogo aktualisieren + // Update Channel Logo if logo, ok := channel["icon"].(string); ok { - if xepgChannel.XUpdateChannelIcon == true && len(logo) > 0 { + if xepgChannel.XUpdateChannelIcon && len(logo) > 0 { xepgChannel.TvgLogo = logo } @@ -610,7 +644,7 @@ func mapping() (err error) { var fileID = strings.TrimSuffix(getFilenameFromPath(file), path.Ext(getFilenameFromPath(file))) - ShowError(fmt.Errorf("Missing XMLTV file: %s", getProviderParameter(fileID, "xmltv", "name")), 0) + ShowError(fmt.Errorf("missing XMLTV file: %s", getProviderParameter(fileID, "xmltv", "name")), 0) showWarning(2301) xepgChannel.XActive = false @@ -642,11 +676,10 @@ func mapping() (err error) { return } -// XMLTV Datei erstellen +// Create XMLTV File func createXMLTVFile() (err error) { // Image Cache - // 4edd81ab7c368208cc6448b615051b37.jpg var imgc = Data.Cache.Images Data.Cache.ImagesFiles = []string{} @@ -658,7 +691,7 @@ func createXMLTVFile() (err error) { for _, file := range files { - if indexOfString(file.Name(), Data.Cache.ImagesCache) == -1 { + if lo.IndexOf(Data.Cache.ImagesCache, file.Name()) == -1 { Data.Cache.ImagesCache = append(Data.Cache.ImagesCache, file.Name()) } @@ -691,24 +724,25 @@ func createXMLTVFile() (err error) { err := json.Unmarshal([]byte(mapToJSON(dxc)), &xepgChannel) if err == nil { - if xepgChannel.XActive == true { + if xepgChannel.XActive { - // Kanäle + // Channels var channel Channel channel.ID = xepgChannel.XChannelID channel.Icon = Icon{Src: imgc.Image.GetURL(xepgChannel.TvgLogo)} - channel.DisplayName = append(channel.DisplayName, DisplayName{Value: xepgChannel.XName}) + channel.DisplayNames = append(channel.DisplayNames, DisplayName{Value: xepgChannel.XName}) xepgXML.Channel = append(xepgXML.Channel, &channel) - // Programme + // Programs *tmpProgram, err = getProgramData(xepgChannel) if err == nil { - for _, program := range tmpProgram.Program { - xepgXML.Program = append(xepgXML.Program, program) - } + // for _, program := range tmpProgram.Program { + // xepgXML.Program = append(xepgXML.Program, program) + // } + xepgXML.Program = append(xepgXML.Program, tmpProgram.Program...) } @@ -730,7 +764,7 @@ func createXMLTVFile() (err error) { return } -// Programmdaten erstellen (createXMLTVFile) +// Create Program Data (createXMLTVFile) func getProgramData(xepgChannel XEPGChannelStruct) (xepgXML XMLTV, err error) { var xmltvFile = System.Folder.Data + xepgChannel.XmltvFile @@ -752,57 +786,63 @@ func getProgramData(xepgChannel XEPGChannelStruct) (xepgXML XMLTV, err error) { for _, xmltvProgram := range xmltv.Program { if xmltvProgram.Channel == channelID { - //fmt.Println(&channelID) var program = &Program{} // Channel ID program.Channel = xepgChannel.XChannelID - program.Start = xmltvProgram.Start - program.Stop = xmltvProgram.Stop + timeshift, _ := strconv.Atoi(xepgChannel.XTimeshift) + progStart := strings.Split(xmltvProgram.Start, " ") + progStop := strings.Split(xmltvProgram.Stop, " ") + tzStart, _ := strconv.Atoi(progStart[1]) + tzStop, _ := strconv.Atoi(progStop[1]) + progStart[1] = fmt.Sprintf("%+05d", tzStart+timeshift*100) + progStop[1] = fmt.Sprintf("%+05d", tzStop+timeshift*100) + program.Start = strings.Join(progStart, " ") + program.Stop = strings.Join(progStop, " ") // Title program.Title = xmltvProgram.Title - // Sub title (Untertitel) + // Subtitle program.SubTitle = xmltvProgram.SubTitle - // Description (Beschreibung) + // Description program.Desc = xmltvProgram.Desc - // Category (Kategorie) + // Category getCategory(program, xmltvProgram, xepgChannel) - // Credits : (Credits) + // Credits program.Credits = xmltvProgram.Credits - // Rating (Bewertung) + // Rating program.Rating = xmltvProgram.Rating - // StarRating (Bewertung / Kritiken) + // StarRating program.StarRating = xmltvProgram.StarRating - // Country (Länder) + // Country program.Country = xmltvProgram.Country - // Program icon (Poster / Cover) + // Program icon getPoster(program, xmltvProgram, xepgChannel) - // Language (Sprache) + // Language program.Language = xmltvProgram.Language - // Episodes numbers (Episodennummern) + // Episodes numbers getEpisodeNum(program, xmltvProgram, xepgChannel) - // Video (Videoparameter) + // Video getVideo(program, xmltvProgram, xepgChannel) - // Date (Datum) + // Date program.Date = xmltvProgram.Date - // Previously shown (Wiederholung) + // Previously shown program.PreviouslyShown = xmltvProgram.PreviouslyShown - // New (Neu) + // New program.New = xmltvProgram.New // Live @@ -820,7 +860,7 @@ func getProgramData(xepgChannel XEPGChannelStruct) (xepgXML XMLTV, err error) { return } -// Dummy Daten erstellen (createXMLTVFile) +// Create Dummy Data (createXMLTVFile) func createDummyProgram(xepgChannel XEPGChannelStruct) (dummyXMLTV XMLTV) { var imgc = Data.Cache.Images @@ -861,7 +901,7 @@ func createDummyProgram(xepgChannel XEPGChannelStruct) (dummyXMLTV XMLTV) { epg.Desc = append(epg.Desc, &Desc{Value: xepgChannel.XDescription, Lang: "en"}) } - if Settings.XepgReplaceMissingImages == true { + if Settings.XepgReplaceMissingImages { poster.Src = imgc.Image.GetURL(xepgChannel.TvgLogo) epg.Poster = append(epg.Poster, poster) } @@ -882,7 +922,7 @@ func createDummyProgram(xepgChannel XEPGChannelStruct) (dummyXMLTV XMLTV) { return } -// Kategorien erweitern (createXMLTVFile) +// Expand Categories (createXMLTVFile) func getCategory(program *Program, xmltvProgram *Program, xepgChannel XEPGChannelStruct) { for _, i := range xmltvProgram.Category { @@ -903,10 +943,9 @@ func getCategory(program *Program, xmltvProgram *Program, xepgChannel XEPGChanne } - return } -// Programm Poster Cover aus der XMLTV Datei laden +// Load the Poster Cover Program from the XMLTV File func getPoster(program *Program, xmltvProgram *Program, xepgChannel XEPGChannelStruct) { var imgc = Data.Cache.Images @@ -916,7 +955,7 @@ func getPoster(program *Program, xmltvProgram *Program, xepgChannel XEPGChannelS program.Poster = append(program.Poster, poster) } - if Settings.XepgReplaceMissingImages == true { + if Settings.XepgReplaceMissingImages { if len(xmltvProgram.Poster) == 0 { var poster Poster @@ -928,7 +967,7 @@ func getPoster(program *Program, xmltvProgram *Program, xepgChannel XEPGChannelS } -// Episodensystem übernehmen, falls keins vorhanden ist und eine Kategorie im Mapping eingestellt wurden, wird eine Episode erstellt +// Apply Episode system, if none is available and a Category has been set in the mapping, an Episode is created func getEpisodeNum(program *Program, xmltvProgram *Program, xepgChannel XEPGChannelStruct) { program.EpisodeNum = xmltvProgram.EpisodeNum @@ -950,10 +989,9 @@ func getEpisodeNum(program *Program, xmltvProgram *Program, xepgChannel XEPGChan } - return } -// Videoparameter erstellen (createXMLTVFile) +// Create Video Parameters (createXMLTVFile) func getVideo(program *Program, xmltvProgram *Program, xepgChannel XEPGChannelStruct) { var video Video @@ -976,30 +1014,29 @@ func getVideo(program *Program, xmltvProgram *Program, xepgChannel XEPGChannelSt program.Video = video - return } -// Lokale Provider XMLTV Datei laden +// Load Local Provider XMLTV file func getLocalXMLTV(file string, xmltv *XMLTV) (err error) { if _, ok := Data.Cache.XMLTV[file]; !ok { - // Cache initialisieren + // Initialize Cache if len(Data.Cache.XMLTV) == 0 { Data.Cache.XMLTV = make(map[string]XMLTV) } - // XML Daten lesen + // Read XML Data content, err := readByteFromFile(file) - // Lokale XML Datei existiert nicht im Ordner: data + // Local XML File does not exist in the folder: Data if err != nil { ShowError(err, 1004) - err = errors.New("Local copy of the file no longer exists") + err = errors.New("local copy of the file no longer exists") return err } - // XML Datei parsen + // Parse XML File err = xml.Unmarshal(content, &xmltv) if err != nil { return err @@ -1014,7 +1051,7 @@ func getLocalXMLTV(file string, xmltv *XMLTV) (err error) { return } -// M3U Datei erstellen +// Create M3U File func createM3UFile() { showInfo("XEPG:" + fmt.Sprintf("Create M3U file (%s)", System.File.M3U)) @@ -1025,14 +1062,11 @@ func createM3UFile() { saveMapToJSONFile(System.File.URLS, Data.Cache.StreamingURLS) - return } -// XEPG Datenbank bereinigen +// Clean up the XEPG Database func cleanupXEPG() { - //fmt.Println(Settings.Files.M3U) - var sourceIDs []string for source := range Settings.Files.M3U { @@ -1043,29 +1077,26 @@ func cleanupXEPG() { sourceIDs = append(sourceIDs, source) } - showInfo("XEPG:" + fmt.Sprintf("Cleanup database")) + showInfo("XEPG:" + "Cleanup database") Data.XEPG.XEPGCount = 0 for id, dxc := range Data.XEPG.Channels { - var xepgChannel XEPGChannelStruct err := json.Unmarshal([]byte(mapToJSON(dxc)), &xepgChannel) - if err == nil { - - if indexOfString(xepgChannel.Name+xepgChannel.FileM3UID, Data.Cache.Streams.Active) == -1 { - delete(Data.XEPG.Channels, id) - } else { - if xepgChannel.XActive == true { - Data.XEPG.XEPGCount++ - } - } - - if indexOfString(xepgChannel.FileM3UID, sourceIDs) == -1 { - delete(Data.XEPG.Channels, id) - } - + if err != nil { + continue + } + if lo.IndexOf(Data.Cache.Streams.Active, xepgChannel.Name+xepgChannel.FileM3UID) == -1 { + delete(Data.XEPG.Channels, id) + continue + } + if lo.IndexOf(sourceIDs, xepgChannel.FileM3UID) == -1 { + delete(Data.XEPG.Channels, id) + continue + } + if xepgChannel.XActive { + Data.XEPG.XEPGCount++ } - } err := saveMapToJSONFile(System.File.XEPG, Data.XEPG.Channels) @@ -1080,34 +1111,10 @@ func cleanupXEPG() { showWarning(2005) } - return } -// Streaming URL für die Channels App generieren -func getStreamByChannelID(channelID string) (playlistID, streamURL string, err error) { - - err = errors.New("Channel not found") - - for _, dxc := range Data.XEPG.Channels { - - var xepgChannel XEPGChannelStruct - err := json.Unmarshal([]byte(mapToJSON(dxc)), &xepgChannel) - - fmt.Println(xepgChannel.XChannelID) - - if err == nil { - - if channelID == xepgChannel.XChannelID { - - playlistID = xepgChannel.FileM3UID - streamURL = xepgChannel.URL - - return playlistID, streamURL, nil - } - - } - - } - - return +// clearXMLTVCache empties XMLTV cache and runs a garbage collector +func clearXMLTVCache() { + Data.Cache.XMLTV = make(map[string]XMLTV) + runtime.GC() } diff --git a/ts/authentication_ts.ts b/ts/authentication_ts.ts index 133b71a..f823b94 100644 --- a/ts/authentication_ts.ts +++ b/ts/authentication_ts.ts @@ -6,8 +6,6 @@ function login() { var inputs:any = div.getElementsByTagName("INPUT") - console.log(inputs) - for (var i = inputs.length - 1; i >= 0; i--) { var key:string = (inputs[i] as HTMLInputElement).name @@ -39,8 +37,6 @@ function login() { } } - - console.log(data) form.submit(); diff --git a/ts/base_ts.ts b/ts/base_ts.ts index e5cd134..90630ae 100644 --- a/ts/base_ts.ts +++ b/ts/base_ts.ts @@ -7,10 +7,9 @@ var SERVER_CONNECTION = false var WS_AVAILABLE = false -// Menü +// Menu var menuItems = new Array() menuItems.push(new MainMenuItem("playlist", "{{.mainMenu.item.playlist}}", "m3u.png", "{{.mainMenu.headline.playlist}}")) -//menuItems.push(new MainMenuItem("pmsID", "{{.mainMenu.item.pmsID}}", "number.png", "{{.mainMenu.headline.pmsID}}")) menuItems.push(new MainMenuItem("filter", "{{.mainMenu.item.filter}}", "filter.png", "{{.mainMenu.headline.filter}}")) menuItems.push(new MainMenuItem("xmltv", "{{.mainMenu.item.xmltv}}", "xmltv.png", "{{.mainMenu.headline.xmltv}}")) menuItems.push(new MainMenuItem("mapping", "{{.mainMenu.item.mapping}}", "mapping.png", "{{.mainMenu.headline.mapping}}")) @@ -19,10 +18,12 @@ menuItems.push(new MainMenuItem("settings", "{{.mainMenu.item.settings}}", "sett menuItems.push(new MainMenuItem("log", "{{.mainMenu.item.log}}", "log.png", "{{.mainMenu.headline.log}}")) menuItems.push(new MainMenuItem("logout", "{{.mainMenu.item.logout}}", "logout.png", "{{.mainMenu.headline.logout}}")) -// Kategorien für die Einstellungen +// Settings categories var settingsCategory = new Array() -settingsCategory.push(new SettingsCategoryItem("{{.settings.category.general}}", "xteveAutoUpdate,tuner,epgSource,api"));settingsCategory.push(new SettingsCategoryItem("{{.settings.category.files}}", "update,files.update,temp.path,cache.images,xepg.replace.missing.images")) -settingsCategory.push(new SettingsCategoryItem("{{.settings.category.streaming}}", "buffer,udpxy,buffer.size.kb,buffer.timeout,user.agent,ffmpeg.path,ffmpeg.options,vlc.path,vlc.options")) +settingsCategory.push(new SettingsCategoryItem("{{.settings.category.general}}", "tlsMode,xteveAutoUpdate,hostIP,hostName,tuner,epgSource,disallowURLDuplicates,clearXMLTVCache,api")) +settingsCategory.push(new SettingsCategoryItem("{{.settings.category.mapping}}", "defaultMissingEPG,enableMappedChannels")) +settingsCategory.push(new SettingsCategoryItem("{{.settings.category.files}}", "update,files.update,temp.path,cache.images,xepg.replace.missing.images")) +settingsCategory.push(new SettingsCategoryItem("{{.settings.category.streaming}}", "buffer,udpxy,buffer.size.kb,storeBufferInRAM,buffer.timeout,user.agent,ffmpeg.path,ffmpeg.options,vlc.path,vlc.options")) settingsCategory.push(new SettingsCategoryItem("{{.settings.category.backup}}", "backup.path,backup.keep")) settingsCategory.push(new SettingsCategoryItem("{{.settings.category.authentication}}", "authentication.web,authentication.pms,authentication.m3u,authentication.xml,authentication.api")) @@ -60,7 +61,7 @@ function changeButtonAction(element, buttonID, attribute) { } function getLocalData(dataType, id):object { - var data = new Object() + let data = {} switch(dataType) { case "m3u": data = SERVER["settings"]["files"][dataType][id] @@ -82,6 +83,8 @@ function getLocalData(dataType, id):object { data["include"] = "" data["name"] = "" data["type"] = "group-title" + data["preserveMapping"] = true + data["startingChannel"] = SERVER["settings"]["mapping.first.channel"] SERVER["settings"]["filter"][id] = data } data = SERVER["settings"]["filter"][id] @@ -107,16 +110,8 @@ function getLocalData(dataType, id):object { return data } -function getObjKeys(obj) { - var keys = new Array(); - - for (var i in obj) { - if (obj.hasOwnProperty(i)) { - keys.push(i); - } - } - - return keys; +function getOwnObjProps(object: Object): string[] { + return object ? Object.getOwnPropertyNames(object) : []; } function getAllSelectedChannels():string[] { @@ -201,38 +196,38 @@ function bulkEdit() { } function sortTable(column) { - //console.log(columm); if (column == COLUMN_TO_SORT) { return; } + const table = document.getElementById("content_table"); + const tableHead = table.getElementsByTagName("TR")[0]; + const tableItems = tableHead.getElementsByTagName("TD"); - var table = document.getElementById("content_table"); - var tableHead = table.getElementsByTagName("TR")[0]; - var tableItems = tableHead.getElementsByTagName("TD"); + type SortEntry = { + key: string | number; + row: HTMLTableRowElement; + } - var sortObj = new Object(); - var x, xValue; - var tableHeader - var sortByString = false + const sortArr: SortEntry[] = []; + let xValue: string | number; - if (column > 0 && COLUMN_TO_SORT > 0) { + if (column >= 0 && COLUMN_TO_SORT >= 0) { tableItems[COLUMN_TO_SORT].className = "pointer"; tableItems[column].className = "sortThis"; } COLUMN_TO_SORT = column; - - var rows = (table as HTMLTableElement).rows; + const rows = (table as HTMLTableElement).rows; if (rows[1] != undefined) { - tableHeader = rows[0] + const tableHeader = rows[0]; - x = rows[1].getElementsByTagName("TD")[column]; + let x: any = rows[1].getElementsByTagName("TD")[column]; - for (i = 1; i < rows.length; i++) { + for (let i = 1; i < rows.length; i++) { x = rows[i].getElementsByTagName("TD")[column]; @@ -245,32 +240,11 @@ function sortTable(column) { xValue = x.getElementsByTagName("P")[0].innerText.toLowerCase(); break; - default: console.log(x.childNodes[0].tagName); + default: + break; } - if (xValue == "" || xValue == NaN) { - - xValue = i - sortObj[i] = rows[i]; - - } else { - - switch(isNaN(xValue)) { - case false: - - xValue = parseFloat(xValue); - sortObj[xValue] = rows[i] - break; - - case true: - - sortByString = true - sortObj[xValue.toLowerCase() + i] = rows[i] - break; - - } - - } + sortArr.push({key: xValue ? xValue : i, row: rows[i]}); } @@ -278,25 +252,30 @@ function sortTable(column) { table.removeChild(table.firstChild); } - var sortValues = getObjKeys(sortObj) + sortArr.sort((se1: SortEntry, se2: SortEntry): number => { + const se1KeyNum = parseFloat(String(se1.key)); + const se2KeyNum = parseFloat(String(se2.key)); - if (sortByString == true) { - sortValues.sort() - console.log(sortValues); - } else { - function sortFloat(a, b) { - return a - b; + if (!isNaN(se1KeyNum) && !isNaN(se2KeyNum)) { + return se1KeyNum - se2KeyNum; } - sortValues.sort(sortFloat); - } - table.appendChild(tableHeader) + if (se1.key < se2.key) { + return -1; + } - for (var i = 0; i < sortValues.length; i++) { + if (se1.key > se2.key) { + return 1; + } - table.appendChild(sortObj[sortValues[i]]) + return 0; + }); - } + table.appendChild(tableHeader); + + sortArr.forEach((se: SortEntry) => { + table.appendChild(se.row); + }); } @@ -307,9 +286,9 @@ function createSearchObj() { SEARCH_MAPPING = new Object() var data = SERVER["xepg"]["epgMapping"] - var channels = getObjKeys(data) + var channels = getOwnObjProps(data) - var channelKeys:string[] = ["x-active", "x-channelID", "x-name", "_file.m3u.name", "x-group-title", "x-xmltv-file"] + var channelKeys:string[] = ["x-active", "x-channelID", "x-name", "updateChannelNameRegex", "_file.m3u.name", "x-group-title", "x-xmltv-file"] channels.forEach(id => { @@ -403,7 +382,7 @@ function changeChannelNumber(element) { var newNumber:number = parseFloat(element.value) var channelNumbers:number[] = [] var data = SERVER["xepg"]["epgMapping"] - var channels = getObjKeys(data) + var channels = getOwnObjProps(data) if (isNaN(newNumber)) { alert("{{.alert.invalidChannelNumber}}") @@ -436,8 +415,6 @@ function changeChannelNumber(element) { data[dbID]["x-channelID"] = newNumber.toString() element.value = newNumber - console.log(data[dbID]["x-channelID"]) - if (COLUMN_TO_SORT == 1) { COLUMN_TO_SORT = -1 sortTable(1) @@ -449,17 +426,12 @@ function changeChannelNumber(element) { function backup() { var data = new Object() - console.log("Backup data") - var cmd = "xteveBackup" - - console.log("SEND TO SERVER"); - console.log(data) - var server:Server = new Server(cmd) server.request(data) return + } function toggleChannelStatus(id:string) { @@ -514,6 +486,24 @@ function toggleChannelStatus(id:string) { } +function toggleGroupUpdateCb(xepgId: string, target: HTMLInputElement) { + target.className = 'changed'; + + const groupInput: HTMLInputElement = document.querySelector('input[name="x-group-title"]'); + const mapping = getLocalData('mapping', xepgId); + + if (target.checked) { + groupInput.dataset.oldValue = groupInput.value; + groupInput.value = mapping['group-title']; + groupInput.disabled = true; + } else { + groupInput.value = groupInput.dataset.oldValue; + groupInput.disabled = false; + } + + groupInput.className = 'changed'; +} + function restore() { if (document.getElementById('upload')) { @@ -543,7 +533,6 @@ function restore() { reader.readAsDataURL(file); reader.onload = function() { - console.log(reader.result); var data = new Object(); var cmd = "xteveRestore" data["base64"] = reader.result @@ -596,7 +585,6 @@ function uploadLogo() { reader.readAsDataURL(file); reader.onload = function() { - console.log(reader.result); var data = new Object(); var cmd = "uploadLogo" data["base64"] = reader.result @@ -640,32 +628,8 @@ function checkUndo(key:string) { return } -function sortSelect(elem) { - - var tmpAry = []; - var selectedValue = elem[elem.selectedIndex].value; - - for (var i=0;i 0) elem.options[0] = null; - - var newSelectedIndex = 0; - - for (var i=0;i { diff --git a/ts/menu_ts.ts b/ts/menu_ts.ts index c8480c4..b666385 100644 --- a/ts/menu_ts.ts +++ b/ts/menu_ts.ts @@ -5,13 +5,14 @@ class MainMenu { ImagePath:string = "img/" createIMG(src):any { - var element = document.createElement("IMG") + let element = document.createElement("IMG") element.setAttribute("src", this.ImagePath + src) + element.setAttribute("alt", src) return element } createValue(value):any { - var element = document.createElement("P") + let element = document.createElement("P") element.innerHTML = value return element } @@ -34,16 +35,16 @@ class MainMenuItem extends MainMenu { } createItem():void { - var item = document.createElement("LI") + let item = document.createElement("LI") item.setAttribute("onclick", "javascript: openThisMenu(this)") item.setAttribute("id", this.id) - var img = this.createIMG(this.imgSrc) - var value = this.createValue(this.value) + let img = this.createIMG(this.imgSrc) + let value = this.createValue(this.value) item.appendChild(img) item.appendChild(value) - var doc = document.getElementById(this.DocumentID) + let doc = document.getElementById(this.DocumentID) doc.appendChild(item) switch(this.menuKey) { @@ -56,20 +57,18 @@ class MainMenuItem extends MainMenu { break case "filter": - this.tableHeader = ["{{.filter.table.name}}", "{{.filter.table.type}}", "{{.filter.table.filter}}"] + this.tableHeader = ["{{.filter.table.startingChannel}}", "{{.filter.table.name}}", "{{.filter.table.type}}", "{{.filter.table.filter}}"] break case "users": this.tableHeader = ["{{.users.table.username}}", "{{.users.table.password}}", "{{.users.table.web}}", "{{.users.table.pms}}", "{{.users.table.m3u}}", "{{.users.table.xml}}", "{{.users.table.api}}"] break - case "mapping": - this.tableHeader = ["BULK", "{{.mapping.table.chNo}}", "{{.mapping.table.logo}}", "{{.mapping.table.channelName}}", "{{.mapping.table.playlist}}", "{{.mapping.table.groupTitle}}", "{{.mapping.table.xmltvFile}}", "{{.mapping.table.xmltvID}}"] + case "mapping": + this.tableHeader = ["BULK", "{{.mapping.table.chNo}}", "{{.mapping.table.logo}}", "{{.mapping.table.channelName}}", "{{.mapping.table.updateChannelNameRegex}}", "{{.mapping.table.playlist}}", "{{.mapping.table.groupTitle}}", "{{.mapping.table.xmltvFile}}", "{{.mapping.table.xmltvID}}", "{{.mapping.table.timeshift}}"] break } - - //console.log(this.menuKey, this.tableHeader); } } @@ -83,54 +82,54 @@ class Content { interactionID:string = "content-interaction" createHeadline(value):any { - var element = document.createElement("H3") + let element = document.createElement("H3") element.innerHTML = value return element } createHR():any { - var element = document.createElement("HR") - return element + return document.createElement("HR") } createInteraction():any { - var element = document.createElement("DIV") + let element = document.createElement("DIV") element.setAttribute("id", this.interactionID) return element } createDIV():any { - var element = document.createElement("DIV") + let element = document.createElement("DIV") element.id = this.DivID return element } createTABLE():any { - var element = document.createElement("TABLE") + let element = document.createElement("TABLE") element.id = this.TableID return element } createTableRow():any { - var element = document.createElement("TR") + let element = document.createElement("TR") element.className = this.headerClass return element } createTableContent(menuKey:string):string[] { - var data = new Object() - var rows = new Array() + let data = {} + let rows = [] + let fileTypes = [] switch(menuKey) { case "playlist": - var fileTypes = new Array("m3u", "hdhr") + fileTypes = ["m3u", "hdhr"] fileTypes.forEach(fileType => { data = SERVER["settings"]["files"][fileType] - var keys = getObjKeys(data) + var keys = getOwnObjProps(data) keys.forEach(key => { var tr = document.createElement("TR") @@ -203,16 +202,22 @@ class Content { }); break - case "filter": + case "filter": delete SERVER["settings"]["filter"][-1] data = SERVER["settings"]["filter"] - var keys = getObjKeys(data) + var keys = getOwnObjProps(data) keys.forEach(key => { var tr = document.createElement("TR") tr.id = key tr.setAttribute('onclick', 'javascript: openPopUp("' + data[key]["type"] + '", this)') - + + var cell:Cell = new Cell() + cell.child = true + cell.childType = "P" + cell.value = data[key]["startingChannel"] + tr.appendChild(cell.createCell()) + var cell:Cell = new Cell() cell.child = true cell.childType = "P" @@ -230,11 +235,11 @@ class Content { case "group-title": cell.value = "{{.filter.group}}" break; - + default: break; } - + tr.appendChild(cell.createCell()) var cell:Cell = new Cell() @@ -249,63 +254,63 @@ class Content { break case "xmltv": - var fileTypes = new Array("xmltv") + fileTypes = new Array("xmltv") fileTypes.forEach(fileType => { - + data = SERVER["settings"]["files"][fileType] - - var keys = getObjKeys(data) - + + var keys = getOwnObjProps(data) + keys.forEach(key => { var tr = document.createElement("TR") - + tr.id = key tr.setAttribute('onclick', 'javascript: openPopUp("' + fileType + '", this)') var cell:Cell = new Cell() cell.child = true cell.childType = "P" - cell.value = data[key]["name"] + cell.value = data[key]["name"] tr.appendChild(cell.createCell()) - + var cell:Cell = new Cell() cell.child = true cell.childType = "P" cell.value = data[key]["last.update"] tr.appendChild(cell.createCell()) - + var cell:Cell = new Cell() cell.child = true cell.childType = "P" cell.value = data[key]["provider.availability"] tr.appendChild(cell.createCell()) - + var cell:Cell = new Cell() cell.child = true cell.childType = "P" cell.value = data[key]["compatibility"]["xmltv.channels"] tr.appendChild(cell.createCell()) - + var cell:Cell = new Cell() cell.child = true cell.childType = "P" cell.value = data[key]["compatibility"]["xmltv.programs"] tr.appendChild(cell.createCell()) - + rows.push(tr) }); - + }); break case "users": - var fileTypes = new Array("users") + fileTypes = new Array("users") fileTypes.forEach(fileType => { data = SERVER[fileType] - var keys = getObjKeys(data) + var keys = getOwnObjProps(data) keys.forEach(key => { var tr = document.createElement("TR") @@ -384,16 +389,13 @@ class Content { BULK_EDIT = false createSearchObj() checkUndo("epgMapping") - console.log("MAPPING") data = SERVER["xepg"]["epgMapping"] - var keys = getObjKeys(data) + var keys = getOwnObjProps(data) keys.forEach(key => { var tr = document.createElement("TR") tr.id = key - //tr.setAttribute('oncontextmenu', 'javascript: rightClick(this)') - switch (data[key]["x-active"]) { case true: tr.className = "activeEPG" @@ -411,12 +413,11 @@ class Content { cell.value = false tr.appendChild(cell.createCell()) - // Kanalnummer + // Channel number var cell:Cell = new Cell() cell.child = true cell.childType = "INPUTCHANNEL" cell.value = data[key]["x-channelID"] - //td.setAttribute('onclick', 'javascript: changeChannelNumber("' + key + '", this)') tr.appendChild(cell.createCell()) // Logo @@ -430,7 +431,7 @@ class Content { tr.appendChild(td) - // Kanalname + // Channel name var cell:Cell = new Cell() cell.child = true cell.childType = "P" @@ -440,13 +441,21 @@ class Content { td.setAttribute('onclick', 'javascript: openPopUp("mapping", this)') td.id = key tr.appendChild(td) - + + // Update channel name regex + var cell:Cell = new Cell() + cell.child = true + cell.childType = "P" + cell.value = data[key]["update-channel-name-regex"] + var td = cell.createCell() + td.setAttribute('onclick', 'javascript: openPopUp("mapping", this)') + td.id = key + tr.appendChild(td) // Playlist var cell:Cell = new Cell() cell.child = true cell.childType = "P" - //cell.value = data[key]["_file.m3u.name"] cell.value = getValueFromProviderFile(data[key]["_file.m3u.id"], "m3u", "name") var td = cell.createCell() td.setAttribute('onclick', 'javascript: openPopUp("mapping", this)') @@ -454,7 +463,7 @@ class Content { tr.appendChild(td) - // Gruppe (group-title) + // Group (group-title) var cell:Cell = new Cell() cell.child = true cell.childType = "P" @@ -464,7 +473,7 @@ class Content { td.id = key tr.appendChild(td) - // XMLTV Datei + // XMLTV file var cell:Cell = new Cell() cell.child = true cell.childType = "P" @@ -480,11 +489,10 @@ class Content { td.id = key tr.appendChild(td) - // XMLTV Kanal + // XMLTV Channel var cell:Cell = new Cell() cell.child = true cell.childType = "P" - //var value = str.substring(1, 4); var value = data[key]["x-mapping"] if (value.length > 20) { value = data[key]["x-mapping"].substring(0, 20) + "..." @@ -493,7 +501,16 @@ class Content { var td = cell.createCell() td.setAttribute('onclick', 'javascript: openPopUp("mapping", this)') td.id = key + tr.appendChild(td) + // TimeShift + var cell:Cell = new Cell() + cell.child = true + cell.childType = "P" + cell.value = data[key]["x-timeshift"] + var td = cell.createCell() + td.setAttribute('onclick', 'javascript: openPopUp("mapping", this)') + td.id = key tr.appendChild(td) rows.push(tr) @@ -506,8 +523,6 @@ class Content { break default: - console.log("Table content (menuKey):", menuKey); - break } @@ -527,10 +542,10 @@ class Cell { tdClassName:string imageURL:string onclick:boolean - onclickFunktion:string + onclickFunction:string createCell():any { - var td = document.createElement("TD") + let td = document.createElement("TD") if (this.child == true) { @@ -587,7 +602,7 @@ class Cell { } if (this.onclick == true) { - td.setAttribute("onclick", this.onclickFunktion) + td.setAttribute("onclick", this.onclickFunction) td.className = "pointer" } @@ -611,7 +626,7 @@ class ShowContent extends Content { createInput(type:string, name:string, value:string,):any { - var input = document.createElement("INPUT") + let input = document.createElement("INPUT") input.setAttribute("type", type) input.setAttribute("name", name) input.setAttribute("value", value) @@ -620,25 +635,25 @@ class ShowContent extends Content { show():void { COLUMN_TO_SORT = -1 - // Alten Inhalt löschen - var doc = document.getElementById(this.DocumentID) + // Delete old content + let doc = document.getElementById(this.DocumentID) doc.innerHTML = "" showPreview(false) - // Überschrift - var headline:string[] = menuItems[this.menuID].headline + // Headline + let headline:string[] = menuItems[this.menuID].headline - var menuKey = menuItems[this.menuID].menuKey - var h = this.createHeadline(headline) + let menuKey = menuItems[this.menuID].menuKey + let h = this.createHeadline(headline) doc.appendChild(h) - var hr = this.createHR() + let hr = this.createHR() doc.appendChild(hr) - // Interaktion - var div =this.createInteraction() + // Interaction + let div =this.createInteraction() doc.appendChild(div) - var interaction = document.getElementById(this.interactionID) + let interaction = document.getElementById(this.interactionID) switch (menuKey) { case "playlist": var input = this.createInput("button", menuKey, "{{.button.new}}") @@ -711,7 +726,6 @@ class ShowContent extends Content { showSettings() return - break case "log": var input = this.createInput("button", menuKey, "{{.button.resetLogs}}") @@ -729,7 +743,6 @@ class ShowContent extends Content { showLogs(true) return - break case "logout": location.reload() @@ -737,11 +750,10 @@ class ShowContent extends Content { break default: - console.log("Show content (menuKey):", menuKey); break; } - // Tabelle erstellen (falls benötigt) + // Create table (if needed) var tableHeader:string[] = menuItems[this.menuID].tableHeader if (tableHeader.length > 0) { var wrapper = document.createElement("DIV") @@ -754,7 +766,7 @@ class ShowContent extends Content { var header = this.createTableRow() table.appendChild(header) - // Kopfzeile der Tablle + // Table header tableHeader.forEach(element => { var cell:Cell = new Cell() cell.child = true @@ -769,33 +781,68 @@ class ShowContent extends Content { if (element == "{{.mapping.table.chNo}}") { cell.onclick = true - cell.onclickFunktion = "javascript: sortTable(1);" + cell.onclickFunction = "javascript: sortTable(1);" cell.tdClassName = "sortThis" } if (element == "{{.mapping.table.channelName}}") { cell.onclick = true - cell.onclickFunktion = "javascript: sortTable(3);" + cell.onclickFunction = "javascript: sortTable(3);" + } + + if (element == "{{.mapping.table.updateChannelNameRegex}}") { + cell.onclick = true + cell.onclickFunction = "javascript: sortTable(4);" } if (element == "{{.mapping.table.playlist}}") { cell.onclick = true - cell.onclickFunktion = "javascript: sortTable(4);" + cell.onclickFunction = "javascript: sortTable(5);" } if (element == "{{.mapping.table.groupTitle}}") { cell.onclick = true - cell.onclickFunktion = "javascript: sortTable(5);" + cell.onclickFunction = "javascript: sortTable(6);" } + if (element == "{{.mapping.table.timeshift}}") { + cell.onclick = true + cell.onclickFunction = "javascript: sortTable(9);" + } + } + if (menuKey == "filter") { + + if (element == "{{.filter.table.startingChannel}}") { + cell.onclick = true + cell.onclickFunction = "javascript: sortTable(0);" + cell.tdClassName = "sortThis" + } + + if (element == "{{.filter.table.name}}") { + cell.onclick = true + cell.onclickFunction = "javascript: sortTable(1);" + } + + if (element == "{{.filter.table.type}}") { + cell.onclick = true + cell.onclickFunction = "javascript: sortTable(2);" + } + + if (element == "{{.filter.table.filter}}") { + cell.onclick = true + cell.onclickFunction = "javascript: sortTable(3);" + } + + } + header.appendChild(cell.createCell()) }); table.appendChild(header) - // Inhalt der Tabelle + // Content of the table var rows:any = this.createTableContent(menuKey) rows.forEach(tr => { table.appendChild(tr) @@ -826,8 +873,8 @@ class ShowContent extends Content { function PageReady() { - var server:Server = new Server("getServerConfig") - server.request(new Object()) + let server:Server = new Server("getServerConfig") + server.request({}) window.addEventListener("resize", function(){ calculateWrapperHeight(); @@ -844,14 +891,21 @@ function PageReady() { function createLayout() { // Client Info - var obj = SERVER["clientInfo"] - var keys = getObjKeys(obj); + let obj = SERVER["clientInfo"] + let keys = getOwnObjProps(obj); for (var i = 0; i < keys.length; i++) { - + if (document.getElementById(keys[i])) { document.getElementById(keys[i]).innerHTML = obj[keys[i]]; + if (location.protocol === 'https:') { + if (keys[i] === "xepg-url" || keys[i] === "m3u-url" || keys[i] === "DVR") { + document.getElementById(keys[i]).addEventListener('click', function (event) { + const target = event.target as HTMLElement; + navigator.clipboard.writeText(target.innerText.split(" ")[0]).then(() => {}); + },false); + } + } } - } if (!document.getElementById("main-menu")) { @@ -860,7 +914,7 @@ function createLayout() { - // Menü erstellen + // Create menu document.getElementById("main-menu").innerHTML = "" for (let i = 0; i < menuItems.length; i++) { @@ -893,8 +947,8 @@ function createLayout() { } function openThisMenu(element) { - var id = element.id - var content:ShowContent = new ShowContent(id) + let id = element.id + let content:ShowContent = new ShowContent(id) content.show() calculateWrapperHeight() @@ -907,20 +961,20 @@ class PopupWindow { doc = document.getElementById(this.DocumentID) createTitle(title:string):any { - var td = document.createElement("TD") + let td = document.createElement("TD") td.className = "left" td.innerHTML = title + ":" return td } createContent(element):any { - var td = document.createElement("TD") + let td = document.createElement("TD") td.appendChild(element) return td } createInteraction():any { - var div = document.createElement("div") + let div = document.createElement("div") div.setAttribute("id", "popup-interaction") div.className = "interaction" this.doc.appendChild(div) @@ -937,15 +991,15 @@ class PopupContent extends PopupWindow{ element.innerHTML = headline.toUpperCase() this.doc.appendChild(element) - // Tabelle erstellen + // Create table this.table = document.createElement("TABLE") this.doc.appendChild(this.table) } appendRow(title:string, element:any):void { - var tr = document.createElement("TR") + let tr = document.createElement("TR") - // Bezeichnung + // Title if (title.length != 0) { tr.appendChild(this.createTitle(title)) } @@ -958,8 +1012,8 @@ class PopupContent extends PopupWindow{ createInput(type:string, name:string, value:string):any { - - var input = document.createElement("INPUT") + + let input = document.createElement("INPUT") if (value == undefined) { value = "" } @@ -971,18 +1025,19 @@ class PopupContent extends PopupWindow{ } createCheckbox(name:string):any { - var input = document.createElement("INPUT") + let input = document.createElement("INPUT") input.setAttribute("type", "checkbox") input.setAttribute("name", name) return input } + // Creates a selection of multiple options values with text descriptions createSelect(text:string[], values:string[], set:string, dbKey:string):any { - var select = document.createElement("SELECT") + let select = document.createElement("SELECT") select.setAttribute("name", dbKey) for (let i = 0; i < text.length; i++) { - var option = document.createElement("OPTION") + let option = document.createElement("OPTION") option.setAttribute("value", values[i]) option.innerText = text[i] select.appendChild(option) @@ -1000,15 +1055,15 @@ class PopupContent extends PopupWindow{ selectOption(select:any, value:string):any { //select.selectedOptions = value - var s:HTMLSelectElement = (select as HTMLSelectElement) + let s:HTMLSelectElement = (select as HTMLSelectElement) s.options[s.selectedIndex].value = value return select } description(value:string):any { - var tr = document.createElement("TR") - var td = document.createElement("TD") - var span = document.createElement("PRE") + let tr = document.createElement("TR") + let td = document.createElement("TD") + let span = document.createElement("PRE") span.innerHTML = value @@ -1019,17 +1074,17 @@ class PopupContent extends PopupWindow{ this.table.appendChild(tr) } - // Interaktion + // Interaction addInteraction(element:any) { - var interaction = document.getElementById("popup-interaction") + let interaction = document.getElementById("popup-interaction") interaction.appendChild(element) } } function openPopUp(dataType, element) { - var data:object = new Object(); - var id:any + let data:object = {}; + let id:any switch (element) { case undefined: @@ -1064,8 +1119,8 @@ function openPopUp(dataType, element) { data = getLocalData(dataType, id) break; } - - var content:PopupContent = new PopupContent() + + let content:PopupContent = new PopupContent() switch (dataType) { case "playlist": @@ -1078,14 +1133,14 @@ function openPopUp(dataType, element) { select.setAttribute("onchange", 'javascript: changeButtonAction(this, "next", "onclick")') // changeButtonAction content.appendRow("{{.playlist.type.title}}", select) - // Interaktion + // Interaction content.createInteraction() - // Abbrechen + // Abort var input = content.createInput("button", "cancel", "{{.button.cancel}}") input.setAttribute("onclick", 'javascript: showElement("popup", false);') content.addInteraction(input) - // Weiter + // Next var input = content.createInput("button", "next", "{{.button.next}}") input.setAttribute("onclick", 'javascript: openPopUp("m3u")') input.setAttribute("id", 'next') @@ -1100,7 +1155,7 @@ function openPopUp(dataType, element) { input.setAttribute("placeholder", "{{.playlist.name.placeholder}}") content.appendRow("{{.playlist.name.title}}", input) - // Beschreibung + // Description var dbKey:string = "description" var input = content.createInput("text", dbKey, data[dbKey]) input.setAttribute("placeholder", "{{.playlist.description.placeholder}}") @@ -1114,8 +1169,8 @@ function openPopUp(dataType, element) { // Tuner if (SERVER["settings"]["buffer"] != "-") { - var text:string[] = new Array() - var values:string[] = new Array() + var text:string[] = [] + var values:string[] = [] for (var i = 1; i <= 100; i++) { text.push(i.toString()) @@ -1139,9 +1194,9 @@ function openPopUp(dataType, element) { content.description("{{.playlist.tuner.description}}") - // Interaktion + // Interation content.createInteraction() - // Löschen + // Delete if (data["id.provider"]!= "-") { var input = content.createInput("button", "delete", "{{.button.delete}}") input.className = "delete" @@ -1153,19 +1208,19 @@ function openPopUp(dataType, element) { content.addInteraction(input) } - // Abbrechen + // Abort var input = content.createInput("button", "cancel", "{{.button.cancel}}") input.setAttribute("onclick", 'javascript: showElement("popup", false);') content.addInteraction(input) - // Aktualisieren + // Update if (data["id.provider"]!= "-") { var input = content.createInput("button", "update", "{{.button.update}}") input.setAttribute('onclick', 'javascript: savePopupData("m3u", "' + id + '", false, 1)') content.addInteraction(input) } - // Speichern + // Save var input = content.createInput("button", "save", "{{.button.save}}") input.setAttribute('onclick', 'javascript: savePopupData("m3u", "' + id + '", false, 0)') content.addInteraction(input) @@ -1179,7 +1234,7 @@ function openPopUp(dataType, element) { input.setAttribute("placeholder", "{{.playlist.name.placeholder}}") content.appendRow("{{.playlist.name.title}}", input) - // Beschreibung + // Description var dbKey:string = "description" var input = content.createInput("text", dbKey, data[dbKey]) input.setAttribute("placeholder", "{{.playlist.description.placeholder}}") @@ -1193,8 +1248,8 @@ function openPopUp(dataType, element) { // Tuner if (SERVER["settings"]["buffer"] != "-") { - var text:string[] = new Array() - var values:string[] = new Array() + var text:string[] = [] + var values:string[] = [] for (var i = 1; i <= 100; i++) { text.push(i.toString()) @@ -1218,9 +1273,9 @@ function openPopUp(dataType, element) { content.description("{{.playlist.tuner.description}}") - // Interaktion + // Interaction content.createInteraction() - // Löschen + // Delete if (data["id.provider"]!= "-") { var input = content.createInput("button", "delete", "{{.button.delete}}") input.setAttribute('onclick', 'javascript: savePopupData("hdhr", "' + id + '", true, 0)') @@ -1232,19 +1287,19 @@ function openPopUp(dataType, element) { content.addInteraction(input) } - // Abbrechen + // Abort var input = content.createInput("button", "cancel", "{{.button.cancel}}") input.setAttribute("onclick", 'javascript: showElement("popup", false);') content.addInteraction(input) - // Aktualisieren + // Update if (data["id.provider"]!= "-") { var input = content.createInput("button", "update", "{{.button.update}}") input.setAttribute('onclick', 'javascript: savePopupData("hdhr", "' + id + '", false, 1)') content.addInteraction(input) } - // Speichern + // Save var input = content.createInput("button", "save", "{{.button.save}}") input.setAttribute('onclick', 'javascript: savePopupData("hdhr", "' + id + '", false, 0)') content.addInteraction(input) @@ -1262,14 +1317,14 @@ function openPopUp(dataType, element) { select.setAttribute("onchange", 'javascript: changeButtonAction(this, "next", "onclick");') // changeButtonAction content.appendRow("{{.filter.type.title}}", select) - // Interaktion + // Interaction content.createInteraction() - // Abbrechen + // Abort var input = content.createInput("button", "cancel", "{{.button.cancel}}") input.setAttribute("onclick", 'javascript: showElement("popup", false);') content.addInteraction(input) - // Weiter + // Next var input = content.createInput("button", "next", "{{.button.next}}") input.setAttribute("onclick", 'javascript: openPopUp("group-title")') input.setAttribute("id", 'next') @@ -1281,11 +1336,11 @@ function openPopUp(dataType, element) { switch (dataType) { case "custom-filter": - content.createHeadline("{{.filter.custom}}") + content.createHeadline("{{.filter.custom}}" + " Filter") break; case "group-title": - content.createHeadline("{{.filter.group}}") + content.createHeadline("{{.filter.group}}" + " Filter") break; } @@ -1295,13 +1350,13 @@ function openPopUp(dataType, element) { input.setAttribute("placeholder", "{{.filter.name.placeholder}}") content.appendRow("{{.filter.name.title}}", input) - // Beschreibung + // Description var dbKey:string = "description" var input = content.createInput("text", dbKey, data[dbKey]) input.setAttribute("placeholder", "{{.filter.description.placeholder}}") content.appendRow("{{.filter.description.title}}", input) - // Typ + // Type var dbKey:string = "type" var input = content.createInput("hidden", dbKey, data[dbKey]) content.appendRow("", input) @@ -1311,23 +1366,29 @@ function openPopUp(dataType, element) { switch (filterType) { case "custom-filter": - // Groß- Kleinschreibung beachten + // Case sensitive var dbKey:string = "caseSensitive" var input = content.createCheckbox(dbKey) input.checked = data[dbKey] content.appendRow("{{.filter.caseSensitive.title}}", input) - // Filterregel (Benutzerdefiniert) + // Filter Rule (Custom) var dbKey:string = "filter" var input = content.createInput("text", dbKey, data[dbKey]) input.setAttribute("placeholder", "{{.filter.filterRule.placeholder}}") content.appendRow("{{.filter.filterRule.title}}", input) + // Starting Channel Number Mapping + var dbKey:string = "startingChannel" + var input = content.createInput("text", dbKey, data[dbKey]) + input.setAttribute("placeholder", "{{.filter.startingChannel.placeholder}}") + content.appendRow("{{.filter.startingChannel.title}}", input) + break; case "group-title": //alert(dbKey + " " + filterType) - // Filter basierend auf den Gruppen in der M3U + // Filter based on the groups in the M3U var dbKey:string = "filter" var groupsM3U = getLocalData("m3uGroups", "") var text:string[] = groupsM3U["text"] @@ -1338,7 +1399,7 @@ function openPopUp(dataType, element) { content.appendRow("{{.filter.filterGroup.title}}", select) content.description("{{.filter.filterGroup.description}}") - // Groß- Kleinschreibung beachten + // Case sensetive var dbKey:string = "caseSensitive" var input = content.createCheckbox(dbKey) input.checked = data[dbKey] @@ -1357,28 +1418,40 @@ function openPopUp(dataType, element) { input.setAttribute("placeholder", "{{.filter.exclude.placeholder}}") content.appendRow("{{.filter.exclude.title}}", input) content.description("{{.filter.exclude.description}}") - - break + + // Preserve M3U Playlist Channel Mapping + var dbKey:string = "preserveMapping" + var input = content.createCheckbox(dbKey) + input.checked = data[dbKey] + content.appendRow("{{.filter.preserveMapping.title}}", input) + + // Starting Channel Number Mapping + var dbKey:string = "startingChannel" + var input = content.createInput("text", dbKey, data[dbKey]) + input.setAttribute("placeholder", "{{.filter.startingChannel.placeholder}}") + content.appendRow("{{.filter.startingChannel.title}}", input) + + break; default: break; } - // Interaktion + // Interaction content.createInteraction() - // Löschen + // Delete var input = content.createInput("button", "delete", "{{.button.delete}}") input.setAttribute('onclick', 'javascript: savePopupData("filter", "' + id + '", true, 0)') input.className = "delete" content.addInteraction(input) - // Abbrechen + // Abort var input = content.createInput("button", "cancel", "{{.button.cancel}}") input.setAttribute("onclick", 'javascript: showElement("popup", false);') content.addInteraction(input) - // Speichern + // Save var input = content.createInput("button", "save", "{{.button.save}}") input.setAttribute('onclick', 'javascript: savePopupData("filter", "' + id + '", false, 0)') content.addInteraction(input) @@ -1393,7 +1466,7 @@ function openPopUp(dataType, element) { input.setAttribute("placeholder", "{{.xmltv.name.placeholder}}") content.appendRow("{{.xmltv.name.title}}", input) - // Beschreibung + // Description var dbKey:string = "description" var input = content.createInput("text", dbKey, data[dbKey]) input.setAttribute("placeholder", "{{.xmltv.description.placeholder}}") @@ -1405,9 +1478,9 @@ function openPopUp(dataType, element) { input.setAttribute("placeholder", "{{.xmltv.fileXMLTV.placeholder}}") content.appendRow("{{.xmltv.fileXMLTV.title}}", input) - // Interaktion + // Interaction content.createInteraction() - // Löschen + // Delete if (data["id.provider"]!= "-") { var input = content.createInput("button", "delete", "{{.button.delete}}") input.setAttribute('onclick', 'javascript: savePopupData("xmltv", "' + id + '", true, 0)') @@ -1415,19 +1488,19 @@ function openPopUp(dataType, element) { content.addInteraction(input) } - // Abbrechen + // Abort var input = content.createInput("button", "cancel", "{{.button.cancel}}") input.setAttribute("onclick", 'javascript: showElement("popup", false);') content.addInteraction(input) - // Aktualisieren + // Update if (data["id.provider"]!= "-") { var input = content.createInput("button", "update", "{{.button.update}}") input.setAttribute('onclick', 'javascript: savePopupData("xmltv", "' + id + '", false, 1)') content.addInteraction(input) } - // Speichern + // Save var input = content.createInput("button", "save", "{{.button.save}}") input.setAttribute('onclick', 'javascript: savePopupData("xmltv", "' + id + '", false, 0)') content.addInteraction(input) @@ -1435,25 +1508,25 @@ function openPopUp(dataType, element) { case "users": content.createHeadline("{{.mainMenu.item.users}}") - // Benutzername + // User name var dbKey:string = "username" var input = content.createInput("text", dbKey, data[dbKey]) input.setAttribute("placeholder", "{{.users.username.placeholder}}") content.appendRow("{{.users.username.title}}", input) - // Neues Passwort + // New Parssword var dbKey:string = "password" var input = content.createInput("password", dbKey, "") input.setAttribute("placeholder", "{{.users.password.placeholder}}") content.appendRow("{{.users.password.title}}", input) - // Bestätigung + // Confirmation var dbKey:string = "confirm" var input = content.createInput("password", dbKey, "") input.setAttribute("placeholder", "{{.users.confirm.placeholder}}") content.appendRow("{{.users.confirm.title}}", input) - // Berechtigung WEB + // Authentication WEB var dbKey:string = "authentication.web" var input = content.createCheckbox(dbKey) input.checked = data[dbKey] @@ -1462,34 +1535,34 @@ function openPopUp(dataType, element) { } content.appendRow("{{.users.web.title}}", input) - // Berechtigung PMS + // Authentication PMS var dbKey:string = "authentication.pms" var input = content.createCheckbox(dbKey) input.checked = data[dbKey] content.appendRow("{{.users.pms.title}}", input) - // Berechtigung M3U + // Authentication M3U var dbKey:string = "authentication.m3u" var input = content.createCheckbox(dbKey) input.checked = data[dbKey] content.appendRow("{{.users.m3u.title}}", input) - // Berechtigung XML + // Authentication XML var dbKey:string = "authentication.xml" var input = content.createCheckbox(dbKey) input.checked = data[dbKey] content.appendRow("{{.users.xml.title}}", input) - // Berechtigung API + // Authentication API var dbKey:string = "authentication.api" var input = content.createCheckbox(dbKey) input.checked = data[dbKey] content.appendRow("{{.users.api.title}}", input) - // Interaktion + // Interaction content.createInteraction() - // Löschen + // Delete if (data["defaultUser"]!= true && id != "-") { var input = content.createInput("button", "delete", "{{.button.delete}}") input.className = "delete" @@ -1497,12 +1570,12 @@ function openPopUp(dataType, element) { content.addInteraction(input) } - // Abbrechen + // Abort var input = content.createInput("button", "cancel", "{{.button.cancel}}") input.setAttribute("onclick", 'javascript: showElement("popup", false);') content.addInteraction(input) - // Speichern + // Save var input = content.createInput("button", "save", "{{.button.save}}") input.setAttribute("onclick", 'javascript: savePopupData("' + dataType + '", "' + id + '", "false");') content.addInteraction(input) @@ -1511,7 +1584,7 @@ function openPopUp(dataType, element) { case "mapping": content.createHeadline("{{.mainMenu.item.mapping}}") - // Aktiv + // Active var dbKey:string = "x-active" var input = content.createCheckbox(dbKey) input.checked = data[dbKey] @@ -1520,7 +1593,7 @@ function openPopUp(dataType, element) { input.setAttribute("onchange", "javascript: toggleChannelStatus('" + id + "', this)") content.appendRow("{{.mapping.active.title}}", input) - // Kanalname + // Channel name var dbKey:string = "x-name" var input = content.createInput("text", dbKey, data[dbKey]) input.setAttribute("onchange", "javascript: this.className = 'changed'") @@ -1532,14 +1605,14 @@ function openPopUp(dataType, element) { content.description(data["name"]) - // Beschreibung + // Description var dbKey:string = "x-description" var input = content.createInput("text", dbKey, data[dbKey]) input.setAttribute("placeholder", "{{.mapping.description.placeholder}}") input.setAttribute("onchange", "javascript: this.className = 'changed'") content.appendRow("{{.mapping.description.title}}", input) - // Aktualisierung des Kanalnamens + // Update the channel x-name if (data.hasOwnProperty("_uuid.key")) { if (data["_uuid.key"] != "") { var dbKey:string = "x-update-channel-name" @@ -1550,14 +1623,30 @@ function openPopUp(dataType, element) { } } - // Logo URL (Kanal) + // Channel name regex for updating the channel name + var dbKey:string = "update-channel-name-regex" + var input = content.createInput("text", dbKey, data[dbKey]) + input.setAttribute("placeholder", "{{.mapping.updateChannelNameRegex.placeholder}}") + input.setAttribute("onchange", "javascript: this.className = 'changed'") + content.appendRow("{{.mapping.updateChannelNameRegex.title}}", input) + content.description("{{.mapping.updateChannelNameRegex.description}}") + + // Channel group regex for updating the channel name + var dbKey:string = "update-channel-name-by-group-regex" + var input = content.createInput("text", dbKey, data[dbKey]) + input.setAttribute("placeholder", "{{.mapping.updateChannelNameByGroupRegex.placeholder}}") + input.setAttribute("onchange", "javascript: this.className = 'changed'") + content.appendRow("{{.mapping.updateChannelNameByGroupRegex.title}}", input) + content.description("{{.mapping.updateChannelNameByGroupRegex.description}}") + + // Logo URL (Channel) var dbKey:string = "tvg-logo" var input = content.createInput("text", dbKey, data[dbKey]) input.setAttribute("onchange", "javascript: this.className = 'changed'") input.setAttribute("id", "channel-icon") content.appendRow("{{.mapping.channelLogo.title}}", input) - // Aktualisierung des Kanallogos + // Channel logo update var dbKey:string = "x-update-channel-icon" var input = content.createCheckbox(dbKey) input.checked = data[dbKey] @@ -1565,7 +1654,7 @@ function openPopUp(dataType, element) { input.setAttribute("onchange", "javascript: this.className = 'changed'; changeChannelLogo('" + id + "');") content.appendRow("{{.mapping.updateChannelLogo.title}}", input) - // Erweitern der EPG Kategorie + // Expand EPG category var dbKey:string = "x-category" var text:string[] = ["-", "Kids (Emby only)", "News", "Movie", "Series", "Sports"] var values:string[] = ["", "Kids", "News", "Movie", "Series", "Sports"] @@ -1573,53 +1662,73 @@ function openPopUp(dataType, element) { select.setAttribute("onchange", "javascript: this.className = 'changed'") content.appendRow("{{.mapping.epgCategory.title}}", select) - // M3U Gruppentitel + // M3U group title var dbKey:string = "x-group-title" var input = content.createInput("text", dbKey, data[dbKey]) input.setAttribute("onchange", "javascript: this.className = 'changed'") + input.dataset.oldValue = data[dbKey] content.appendRow("{{.mapping.m3uGroupTitle.title}}", input) - if (data["group-title"] != undefined) { content.description(data["group-title"]) } + if (data["x-update-channel-group"] == true) { + input.disabled = true; + } - // XMLTV Datei - var dbKey:string = "x-xmltv-file" - var xmlFile = data[dbKey] - var xmltv:XMLTVFile = new XMLTVFile() - var select = xmltv.getFiles(data[dbKey]) - select.setAttribute("name", dbKey) - select.setAttribute("id", "popup-xmltv") - select.setAttribute("onchange", "javascript: this.className = 'changed'; setXmltvChannel('" + id + "',this);") - content.appendRow("{{.mapping.xmltvFile.title}}", select) - var file = data[dbKey] + // Update channel group checkbox + var dbKey:string = "x-update-channel-group" + var input = content.createCheckbox(dbKey) + input.setAttribute("onchange", "javascript: toggleGroupUpdateCb('" + id + "', this);") + input.checked = data[dbKey] + content.appendRow("{{.mapping.updateChannelGroup.title}}", input) + content.description("{{.mapping.updateChannelGroup.description}}") + + // XMLTV file + var dbKey = 'x-xmltv-file'; + const xmlTvFile: string = data[dbKey]; + var xmlTv = new XMLTVFile(); + const xmlTvFileSelect = xmlTv.getFiles(data[dbKey]); + xmlTvFileSelect.setAttribute('name', dbKey); + xmlTvFileSelect.setAttribute('id', 'popup-xmltv'); + xmlTvFileSelect.setAttribute('onchange', `javascript: this.className = 'changed'; setXmltvChannel('${id}', this);`); + content.appendRow('{{.mapping.xmltvFile.title}}', xmlTvFileSelect); // XMLTV Mapping - var dbKey:string = "x-mapping" - var xmltv:XMLTVFile = new XMLTVFile() - var select = xmltv.getPrograms(file, data[dbKey]) - select.setAttribute("name", dbKey) - select.setAttribute("id", "popup-mapping") - select.setAttribute("onchange", "javascript: this.className = 'changed'; checkXmltvChannel('" + id + "',this,'" + xmlFile + "');") - - sortSelect(select) - content.appendRow("{{.mapping.xmltvChannel.title}}", select) - - // Interaktion + var dbKey: string = 'x-mapping'; + var xmlTv = new XMLTVFile(); + const currentXmlTvId: string = data[dbKey]; + const [xmlTvIdContainer, xmlTvIdInput, xmlTvIdDatalist] = xmlTv.newXmlTvIdPicker(xmlTvFile, currentXmlTvId); + xmlTvIdContainer.setAttribute('id', 'xmltv-id-picker-container'); + xmlTvIdInput.setAttribute('list', 'xmltv-id-picker-datalist'); + xmlTvIdInput.setAttribute('name', 'x-mapping'); // Should stay x-mapping as it will be used in donePopupData to make a server request + xmlTvIdInput.setAttribute('id', 'xmltv-id-picker-input'); + xmlTvIdInput.setAttribute('onchange', `javascript: this.className = 'changed'; checkXmltvChannel('${id}', this.value, '${xmlTvFile}');`); + xmlTvIdDatalist.setAttribute('id', 'xmltv-id-picker-datalist'); + content.appendRow('{{.mapping.xmltvChannel.title}}', xmlTvIdContainer); + + // Timeshift + var dbKey:string = "x-timeshift" + var input = content.createInput("text", dbKey, data[dbKey]) + input.setAttribute("onchange", "javascript: this.className = 'changed'") + input.setAttribute("placeholder", "{{.mapping.timeshift.placeholder}}") + input.setAttribute("id", "timeshift") + content.appendRow("{{.mapping.timeshift.title}}", input) + + // Interaction content.createInteraction() - // Logo hochladen + // Upload logo var input = content.createInput("button", "cancel", "{{.button.uploadLogo}}") input.setAttribute("onclick", 'javascript: uploadLogo();') content.addInteraction(input) - // Abbrechen + // Abort var input = content.createInput("button", "cancel", "{{.button.cancel}}") input.setAttribute("onclick", 'javascript: showElement("popup", false);') content.addInteraction(input) - // Fertig - var ids:string[] = new Array() + // Finished + var ids:string[] = [] ids = getAllSelectedChannels() if (ids.length == 0) { ids.push(id) @@ -1641,9 +1750,9 @@ class XMLTVFile { File:string getFiles(set:string):any { - var fileIDs:string[] = getObjKeys(SERVER["xepg"]["xmltvMap"]) - var values = new Array("-"); - var text = new Array("-"); + let fileIDs:string[] = getOwnObjProps(SERVER["xepg"]["xmltvMap"]) + let values = new Array("-"); + let text = new Array("-"); for (let i = 0; i < fileIDs.length; i++) { if (fileIDs[i] != "xTeVe Dummy") { @@ -1656,7 +1765,7 @@ class XMLTVFile { } - var select = document.createElement("SELECT") + let select = document.createElement("SELECT") for (let i = 0; i < text.length; i++) { var option = document.createElement("OPTION") option.setAttribute("value", values[i]) @@ -1671,42 +1780,72 @@ class XMLTVFile { return select } - getPrograms(file:string, set:string):any { - //var fileIDs:string[] = getObjKeys(SERVER["xepg"]["xmltvMap"]) - var values = getObjKeys(SERVER["xepg"]["xmltvMap"][file]); - var text = new Array() - var displayName:string + /** + * @param xmlTvFile XML file path to get EPG from. + * @param currentXmlTvId Current XMLTV ID to set initial input value to. + * @returns Array of, sequentially: + * 1) Container of the picker. + * 2) Input field to type at and get choice from. + * 3) Datalist containing every option. + */ + newXmlTvIdPicker(xmlTvFile: string, currentXmlTvId: string): [HTMLDivElement, HTMLInputElement, HTMLDataListElement] { + const container = document.createElement('div'); + const input = document.createElement('input'); + input.setAttribute('type', 'text'); + + // Initially, set value to '-' if input is empty + input.value = (currentXmlTvId) ? currentXmlTvId : '-'; + + // When input is focused, remove '-' from it + input.addEventListener('focus', (evt) => { + const target = evt.target as HTMLInputElement; + target.value = (target.value === '-') ? '' : target.value; + }); - for (let i = 0; i < values.length; i++) { - if (SERVER["xepg"]["xmltvMap"][file][values[i]].hasOwnProperty('display-name') == true) { - displayName = SERVER["xepg"]["xmltvMap"][file][values[i]]["display-name"]; - } else { - displayName = "-" - } - - text[i] = displayName + " (" + values[i] + ")"; + // When input lose focus or take a value, if it's empty, set value to '-' + input.addEventListener('blur', setFallbackValue); + input.addEventListener('change', setFallbackValue); + function setFallbackValue(evt: Event) { + const target = evt.target as HTMLInputElement; + target.value = (target.value) ? target.value : '-'; } - text.unshift("-"); - values.unshift("-"); + container.appendChild(input); - var select = document.createElement("SELECT") - for (let i = 0; i < text.length; i++) { - var option = document.createElement("OPTION") - option.setAttribute("value", values[i]) - option.innerText = text[i] - select.appendChild(option) - } + const datalist = document.createElement('datalist'); - if(set != "") { - (select as HTMLSelectElement).value = set + const option = document.createElement('option'); + option.setAttribute('value', '-'); + option.innerText = '-'; + datalist.appendChild(option); + + const epg: Object = SERVER['xepg']['xmltvMap'][xmlTvFile]; + + if (epg) { + const programIds = getOwnObjProps(epg); + + programIds.forEach((programId) => { + const program: Object = epg[programId]; + + if (program.hasOwnProperty('display-names')) { + program['display-names'].forEach((displayName: Object) => { + const option = document.createElement('option'); + option.setAttribute('value', programId); + option.innerText = displayName['Value']; + datalist.appendChild(option); + }); + } else { + const option = document.createElement('option'); + option.setAttribute('value', programId); + option.innerText = '-'; + datalist.appendChild(option); + } + }); } - if ((select as HTMLSelectElement).value != set) { - (select as HTMLSelectElement).value = "-" - } + container.appendChild(datalist); - return select + return [container, input, datalist]; } return @@ -1718,8 +1857,8 @@ function getValueFromProviderFile(file:string, fileType, key) { return file } - var fileID:string - var indicator = file.charAt(0) + let fileID:string + let indicator = file.charAt(0) switch (indicator) { case "M": @@ -1748,115 +1887,97 @@ function getValueFromProviderFile(file:string, fileType, key) { } -function setXmltvChannel(id, element) { +function setXmltvChannel(epgMapId: string, xmlTvFileSelect: HTMLSelectElement) { - var xmltv:XMLTVFile = new XMLTVFile() - var xmlFile = element.value + const xmlTv = new XMLTVFile(); + const newXmlTvFile = xmlTvFileSelect.value; - var tvgId:string = SERVER["xepg"]["epgMapping"][id]["tvg-id"] - var td = document.getElementById("popup-mapping").parentElement - td.innerHTML = "" + // Remove old XMLTV ID selection box + const xmlTvIdPickerParent = document.getElementById('xmltv-id-picker-container').parentElement as HTMLTableCellElement; + xmlTvIdPickerParent.innerHTML = ''; + + // Create new XMLTV ID selection box + const tvgId: string = SERVER['xepg']['epgMapping'][epgMapId]['tvg-id']; + + const [xmlTvIdContainer, xmlTvIdInput, xmlTvIdDatalist] = xmlTv.newXmlTvIdPicker(newXmlTvFile, tvgId); + xmlTvIdContainer.setAttribute('id', 'xmltv-id-picker-container'); + xmlTvIdInput.setAttribute('list', 'xmltv-id-picker-datalist'); + xmlTvIdInput.setAttribute('name', 'x-mapping'); // Should stay x-mapping as it will be used in donePopupData to make a server request + xmlTvIdInput.setAttribute('id', 'xmltv-id-picker-input'); + xmlTvIdInput.setAttribute('onchange', `javascript: this.className = 'changed'; checkXmltvChannel('${epgMapId}', this.value, '${newXmlTvFile}');`); + xmlTvIdInput.classList.add('changed'); + xmlTvIdDatalist.setAttribute('id', 'xmltv-id-picker-datalist'); + + // Add new XMLTV ID selection box to it's parent + xmlTvIdPickerParent.appendChild(xmlTvIdContainer); + + checkXmltvChannel(epgMapId, xmlTvIdInput.value, newXmlTvFile); - var select = xmltv.getPrograms(element.value, tvgId) - select.setAttribute("name", "x-mapping") - select.setAttribute("id", "popup-mapping") - select.setAttribute("onchange", "javascript: this.className = 'changed'; checkXmltvChannel('" + id + "',this,'" + xmlFile + "');") - select.className = "changed" - sortSelect(select) - td.appendChild(select); - - checkXmltvChannel(id, select, xmlFile) } -function checkXmltvChannel(id:string, element:any, xmlFile) { - - var value = (element as HTMLSelectElement).value - var bool:boolean - var checkbox = document.getElementById('active') - var channel:any = SERVER["xepg"]["epgMapping"][id] - var updateLogo:boolean - +function checkXmltvChannel(epgMapId: string, newXmlTvId: string, xmlTvFile: string) { - if (value == "-") { - bool = false - } else { - bool = true - } + const channelActiveCb = document.getElementById('active') as HTMLInputElement; - (checkbox as HTMLInputElement).checked = bool - checkbox.className = "changed" - console.log(xmlFile); - - // Kanallogo aktualisieren - /* - updateLogo = (document.getElementById("update-icon") as HTMLInputElement).checked - console.log(updateLogo); - */ - - if(xmlFile != "xTeVe Dummy" && bool == true) { - - //(document.getElementById("update-icon") as HTMLInputElement).checked = true; - //(document.getElementById("update-icon") as HTMLInputElement).className = "changed"; + const channelActive = newXmlTvId != '-'; - console.log("ID", id) - changeChannelLogo(id) + channelActiveCb.checked = channelActive; + channelActiveCb.className = 'changed'; - return + if(xmlTvFile != 'xTeVe Dummy' && channelActive == true) { + changeChannelLogo(epgMapId); + return; } - if (xmlFile == "xTeVe Dummy") { - (document.getElementById("update-icon") as HTMLInputElement).checked = false; - (document.getElementById("update-icon") as HTMLInputElement).className = "changed"; + if (xmlTvFile == 'xTeVe Dummy') { + (document.getElementById('update-icon') as HTMLInputElement).checked = false; + (document.getElementById('update-icon') as HTMLInputElement).className = 'changed'; } - return } -function changeChannelLogo(id:string) { +function changeChannelLogo(epgMapId: string) { + + const channel: Object = SERVER['xepg']['epgMapping'][epgMapId]; - var updateLogo:boolean - var channel:any = SERVER["xepg"]["epgMapping"][id] + const xmlTvFileSelect = document.getElementById('popup-xmltv') as HTMLSelectElement; + const xmlTvFile = xmlTvFileSelect.options[xmlTvFileSelect.selectedIndex].value; - var f = (document.getElementById("popup-xmltv") as HTMLSelectElement); - var xmltvFile = f.options[f.selectedIndex].value; + const xmlTvIdInput = document.getElementById('xmltv-id-picker-input') as HTMLInputElement; + const newXmlTvId = xmlTvIdInput.value; - var m = (document.getElementById("popup-mapping") as HTMLSelectElement); - var xMapping = m.options[m.selectedIndex].value; + const updateLogo = (document.getElementById('update-icon') as HTMLInputElement).checked; - var xmltvLogo = SERVER["xepg"]["xmltvMap"][xmltvFile][xMapping]["icon"] - updateLogo = (document.getElementById("update-icon") as HTMLInputElement).checked + let logo: string; - if (updateLogo == true && xmltvFile != "xTeVe Dummy") { + if (updateLogo == true && xmlTvFile != 'xTeVe Dummy') { - if (SERVER["xepg"]["xmltvMap"][xmltvFile].hasOwnProperty(xMapping)) { - var logo = xmltvLogo + if (SERVER['xepg']['xmltvMap'][xmlTvFile].hasOwnProperty(newXmlTvId)) { + logo = SERVER['xepg']['xmltvMap'][xmlTvFile][newXmlTvId]['icon']; } else { - logo = channel["tvg-logo"] + logo = channel['tvg-logo']; } - var logoInput = (document.getElementById("channel-icon") as HTMLInputElement); - logoInput.value = logo + var logoInput = (document.getElementById('channel-icon') as HTMLInputElement); + logoInput.value = logo; + if (BULK_EDIT == false) { - logoInput.className = "changed" + logoInput.className = 'changed'; } } } -function savePopupData(dataType:string, id:string, remove:Boolean, option:number) { +function savePopupData(dataType: string, id: string, remove: Boolean, option: number) { if (dataType == "mapping") { - var data = new Object() - console.log("Save mapping data") - - cmd = "saveEpgMapping" + let data = {} + let cmd = "saveEpgMapping" data["epgMapping"] = SERVER["xepg"]["epgMapping"] - - console.log("SEND TO SERVER"); - var server:Server = new Server(cmd) + let server:Server = new Server(cmd) server.request(data) delete UNDO["epgMapping"] @@ -1864,14 +1985,13 @@ function savePopupData(dataType:string, id:string, remove:Boolean, option:number return } - console.log("Save popup data") - var div = document.getElementById("popup-custom") + let div = document.getElementById("popup-custom") - var inputs = div.getElementsByTagName("TABLE")[0].getElementsByTagName("INPUT"); - var selects = div.getElementsByTagName("TABLE")[0].getElementsByTagName("SELECT"); + let inputs = div.getElementsByTagName("TABLE")[0].getElementsByTagName("INPUT"); + let selects = div.getElementsByTagName("TABLE")[0].getElementsByTagName("SELECT"); - var input = new Object(); - var confirmMsg: string + let input = {}; + let confirmMsg: string for (let i = 0; i < selects.length; i++) { @@ -1922,9 +2042,9 @@ function savePopupData(dataType:string, id:string, remove:Boolean, option:number } - var data = new Object() + let data = {} - var cmd:string + let cmd:string if (remove == true) { input["delete"] = true @@ -1939,7 +2059,7 @@ function savePopupData(dataType:string, id:string, remove:Boolean, option:number data["userData"] = input } else { cmd = "saveUserData" - var d = new Object() + let d = {} d[id] = input data["userData"] = d } @@ -1962,8 +2082,8 @@ function savePopupData(dataType:string, id:string, remove:Boolean, option:number } - data["files"] = new Object - data["files"][dataType] = new Object + data["files"] = {} + data["files"][dataType] = {} data["files"][dataType][id] = input break @@ -1984,8 +2104,8 @@ function savePopupData(dataType:string, id:string, remove:Boolean, option:number } - data["files"] = new Object - data["files"][dataType] = new Object + data["files"] = {} + data["files"][dataType] = {} data["files"][dataType][id] = input break @@ -2006,8 +2126,8 @@ function savePopupData(dataType:string, id:string, remove:Boolean, option:number } - data["files"] = new Object - data["files"][dataType] = new Object + data["files"] = {} + data["files"][dataType] = {} data["files"][dataType][id] = input break @@ -2016,14 +2136,12 @@ function savePopupData(dataType:string, id:string, remove:Boolean, option:number confirmMsg = "Delete this filter?" cmd = "saveFilter" - data["filter"] = new Object + data["filter"] = {} data["filter"][id] = input break default: - console.log(dataType, id); return - break; } @@ -2035,32 +2153,26 @@ function savePopupData(dataType:string, id:string, remove:Boolean, option:number } } - - console.log("SEND TO SERVER"); - - console.log(data); - - var server:Server = new Server(cmd) + + let server:Server = new Server(cmd) server.request(data) } function donePopupData(dataType:string, idsStr:string) { - - var ids:string[] = idsStr.split(','); - var div = document.getElementById("popup-custom") - var inputs = div.getElementsByClassName("changed") - + + let ids:string[] = idsStr.split(','); + let div = document.getElementById("popup-custom") + let inputs = div.getElementsByClassName("changed") + ids.forEach(id => { - var input = new Object(); + let input: Object; input = SERVER["xepg"]["epgMapping"][id] - console.log(input); - for (let i = 0; i < inputs.length; i++) { - - var name:string - var value:any + + let name:string + let value:any switch (inputs[i].tagName) { @@ -2105,8 +2217,12 @@ function donePopupData(dataType:string, idsStr:string) { (document.getElementById(id).childNodes[3].firstChild as HTMLElement).className = value break + case "update-channel-name-regex": + (document.getElementById(id).childNodes[4].firstChild as HTMLElement).innerHTML = value + break + case "x-group-title": - (document.getElementById(id).childNodes[5].firstChild as HTMLElement).innerHTML = value + (document.getElementById(id).childNodes[6].firstChild as HTMLElement).innerHTML = value break case "x-xmltv-file": @@ -2118,7 +2234,7 @@ function donePopupData(dataType:string, idsStr:string) { input["x-active"] = false } - (document.getElementById(id).childNodes[6].firstChild as HTMLElement).innerHTML = value + (document.getElementById(id).childNodes[7].firstChild as HTMLElement).innerHTML = value break case "x-mapping": @@ -2126,10 +2242,14 @@ function donePopupData(dataType:string, idsStr:string) { input["x-active"] = false } - (document.getElementById(id).childNodes[7].firstChild as HTMLElement).innerHTML = value + (document.getElementById(id).childNodes[8].firstChild as HTMLElement).innerHTML = value break + case "x-timeshift": + (document.getElementById(id).childNodes[9].firstChild as HTMLElement).innerHTML = value + break + default: } @@ -2145,7 +2265,6 @@ function donePopupData(dataType:string, idsStr:string) { document.getElementById(id).className = "activeEPG" } - console.log(input["tvg-logo"]); (document.getElementById(id).childNodes[2].firstChild as HTMLElement).setAttribute("src", input["tvg-logo"]) @@ -2158,28 +2277,27 @@ function donePopupData(dataType:string, idsStr:string) { function showPreview(element:boolean) { - var div = document.getElementById("myStreamsBox") + let div = document.getElementById("myStreamsBox") switch (element) { case false: div.className = "notVisible" return - break; } - - var streams:string[] = ["activeStreams", "inactiveStreams"] + + let streams:string[] = ["activeStreams", "inactiveStreams"] streams.forEach(preview => { - - var table = document.getElementById(preview) + + let table = document.getElementById(preview) table.innerHTML = "" - var obj:string[] = SERVER["data"]["StreamPreviewUI"][preview] + let obj:string[] = SERVER["data"]["StreamPreviewUI"][preview] obj.forEach(channel => { - - var tr = document.createElement("TR") - var tdKey = document.createElement("TD") - var tdVal = document.createElement("TD") + + let tr = document.createElement("TR") + let tdKey = document.createElement("TD") + let tdVal = document.createElement("TD") tdKey.className = "tdKey" tdVal.className = "tdVal" diff --git a/ts/network_ts.ts b/ts/network_ts.ts index 35b9318..491d1a4 100644 --- a/ts/network_ts.ts +++ b/ts/network_ts.ts @@ -13,8 +13,7 @@ class Server { } SERVER_CONNECTION = true - - console.log(data) + if (this.cmd != "updateLog") { showElement("loading", true) UNDO = new Object() @@ -36,18 +35,11 @@ class Server { ws.onopen = function() { WS_AVAILABLE = true - - console.log("REQUEST (JS):"); - console.log(data) - - console.log("REQUEST: (JSON)"); - console.log(JSON.stringify(data)) - this.send(JSON.stringify(data)); - + } - ws.onerror = function(e) { + ws.onerror = function(wsErrEvt) { console.log("No websocket connection to xTeVe could be established. Check your network configuration.") SERVER_CONNECTION = false @@ -59,31 +51,33 @@ class Server { } - ws.onmessage = function (e) { + ws.onmessage = function (wsMessageEvt) { SERVER_CONNECTION = false showElement("loading", false) - console.log("RESPONSE:"); - var response = JSON.parse(e.data); - - console.log(response); + const response: Object = JSON.parse(wsMessageEvt.data); if (response.hasOwnProperty("token")) { - document.cookie = "Token=" + response["token"] + document.cookie = "Token=" + response["token"]; } if (response["status"] == false) { - - alert(response["err"]) + alert(response["err"]); + return; + } - if (response.hasOwnProperty("reload")) { - location.reload() - } + if (response.hasOwnProperty('openLink')) { + window.location = response['openLink']; + } - return + if (response.hasOwnProperty("reload")) { + window.location.reload(); } + if (response.hasOwnProperty("alert")) { + alert(response["alert"]); + } if (response.hasOwnProperty("logoURL")) { var div = (document.getElementById("channel-icon") as HTMLInputElement) @@ -99,7 +93,6 @@ class Server { showLogs(false) } return - break; default: SERVER = new Object() @@ -113,19 +106,10 @@ class Server { showElement("popup", false) } - if (response.hasOwnProperty("openLink")) { - window.location = response["openLink"] - } - - if (response.hasOwnProperty("alert")) { - alert(response["alert"]) - } - if (response.hasOwnProperty("reload")) { location.reload() } - if (response.hasOwnProperty("wizard")) { createLayout() configurationWizard[response["wizard"]].createWizard() @@ -143,5 +127,7 @@ class Server { function getCookie(name) { var value = "; " + document.cookie; var parts = value.split("; " + name + "="); - if (parts.length == 2) return parts.pop().split(";").shift(); -} \ No newline at end of file + if (parts.length == 2) { + return parts.pop().split(";").shift(); + } +} diff --git a/ts/settings_ts.ts b/ts/settings_ts.ts index 432f91a..b9064c5 100644 --- a/ts/settings_ts.ts +++ b/ts/settings_ts.ts @@ -18,7 +18,7 @@ class SettingsCategory { switch (settingsKey) { - // Texteingaben + // Text inputs case "update": var tdLeft = document.createElement("TD") tdLeft.innerHTML = "{{.settings.update.title}}" + ":" @@ -145,7 +145,35 @@ class SettingsCategory { setting.appendChild(tdRight) break - // Checkboxen + // Checkboxes + case "tlsMode": + var tdLeft = document.createElement("TD") + tdLeft.innerHTML = "{{.settings.tlsMode.title}}" + ":" + + var tdRight = document.createElement("TD") + var input = content.createCheckbox(settingsKey) + input.checked = data + input.setAttribute("onchange", "javascript: this.className = 'changed'") + tdRight.appendChild(input) + + setting.appendChild(tdLeft) + setting.appendChild(tdRight) + break + + case "disallowURLDuplicates": + var tdLeft = document.createElement("TD") + tdLeft.innerHTML = "{{.settings.disallowURLDuplicates.title}}" + ":" + + var tdRight = document.createElement("TD") + var input = content.createCheckbox(settingsKey) + input.checked = data + input.setAttribute("onchange", "javascript: this.className = 'changed'") + tdRight.appendChild(input) + + setting.appendChild(tdLeft) + setting.appendChild(tdRight) + break + case "authentication.web": var tdLeft = document.createElement("TD") tdLeft.innerHTML = "{{.settings.authenticationWEB.title}}" + ":" @@ -258,6 +286,20 @@ class SettingsCategory { setting.appendChild(tdRight) break + case "storeBufferInRAM": + var tdLeft = document.createElement("TD") + tdLeft.innerHTML = "{{.settings.storeBufferInRAM.title}}" + ":" + + var tdRight = document.createElement("TD") + var input = content.createCheckbox(settingsKey) + input.checked = data + input.setAttribute("onchange", "javascript: this.className = 'changed'") + tdRight.appendChild(input) + + setting.appendChild(tdLeft) + setting.appendChild(tdRight) + break + case "xteveAutoUpdate": var tdLeft = document.createElement("TD") tdLeft.innerHTML = "{{.settings.xteveAutoUpdate.title}}" + ":" @@ -272,6 +314,20 @@ class SettingsCategory { setting.appendChild(tdRight) break + case "clearXMLTVCache": + var tdLeft = document.createElement("TD") + tdLeft.innerHTML = "{{.settings.clearXMLTVCache.title}}" + ":" + + var tdRight = document.createElement("TD") + var input = content.createCheckbox(settingsKey) + input.checked = data + input.setAttribute("onchange", "javascript: this.className = 'changed'") + tdRight.appendChild(input) + + setting.appendChild(tdLeft) + setting.appendChild(tdRight) + break + case "api": var tdLeft = document.createElement("TD") tdLeft.innerHTML = "{{.settings.api.title}}" + ":" @@ -286,7 +342,48 @@ class SettingsCategory { setting.appendChild(tdRight) break - // Select + case "enableMappedChannels": + var tdLeft = document.createElement("TD") + tdLeft.innerHTML = "{{.settings.enableMappedChannels.title}}" + ":" + + var tdRight = document.createElement("TD") + var input = content.createCheckbox(settingsKey) + input.checked = data + input.setAttribute("onchange", "javascript: this.className = 'changed'") + tdRight.appendChild(input) + + setting.appendChild(tdLeft) + setting.appendChild(tdRight) + break + + // Select + case "hostIP": + var tdLeft = document.createElement("TD") + tdLeft.innerHTML = "{{.settings.hostIP.title}}" + ":" + + var tdRight = document.createElement("TD") + var text: any[] = SERVER["ipAddressesV4Host"] + var values: any[] = SERVER["ipAddressesV4Host"] + + var select = content.createSelect(text, values, data, settingsKey) + select.setAttribute("onchange", "javascript: this.className = 'changed'") + tdRight.appendChild(select) + + setting.appendChild(tdLeft) + setting.appendChild(tdRight) + break; + + case "hostName": + var tdLeft = document.createElement("TD"); + tdLeft.innerHTML = "{{.settings.hostName.title}}" + ":"; + var tdRight = document.createElement("TD"); + var input = content.createInput("text", "hostName", data); + input.setAttribute("placeholder", "{{.settings.hostName.placeholder}}"); + input.setAttribute("onchange", "javascript: this.className = 'changed'"); + tdRight.appendChild(input); + setting.appendChild(tdLeft); + setting.appendChild(tdRight); + break; case "tuner": var tdLeft = document.createElement("TD") tdLeft.innerHTML = "{{.settings.tuner.title}}" + ":" @@ -324,6 +421,27 @@ class SettingsCategory { setting.appendChild(tdRight) break + case "defaultMissingEPG": + var tdLeft = document.createElement("TD") + tdLeft.innerHTML = "{{.settings.defaultMissingEPG.title}}" + ":" + + var tdRight = document.createElement("TD") + var text:any[] = [ + "-", "30 Minutes (30_Minutes)", "60 Minutes (60_Minutes)", "90 Minutes (90_Minutes)", + "120 Minutes (120_Minutes)", "180 Minutes (180_Minutes)", "240 Minutes (240_Minutes)", "360 Minutes (360_Minutes)" + ] + var values:any[] = [ + "-", "30_Minutes", "60_Minutes", "90_Minutes", "120_Minutes", "180_Minutes", "240_Minutes", "360_Minutes" + ] + + var select = content.createSelect(text, values, data, settingsKey) + select.setAttribute("onchange", "javascript: this.className = 'changed'") + tdRight.appendChild(select) + + setting.appendChild(tdLeft) + setting.appendChild(tdRight) + break + case "backup.keep": var tdLeft = document.createElement("TD") tdLeft.innerHTML = "{{.settings.backupKeep.title}}" + ":" @@ -400,6 +518,14 @@ class SettingsCategory { var text:string switch (settingsKey) { + case "tlsMode": + text = "{{.settings.tlsMode.description}}" + break + + case "disallowURLDuplicates": + text = "{{.settings.disallowURLDuplicates.description}}" + break + case "authentication.web": text = "{{.settings.authenticationWEB.description}}" break @@ -446,6 +572,10 @@ class SettingsCategory { text = "{{.settings.bufferSize.description}}" break + case "storeBufferInRAM": + text = "{{.settings.storeBufferInRAM.description}}" + break + case "buffer.timeout": text = "{{.settings.bufferTimeout.description}}" break @@ -474,6 +604,14 @@ class SettingsCategory { text = "{{.settings.epgSource.description}}" break + case "hostIP": + text = "{{.settings.hostIP.description}}" + break; + + case "hostName": + text = "{{.settings.hostName.description}}" + break; + case "tuner": text = "{{.settings.tuner.description}}" break @@ -482,10 +620,22 @@ class SettingsCategory { text = "{{.settings.update.description}}" break + case "clearXMLTVCache": + text = "{{.settings.clearXMLTVCache.description}}" + break + case "api": text = "{{.settings.api.description}}" break + case "defaultMissingEPG": + text = "{{.settings.defaultMissingEPG.description}}" + break + + case "enableMappedChannels": + text = "{{.settings.enableMappedChannels.description}}" + break + case "files.update": text = "{{.settings.filesUpdate.description}}" break @@ -542,7 +692,7 @@ class SettingsCategoryItem extends SettingsCategory { var doc = document.getElementById(this.DocumentID) doc.appendChild(headline) - // Tabelle für die Kategorie erstellen + // Create a table for the category var table = document.createElement("TABLE") @@ -579,7 +729,6 @@ class SettingsCategoryItem extends SettingsCategory { } function showSettings() { - console.log("SETTINGS"); for (let i = 0; i < settingsCategory.length; i++) { settingsCategory[i].createCategory() @@ -588,7 +737,6 @@ function showSettings() { } function saveSettings() { - console.log("Save Settings"); var cmd = "saveSettings" var div = document.getElementById("content_settings") @@ -636,7 +784,7 @@ function saveSettings() { name = (settings[i] as HTMLSelectElement).name value = (settings[i] as HTMLSelectElement).value - // Wenn der Wert eine Zahl ist, wird dieser als Zahl gespeichert + // If the value is a number, store it as a number if(isNaN(value)){ newSettings[name] = value } else { @@ -654,4 +802,5 @@ function saveSettings() { var server:Server = new Server(cmd) server.request(data) + } diff --git a/ts/tsconfig.json b/ts/tsconfig.json new file mode 100644 index 0000000..ba9756d --- /dev/null +++ b/ts/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "sourceMap": false, + "outDir": "../html/js" + }, + "include": [ + "*.ts" + ], + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/update_version.sh b/update_version.sh new file mode 100755 index 0000000..d215ce0 --- /dev/null +++ b/update_version.sh @@ -0,0 +1,17 @@ +#!/bin/sh +VERSION=`cat VERSION` +cat << EOF > release.json +{ + "version": "$VERSION", + "go_version": "1.19.0" +} +EOF + +cat << EOF > src/version.go +package src + +// Version : Version, the Build Number is parsed in the main func +const Version = "$VERSION" +EOF + +sed -Ei "s/ARG XTEVE_VERSION.*/ARG XTEVE_VERSION=$VERSION/" Dockerfile diff --git a/xteve.go b/xteve.go index 36a9546..d1271ef 100644 --- a/xteve.go +++ b/xteve.go @@ -1,7 +1,8 @@ // Copyright 2019 marmei. All rights reserved. +// Copyright 2022 senexcrenshaw. All rights reserved. // Use of this source code is governed by a MIT license that can be found in the // LICENSE file. -// GitHub: https://github.com/xteve-project/xTeVe +// GitHub: https://github.com/SenexCrenshaw/xTeVe package main @@ -16,7 +17,7 @@ import ( "xteve/src" ) -// GitHubStruct : GitHub Account. Über diesen Account werden die Updates veröffentlicht +// GitHubStruct : GitHub Account. The Updates are published via this Account type GitHubStruct struct { Branch string Repo string @@ -26,23 +27,18 @@ type GitHubStruct struct { // GitHub : GitHub Account // If you want to fork this project, enter your Github account here. This prevents a newer version of xTeVe from updating your version. -var GitHub = GitHubStruct{Branch: "master", User: "xteve-project", Repo: "xTeVe-Downloads", Update: true} +var GitHub = GitHubStruct{Branch: "main", User: "SenexCrenshaw", Repo: "xTeVe", Update: false} -/* - Branch: GitHub Branch - User: GitHub Username - Repo: GitHub Repository - Update: Automatic updates from the GitHub repository [true|false] -*/ +// Branch: GitHub Branch +// User: GitHub Username +// Repo: GitHub Repository +// Update: Automatic updates from the GitHub repository [true|false] -// Name : Programmname +// Name : Program Name const Name = "xTeVe" -// Version : Version, die Build Nummer wird in der main func geparst. -const Version = "2.2.0.0200" - -// DBVersion : Datanbank Version -const DBVersion = "2.1.0" +// DBVersion : Database Version +const DBVersion = "2.3.0" // APIVersion : API Version const APIVersion = "1.1.0" @@ -56,17 +52,20 @@ var port = flag.String("port", "", ": Server port [34400] (default: 344 var restore = flag.String("restore", "", ": Restore from backup ["+sampleRestore+"xteve_backup.zip]") var gitBranch = flag.String("branch", "", ": Git Branch [master|beta] (default: master)") +var noUpdates = flag.Bool("no-updates", false, ": Disable updates") var debug = flag.Int("debug", 0, ": Debug level [0 - 3] (default: 0)") var info = flag.Bool("info", false, ": Show system info") +var version = flag.Bool("version", false, ": Show system version") var h = flag.Bool("h", false, ": Show help") -// Aktiviert den Entwicklungsmodus. Für den Webserver werden dann die lokalen Dateien verwendet. +// Activates Development Mode. The local Files are then used for the Webserver. var dev = flag.Bool("dev", false, ": Activates the developer mode, the source code must be available. The local files for the web interface are used.") +var buildwebui = flag.Bool("buildwebui", false, ": Builds webUI.go and exits.") func main() { - // Build-Nummer von der Versionsnummer trennen - var build = strings.Split(Version, ".") + // Separate Build Number from Version Number + var build = strings.Split(src.Version, ".") var system = &src.System system.APIVersion = APIVersion @@ -77,7 +76,7 @@ func main() { system.Name = Name system.Version = strings.Join(build[0:len(build)-1], ".") - // Panic !!! + // Panic defer func() { if r := recover(); r != nil { @@ -121,11 +120,26 @@ func main() { return } + if *buildwebui { + src.HTMLInit("webUI", "src", "html"+string(os.PathSeparator), "src"+string(os.PathSeparator)+"webUI.go") + err := src.BuildGoFile() + if err != nil { + src.ShowError(err, 0) + } else { + fmt.Println("webUI.go built successfully") + } + os.Exit(0) + } + system.Dev = *dev - // Systeminformationen anzeigen - if *info { + if *version { + src.ShowSystemVersion() + return + } + // Display System Information + if *info { system.Flag.Info = true err := src.Init() @@ -150,6 +164,11 @@ func main() { fmt.Println("Git Branch is now:", system.Flag.Branch) } + // Updates + if noUpdates != nil { + system.GitHub.Update = false + } + // Debug Level system.Flag.Debug = *debug if system.Flag.Debug > 3 { @@ -157,12 +176,12 @@ func main() { return } - // Speicherort für die Konfigurationsdateien + // Storage location for the Configuration Files if len(*configFolder) > 0 { system.Folder.Config = *configFolder } - // Backup wiederherstellen + // Restore Backup if len(*restore) > 0 { system.Flag.Restore = *restore diff --git a/xteve_test.go b/xteve_test.go new file mode 100644 index 0000000..ef64976 --- /dev/null +++ b/xteve_test.go @@ -0,0 +1,7 @@ +package main + +import "testing" + +func TestMain(t *testing.T) { + main() +}