own-rag-cli 0.0.1-snapshot → 0.0.2-snapshot
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -3
- package/bin/indexer_full.py +189 -43
- package/bin/mcp_server.py +163 -18
- package/bin/postinstall.sh +28 -0
- package/bin/rag-remove.sh +3 -0
- package/chroma_monitor.sh +92 -18
- package/package.json +1 -1
- package/rag-setup-macos.run +295 -71
- package/rag-setup.run +295 -73
package/rag-setup-macos.run
CHANGED
|
@@ -325,6 +325,158 @@ normalize_port() {
|
|
|
325
325
|
return 1
|
|
326
326
|
}
|
|
327
327
|
|
|
328
|
+
normalize_scheme() {
|
|
329
|
+
local raw_scheme="${1:-}"
|
|
330
|
+
local lowered
|
|
331
|
+
lowered="$(echo "${raw_scheme}" | tr '[:upper:]' '[:lower:]' | xargs)"
|
|
332
|
+
if [[ "${lowered}" == "http" || "${lowered}" == "https" ]]; then
|
|
333
|
+
echo "${lowered}"
|
|
334
|
+
return 0
|
|
335
|
+
fi
|
|
336
|
+
return 1
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
is_local_chroma_host() {
|
|
340
|
+
local raw_host="${1:-}"
|
|
341
|
+
local lowered
|
|
342
|
+
lowered="$(echo "${raw_host}" | tr '[:upper:]' '[:lower:]' | xargs)"
|
|
343
|
+
case "${lowered}" in
|
|
344
|
+
localhost|127.0.0.1|::1)
|
|
345
|
+
return 0
|
|
346
|
+
;;
|
|
347
|
+
esac
|
|
348
|
+
return 1
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
ensure_own_rag_cli_config() {
|
|
352
|
+
python3 - "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
|
|
353
|
+
import json
|
|
354
|
+
import sys
|
|
355
|
+
from pathlib import Path
|
|
356
|
+
|
|
357
|
+
cfg = Path(sys.argv[1]).expanduser()
|
|
358
|
+
if cfg.exists():
|
|
359
|
+
sys.exit(0)
|
|
360
|
+
|
|
361
|
+
cfg.parent.mkdir(parents=True, exist_ok=True)
|
|
362
|
+
payload = {
|
|
363
|
+
"chroma": {
|
|
364
|
+
"scheme": "http",
|
|
365
|
+
"host": "localhost",
|
|
366
|
+
"port": 8000,
|
|
367
|
+
},
|
|
368
|
+
"indexing": {
|
|
369
|
+
"embedding_batch_size": 4,
|
|
370
|
+
"batch_count": 4,
|
|
371
|
+
},
|
|
372
|
+
}
|
|
373
|
+
cfg.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
|
374
|
+
PYEOF
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
load_own_rag_cli_chroma() {
|
|
378
|
+
python3 - "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
|
|
379
|
+
import json
|
|
380
|
+
import sys
|
|
381
|
+
from pathlib import Path
|
|
382
|
+
from urllib.parse import urlparse
|
|
383
|
+
|
|
384
|
+
cfg = Path(sys.argv[1]).expanduser()
|
|
385
|
+
scheme = "http"
|
|
386
|
+
host = "localhost"
|
|
387
|
+
port = 8000
|
|
388
|
+
|
|
389
|
+
def read_scheme(raw):
|
|
390
|
+
global scheme
|
|
391
|
+
if isinstance(raw, str) and raw.strip().lower() in {"http", "https"}:
|
|
392
|
+
scheme = raw.strip().lower()
|
|
393
|
+
|
|
394
|
+
def read_host(raw):
|
|
395
|
+
global scheme, host, port
|
|
396
|
+
if not isinstance(raw, str):
|
|
397
|
+
return
|
|
398
|
+
candidate = raw.strip()
|
|
399
|
+
if not candidate:
|
|
400
|
+
return
|
|
401
|
+
parsed = urlparse(candidate if "://" in candidate else f"//{candidate}")
|
|
402
|
+
if parsed.scheme in {"http", "https"}:
|
|
403
|
+
scheme = parsed.scheme
|
|
404
|
+
if parsed.hostname:
|
|
405
|
+
host = parsed.hostname
|
|
406
|
+
elif "://" not in candidate:
|
|
407
|
+
host = candidate.strip().strip("/")
|
|
408
|
+
if parsed.port and 1 <= parsed.port <= 65535:
|
|
409
|
+
port = parsed.port
|
|
410
|
+
|
|
411
|
+
def read_port(raw):
|
|
412
|
+
global port
|
|
413
|
+
try:
|
|
414
|
+
parsed = int(str(raw).strip())
|
|
415
|
+
except Exception:
|
|
416
|
+
return
|
|
417
|
+
if 1 <= parsed <= 65535:
|
|
418
|
+
port = parsed
|
|
419
|
+
|
|
420
|
+
if cfg.exists():
|
|
421
|
+
try:
|
|
422
|
+
payload = json.loads(cfg.read_text(encoding="utf-8"))
|
|
423
|
+
if isinstance(payload, dict):
|
|
424
|
+
chroma = payload.get("chroma")
|
|
425
|
+
if isinstance(chroma, dict):
|
|
426
|
+
read_scheme(chroma.get("scheme"))
|
|
427
|
+
read_host(chroma.get("host"))
|
|
428
|
+
read_port(chroma.get("port"))
|
|
429
|
+
read_scheme(payload.get("CHROMA_SCHEME"))
|
|
430
|
+
read_host(payload.get("CHROMA_HOST"))
|
|
431
|
+
read_port(payload.get("CHROMA_PORT"))
|
|
432
|
+
except Exception:
|
|
433
|
+
pass
|
|
434
|
+
|
|
435
|
+
print(f"{scheme}|{host}|{port}")
|
|
436
|
+
PYEOF
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
save_own_rag_cli_chroma() {
|
|
440
|
+
local scheme="$1"
|
|
441
|
+
local host="$2"
|
|
442
|
+
local port="$3"
|
|
443
|
+
python3 - "${OWN_RAG_CONFIG_FILE}" "${scheme}" "${host}" "${port}" <<'PYEOF'
|
|
444
|
+
import json
|
|
445
|
+
import sys
|
|
446
|
+
from pathlib import Path
|
|
447
|
+
|
|
448
|
+
cfg = Path(sys.argv[1]).expanduser()
|
|
449
|
+
scheme = sys.argv[2].strip().lower() or "http"
|
|
450
|
+
host = sys.argv[3].strip() or "localhost"
|
|
451
|
+
try:
|
|
452
|
+
port = int(sys.argv[4])
|
|
453
|
+
except Exception:
|
|
454
|
+
port = 8000
|
|
455
|
+
if port < 1 or port > 65535:
|
|
456
|
+
port = 8000
|
|
457
|
+
|
|
458
|
+
payload = {}
|
|
459
|
+
if cfg.exists():
|
|
460
|
+
try:
|
|
461
|
+
loaded = json.loads(cfg.read_text(encoding="utf-8"))
|
|
462
|
+
if isinstance(loaded, dict):
|
|
463
|
+
payload = loaded
|
|
464
|
+
except Exception:
|
|
465
|
+
payload = {}
|
|
466
|
+
|
|
467
|
+
chroma = payload.get("chroma")
|
|
468
|
+
if not isinstance(chroma, dict):
|
|
469
|
+
chroma = {}
|
|
470
|
+
chroma["scheme"] = "https" if scheme == "https" else "http"
|
|
471
|
+
chroma["host"] = host
|
|
472
|
+
chroma["port"] = port
|
|
473
|
+
payload["chroma"] = chroma
|
|
474
|
+
|
|
475
|
+
cfg.parent.mkdir(parents=True, exist_ok=True)
|
|
476
|
+
cfg.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
|
477
|
+
PYEOF
|
|
478
|
+
}
|
|
479
|
+
|
|
328
480
|
extract_chroma_port_from_compose() {
|
|
329
481
|
local compose_file="$1"
|
|
330
482
|
local parsed_port=""
|
|
@@ -516,20 +668,32 @@ VENV_PYTHON="${VENV_DIR}/bin/python3"
|
|
|
516
668
|
VENV_PIP="${VENV_DIR}/bin/pip"
|
|
517
669
|
DOCKER_COMPOSE_DIR="${USER_HOME}/docker-chromadb"
|
|
518
670
|
RAG_DB_DIR="${USER_HOME}/.rag_db"
|
|
519
|
-
|
|
671
|
+
OWN_RAG_CONFIG_FILE="${USER_HOME}/.own-rag-cli.json"
|
|
672
|
+
CHROMA_SCHEME_DEFAULT="http"
|
|
673
|
+
CHROMA_HOST_DEFAULT="localhost"
|
|
520
674
|
CHROMA_PORT_DEFAULT="8000"
|
|
675
|
+
CHROMA_SCHEME="${CHROMA_SCHEME_DEFAULT}"
|
|
676
|
+
CHROMA_HOST="${CHROMA_HOST_DEFAULT}"
|
|
677
|
+
CHROMA_PORT="${CHROMA_PORT_DEFAULT}"
|
|
521
678
|
CHROMA_PORT_FROM_ENV=false
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
679
|
+
CHROMA_IS_LOCAL=true
|
|
680
|
+
ENV_CHROMA_SCHEME_RAW="${MCP_CHROMA_SCHEME-}"
|
|
681
|
+
if [[ -z "${ENV_CHROMA_SCHEME_RAW}" ]]; then
|
|
682
|
+
ENV_CHROMA_SCHEME_RAW="$(printenv CHROMA_SCHEME 2>/dev/null || true)"
|
|
683
|
+
fi
|
|
684
|
+
ENV_CHROMA_HOST_RAW="${MCP_CHROMA_HOST-}"
|
|
685
|
+
if [[ -z "${ENV_CHROMA_HOST_RAW}" ]]; then
|
|
686
|
+
ENV_CHROMA_HOST_RAW="$(printenv CHROMA_HOST 2>/dev/null || true)"
|
|
687
|
+
fi
|
|
688
|
+
ENV_CHROMA_PORT_RAW="${MCP_CHROMA_PORT-}"
|
|
689
|
+
if [[ -z "${ENV_CHROMA_PORT_RAW}" ]]; then
|
|
690
|
+
ENV_CHROMA_PORT_RAW="$(printenv CHROMA_PORT 2>/dev/null || true)"
|
|
527
691
|
fi
|
|
528
692
|
BIN_DIR="${USER_HOME}/.local/bin"
|
|
529
693
|
MCP_SERVER_DEST="${BIN_DIR}/mcp-rag-server"
|
|
530
694
|
MODEL_DL_HF_DEST="${BIN_DIR}/download_model_from_hugginface.py"
|
|
531
695
|
MODEL_DL_MS_DEST="${BIN_DIR}/download_model_from_modelscope.py"
|
|
532
|
-
MODEL_CACHE_DIR="${USER_HOME}/.cache/
|
|
696
|
+
MODEL_CACHE_DIR="${USER_HOME}/.cache/own-rag-cli/models"
|
|
533
697
|
EXTRACT_DIR="$(mktemp -d "${TMPDIR:-/tmp}/rag-setup-macos.XXXXXX")"
|
|
534
698
|
DOCKER_COMPOSE_FILE_PATH="${DOCKER_COMPOSE_DIR}/docker-compose.yml"
|
|
535
699
|
|
|
@@ -560,8 +724,8 @@ log_info "$(t extracting)"
|
|
|
560
724
|
|
|
561
725
|
B64_COMPOSE="c2VydmljZXM6CiAgY2hyb21hZGI6CiAgICBpbWFnZTogY2hyb21hZGIvY2hyb21hOmxhdGVzdAogICAgY29udGFpbmVyX25hbWU6IGNocm9tYWRiLXJhZwogICAgcG9ydHM6CiAgICAgIC0gIjgwMDA6ODAwMCIKICAgIHZvbHVtZXM6CiAgICAgICMgUGVyc2lzdGUgbyBiYW5jbyBkaXJldGFtZW50ZSBuYSBwYXN0YSBkbyB1c3XDoXJpbyBubyBob3N0CiAgICAgIC0gJHtIT01FfS8ucmFnX2RiOi9jaHJvbWEvY2hyb21hCiAgICBlbnZpcm9ubWVudDoKICAgICAgIyBIYWJpbGl0YSBhdXRlbnRpY2HDp8OjbyBhbsO0bmltYSAoc2VtIHRva2VuKSBwYXJhIHVzbyBsb2NhbAogICAgICAtIEFOT05ZTUlaRURfVEVMRU1FVFJZPWZhbHNlCiAgICAgIC0gQ0hST01BX1NFUlZFUl9BVVRITl9DUkVERU5USUFMU19GSUxFPSIiCiAgICAgIC0gQ0hST01BX1NFUlZFUl9BVVRITl9QUk9WSURFUj0iIgogICAgcmVzdGFydDogYWx3YXlzCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQiLCAiY3VybCIsICItZiIsICJodHRwOi8vbG9jYWxob3N0OjgwMDAvYXBpL3YxL2hlYXJ0YmVhdCJdCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDMKICAgICAgc3RhcnRfcGVyaW9kOiAxMHMK"
|
|
562
726
|
B64_REQUIREMENTS="IyBDbGllbnRlIEhUVFAgZG8gQ2hyb21hREIgKGNvbmVjdGEgYW8gc2Vydmlkb3IgRG9ja2VyKQpjaHJvbWFkYj49MC41LjAKCiMgTW9kZWxvIGRlIGVtYmVkZGluZ3MgbG9jYWwgcm9kYW5kbyBuYSBDUFUKc2VudGVuY2UtdHJhbnNmb3JtZXJzPj0zLjAuMAojIERlcGVuZMOqbmNpYSB1c2FkYSBwb3IgbW9kZWxvcyBKaW5hIHYzIGNvbSBjw7NkaWdvIHJlbW90bwplaW5vcHM+PTAuNy4wCiMgRXZpdGEgaW5jb21wYXRpYmlsaWRhZGVzIGNvbmhlY2lkYXMgZG8gSmluYSB2MyBjb20gQVBJcyBub3ZhcyBkbyB0cmFuc2Zvcm1lcnMgNS54CnRyYW5zZm9ybWVyczw1CgojIFNwbGl0dGVyIGRlIHRleHRvIHBhcmEgY2h1bmtpbmcgaW50ZWxpZ2VudGUKbGFuZ2NoYWluLXRleHQtc3BsaXR0ZXJzPj0wLjIuMAoKIyBCYXJyYSBkZSBwcm9ncmVzc28gdmlzdWFsIG5vIHRlcm1pbmFsCnRxZG0+PTQuNjYuMAoKIyBNb25pdG9yIGRlIG1lbcOzcmlhIGVtIHRlbXBvIHJlYWwgZHVyYW50ZSBpbmRleGHDp8Ojbwpwc3V0aWw+PTUuOS4wCgojIFNESyBvZmljaWFsIGRvIE1DUCAoTW9kZWwgQ29udGV4dCBQcm90b2NvbCkgZGEgQW50aHJvcGljCm1jcD49MS4wLjAK"
|
|
563
|
-
B64_INDEXER="IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwoiIiIKaW5kZXhlcl9mdWxsLnB5IOKAlCBTY3JpcHQgc3RhbmRhbG9uZSBkZSBpbmRleGHDp8OjbyBkbyBSQUcgbG9jYWwuCgpVc286CiAgICBweXRob24gaW5kZXhlcl9mdWxsLnB5IFtjYW1pbmhvX2RvX3Byb2pldG9dCgpTZSBuZW5odW0gY2FtaW5obyBmb3IgcGFzc2FkbywgdXNhIG8gZGlyZXTDs3JpbyBhdHVhbC4KTyBDaHJvbWFEQiBkZXZlIGVzdGFyIHJvZGFuZG8gdmlhIERvY2tlciBlbSBsb2NhbGhvc3Q6ODAwMC4KIiIiCgppbXBvcnQgb3MKaW1wb3J0IHN5cwppbXBvcnQgaGFzaGxpYgppbXBvcnQgYXJncGFyc2UKaW1wb3J0IHNodXRpbAppbXBvcnQgbG9nZ2luZwppbXBvcnQgZ2MKaW1wb3J0IGpzb24KZnJvbSB0aW1lIGltcG9ydCBwZXJmX2NvdW50ZXIsIHRpbWUKZnJvbSBjb2xsZWN0aW9ucy5hYmMgaW1wb3J0IEl0ZXJhdG9yCmZyb20gcGF0aGxpYiBpbXBvcnQgUGF0aApmcm9tIGRhdGFjbGFzc2VzIGltcG9ydCBkYXRhY2xhc3MKZnJvbSBkYXRldGltZSBpbXBvcnQgZGF0ZXRpbWUKCiMgRXZpdGEgYXZpc29zICJhZHZpc29yeSIgcnVpZG9zb3MgZG8gdHJhbnNmb3JtZXJzIG5vIGZsdXhvIGludGVyYXRpdm8uCm9zLmVudmlyb24uc2V0ZGVmYXVsdCgiVFJBTlNGT1JNRVJTX05PX0FEVklTT1JZX1dBUk5JTkdTIiwgIjEiKQoKCmNsYXNzIF9Ub3JjaER0eXBlV2FybmluZ0ZpbHRlcihsb2dnaW5nLkZpbHRlcik6CiAgICBkZWYgZmlsdGVyKHNlbGYsIHJlY29yZDogbG9nZ2luZy5Mb2dSZWNvcmQpIC0+IGJvb2w6CiAgICAgICAgcmV0dXJuICJgdG9yY2hfZHR5cGVgIGlzIGRlcHJlY2F0ZWQhIFVzZSBgZHR5cGVgIGluc3RlYWQhIiBub3QgaW4gcmVjb3JkLmdldE1lc3NhZ2UoKQoKCmZvciBfbG9nZ2VyX25hbWUgaW4gKCJ0cmFuc2Zvcm1lcnMuY29uZmlndXJhdGlvbl91dGlscyIsICJ0cmFuc2Zvcm1lcnMubW9kZWxpbmdfdXRpbHMiKToKICAgIGxvZ2dpbmcuZ2V0TG9nZ2VyKF9sb2dnZXJfbmFtZSkuYWRkRmlsdGVyKF9Ub3JjaER0eXBlV2FybmluZ0ZpbHRlcigpKQoKaW1wb3J0IGNocm9tYWRiCmZyb20gc2VudGVuY2VfdHJhbnNmb3JtZXJzIGltcG9ydCBTZW50ZW5jZVRyYW5zZm9ybWVyCmZyb20gbGFuZ2NoYWluX3RleHRfc3BsaXR0ZXJzIGltcG9ydCBSZWN1cnNpdmVDaGFyYWN0ZXJUZXh0U3BsaXR0ZXIKZnJvbSB0cWRtIGltcG9ydCB0cWRtCmZyb20gZG93bmxvYWRfbW9kZWxfZnJvbV9odWdnaW5mYWNlIGltcG9ydCBkb3dubG9hZF9tb2RlbF93aXRoX2ZhbGxiYWNrCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIENvbmZpZ3VyYcOnw7VlcyBnbG9iYWlzCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgoKZGVmIF9lbnZfaW50KG5hbWU6IHN0ciwgZGVmYXVsdDogaW50LCAqLCBtaW5fdmFsdWU6IGludCA9IDEpIC0+IGludDoKICAgIHJhdyA9IG9zLmVudmlyb24uZ2V0KG5hbWUpCiAgICBpZiByYXcgaXMgTm9uZToKICAgICAgICByZXR1cm4gbWF4KG1pbl92YWx1ZSwgZGVmYXVsdCkKICAgIHRyeToKICAgICAgICByZXR1cm4gbWF4KG1pbl92YWx1ZSwgaW50KHJhdykpCiAgICBleGNlcHQgVmFsdWVFcnJvcjoKICAgICAgICByZXR1cm4gbWF4KG1pbl92YWx1ZSwgZGVmYXVsdCkKCkNIUk9NQV9IT1NUID0gImxvY2FsaG9zdCIKQ0hST01BX1BPUlQgPSBfZW52X2ludCgiTUNQX0NIUk9NQV9QT1JUIiwgODAwMCwgbWluX3ZhbHVlPTEpCkNPTExFQ1RJT05fQ09ERV9KSU5BID0gImNvZGVfdmVjdG9yc19qaW5hIgpDT0xMRUNUSU9OX0RPQ19CR0UgPSAiZG9jX3ZlY3RvcnNfYmdlIgoKIyBQYXN0YXMgZSBleHRlbnPDtWVzIGlnbm9yYWRhcyBkdXJhbnRlIGEgdmFycmVkdXJhCklHTk9SRURfRElSUyA9IHsKICAgICIuZ2l0IiwgIm5vZGVfbW9kdWxlcyIsICJfX3B5Y2FjaGVfXyIsICIudmVudiIsICJ2ZW52IiwgImVudiIsCiAgICAiZGlzdCIsICJidWlsZCIsICJvdXQiLCAiLm5leHQiLCAiLm51eHQiLCAiLmNhY2hlIiwgImNvdmVyYWdlIiwKICAgICIucHl0ZXN0X2NhY2hlIiwgIi5teXB5X2NhY2hlIiwgIi5ydWZmX2NhY2hlIiwgInRhcmdldCIsICJiaW4iLCAib2JqIiwKICAgICIuaWRlYSIsICIudnNjb2RlIiwgIi5EU19TdG9yZSIsICJ2ZW5kb3IiLCAidG1wIiwgInRlbXAiLCAibG9ncyIsCiAgICAiLnJhZ19kYiIsCn0KCklHTk9SRURfRVhURU5TSU9OUyA9IHsKICAgICMgQmluw6FyaW9zIGUgaW1hZ2VucwogICAgIi5wbmciLCAiLmpwZyIsICIuanBlZyIsICIuZ2lmIiwgIi5zdmciLCAiLmljbyIsICIud2VicCIsICIuYm1wIiwKICAgICIubXA0IiwgIi5tcDMiLCAiLndhdiIsICIub2dnIiwgIi5hdmkiLCAiLm1vdiIsCiAgICAjIFBhY290ZXMgZSBjb21waWxhZG9zCiAgICAiLnppcCIsICIudGFyIiwgIi5neiIsICIucmFyIiwgIi43eiIsICIuamFyIiwgIi53YXIiLCAiLmVhciIsCiAgICAiLnB5YyIsICIucHlvIiwgIi5zbyIsICIuZGxsIiwgIi5leGUiLCAiLmJpbiIsCiAgICAjIExvY2tmaWxlcyBlIGdlcmFkb3MKICAgICIubG9jayIsICIuc3VtIiwKICAgICMgQmFuY28gZGUgZGFkb3MKICAgICIuc3FsaXRlIiwgIi5kYiIsICIuc3FsaXRlMyIsCiAgICAjIEZvbnRlcwogICAgIi50dGYiLCAiLndvZmYiLCAiLndvZmYyIiwgIi5lb3QiLAogICAgIyBQREYvRG9jdW1lbnRvcyBiaW7DoXJpb3MKICAgICIucGRmIiwgIi5kb2N4IiwgIi54bHN4IiwgIi5wcHR4IiwKfQoKQ09ERV9FWFRFTlNJT05TID0gewogICAgIi5weSIsICIuanMiLCAiLnRzIiwgIi50c3giLCAiLmpzeCIsICIuamF2YSIsICIuYyIsICIuaCIsICIuY3BwIiwgIi5ocHAiLAogICAgIi5nbyIsICIucnMiLCAiLnJiIiwgIi5waHAiLCAiLmNzIiwgIi5zd2lmdCIsICIua3QiLCAiLmt0cyIsICIuc2NhbGEiLCAiLnNxbCIsCiAgICAiLnNoIiwgIi5iYXNoIiwgIi56c2giLCAiLnBzMSIsICIueWFtbCIsICIueW1sIiwgIi50b21sIiwgIi5pbmkiLCAiLmNvbmYiLAogICAgIi5qc29uIiwgIi54bWwiLCAiLmh0bWwiLCAiLmNzcyIsICIuc2NzcyIsICIuc2FzcyIsICIudnVlIiwgIi5zdmVsdGUiLCAiLmRhcnQiLAogICAgIi5sdWEiLCAiLnIiLCAiLm0iLCAiLm1tIiwKfQoKRE9DX0VYVEVOU0lPTlMgPSB7CiAgICAiLm1kIiwgIi5tZHgiLCAiLnJzdCIsICIudHh0IiwgIi5hZG9jIiwgIi5vcmciLCAiLnRleCIsICIuY3N2IiwKfQoKIyBUYW1hbmhvIG3DoXhpbW8gZGUgYXJxdWl2byAoZXZpdGEgaW5kZXhhciBhcnF1aXZvcyBlbm9ybWVzIGdlcmFkb3MpCk1BWF9GSUxFX1NJWkVfQllURVMgPSA1MDAgKiAxMDI0ICAjIDUwMCBLQgoKIyBQYXLDom1ldHJvcyBkbyBzcGxpdHRlciBlIGJhdGNoIChwZXJmaWwgbG93LW1lbW9yeSBwb3IgcGFkcsOjbykuCkNIVU5LX1NJWkUgPSBfZW52X2ludCgiTUNQX0NIVU5LX1NJWkUiLCAzMDAwLCBtaW5fdmFsdWU9MjU2KQpDSFVOS19PVkVSTEFQID0gbWluKENIVU5LX1NJWkUgLSAxLCBfZW52X2ludCgiTUNQX0NIVU5LX09WRVJMQVAiLCA0MDAsIG1pbl92YWx1ZT0wKSkKRU1CRURESU5HX0JBVENIX1NJWkUgPSBfZW52X2ludCgiTUNQX0VNQkVERElOR19CQVRDSF9TSVpFIiwgNCwgbWluX3ZhbHVlPTEpCkRFRkFVTFRfUEVSRl9QUk9GSUxFID0gImF1dG90dW5lIgpJTkRFWEVSX0NPTkZJR19QQVRIID0gUGF0aCgKICAgIG9zLmVudmlyb24uZ2V0KCJNQ1BfSU5ERVhFUl9DT05GSUdfRklMRSIsIHN0cihQYXRoLmhvbWUoKSAvICIucmFnX2RiIiAvICJpbmRleGVyX3R1bmluZy5qc29uIikpCikuZXhwYW5kdXNlcigpCklOREVYRVJfQ09ORklHX0ZBTExCQUNLX1BBVEggPSBQYXRoLmhvbWUoKSAvICIuY2FjaGUiIC8gIm15LWN1c3RvbS1yYWctcHl0aG9uIiAvICJpbmRleGVyX3R1bmluZy5qc29uIgoKIyBNb2RlbG8gZGUgZW1iZWRkaW5ncyAocm9kYSBuYSBDUFUpCkpJTkFfVjNfRU1CRURESU5HX01PREVMID0gImppbmFhaS9qaW5hLWVtYmVkZGluZ3MtdjMiCkpJTkFfVjJfRU1CRURESU5HX01PREVMID0gImppbmFhaS9qaW5hLWVtYmVkZGluZ3MtdjItYmFzZS1jb2RlIgpCR0VfRU1CRURESU5HX01PREVMID0gIkJBQUkvYmdlLW0zIgpERUZBVUxUX0VNQkVERElOR19NT0RFTF9DSE9JQ0UgPSAiamluYSIKREVGQVVMVF9KSU5BX1FVQU5USVpBVElPTiA9ICJkeW5hbWljLWludDgiCk1PREVMX0NBQ0hFX0JBU0VfRElSID0gUGF0aCgKICAgIG9zLmVudmlyb24uZ2V0KCJNQ1BfTU9ERUxfRElSIiwgc3RyKFBhdGguaG9tZSgpIC8gIi5jYWNoZSIgLyAibXktY3VzdG9tLXJhZy1weXRob24iIC8gIm1vZGVscyIpKQopLmV4cGFuZHVzZXIoKQpKSU5BX1JFQ09NTUVOREVEX1JBTV9HQl9ERUZBVUxUID0gNjQKSklOQV9SRUNPTU1FTkRFRF9SQU1fR0JfRFlOQU1JQ19JTlQ4ID0gNDgKSklOQV9SRUNPTU1FTkRFRF9TV0FQX0dCID0gMTYKSklOQV9NSU5fQVZBSUxBQkxFX1JBTV9HQl9ISU5UID0gMTIKCgpkZWYgX2Vudl9ib29sKG5hbWU6IHN0ciwgZGVmYXVsdDogYm9vbCA9IEZhbHNlKSAtPiBib29sOgogICAgcmF3ID0gb3MuZW52aXJvbi5nZXQobmFtZSkKICAgIGlmIHJhdyBpcyBOb25lOgogICAgICAgIHJldHVybiBkZWZhdWx0CiAgICByZXR1cm4gcmF3LnN0cmlwKCkubG93ZXIoKSBpbiB7IjEiLCAidHJ1ZSIsICJ5ZXMiLCAib24ifQoKCmRlZiBfY2xhbXAodmFsdWU6IGZsb2F0LCBsb3c6IGZsb2F0LCBoaWdoOiBmbG9hdCkgLT4gZmxvYXQ6CiAgICByZXR1cm4gbWF4KGxvdywgbWluKGhpZ2gsIHZhbHVlKSkKCgpkZWYgX2lzX21lbW9yeV9yZWxhdGVkX2Vycm9yKGV4YzogRXhjZXB0aW9uKSAtPiBib29sOgogICAgaWYgaXNpbnN0YW5jZShleGMsIE1lbW9yeUVycm9yKToKICAgICAgICByZXR1cm4gVHJ1ZQogICAgbXNnID0gc3RyKGV4YykubG93ZXIoKQogICAgbWVtb3J5X21hcmtlcnMgPSAoCiAgICAgICAgIm91dCBvZiBtZW1vcnkiLAogICAgICAgICJvb20iLAogICAgICAgICJjYW5ub3QgYWxsb2NhdGUgbWVtb3J5IiwKICAgICAgICAic3RkOjpiYWRfYWxsb2MiLAogICAgICAgICJiYWQgYWxsb2MiLAogICAgICAgICJpbnN1ZmZpY2llbnQgbWVtb3J5IiwKICAgICkKICAgIHJldHVybiBhbnkobWFya2VyIGluIG1zZyBmb3IgbWFya2VyIGluIG1lbW9yeV9tYXJrZXJzKQoKCmRlZiBfaXNfZGltZW5zaW9uX21pc21hdGNoX2Vycm9yKGV4YzogRXhjZXB0aW9uKSAtPiBib29sOgogICAgbXNnID0gc3RyKGV4YykubG93ZXIoKQogICAgcmV0dXJuICgKICAgICAgICAiZXhwZWN0aW5nIGVtYmVkZGluZyB3aXRoIGRpbWVuc2lvbiIgaW4gbXNnCiAgICAgICAgb3IgKCJlbWJlZGRpbmciIGluIG1zZyBhbmQgImRpbWVuc2lvbiIgaW4gbXNnIGFuZCAiZ290IiBpbiBtc2cpCiAgICApCgoKZGVmIF9mb3JtYXRfZXhjZXB0aW9uKGV4YzogRXhjZXB0aW9uKSAtPiBzdHI6CiAgICBtZXNzYWdlID0gc3RyKGV4Yykuc3RyaXAoKQogICAgaWYgbWVzc2FnZToKICAgICAgICByZXR1cm4gbWVzc2FnZQogICAgcmV0dXJuIHJlcHIoZXhjKQoKCkBkYXRhY2xhc3MoZnJvemVuPVRydWUpCmNsYXNzIEluZGV4VGFyZ2V0OgogICAgbW9kZWxfY2hvaWNlOiBzdHIKICAgIGNvbGxlY3Rpb25fbmFtZTogc3RyCiAgICBsYWJlbDogc3RyCgoKZGVmIF9yZXNvbHZlX21vZGVsX2lkKG1vZGVsX2Nob2ljZTogc3RyKSAtPiBzdHI6CiAgICBpZiBtb2RlbF9jaG9pY2UgPT0gImppbmEiOgogICAgICAgIHJldHVybiBKSU5BX1YzX0VNQkVERElOR19NT0RFTAogICAgaWYgbW9kZWxfY2hvaWNlID09ICJqaW5hLXYyIjoKICAgICAgICByZXR1cm4gSklOQV9WMl9FTUJFRERJTkdfTU9ERUwKICAgIGlmIG1vZGVsX2Nob2ljZSA9PSAiYmdlIjoKICAgICAgICByZXR1cm4gQkdFX0VNQkVERElOR19NT0RFTAogICAgcmFpc2UgVmFsdWVFcnJvcihmIk1vZGVsbyBuw6NvIHN1cG9ydGFkbzoge21vZGVsX2Nob2ljZX0iKQoKCmRlZiBfcmVzb2x2ZV9mYWxsYmFja19tb2RlbF9pZChtb2RlbF9jaG9pY2U6IHN0cikgLT4gc3RyOgogICAgcmV0dXJuIEJHRV9FTUJFRERJTkdfTU9ERUwKCgpkZWYgX2Rlc2NyaWJlX2VtYmVkZGluZ19jaG9pY2UobW9kZWxfY2hvaWNlOiBzdHIpIC0+IHN0cjoKICAgIGlmIG1vZGVsX2Nob2ljZSA9PSAiamluYSI6CiAgICAgICAgcmV0dXJuIGYiamluYSAoe0pJTkFfVjNfRU1CRURESU5HX01PREVMfSkiCiAgICBpZiBtb2RlbF9jaG9pY2UgPT0gImJnZSI6CiAgICAgICAgcmV0dXJuIGYiYmdlICh7QkdFX0VNQkVERElOR19NT0RFTH0pIgogICAgaWYgbW9kZWxfY2hvaWNlID09ICJoeWJyaWQiOgogICAgICAgIHJldHVybiBmImh5YnJpZCAoe0pJTkFfVjJfRU1CRURESU5HX01PREVMfSArIHtCR0VfRU1CRURESU5HX01PREVMfSkiCiAgICByZXR1cm4gbW9kZWxfY2hvaWNlCgoKZGVmIF9yZXNvbHZlX2luZGV4X3RhcmdldHMobW9kZWxfY2hvaWNlOiBzdHIpIC0+IGxpc3RbSW5kZXhUYXJnZXRdOgogICAgaWYgbW9kZWxfY2hvaWNlID09ICJqaW5hIjoKICAgICAgICByZXR1cm4gWwogICAgICAgICAgICBJbmRleFRhcmdldCgKICAgICAgICAgICAgICAgIG1vZGVsX2Nob2ljZT0iamluYSIsCiAgICAgICAgICAgICAgICBjb2xsZWN0aW9uX25hbWU9Q09MTEVDVElPTl9DT0RFX0pJTkEsCiAgICAgICAgICAgICAgICBsYWJlbD0iQ29kZS9KaW5hIiwKICAgICAgICAgICAgKQogICAgICAgIF0KICAgIGlmIG1vZGVsX2Nob2ljZSA9PSAiYmdlIjoKICAgICAgICByZXR1cm4gWwogICAgICAgICAgICBJbmRleFRhcmdldCgKICAgICAgICAgICAgICAgIG1vZGVsX2Nob2ljZT0iYmdlIiwKICAgICAgICAgICAgICAgIGNvbGxlY3Rpb25fbmFtZT1DT0xMRUNUSU9OX0RPQ19CR0UsCiAgICAgICAgICAgICAgICBsYWJlbD0iRG9jL0JHRSIsCiAgICAgICAgICAgICkKICAgICAgICBdCiAgICBpZiBtb2RlbF9jaG9pY2UgPT0gImh5YnJpZCI6CiAgICAgICAgcmV0dXJuIFsKICAgICAgICAgICAgSW5kZXhUYXJnZXQoCiAgICAgICAgICAgICAgICBtb2RlbF9jaG9pY2U9ImppbmEtdjIiLAogICAgICAgICAgICAgICAgY29sbGVjdGlvbl9uYW1lPUNPTExFQ1RJT05fQ09ERV9KSU5BLAogICAgICAgICAgICAgICAgbGFiZWw9IkNvZGUvSmluYSB2MiIsCiAgICAgICAgICAgICksCiAgICAgICAgICAgIEluZGV4VGFyZ2V0KAogICAgICAgICAgICAgICAgbW9kZWxfY2hvaWNlPSJiZ2UiLAogICAgICAgICAgICAgICAgY29sbGVjdGlvbl9uYW1lPUNPTExFQ1RJT05fRE9DX0JHRSwKICAgICAgICAgICAgICAgIGxhYmVsPSJEb2MvQkdFIiwKICAgICAgICAgICAgKSwKICAgICAgICBdCiAgICByYWlzZSBWYWx1ZUVycm9yKGYiTW9kZWxvIG7Do28gc3Vwb3J0YWRvOiB7bW9kZWxfY2hvaWNlfSIpCgoKZGVmIF9jbGFzc2lmeV9maWxlX3RhcmdldHMoZmlsZXBhdGg6IFBhdGgsIG1vZGVsX2Nob2ljZTogc3RyKSAtPiBzZXRbc3RyXToKICAgIGlmIG1vZGVsX2Nob2ljZSAhPSAiaHlicmlkIjoKICAgICAgICByZXR1cm4ge21vZGVsX2Nob2ljZX0KCiAgICBzdWZmaXggPSBmaWxlcGF0aC5zdWZmaXgubG93ZXIoKQogICAgaXNfY29kZSA9IHN1ZmZpeCBpbiBDT0RFX0VYVEVOU0lPTlMKICAgIGlzX2RvYyA9IHN1ZmZpeCBpbiBET0NfRVhURU5TSU9OUwoKICAgIGlmIGlzX2NvZGUgYW5kIG5vdCBpc19kb2M6CiAgICAgICAgcmV0dXJuIHsiamluYS12MiJ9CiAgICBpZiBpc19kb2MgYW5kIG5vdCBpc19jb2RlOgogICAgICAgIHJldHVybiB7ImJnZSJ9CgogICAgIyBFeHRlbnPDo28gZGVzY29uaGVjaWRhL2FtYsOtZ3VhOiBpbmRleGEgbm9zIGRvaXMgcmFtb3MgcGFyYSBtYW50ZXIgcmVjYWxsLgogICAgcmV0dXJuIHsiamluYS12MiIsICJiZ2UifQoKCmRlZiBfbW9kZWxfY2FjaGVfZGlyKGJhc2VfZGlyOiBQYXRoLCBtb2RlbF9pZDogc3RyKSAtPiBQYXRoOgogICAgc2FmZV9uYW1lID0gbW9kZWxfaWQucmVwbGFjZSgiLyIsICJfXyIpLnJlcGxhY2UoIjoiLCAiXyIpCiAgICByZXR1cm4gYmFzZV9kaXIgLyBzYWZlX25hbWUKCgpkZWYgX3BpY2tfd2l0aF9wcm9tcHQoCiAgICAqLAogICAgY3VycmVudF92YWx1ZTogc3RyIHwgTm9uZSwKICAgIGRlZmF1bHRfdmFsdWU6IHN0ciwKICAgIHRpdGxlOiBzdHIsCiAgICBvcHRpb25zOiBsaXN0W3R1cGxlW3N0ciwgc3RyXV0sCikgLT4gc3RyOgogICAgaWYgY3VycmVudF92YWx1ZToKICAgICAgICByZXR1cm4gY3VycmVudF92YWx1ZQogICAgaWYgbm90IHN5cy5zdGRpbi5pc2F0dHkoKToKICAgICAgICByZXR1cm4gZGVmYXVsdF92YWx1ZQoKICAgIHByaW50KGYiXG5bQ09ORklHXSB7dGl0bGV9IikKICAgIGZvciBpbmRleCwgKF8sIGRlc2NyaXB0aW9uKSBpbiBlbnVtZXJhdGUob3B0aW9ucywgc3RhcnQ9MSk6CiAgICAgICAgcHJpbnQoZiIgIHtpbmRleH0pIHtkZXNjcmlwdGlvbn0iKQogICAgcHJpbnQoZiIgIEVudGVyID0gcGFkcsOjbyAoe2RlZmF1bHRfdmFsdWV9KSIpCgogICAgYW5zd2VyID0gaW5wdXQoIj4gRXNjb2xoYTogIikuc3RyaXAoKQogICAgaWYgbm90IGFuc3dlcjoKICAgICAgICByZXR1cm4gZGVmYXVsdF92YWx1ZQogICAgaWYgYW5zd2VyLmlzZGlnaXQoKToKICAgICAgICBpZHggPSBpbnQoYW5zd2VyKSAtIDEKICAgICAgICBpZiAwIDw9IGlkeCA8IGxlbihvcHRpb25zKToKICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnNbaWR4XVswXQogICAgbG93ZXJlZCA9IGFuc3dlci5sb3dlcigpCiAgICB2YWxpZF9rZXlzID0ge2sgZm9yIGssIF8gaW4gb3B0aW9uc30KICAgIGlmIGxvd2VyZWQgaW4gdmFsaWRfa2V5czoKICAgICAgICByZXR1cm4gbG93ZXJlZAogICAgcHJpbnQoZiJbQVZJU09dIE9ww6fDo28gaW52w6FsaWRhICd7YW5zd2VyfScuIFVzYW5kbyBwYWRyw6NvOiB7ZGVmYXVsdF92YWx1ZX0iKQogICAgcmV0dXJuIGRlZmF1bHRfdmFsdWUKCgpkZWYgcmVzb2x2ZV9lbWJlZGRpbmdfY29uZmlnKAogICAgbW9kZWxfY2hvaWNlX2FyZzogc3RyIHwgTm9uZSwKICAgIGppbmFfcXVhbnRpemF0aW9uX2FyZzogc3RyIHwgTm9uZSwKICAgIHBlcnNpc3RlZF9jb25maWc6IGRpY3Rbc3RyLCBvYmplY3RdIHwgTm9uZSA9IE5vbmUsCikgLT4gdHVwbGVbc3RyLCBzdHJdOgogICAgcGVyc2lzdGVkX2NvbmZpZyA9IHBlcnNpc3RlZF9jb25maWcgb3Ige30KICAgIG1vZGVsX2Nob2ljZV9mcm9tX2NvbmZpZyA9IHBlcnNpc3RlZF9jb25maWcuZ2V0KCJlbWJlZGRpbmdfbW9kZWwiKQogICAgbW9kZWxfY2hvaWNlID0gbW9kZWxfY2hvaWNlX2FyZyBvciBvcy5lbnZpcm9uLmdldCgiTUNQX0VNQkVERElOR19NT0RFTCIpCiAgICBpZiBub3QgbW9kZWxfY2hvaWNlIGFuZCBpc2luc3RhbmNlKG1vZGVsX2Nob2ljZV9mcm9tX2NvbmZpZywgc3RyKToKICAgICAgICBtb2RlbF9jaG9pY2UgPSBtb2RlbF9jaG9pY2VfZnJvbV9jb25maWcKICAgIGlmIG1vZGVsX2Nob2ljZToKICAgICAgICBtb2RlbF9jaG9pY2UgPSBtb2RlbF9jaG9pY2Uuc3RyaXAoKS5sb3dlcigpCiAgICBtb2RlbF9jaG9pY2UgPSBfcGlja193aXRoX3Byb21wdCgKICAgICAgICBjdXJyZW50X3ZhbHVlPW1vZGVsX2Nob2ljZSwKICAgICAgICBkZWZhdWx0X3ZhbHVlPURFRkFVTFRfRU1CRURESU5HX01PREVMX0NIT0lDRSwKICAgICAgICB0aXRsZT0iRXNjb2xoYSBkbyBtb2RlbG8gZGUgZW1iZWRkaW5ncyIsCiAgICAgICAgb3B0aW9ucz1bCiAgICAgICAgICAgICgKICAgICAgICAgICAgICAgICJqaW5hIiwKICAgICAgICAgICAgICAgIGYiamluYSAoe0pJTkFfVjNfRU1CRURESU5HX01PREVMfSkgLSBmb2NvIGVtIGPDs2RpZ28uIiwKICAgICAgICAgICAgKSwKICAgICAgICAgICAgKAogICAgICAgICAgICAgICAgImJnZSIsCiAgICAgICAgICAgICAgICBmImJnZSAoe0JHRV9FTUJFRERJTkdfTU9ERUx9KSAtIGNvbnRlw7pkbyBtaXN0by4iLAogICAgICAgICAgICApLAogICAgICAgICAgICAoCiAgICAgICAgICAgICAgICAiaHlicmlkIiwKICAgICAgICAgICAgICAgIGYiaHlicmlkIChKaW5hIHYyIHtKSU5BX1YyX0VNQkVERElOR19NT0RFTH0gKyBCR0UpIC0gZHVhcyBjb2xlw6fDtWVzLiIsCiAgICAgICAgICAgICksCiAgICAgICAgXSwKICAgICkKICAgIGlmIG1vZGVsX2Nob2ljZSBub3QgaW4geyJqaW5hIiwgImJnZSIsICJoeWJyaWQifToKICAgICAgICBwcmludChmIltBVklTT10gTUNQX0VNQkVERElOR19NT0RFTCBpbnbDoWxpZG8gJ3ttb2RlbF9jaG9pY2V9Jy4gVXNhbmRvICd7REVGQVVMVF9FTUJFRERJTkdfTU9ERUxfQ0hPSUNFfScuIikKICAgICAgICBtb2RlbF9jaG9pY2UgPSBERUZBVUxUX0VNQkVERElOR19NT0RFTF9DSE9JQ0UKCiAgICBxdWFudGl6YXRpb25fZnJvbV9jb25maWcgPSBwZXJzaXN0ZWRfY29uZmlnLmdldCgiamluYV9xdWFudGl6YXRpb24iKQogICAgamluYV9xdWFudGl6YXRpb24gPSBqaW5hX3F1YW50aXphdGlvbl9hcmcgb3Igb3MuZW52aXJvbi5nZXQoIk1DUF9KSU5BX1FVQU5USVpBVElPTiIpCiAgICBpZiBub3QgamluYV9xdWFudGl6YXRpb24gYW5kIGlzaW5zdGFuY2UocXVhbnRpemF0aW9uX2Zyb21fY29uZmlnLCBzdHIpOgogICAgICAgIGppbmFfcXVhbnRpemF0aW9uID0gcXVhbnRpemF0aW9uX2Zyb21fY29uZmlnCiAgICBpZiBqaW5hX3F1YW50aXphdGlvbjoKICAgICAgICBqaW5hX3F1YW50aXphdGlvbiA9IGppbmFfcXVhbnRpemF0aW9uLnN0cmlwKCkubG93ZXIoKS5yZXBsYWNlKCJfIiwgIi0iKQoKICAgIGlmIG1vZGVsX2Nob2ljZSA9PSAiamluYSI6CiAgICAgICAgamluYV9xdWFudGl6YXRpb24gPSBfcGlja193aXRoX3Byb21wdCgKICAgICAgICAgICAgY3VycmVudF92YWx1ZT1qaW5hX3F1YW50aXphdGlvbiwKICAgICAgICAgICAgZGVmYXVsdF92YWx1ZT1ERUZBVUxUX0pJTkFfUVVBTlRJWkFUSU9OLAogICAgICAgICAgICB0aXRsZT0iUXVhbnRpemFjYW8gZG8gSmluYSAoYXBlbmFzIHBhcmEgQ1BVKSIsCiAgICAgICAgICAgIG9wdGlvbnM9WwogICAgICAgICAgICAgICAgKCJkZWZhdWx0IiwgImRlZmF1bHQgKHNlbSBxdWFudGl6YWNhbykgLSBtYWlvciBxdWFsaWRhZGUsIGluZGV4YWNhbyBtYWlzIGxlbnRhLiIpLAogICAgICAgICAgICAgICAgKCJkeW5hbWljLWludDgiLCAiZHluYW1pYy1pbnQ4IC0gaW5kZXhhY2FvIG1haXMgcmFwaWRhIGUgbWVub3IgdXNvIGRlIFJBTSwgY29tIHBlcXVlbmEgcGVyZGEgZGUgcXVhbGlkYWRlLiIpLAogICAgICAgICAgICBdLAogICAgICAgICkKICAgICAgICBpZiBqaW5hX3F1YW50aXphdGlvbiBub3QgaW4geyJkZWZhdWx0IiwgImR5bmFtaWMtaW50OCJ9OgogICAgICAgICAgICBwcmludCgKICAgICAgICAgICAgICAgIGYiW0FWSVNPXSBNQ1BfSklOQV9RVUFOVElaQVRJT04gaW52w6FsaWRvICd7amluYV9xdWFudGl6YXRpb259Jy4gIgogICAgICAgICAgICAgICAgZiJVc2FuZG8gJ3tERUZBVUxUX0pJTkFfUVVBTlRJWkFUSU9OfScuIgogICAgICAgICAgICApCiAgICAgICAgICAgIGppbmFfcXVhbnRpemF0aW9uID0gREVGQVVMVF9KSU5BX1FVQU5USVpBVElPTgogICAgZWxzZToKICAgICAgICBqaW5hX3F1YW50aXphdGlvbiA9ICJkZWZhdWx0IgoKICAgIHJldHVybiBtb2RlbF9jaG9pY2UsIGppbmFfcXVhbnRpemF0aW9uCgoKZGVmIF9pbmRleGVyX2NvbmZpZ19jYW5kaWRhdGVzKCkgLT4gbGlzdFtQYXRoXToKICAgIGNhbmRpZGF0ZXMgPSBbSU5ERVhFUl9DT05GSUdfUEFUSF0KICAgIGlmIElOREVYRVJfQ09ORklHX0ZBTExCQUNLX1BBVEggbm90IGluIGNhbmRpZGF0ZXM6CiAgICAgICAgY2FuZGlkYXRlcy5hcHBlbmQoSU5ERVhFUl9DT05GSUdfRkFMTEJBQ0tfUEFUSCkKICAgIHJldHVybiBjYW5kaWRhdGVzCgoKZGVmIGxvYWRfaW5kZXhlcl90dW5pbmdfY29uZmlnKGZvcmNlX3JlY29uZmlndXJlOiBib29sKSAtPiBkaWN0W3N0ciwgb2JqZWN0XToKICAgIGlmIGZvcmNlX3JlY29uZmlndXJlOgogICAgICAgIHJldHVybiB7fQogICAgZm9yIGNhbmRpZGF0ZSBpbiBfaW5kZXhlcl9jb25maWdfY2FuZGlkYXRlcygpOgogICAgICAgIHRyeToKICAgICAgICAgICAgaWYgbm90IGNhbmRpZGF0ZS5leGlzdHMoKToKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIGRhdGEgPSBqc29uLmxvYWRzKGNhbmRpZGF0ZS5yZWFkX3RleHQoZW5jb2Rpbmc9InV0Zi04IikpCiAgICAgICAgICAgIGlmIGlzaW5zdGFuY2UoZGF0YSwgZGljdCk6CiAgICAgICAgICAgICAgICByZXR1cm4gZGF0YQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgICAgIGNvbnRpbnVlCiAgICByZXR1cm4ge30KCgpkZWYgc2F2ZV9pbmRleGVyX3R1bmluZ19jb25maWcoY29uZmlnOiBkaWN0W3N0ciwgb2JqZWN0XSkgLT4gTm9uZToKICAgIHBheWxvYWQgPSB7CiAgICAgICAgKipjb25maWcsCiAgICAgICAgInVwZGF0ZWRfYXQiOiBpbnQodGltZSgpKSwKICAgIH0KICAgIHdyaXRlX2Vycm9yczogbGlzdFt0dXBsZVtQYXRoLCBFeGNlcHRpb25dXSA9IFtdCgogICAgZm9yIGNhbmRpZGF0ZSBpbiBfaW5kZXhlcl9jb25maWdfY2FuZGlkYXRlcygpOgogICAgICAgIHRyeToKICAgICAgICAgICAgY2FuZGlkYXRlLnBhcmVudC5ta2RpcihwYXJlbnRzPVRydWUsIGV4aXN0X29rPVRydWUpCiAgICAgICAgICAgIGNhbmRpZGF0ZS53cml0ZV90ZXh0KGpzb24uZHVtcHMocGF5bG9hZCwgZW5zdXJlX2FzY2lpPUZhbHNlLCBpbmRlbnQ9MikgKyAiXG4iLCBlbmNvZGluZz0idXRmLTgiKQogICAgICAgICAgICBpZiBjYW5kaWRhdGUgPT0gSU5ERVhFUl9DT05GSUdfUEFUSDoKICAgICAgICAgICAgICAgIHByaW50KGYiW0NPTkZJR10gQ29uZmlndXJhw6fDo28gcGVyc2lzdGlkYSBlbToge2NhbmRpZGF0ZX0iKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgcHJpbnQoCiAgICAgICAgICAgICAgICAgICAgZiJbQ09ORklHXSBDb25maWd1cmHDp8OjbyBwZXJzaXN0aWRhIGVtIGZhbGxiYWNrOiB7Y2FuZGlkYXRlfSAiCiAgICAgICAgICAgICAgICAgICAgZiIoZGVzdGlubyBwcmltw6FyaW8gc2VtIHBlcm1pc3PDo286IHtJTkRFWEVSX0NPTkZJR19QQVRIfSkiCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIHJldHVybgogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgd3JpdGVfZXJyb3JzLmFwcGVuZCgoY2FuZGlkYXRlLCBlKSkKCiAgICBkZXRhaWxzID0gIiB8ICIuam9pbihmIntwYXRofToge19mb3JtYXRfZXhjZXB0aW9uKGVycil9IiBmb3IgcGF0aCwgZXJyIGluIHdyaXRlX2Vycm9ycykKICAgIHByaW50KGYiW0FWSVNPXSBOw6NvIGZvaSBwb3Nzw612ZWwgcGVyc2lzdGlyIGNvbmZpZ3VyYcOnw6NvOiB7ZGV0YWlsc30iKQoKCmRlZiByZXNvbHZlX3BlcmZfcHJvZmlsZShwZXJmX3Byb2ZpbGVfYXJnOiBzdHIgfCBOb25lLCBwZXJzaXN0ZWRfY29uZmlnOiBkaWN0W3N0ciwgb2JqZWN0XSkgLT4gc3RyOgogICAgcHJvZmlsZV9mcm9tX2NvbmZpZyA9IHBlcnNpc3RlZF9jb25maWcuZ2V0KCJwZXJmX3Byb2ZpbGUiKQogICAgcHJvZmlsZSA9IHBlcmZfcHJvZmlsZV9hcmcgb3Igb3MuZW52aXJvbi5nZXQoIk1DUF9QRVJGX1BST0ZJTEUiKQogICAgaWYgbm90IHByb2ZpbGUgYW5kIGlzaW5zdGFuY2UocHJvZmlsZV9mcm9tX2NvbmZpZywgc3RyKToKICAgICAgICBwcm9maWxlID0gcHJvZmlsZV9mcm9tX2NvbmZpZwogICAgaWYgcHJvZmlsZToKICAgICAgICBwcm9maWxlID0gcHJvZmlsZS5zdHJpcCgpLmxvd2VyKCkKCiAgICBwcm9maWxlID0gX3BpY2tfd2l0aF9wcm9tcHQoCiAgICAgICAgY3VycmVudF92YWx1ZT1wcm9maWxlLAogICAgICAgIGRlZmF1bHRfdmFsdWU9REVGQVVMVF9QRVJGX1BST0ZJTEUsCiAgICAgICAgdGl0bGU9IlBlcmZpbCBkZSBwZXJmb3JtYW5jZSBkYSBpbmRleGHDp8OjbyIsCiAgICAgICAgb3B0aW9ucz1bCiAgICAgICAgICAgICgKICAgICAgICAgICAgICAgICJhdXRvdHVuZSIsCiAgICAgICAgICAgICAgICAiYXV0b3R1bmUgLSBlcXVpbMOtYnJpbyAocmVjb21lbmRhZG8pLiIsCiAgICAgICAgICAgICksCiAgICAgICAgICAgICgKICAgICAgICAgICAgICAgICJtYXgtcGVyZm9ybWFuY2UiLAogICAgICAgICAgICAgICAgIm1heC1wZXJmb3JtYW5jZSAtIG3DoXhpbW8gdGhyb3VnaHB1dCAobWFpcyBSQU0pLiIsCiAgICAgICAgICAgICksCiAgICAgICAgXSwKICAgICkKICAgIGlmIHByb2ZpbGUgbm90IGluIHsiYXV0b3R1bmUiLCAibWF4LXBlcmZvcm1hbmNlIn06CiAgICAgICAgcHJpbnQoZiJbQVZJU09dIFBlcmZpbCBpbnbDoWxpZG8gJ3twcm9maWxlfScuIFVzYW5kbyAne0RFRkFVTFRfUEVSRl9QUk9GSUxFfScuIikKICAgICAgICBwcm9maWxlID0gREVGQVVMVF9QRVJGX1BST0ZJTEUKICAgIHJldHVybiBwcm9maWxlCgoKZGVmIF9wYXJzZV9jb25maWdfaW50KGNvbmZpZzogZGljdFtzdHIsIG9iamVjdF0sIGtleTogc3RyKSAtPiBpbnQgfCBOb25lOgogICAgcmF3ID0gY29uZmlnLmdldChrZXkpCiAgICBpZiBpc2luc3RhbmNlKHJhdywgaW50KToKICAgICAgICByZXR1cm4gcmF3CiAgICBpZiBpc2luc3RhbmNlKHJhdywgc3RyKSBhbmQgcmF3LmlzZGlnaXQoKToKICAgICAgICByZXR1cm4gaW50KHJhdykKICAgIHJldHVybiBOb25lCgoKZGVmIF9yZWFkX21lbWluZm9fZ2liKCkgLT4gdHVwbGVbZmxvYXQgfCBOb25lLCBmbG9hdCB8IE5vbmUsIGZsb2F0IHwgTm9uZV06CiAgICAiIiJSZXRvcm5hIChtZW1fdG90YWwsIG1lbV9hdmFpbGFibGUsIHN3YXBfdG90YWwpIGVtIEdpQiwgcXVhbmRvIGRpc3BvbsOtdmVsLiIiIgogICAgbWVtX3RvdGFsX2tpYjogaW50IHwgTm9uZSA9IE5vbmUKICAgIG1lbV9hdmFpbGFibGVfa2liOiBpbnQgfCBOb25lID0gTm9uZQogICAgc3dhcF90b3RhbF9raWI6IGludCB8IE5vbmUgPSBOb25lCgogICAgdHJ5OgogICAgICAgIGZvciBsaW5lIGluIFBhdGgoIi9wcm9jL21lbWluZm8iKS5yZWFkX3RleHQoZW5jb2Rpbmc9InV0Zi04Iikuc3BsaXRsaW5lcygpOgogICAgICAgICAgICBpZiBsaW5lLnN0YXJ0c3dpdGgoIk1lbVRvdGFsOiIpOgogICAgICAgICAgICAgICAgbWVtX3RvdGFsX2tpYiA9IGludChsaW5lLnNwbGl0KClbMV0pCiAgICAgICAgICAgIGVsaWYgbGluZS5zdGFydHN3aXRoKCJNZW1BdmFpbGFibGU6Iik6CiAgICAgICAgICAgICAgICBtZW1fYXZhaWxhYmxlX2tpYiA9IGludChsaW5lLnNwbGl0KClbMV0pCiAgICAgICAgICAgIGVsaWYgbGluZS5zdGFydHN3aXRoKCJTd2FwVG90YWw6Iik6CiAgICAgICAgICAgICAgICBzd2FwX3RvdGFsX2tpYiA9IGludChsaW5lLnNwbGl0KClbMV0pCiAgICBleGNlcHQgKE9TRXJyb3IsIFZhbHVlRXJyb3IsIEluZGV4RXJyb3IpOgogICAgICAgIHJldHVybiBOb25lLCBOb25lLCBOb25lCgogICAgdG9fZ2liID0gbGFtYmRhIGtpYjogKGtpYiAvICgxMDI0ICogMTAyNCkpIGlmIGtpYiBpcyBub3QgTm9uZSBlbHNlIE5vbmUKICAgIHJldHVybiB0b19naWIobWVtX3RvdGFsX2tpYiksIHRvX2dpYihtZW1fYXZhaWxhYmxlX2tpYiksIHRvX2dpYihzd2FwX3RvdGFsX2tpYikKCgpkZWYgd2Fybl9pZl9qaW5hX21lbW9yeV9yaXNrKG1vZGVsX2Nob2ljZTogc3RyLCBqaW5hX3F1YW50aXphdGlvbjogc3RyKSAtPiBOb25lOgogICAgIiIiTW9zdHJhIGF2aXNvIGRlIHJpc2NvIGRlIE9PTSBwYXJhIG8gbW9kZWxvIEppbmEgZW0gbcOhcXVpbmFzIGNvbSBwb3VjYSBtZW3Ds3JpYS4iIiIKICAgIGlmIG1vZGVsX2Nob2ljZSBub3QgaW4geyJqaW5hIiwgImh5YnJpZCJ9OgogICAgICAgIHJldHVybgoKICAgIG1lbV90b3RhbF9naWIsIG1lbV9hdmFpbGFibGVfZ2liLCBzd2FwX3RvdGFsX2dpYiA9IF9yZWFkX21lbWluZm9fZ2liKCkKICAgIGlmIG1lbV90b3RhbF9naWIgaXMgTm9uZToKICAgICAgICByZXR1cm4KCiAgICByZWNvbW1lbmRlZF9yYW1fZ2liID0gKAogICAgICAgIEpJTkFfUkVDT01NRU5ERURfUkFNX0dCX0RFRkFVTFQKICAgICAgICBpZiBqaW5hX3F1YW50aXphdGlvbiA9PSAiZGVmYXVsdCIKICAgICAgICBlbHNlIEpJTkFfUkVDT01NRU5ERURfUkFNX0dCX0RZTkFNSUNfSU5UOAogICAgKQoKICAgIHJlYXNvbnM6IGxpc3Rbc3RyXSA9IFtdCiAgICBpZiBtZW1fdG90YWxfZ2liIDwgcmVjb21tZW5kZWRfcmFtX2dpYjoKICAgICAgICByZWFzb25zLmFwcGVuZCgKICAgICAgICAgICAgZiJSQU0gdG90YWwgZGV0ZWN0YWRhOiB7bWVtX3RvdGFsX2dpYjouMWZ9IEdpQiAocmVjb21lbmRhZG8gPj0ge3JlY29tbWVuZGVkX3JhbV9naWJ9IEdpQiBwYXJhIEppbmEve2ppbmFfcXVhbnRpemF0aW9ufSkuIgogICAgICAgICkKICAgIGlmIHN3YXBfdG90YWxfZ2liIGlzIG5vdCBOb25lIGFuZCBzd2FwX3RvdGFsX2dpYiA8IEpJTkFfUkVDT01NRU5ERURfU1dBUF9HQjoKICAgICAgICByZWFzb25zLmFwcGVuZCgKICAgICAgICAgICAgZiJTd2FwIGRldGVjdGFkYToge3N3YXBfdG90YWxfZ2liOi4xZn0gR2lCIChyZWNvbWVuZGFkbyA+PSB7SklOQV9SRUNPTU1FTkRFRF9TV0FQX0dCfSBHaUIpLiIKICAgICAgICApCiAgICBpZiBtZW1fYXZhaWxhYmxlX2dpYiBpcyBub3QgTm9uZSBhbmQgbWVtX2F2YWlsYWJsZV9naWIgPCBKSU5BX01JTl9BVkFJTEFCTEVfUkFNX0dCX0hJTlQ6CiAgICAgICAgcmVhc29ucy5hcHBlbmQoCiAgICAgICAgICAgIGYiUkFNIGxpdnJlIGF0dWFsOiB7bWVtX2F2YWlsYWJsZV9naWI6LjFmfSBHaUIgKGJhaXhvIHBhcmEgYSBjYXJnYSBpbmljaWFsIGRvIEppbmEpLiIKICAgICAgICApCgogICAgaWYgbm90IHJlYXNvbnM6CiAgICAgICAgcmV0dXJuCgogICAgcHJpbnQoIltBVklTT10gQWx0byByaXNjbyBkZSBPT00gY29tIEppbmEgbmVzdGEgbcOhcXVpbmEvY2FyZ2EuIikKICAgIGZvciByZWFzb24gaW4gcmVhc29uczoKICAgICAgICBwcmludChmIiAgICAgICAgLSB7cmVhc29ufSIpCiAgICBwcmludCgiICAgICAgICAtIFNlIG9jb3JyZXIgJ0tpbGxlZCcgKGV4aXQgMTM3KSwgdXNlIEJHRTogLS1lbWJlZGRpbmctbW9kZWwgYmdlIikKICAgIHByaW50KCIgICAgICAgIC0gT3Ugcm9kZSBvIEppbmEgZW0gbcOhcXVpbmEgY29tIG1haXMgUkFNL3N3YXAgZSBtZW5vcyBwcm9jZXNzb3MgY29uY29ycmVudGVzLiIpCgoKQGRhdGFjbGFzcyhmcm96ZW49VHJ1ZSkKY2xhc3MgUnVudGltZUluZGV4aW5nUGFyYW1zOgogICAgY2h1bmtfc2l6ZTogaW50CiAgICBjaHVua19vdmVybGFwOiBpbnQKICAgIGVtYmVkZGluZ19iYXRjaF9zaXplOiBpbnQKICAgIHJlYXNvbnM6IGxpc3Rbc3RyXQoKCmRlZiBfcmVzb2x2ZV9tYXhfcGVyZm9ybWFuY2VfcGFyYW1zKAogICAgKiwKICAgIGNodW5rX3NpemVfbG9ja2VkOiBib29sLAogICAgY2h1bmtfb3ZlcmxhcF9sb2NrZWQ6IGJvb2wsCiAgICBiYXRjaF9zaXplX2xvY2tlZDogYm9vbCwKICAgIGNodW5rX3NpemU6IGludCwKICAgIGNodW5rX292ZXJsYXA6IGludCwKICAgIGVtYmVkZGluZ19iYXRjaF9zaXplOiBpbnQsCikgLT4gUnVudGltZUluZGV4aW5nUGFyYW1zOgogICAgbWVtX3RvdGFsX2dpYiwgbWVtX2F2YWlsYWJsZV9naWIsIF8gPSBfcmVhZF9tZW1pbmZvX2dpYigpCiAgICByZWFzb25zID0gWwogICAgICAgICJQZXJmaWwgc2VsZWNpb25hZG86IG1heC1wZXJmb3JtYW5jZS4iLAogICAgICAgICJNb2RvIHBvZGUgZWxldmFyIGNvbnNpZGVyYXZlbG1lbnRlIG8gY29uc3VtbyBkZSBtZW3Ds3JpYSBlIGNhdXNhciBlbmNlcnJhbWVudG8gcG9yIE9PTSAoZXhpdCAxMzcpLiIsCiAgICBdCgogICAgdHVuZWRfY2h1bmtfc2l6ZSA9IGNodW5rX3NpemUKICAgIHR1bmVkX2NodW5rX292ZXJsYXAgPSBjaHVua19vdmVybGFwCiAgICB0dW5lZF9iYXRjaCA9IGVtYmVkZGluZ19iYXRjaF9zaXplCgogICAgaWYgbm90IGNodW5rX3NpemVfbG9ja2VkOgogICAgICAgIGlmIG1lbV90b3RhbF9naWIgaXMgbm90IE5vbmUgYW5kIG1lbV90b3RhbF9naWIgPj0gNjQgYW5kIChtZW1fYXZhaWxhYmxlX2dpYiBvciAwKSA+PSAxNjoKICAgICAgICAgICAgdHVuZWRfY2h1bmtfc2l6ZSA9IDcwMDAKICAgICAgICBlbHNlOgogICAgICAgICAgICB0dW5lZF9jaHVua19zaXplID0gNjAwMAogICAgICAgIHJlYXNvbnMuYXBwZW5kKGYiY2h1bmtfc2l6ZSBhanVzdGFkbyBwYXJhIHt0dW5lZF9jaHVua19zaXplfSBubyBwZXJmaWwgbWF4LXBlcmZvcm1hbmNlLiIpCgogICAgaWYgbm90IGNodW5rX292ZXJsYXBfbG9ja2VkOgogICAgICAgIHR1bmVkX2NodW5rX292ZXJsYXAgPSBtaW4odHVuZWRfY2h1bmtfc2l6ZSAtIDEsIG1heCgzMDAsIGludCh0dW5lZF9jaHVua19zaXplICogMC4xNSkpKQogICAgICAgIHJlYXNvbnMuYXBwZW5kKGYiY2h1bmtfb3ZlcmxhcCBhanVzdGFkbyBwYXJhIHt0dW5lZF9jaHVua19vdmVybGFwfS4iKQoKICAgIGlmIG5vdCBiYXRjaF9zaXplX2xvY2tlZDoKICAgICAgICBpZiBtZW1fdG90YWxfZ2liIGlzIG5vdCBOb25lIGFuZCBtZW1fdG90YWxfZ2liID49IDY0IGFuZCAobWVtX2F2YWlsYWJsZV9naWIgb3IgMCkgPj0gMTY6CiAgICAgICAgICAgIHR1bmVkX2JhdGNoID0gMjQKICAgICAgICBlbGlmIG1lbV90b3RhbF9naWIgaXMgbm90IE5vbmUgYW5kIG1lbV90b3RhbF9naWIgPj0gMzI6CiAgICAgICAgICAgIHR1bmVkX2JhdGNoID0gMTYKICAgICAgICBlbHNlOgogICAgICAgICAgICB0dW5lZF9iYXRjaCA9IDEyCiAgICAgICAgcmVhc29ucy5hcHBlbmQoZiJlbWJlZGRpbmdfYmF0Y2hfc2l6ZSBhanVzdGFkbyBwYXJhIHt0dW5lZF9iYXRjaH0uIikKCiAgICByZXR1cm4gUnVudGltZUluZGV4aW5nUGFyYW1zKAogICAgICAgIGNodW5rX3NpemU9dHVuZWRfY2h1bmtfc2l6ZSwKICAgICAgICBjaHVua19vdmVybGFwPXR1bmVkX2NodW5rX292ZXJsYXAsCiAgICAgICAgZW1iZWRkaW5nX2JhdGNoX3NpemU9bWF4KDEsIHR1bmVkX2JhdGNoKSwKICAgICAgICByZWFzb25zPXJlYXNvbnMsCiAgICApCgoKZGVmIF9yZXNvbHZlX2F1dG90dW5lZF9wYXJhbXMoCiAgICAqLAogICAgbW9kZWw6IFNlbnRlbmNlVHJhbnNmb3JtZXIsCiAgICBjaHVua19zaXplX2xvY2tlZDogYm9vbCwKICAgIGNodW5rX292ZXJsYXBfbG9ja2VkOiBib29sLAogICAgYmF0Y2hfc2l6ZV9sb2NrZWQ6IGJvb2wsCiAgICBjaHVua19zaXplOiBpbnQsCiAgICBjaHVua19vdmVybGFwOiBpbnQsCiAgICBlbWJlZGRpbmdfYmF0Y2hfc2l6ZTogaW50LAopIC0+IFJ1bnRpbWVJbmRleGluZ1BhcmFtczoKICAgIHJlYXNvbnM6IGxpc3Rbc3RyXSA9IFsiUGVyZmlsIHNlbGVjaW9uYWRvOiBhdXRvdHVuZSAoY3VzdG8tYmVuZWbDrWNpbykuIl0KICAgIHZlcmJvc2VfYXV0b3R1bmUgPSBfZW52X2Jvb2woIk1DUF9BVVRPVFVORV9WRVJCT1NFIiwgZGVmYXVsdD1GYWxzZSkKCiAgICB0cnk6CiAgICAgICAgaW1wb3J0IHBzdXRpbCAgIyB0eXBlOiBpZ25vcmUKICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgcmVhc29ucy5hcHBlbmQoInBzdXRpbCBpbmRpc3BvbsOtdmVsOyBtYW50ZW5kbyBwYXLDom1ldHJvcyBhdHVhaXMgc2VtIGJlbmNobWFyay4iKQogICAgICAgIHJldHVybiBSdW50aW1lSW5kZXhpbmdQYXJhbXMoCiAgICAgICAgICAgIGNodW5rX3NpemU9Y2h1bmtfc2l6ZSwKICAgICAgICAgICAgY2h1bmtfb3ZlcmxhcD1jaHVua19vdmVybGFwLAogICAgICAgICAgICBlbWJlZGRpbmdfYmF0Y2hfc2l6ZT1lbWJlZGRpbmdfYmF0Y2hfc2l6ZSwKICAgICAgICAgICAgcmVhc29ucz1yZWFzb25zLAogICAgICAgICkKCiAgICB2bSA9IHBzdXRpbC52aXJ0dWFsX21lbW9yeSgpCiAgICBzd2FwID0gcHN1dGlsLnN3YXBfbWVtb3J5KCkKICAgIG1lbV90b3RhbF9naWIgPSB2bS50b3RhbCAvICgxMDI0KiozKQogICAgbWVtX2F2YWlsYWJsZV9naWIgPSB2bS5hdmFpbGFibGUgLyAoMTAyNCoqMykKICAgIHN3YXBfdG90YWxfZ2liID0gc3dhcC50b3RhbCAvICgxMDI0KiozKQoKICAgIHRhcmdldF9yYW1fcGVyY2VudCA9IF9jbGFtcCgKICAgICAgICBmbG9hdChvcy5lbnZpcm9uLmdldCgiTUNQX0FVVE9UVU5FX1RBUkdFVF9SQU1fUEVSQ0VOVCIsICI2OCIpKSwKICAgICAgICA2MC4wLAogICAgICAgIDc1LjAsCiAgICApCiAgICBpZiBtZW1fYXZhaWxhYmxlX2dpYiA8IDYgb3Igc3dhcF90b3RhbF9naWIgPCA0OgogICAgICAgIHRhcmdldF9yYW1fcGVyY2VudCA9IG1pbih0YXJnZXRfcmFtX3BlcmNlbnQsIDYzLjApCiAgICByZWFzb25zLmFwcGVuZCgKICAgICAgICBmIk1lbcOzcmlhIGRldGVjdGFkYTogdG90YWw9e21lbV90b3RhbF9naWI6LjFmfSBHaUIsIGxpdnJlPXttZW1fYXZhaWxhYmxlX2dpYjouMWZ9IEdpQiwgIgogICAgICAgIGYic3dhcD17c3dhcF90b3RhbF9naWI6LjFmfSBHaUIsIGFsdm89e3RhcmdldF9yYW1fcGVyY2VudDouMWZ9JS4iCiAgICApCgogICAgdHVuZWRfY2h1bmtfc2l6ZSA9IGNodW5rX3NpemUKICAgIHR1bmVkX2NodW5rX292ZXJsYXAgPSBjaHVua19vdmVybGFwCiAgICB0dW5lZF9iYXRjaCA9IGVtYmVkZGluZ19iYXRjaF9zaXplCgogICAgaWYgbm90IGNodW5rX3NpemVfbG9ja2VkOgogICAgICAgIGlmIG1lbV90b3RhbF9naWIgPCA4IG9yIG1lbV9hdmFpbGFibGVfZ2liIDwgMzoKICAgICAgICAgICAgdHVuZWRfY2h1bmtfc2l6ZSA9IDE4MDAKICAgICAgICBlbGlmIG1lbV90b3RhbF9naWIgPCAxNiBvciBtZW1fYXZhaWxhYmxlX2dpYiA8IDY6CiAgICAgICAgICAgIHR1bmVkX2NodW5rX3NpemUgPSAyNDAwCiAgICAgICAgZWxpZiBtZW1fdG90YWxfZ2liIDwgMzIgb3IgbWVtX2F2YWlsYWJsZV9naWIgPCAxMjoKICAgICAgICAgICAgdHVuZWRfY2h1bmtfc2l6ZSA9IDMyMDAKICAgICAgICBlbHNlOgogICAgICAgICAgICB0dW5lZF9jaHVua19zaXplID0gNDIwMAogICAgICAgIHJlYXNvbnMuYXBwZW5kKGYiY2h1bmtfc2l6ZSBhdXRvdHVuYWRvIHBhcmEge3R1bmVkX2NodW5rX3NpemV9LiIpCgogICAgaWYgbm90IGNodW5rX292ZXJsYXBfbG9ja2VkOgogICAgICAgIHR1bmVkX2NodW5rX292ZXJsYXAgPSBtaW4odHVuZWRfY2h1bmtfc2l6ZSAtIDEsIG1heCgxMjAsIGludCh0dW5lZF9jaHVua19zaXplICogMC4xNSkpKQogICAgICAgIHJlYXNvbnMuYXBwZW5kKGYiY2h1bmtfb3ZlcmxhcCBhdXRvdHVuYWRvIHBhcmEge3R1bmVkX2NodW5rX292ZXJsYXB9LiIpCgogICAgaWYgbm90IGJhdGNoX3NpemVfbG9ja2VkOgogICAgICAgIG1heF9jYW5kaWRhdGUgPSAxNgogICAgICAgIGlmIG1lbV90b3RhbF9naWIgPCA4IG9yIG1lbV9hdmFpbGFibGVfZ2liIDwgMyBvciBzd2FwX3RvdGFsX2dpYiA8IDI6CiAgICAgICAgICAgIG1heF9jYW5kaWRhdGUgPSAyCiAgICAgICAgZWxpZiBtZW1fdG90YWxfZ2liIDwgMTYgb3IgbWVtX2F2YWlsYWJsZV9naWIgPCA2OgogICAgICAgICAgICBtYXhfY2FuZGlkYXRlID0gNAogICAgICAgIGVsaWYgbWVtX3RvdGFsX2dpYiA8IDMyIG9yIG1lbV9hdmFpbGFibGVfZ2liIDwgMTA6CiAgICAgICAgICAgIG1heF9jYW5kaWRhdGUgPSA4CgogICAgICAgIGNhbmRpZGF0ZXMgPSBbMiwgNCwgNiwgOCwgMTIsIDE2XQogICAgICAgIGNhbmRpZGF0ZXMgPSBbYyBmb3IgYyBpbiBjYW5kaWRhdGVzIGlmIGMgPD0gbWF4X2NhbmRpZGF0ZV0KICAgICAgICBpZiBub3QgY2FuZGlkYXRlczoKICAgICAgICAgICAgY2FuZGlkYXRlcyA9IFsyXQoKICAgICAgICBwcm9jZXNzID0gcHN1dGlsLlByb2Nlc3MoKQogICAgICAgIHNhbXBsZV9zaXplID0gbWluKG1heCg1MTIsIHR1bmVkX2NodW5rX3NpemUpLCAzMDAwKQogICAgICAgIHNhbXBsZV90ZXh0ID0gKCIjIGF1dG90dW5lLXNhbXBsZVxuIiArICgieCIgKiBzYW1wbGVfc2l6ZSkpCgogICAgICAgIGJlc3RfYmF0Y2ggPSBjYW5kaWRhdGVzWzBdCiAgICAgICAgYmVzdF9zY29yZSA9IC0xLjAKICAgICAgICBiZXN0X21lbW9yeV9wY3QgPSAxMDAuMAogICAgICAgIHNlbGVjdGVkX2JlbmNobWFya19saW5lOiBzdHIgfCBOb25lID0gTm9uZQogICAgICAgIGJlbmNobWFya19saW5lczogbGlzdFtzdHJdID0gW10KCiAgICAgICAgIyBXYXJtdXAgY3VydG8gcGFyYSBlc3RhYmlsaXphciBjYWNoZSBpbnRlcm5vLgogICAgICAgIHRyeToKICAgICAgICAgICAgXyA9IG1vZGVsLmVuY29kZShbc2FtcGxlX3RleHRdLCBzaG93X3Byb2dyZXNzX2Jhcj1GYWxzZSwgYmF0Y2hfc2l6ZT0xKQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgICAgIHBhc3MKCiAgICAgICAgZm9yIGNhbmRpZGF0ZSBpbiBjYW5kaWRhdGVzOgogICAgICAgICAgICBkb2NzID0gW3NhbXBsZV90ZXh0XSAqIGNhbmRpZGF0ZQogICAgICAgICAgICBnYy5jb2xsZWN0KCkKICAgICAgICAgICAgYmVmb3JlX3ZtID0gcHN1dGlsLnZpcnR1YWxfbWVtb3J5KCkucGVyY2VudAogICAgICAgICAgICBiZWZvcmVfcnNzID0gcHJvY2Vzcy5tZW1vcnlfaW5mbygpLnJzcyAvICgxMDI0KioyKQogICAgICAgICAgICBzdGFydGVkID0gcGVyZl9jb3VudGVyKCkKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgZW1iZWRkaW5ncyA9IG1vZGVsLmVuY29kZSgKICAgICAgICAgICAgICAgICAgICBkb2NzLAogICAgICAgICAgICAgICAgICAgIHNob3dfcHJvZ3Jlc3NfYmFyPUZhbHNlLAogICAgICAgICAgICAgICAgICAgIGJhdGNoX3NpemU9Y2FuZGlkYXRlLAogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgICAgICBiZW5jaG1hcmtfbGluZXMuYXBwZW5kKGYiYmF0Y2g9e2NhbmRpZGF0ZX06IGVycm8gKHtlfSkiKQogICAgICAgICAgICAgICAgY29udGludWUKCiAgICAgICAgICAgIGVsYXBzZWQgPSBtYXgocGVyZl9jb3VudGVyKCkgLSBzdGFydGVkLCAxZS02KQogICAgICAgICAgICBhZnRlcl92bSA9IHBzdXRpbC52aXJ0dWFsX21lbW9yeSgpLnBlcmNlbnQKICAgICAgICAgICAgYWZ0ZXJfcnNzID0gcHJvY2Vzcy5tZW1vcnlfaW5mbygpLnJzcyAvICgxMDI0KioyKQogICAgICAgICAgICBkZWwgZW1iZWRkaW5ncwogICAgICAgICAgICBnYy5jb2xsZWN0KCkKCiAgICAgICAgICAgIHRocm91Z2hwdXQgPSBjYW5kaWRhdGUgLyBlbGFwc2VkCiAgICAgICAgICAgIHNhZmUgPSBhZnRlcl92bSA8PSAodGFyZ2V0X3JhbV9wZXJjZW50ICsgMy4wKQogICAgICAgICAgICBiZW5jaG1hcmtfbGluZXMuYXBwZW5kKAogICAgICAgICAgICAgICAgZiJiYXRjaD17Y2FuZGlkYXRlfToge3Rocm91Z2hwdXQ6LjJmfSBpdGVucy9zLCB2bT17YWZ0ZXJfdm06LjFmfSUsIHJzc19kZWx0YT17YWZ0ZXJfcnNzIC0gYmVmb3JlX3JzczorLjFmfSBNaUIiCiAgICAgICAgICAgICkKCiAgICAgICAgICAgIGlmIHNhZmUgYW5kIHRocm91Z2hwdXQgPiBiZXN0X3Njb3JlOgogICAgICAgICAgICAgICAgYmVzdF9zY29yZSA9IHRocm91Z2hwdXQKICAgICAgICAgICAgICAgIGJlc3RfYmF0Y2ggPSBjYW5kaWRhdGUKICAgICAgICAgICAgICAgIGJlc3RfbWVtb3J5X3BjdCA9IGFmdGVyX3ZtCiAgICAgICAgICAgICAgICBzZWxlY3RlZF9iZW5jaG1hcmtfbGluZSA9IGJlbmNobWFya19saW5lc1stMV0KICAgICAgICAgICAgZWxpZiBiZXN0X3Njb3JlIDwgMCBhbmQgYWZ0ZXJfdm0gPCBiZXN0X21lbW9yeV9wY3Q6CiAgICAgICAgICAgICAgICAjIFNlIG5lbmh1bSBjYW5kaWRhdG8gZmljb3UgInNhZmUiLCBlc2NvbGhlIG8gbWVub3MgYWdyZXNzaXZvIGVtIG1lbcOzcmlhLgogICAgICAgICAgICAgICAgYmVzdF9iYXRjaCA9IGNhbmRpZGF0ZQogICAgICAgICAgICAgICAgYmVzdF9tZW1vcnlfcGN0ID0gYWZ0ZXJfdm0KICAgICAgICAgICAgICAgIHNlbGVjdGVkX2JlbmNobWFya19saW5lID0gYmVuY2htYXJrX2xpbmVzWy0xXQoKICAgICAgICAgICAgIyBTZSBqw6EgcGFzc291IG11aXRvIGRvIGxpbWl0ZSwgZXZpdGEgdGVudGFyIGJhdGNoZXMgbWFpb3Jlcy4KICAgICAgICAgICAgaWYgYWZ0ZXJfdm0gPiB0YXJnZXRfcmFtX3BlcmNlbnQgKyA4LjA6CiAgICAgICAgICAgICAgICBicmVhawoKICAgICAgICAgICAgIyBFdml0YSBlc2NvbGhlciBjYW5kaWRhdG8gcXVlIGrDoSBjb21lw6dvdSBhY2ltYSBkbyBsaW1pdGUuCiAgICAgICAgICAgIGlmIGJlZm9yZV92bSA+IHRhcmdldF9yYW1fcGVyY2VudCArIDUuMDoKICAgICAgICAgICAgICAgIGJyZWFrCgogICAgICAgIHR1bmVkX2JhdGNoID0gbWF4KDEsIGJlc3RfYmF0Y2gpCiAgICAgICAgaWYgdmVyYm9zZV9hdXRvdHVuZToKICAgICAgICAgICAgcmVhc29ucy5leHRlbmQoYmVuY2htYXJrX2xpbmVzKQogICAgICAgIGVsaWYgc2VsZWN0ZWRfYmVuY2htYXJrX2xpbmU6CiAgICAgICAgICAgIHJlYXNvbnMuYXBwZW5kKGYiTWljcm8tYmVuY2htYXJrOiB7c2VsZWN0ZWRfYmVuY2htYXJrX2xpbmV9IikKICAgICAgICByZWFzb25zLmFwcGVuZCgKICAgICAgICAgICAgZiJlbWJlZGRpbmdfYmF0Y2hfc2l6ZSBhdXRvdHVuYWRvIHBhcmEge3R1bmVkX2JhdGNofSAoYWx2byBkZSBtZW3Ds3JpYToge3RhcmdldF9yYW1fcGVyY2VudDouMWZ9JSkuIgogICAgICAgICkKCiAgICByZXR1cm4gUnVudGltZUluZGV4aW5nUGFyYW1zKAogICAgICAgIGNodW5rX3NpemU9dHVuZWRfY2h1bmtfc2l6ZSwKICAgICAgICBjaHVua19vdmVybGFwPXR1bmVkX2NodW5rX292ZXJsYXAsCiAgICAgICAgZW1iZWRkaW5nX2JhdGNoX3NpemU9bWF4KDEsIHR1bmVkX2JhdGNoKSwKICAgICAgICByZWFzb25zPXJlYXNvbnMsCiAgICApCgoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBGdW7Dp8O1ZXMgYXV4aWxpYXJlcwojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKZGVmIGdldF90ZXh0X3NwbGl0dGVyKGNodW5rX3NpemU6IGludCwgY2h1bmtfb3ZlcmxhcDogaW50KSAtPiBSZWN1cnNpdmVDaGFyYWN0ZXJUZXh0U3BsaXR0ZXI6CiAgICAiIiJSZXRvcm5hIG8gc3BsaXR0ZXIgY29tcGFydGlsaGFkbyBjb20gYXMgY29uZmlndXJhw6fDtWVzIHBhZHLDo28gZG8gcHJvamV0by4iIiIKICAgIHJldHVybiBSZWN1cnNpdmVDaGFyYWN0ZXJUZXh0U3BsaXR0ZXIoCiAgICAgICAgY2h1bmtfc2l6ZT1jaHVua19zaXplLAogICAgICAgIGNodW5rX292ZXJsYXA9Y2h1bmtfb3ZlcmxhcCwKICAgICAgICBsZW5ndGhfZnVuY3Rpb249bGVuLAogICAgICAgIHNlcGFyYXRvcnM9WyJcblxuIiwgIlxuIiwgIiAiLCAiIl0sCiAgICApCgoKZGVmIGxvYWRfZW1iZWRkaW5nX21vZGVsKG1vZGVsX2Nob2ljZTogc3RyLCBqaW5hX3F1YW50aXphdGlvbjogc3RyKSAtPiBTZW50ZW5jZVRyYW5zZm9ybWVyOgogICAgIiIiQ2FycmVnYSBvIG1vZGVsbyBkZSBlbWJlZGRpbmdzIGZvcsOnYW5kbyB1c28gZGUgQ1BVLiIiIgogICAgZW1iZWRkaW5nX21vZGVsX2lkID0gX3Jlc29sdmVfbW9kZWxfaWQobW9kZWxfY2hvaWNlKQogICAgZmFsbGJhY2tfbW9kZWxfaWQgPSBfcmVzb2x2ZV9mYWxsYmFja19tb2RlbF9pZChtb2RlbF9jaG9pY2UpCgogICAgbW9kZWxfYmFzZV9kaXIgPSBNT0RFTF9DQUNIRV9CQVNFX0RJUgogICAgbW9kZWxfYmFzZV9kaXIubWtkaXIocGFyZW50cz1UcnVlLCBleGlzdF9vaz1UcnVlKQogICAgcHJlZmVycmVkX21vZGVsX2NhY2hlX2RpciA9IF9tb2RlbF9jYWNoZV9kaXIobW9kZWxfYmFzZV9kaXIsIGVtYmVkZGluZ19tb2RlbF9pZCkKCiAgICBwcmludChmIlsrXSBCYWl4YW5kbyBtb2RlbG8gcHJlZmVyaWRvOiB7ZW1iZWRkaW5nX21vZGVsX2lkfSIpCiAgICBwcmludChmIlsrXSBEaXJldMOzcmlvIGRlIGRvd25sb2FkL2NhY2hlIGRvIG1vZGVsbzoge3ByZWZlcnJlZF9tb2RlbF9jYWNoZV9kaXJ9IikKICAgIHNlbGVjdGlvbiA9IGRvd25sb2FkX21vZGVsX3dpdGhfZmFsbGJhY2soCiAgICAgICAgcHJlZmVycmVkX21vZGVsX2lkPWVtYmVkZGluZ19tb2RlbF9pZCwKICAgICAgICBmYWxsYmFja19tb2RlbF9pZD1mYWxsYmFja19tb2RlbF9pZCwKICAgICAgICBsb2NhbF9kaXI9bW9kZWxfYmFzZV9kaXIsCiAgICApCiAgICBzZWxlY3RlZF9tb2RlbF9kaXIgPSBzZWxlY3Rpb24ubG9jYWxfZGlyCiAgICBwcmludCgKICAgICAgICBmIlsrXSBNb2RlbG8gc2VsZWNpb25hZG86IHtzZWxlY3Rpb24ubW9kZWxfaWR9ICIKICAgICAgICBmIihwcm92aWRlcj17c2VsZWN0aW9uLnByb3ZpZGVyfSwgcGF0aD17c2VsZWN0ZWRfbW9kZWxfZGlyfSkiCiAgICApCgogICAgZGVmIF9jbGVhcl9oZl9keW5hbWljX21vZHVsZXNfY2FjaGUoKSAtPiBOb25lOgogICAgICAgIGNhY2hlX2RpciA9IFBhdGguaG9tZSgpIC8gIi5jYWNoZSIgLyAiaHVnZ2luZ2ZhY2UiIC8gIm1vZHVsZXMiIC8gInRyYW5zZm9ybWVyc19tb2R1bGVzIgogICAgICAgIGlmIGNhY2hlX2Rpci5leGlzdHMoKToKICAgICAgICAgICAgcHJpbnQoZiJbIV0gTGltcGFuZG8gY2FjaGUgZGUgbcOzZHVsb3MgZGluw6JtaWNvcyBkbyBIdWdnaW5nIEZhY2U6IHtjYWNoZV9kaXJ9IikKICAgICAgICAgICAgc2h1dGlsLnJtdHJlZShjYWNoZV9kaXIsIGlnbm9yZV9lcnJvcnM9VHJ1ZSkKCiAgICBkZWYgX2xvYWRfZnJvbV9sb2NhbF9kaXIobW9kZWxfaWQ6IHN0cikgLT4gU2VudGVuY2VUcmFuc2Zvcm1lcjoKICAgICAgICAjIE8gbW9kZWxvIGRhIEppbmEgZGVwZW5kZSBkZSBjw7NkaWdvIHJlbW90bzsgZmFsbGJhY2sgbm9ybWFsbWVudGUgbsOjby4KICAgICAgICB0cnVzdF9yZW1vdGVfY29kZSA9IG1vZGVsX2lkLnN0YXJ0c3dpdGgoImppbmFhaS8iKQogICAgICAgIHRva2VuaXplcl9rd2FyZ3MgPSB7ImZpeF9taXN0cmFsX3JlZ2V4IjogVHJ1ZX0KCiAgICAgICAgZGVmIF9pbnN0YW50aWF0ZV9tb2RlbCgpIC0+IFNlbnRlbmNlVHJhbnNmb3JtZXI6CiAgICAgICAgICAgIHJldHVybiBTZW50ZW5jZVRyYW5zZm9ybWVyKAogICAgICAgICAgICAgICAgc3RyKHNlbGVjdGVkX21vZGVsX2RpciksCiAgICAgICAgICAgICAgICBkZXZpY2U9ImNwdSIsCiAgICAgICAgICAgICAgICB0cnVzdF9yZW1vdGVfY29kZT10cnVzdF9yZW1vdGVfY29kZSwKICAgICAgICAgICAgICAgIHRva2VuaXplcl9rd2FyZ3M9dG9rZW5pemVyX2t3YXJncywKICAgICAgICAgICAgKQoKICAgICAgICBkZWYgX2xvYWRfd2l0aF9taXN0cmFsX3JlZ2V4X3BhdGNoKCkgLT4gU2VudGVuY2VUcmFuc2Zvcm1lcjoKICAgICAgICAgICAgIyBPIGPDs2RpZ28gcmVtb3RvIGRhIEppbmEgaW5zdGFuY2lhIHVtIHRva2VuaXplciBpbnRlcm5vIHNlbSByZXBhc3NhciB0b2tlbml6ZXJfa3dhcmdzLgogICAgICAgICAgICBpZiBub3QgdHJ1c3RfcmVtb3RlX2NvZGU6CiAgICAgICAgICAgICAgICByZXR1cm4gX2luc3RhbnRpYXRlX21vZGVsKCkKCiAgICAgICAgICAgIGZyb20gdHJhbnNmb3JtZXJzIGltcG9ydCBBdXRvTW9kZWwsIEF1dG9Ub2tlbml6ZXIKICAgICAgICAgICAgZnJvbSB0cmFuc2Zvcm1lcnMubW9kZWxpbmdfdXRpbHMgaW1wb3J0IFByZVRyYWluZWRNb2RlbAoKICAgICAgICAgICAgb3JpZ2luYWxfZnJvbV9wcmV0cmFpbmVkID0gQXV0b1Rva2VuaXplci5mcm9tX3ByZXRyYWluZWQKICAgICAgICAgICAgb3JpZ2luYWxfbW9kZWxfZnJvbV9wcmV0cmFpbmVkID0gQXV0b01vZGVsLmZyb21fcHJldHJhaW5lZAogICAgICAgICAgICBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fcHJldHJhaW5lZCA9IFByZVRyYWluZWRNb2RlbC5mcm9tX3ByZXRyYWluZWQKICAgICAgICAgICAgb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX2NvbmZpZyA9IFByZVRyYWluZWRNb2RlbC5fZnJvbV9jb25maWcKICAgICAgICAgICAgbW9kZWxfcmVmcyA9IHtzdHIoc2VsZWN0ZWRfbW9kZWxfZGlyKSwgc3RyKHNlbGVjdGVkX21vZGVsX2Rpci5yZXNvbHZlKCkpfQoKICAgICAgICAgICAgZGVmIF9wYXRjaGVkX2Zyb21fcHJldHJhaW5lZCgqYXJncywgKiprd2FyZ3MpOgogICAgICAgICAgICAgICAgbW9kZWxfcmVmID0gYXJnc1swXSBpZiBhcmdzIGVsc2Uga3dhcmdzLmdldCgicHJldHJhaW5lZF9tb2RlbF9uYW1lX29yX3BhdGgiKQogICAgICAgICAgICAgICAgaWYgbW9kZWxfcmVmIGlzIG5vdCBOb25lIGFuZCBzdHIobW9kZWxfcmVmKSBpbiBtb2RlbF9yZWZzOgogICAgICAgICAgICAgICAgICAgIGt3YXJncy5zZXRkZWZhdWx0KCJmaXhfbWlzdHJhbF9yZWdleCIsIFRydWUpCiAgICAgICAgICAgICAgICByZXR1cm4gb3JpZ2luYWxfZnJvbV9wcmV0cmFpbmVkKCphcmdzLCAqKmt3YXJncykKCiAgICAgICAgICAgIGRlZiBfcGF0Y2hlZF9tb2RlbF9mcm9tX3ByZXRyYWluZWQoKmFyZ3MsICoqa3dhcmdzKToKICAgICAgICAgICAgICAgIG1vZGVsX3JlZiA9IGFyZ3NbMF0gaWYgYXJncyBlbHNlIGt3YXJncy5nZXQoInByZXRyYWluZWRfbW9kZWxfbmFtZV9vcl9wYXRoIikKICAgICAgICAgICAgICAgIGlmIG1vZGVsX3JlZiBpcyBub3QgTm9uZSBhbmQgc3RyKG1vZGVsX3JlZikgaW4gbW9kZWxfcmVmcyBhbmQgInRvcmNoX2R0eXBlIiBpbiBrd2FyZ3M6CiAgICAgICAgICAgICAgICAgICAga3dhcmdzID0gZGljdChrd2FyZ3MpCiAgICAgICAgICAgICAgICAgICAgaWYgImR0eXBlIiBub3QgaW4ga3dhcmdzOgogICAgICAgICAgICAgICAgICAgICAgICBrd2FyZ3NbImR0eXBlIl0gPSBrd2FyZ3NbInRvcmNoX2R0eXBlIl0KICAgICAgICAgICAgICAgICAgICBrd2FyZ3MucG9wKCJ0b3JjaF9kdHlwZSIsIE5vbmUpCiAgICAgICAgICAgICAgICByZXR1cm4gb3JpZ2luYWxfbW9kZWxfZnJvbV9wcmV0cmFpbmVkKCphcmdzLCAqKmt3YXJncykKCiAgICAgICAgICAgIG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9wcmV0cmFpbmVkX2ZuID0gb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX3ByZXRyYWluZWQuX19mdW5jX18KCiAgICAgICAgICAgIEBjbGFzc21ldGhvZAogICAgICAgICAgICBkZWYgX3BhdGNoZWRfcHJldHJhaW5lZF9tb2RlbF9mcm9tX3ByZXRyYWluZWQoY2xzLCAqYXJncywgKiprd2FyZ3MpOgogICAgICAgICAgICAgICAgaWYgInRvcmNoX2R0eXBlIiBpbiBrd2FyZ3M6CiAgICAgICAgICAgICAgICAgICAga3dhcmdzID0gZGljdChrd2FyZ3MpCiAgICAgICAgICAgICAgICAgICAgaWYgImR0eXBlIiBub3QgaW4ga3dhcmdzOgogICAgICAgICAgICAgICAgICAgICAgICBrd2FyZ3NbImR0eXBlIl0gPSBrd2FyZ3NbInRvcmNoX2R0eXBlIl0KICAgICAgICAgICAgICAgICAgICBrd2FyZ3MucG9wKCJ0b3JjaF9kdHlwZSIsIE5vbmUpCiAgICAgICAgICAgICAgICByZXR1cm4gb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX3ByZXRyYWluZWRfZm4oY2xzLCAqYXJncywgKiprd2FyZ3MpCgogICAgICAgICAgICBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fY29uZmlnX2ZuID0gb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX2NvbmZpZy5fX2Z1bmNfXwoKICAgICAgICAgICAgQGNsYXNzbWV0aG9kCiAgICAgICAgICAgIGRlZiBfcGF0Y2hlZF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fY29uZmlnKGNscywgKmFyZ3MsICoqa3dhcmdzKToKICAgICAgICAgICAgICAgIGlmICJ0b3JjaF9kdHlwZSIgaW4ga3dhcmdzOgogICAgICAgICAgICAgICAgICAgIGt3YXJncyA9IGRpY3Qoa3dhcmdzKQogICAgICAgICAgICAgICAgICAgIGlmICJkdHlwZSIgbm90IGluIGt3YXJnczoKICAgICAgICAgICAgICAgICAgICAgICAga3dhcmdzWyJkdHlwZSJdID0ga3dhcmdzWyJ0b3JjaF9kdHlwZSJdCiAgICAgICAgICAgICAgICAgICAga3dhcmdzLnBvcCgidG9yY2hfZHR5cGUiLCBOb25lKQogICAgICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9jb25maWdfZm4oY2xzLCAqYXJncywgKiprd2FyZ3MpCgogICAgICAgICAgICBBdXRvVG9rZW5pemVyLmZyb21fcHJldHJhaW5lZCA9IF9wYXRjaGVkX2Zyb21fcHJldHJhaW5lZAogICAgICAgICAgICBBdXRvTW9kZWwuZnJvbV9wcmV0cmFpbmVkID0gX3BhdGNoZWRfbW9kZWxfZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgICAgIFByZVRyYWluZWRNb2RlbC5mcm9tX3ByZXRyYWluZWQgPSBfcGF0Y2hlZF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fcHJldHJhaW5lZAogICAgICAgICAgICBQcmVUcmFpbmVkTW9kZWwuX2Zyb21fY29uZmlnID0gX3BhdGNoZWRfcHJldHJhaW5lZF9tb2RlbF9mcm9tX2NvbmZpZwogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICByZXR1cm4gX2luc3RhbnRpYXRlX21vZGVsKCkKICAgICAgICAgICAgZmluYWxseToKICAgICAgICAgICAgICAgIEF1dG9Ub2tlbml6ZXIuZnJvbV9wcmV0cmFpbmVkID0gb3JpZ2luYWxfZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgICAgICAgICBBdXRvTW9kZWwuZnJvbV9wcmV0cmFpbmVkID0gb3JpZ2luYWxfbW9kZWxfZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgICAgICAgICBQcmVUcmFpbmVkTW9kZWwuZnJvbV9wcmV0cmFpbmVkID0gb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX3ByZXRyYWluZWQKICAgICAgICAgICAgICAgIFByZVRyYWluZWRNb2RlbC5fZnJvbV9jb25maWcgPSBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fY29uZmlnCgogICAgICAgIHByaW50KGYiWytdIENhcnJlZ2FuZG8gbW9kZWxvIGRlIGVtYmVkZGluZ3MgYSBwYXJ0aXIgZGU6IHtzZWxlY3RlZF9tb2RlbF9kaXJ9IChDUFUpLi4uIikKICAgICAgICB0cnk6CiAgICAgICAgICAgIHJldHVybiBfbG9hZF93aXRoX21pc3RyYWxfcmVnZXhfcGF0Y2goKQogICAgICAgIGV4Y2VwdCBGaWxlTm90Rm91bmRFcnJvciBhcyBlOgogICAgICAgICAgICAjIENvcnJpZ2UgY29ycnVww6fDo28vaW5jb21wbGV0dWRlIG5vIGNhY2hlIGRpbsOibWljbyBkbyB0cmFuc2Zvcm1lcnMuCiAgICAgICAgICAgIGlmIHRydXN0X3JlbW90ZV9jb2RlIGFuZCAidHJhbnNmb3JtZXJzX21vZHVsZXMiIGluIHN0cihlKToKICAgICAgICAgICAgICAgIHByaW50KGYiWyFdIENhY2hlIGRpbsOibWljbyBpbmNvbnNpc3RlbnRlIGRldGVjdGFkbzoge2V9IikKICAgICAgICAgICAgICAgIF9jbGVhcl9oZl9keW5hbWljX21vZHVsZXNfY2FjaGUoKQogICAgICAgICAgICAgICAgcmV0dXJuIF9sb2FkX3dpdGhfbWlzdHJhbF9yZWdleF9wYXRjaCgpCiAgICAgICAgICAgIHJhaXNlCgogICAgZGVmIF9hcHBseV9qaW5hX3F1YW50aXphdGlvbl9pZl9uZWVkZWQobW9kZWw6IFNlbnRlbmNlVHJhbnNmb3JtZXIsIG1vZGVsX2lkOiBzdHIpIC0+IFNlbnRlbmNlVHJhbnNmb3JtZXI6CiAgICAgICAgaWYgbW9kZWxfaWQgIT0gSklOQV9WM19FTUJFRERJTkdfTU9ERUwgb3IgamluYV9xdWFudGl6YXRpb24gPT0gImRlZmF1bHQiOgogICAgICAgICAgICByZXR1cm4gbW9kZWwKICAgICAgICB0cnk6CiAgICAgICAgICAgIGltcG9ydCB0b3JjaAogICAgICAgICAgICBpbXBvcnQgd2FybmluZ3MKCiAgICAgICAgICAgIHF1YW50aXplZF9sYXllcnMgPSAwCiAgICAgICAgICAgIGZvciBtb2R1bGUgaW4gbW9kZWwubW9kdWxlcygpOgogICAgICAgICAgICAgICAgaWYgdHlwZShtb2R1bGUpLl9fbmFtZV9fICE9ICJQYXJhbWV0cml6ZWRMaW5lYXIiOgogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlCgogICAgICAgICAgICAgICAgZmxvYXRfbGluZWFyID0gdG9yY2gubm4uTGluZWFyKAogICAgICAgICAgICAgICAgICAgIG1vZHVsZS5pbl9mZWF0dXJlcywKICAgICAgICAgICAgICAgICAgICBtb2R1bGUub3V0X2ZlYXR1cmVzLAogICAgICAgICAgICAgICAgICAgIGJpYXM9bW9kdWxlLmJpYXMgaXMgbm90IE5vbmUsCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICB3aXRoIHRvcmNoLm5vX2dyYWQoKToKICAgICAgICAgICAgICAgICAgICBmbG9hdF9saW5lYXIud2VpZ2h0LmNvcHlfKG1vZHVsZS53ZWlnaHQuZGV0YWNoKCkudG8odG9yY2guZmxvYXQzMikpCiAgICAgICAgICAgICAgICAgICAgaWYgbW9kdWxlLmJpYXMgaXMgbm90IE5vbmU6CiAgICAgICAgICAgICAgICAgICAgICAgIGZsb2F0X2xpbmVhci5iaWFzLmNvcHlfKG1vZHVsZS5iaWFzLmRldGFjaCgpLnRvKHRvcmNoLmZsb2F0MzIpKQoKICAgICAgICAgICAgICAgIHdpdGggd2FybmluZ3MuY2F0Y2hfd2FybmluZ3MoKToKICAgICAgICAgICAgICAgICAgICB3YXJuaW5ncy5maWx0ZXJ3YXJuaW5ncygiaWdub3JlIiwgY2F0ZWdvcnk9RGVwcmVjYXRpb25XYXJuaW5nKQogICAgICAgICAgICAgICAgICAgIHF1YW50aXplZF9saW5lYXIgPSB0b3JjaC5xdWFudGl6YXRpb24ucXVhbnRpemVfZHluYW1pYygKICAgICAgICAgICAgICAgICAgICAgICAgdG9yY2gubm4uU2VxdWVudGlhbChmbG9hdF9saW5lYXIpLAogICAgICAgICAgICAgICAgICAgICAgICB7dG9yY2gubm4uTGluZWFyfSwKICAgICAgICAgICAgICAgICAgICAgICAgZHR5cGU9dG9yY2gucWludDgsCiAgICAgICAgICAgICAgICAgICAgKVswXQoKICAgICAgICAgICAgICAgIG1vZHVsZS5fZHluYW1pY19pbnQ4X2xpbmVhciA9IHF1YW50aXplZF9saW5lYXIKCiAgICAgICAgICAgICAgICBkZWYgX2ZvcndhcmRfZHluYW1pY19pbnQ4KHNlbGYsIGlucHV0LCB0YXNrX2lkPU5vbmUsIHJlc2lkdWFsPUZhbHNlKToKICAgICAgICAgICAgICAgICAgICBvdXQgPSBzZWxmLl9keW5hbWljX2ludDhfbGluZWFyKGlucHV0KQogICAgICAgICAgICAgICAgICAgIGlmIHJlc2lkdWFsOgogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0LCBpbnB1dAogICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXQKCiAgICAgICAgICAgICAgICBtb2R1bGUuZm9yd2FyZCA9IF9mb3J3YXJkX2R5bmFtaWNfaW50OC5fX2dldF9fKG1vZHVsZSwgbW9kdWxlLl9fY2xhc3NfXykKICAgICAgICAgICAgICAgIHF1YW50aXplZF9sYXllcnMgKz0gMQoKICAgICAgICAgICAgaWYgcXVhbnRpemVkX2xheWVycyA9PSAwOgogICAgICAgICAgICAgICAgcHJpbnQoCiAgICAgICAgICAgICAgICAgICAgIltBVklTT10gTmVuaHVtYSBjYW1hZGEgUGFyYW1ldHJpemVkTGluZWFyIGVuY29udHJhZGEgcGFyYSBkeW5hbWljLWludDg7IHVzYW5kbyBtb2RlbG8gcGFkcmFvLiIKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIHJldHVybiBtb2RlbAoKICAgICAgICAgICAgcHJpbnQoZiJbK10gUXVhbnRpemFjYW8gSmluYSBhcGxpY2FkYTogZHluYW1pYy1pbnQ4IChDUFUsIHtxdWFudGl6ZWRfbGF5ZXJzfSBjYW1hZGFzKS4iKQogICAgICAgICAgICByZXR1cm4gbW9kZWwKICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIHF1YW50X2Vycm9yOgogICAgICAgICAgICBwcmludChmIltBVklTT10gRmFsaGEgYW8gYXBsaWNhciBkeW5hbWljLWludDggKHtxdWFudF9lcnJvcn0pOyB1c2FuZG8gbW9kZWxvIHBhZHJhby4iKQogICAgICAgICAgICByZXR1cm4gbW9kZWwKCiAgICB0cnk6CiAgICAgICAgbW9kZWwgPSBfbG9hZF9mcm9tX2xvY2FsX2RpcihzZWxlY3Rpb24ubW9kZWxfaWQpCiAgICAgICAgbW9kZWwgPSBfYXBwbHlfamluYV9xdWFudGl6YXRpb25faWZfbmVlZGVkKG1vZGVsLCBzZWxlY3Rpb24ubW9kZWxfaWQpCiAgICAgICAgcHJpbnQoIlsrXSBNb2RlbG8gY2FycmVnYWRvIGNvbSBzdWNlc3NvLiIpCiAgICAgICAgcmV0dXJuIG1vZGVsCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGZpcnN0X2Vycm9yOgogICAgICAgIGlmIHNlbGVjdGlvbi5tb2RlbF9pZCA9PSBmYWxsYmFja19tb2RlbF9pZDoKICAgICAgICAgICAgcmFpc2UgUnVudGltZUVycm9yKAogICAgICAgICAgICAgICAgZiJGYWxoYSBhbyBjYXJyZWdhciBvIG1vZGVsbyBmYWxsYmFjayAne2ZhbGxiYWNrX21vZGVsX2lkfSc6IHtmaXJzdF9lcnJvcn0iCiAgICAgICAgICAgICkgZnJvbSBmaXJzdF9lcnJvcgoKICAgICAgICBwcmludCgKICAgICAgICAgICAgZiJbIV0gRmFsaGEgYW8gY2FycmVnYXIgJ3tzZWxlY3Rpb24ubW9kZWxfaWR9Jzoge19mb3JtYXRfZXhjZXB0aW9uKGZpcnN0X2Vycm9yKX1cbiIKICAgICAgICAgICAgZiIgICAgVGVudGFuZG8gZmFsbGJhY2sgZGUgY2FycmVnYW1lbnRvOiB7ZmFsbGJhY2tfbW9kZWxfaWR9IgogICAgICAgICkKICAgICAgICBmYWxsYmFja19zZWxlY3Rpb24gPSBkb3dubG9hZF9tb2RlbF93aXRoX2ZhbGxiYWNrKAogICAgICAgICAgICBwcmVmZXJyZWRfbW9kZWxfaWQ9ZmFsbGJhY2tfbW9kZWxfaWQsCiAgICAgICAgICAgIGZhbGxiYWNrX21vZGVsX2lkPWZhbGxiYWNrX21vZGVsX2lkLAogICAgICAgICAgICBsb2NhbF9kaXI9bW9kZWxfYmFzZV9kaXIsCiAgICAgICAgKQogICAgICAgIHNlbGVjdGVkX21vZGVsX2RpciA9IGZhbGxiYWNrX3NlbGVjdGlvbi5sb2NhbF9kaXIKICAgICAgICBwcmludCgKICAgICAgICAgICAgZiJbK10gTW9kZWxvIHNlbGVjaW9uYWRvOiB7ZmFsbGJhY2tfc2VsZWN0aW9uLm1vZGVsX2lkfSAiCiAgICAgICAgICAgIGYiKHByb3ZpZGVyPXtmYWxsYmFja19zZWxlY3Rpb24ucHJvdmlkZXJ9LCBwYXRoPXtzZWxlY3RlZF9tb2RlbF9kaXJ9KSIKICAgICAgICApCiAgICAgICAgbW9kZWwgPSBfbG9hZF9mcm9tX2xvY2FsX2RpcihmYWxsYmFja19zZWxlY3Rpb24ubW9kZWxfaWQpCiAgICAgICAgbW9kZWwgPSBfYXBwbHlfamluYV9xdWFudGl6YXRpb25faWZfbmVlZGVkKG1vZGVsLCBmYWxsYmFja19zZWxlY3Rpb24ubW9kZWxfaWQpCiAgICAgICAgcHJpbnQoIlsrXSBNb2RlbG8gZmFsbGJhY2sgY2FycmVnYWRvIGNvbSBzdWNlc3NvLiIpCiAgICAgICAgcmV0dXJuIG1vZGVsCgoKZGVmIGNvbm5lY3RfdG9fY2hyb21hKCkgLT4gY2hyb21hZGIuSHR0cENsaWVudDoKICAgICIiIkNvbmVjdGEgYW8gQ2hyb21hREIgdmlhIEhUVFAgZSB2YWxpZGEgYSBjb25leMOjby4iIiIKICAgIHRyeToKICAgICAgICBjbGllbnQgPSBjaHJvbWFkYi5IdHRwQ2xpZW50KGhvc3Q9Q0hST01BX0hPU1QsIHBvcnQ9Q0hST01BX1BPUlQpCiAgICAgICAgIyBGYXogdW0gaGVhcnRiZWF0IHBhcmEgY29uZmlybWFyIHF1ZSBvIHNlcnZpZG9yIGVzdMOhIG5vIGFyCiAgICAgICAgY2xpZW50LmhlYXJ0YmVhdCgpCiAgICAgICAgcHJpbnQoZiJbK10gQ29uZWN0YWRvIGFvIENocm9tYURCIGVtIHtDSFJPTUFfSE9TVH06e0NIUk9NQV9QT1JUfSIpCiAgICAgICAgcmV0dXJuIGNsaWVudAogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIHByaW50KGYiW0VSUk9dIE7Do28gZm9pIHBvc3PDrXZlbCBjb25lY3RhciBhbyBDaHJvbWFEQjoge2V9IikKICAgICAgICBwcmludCgiICAgICAgIFZlcmlmaXF1ZSBzZSBvIGNvbnRhaW5lciBEb2NrZXIgZXN0w6Egcm9kYW5kbzoiKQogICAgICAgIHByaW50KCIgICAgICAgZG9ja2VyIGNvbXBvc2UgdXAgLWQiKQogICAgICAgIHN5cy5leGl0KDEpCgoKZGVmIHNjYW5fZmlsZXMocm9vdF9wYXRoOiBQYXRoKSAtPiBJdGVyYXRvcltQYXRoXToKICAgICIiIgogICAgVmFycmUgcmVjdXJzaXZhbWVudGUgbyBkaXJldMOzcmlvIHJhaXosIHJldG9ybmFuZG8gZW0gc3RyZWFtaW5nCiAgICBvcyBhcnF1aXZvcyBkZSB0ZXh0byByZWxldmFudGVzIHBhcmEgaW5kZXhhw6fDo28uCiAgICAiIiIKICAgIGZvciBkaXJwYXRoLCBkaXJuYW1lcywgZmlsZW5hbWVzIGluIG9zLndhbGsocm9vdF9wYXRoKToKICAgICAgICAjIFJlbW92ZSBkaXJzIGlnbm9yYWRvcyBpbi1wbGFjZSBwYXJhIHF1ZSBvcy53YWxrIG7Do28gZGVzw6dhIG5lbGVzCiAgICAgICAgZGlybmFtZXNbOl0gPSBbCiAgICAgICAgICAgIGQgZm9yIGQgaW4gZGlybmFtZXMKICAgICAgICAgICAgaWYgZCBub3QgaW4gSUdOT1JFRF9ESVJTIGFuZCBub3QgZC5zdGFydHN3aXRoKCIuIikKICAgICAgICBdCiAgICAgICAgZGlybmFtZXMuc29ydCgpCgogICAgICAgIGZvciBmaWxlbmFtZSBpbiBzb3J0ZWQoZmlsZW5hbWVzKToKICAgICAgICAgICAgZmlsZXBhdGggPSBQYXRoKGRpcnBhdGgpIC8gZmlsZW5hbWUKCiAgICAgICAgICAgICMgSWdub3JhIHBvciBleHRlbnPDo28KICAgICAgICAgICAgaWYgZmlsZXBhdGguc3VmZml4Lmxvd2VyKCkgaW4gSUdOT1JFRF9FWFRFTlNJT05TOgogICAgICAgICAgICAgICAgY29udGludWUKCiAgICAgICAgICAgICMgSWdub3JhIGFycXVpdm9zIG11aXRvIGdyYW5kZXMKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgaWYgZmlsZXBhdGguc3RhdCgpLnN0X3NpemUgPiBNQVhfRklMRV9TSVpFX0JZVEVTOgogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIGV4Y2VwdCBPU0Vycm9yOgogICAgICAgICAgICAgICAgY29udGludWUKCiAgICAgICAgICAgIHlpZWxkIGZpbGVwYXRoCgoKZGVmIG1ha2VfY2h1bmtfaWQoZmlsZV9wYXRoOiBzdHIsIGNodW5rX2luZGV4OiBpbnQpIC0+IHN0cjoKICAgICIiIkdlcmEgdW0gSUQgZGV0ZXJtaW7DrXN0aWNvIHBhcmEgY2FkYSBjaHVuayBiYXNlYWRvIG5vIGNhbWluaG8gKyDDrW5kaWNlLiIiIgogICAgcmF3ID0gZiJ7ZmlsZV9wYXRofTo6Y2h1bms6OntjaHVua19pbmRleH0iCiAgICByZXR1cm4gaGFzaGxpYi5tZDUocmF3LmVuY29kZSgpKS5oZXhkaWdlc3QoKQoKCmRlZiByZWFkX2ZpbGVfc2FmZShmaWxlcGF0aDogUGF0aCkgLT4gc3RyIHwgTm9uZToKICAgICIiIkzDqiB1bSBhcnF1aXZvIGRlIHRleHRvLCB0ZW50YW5kbyBtw7psdGlwbG9zIGVuY29kaW5ncy4iIiIKICAgIGZvciBlbmNvZGluZyBpbiAoInV0Zi04IiwgImxhdGluLTEiLCAiY3AxMjUyIik6CiAgICAgICAgdHJ5OgogICAgICAgICAgICByZXR1cm4gZmlsZXBhdGgucmVhZF90ZXh0KGVuY29kaW5nPWVuY29kaW5nKQogICAgICAgIGV4Y2VwdCBVbmljb2RlRGVjb2RlRXJyb3I6CiAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgZXhjZXB0IE9TRXJyb3IgYXMgZToKICAgICAgICAgICAgcHJpbnQoZiIgIFtBVklTT10gTsOjbyBmb2kgcG9zc8OtdmVsIGxlciB7ZmlsZXBhdGh9OiB7ZX0iKQogICAgICAgICAgICByZXR1cm4gTm9uZQogICAgIyBTZSBuZW5odW0gZW5jb2RpbmcgZnVuY2lvbm91LCDDqSBwcm92YXZlbG1lbnRlIGJpbsOhcmlvIGRpc2ZhcsOnYWRvCiAgICByZXR1cm4gTm9uZQoKCmRlZiBkZWxldGVfZmlsZV9jaHVua3MoY29sbGVjdGlvbjogY2hyb21hZGIuQ29sbGVjdGlvbiwgZmlsZV9wYXRoOiBzdHIpIC0+IE5vbmU6CiAgICAiIiJSZW1vdmUgdG9kb3Mgb3MgY2h1bmtzIGRlIHVtIGFycXVpdm8gZXNwZWPDrWZpY28gZGEgY29sZcOnw6NvLiIiIgogICAgdHJ5OgogICAgICAgICMgUGVkZSBzb21lbnRlIElEcyBwYXJhIGV2aXRhciBtYXRlcmlhbGl6YXIgZG9jcy9tZXRhZGF0YSBuYSBtZW3Ds3JpYS4KICAgICAgICByZXN1bHRzID0gY29sbGVjdGlvbi5nZXQod2hlcmU9eyJmaWxlX3BhdGgiOiBmaWxlX3BhdGh9LCBpbmNsdWRlPVtdKQogICAgICAgIGlmIHJlc3VsdHMgYW5kIHJlc3VsdHNbImlkcyJdOgogICAgICAgICAgICBjb2xsZWN0aW9uLmRlbGV0ZShpZHM9cmVzdWx0c1siaWRzIl0pCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgcHJpbnQoZiIgIFtBVklTT10gRXJybyBhbyBkZWxldGFyIGNodW5rcyBkZSB7ZmlsZV9wYXRofToge19mb3JtYXRfZXhjZXB0aW9uKGUpfSIpCgoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBJbmRleGHDp8OjbyBkZSB1bSDDum5pY28gYXJxdWl2bwojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKZGVmIGluZGV4X2ZpbGUoCiAgICBmaWxlcGF0aDogUGF0aCwKICAgIGNvbGxlY3Rpb246IGNocm9tYWRiLkNvbGxlY3Rpb24sCiAgICBtb2RlbDogU2VudGVuY2VUcmFuc2Zvcm1lciwKICAgIHNwbGl0dGVyOiBSZWN1cnNpdmVDaGFyYWN0ZXJUZXh0U3BsaXR0ZXIsCiAgICByb290X3BhdGg6IFBhdGgsCiAgICBlbWJlZGRpbmdfYmF0Y2hfc2l6ZTogaW50LAopIC0+IGludDoKICAgICIiIgogICAgSW5kZXhhIHVtIMO6bmljbyBhcnF1aXZvOiBsw6osIGRpdmlkZSBlbSBjaHVua3MsIGdlcmEgZW1iZWRkaW5ncyBlIGZheiB1cHNlcnQuCiAgICBSZXRvcm5hIG8gbsO6bWVybyBkZSBjaHVua3MgaW5kZXhhZG9zLgogICAgIiIiCiAgICBjb250ZW50ID0gcmVhZF9maWxlX3NhZmUoZmlsZXBhdGgpCiAgICBpZiBub3QgY29udGVudCBvciBub3QgY29udGVudC5zdHJpcCgpOgogICAgICAgIHJldHVybiAwCgogICAgIyBVc2EgY2FtaW5obyBhYnNvbHV0byBjb21vIG1ldGFkYWRvCiAgICBhYnNfcGF0aCA9IHN0cihmaWxlcGF0aC5yZXNvbHZlKCkpCgogICAgIyBSZW1vdmUgY2h1bmtzIGFudGlnb3MgZGVzdGUgYXJxdWl2byAoYXR1YWxpemHDp8OjbyBpZGVtcG90ZW50ZSkKICAgIGRlbGV0ZV9maWxlX2NodW5rcyhjb2xsZWN0aW9uLCBhYnNfcGF0aCkKCiAgICBjaHVua3MgPSBzcGxpdHRlci5zcGxpdF90ZXh0KGNvbnRlbnQpCiAgICBpZiBub3QgY2h1bmtzOgogICAgICAgIHJldHVybiAwCgogICAgcmVsYXRpdmVfcGF0aCA9IHN0cihmaWxlcGF0aC5yZWxhdGl2ZV90byhyb290X3BhdGgpKQogICAgaW5zZXJ0ZWRfY2h1bmtzID0gMAogICAgYmF0Y2hfaWRzOiBsaXN0W3N0cl0gPSBbXQogICAgYmF0Y2hfZG9jczogbGlzdFtzdHJdID0gW10KICAgIGJhdGNoX21ldGFkYXRhczogbGlzdFtkaWN0W3N0ciwgb2JqZWN0XV0gPSBbXQoKICAgIGRlZiBfZmx1c2hfYmF0Y2goKSAtPiBOb25lOgogICAgICAgIG5vbmxvY2FsIGluc2VydGVkX2NodW5rcwogICAgICAgIGlmIG5vdCBiYXRjaF9pZHM6CiAgICAgICAgICAgIHJldHVybgoKICAgICAgICBlbWJlZGRpbmdzID0gbW9kZWwuZW5jb2RlKAogICAgICAgICAgICBiYXRjaF9kb2NzLAogICAgICAgICAgICBzaG93X3Byb2dyZXNzX2Jhcj1GYWxzZSwKICAgICAgICAgICAgYmF0Y2hfc2l6ZT1lbWJlZGRpbmdfYmF0Y2hfc2l6ZSwKICAgICAgICApLnRvbGlzdCgpCiAgICAgICAgY29sbGVjdGlvbi51cHNlcnQoCiAgICAgICAgICAgIGlkcz1iYXRjaF9pZHMsCiAgICAgICAgICAgIGVtYmVkZGluZ3M9ZW1iZWRkaW5ncywKICAgICAgICAgICAgZG9jdW1lbnRzPWJhdGNoX2RvY3MsCiAgICAgICAgICAgIG1ldGFkYXRhcz1iYXRjaF9tZXRhZGF0YXMsCiAgICAgICAgKQogICAgICAgIGluc2VydGVkX2NodW5rcyArPSBsZW4oYmF0Y2hfaWRzKQogICAgICAgIGRlbCBlbWJlZGRpbmdzCiAgICAgICAgYmF0Y2hfaWRzLmNsZWFyKCkKICAgICAgICBiYXRjaF9kb2NzLmNsZWFyKCkKICAgICAgICBiYXRjaF9tZXRhZGF0YXMuY2xlYXIoKQogICAgICAgIGdjLmNvbGxlY3QoKQoKICAgIGZvciBpLCBjaHVuayBpbiBlbnVtZXJhdGUoY2h1bmtzKToKICAgICAgICBiYXRjaF9pZHMuYXBwZW5kKG1ha2VfY2h1bmtfaWQoYWJzX3BhdGgsIGkpKQogICAgICAgIGJhdGNoX2RvY3MuYXBwZW5kKGNodW5rKQogICAgICAgIGJhdGNoX21ldGFkYXRhcy5hcHBlbmQoCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJmaWxlX3BhdGgiOiBhYnNfcGF0aCwKICAgICAgICAgICAgICAgICJjaHVua19pbmRleCI6IGksCiAgICAgICAgICAgICAgICAiZmlsZV9uYW1lIjogZmlsZXBhdGgubmFtZSwKICAgICAgICAgICAgICAgICMgQ2FtaW5obyByZWxhdGl2byDDoCByYWl6IGRvIHByb2pldG8gcGFyYSBleGliacOnw6NvIGNvbXBhY3RhCiAgICAgICAgICAgICAgICAicmVsYXRpdmVfcGF0aCI6IHJlbGF0aXZlX3BhdGgsCiAgICAgICAgICAgIH0KICAgICAgICApCiAgICAgICAgaWYgbGVuKGJhdGNoX2lkcykgPj0gZW1iZWRkaW5nX2JhdGNoX3NpemU6CiAgICAgICAgICAgIF9mbHVzaF9iYXRjaCgpCgogICAgX2ZsdXNoX2JhdGNoKCkKICAgIHJldHVybiBpbnNlcnRlZF9jaHVua3MKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIFBvbnRvIGRlIGVudHJhZGEgcHJpbmNpcGFsCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpkZWYgbWFpbigpOgogICAgcGFyc2VyID0gYXJncGFyc2UuQXJndW1lbnRQYXJzZXIoCiAgICAgICAgZGVzY3JpcHRpb249IkluZGV4YSB1bSBwcm9qZXRvIGRlIGPDs2RpZ28gbm8gQ2hyb21hREIgcGFyYSBSQUcgbG9jYWwuIgogICAgKQogICAgcGFyc2VyLmFkZF9hcmd1bWVudCgKICAgICAgICAicHJvamVjdF9wYXRoIiwKICAgICAgICBuYXJncz0iPyIsCiAgICAgICAgZGVmYXVsdD0iLiIsCiAgICAgICAgaGVscD0iQ2FtaW5obyByYWl6IGRvIHByb2pldG8gYSBpbmRleGFyIChwYWRyw6NvOiBkaXJldMOzcmlvIGF0dWFsKSIsCiAgICApCiAgICBwYXJzZXIuYWRkX2FyZ3VtZW50KAogICAgICAgICItLWNsZWFyIiwKICAgICAgICBhY3Rpb249InN0b3JlX3RydWUiLAogICAgICAgIGhlbHA9IkxpbXBhIHRvZGEgYSBjb2xlw6fDo28gYW50ZXMgZGUgcmVpbmRleGFyIiwKICAgICkKICAgIHBhcnNlci5hZGRfYXJndW1lbnQoCiAgICAgICAgIi0tZW1iZWRkaW5nLW1vZGVsIiwKICAgICAgICBjaG9pY2VzPVsiamluYSIsICJiZ2UiLCAiaHlicmlkIl0sCiAgICAgICAgaGVscD0oCiAgICAgICAgICAgICJNb2RlbG8gZGUgZW1iZWRkaW5nczogJ2ppbmEnIChjb2RpZ28pLCAiCiAgICAgICAgICAgICInYmdlJyAoY29udGV1ZG8gbWlzdG8pIG91ICdoeWJyaWQnIChkdWFzIGNvbGVjb2VzOiBKaW5hIHYyICsgQkdFKS4iCiAgICAgICAgKSwKICAgICkKICAgIHBhcnNlci5hZGRfYXJndW1lbnQoCiAgICAgICAgIi0tamluYS1xdWFudGl6YXRpb24iLAogICAgICAgIGNob2ljZXM9WyJkZWZhdWx0IiwgImR5bmFtaWMtaW50OCJdLAogICAgICAgIGhlbHA9IlF1YW50aXphY2FvIHBhcmEgSmluYTogJ2RlZmF1bHQnIChtYWlzIHF1YWxpZGFkZSkgb3UgJ2R5bmFtaWMtaW50OCcgKG1haXMgdmVsb2NpZGFkZSkuIiwKICAgICkKICAgIHBhcnNlci5hZGRfYXJndW1lbnQoCiAgICAgICAgIi0tcGVyZi1wcm9maWxlIiwKICAgICAgICBjaG9pY2VzPVsiYXV0b3R1bmUiLCAibWF4LXBlcmZvcm1hbmNlIl0sCiAgICAgICAgaGVscD0oCiAgICAgICAgICAgICJQZXJmaWwgZGUgcGVyZm9ybWFuY2UgZGEgaW5kZXhhw6fDo286ICIKICAgICAgICAgICAgIidhdXRvdHVuZScgKGN1c3RvLWJlbmVmw61jaW8pIG91ICdtYXgtcGVyZm9ybWFuY2UnIChtYWlzIHRocm91Z2hwdXQsIG1haW9yIHVzbyBkZSBSQU0pLiIKICAgICAgICApLAogICAgKQogICAgYXJncyA9IHBhcnNlci5wYXJzZV9hcmdzKCkKCiAgICByb290X3BhdGggPSBQYXRoKGFyZ3MucHJvamVjdF9wYXRoKS5yZXNvbHZlKCkKICAgIGlmIG5vdCByb290X3BhdGguaXNfZGlyKCk6CiAgICAgICAgcHJpbnQoZiJbRVJST10gQ2FtaW5obyBuw6NvIGV4aXN0ZSBvdSBuw6NvIMOpIHVtIGRpcmV0w7NyaW86IHtyb290X3BhdGh9IikKICAgICAgICBzeXMuZXhpdCgxKQoKICAgIHByaW50KGYiXG57Jz0nKjYwfSIpCiAgICBwcmludChmIiAgUkFHIEluZGV4ZXIg4oCUIFByb2pldG86IHtyb290X3BhdGh9IikKICAgIHByaW50KGYieyc9Jyo2MH1cbiIpCiAgICBpbmRleF9zdGFydGVkX2F0ID0gZGF0ZXRpbWUubm93KCkKICAgIHByaW50KGYiW0lORk9dIEluw61jaW86IHtpbmRleF9zdGFydGVkX2F0LnN0cmZ0aW1lKCclWS0lbS0lZCAlSDolTTolUycpfSIpCgogICAgZm9yY2VfbW9kZWxfcmVjb25maWd1cmUgPSBfZW52X2Jvb2woIk1DUF9GT1JDRV9NT0RFTF9SRUNPTkZJRyIsIGRlZmF1bHQ9RmFsc2UpCiAgICBwZXJzaXN0ZWRfY29uZmlnID0gbG9hZF9pbmRleGVyX3R1bmluZ19jb25maWcoZm9yY2VfbW9kZWxfcmVjb25maWd1cmUpCiAgICBtb2RlbF9jaG9pY2UsIGppbmFfcXVhbnRpemF0aW9uID0gcmVzb2x2ZV9lbWJlZGRpbmdfY29uZmlnKAogICAgICAgIGFyZ3MuZW1iZWRkaW5nX21vZGVsLAogICAgICAgIGFyZ3MuamluYV9xdWFudGl6YXRpb24sCiAgICAgICAgcGVyc2lzdGVkX2NvbmZpZz1wZXJzaXN0ZWRfY29uZmlnLAogICAgKQogICAgcGVyZl9wcm9maWxlID0gcmVzb2x2ZV9wZXJmX3Byb2ZpbGUoYXJncy5wZXJmX3Byb2ZpbGUsIHBlcnNpc3RlZF9jb25maWcpCgogICAgY2h1bmtfc2l6ZV9sb2NrZWQgPSAiTUNQX0NIVU5LX1NJWkUiIGluIG9zLmVudmlyb24KICAgIGNodW5rX292ZXJsYXBfbG9ja2VkID0gIk1DUF9DSFVOS19PVkVSTEFQIiBpbiBvcy5lbnZpcm9uCiAgICBiYXRjaF9zaXplX2xvY2tlZCA9ICJNQ1BfRU1CRURESU5HX0JBVENIX1NJWkUiIGluIG9zLmVudmlyb24KCiAgICBwZXJzaXN0ZWRfY2h1bmtfc2l6ZSA9IF9wYXJzZV9jb25maWdfaW50KHBlcnNpc3RlZF9jb25maWcsICJjaHVua19zaXplIikKICAgIHBlcnNpc3RlZF9jaHVua19vdmVybGFwID0gX3BhcnNlX2NvbmZpZ19pbnQocGVyc2lzdGVkX2NvbmZpZywgImNodW5rX292ZXJsYXAiKQogICAgcGVyc2lzdGVkX2JhdGNoX3NpemUgPSBfcGFyc2VfY29uZmlnX2ludChwZXJzaXN0ZWRfY29uZmlnLCAiZW1iZWRkaW5nX2JhdGNoX3NpemUiKQoKICAgIGVmZmVjdGl2ZV9jaHVua19zaXplID0gQ0hVTktfU0laRQogICAgaWYgbm90IGNodW5rX3NpemVfbG9ja2VkIGFuZCBwZXJzaXN0ZWRfY2h1bmtfc2l6ZSBpcyBub3QgTm9uZToKICAgICAgICBlZmZlY3RpdmVfY2h1bmtfc2l6ZSA9IG1heCgyNTYsIHBlcnNpc3RlZF9jaHVua19zaXplKQoKICAgIGVmZmVjdGl2ZV9jaHVua19vdmVybGFwID0gQ0hVTktfT1ZFUkxBUAogICAgaWYgbm90IGNodW5rX292ZXJsYXBfbG9ja2VkIGFuZCBwZXJzaXN0ZWRfY2h1bmtfb3ZlcmxhcCBpcyBub3QgTm9uZToKICAgICAgICBlZmZlY3RpdmVfY2h1bmtfb3ZlcmxhcCA9IG1heCgwLCBtaW4oZWZmZWN0aXZlX2NodW5rX3NpemUgLSAxLCBwZXJzaXN0ZWRfY2h1bmtfb3ZlcmxhcCkpCgogICAgZWZmZWN0aXZlX2JhdGNoX3NpemUgPSBFTUJFRERJTkdfQkFUQ0hfU0laRQogICAgaWYgbm90IGJhdGNoX3NpemVfbG9ja2VkIGFuZCBwZXJzaXN0ZWRfYmF0Y2hfc2l6ZSBpcyBub3QgTm9uZToKICAgICAgICBlZmZlY3RpdmVfYmF0Y2hfc2l6ZSA9IG1heCgxLCBwZXJzaXN0ZWRfYmF0Y2hfc2l6ZSkKCiAgICBwcmludCgKICAgICAgICBmIltDT05GSUddIE1vZGVsbyBlc2NvbGhpZG86IHttb2RlbF9jaG9pY2V9ICIKICAgICAgICBmIih7X2Rlc2NyaWJlX2VtYmVkZGluZ19jaG9pY2UobW9kZWxfY2hvaWNlKX0pIgogICAgKQogICAgaWYgbW9kZWxfY2hvaWNlID09ICJqaW5hIjoKICAgICAgICBwcmludChmIltDT05GSUddIFF1YW50aXphY2FvIEppbmE6IHtqaW5hX3F1YW50aXphdGlvbn0iKQogICAgZWxpZiBtb2RlbF9jaG9pY2UgPT0gImh5YnJpZCI6CiAgICAgICAgcHJpbnQoIltDT05GSUddIFF1YW50aXphY2FvIEppbmE6IG5hbyBhcGxpY2F2ZWwgbm8gaHlicmlkIChKaW5hIHYyICsgQkdFKSIpCiAgICBlbHNlOgogICAgICAgIHByaW50KCJbQ09ORklHXSBRdWFudGl6YWNhbyBKaW5hOiBuYW8gYXBsaWNhdmVsIChtb2RlbG8gQkdFIHNlbGVjaW9uYWRvKSIpCiAgICBwcmludChmIltDT05GSUddIFBlcmZpbCBkZSBwZXJmb3JtYW5jZToge3BlcmZfcHJvZmlsZX0iKQogICAgaWYgcGVyZl9wcm9maWxlID09ICJtYXgtcGVyZm9ybWFuY2UiOgogICAgICAgIHByaW50KAogICAgICAgICAgICAiW0FWSVNPXSBFc3RlIG1vZG8gcG9kZSBlbGV2YXIgY29uc2lkZXJhdmVsbWVudGUgbyBjb25zdW1vIGRlIG1lbcOzcmlhICIKICAgICAgICAgICAgImUgY2F1c2FyIGVuY2VycmFtZW50byBwb3IgT09NIChleGl0IDEzNykuIgogICAgICAgICkKICAgIHdhcm5faWZfamluYV9tZW1vcnlfcmlzayhtb2RlbF9jaG9pY2UsIGppbmFfcXVhbnRpemF0aW9uKQoKICAgICMgSW5pY2lhbGl6YSBjb21wb25lbnRlcwogICAgY2xpZW50ID0gY29ubmVjdF90b19jaHJvbWEoKQogICAgdGFyZ2V0cyA9IF9yZXNvbHZlX2luZGV4X3RhcmdldHMobW9kZWxfY2hvaWNlKQoKICAgICMgT2J0w6ltIG91IHJlY3JpYSBhcyBjb2xlw6fDtWVzIGVudm9sdmlkYXMuCiAgICBjb2xsZWN0aW9uczogZGljdFtzdHIsIGNocm9tYWRiLkNvbGxlY3Rpb25dID0ge30KICAgIGNvbGxlY3Rpb25fZGltZW5zaW9uX3Jlc2V0X2RvbmU6IGRpY3Rbc3RyLCBib29sXSA9IHt9CiAgICBmb3IgdGFyZ2V0IGluIHRhcmdldHM6CiAgICAgICAgaWYgYXJncy5jbGVhcjoKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgY2xpZW50LmRlbGV0ZV9jb2xsZWN0aW9uKHRhcmdldC5jb2xsZWN0aW9uX25hbWUpCiAgICAgICAgICAgICAgICBwcmludChmIlshXSBDb2xlw6fDo28gJ3t0YXJnZXQuY29sbGVjdGlvbl9uYW1lfScgcmVtb3ZpZGEgcGFyYSByZWluZGV4YcOnw6NvIGxpbXBhLiIpCiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgICAgICAgICBwYXNzCiAgICAgICAgY29sbGVjdGlvbnNbdGFyZ2V0LmNvbGxlY3Rpb25fbmFtZV0gPSBjbGllbnQuZ2V0X29yX2NyZWF0ZV9jb2xsZWN0aW9uKAogICAgICAgICAgICBuYW1lPXRhcmdldC5jb2xsZWN0aW9uX25hbWUsCiAgICAgICAgICAgIG1ldGFkYXRhPXsiaG5zdzpzcGFjZSI6ICJjb3NpbmUifSwKICAgICAgICApCiAgICAgICAgY29sbGVjdGlvbl9kaW1lbnNpb25fcmVzZXRfZG9uZVt0YXJnZXQuY29sbGVjdGlvbl9uYW1lXSA9IEZhbHNlCgogICAgIyBDYXJyZWdhIG1vZGVsb3MgZGUgZm9ybWEgbGF6eSBlIHJlYXByb3ZlaXRhIHBvciB0YXJnZXQuCiAgICBsb2FkZWRfbW9kZWxzOiBkaWN0W3N0ciwgU2VudGVuY2VUcmFuc2Zvcm1lcl0gPSB7fQogICAgdG90YWxfY2h1bmtzID0gMAogICAgZXJyb3JzID0gMAogICAgZmlsZXNfc2Nhbm5lZCA9IDAKICAgIGZpbGVzX3Byb2Nlc3NlZF90b3RhbCA9IDAKICAgIGNodW5rc19ieV9jb2xsZWN0aW9uID0ge3RhcmdldC5jb2xsZWN0aW9uX25hbWU6IDAgZm9yIHRhcmdldCBpbiB0YXJnZXRzfQogICAgZmlsZXNfYnlfY29sbGVjdGlvbiA9IHt0YXJnZXQuY29sbGVjdGlvbl9uYW1lOiAwIGZvciB0YXJnZXQgaW4gdGFyZ2V0c30KICAgIGZpbGVzX2VsaWdpYmxlX2J5X2NvbGxlY3Rpb24gPSB7dGFyZ2V0LmNvbGxlY3Rpb25fbmFtZTogMCBmb3IgdGFyZ2V0IGluIHRhcmdldHN9CiAgICBlcnJvcnNfYnlfY29sbGVjdGlvbiA9IHt0YXJnZXQuY29sbGVjdGlvbl9uYW1lOiAwIGZvciB0YXJnZXQgaW4gdGFyZ2V0c30KICAgIGVycm9yX3NhbXBsZXNfYnlfY29sbGVjdGlvbjogZGljdFtzdHIsIGxpc3Rbc3RyXV0gPSB7dGFyZ2V0LmNvbGxlY3Rpb25fbmFtZTogW10gZm9yIHRhcmdldCBpbiB0YXJnZXRzfQogICAgdGFyZ2V0X2J5X21vZGVsID0ge3RhcmdldC5tb2RlbF9jaG9pY2U6IHRhcmdldCBmb3IgdGFyZ2V0IGluIHRhcmdldHN9CgogICAgIyBDYXJyZWdhIG8gcHJpbWVpcm8gbW9kZWxvIGFudGVzIHBhcmEgYXV0b3R1bmUgY29tIG1pY3JvLWJlbmNobWFyay4KICAgIHByaW1hcnlfdGFyZ2V0ID0gdGFyZ2V0c1swXQogICAgcHJpbWFyeV9xdWFudGl6YXRpb24gPSBqaW5hX3F1YW50aXphdGlvbiBpZiBwcmltYXJ5X3RhcmdldC5tb2RlbF9jaG9pY2UgPT0gImppbmEiIGVsc2UgImRlZmF1bHQiCiAgICBsb2FkZWRfbW9kZWxzW3ByaW1hcnlfdGFyZ2V0Lm1vZGVsX2Nob2ljZV0gPSBsb2FkX2VtYmVkZGluZ19tb2RlbChwcmltYXJ5X3RhcmdldC5tb2RlbF9jaG9pY2UsIHByaW1hcnlfcXVhbnRpemF0aW9uKQogICAgcHJpbWFyeV9tb2RlbCA9IGxvYWRlZF9tb2RlbHNbcHJpbWFyeV90YXJnZXQubW9kZWxfY2hvaWNlXQoKICAgIGlmIHBlcmZfcHJvZmlsZSA9PSAiYXV0b3R1bmUiOgogICAgICAgIHR1bmVkID0gX3Jlc29sdmVfYXV0b3R1bmVkX3BhcmFtcygKICAgICAgICAgICAgbW9kZWw9cHJpbWFyeV9tb2RlbCwKICAgICAgICAgICAgY2h1bmtfc2l6ZV9sb2NrZWQ9Y2h1bmtfc2l6ZV9sb2NrZWQsCiAgICAgICAgICAgIGNodW5rX292ZXJsYXBfbG9ja2VkPWNodW5rX292ZXJsYXBfbG9ja2VkLAogICAgICAgICAgICBiYXRjaF9zaXplX2xvY2tlZD1iYXRjaF9zaXplX2xvY2tlZCwKICAgICAgICAgICAgY2h1bmtfc2l6ZT1lZmZlY3RpdmVfY2h1bmtfc2l6ZSwKICAgICAgICAgICAgY2h1bmtfb3ZlcmxhcD1lZmZlY3RpdmVfY2h1bmtfb3ZlcmxhcCwKICAgICAgICAgICAgZW1iZWRkaW5nX2JhdGNoX3NpemU9ZWZmZWN0aXZlX2JhdGNoX3NpemUsCiAgICAgICAgKQogICAgZWxzZToKICAgICAgICB0dW5lZCA9IF9yZXNvbHZlX21heF9wZXJmb3JtYW5jZV9wYXJhbXMoCiAgICAgICAgICAgIGNodW5rX3NpemVfbG9ja2VkPWNodW5rX3NpemVfbG9ja2VkLAogICAgICAgICAgICBjaHVua19vdmVybGFwX2xvY2tlZD1jaHVua19vdmVybGFwX2xvY2tlZCwKICAgICAgICAgICAgYmF0Y2hfc2l6ZV9sb2NrZWQ9YmF0Y2hfc2l6ZV9sb2NrZWQsCiAgICAgICAgICAgIGNodW5rX3NpemU9ZWZmZWN0aXZlX2NodW5rX3NpemUsCiAgICAgICAgICAgIGNodW5rX292ZXJsYXA9ZWZmZWN0aXZlX2NodW5rX292ZXJsYXAsCiAgICAgICAgICAgIGVtYmVkZGluZ19iYXRjaF9zaXplPWVmZmVjdGl2ZV9iYXRjaF9zaXplLAogICAgICAgICkKCiAgICBlZmZlY3RpdmVfY2h1bmtfc2l6ZSA9IG1heCgyNTYsIHR1bmVkLmNodW5rX3NpemUpCiAgICBlZmZlY3RpdmVfY2h1bmtfb3ZlcmxhcCA9IG1heCgwLCBtaW4oZWZmZWN0aXZlX2NodW5rX3NpemUgLSAxLCB0dW5lZC5jaHVua19vdmVybGFwKSkKICAgIGVmZmVjdGl2ZV9iYXRjaF9zaXplID0gbWF4KDEsIHR1bmVkLmVtYmVkZGluZ19iYXRjaF9zaXplKQoKICAgIGZvciByZWFzb24gaW4gdHVuZWQucmVhc29uczoKICAgICAgICBwcmludChmIltDT05GSUddIHtyZWFzb259IikKCiAgICBwcmludCgKICAgICAgICBmIltDT05GSUddIFBhcsOibWV0cm9zIGZpbmFpczogIgogICAgICAgIGYiY2h1bmtfc2l6ZT17ZWZmZWN0aXZlX2NodW5rX3NpemV9LCBjaHVua19vdmVybGFwPXtlZmZlY3RpdmVfY2h1bmtfb3ZlcmxhcH0sICIKICAgICAgICBmImVtYmVkZGluZ19iYXRjaD17ZWZmZWN0aXZlX2JhdGNoX3NpemV9IgogICAgKQoKICAgIHNhdmVfaW5kZXhlcl90dW5pbmdfY29uZmlnKAogICAgICAgIHsKICAgICAgICAgICAgImVtYmVkZGluZ19tb2RlbCI6IG1vZGVsX2Nob2ljZSwKICAgICAgICAgICAgImppbmFfcXVhbnRpemF0aW9uIjogamluYV9xdWFudGl6YXRpb24sCiAgICAgICAgICAgICJwZXJmX3Byb2ZpbGUiOiBwZXJmX3Byb2ZpbGUsCiAgICAgICAgICAgICJjaHVua19zaXplIjogZWZmZWN0aXZlX2NodW5rX3NpemUsCiAgICAgICAgICAgICJjaHVua19vdmVybGFwIjogZWZmZWN0aXZlX2NodW5rX292ZXJsYXAsCiAgICAgICAgICAgICJlbWJlZGRpbmdfYmF0Y2hfc2l6ZSI6IGVmZmVjdGl2ZV9iYXRjaF9zaXplLAogICAgICAgIH0KICAgICkKCiAgICBzcGxpdHRlciA9IGdldF90ZXh0X3NwbGl0dGVyKGVmZmVjdGl2ZV9jaHVua19zaXplLCBlZmZlY3RpdmVfY2h1bmtfb3ZlcmxhcCkKCiAgICBwcmludChmIlxuWytdIFZhcnJlbmRvIGUgaW5kZXhhbmRvIGFycXVpdm9zIGVtOiB7cm9vdF9wYXRofSIpCiAgICBmaWxlcyA9IGxpc3Qoc2Nhbl9maWxlcyhyb290X3BhdGgpKQogICAgZmlsZXNfc2Nhbm5lZCA9IGxlbihmaWxlcykKICAgIGlmIGZpbGVzX3NjYW5uZWQgPT0gMDoKICAgICAgICBwcmludCgiW0FWSVNPXSBOZW5odW0gYXJxdWl2byBlbmNvbnRyYWRvLiBWZXJpZmlxdWUgbyBjYW1pbmhvIGUgb3MgZmlsdHJvcy4iKQogICAgICAgIHN5cy5leGl0KDApCgogICAgcHJpbnQoZiJbK10ge2ZpbGVzX3NjYW5uZWR9IGFycXVpdm8ocykgZWxlZ8OtdmVsKGlzKSBwYXJhIGluZGV4YcOnw6NvLiIpCiAgICB3aXRoIHRxZG0oCiAgICAgICAgdG90YWw9ZmlsZXNfc2Nhbm5lZCwKICAgICAgICBkZXNjPSJJbmRleGFuZG8iLAogICAgICAgIHVuaXQ9ImFycXVpdm8iLAogICAgICAgIGJhcl9mb3JtYXQ9IntsX2Jhcn17YmFyfXwge25fZm10fS97dG90YWxfZm10fSBbe2VsYXBzZWR9LCB7cmF0ZV9mbXR9XSIsCiAgICApIGFzIHBiYXI6CiAgICAgICAgZm9yIGZpbGVwYXRoIGluIGZpbGVzOgogICAgICAgICAgICB0YXJnZXRfbW9kZWxzID0gX2NsYXNzaWZ5X2ZpbGVfdGFyZ2V0cyhmaWxlcGF0aCwgbW9kZWxfY2hvaWNlKQoKICAgICAgICAgICAgZm9yIHRhcmdldF9tb2RlbCBpbiB0YXJnZXRfbW9kZWxzOgogICAgICAgICAgICAgICAgdGFyZ2V0ID0gdGFyZ2V0X2J5X21vZGVsLmdldCh0YXJnZXRfbW9kZWwpCiAgICAgICAgICAgICAgICBpZiB0YXJnZXQgaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICBjb250aW51ZQoKICAgICAgICAgICAgICAgIGlmIHRhcmdldC5tb2RlbF9jaG9pY2Ugbm90IGluIGxvYWRlZF9tb2RlbHM6CiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0X3F1YW50aXphdGlvbiA9IGppbmFfcXVhbnRpemF0aW9uIGlmIHRhcmdldC5tb2RlbF9jaG9pY2UgPT0gImppbmEiIGVsc2UgImRlZmF1bHQiCiAgICAgICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgICAgICBsb2FkZWRfbW9kZWxzW3RhcmdldC5tb2RlbF9jaG9pY2VdID0gbG9hZF9lbWJlZGRpbmdfbW9kZWwoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQubW9kZWxfY2hvaWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0X3F1YW50aXphdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgbG9hZF9lcnJvcjoKICAgICAgICAgICAgICAgICAgICAgICAgIyBFbSBoeWJyaWQsIHBvZGUgZmFsdGFyIFJBTSBhbyBtYW50ZXIgZG9pcyBtb2RlbG9zIGdyYW5kZXMgc2ltdWx0YW5lYW1lbnRlLgogICAgICAgICAgICAgICAgICAgICAgICBpZiBtb2RlbF9jaG9pY2UgPT0gImh5YnJpZCIgYW5kIGxvYWRlZF9tb2RlbHMgYW5kIF9pc19tZW1vcnlfcmVsYXRlZF9lcnJvcihsb2FkX2Vycm9yKToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW50KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJbQVZJU09dIEZhbGhhIGFvIGNhcnJlZ2FyIG1vZGVsbyBhZGljaW9uYWwgbm8gaHlicmlkIHBvciBtZW3Ds3JpYS4gIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMaWJlcmFuZG8gbW9kZWxvIGFudGVyaW9yIGUgdGVudGFuZG8gbm92YW1lbnRlLiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvYWRlZF9tb2RlbHMuY2xlYXIoKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2MuY29sbGVjdCgpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2FkZWRfbW9kZWxzW3RhcmdldC5tb2RlbF9jaG9pY2VdID0gbG9hZF9lbWJlZGRpbmdfbW9kZWwoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0Lm1vZGVsX2Nob2ljZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRfcXVhbnRpemF0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFpc2UKCiAgICAgICAgICAgICAgICBtb2RlbCA9IGxvYWRlZF9tb2RlbHNbdGFyZ2V0Lm1vZGVsX2Nob2ljZV0KICAgICAgICAgICAgICAgIGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1t0YXJnZXQuY29sbGVjdGlvbl9uYW1lXQogICAgICAgICAgICAgICAgZmlsZXNfZWxpZ2libGVfYnlfY29sbGVjdGlvblt0YXJnZXQuY29sbGVjdGlvbl9uYW1lXSArPSAxCgogICAgICAgICAgICAgICAgd2hpbGUgVHJ1ZToKICAgICAgICAgICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICAgICAgICAgIG5fY2h1bmtzID0gaW5kZXhfZmlsZSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVwYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sbGVjdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BsaXR0ZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290X3BhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbWJlZGRpbmdfYmF0Y2hfc2l6ZT1lZmZlY3RpdmVfYmF0Y2hfc2l6ZSwKICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICB0b3RhbF9jaHVua3MgKz0gbl9jaHVua3MKICAgICAgICAgICAgICAgICAgICAgICAgZmlsZXNfcHJvY2Vzc2VkX3RvdGFsICs9IDEKICAgICAgICAgICAgICAgICAgICAgICAgY2h1bmtzX2J5X2NvbGxlY3Rpb25bdGFyZ2V0LmNvbGxlY3Rpb25fbmFtZV0gKz0gbl9jaHVua3MKICAgICAgICAgICAgICAgICAgICAgICAgZmlsZXNfYnlfY29sbGVjdGlvblt0YXJnZXQuY29sbGVjdGlvbl9uYW1lXSArPSAxCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICAgICAgICAgICAgICAjIEZhbGxiYWNrIGF1dG9tw6F0aWNvIHBhcmEgZXZpdGFyIHF1ZWJyYSB0b3RhbCBlbSBtw6FxdWluYXMgbm8gbGltaXRlIGRlIFJBTS4KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbm90IGJhdGNoX3NpemVfbG9ja2VkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmQgZWZmZWN0aXZlX2JhdGNoX3NpemUgPiAxCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmQgX2lzX21lbW9yeV9yZWxhdGVkX2Vycm9yKGUpCiAgICAgICAgICAgICAgICAgICAgICAgICk6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdfYmF0Y2ggPSBtYXgoMSwgZWZmZWN0aXZlX2JhdGNoX3NpemUgLy8gMikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIG5ld19iYXRjaCA8IGVmZmVjdGl2ZV9iYXRjaF9zaXplOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRxZG0ud3JpdGUoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGYiICBbQUpVU1RFXSBNZW3Ds3JpYSBhbHRhIGVtIHt0YXJnZXQubGFiZWx9LiAiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGYiQmF0Y2ggcmVkdXppZG8ge2VmZmVjdGl2ZV9iYXRjaF9zaXplfSAtPiB7bmV3X2JhdGNofS4iCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVmZmVjdGl2ZV9iYXRjaF9zaXplID0gbmV3X2JhdGNoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2MuY29sbGVjdCgpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWUKCiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9pc19kaW1lbnNpb25fbWlzbWF0Y2hfZXJyb3IoZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuZCBub3QgY29sbGVjdGlvbl9kaW1lbnNpb25fcmVzZXRfZG9uZVt0YXJnZXQuY29sbGVjdGlvbl9uYW1lXQogICAgICAgICAgICAgICAgICAgICAgICApOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHFkbS53cml0ZSgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmIiAgW0FKVVNURV0gRGltZW5zw6NvIGluY29tcGF0w612ZWwgZGV0ZWN0YWRhIGVtICd7dGFyZ2V0LmNvbGxlY3Rpb25fbmFtZX0nLiAiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlY3JpYW5kbyBjb2xlw6fDo28gZSB0ZW50YW5kbyBub3ZhbWVudGUuIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaWVudC5kZWxldGVfY29sbGVjdGlvbih0YXJnZXQuY29sbGVjdGlvbl9uYW1lKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXNzCgogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sbGVjdGlvbnNbdGFyZ2V0LmNvbGxlY3Rpb25fbmFtZV0gPSBjbGllbnQuZ2V0X29yX2NyZWF0ZV9jb2xsZWN0aW9uKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9dGFyZ2V0LmNvbGxlY3Rpb25fbmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YT17Imhuc3c6c3BhY2UiOiAiY29zaW5lIn0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsZWN0aW9uX2RpbWVuc2lvbl9yZXNldF9kb25lW3RhcmdldC5jb2xsZWN0aW9uX25hbWVdID0gVHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2MuY29sbGVjdCgpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZQoKICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JzICs9IDEKICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JzX2J5X2NvbGxlY3Rpb25bdGFyZ2V0LmNvbGxlY3Rpb25fbmFtZV0gKz0gMQogICAgICAgICAgICAgICAgICAgICAgICBpZiBsZW4oZXJyb3Jfc2FtcGxlc19ieV9jb2xsZWN0aW9uW3RhcmdldC5jb2xsZWN0aW9uX25hbWVdKSA8IDM6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl9zYW1wbGVzX2J5X2NvbGxlY3Rpb25bdGFyZ2V0LmNvbGxlY3Rpb25fbmFtZV0uYXBwZW5kKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGYie2ZpbGVwYXRoLm5hbWV9OiB7X2Zvcm1hdF9leGNlcHRpb24oZSl9IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICB0cWRtLndyaXRlKGYiICBbRVJST10ge2ZpbGVwYXRofSBbe3RhcmdldC5sYWJlbH1dOiB7X2Zvcm1hdF9leGNlcHRpb24oZSl9IikKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsKCiAgICAgICAgICAgIHBiYXIuc2V0X3Bvc3RmaXgoeyJjaHVua3MiOiB0b3RhbF9jaHVua3MsICJhdHVhbCI6IGZpbGVwYXRoLm5hbWVbOjIwXX0pCiAgICAgICAgICAgIHBiYXIudXBkYXRlKDEpCgogICAgZm9yIHRhcmdldCBpbiB0YXJnZXRzOgogICAgICAgIGNvbGxlY3Rpb25fbmFtZSA9IHRhcmdldC5jb2xsZWN0aW9uX25hbWUKICAgICAgICBlbGlnaWJsZSA9IGZpbGVzX2VsaWdpYmxlX2J5X2NvbGxlY3Rpb25bY29sbGVjdGlvbl9uYW1lXQogICAgICAgIHByb2Nlc3NlZCA9IGZpbGVzX2J5X2NvbGxlY3Rpb25bY29sbGVjdGlvbl9uYW1lXQogICAgICAgIHRhcmdldF9lcnJvcnMgPSBlcnJvcnNfYnlfY29sbGVjdGlvbltjb2xsZWN0aW9uX25hbWVdCgogICAgICAgIGlmIGVsaWdpYmxlID09IDA6CiAgICAgICAgICAgIHByaW50KGYiW0FWSVNPXSBOZW5odW0gYXJxdWl2byBlbGVnw612ZWwgcGFyYSB7dGFyZ2V0LmxhYmVsfTsgZXRhcGEgaWdub3JhZGEuIikKICAgICAgICBlbGlmIHByb2Nlc3NlZCA9PSAwIGFuZCB0YXJnZXRfZXJyb3JzID4gMDoKICAgICAgICAgICAgcHJpbnQoCiAgICAgICAgICAgICAgICBmIltBVklTT10ge2VsaWdpYmxlfSBhcnF1aXZvKHMpIGVsZWfDrXZlbChpcykgcGFyYSB7dGFyZ2V0LmxhYmVsfSwgIgogICAgICAgICAgICAgICAgIm1hcyB0b2RvcyBmYWxoYXJhbS4iCiAgICAgICAgICAgICkKCiAgICAgICAgaWYgdGFyZ2V0X2Vycm9yczoKICAgICAgICAgICAgcHJpbnQoZiJbQVZJU09dIHt0YXJnZXRfZXJyb3JzfSBlcnJvKHMpIGR1cmFudGUgYSBpbmRleGHDp8OjbyBkbyB0YXJnZXQge3RhcmdldC5sYWJlbH0uIikKICAgICAgICAgICAgZm9yIHNhbXBsZSBpbiBlcnJvcl9zYW1wbGVzX2J5X2NvbGxlY3Rpb25bY29sbGVjdGlvbl9uYW1lXToKICAgICAgICAgICAgICAgIHByaW50KGYiICAgICAgICAtIHtzYW1wbGV9IikKCiAgICBpbmRleF9maW5pc2hlZF9hdCA9IGRhdGV0aW1lLm5vdygpCiAgICBlbGFwc2VkX3NlY29uZHMgPSBpbnQoKGluZGV4X2ZpbmlzaGVkX2F0IC0gaW5kZXhfc3RhcnRlZF9hdCkudG90YWxfc2Vjb25kcygpKQogICAgZWxhcHNlZF9oID0gZWxhcHNlZF9zZWNvbmRzIC8vIDM2MDAKICAgIGVsYXBzZWRfbSA9IChlbGFwc2VkX3NlY29uZHMgJSAzNjAwKSAvLyA2MAogICAgZWxhcHNlZF9zID0gZWxhcHNlZF9zZWNvbmRzICUgNjAKICAgIHByaW50KGYiXG57Jz0nKjYwfSIpCiAgICBwcmludChmIiAgSW5kZXhhw6fDo28gY29uY2x1w61kYSEiKQogICAgcHJpbnQoZiIgIEluw61jaW8gICAgICAgICAgICAgICA6IHtpbmRleF9zdGFydGVkX2F0LnN0cmZ0aW1lKCclWS0lbS0lZCAlSDolTTolUycpfSIpCiAgICBwcmludChmIiAgRmltICAgICAgICAgICAgICAgICAgOiB7aW5kZXhfZmluaXNoZWRfYXQuc3RyZnRpbWUoJyVZLSVtLSVkICVIOiVNOiVTJyl9IikKICAgIHByaW50KGYiICBEdXJhw6fDo28gICAgICAgICAgICAgIDoge2VsYXBzZWRfaDowMmR9OntlbGFwc2VkX206MDJkfTp7ZWxhcHNlZF9zOjAyZH0iKQogICAgcHJpbnQoZiIgIEFycXVpdm9zIHZhcnJpZG9zICAgIDoge2ZpbGVzX3NjYW5uZWR9IikKICAgIHByaW50KGYiICBBcnF1aXZvcyBwcm9jZXNzYWRvcyA6IHtmaWxlc19wcm9jZXNzZWRfdG90YWx9IikKICAgIHByaW50KGYiICBUb3RhbCBkZSBjaHVua3MgICAgICA6IHt0b3RhbF9jaHVua3N9IikKICAgIHByaW50KGYiICBFcnJvcyAgICAgICAgICAgICAgICA6IHtlcnJvcnN9IikKICAgIGZvciB0YXJnZXQgaW4gdGFyZ2V0czoKICAgICAgICBjb2xsZWN0aW9uX25hbWUgPSB0YXJnZXQuY29sbGVjdGlvbl9uYW1lCiAgICAgICAgcHJpbnQoCiAgICAgICAgICAgIGYiICBDb2xlw6fDo28gQ2hyb21hREIgICAgIDogJ3tjb2xsZWN0aW9uX25hbWV9JyAiCiAgICAgICAgICAgIGYiKGVsZWfDrXZlaXM9e2ZpbGVzX2VsaWdpYmxlX2J5X2NvbGxlY3Rpb24uZ2V0KGNvbGxlY3Rpb25fbmFtZSwgMCl9LCAiCiAgICAgICAgICAgIGYiYXJxdWl2b3M9e2ZpbGVzX2J5X2NvbGxlY3Rpb24uZ2V0KGNvbGxlY3Rpb25fbmFtZSwgMCl9LCAiCiAgICAgICAgICAgIGYiY2h1bmtzPXtjaHVua3NfYnlfY29sbGVjdGlvbi5nZXQoY29sbGVjdGlvbl9uYW1lLCAwKX0pIgogICAgICAgICkKICAgIHByaW50KGYieyc9Jyo2MH1cbiIpCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHRyeToKICAgICAgICBtYWluKCkKICAgIGV4Y2VwdCBNZW1vcnlFcnJvcjoKICAgICAgICBwcmludCgKICAgICAgICAgICAgIltFUlJPXSBGYWxoYSBkZSBtZW3Ds3JpYSBkdXJhbnRlIGEgaW5kZXhhw6fDo28uICIKICAgICAgICAgICAgIlVzZSAtLWVtYmVkZGluZy1tb2RlbCBiZ2Ugb3UgZXhlY3V0ZSBvIEppbmEgZW0gbcOhcXVpbmEgY29tIG1haXMgUkFNL3N3YXAuIgogICAgICAgICkKICAgICAgICBzeXMuZXhpdCgxKQo="
|
|
564
|
-
B64_MCP="IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwpmcm9tIF9fZnV0dXJlX18gaW1wb3J0IGFubm90YXRpb25zCiIiIgptY3Bfc2VydmVyLnB5IOKAlCBTZXJ2aWRvciBNQ1AgcGFyYSBSQUcgbG9jYWwgZGUgY29kZWJhc2UuCgpFeHDDtWUgZmVycmFtZW50YXMgZGUgYnVzY2Egc2Vtw6JudGljYSBlIGluZGV4YcOnw6NvIHZpYSBzdGRpbyBwYXJhIG8gQ2xhdWRlIENvZGUgQ0xJLgpDb25lY3RhLXNlIGFvIENocm9tYURCIHJvZGFuZG8gZW0gRG9ja2VyIChsb2NhbGhvc3Q6ODAwMCkuCgpOb3ZpZGFkZTogbW9kbyBow61icmlkbyBlbnNlbWJsZSBjb20gZHVhcyBjb2xlw6fDtWVzIHNlcGFyYWRhcyArIFJSRiArIHJlcmFua2luZyBsZXZlLgoiIiIKCmltcG9ydCBzeXMKaW1wb3J0IG9zCmltcG9ydCBoYXNobGliCmltcG9ydCBqc29uCmltcG9ydCBsb2dnaW5nCmltcG9ydCBnZXRwYXNzCmltcG9ydCBzaHV0aWwKZnJvbSBjb2xsZWN0aW9ucy5hYmMgaW1wb3J0IEl0ZXJhdG9yCmZyb20gY29uY3VycmVudC5mdXR1cmVzIGltcG9ydCBUaHJlYWRQb29sRXhlY3V0b3IsIGFzX2NvbXBsZXRlZApmcm9tIGRhdGFjbGFzc2VzIGltcG9ydCBkYXRhY2xhc3MKZnJvbSBkYXRldGltZSBpbXBvcnQgZGF0ZXRpbWUsIHRpbWV6b25lCmZyb20gcGF0aGxpYiBpbXBvcnQgUGF0aAoKIyBFdml0YSBtZW5zYWdlbnMgYWR2aXNvcnkgZG8gdHJhbnNmb3JtZXJzIGVtIHN0ZGVyciBkdXJhbnRlIGEgY2FyZ2EgZG8gbW9kZWxvLgpvcy5lbnZpcm9uLnNldGRlZmF1bHQoIlRSQU5TRk9STUVSU19OT19BRFZJU09SWV9XQVJOSU5HUyIsICIxIikKCgpjbGFzcyBfVG9yY2hEdHlwZVdhcm5pbmdGaWx0ZXIobG9nZ2luZy5GaWx0ZXIpOgogICAgZGVmIGZpbHRlcihzZWxmLCByZWNvcmQ6IGxvZ2dpbmcuTG9nUmVjb3JkKSAtPiBib29sOgogICAgICAgIHJldHVybiAiYHRvcmNoX2R0eXBlYCBpcyBkZXByZWNhdGVkISBVc2UgYGR0eXBlYCBpbnN0ZWFkISIgbm90IGluIHJlY29yZC5nZXRNZXNzYWdlKCkKCgpmb3IgX2xvZ2dlcl9uYW1lIGluICgidHJhbnNmb3JtZXJzLmNvbmZpZ3VyYXRpb25fdXRpbHMiLCAidHJhbnNmb3JtZXJzLm1vZGVsaW5nX3V0aWxzIik6CiAgICBsb2dnaW5nLmdldExvZ2dlcihfbG9nZ2VyX25hbWUpLmFkZEZpbHRlcihfVG9yY2hEdHlwZVdhcm5pbmdGaWx0ZXIoKSkKCmltcG9ydCBjaHJvbWFkYgpmcm9tIHNlbnRlbmNlX3RyYW5zZm9ybWVycyBpbXBvcnQgQ3Jvc3NFbmNvZGVyLCBTZW50ZW5jZVRyYW5zZm9ybWVyCmZyb20gbGFuZ2NoYWluX3RleHRfc3BsaXR0ZXJzIGltcG9ydCBSZWN1cnNpdmVDaGFyYWN0ZXJUZXh0U3BsaXR0ZXIKZnJvbSBtY3Auc2VydmVyLmZhc3RtY3AgaW1wb3J0IEZhc3RNQ1AKZnJvbSBkb3dubG9hZF9tb2RlbF9mcm9tX2h1Z2dpbmZhY2UgaW1wb3J0IGRvd25sb2FkX21vZGVsX3dpdGhfZmFsbGJhY2sKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgQ29uZmlndXJhw6fDo28gZGUgbG9nZ2luZyAoc3RkZXJyIHBhcmEgbsOjbyBwb2x1aXIgbyBwcm90b2NvbG8gc3RkaW8pCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpsb2dnaW5nLmJhc2ljQ29uZmlnKAogICAgbGV2ZWw9bG9nZ2luZy5JTkZPLAogICAgZm9ybWF0PSJbTUNQLVJBR10gJShhc2N0aW1lKXMgJShsZXZlbG5hbWUpczogJShtZXNzYWdlKXMiLAogICAgc3RyZWFtPXN5cy5zdGRlcnIsCikKbG9nID0gbG9nZ2luZy5nZXRMb2dnZXIoX19uYW1lX18pCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIExvZyBlc3RydXR1cmFkbyBkZSB1c28gTUNQIChKU09OTCkKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCk1DUF9VU0FHRV9MT0dfUEFUSCA9IFBhdGgoCiAgICBvcy5lbnZpcm9uLmdldCgiTUNQX1VTQUdFX0xPRyIsIHN0cihQYXRoLmhvbWUoKSAvICIucmFnX2RiIiAvICJtY3BfdXNhZ2UubG9nIikpCikuZXhwYW5kdXNlcigpCgoKZGVmIF9zYWZlX3ByZXZpZXcodmFsdWU6IHN0ciwgbGltaXQ6IGludCA9IDEyMCkgLT4gc3RyOgogICAgaWYgbGVuKHZhbHVlKSA8PSBsaW1pdDoKICAgICAgICByZXR1cm4gdmFsdWUKICAgIHJldHVybiB2YWx1ZVs6bGltaXRdICsgIi4uLlt0cnVuY2F0ZWRdIgoKCmRlZiBfZ2V0X3BhcmVudF9jbWRsaW5lKCkgLT4gc3RyOgogICAgcHBpZCA9IG9zLmdldHBwaWQoKQogICAgY21kbGluZV9wYXRoID0gUGF0aChmIi9wcm9jL3twcGlkfS9jbWRsaW5lIikKICAgIHRyeToKICAgICAgICByYXcgPSBjbWRsaW5lX3BhdGgucmVhZF9ieXRlcygpCiAgICAgICAgaWYgbm90IHJhdzoKICAgICAgICAgICAgcmV0dXJuICJ1bmtub3duIgogICAgICAgIHBhcnRzID0gW3AuZGVjb2RlKCJ1dGYtOCIsIGVycm9ycz0iaWdub3JlIikgZm9yIHAgaW4gcmF3LnNwbGl0KGIiXHgwMCIpIGlmIHBdCiAgICAgICAgcmV0dXJuICIgIi5qb2luKHBhcnRzKSBpZiBwYXJ0cyBlbHNlICJ1bmtub3duIgogICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICByZXR1cm4gInVua25vd24iCgoKZGVmIF9pbmZlcl9hY3RvcigpIC0+IGRpY3Rbc3RyLCBzdHJdOgogICAgYWN0b3IgPSBvcy5lbnZpcm9uLmdldCgiTUNQX0NMSUVOVF9OQU1FIikgb3Igb3MuZW52aXJvbi5nZXQoIkNMQVVERV9VU0VSIikgb3IgZ2V0cGFzcy5nZXR1c2VyKCkKICAgIHNvdXJjZSA9ICgKICAgICAgICAiTUNQX0NMSUVOVF9OQU1FIiBpZiBvcy5lbnZpcm9uLmdldCgiTUNQX0NMSUVOVF9OQU1FIikKICAgICAgICBlbHNlICJDTEFVREVfVVNFUiIgaWYgb3MuZW52aXJvbi5nZXQoIkNMQVVERV9VU0VSIikKICAgICAgICBlbHNlICJzeXN0ZW1fdXNlciIKICAgICkKICAgIHJldHVybiB7CiAgICAgICAgImFjdG9yIjogYWN0b3IsCiAgICAgICAgImFjdG9yX3NvdXJjZSI6IHNvdXJjZSwKICAgICAgICAiY2xpZW50X3Byb2Nlc3MiOiBfZ2V0X3BhcmVudF9jbWRsaW5lKCksCiAgICB9CgoKZGVmIF9sb2dfdG9vbF91c2FnZShldmVudDogc3RyLCB0b29sX25hbWU6IHN0ciwgZGV0YWlsczogZGljdFtzdHIsIG9iamVjdF0gfCBOb25lID0gTm9uZSkgLT4gTm9uZToKICAgIHRyeToKICAgICAgICBNQ1BfVVNBR0VfTE9HX1BBVEgucGFyZW50Lm1rZGlyKHBhcmVudHM9VHJ1ZSwgZXhpc3Rfb2s9VHJ1ZSkKICAgICAgICBwYXlsb2FkOiBkaWN0W3N0ciwgb2JqZWN0XSA9IHsKICAgICAgICAgICAgInRpbWVzdGFtcCI6IGRhdGV0aW1lLm5vdyh0aW1lem9uZS51dGMpLmlzb2Zvcm1hdCgpLAogICAgICAgICAgICAiZXZlbnQiOiBldmVudCwKICAgICAgICAgICAgInRvb2wiOiB0b29sX25hbWUsCiAgICAgICAgICAgICJwaWQiOiBvcy5nZXRwaWQoKSwKICAgICAgICAgICAgKipfaW5mZXJfYWN0b3IoKSwKICAgICAgICB9CiAgICAgICAgaWYgZGV0YWlsczoKICAgICAgICAgICAgcGF5bG9hZFsiZGV0YWlscyJdID0gZGV0YWlscwoKICAgICAgICB3aXRoIE1DUF9VU0FHRV9MT0dfUEFUSC5vcGVuKCJhIiwgZW5jb2Rpbmc9InV0Zi04IikgYXMgZjoKICAgICAgICAgICAgZi53cml0ZShqc29uLmR1bXBzKHBheWxvYWQsIGVuc3VyZV9hc2NpaT1UcnVlKSArICJcbiIpCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgbG9nLndhcm5pbmcoIkZhbGhhIGFvIHJlZ2lzdHJhciB1c28gTUNQIGVtICVzOiAlcyIsIE1DUF9VU0FHRV9MT0dfUEFUSCwgZSkKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIENvbmZpZ3VyYcOnw7VlcwojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCklOREVYRVJfQ09ORklHX1BBVEggPSBQYXRoKAogICAgb3MuZW52aXJvbi5nZXQoIk1DUF9JTkRFWEVSX0NPTkZJR19GSUxFIiwgc3RyKFBhdGguaG9tZSgpIC8gIi5yYWdfZGIiIC8gImluZGV4ZXJfdHVuaW5nLmpzb24iKSkKKS5leHBhbmR1c2VyKCkKCgpkZWYgX2xvYWRfaW5kZXhlcl90dW5pbmdfY29uZmlnKCkgLT4gZGljdFtzdHIsIG9iamVjdF06CiAgICB0cnk6CiAgICAgICAgaWYgbm90IElOREVYRVJfQ09ORklHX1BBVEguZXhpc3RzKCk6CiAgICAgICAgICAgIHJldHVybiB7fQogICAgICAgIHBheWxvYWQgPSBqc29uLmxvYWRzKElOREVYRVJfQ09ORklHX1BBVEgucmVhZF90ZXh0KGVuY29kaW5nPSJ1dGYtOCIpKQogICAgICAgIHJldHVybiBwYXlsb2FkIGlmIGlzaW5zdGFuY2UocGF5bG9hZCwgZGljdCkgZWxzZSB7fQogICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICByZXR1cm4ge30KCgpJTkRFWEVSX1RVTklOR19DT05GSUcgPSBfbG9hZF9pbmRleGVyX3R1bmluZ19jb25maWcoKQoKCmRlZiBfY29uZmlnX3N0cihlbnZfbmFtZTogc3RyLCBjb25maWdfa2V5OiBzdHIsIGRlZmF1bHQ6IHN0cikgLT4gc3RyOgogICAgZW52X3JhdyA9IG9zLmVudmlyb24uZ2V0KGVudl9uYW1lKQogICAgaWYgZW52X3JhdyBpcyBub3QgTm9uZSBhbmQgZW52X3Jhdy5zdHJpcCgpOgogICAgICAgIHJldHVybiBlbnZfcmF3CiAgICBjZmdfcmF3ID0gSU5ERVhFUl9UVU5JTkdfQ09ORklHLmdldChjb25maWdfa2V5KQogICAgaWYgaXNpbnN0YW5jZShjZmdfcmF3LCBzdHIpIGFuZCBjZmdfcmF3LnN0cmlwKCk6CiAgICAgICAgcmV0dXJuIGNmZ19yYXcKICAgIHJldHVybiBkZWZhdWx0CgoKZGVmIF9jb25maWdfaW50KGVudl9uYW1lOiBzdHIsIGNvbmZpZ19rZXk6IHN0ciwgZGVmYXVsdDogaW50LCAqLCBtaW5fdmFsdWU6IGludCA9IDEpIC0+IGludDoKICAgIGVudl9yYXcgPSBvcy5lbnZpcm9uLmdldChlbnZfbmFtZSkKICAgIGlmIGVudl9yYXcgaXMgbm90IE5vbmUgYW5kIGVudl9yYXcuc3RyaXAoKToKICAgICAgICB0cnk6CiAgICAgICAgICAgIHJldHVybiBtYXgobWluX3ZhbHVlLCBpbnQoZW52X3JhdykpCiAgICAgICAgZXhjZXB0IFZhbHVlRXJyb3I6CiAgICAgICAgICAgIHBhc3MKCiAgICBjZmdfcmF3ID0gSU5ERVhFUl9UVU5JTkdfQ09ORklHLmdldChjb25maWdfa2V5KQogICAgaWYgaXNpbnN0YW5jZShjZmdfcmF3LCBpbnQpOgogICAgICAgIHJldHVybiBtYXgobWluX3ZhbHVlLCBjZmdfcmF3KQogICAgaWYgaXNpbnN0YW5jZShjZmdfcmF3LCBzdHIpOgogICAgICAgIHRyeToKICAgICAgICAgICAgcmV0dXJuIG1heChtaW5fdmFsdWUsIGludChjZmdfcmF3KSkKICAgICAgICBleGNlcHQgVmFsdWVFcnJvcjoKICAgICAgICAgICAgcGFzcwoKICAgIHJldHVybiBtYXgobWluX3ZhbHVlLCBkZWZhdWx0KQoKCkNIUk9NQV9IT1NUID0gb3MuZW52aXJvbi5nZXQoIkNIUk9NQV9IT1NUIiwgImxvY2FsaG9zdCIpCkNIUk9NQV9QT1JUID0gaW50KG9zLmVudmlyb24uZ2V0KCJDSFJPTUFfUE9SVCIsICI4MDAwIikpCgojIENvbGXDp8O1ZXMgc2VwYXJhZGFzIHBvciBlc3BlY2lhbGl6YcOnw6NvIGRlIGVtYmVkZGluZwpDT0xMRUNUSU9OX0NPREVfSklOQSA9ICJjb2RlX3ZlY3RvcnNfamluYSIKQ09MTEVDVElPTl9ET0NfQkdFID0gImRvY192ZWN0b3JzX2JnZSIKCkpJTkFfVjNfRU1CRURESU5HX01PREVMID0gImppbmFhaS9qaW5hLWVtYmVkZGluZ3MtdjMiCkpJTkFfVjJfRU1CRURESU5HX01PREVMID0gImppbmFhaS9qaW5hLWVtYmVkZGluZ3MtdjItYmFzZS1jb2RlIgpCR0VfRU1CRURESU5HX01PREVMID0gIkJBQUkvYmdlLW0zIgoKREVGQVVMVF9FTUJFRERJTkdfTU9ERUxfQ0hPSUNFID0gImppbmEiCkRFRkFVTFRfSklOQV9RVUFOVElaQVRJT04gPSAiZHluYW1pYy1pbnQ4IgpERUZBVUxUX1NFQVJDSF9NT0RFID0gInNpbmdsZSIgICMgc2luZ2xlIHwgZW5zZW1ibGUKCl9lbWJlZGRpbmdfbW9kZWxfY2hvaWNlID0gX2NvbmZpZ19zdHIoCiAgICAiTUNQX0VNQkVERElOR19NT0RFTCIsCiAgICAiZW1iZWRkaW5nX21vZGVsIiwKICAgIERFRkFVTFRfRU1CRURESU5HX01PREVMX0NIT0lDRSwKKS5zdHJpcCgpLmxvd2VyKCkKaWYgX2VtYmVkZGluZ19tb2RlbF9jaG9pY2Ugbm90IGluIHsiamluYSIsICJiZ2UiLCAiaHlicmlkIn06CiAgICBsb2cud2FybmluZygKICAgICAgICAiTUNQX0VNQkVERElOR19NT0RFTCBpbnZhbGlkbyAnJXMnLiBVc2FuZG8gJyVzJy4iLAogICAgICAgIF9lbWJlZGRpbmdfbW9kZWxfY2hvaWNlLAogICAgICAgIERFRkFVTFRfRU1CRURESU5HX01PREVMX0NIT0lDRSwKICAgICkKICAgIF9lbWJlZGRpbmdfbW9kZWxfY2hvaWNlID0gREVGQVVMVF9FTUJFRERJTkdfTU9ERUxfQ0hPSUNFCgpfcmF3X2ppbmFfcXVhbnRpemF0aW9uID0gX2NvbmZpZ19zdHIoCiAgICAiTUNQX0pJTkFfUVVBTlRJWkFUSU9OIiwKICAgICJqaW5hX3F1YW50aXphdGlvbiIsCiAgICBERUZBVUxUX0pJTkFfUVVBTlRJWkFUSU9OLAopCkpJTkFfUVVBTlRJWkFUSU9OID0gX3Jhd19qaW5hX3F1YW50aXphdGlvbi5zdHJpcCgpLmxvd2VyKCkucmVwbGFjZSgiXyIsICItIikKaWYgSklOQV9RVUFOVElaQVRJT04gbm90IGluIHsiZGVmYXVsdCIsICJkeW5hbWljLWludDgifToKICAgIGxvZy53YXJuaW5nKAogICAgICAgICJNQ1BfSklOQV9RVUFOVElaQVRJT04gaW52YWxpZG8gJyVzJy4gVXNhbmRvICclcycuIiwKICAgICAgICBKSU5BX1FVQU5USVpBVElPTiwKICAgICAgICBERUZBVUxUX0pJTkFfUVVBTlRJWkFUSU9OLAogICAgKQogICAgSklOQV9RVUFOVElaQVRJT04gPSBERUZBVUxUX0pJTkFfUVVBTlRJWkFUSU9OCgpTRUFSQ0hfTU9ERV9ERUZBVUxUID0gb3MuZW52aXJvbi5nZXQoIk1DUF9TRUFSQ0hfTU9ERSIsIERFRkFVTFRfU0VBUkNIX01PREUpLnN0cmlwKCkubG93ZXIoKQppZiBTRUFSQ0hfTU9ERV9ERUZBVUxUIG5vdCBpbiB7InNpbmdsZSIsICJlbnNlbWJsZSJ9OgogICAgU0VBUkNIX01PREVfREVGQVVMVCA9IERFRkFVTFRfU0VBUkNIX01PREUKCmlmIF9lbWJlZGRpbmdfbW9kZWxfY2hvaWNlID09ICJoeWJyaWQiIGFuZCAiTUNQX1NFQVJDSF9NT0RFIiBub3QgaW4gb3MuZW52aXJvbjoKICAgICMgTm8gbW9kbyBow61icmlkbywgbyBjb21wb3J0YW1lbnRvIGVzcGVyYWRvIGNvc3R1bWEgc2VyIGVuc2VtYmxlIHBvciBwYWRyw6NvLgogICAgU0VBUkNIX01PREVfREVGQVVMVCA9ICJlbnNlbWJsZSIKClJFUkFOS19NT0RFTF9JRCA9IG9zLmVudmlyb24uZ2V0KCJNQ1BfUkVSQU5LX01PREVMIiwgImNyb3NzLWVuY29kZXIvbXMtbWFyY28tTWluaUxNLUwtNi12MiIpClJFUkFOS19FTkFCTEVEID0gb3MuZW52aXJvbi5nZXQoIk1DUF9SRVJBTktfRU5BQkxFRCIsICJ0cnVlIikuc3RyaXAoKS5sb3dlcigpIGluIHsiMSIsICJ0cnVlIiwgInllcyIsICJvbiJ9ClJFUkFOS19DQU5ESURBVEVfTVVMVElQTElFUiA9IGludChvcy5lbnZpcm9uLmdldCgiTUNQX1JFUkFOS19DQU5ESURBVEVfTVVMVElQTElFUiIsICIzIikpClJFUkFOS19NQVhfQ0FORElEQVRFUyA9IGludChvcy5lbnZpcm9uLmdldCgiTUNQX1JFUkFOS19NQVhfQ0FORElEQVRFUyIsICI0MCIpKQpSRVJBTktFUl9NQVhfTEVOR1RIID0gaW50KG9zLmVudmlyb24uZ2V0KCJNQ1BfUkVSQU5LX01BWF9MRU5HVEgiLCAiNTEyIikpClJFUkFOS0VSX1FVQU5USVpBVElPTiA9IG9zLmVudmlyb24uZ2V0KCJNQ1BfUkVSQU5LX1FVQU5USVpBVElPTiIsICJkeW5hbWljLWludDgiKS5zdHJpcCgpLmxvd2VyKCkKaWYgUkVSQU5LRVJfUVVBTlRJWkFUSU9OIG5vdCBpbiB7ImRlZmF1bHQiLCAiZHluYW1pYy1pbnQ4In06CiAgICBSRVJBTktFUl9RVUFOVElaQVRJT04gPSAiZHluYW1pYy1pbnQ4IgoKUlJGX0sgPSBpbnQob3MuZW52aXJvbi5nZXQoIk1DUF9SUkZfSyIsICI2MCIpKQpFTUJFRERJTkdfQkFUQ0hfU0laRSA9IF9jb25maWdfaW50KCJNQ1BfRU1CRURESU5HX0JBVENIX1NJWkUiLCAiZW1iZWRkaW5nX2JhdGNoX3NpemUiLCA0LCBtaW5fdmFsdWU9MSkKCl9lbnZfbW9kZWxfZGlyID0gb3MuZW52aXJvbi5nZXQoIk1DUF9NT0RFTF9ESVIiKQpNT0RFTF9ESVIgPSAoCiAgICBQYXRoKF9lbnZfbW9kZWxfZGlyKS5leHBhbmR1c2VyKCkKICAgIGlmIF9lbnZfbW9kZWxfZGlyCiAgICBlbHNlIFBhdGguaG9tZSgpIC8gIi5jYWNoZSIgLyAibXktY3VzdG9tLXJhZy1weXRob24iIC8gIm1vZGVscyIKKQoKIyBQYXLDom1ldHJvcyBkbyBzcGxpdHRlciAoYWxpbmhhZG9zIGNvbSBpbmRleGVyX2Z1bGwucHksIHBlcmZpbCBsb3ctbWVtb3J5KQpDSFVOS19TSVpFID0gX2NvbmZpZ19pbnQoIk1DUF9DSFVOS19TSVpFIiwgImNodW5rX3NpemUiLCAzMDAwLCBtaW5fdmFsdWU9MjU2KQpDSFVOS19PVkVSTEFQID0gbWluKENIVU5LX1NJWkUgLSAxLCBfY29uZmlnX2ludCgiTUNQX0NIVU5LX09WRVJMQVAiLCAiY2h1bmtfb3ZlcmxhcCIsIDQwMCwgbWluX3ZhbHVlPTApKQoKTUFYX0ZJTEVfU0laRV9CWVRFUyA9IDUwMCAqIDEwMjQgICMgNTAwIEtCClRPUF9LX1JFU1VMVFMgPSA3Ck1BWF9RVUVSWV9SRVNVTFRTID0gMzAKCiMgRmlsdHJvcyBkZSB2YXJyZWR1cmEKSUdOT1JFRF9ESVJTID0gewogICAgIi5naXQiLCAibm9kZV9tb2R1bGVzIiwgIl9fcHljYWNoZV9fIiwgIi52ZW52IiwgInZlbnYiLCAiZW52IiwKICAgICJkaXN0IiwgImJ1aWxkIiwgIm91dCIsICIubmV4dCIsICIubnV4dCIsICIuY2FjaGUiLCAiY292ZXJhZ2UiLAogICAgIi5weXRlc3RfY2FjaGUiLCAiLm15cHlfY2FjaGUiLCAiLnJ1ZmZfY2FjaGUiLCAidGFyZ2V0IiwgImJpbiIsICJvYmoiLAogICAgIi5pZGVhIiwgIi52c2NvZGUiLCAidmVuZG9yIiwgInRtcCIsICJ0ZW1wIiwgImxvZ3MiLCAiLnJhZ19kYiIsCn0KCklHTk9SRURfRVhURU5TSU9OUyA9IHsKICAgICIucG5nIiwgIi5qcGciLCAiLmpwZWciLCAiLmdpZiIsICIuc3ZnIiwgIi5pY28iLCAiLndlYnAiLCAiLmJtcCIsCiAgICAiLm1wNCIsICIubXAzIiwgIi53YXYiLCAiLm9nZyIsICIuYXZpIiwgIi5tb3YiLAogICAgIi56aXAiLCAiLnRhciIsICIuZ3oiLCAiLnJhciIsICIuN3oiLCAiLmphciIsICIud2FyIiwKICAgICIucHljIiwgIi5weW8iLCAiLnNvIiwgIi5kbGwiLCAiLmV4ZSIsICIuYmluIiwKICAgICIubG9jayIsICIuc3VtIiwgIi5zcWxpdGUiLCAiLmRiIiwgIi5zcWxpdGUzIiwKICAgICIudHRmIiwgIi53b2ZmIiwgIi53b2ZmMiIsICIuZW90IiwKICAgICIucGRmIiwgIi5kb2N4IiwgIi54bHN4IiwgIi5wcHR4IiwKfQoKQ09ERV9FWFRFTlNJT05TID0gewogICAgIi5weSIsICIuanMiLCAiLnRzIiwgIi50c3giLCAiLmpzeCIsICIuamF2YSIsICIuYyIsICIuaCIsICIuY3BwIiwgIi5ocHAiLAogICAgIi5nbyIsICIucnMiLCAiLnJiIiwgIi5waHAiLCAiLmNzIiwgIi5zd2lmdCIsICIua3QiLCAiLmt0cyIsICIuc2NhbGEiLCAiLnNxbCIsCiAgICAiLnNoIiwgIi5iYXNoIiwgIi56c2giLCAiLnBzMSIsICIueWFtbCIsICIueW1sIiwgIi50b21sIiwgIi5pbmkiLCAiLmNvbmYiLAogICAgIi5qc29uIiwgIi54bWwiLCAiLmh0bWwiLCAiLmNzcyIsICIuc2NzcyIsICIuc2FzcyIsICIudnVlIiwgIi5zdmVsdGUiLCAiLmRhcnQiLAogICAgIi5sdWEiLCAiLnIiLCAiLm0iLCAiLm1tIiwKfQoKRE9DX0VYVEVOU0lPTlMgPSB7CiAgICAiLm1kIiwgIi5tZHgiLCAiLnJzdCIsICIudHh0IiwgIi5hZG9jIiwgIi5vcmciLCAiLnRleCIsICIuY3N2IiwKfQoKCkBkYXRhY2xhc3MoZnJvemVuPVRydWUpCmNsYXNzIEJyYW5jaFNwZWM6CiAgICBrZXk6IHN0cgogICAgbW9kZWxfY2hvaWNlOiBzdHIKICAgIG1vZGVsX2lkOiBzdHIKICAgIGNvbGxlY3Rpb25fbmFtZTogc3RyCiAgICBjb250ZW50X2RvbWFpbjogc3RyCiAgICBsYWJlbDogc3RyCgoKSklOQV9DT0RFX0JSQU5DSF9NT0RFTF9DSE9JQ0UgPSAiamluYV92MiIgaWYgX2VtYmVkZGluZ19tb2RlbF9jaG9pY2UgPT0gImh5YnJpZCIgZWxzZSAiamluYSIKSklOQV9DT0RFX0JSQU5DSF9NT0RFTF9JRCA9IEpJTkFfVjJfRU1CRURESU5HX01PREVMIGlmIF9lbWJlZGRpbmdfbW9kZWxfY2hvaWNlID09ICJoeWJyaWQiIGVsc2UgSklOQV9WM19FTUJFRERJTkdfTU9ERUwKCkJSQU5DSF9TUEVDUzogZGljdFtzdHIsIEJyYW5jaFNwZWNdID0gewogICAgImppbmFfY29kZSI6IEJyYW5jaFNwZWMoCiAgICAgICAga2V5PSJqaW5hX2NvZGUiLAogICAgICAgIG1vZGVsX2Nob2ljZT1KSU5BX0NPREVfQlJBTkNIX01PREVMX0NIT0lDRSwKICAgICAgICBtb2RlbF9pZD1KSU5BX0NPREVfQlJBTkNIX01PREVMX0lELAogICAgICAgIGNvbGxlY3Rpb25fbmFtZT1DT0xMRUNUSU9OX0NPREVfSklOQSwKICAgICAgICBjb250ZW50X2RvbWFpbj0iY29kZSIsCiAgICAgICAgbGFiZWw9IkppbmEgdjIgQ29kZSIgaWYgX2VtYmVkZGluZ19tb2RlbF9jaG9pY2UgPT0gImh5YnJpZCIgZWxzZSAiSmluYSB2MyBDb2RlIiwKICAgICksCiAgICAiYmdlX2RvYyI6IEJyYW5jaFNwZWMoCiAgICAgICAga2V5PSJiZ2VfZG9jIiwKICAgICAgICBtb2RlbF9jaG9pY2U9ImJnZSIsCiAgICAgICAgbW9kZWxfaWQ9QkdFX0VNQkVERElOR19NT0RFTCwKICAgICAgICBjb2xsZWN0aW9uX25hbWU9Q09MTEVDVElPTl9ET0NfQkdFLAogICAgICAgIGNvbnRlbnRfZG9tYWluPSJkb2MiLAogICAgICAgIGxhYmVsPSJCR0UgRG9jcyIsCiAgICApLAp9CgpERUZBVUxUX1NJTkdMRV9CUkFOQ0hfS0VZID0gImJnZV9kb2MiIGlmIF9lbWJlZGRpbmdfbW9kZWxfY2hvaWNlID09ICJiZ2UiIGVsc2UgImppbmFfY29kZSIKCgpAZGF0YWNsYXNzCmNsYXNzIFJldHJpZXZlZEhpdDoKICAgIGtleTogc3RyCiAgICBkb2N1bWVudDogc3RyCiAgICBtZXRhZGF0YTogZGljdFtzdHIsIG9iamVjdF0KICAgIGRpc3RhbmNlOiBmbG9hdCB8IE5vbmUKICAgIHNpbWlsYXJpdHk6IGZsb2F0IHwgTm9uZQogICAgYnJhbmNoOiBCcmFuY2hTcGVjCiAgICByYW5rOiBpbnQKCgpAZGF0YWNsYXNzCmNsYXNzIEZ1c2VkSGl0OgogICAga2V5OiBzdHIKICAgIGRvY3VtZW50OiBzdHIKICAgIG1ldGFkYXRhOiBkaWN0W3N0ciwgb2JqZWN0XQogICAgcnJmX3Njb3JlOiBmbG9hdAogICAgc291cmNlX2RldGFpbHM6IGRpY3Rbc3RyLCBkaWN0W3N0ciwgb2JqZWN0XV0KICAgIHJlcmFua19zY29yZTogZmxvYXQgfCBOb25lID0gTm9uZQoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgUnVudGltZSBjYWNoZXMgKGxhenkgbG9hZGluZyBwYXJhIGVjb25vbWl6YXIgUkFNKQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKX2Nocm9tYV9jbGllbnQ6IGNocm9tYWRiLkh0dHBDbGllbnQgfCBOb25lID0gTm9uZQpfY29sbGVjdGlvbnM6IGRpY3Rbc3RyLCBjaHJvbWFkYi5Db2xsZWN0aW9uXSA9IHt9Cl9tb2RlbHM6IGRpY3Rbc3RyLCBTZW50ZW5jZVRyYW5zZm9ybWVyXSA9IHt9Cl9tb2RlbF9sb2FkX2Vycm9yczogZGljdFtzdHIsIHN0cl0gPSB7fQpfc3BsaXR0ZXI6IFJlY3Vyc2l2ZUNoYXJhY3RlclRleHRTcGxpdHRlciB8IE5vbmUgPSBOb25lCl9yZXJhbmtlcjogQ3Jvc3NFbmNvZGVyIHwgTm9uZSA9IE5vbmUKX3JlcmFua2VyX2Vycm9yOiBzdHIgfCBOb25lID0gTm9uZQoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgQ2hyb21hIGUgbW9kZWxvcwojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCmRlZiBfbW9kZWxfY2FjaGVfZGlyKGJhc2VfZGlyOiBQYXRoLCBtb2RlbF9pZDogc3RyKSAtPiBQYXRoOgogICAgc2FmZV9uYW1lID0gbW9kZWxfaWQucmVwbGFjZSgiLyIsICJfXyIpLnJlcGxhY2UoIjoiLCAiXyIpCiAgICByZXR1cm4gYmFzZV9kaXIgLyBzYWZlX25hbWUKCgpkZWYgX2dldF9jaHJvbWFfY2xpZW50KCkgLT4gY2hyb21hZGIuSHR0cENsaWVudDoKICAgIGdsb2JhbCBfY2hyb21hX2NsaWVudAogICAgaWYgX2Nocm9tYV9jbGllbnQgaXMgTm9uZToKICAgICAgICBfY2hyb21hX2NsaWVudCA9IGNocm9tYWRiLkh0dHBDbGllbnQoaG9zdD1DSFJPTUFfSE9TVCwgcG9ydD1DSFJPTUFfUE9SVCkKICAgICAgICBfY2hyb21hX2NsaWVudC5oZWFydGJlYXQoKQogICAgICAgIGxvZy5pbmZvKCJDb25lY3RhZG8gYW8gQ2hyb21hREIgZW0gJXM6JXMiLCBDSFJPTUFfSE9TVCwgQ0hST01BX1BPUlQpCiAgICByZXR1cm4gX2Nocm9tYV9jbGllbnQKCgpkZWYgZ2V0X2Nocm9tYV9jb2xsZWN0aW9uKGNvbGxlY3Rpb25fbmFtZTogc3RyKSAtPiBjaHJvbWFkYi5Db2xsZWN0aW9uOgogICAgaWYgY29sbGVjdGlvbl9uYW1lIGluIF9jb2xsZWN0aW9uczoKICAgICAgICByZXR1cm4gX2NvbGxlY3Rpb25zW2NvbGxlY3Rpb25fbmFtZV0KCiAgICB0cnk6CiAgICAgICAgY2xpZW50ID0gX2dldF9jaHJvbWFfY2xpZW50KCkKICAgICAgICBjb2xsZWN0aW9uID0gY2xpZW50LmdldF9vcl9jcmVhdGVfY29sbGVjdGlvbigKICAgICAgICAgICAgbmFtZT1jb2xsZWN0aW9uX25hbWUsCiAgICAgICAgICAgIG1ldGFkYXRhPXsiaG5zdzpzcGFjZSI6ICJjb3NpbmUifSwKICAgICAgICApCiAgICAgICAgX2NvbGxlY3Rpb25zW2NvbGxlY3Rpb25fbmFtZV0gPSBjb2xsZWN0aW9uCiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb24KICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICByYWlzZSBSdW50aW1lRXJyb3IoCiAgICAgICAgICAgIGYiTsOjbyBmb2kgcG9zc8OtdmVsIGFjZXNzYXIgYSBjb2xlw6fDo28gJ3tjb2xsZWN0aW9uX25hbWV9JyBubyBDaHJvbWFEQiAiCiAgICAgICAgICAgIGYiKHtDSFJPTUFfSE9TVH06e0NIUk9NQV9QT1JUfSkuIEVycm86IHtlfSIKICAgICAgICApCgoKZGVmIF9sb2FkX3NlbnRlbmNlX3RyYW5zZm9ybWVyX2Zyb21fbG9jYWwobW9kZWxfaWQ6IHN0ciwgbG9jYWxfbW9kZWxfZGlyOiBQYXRoKSAtPiBTZW50ZW5jZVRyYW5zZm9ybWVyOgogICAgdHJ1c3RfcmVtb3RlX2NvZGUgPSBtb2RlbF9pZC5zdGFydHN3aXRoKCJqaW5hYWkvIikKICAgIHRva2VuaXplcl9rd2FyZ3MgPSB7ImZpeF9taXN0cmFsX3JlZ2V4IjogVHJ1ZX0KCiAgICBkZWYgX2luc3RhbnRpYXRlX21vZGVsKCkgLT4gU2VudGVuY2VUcmFuc2Zvcm1lcjoKICAgICAgICByZXR1cm4gU2VudGVuY2VUcmFuc2Zvcm1lcigKICAgICAgICAgICAgc3RyKGxvY2FsX21vZGVsX2RpciksCiAgICAgICAgICAgIGRldmljZT0iY3B1IiwKICAgICAgICAgICAgdHJ1c3RfcmVtb3RlX2NvZGU9dHJ1c3RfcmVtb3RlX2NvZGUsCiAgICAgICAgICAgIHRva2VuaXplcl9rd2FyZ3M9dG9rZW5pemVyX2t3YXJncywKICAgICAgICApCgogICAgZGVmIF9jbGVhcl9oZl9keW5hbWljX21vZHVsZXNfY2FjaGUoKSAtPiBOb25lOgogICAgICAgIGNhY2hlX2RpciA9IFBhdGguaG9tZSgpIC8gIi5jYWNoZSIgLyAiaHVnZ2luZ2ZhY2UiIC8gIm1vZHVsZXMiIC8gInRyYW5zZm9ybWVyc19tb2R1bGVzIgogICAgICAgIGlmIGNhY2hlX2Rpci5leGlzdHMoKToKICAgICAgICAgICAgbG9nLndhcm5pbmcoIkxpbXBhbmRvIGNhY2hlIGRpbsOibWljbyBkbyBIdWdnaW5nIEZhY2UgZW0gJXMiLCBjYWNoZV9kaXIpCiAgICAgICAgICAgIHNodXRpbC5ybXRyZWUoY2FjaGVfZGlyLCBpZ25vcmVfZXJyb3JzPVRydWUpCgogICAgZGVmIF9sb2FkX3dpdGhfamluYV9wYXRjaCgpIC0+IFNlbnRlbmNlVHJhbnNmb3JtZXI6CiAgICAgICAgaWYgbm90IHRydXN0X3JlbW90ZV9jb2RlOgogICAgICAgICAgICByZXR1cm4gX2luc3RhbnRpYXRlX21vZGVsKCkKCiAgICAgICAgZnJvbSB0cmFuc2Zvcm1lcnMgaW1wb3J0IEF1dG9Nb2RlbCwgQXV0b1Rva2VuaXplcgogICAgICAgIGZyb20gdHJhbnNmb3JtZXJzLm1vZGVsaW5nX3V0aWxzIGltcG9ydCBQcmVUcmFpbmVkTW9kZWwKCiAgICAgICAgb3JpZ2luYWxfZnJvbV9wcmV0cmFpbmVkID0gQXV0b1Rva2VuaXplci5mcm9tX3ByZXRyYWluZWQKICAgICAgICBvcmlnaW5hbF9tb2RlbF9mcm9tX3ByZXRyYWluZWQgPSBBdXRvTW9kZWwuZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX3ByZXRyYWluZWQgPSBQcmVUcmFpbmVkTW9kZWwuZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX2NvbmZpZyA9IFByZVRyYWluZWRNb2RlbC5fZnJvbV9jb25maWcKICAgICAgICBtb2RlbF9yZWZzID0ge3N0cihsb2NhbF9tb2RlbF9kaXIpLCBzdHIobG9jYWxfbW9kZWxfZGlyLnJlc29sdmUoKSl9CgogICAgICAgIGRlZiBfcGF0Y2hlZF9mcm9tX3ByZXRyYWluZWQoKmFyZ3MsICoqa3dhcmdzKToKICAgICAgICAgICAgbW9kZWxfcmVmID0gYXJnc1swXSBpZiBhcmdzIGVsc2Uga3dhcmdzLmdldCgicHJldHJhaW5lZF9tb2RlbF9uYW1lX29yX3BhdGgiKQogICAgICAgICAgICBpZiBtb2RlbF9yZWYgaXMgbm90IE5vbmUgYW5kIHN0cihtb2RlbF9yZWYpIGluIG1vZGVsX3JlZnM6CiAgICAgICAgICAgICAgICBrd2FyZ3Muc2V0ZGVmYXVsdCgiZml4X21pc3RyYWxfcmVnZXgiLCBUcnVlKQogICAgICAgICAgICByZXR1cm4gb3JpZ2luYWxfZnJvbV9wcmV0cmFpbmVkKCphcmdzLCAqKmt3YXJncykKCiAgICAgICAgZGVmIF9wYXRjaGVkX21vZGVsX2Zyb21fcHJldHJhaW5lZCgqYXJncywgKiprd2FyZ3MpOgogICAgICAgICAgICBtb2RlbF9yZWYgPSBhcmdzWzBdIGlmIGFyZ3MgZWxzZSBrd2FyZ3MuZ2V0KCJwcmV0cmFpbmVkX21vZGVsX25hbWVfb3JfcGF0aCIpCiAgICAgICAgICAgIGlmIG1vZGVsX3JlZiBpcyBub3QgTm9uZSBhbmQgc3RyKG1vZGVsX3JlZikgaW4gbW9kZWxfcmVmcyBhbmQgInRvcmNoX2R0eXBlIiBpbiBrd2FyZ3M6CiAgICAgICAgICAgICAgICBrd2FyZ3MgPSBkaWN0KGt3YXJncykKICAgICAgICAgICAgICAgIGlmICJkdHlwZSIgbm90IGluIGt3YXJnczoKICAgICAgICAgICAgICAgICAgICBrd2FyZ3NbImR0eXBlIl0gPSBrd2FyZ3NbInRvcmNoX2R0eXBlIl0KICAgICAgICAgICAgICAgIGt3YXJncy5wb3AoInRvcmNoX2R0eXBlIiwgTm9uZSkKICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsX21vZGVsX2Zyb21fcHJldHJhaW5lZCgqYXJncywgKiprd2FyZ3MpCgogICAgICAgIG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9wcmV0cmFpbmVkX2ZuID0gb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX3ByZXRyYWluZWQuX19mdW5jX18KCiAgICAgICAgQGNsYXNzbWV0aG9kCiAgICAgICAgZGVmIF9wYXRjaGVkX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9wcmV0cmFpbmVkKGNscywgKmFyZ3MsICoqa3dhcmdzKToKICAgICAgICAgICAgaWYgInRvcmNoX2R0eXBlIiBpbiBrd2FyZ3M6CiAgICAgICAgICAgICAgICBrd2FyZ3MgPSBkaWN0KGt3YXJncykKICAgICAgICAgICAgICAgIGlmICJkdHlwZSIgbm90IGluIGt3YXJnczoKICAgICAgICAgICAgICAgICAgICBrd2FyZ3NbImR0eXBlIl0gPSBrd2FyZ3NbInRvcmNoX2R0eXBlIl0KICAgICAgICAgICAgICAgIGt3YXJncy5wb3AoInRvcmNoX2R0eXBlIiwgTm9uZSkKICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9wcmV0cmFpbmVkX2ZuKGNscywgKmFyZ3MsICoqa3dhcmdzKQoKICAgICAgICBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fY29uZmlnX2ZuID0gb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX2NvbmZpZy5fX2Z1bmNfXwoKICAgICAgICBAY2xhc3NtZXRob2QKICAgICAgICBkZWYgX3BhdGNoZWRfcHJldHJhaW5lZF9tb2RlbF9mcm9tX2NvbmZpZyhjbHMsICphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgICAgIGlmICJ0b3JjaF9kdHlwZSIgaW4ga3dhcmdzOgogICAgICAgICAgICAgICAga3dhcmdzID0gZGljdChrd2FyZ3MpCiAgICAgICAgICAgICAgICBpZiAiZHR5cGUiIG5vdCBpbiBrd2FyZ3M6CiAgICAgICAgICAgICAgICAgICAga3dhcmdzWyJkdHlwZSJdID0ga3dhcmdzWyJ0b3JjaF9kdHlwZSJdCiAgICAgICAgICAgICAgICBrd2FyZ3MucG9wKCJ0b3JjaF9kdHlwZSIsIE5vbmUpCiAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fY29uZmlnX2ZuKGNscywgKmFyZ3MsICoqa3dhcmdzKQoKICAgICAgICBBdXRvVG9rZW5pemVyLmZyb21fcHJldHJhaW5lZCA9IF9wYXRjaGVkX2Zyb21fcHJldHJhaW5lZAogICAgICAgIEF1dG9Nb2RlbC5mcm9tX3ByZXRyYWluZWQgPSBfcGF0Y2hlZF9tb2RlbF9mcm9tX3ByZXRyYWluZWQKICAgICAgICBQcmVUcmFpbmVkTW9kZWwuZnJvbV9wcmV0cmFpbmVkID0gX3BhdGNoZWRfcHJldHJhaW5lZF9tb2RlbF9mcm9tX3ByZXRyYWluZWQKICAgICAgICBQcmVUcmFpbmVkTW9kZWwuX2Zyb21fY29uZmlnID0gX3BhdGNoZWRfcHJldHJhaW5lZF9tb2RlbF9mcm9tX2NvbmZpZwogICAgICAgIHRyeToKICAgICAgICAgICAgcmV0dXJuIF9pbnN0YW50aWF0ZV9tb2RlbCgpCiAgICAgICAgZmluYWxseToKICAgICAgICAgICAgQXV0b1Rva2VuaXplci5mcm9tX3ByZXRyYWluZWQgPSBvcmlnaW5hbF9mcm9tX3ByZXRyYWluZWQKICAgICAgICAgICAgQXV0b01vZGVsLmZyb21fcHJldHJhaW5lZCA9IG9yaWdpbmFsX21vZGVsX2Zyb21fcHJldHJhaW5lZAogICAgICAgICAgICBQcmVUcmFpbmVkTW9kZWwuZnJvbV9wcmV0cmFpbmVkID0gb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX3ByZXRyYWluZWQKICAgICAgICAgICAgUHJlVHJhaW5lZE1vZGVsLl9mcm9tX2NvbmZpZyA9IG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9jb25maWcKCiAgICB0cnk6CiAgICAgICAgcmV0dXJuIF9sb2FkX3dpdGhfamluYV9wYXRjaCgpCiAgICBleGNlcHQgRmlsZU5vdEZvdW5kRXJyb3IgYXMgZToKICAgICAgICBpZiB0cnVzdF9yZW1vdGVfY29kZSBhbmQgInRyYW5zZm9ybWVyc19tb2R1bGVzIiBpbiBzdHIoZSk6CiAgICAgICAgICAgIGxvZy53YXJuaW5nKCJDYWNoZSBkaW7Dom1pY28gaW5jb25zaXN0ZW50ZSBkZXRlY3RhZG86ICVzIiwgZSkKICAgICAgICAgICAgX2NsZWFyX2hmX2R5bmFtaWNfbW9kdWxlc19jYWNoZSgpCiAgICAgICAgICAgIHJldHVybiBfbG9hZF93aXRoX2ppbmFfcGF0Y2goKQogICAgICAgIHJhaXNlCgoKZGVmIF9hcHBseV9qaW5hX3F1YW50aXphdGlvbl9pZl9uZWVkZWQobW9kZWw6IFNlbnRlbmNlVHJhbnNmb3JtZXIsIG1vZGVsX2lkOiBzdHIpIC0+IFNlbnRlbmNlVHJhbnNmb3JtZXI6CiAgICBpZiBtb2RlbF9pZCAhPSBKSU5BX1YzX0VNQkVERElOR19NT0RFTCBvciBKSU5BX1FVQU5USVpBVElPTiA9PSAiZGVmYXVsdCI6CiAgICAgICAgcmV0dXJuIG1vZGVsCgogICAgdHJ5OgogICAgICAgIGltcG9ydCB0b3JjaAogICAgICAgIGltcG9ydCB3YXJuaW5ncwoKICAgICAgICBxdWFudGl6ZWRfbGF5ZXJzID0gMAogICAgICAgIGZvciBtb2R1bGUgaW4gbW9kZWwubW9kdWxlcygpOgogICAgICAgICAgICBpZiB0eXBlKG1vZHVsZSkuX19uYW1lX18gIT0gIlBhcmFtZXRyaXplZExpbmVhciI6CiAgICAgICAgICAgICAgICBjb250aW51ZQoKICAgICAgICAgICAgZmxvYXRfbGluZWFyID0gdG9yY2gubm4uTGluZWFyKAogICAgICAgICAgICAgICAgbW9kdWxlLmluX2ZlYXR1cmVzLAogICAgICAgICAgICAgICAgbW9kdWxlLm91dF9mZWF0dXJlcywKICAgICAgICAgICAgICAgIGJpYXM9bW9kdWxlLmJpYXMgaXMgbm90IE5vbmUsCiAgICAgICAgICAgICkKICAgICAgICAgICAgd2l0aCB0b3JjaC5ub19ncmFkKCk6CiAgICAgICAgICAgICAgICBmbG9hdF9saW5lYXIud2VpZ2h0LmNvcHlfKG1vZHVsZS53ZWlnaHQuZGV0YWNoKCkudG8odG9yY2guZmxvYXQzMikpCiAgICAgICAgICAgICAgICBpZiBtb2R1bGUuYmlhcyBpcyBub3QgTm9uZToKICAgICAgICAgICAgICAgICAgICBmbG9hdF9saW5lYXIuYmlhcy5jb3B5Xyhtb2R1bGUuYmlhcy5kZXRhY2goKS50byh0b3JjaC5mbG9hdDMyKSkKCiAgICAgICAgICAgIHdpdGggd2FybmluZ3MuY2F0Y2hfd2FybmluZ3MoKToKICAgICAgICAgICAgICAgIHdhcm5pbmdzLmZpbHRlcndhcm5pbmdzKCJpZ25vcmUiLCBjYXRlZ29yeT1EZXByZWNhdGlvbldhcm5pbmcpCiAgICAgICAgICAgICAgICBxdWFudGl6ZWRfbGluZWFyID0gdG9yY2gucXVhbnRpemF0aW9uLnF1YW50aXplX2R5bmFtaWMoCiAgICAgICAgICAgICAgICAgICAgdG9yY2gubm4uU2VxdWVudGlhbChmbG9hdF9saW5lYXIpLAogICAgICAgICAgICAgICAgICAgIHt0b3JjaC5ubi5MaW5lYXJ9LAogICAgICAgICAgICAgICAgICAgIGR0eXBlPXRvcmNoLnFpbnQ4LAogICAgICAgICAgICAgICAgKVswXQoKICAgICAgICAgICAgbW9kdWxlLl9keW5hbWljX2ludDhfbGluZWFyID0gcXVhbnRpemVkX2xpbmVhcgoKICAgICAgICAgICAgZGVmIF9mb3J3YXJkX2R5bmFtaWNfaW50OChzZWxmLCBpbnB1dCwgdGFza19pZD1Ob25lLCByZXNpZHVhbD1GYWxzZSk6CiAgICAgICAgICAgICAgICBvdXQgPSBzZWxmLl9keW5hbWljX2ludDhfbGluZWFyKGlucHV0KQogICAgICAgICAgICAgICAgaWYgcmVzaWR1YWw6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dCwgaW5wdXQKICAgICAgICAgICAgICAgIHJldHVybiBvdXQKCiAgICAgICAgICAgIG1vZHVsZS5mb3J3YXJkID0gX2ZvcndhcmRfZHluYW1pY19pbnQ4Ll9fZ2V0X18obW9kdWxlLCBtb2R1bGUuX19jbGFzc19fKQogICAgICAgICAgICBxdWFudGl6ZWRfbGF5ZXJzICs9IDEKCiAgICAgICAgaWYgcXVhbnRpemVkX2xheWVycyA9PSAwOgogICAgICAgICAgICBsb2cud2FybmluZygiTmVuaHVtYSBjYW1hZGEgUGFyYW1ldHJpemVkTGluZWFyIGVuY29udHJhZGEgcGFyYSBkeW5hbWljLWludDggbm8gSmluYS4iKQogICAgICAgICAgICByZXR1cm4gbW9kZWwKCiAgICAgICAgbG9nLmluZm8oIlF1YW50aXphY2FvIEppbmEgYXBsaWNhZGE6IGR5bmFtaWMtaW50OCAoQ1BVLCAlcyBjYW1hZGFzKS4iLCBxdWFudGl6ZWRfbGF5ZXJzKQogICAgICAgIHJldHVybiBtb2RlbAogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBxdWFudF9lcnJvcjoKICAgICAgICBsb2cud2FybmluZygiRmFsaGEgYW8gYXBsaWNhciBkeW5hbWljLWludDggbm8gSmluYSAoJXMpOyB1c2FuZG8gbW9kZWxvIHBhZHJhby4iLCBxdWFudF9lcnJvcikKICAgICAgICByZXR1cm4gbW9kZWwKCgpkZWYgZ2V0X2VtYmVkZGluZ19tb2RlbChtb2RlbF9jaG9pY2U6IHN0cikgLT4gU2VudGVuY2VUcmFuc2Zvcm1lcjoKICAgIGlmIG1vZGVsX2Nob2ljZSBpbiBfbW9kZWxzOgogICAgICAgIHJldHVybiBfbW9kZWxzW21vZGVsX2Nob2ljZV0KCiAgICBpZiBtb2RlbF9jaG9pY2UgaW4gX21vZGVsX2xvYWRfZXJyb3JzOgogICAgICAgIHJhaXNlIFJ1bnRpbWVFcnJvcihfbW9kZWxfbG9hZF9lcnJvcnNbbW9kZWxfY2hvaWNlXSkKCiAgICBpZiBtb2RlbF9jaG9pY2UgPT0gImppbmEiOgogICAgICAgIG1vZGVsX2lkID0gSklOQV9WM19FTUJFRERJTkdfTU9ERUwKICAgIGVsaWYgbW9kZWxfY2hvaWNlID09ICJqaW5hX3YyIjoKICAgICAgICBtb2RlbF9pZCA9IEpJTkFfVjJfRU1CRURESU5HX01PREVMCiAgICBlbGlmIG1vZGVsX2Nob2ljZSA9PSAiYmdlIjoKICAgICAgICBtb2RlbF9pZCA9IEJHRV9FTUJFRERJTkdfTU9ERUwKICAgIGVsc2U6CiAgICAgICAgcmFpc2UgUnVudGltZUVycm9yKGYiTW9kZWxvIG7Do28gc3Vwb3J0YWRvOiB7bW9kZWxfY2hvaWNlfSIpCgogICAgdHJ5OgogICAgICAgIE1PREVMX0RJUi5ta2RpcihwYXJlbnRzPVRydWUsIGV4aXN0X29rPVRydWUpCiAgICAgICAgcHJlZmVycmVkX21vZGVsX2NhY2hlX2RpciA9IF9tb2RlbF9jYWNoZV9kaXIoTU9ERUxfRElSLCBtb2RlbF9pZCkKICAgICAgICBsb2cuaW5mbygiQ2FycmVnYW5kbyBlbWJlZGRpbmdzICclcycgZW0gQ1BVIChjYWNoZTogJXMpIiwgbW9kZWxfaWQsIHByZWZlcnJlZF9tb2RlbF9jYWNoZV9kaXIpCgogICAgICAgIHNlbGVjdGlvbiA9IGRvd25sb2FkX21vZGVsX3dpdGhfZmFsbGJhY2soCiAgICAgICAgICAgIHByZWZlcnJlZF9tb2RlbF9pZD1tb2RlbF9pZCwKICAgICAgICAgICAgZmFsbGJhY2tfbW9kZWxfaWQ9bW9kZWxfaWQsCiAgICAgICAgICAgIGxvY2FsX2Rpcj1NT0RFTF9ESVIsCiAgICAgICAgKQogICAgICAgIG1vZGVsID0gX2xvYWRfc2VudGVuY2VfdHJhbnNmb3JtZXJfZnJvbV9sb2NhbChzZWxlY3Rpb24ubW9kZWxfaWQsIHNlbGVjdGlvbi5sb2NhbF9kaXIpCiAgICAgICAgaWYgbW9kZWxfY2hvaWNlID09ICJqaW5hIjoKICAgICAgICAgICAgbW9kZWwgPSBfYXBwbHlfamluYV9xdWFudGl6YXRpb25faWZfbmVlZGVkKG1vZGVsLCBzZWxlY3Rpb24ubW9kZWxfaWQpCgogICAgICAgIF9tb2RlbHNbbW9kZWxfY2hvaWNlXSA9IG1vZGVsCiAgICAgICAgbG9nLmluZm8oCiAgICAgICAgICAgICJNb2RlbG8gZGUgZW1iZWRkaW5ncyBwcm9udG86ICVzIChwcm92aWRlcj0lcywgcGF0aD0lcykiLAogICAgICAgICAgICBzZWxlY3Rpb24ubW9kZWxfaWQsCiAgICAgICAgICAgIHNlbGVjdGlvbi5wcm92aWRlciwKICAgICAgICAgICAgc2VsZWN0aW9uLmxvY2FsX2RpciwKICAgICAgICApCiAgICAgICAgcmV0dXJuIG1vZGVsCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgbWVzc2FnZSA9IGYiRmFsaGEgYW8gY2FycmVnYXIgbW9kZWxvICd7bW9kZWxfY2hvaWNlfScgKHttb2RlbF9pZH0pOiB7ZX0iCiAgICAgICAgX21vZGVsX2xvYWRfZXJyb3JzW21vZGVsX2Nob2ljZV0gPSBtZXNzYWdlCiAgICAgICAgcmFpc2UgUnVudGltZUVycm9yKG1lc3NhZ2UpCgoKZGVmIGdldF9yZXJhbmtlcigpIC0+IENyb3NzRW5jb2RlciB8IE5vbmU6CiAgICBnbG9iYWwgX3JlcmFua2VyLCBfcmVyYW5rZXJfZXJyb3IKCiAgICBpZiBub3QgUkVSQU5LX0VOQUJMRUQ6CiAgICAgICAgcmV0dXJuIE5vbmUKICAgIGlmIF9yZXJhbmtlciBpcyBub3QgTm9uZToKICAgICAgICByZXR1cm4gX3JlcmFua2VyCiAgICBpZiBfcmVyYW5rZXJfZXJyb3IgaXMgbm90IE5vbmU6CiAgICAgICAgcmV0dXJuIE5vbmUKCiAgICB0cnk6CiAgICAgICAgTU9ERUxfRElSLm1rZGlyKHBhcmVudHM9VHJ1ZSwgZXhpc3Rfb2s9VHJ1ZSkKICAgICAgICBzZWxlY3Rpb24gPSBkb3dubG9hZF9tb2RlbF93aXRoX2ZhbGxiYWNrKAogICAgICAgICAgICBwcmVmZXJyZWRfbW9kZWxfaWQ9UkVSQU5LX01PREVMX0lELAogICAgICAgICAgICBmYWxsYmFja19tb2RlbF9pZD1SRVJBTktfTU9ERUxfSUQsCiAgICAgICAgICAgIGxvY2FsX2Rpcj1NT0RFTF9ESVIsCiAgICAgICAgKQoKICAgICAgICByZXJhbmtlciA9IENyb3NzRW5jb2RlcigKICAgICAgICAgICAgc3RyKHNlbGVjdGlvbi5sb2NhbF9kaXIpLAogICAgICAgICAgICBkZXZpY2U9ImNwdSIsCiAgICAgICAgICAgIG1heF9sZW5ndGg9UkVSQU5LRVJfTUFYX0xFTkdUSCwKICAgICAgICAgICAgdHJ1c3RfcmVtb3RlX2NvZGU9RmFsc2UsCiAgICAgICAgKQoKICAgICAgICBpZiBSRVJBTktFUl9RVUFOVElaQVRJT04gPT0gImR5bmFtaWMtaW50OCI6CiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIGltcG9ydCB0b3JjaAoKICAgICAgICAgICAgICAgIHJlcmFua2VyLm1vZGVsID0gdG9yY2gucXVhbnRpemF0aW9uLnF1YW50aXplX2R5bmFtaWMoCiAgICAgICAgICAgICAgICAgICAgcmVyYW5rZXIubW9kZWwsCiAgICAgICAgICAgICAgICAgICAge3RvcmNoLm5uLkxpbmVhcn0sCiAgICAgICAgICAgICAgICAgICAgZHR5cGU9dG9yY2gucWludDgsCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICBsb2cuaW5mbygiUmVyYW5rZXIgY29tIHF1YW50aXphY2FvIGR5bmFtaWMtaW50OCBoYWJpbGl0YWRhLiIpCiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgcXVhbnRfZXJyb3I6CiAgICAgICAgICAgICAgICBsb2cud2FybmluZygiRmFsaGEgYW8gcXVhbnRpemFyIHJlcmFua2VyICglcykuIFNlZ3VpbmRvIHNlbSBxdWFudGl6YWNhby4iLCBxdWFudF9lcnJvcikKCiAgICAgICAgX3JlcmFua2VyID0gcmVyYW5rZXIKICAgICAgICBsb2cuaW5mbygKICAgICAgICAgICAgIlJlcmFua2VyIHByb250bzogJXMgKHByb3ZpZGVyPSVzLCBwYXRoPSVzKSIsCiAgICAgICAgICAgIHNlbGVjdGlvbi5tb2RlbF9pZCwKICAgICAgICAgICAgc2VsZWN0aW9uLnByb3ZpZGVyLAogICAgICAgICAgICBzZWxlY3Rpb24ubG9jYWxfZGlyLAogICAgICAgICkKICAgICAgICByZXR1cm4gX3JlcmFua2VyCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgX3JlcmFua2VyX2Vycm9yID0gc3RyKGUpCiAgICAgICAgbG9nLndhcm5pbmcoIlJlcmFua2VyIGluZGlzcG9uw612ZWwuIEJ1c2NhIHNlZ3VpcsOhIHNlbSByZXJhbmtpbmcuIEVycm86ICVzIiwgZSkKICAgICAgICByZXR1cm4gTm9uZQoKCmRlZiBnZXRfc3BsaXR0ZXIoKSAtPiBSZWN1cnNpdmVDaGFyYWN0ZXJUZXh0U3BsaXR0ZXI6CiAgICBnbG9iYWwgX3NwbGl0dGVyCiAgICBpZiBfc3BsaXR0ZXIgaXMgTm9uZToKICAgICAgICBfc3BsaXR0ZXIgPSBSZWN1cnNpdmVDaGFyYWN0ZXJUZXh0U3BsaXR0ZXIoCiAgICAgICAgICAgIGNodW5rX3NpemU9Q0hVTktfU0laRSwKICAgICAgICAgICAgY2h1bmtfb3ZlcmxhcD1DSFVOS19PVkVSTEFQLAogICAgICAgICAgICBsZW5ndGhfZnVuY3Rpb249bGVuLAogICAgICAgICAgICBzZXBhcmF0b3JzPVsiXG5cbiIsICJcbiIsICIgIiwgIiJdLAogICAgICAgICkKICAgIHJldHVybiBfc3BsaXR0ZXIKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEluZGV4YcOnw6NvIGludGVybmEKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCgpkZWYgX21ha2VfY2h1bmtfaWQoZmlsZV9wYXRoOiBzdHIsIGNodW5rX2luZGV4OiBpbnQpIC0+IHN0cjoKICAgIHJhdyA9IGYie2ZpbGVfcGF0aH06OmNodW5rOjp7Y2h1bmtfaW5kZXh9IgogICAgcmV0dXJuIGhhc2hsaWIubWQ1KHJhdy5lbmNvZGUoKSkuaGV4ZGlnZXN0KCkKCgpkZWYgX21ha2VfcmVzdWx0X2tleShtZXRhZGF0YTogZGljdFtzdHIsIG9iamVjdF0sIGZhbGxiYWNrX2lkOiBzdHIpIC0+IHN0cjoKICAgIGZpbGVfcGF0aCA9IHN0cihtZXRhZGF0YS5nZXQoImZpbGVfcGF0aCIsICIiKSkKICAgIGNodW5rX2luZGV4ID0gc3RyKG1ldGFkYXRhLmdldCgiY2h1bmtfaW5kZXgiLCAiIikpCiAgICBpZiBmaWxlX3BhdGggYW5kIGNodW5rX2luZGV4OgogICAgICAgIHJldHVybiBmIntmaWxlX3BhdGh9OjpjaHVuazo6e2NodW5rX2luZGV4fSIKICAgIHJldHVybiBmYWxsYmFja19pZAoKCmRlZiBfZGVsZXRlX2ZpbGVfY2h1bmtzKGNvbGxlY3Rpb246IGNocm9tYWRiLkNvbGxlY3Rpb24sIGZpbGVfcGF0aDogc3RyKSAtPiBpbnQ6CiAgICAjIFBlZGUgYXBlbmFzIElEcyBwYXJhIG7Do28gbWF0ZXJpYWxpemFyIGRvY3VtZW50b3MvbWV0YWRhdGEgZGVzbmVjZXNzw6FyaW9zIGVtIFJBTS4KICAgIHJlc3VsdHMgPSBjb2xsZWN0aW9uLmdldCh3aGVyZT17ImZpbGVfcGF0aCI6IGZpbGVfcGF0aH0sIGluY2x1ZGU9W10pCiAgICBpZHMgPSByZXN1bHRzLmdldCgiaWRzIiwgW10pIGlmIHJlc3VsdHMgZWxzZSBbXQogICAgaWYgaWRzOgogICAgICAgIGNvbGxlY3Rpb24uZGVsZXRlKGlkcz1pZHMpCiAgICByZXR1cm4gbGVuKGlkcykKCgpkZWYgX3JlYWRfZmlsZV9zYWZlKGZpbGVwYXRoOiBQYXRoKSAtPiBzdHIgfCBOb25lOgogICAgZm9yIGVuY29kaW5nIGluICgidXRmLTgiLCAibGF0aW4tMSIsICJjcDEyNTIiKToKICAgICAgICB0cnk6CiAgICAgICAgICAgIHJldHVybiBmaWxlcGF0aC5yZWFkX3RleHQoZW5jb2Rpbmc9ZW5jb2RpbmcpCiAgICAgICAgZXhjZXB0IFVuaWNvZGVEZWNvZGVFcnJvcjoKICAgICAgICAgICAgY29udGludWUKICAgICAgICBleGNlcHQgT1NFcnJvcjoKICAgICAgICAgICAgcmV0dXJuIE5vbmUKICAgIHJldHVybiBOb25lCgoKZGVmIF9zY2FuX2ZvbGRlcihmb2xkZXJfcGF0aDogUGF0aCkgLT4gSXRlcmF0b3JbUGF0aF06CiAgICBmb3IgZGlycGF0aCwgZGlybmFtZXMsIGZpbGVuYW1lcyBpbiBvcy53YWxrKGZvbGRlcl9wYXRoKToKICAgICAgICBkaXJuYW1lc1s6XSA9IFsKICAgICAgICAgICAgZCBmb3IgZCBpbiBkaXJuYW1lcwogICAgICAgICAgICBpZiBkIG5vdCBpbiBJR05PUkVEX0RJUlMgYW5kIG5vdCBkLnN0YXJ0c3dpdGgoIi4iKQogICAgICAgIF0KICAgICAgICBkaXJuYW1lcy5zb3J0KCkKICAgICAgICBmb3IgZmlsZW5hbWUgaW4gc29ydGVkKGZpbGVuYW1lcyk6CiAgICAgICAgICAgIGZwID0gUGF0aChkaXJwYXRoKSAvIGZpbGVuYW1lCiAgICAgICAgICAgIGlmIGZwLnN1ZmZpeC5sb3dlcigpIGluIElHTk9SRURfRVhURU5TSU9OUzoKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIGlmIGZwLnN0YXQoKS5zdF9zaXplID4gTUFYX0ZJTEVfU0laRV9CWVRFUzoKICAgICAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICBleGNlcHQgT1NFcnJvcjoKICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgIHlpZWxkIGZwCgoKZGVmIF9jbGFzc2lmeV9maWxlX3RhcmdldHMoZmlsZXBhdGg6IFBhdGgpIC0+IGxpc3RbQnJhbmNoU3BlY106CiAgICBzdWZmaXggPSBmaWxlcGF0aC5zdWZmaXgubG93ZXIoKQogICAgaXNfY29kZSA9IHN1ZmZpeCBpbiBDT0RFX0VYVEVOU0lPTlMKICAgIGlzX2RvYyA9IHN1ZmZpeCBpbiBET0NfRVhURU5TSU9OUwoKICAgIGlmIGlzX2NvZGUgYW5kIG5vdCBpc19kb2M6CiAgICAgICAgcmV0dXJuIFtCUkFOQ0hfU1BFQ1NbImppbmFfY29kZSJdXQogICAgaWYgaXNfZG9jIGFuZCBub3QgaXNfY29kZToKICAgICAgICByZXR1cm4gW0JSQU5DSF9TUEVDU1siYmdlX2RvYyJdXQoKICAgICMgQXJxdWl2b3MgYW1iw61ndW9zL2V4dGVuc8OjbyBkZXNjb25oZWNpZGE6IGluZGV4YSBlbSBhbWJhcyBwYXJhIG7Do28gcGVyZGVyIHJlY2FsbC4KICAgIHJldHVybiBbQlJBTkNIX1NQRUNTWyJqaW5hX2NvZGUiXSwgQlJBTkNIX1NQRUNTWyJiZ2VfZG9jIl1dCgoKZGVmIF9pbmRleF9zaW5nbGVfZmlsZV9mb3JfYnJhbmNoKAogICAgZmlsZXBhdGg6IFBhdGgsCiAgICBicmFuY2g6IEJyYW5jaFNwZWMsCiAgICBzcGxpdHRlcjogUmVjdXJzaXZlQ2hhcmFjdGVyVGV4dFNwbGl0dGVyLAogICAgKiwKICAgIGRlbGV0ZV9leGlzdGluZzogYm9vbCA9IFRydWUsCikgLT4gaW50OgogICAgY29udGVudCA9IF9yZWFkX2ZpbGVfc2FmZShmaWxlcGF0aCkKICAgIGlmIG5vdCBjb250ZW50IG9yIG5vdCBjb250ZW50LnN0cmlwKCk6CiAgICAgICAgcmV0dXJuIDAKCiAgICBhYnNfcGF0aCA9IHN0cihmaWxlcGF0aC5yZXNvbHZlKCkpCiAgICBtb2RlbCA9IGdldF9lbWJlZGRpbmdfbW9kZWwoYnJhbmNoLm1vZGVsX2Nob2ljZSkKICAgIGNvbGxlY3Rpb24gPSBnZXRfY2hyb21hX2NvbGxlY3Rpb24oYnJhbmNoLmNvbGxlY3Rpb25fbmFtZSkKCiAgICBjaHVua3MgPSBzcGxpdHRlci5zcGxpdF90ZXh0KGNvbnRlbnQpCiAgICBpZiBub3QgY2h1bmtzOgogICAgICAgIHJldHVybiAwCgogICAgIyBBdHVhbGl6YcOnw6NvIGlkZW1wb3RlbnRlIHBvciBhcnF1aXZvIGVtIGNhZGEgY29sZcOnw6NvLgogICAgaWYgZGVsZXRlX2V4aXN0aW5nOgogICAgICAgIF9kZWxldGVfZmlsZV9jaHVua3MoY29sbGVjdGlvbiwgYWJzX3BhdGgpCgogICAgaW5zZXJ0ZWRfY2h1bmtzID0gMAogICAgYmF0Y2hfaWRzOiBsaXN0W3N0cl0gPSBbXQogICAgYmF0Y2hfZG9jczogbGlzdFtzdHJdID0gW10KICAgIGJhdGNoX21ldGFkYXRhczogbGlzdFtkaWN0W3N0ciwgb2JqZWN0XV0gPSBbXQoKICAgIGRlZiBfZmx1c2hfYmF0Y2goKSAtPiBOb25lOgogICAgICAgIG5vbmxvY2FsIGluc2VydGVkX2NodW5rcwogICAgICAgIGlmIG5vdCBiYXRjaF9pZHM6CiAgICAgICAgICAgIHJldHVybgogICAgICAgIGVtYmVkZGluZ3MgPSBtb2RlbC5lbmNvZGUoCiAgICAgICAgICAgIGJhdGNoX2RvY3MsCiAgICAgICAgICAgIHNob3dfcHJvZ3Jlc3NfYmFyPUZhbHNlLAogICAgICAgICAgICBiYXRjaF9zaXplPUVNQkVERElOR19CQVRDSF9TSVpFLAogICAgICAgICkudG9saXN0KCkKICAgICAgICBjb2xsZWN0aW9uLnVwc2VydCgKICAgICAgICAgICAgaWRzPWJhdGNoX2lkcywKICAgICAgICAgICAgZW1iZWRkaW5ncz1lbWJlZGRpbmdzLAogICAgICAgICAgICBkb2N1bWVudHM9YmF0Y2hfZG9jcywKICAgICAgICAgICAgbWV0YWRhdGFzPWJhdGNoX21ldGFkYXRhcywKICAgICAgICApCiAgICAgICAgaW5zZXJ0ZWRfY2h1bmtzICs9IGxlbihiYXRjaF9pZHMpCiAgICAgICAgZGVsIGVtYmVkZGluZ3MKICAgICAgICBiYXRjaF9pZHMuY2xlYXIoKQogICAgICAgIGJhdGNoX2RvY3MuY2xlYXIoKQogICAgICAgIGJhdGNoX21ldGFkYXRhcy5jbGVhcigpCgogICAgZm9yIGksIGNodW5rIGluIGVudW1lcmF0ZShjaHVua3MpOgogICAgICAgIGJhdGNoX2lkcy5hcHBlbmQoX21ha2VfY2h1bmtfaWQoYWJzX3BhdGgsIGkpKQogICAgICAgIGJhdGNoX2RvY3MuYXBwZW5kKGNodW5rKQogICAgICAgIGJhdGNoX21ldGFkYXRhcy5hcHBlbmQoCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICJmaWxlX3BhdGgiOiBhYnNfcGF0aCwKICAgICAgICAgICAgICAgICJmaWxlX25hbWUiOiBmaWxlcGF0aC5uYW1lLAogICAgICAgICAgICAgICAgImNodW5rX2luZGV4IjogaSwKICAgICAgICAgICAgICAgICJzb3VyY2VfY29sbGVjdGlvbiI6IGJyYW5jaC5jb2xsZWN0aW9uX25hbWUsCiAgICAgICAgICAgICAgICAic291cmNlX21vZGVsX2Nob2ljZSI6IGJyYW5jaC5tb2RlbF9jaG9pY2UsCiAgICAgICAgICAgICAgICAic291cmNlX21vZGVsX2lkIjogYnJhbmNoLm1vZGVsX2lkLAogICAgICAgICAgICAgICAgImNvbnRlbnRfZG9tYWluIjogYnJhbmNoLmNvbnRlbnRfZG9tYWluLAogICAgICAgICAgICB9CiAgICAgICAgKQogICAgICAgIGlmIGxlbihiYXRjaF9pZHMpID49IEVNQkVERElOR19CQVRDSF9TSVpFOgogICAgICAgICAgICBfZmx1c2hfYmF0Y2goKQoKICAgIF9mbHVzaF9iYXRjaCgpCiAgICByZXR1cm4gaW5zZXJ0ZWRfY2h1bmtzCgoKZGVmIF9yZW1vdmVfZmlsZV9mcm9tX2FsbF9jb2xsZWN0aW9ucyhhYnNfcGF0aDogc3RyKSAtPiB0dXBsZVtkaWN0W3N0ciwgaW50XSwgbGlzdFtzdHJdXToKICAgIGRlbGV0ZWRfcGVyX2JyYW5jaDogZGljdFtzdHIsIGludF0gPSB7fQogICAgZXJyb3JzOiBsaXN0W3N0cl0gPSBbXQoKICAgIGZvciBicmFuY2ggaW4gQlJBTkNIX1NQRUNTLnZhbHVlcygpOgogICAgICAgIHRyeToKICAgICAgICAgICAgY29sbGVjdGlvbiA9IGdldF9jaHJvbWFfY29sbGVjdGlvbihicmFuY2guY29sbGVjdGlvbl9uYW1lKQogICAgICAgICAgICBkZWxldGVkID0gX2RlbGV0ZV9maWxlX2NodW5rcyhjb2xsZWN0aW9uLCBhYnNfcGF0aCkKICAgICAgICAgICAgZGVsZXRlZF9wZXJfYnJhbmNoW2JyYW5jaC5rZXldID0gZGVsZXRlZAogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgZXJyb3JzLmFwcGVuZChmInticmFuY2gua2V5fToge2V9IikKICAgIHJldHVybiBkZWxldGVkX3Blcl9icmFuY2gsIGVycm9ycwoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgQnVzY2Egc2Vtw6JudGljYSBow61icmlkYQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCmRlZiBfcXVlcnlfYnJhbmNoKGJyYW5jaDogQnJhbmNoU3BlYywgcXVlcnk6IHN0ciwgbl9yZXN1bHRzOiBpbnQpIC0+IHR1cGxlW2xpc3RbUmV0cmlldmVkSGl0XSwgc3RyIHwgTm9uZV06CiAgICB0cnk6CiAgICAgICAgY29sbGVjdGlvbiA9IGdldF9jaHJvbWFfY29sbGVjdGlvbihicmFuY2guY29sbGVjdGlvbl9uYW1lKQogICAgICAgIG1vZGVsID0gZ2V0X2VtYmVkZGluZ19tb2RlbChicmFuY2gubW9kZWxfY2hvaWNlKQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIHJldHVybiBbXSwgZiJ7YnJhbmNoLmtleX06IHJlY3Vyc28gaW5kaXNwb27DrXZlbCAoe2V9KSIKCiAgICB0cnk6CiAgICAgICAgcXVlcnlfZW1iZWRkaW5nID0gbW9kZWwuZW5jb2RlKFtxdWVyeV0sIHNob3dfcHJvZ3Jlc3NfYmFyPUZhbHNlKS50b2xpc3QoKQogICAgICAgIHJlc3VsdHMgPSBjb2xsZWN0aW9uLnF1ZXJ5KAogICAgICAgICAgICBxdWVyeV9lbWJlZGRpbmdzPXF1ZXJ5X2VtYmVkZGluZywKICAgICAgICAgICAgbl9yZXN1bHRzPW5fcmVzdWx0cywKICAgICAgICAgICAgaW5jbHVkZT1bImRvY3VtZW50cyIsICJtZXRhZGF0YXMiLCAiZGlzdGFuY2VzIl0sCiAgICAgICAgKQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIHJldHVybiBbXSwgZiJ7YnJhbmNoLmtleX06IGZhbGhhIG5hIHF1ZXJ5ICh7ZX0pIgoKICAgIGRvY3VtZW50cyA9IHJlc3VsdHMuZ2V0KCJkb2N1bWVudHMiLCBbW11dKVswXQogICAgbWV0YWRhdGFzID0gcmVzdWx0cy5nZXQoIm1ldGFkYXRhcyIsIFtbXV0pWzBdCiAgICBkaXN0YW5jZXMgPSByZXN1bHRzLmdldCgiZGlzdGFuY2VzIiwgW1tdXSlbMF0KICAgIGlkcyA9IHJlc3VsdHMuZ2V0KCJpZHMiLCBbW11dKVswXQoKICAgIGhpdHM6IGxpc3RbUmV0cmlldmVkSGl0XSA9IFtdCiAgICBmb3IgaWR4LCAoZG9jLCBtZXRhLCBkaXN0KSBpbiBlbnVtZXJhdGUoemlwKGRvY3VtZW50cywgbWV0YWRhdGFzLCBkaXN0YW5jZXMpLCBzdGFydD0xKToKICAgICAgICBtZXRhZGF0YSA9IG1ldGEgb3Ige30KICAgICAgICBmYWxsYmFja19pZCA9IGlkc1tpZHggLSAxXSBpZiBpZHggLSAxIDwgbGVuKGlkcykgZWxzZSBmInticmFuY2gua2V5fTp7aWR4fSIKICAgICAgICBrZXkgPSBfbWFrZV9yZXN1bHRfa2V5KG1ldGFkYXRhLCBmYWxsYmFja19pZCkKCiAgICAgICAgc2ltaWxhcml0eSA9IE5vbmUKICAgICAgICBpZiBkaXN0IGlzIG5vdCBOb25lOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBzaW1pbGFyaXR5ID0gMS4wIC0gZmxvYXQoZGlzdCkKICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICAgICAgICAgIHNpbWlsYXJpdHkgPSBOb25lCgogICAgICAgIGhpdHMuYXBwZW5kKAogICAgICAgICAgICBSZXRyaWV2ZWRIaXQoCiAgICAgICAgICAgICAgICBrZXk9a2V5LAogICAgICAgICAgICAgICAgZG9jdW1lbnQ9KGRvYyBvciAiIiksCiAgICAgICAgICAgICAgICBtZXRhZGF0YT1tZXRhZGF0YSwKICAgICAgICAgICAgICAgIGRpc3RhbmNlPWZsb2F0KGRpc3QpIGlmIGRpc3QgaXMgbm90IE5vbmUgZWxzZSBOb25lLAogICAgICAgICAgICAgICAgc2ltaWxhcml0eT1zaW1pbGFyaXR5LAogICAgICAgICAgICAgICAgYnJhbmNoPWJyYW5jaCwKICAgICAgICAgICAgICAgIHJhbms9aWR4LAogICAgICAgICAgICApCiAgICAgICAgKQoKICAgIHJldHVybiBoaXRzLCBOb25lCgoKZGVmIF9ycmZfZnVzZShoaXRzX2J5X2JyYW5jaDogZGljdFtzdHIsIGxpc3RbUmV0cmlldmVkSGl0XV0sIHRvcF9saW1pdDogaW50KSAtPiBsaXN0W0Z1c2VkSGl0XToKICAgIGZ1c2VkOiBkaWN0W3N0ciwgRnVzZWRIaXRdID0ge30KCiAgICBmb3IgYnJhbmNoX2tleSwgaGl0cyBpbiBoaXRzX2J5X2JyYW5jaC5pdGVtcygpOgogICAgICAgIF8gPSBicmFuY2hfa2V5CiAgICAgICAgZm9yIHJhbmssIGhpdCBpbiBlbnVtZXJhdGUoaGl0cywgc3RhcnQ9MSk6CiAgICAgICAgICAgIGNvbnRyaWJ1dGlvbiA9IDEuMCAvIChSUkZfSyArIHJhbmspCiAgICAgICAgICAgIGVudHJ5ID0gZnVzZWQuZ2V0KGhpdC5rZXkpCgogICAgICAgICAgICBpZiBlbnRyeSBpcyBOb25lOgogICAgICAgICAgICAgICAgZW50cnkgPSBGdXNlZEhpdCgKICAgICAgICAgICAgICAgICAgICBrZXk9aGl0LmtleSwKICAgICAgICAgICAgICAgICAgICBkb2N1bWVudD1oaXQuZG9jdW1lbnQsCiAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE9ZGljdChoaXQubWV0YWRhdGEpLAogICAgICAgICAgICAgICAgICAgIHJyZl9zY29yZT0wLjAsCiAgICAgICAgICAgICAgICAgICAgc291cmNlX2RldGFpbHM9e30sCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICBmdXNlZFtoaXQua2V5XSA9IGVudHJ5CgogICAgICAgICAgICBlbnRyeS5ycmZfc2NvcmUgKz0gY29udHJpYnV0aW9uCiAgICAgICAgICAgIGVudHJ5LnNvdXJjZV9kZXRhaWxzW2hpdC5icmFuY2gua2V5XSA9IHsKICAgICAgICAgICAgICAgICJyYW5rIjogcmFuaywKICAgICAgICAgICAgICAgICJkaXN0YW5jZSI6IGhpdC5kaXN0YW5jZSwKICAgICAgICAgICAgICAgICJzaW1pbGFyaXR5IjogaGl0LnNpbWlsYXJpdHksCiAgICAgICAgICAgICAgICAiY29sbGVjdGlvbiI6IGhpdC5icmFuY2guY29sbGVjdGlvbl9uYW1lLAogICAgICAgICAgICAgICAgIm1vZGVsX2Nob2ljZSI6IGhpdC5icmFuY2gubW9kZWxfY2hvaWNlLAogICAgICAgICAgICAgICAgIm1vZGVsX2lkIjogaGl0LmJyYW5jaC5tb2RlbF9pZCwKICAgICAgICAgICAgICAgICJjb250ZW50X2RvbWFpbiI6IGhpdC5icmFuY2guY29udGVudF9kb21haW4sCiAgICAgICAgICAgIH0KCiAgICAgICAgICAgICMgVXNhIG1ldGFkYWRvcyBkbyBoaXQgY29tIG1lbGhvciBzaW1pbGFyaWRhZGUgbG9jYWwgY29tbyBiYXNlIHByaW5jaXBhbC4KICAgICAgICAgICAgY3VycmVudF9zaW0gPSBlbnRyeS5tZXRhZGF0YS5nZXQoIl9iZXN0X3NpbWlsYXJpdHkiLCAtMTAuMCkKICAgICAgICAgICAgY2FuZGlkYXRlX3NpbSA9IGhpdC5zaW1pbGFyaXR5IGlmIGhpdC5zaW1pbGFyaXR5IGlzIG5vdCBOb25lIGVsc2UgLTEwLjAKICAgICAgICAgICAgaWYgY2FuZGlkYXRlX3NpbSA+IGN1cnJlbnRfc2ltOgogICAgICAgICAgICAgICAgZW50cnkuZG9jdW1lbnQgPSBoaXQuZG9jdW1lbnQKICAgICAgICAgICAgICAgIGVudHJ5Lm1ldGFkYXRhID0gZGljdChoaXQubWV0YWRhdGEpCiAgICAgICAgICAgICAgICBlbnRyeS5tZXRhZGF0YVsiX2Jlc3Rfc2ltaWxhcml0eSJdID0gY2FuZGlkYXRlX3NpbQoKICAgIGZ1c2VkX2hpdHMgPSBsaXN0KGZ1c2VkLnZhbHVlcygpKQogICAgZnVzZWRfaGl0cy5zb3J0KGtleT1sYW1iZGEgaDogaC5ycmZfc2NvcmUsIHJldmVyc2U9VHJ1ZSkKCiAgICAjIExpbWl0YSBvIHBvb2wgYW50ZXMgZG8gcmVyYW5raW5nIHBhcmEgcmVkdXppciBDUFUvUkFNLgogICAgcmV0dXJuIGZ1c2VkX2hpdHNbOnRvcF9saW1pdF0KCgpkZWYgX2FwcGx5X3JlcmFuayhxdWVyeTogc3RyLCBmdXNlZF9oaXRzOiBsaXN0W0Z1c2VkSGl0XSwgdG9wX2s6IGludCkgLT4gdHVwbGVbbGlzdFtGdXNlZEhpdF0sIGJvb2wsIHN0ciB8IE5vbmVdOgogICAgaWYgbm90IGZ1c2VkX2hpdHM6CiAgICAgICAgcmV0dXJuIFtdLCBGYWxzZSwgTm9uZQoKICAgIHJlcmFua2VyID0gZ2V0X3JlcmFua2VyKCkKICAgIGlmIHJlcmFua2VyIGlzIE5vbmU6CiAgICAgICAgcmVhc29uID0gX3JlcmFua2VyX2Vycm9yIGlmIF9yZXJhbmtlcl9lcnJvciBlbHNlICJyZXJhbmtlcl9kZXNhYmlsaXRhZG8iCiAgICAgICAgcmV0dXJuIGZ1c2VkX2hpdHNbOnRvcF9rXSwgRmFsc2UsIHJlYXNvbgoKICAgIHRyeToKICAgICAgICBwYWlycyA9IFsocXVlcnksIGhpdC5kb2N1bWVudCkgZm9yIGhpdCBpbiBmdXNlZF9oaXRzXQogICAgICAgIHNjb3JlcyA9IHJlcmFua2VyLnByZWRpY3QocGFpcnMsIHNob3dfcHJvZ3Jlc3NfYmFyPUZhbHNlLCBjb252ZXJ0X3RvX251bXB5PVRydWUpCgogICAgICAgIGZvciBoaXQsIHNjb3JlIGluIHppcChmdXNlZF9oaXRzLCBzY29yZXMpOgogICAgICAgICAgICBoaXQucmVyYW5rX3Njb3JlID0gZmxvYXQoc2NvcmUpCgogICAgICAgIGZ1c2VkX2hpdHMuc29ydCgKICAgICAgICAgICAga2V5PWxhbWJkYSBoOiAoCiAgICAgICAgICAgICAgICBoLnJlcmFua19zY29yZSBpZiBoLnJlcmFua19zY29yZSBpcyBub3QgTm9uZSBlbHNlIC0xZTksCiAgICAgICAgICAgICAgICBoLnJyZl9zY29yZSwKICAgICAgICAgICAgKSwKICAgICAgICAgICAgcmV2ZXJzZT1UcnVlLAogICAgICAgICkKICAgICAgICByZXR1cm4gZnVzZWRfaGl0c1s6dG9wX2tdLCBUcnVlLCBOb25lCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgcmV0dXJuIGZ1c2VkX2hpdHNbOnRvcF9rXSwgRmFsc2UsIHN0cihlKQoKCmRlZiBfZm9ybWF0X3NpbWlsYXJpdHkoc2ltaWxhcml0eTogZmxvYXQgfCBOb25lKSAtPiBzdHI6CiAgICBpZiBzaW1pbGFyaXR5IGlzIE5vbmU6CiAgICAgICAgcmV0dXJuICJuL2EiCiAgICByZXR1cm4gZiJ7cm91bmQoc2ltaWxhcml0eSAqIDEwMCwgMSl9JSIKCgpkZWYgX2Zvcm1hdF9mdXNlZF9yZXN1bHRzKAogICAgKiwKICAgIHF1ZXJ5OiBzdHIsCiAgICBtb2RlOiBzdHIsCiAgICBoaXRzOiBsaXN0W0Z1c2VkSGl0XSwKICAgIGJyYW5jaF9lcnJvcnM6IGxpc3Rbc3RyXSwKICAgIHJlcmFua19hcHBsaWVkOiBib29sLAogICAgcmVyYW5rX2Vycm9yOiBzdHIgfCBOb25lLAopIC0+IHN0cjoKICAgIGlmIG5vdCBoaXRzOgogICAgICAgIG1zZyA9ICJOZW5odW0gcmVzdWx0YWRvIGVuY29udHJhZG8uIEFzIGNvbGXDp8O1ZXMgcG9kZW0gZXN0YXIgdmF6aWFzLiIKICAgICAgICBpZiBicmFuY2hfZXJyb3JzOgogICAgICAgICAgICBtc2cgKz0gIlxuRmFsaGFzIGRldGVjdGFkYXM6ICIgKyAiIHwgIi5qb2luKGJyYW5jaF9lcnJvcnMpCiAgICAgICAgcmV0dXJuIG1zZwoKICAgIGxpbmVzOiBsaXN0W3N0cl0gPSBbZiIjIFJlc3VsdGFkb3MgcGFyYTogJ3txdWVyeX0nIiwgZiIqKk1vZG86Kioge21vZGV9Il0KCiAgICBpZiBicmFuY2hfZXJyb3JzOgogICAgICAgIGxpbmVzLmFwcGVuZCgiKipBdmlzb3MgZGUgYnJhbmNoOioqICIgKyAiIHwgIi5qb2luKGJyYW5jaF9lcnJvcnMpKQoKICAgIGlmIG1vZGUgPT0gImVuc2VtYmxlIjoKICAgICAgICBpZiByZXJhbmtfYXBwbGllZDoKICAgICAgICAgICAgbGluZXMuYXBwZW5kKGYiKipSZXJhbmtpbmc6KiogYXRpdm8gKHtSRVJBTktfTU9ERUxfSUR9KSIpCiAgICAgICAgZWxzZToKICAgICAgICAgICAgbGluZXMuYXBwZW5kKGYiKipSZXJhbmtpbmc6KiogaW5kaXNwb27DrXZlbCAoe3JlcmFua19lcnJvciBvciAnc2VtIGRldGFsaGVzJ30pIikKCiAgICBsaW5lcy5hcHBlbmQoIiIpCgogICAgZm9yIGlkeCwgaGl0IGluIGVudW1lcmF0ZShoaXRzLCBzdGFydD0xKToKICAgICAgICBtZXRhZGF0YSA9IGRpY3QoaGl0Lm1ldGFkYXRhKQogICAgICAgIG1ldGFkYXRhLnBvcCgiX2Jlc3Rfc2ltaWxhcml0eSIsIE5vbmUpCgogICAgICAgIGZpbGVfcGF0aCA9IHN0cihtZXRhZGF0YS5nZXQoImZpbGVfcGF0aCIsICJkZXNjb25oZWNpZG8iKSkKICAgICAgICBjaHVua19pbmRleCA9IG1ldGFkYXRhLmdldCgiY2h1bmtfaW5kZXgiLCAiPyIpCiAgICAgICAgZmlsZV9uYW1lID0gc3RyKG1ldGFkYXRhLmdldCgiZmlsZV9uYW1lIiwgUGF0aChmaWxlX3BhdGgpLm5hbWUgaWYgZmlsZV9wYXRoICE9ICJkZXNjb25oZWNpZG8iIGVsc2UgIj8iKSkKCiAgICAgICAgc291cmNlX21vZGVscyA9IHNvcnRlZCh7c3RyKHYuZ2V0KCJtb2RlbF9jaG9pY2UiLCAiPyIpKSBmb3IgdiBpbiBoaXQuc291cmNlX2RldGFpbHMudmFsdWVzKCl9KQogICAgICAgIHNvdXJjZV9jb2xsZWN0aW9ucyA9IHNvcnRlZCh7c3RyKHYuZ2V0KCJjb2xsZWN0aW9uIiwgIj8iKSkgZm9yIHYgaW4gaGl0LnNvdXJjZV9kZXRhaWxzLnZhbHVlcygpfSkKCiAgICAgICAgc291cmNlX3BhcnRzOiBsaXN0W3N0cl0gPSBbXQogICAgICAgIGZvciBzb3VyY2Vfa2V5LCBkZXRhaWxzIGluIHNvcnRlZCgKICAgICAgICAgICAgaGl0LnNvdXJjZV9kZXRhaWxzLml0ZW1zKCksCiAgICAgICAgICAgIGtleT1sYW1iZGEgaXRlbTogaW50KGl0ZW1bMV0uZ2V0KCJyYW5rIiwgOTk5OTk5KSksCiAgICAgICAgKToKICAgICAgICAgICAgc291cmNlX3BhcnRzLmFwcGVuZCgKICAgICAgICAgICAgICAgIGYie3NvdXJjZV9rZXl9KHJhbms9e2RldGFpbHMuZ2V0KCdyYW5rJyl9LCBzaW09e19mb3JtYXRfc2ltaWxhcml0eShkZXRhaWxzLmdldCgnc2ltaWxhcml0eScpKX0pIgogICAgICAgICAgICApCgogICAgICAgIHNuaXBwZXQgPSBoaXQuZG9jdW1lbnQuc3RyaXAoKQogICAgICAgIGlmIGxlbihzbmlwcGV0KSA+IDgwMDoKICAgICAgICAgICAgc25pcHBldCA9IHNuaXBwZXRbOjgwMF0gKyAiXG4uLi4gW3RydW5jYWRvXSIKCiAgICAgICAgc2NvcmVfbGluZSA9IGYiUlJGPXtoaXQucnJmX3Njb3JlOi40Zn0iCiAgICAgICAgaWYgaGl0LnJlcmFua19zY29yZSBpcyBub3QgTm9uZToKICAgICAgICAgICAgc2NvcmVfbGluZSArPSBmIiB8IHJlcmFuaz17aGl0LnJlcmFua19zY29yZTouNGZ9IgoKICAgICAgICBsaW5lcy5hcHBlbmQoZiIjIyBbe2lkeH1dIHtmaWxlX3BhdGh9IikKICAgICAgICBsaW5lcy5hcHBlbmQoZiIqKlNjb3JlczoqKiB7c2NvcmVfbGluZX0iKQogICAgICAgIGxpbmVzLmFwcGVuZChmIioqRm9udGVzIGRlIHJlY3VwZXJhw6fDo286KiogeycsICcuam9pbihzb3VyY2VfcGFydHMpfSIpCiAgICAgICAgbGluZXMuYXBwZW5kKAogICAgICAgICAgICAiKipNZXRhZGFkb3MgdW5pZmljYWRvczoqKiAiCiAgICAgICAgICAgIGYiZmlsZV9uYW1lPXtmaWxlX25hbWV9IHwgY2h1bmtfaW5kZXg9e2NodW5rX2luZGV4fSB8ICIKICAgICAgICAgICAgZiJzb3VyY2VfbW9kZWxzPXtzb3VyY2VfbW9kZWxzfSB8IHNvdXJjZV9jb2xsZWN0aW9ucz17c291cmNlX2NvbGxlY3Rpb25zfSIKICAgICAgICApCiAgICAgICAgbGluZXMuYXBwZW5kKCIiKQogICAgICAgIGxpbmVzLmFwcGVuZChmImBgYFxue3NuaXBwZXR9XG5gYGAiKQogICAgICAgIGxpbmVzLmFwcGVuZCgiIikKCiAgICByZXR1cm4gIlxuIi5qb2luKGxpbmVzKQoKCmRlZiBfcnVuX3NpbmdsZV9tb2RlKHF1ZXJ5OiBzdHIsIHRvcF9rOiBpbnQpIC0+IHR1cGxlW2xpc3RbRnVzZWRIaXRdLCBsaXN0W3N0cl0sIGJvb2wsIHN0ciB8IE5vbmVdOgogICAgcHJpbWFyeV9icmFuY2ggPSBCUkFOQ0hfU1BFQ1NbREVGQVVMVF9TSU5HTEVfQlJBTkNIX0tFWV0KCiAgICBoaXRzLCBlcnJvciA9IF9xdWVyeV9icmFuY2gocHJpbWFyeV9icmFuY2gsIHF1ZXJ5LCB0b3BfaykKICAgIGVycm9yczogbGlzdFtzdHJdID0gW10KICAgIGlmIGVycm9yOgogICAgICAgIGVycm9ycy5hcHBlbmQoZXJyb3IpCgogICAgIyBGYWxsYmFjayBhdXRvbcOhdGljbyBwYXJhIGEgYnJhbmNoIGFsdGVybmF0aXZhLCBwcmVzZXJ2YW5kbyBkaXNwb25pYmlsaWRhZGUuCiAgICBpZiBub3QgaGl0czoKICAgICAgICBmYWxsYmFja19icmFuY2hfa2V5ID0gImJnZV9kb2MiIGlmIHByaW1hcnlfYnJhbmNoLmtleSA9PSAiamluYV9jb2RlIiBlbHNlICJqaW5hX2NvZGUiCiAgICAgICAgZmFsbGJhY2tfaGl0cywgZmFsbGJhY2tfZXJyb3IgPSBfcXVlcnlfYnJhbmNoKEJSQU5DSF9TUEVDU1tmYWxsYmFja19icmFuY2hfa2V5XSwgcXVlcnksIHRvcF9rKQogICAgICAgIGlmIGZhbGxiYWNrX2Vycm9yOgogICAgICAgICAgICBlcnJvcnMuYXBwZW5kKGZhbGxiYWNrX2Vycm9yKQogICAgICAgIGlmIGZhbGxiYWNrX2hpdHM6CiAgICAgICAgICAgIGhpdHMgPSBmYWxsYmFja19oaXRzCgogICAgaWYgbm90IGhpdHM6CiAgICAgICAgcmV0dXJuIFtdLCBlcnJvcnMsIEZhbHNlLCBOb25lCgogICAgZnVzZWQgPSBfcnJmX2Z1c2UoeyJzaW5nbGUiOiBoaXRzfSwgdG9wX2spCiAgICByZXR1cm4gZnVzZWQsIGVycm9ycywgRmFsc2UsIE5vbmUKCgpkZWYgX3J1bl9lbnNlbWJsZV9tb2RlKHF1ZXJ5OiBzdHIsIHRvcF9rOiBpbnQpIC0+IHR1cGxlW2xpc3RbRnVzZWRIaXRdLCBsaXN0W3N0cl0sIGJvb2wsIHN0ciB8IE5vbmVdOgogICAgcGVyX2JyYW5jaF9rID0gbWluKE1BWF9RVUVSWV9SRVNVTFRTLCBtYXgodG9wX2sgKiAyLCB0b3BfaykpCiAgICBicmFuY2hlcyA9IFtCUkFOQ0hfU1BFQ1NbImppbmFfY29kZSJdLCBCUkFOQ0hfU1BFQ1NbImJnZV9kb2MiXV0KCiAgICBoaXRzX2J5X2JyYW5jaDogZGljdFtzdHIsIGxpc3RbUmV0cmlldmVkSGl0XV0gPSB7fQogICAgYnJhbmNoX2Vycm9yczogbGlzdFtzdHJdID0gW10KCiAgICB3aXRoIFRocmVhZFBvb2xFeGVjdXRvcihtYXhfd29ya2Vycz1sZW4oYnJhbmNoZXMpKSBhcyBleGVjdXRvcjoKICAgICAgICBmdXR1cmVzID0gewogICAgICAgICAgICBleGVjdXRvci5zdWJtaXQoX3F1ZXJ5X2JyYW5jaCwgYnJhbmNoLCBxdWVyeSwgcGVyX2JyYW5jaF9rKTogYnJhbmNoCiAgICAgICAgICAgIGZvciBicmFuY2ggaW4gYnJhbmNoZXMKICAgICAgICB9CiAgICAgICAgZm9yIGZ1dHVyZSBpbiBhc19jb21wbGV0ZWQoZnV0dXJlcyk6CiAgICAgICAgICAgIGJyYW5jaCA9IGZ1dHVyZXNbZnV0dXJlXQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBoaXRzLCBlcnJvciA9IGZ1dHVyZS5yZXN1bHQoKQogICAgICAgICAgICAgICAgaWYgZXJyb3I6CiAgICAgICAgICAgICAgICAgICAgYnJhbmNoX2Vycm9ycy5hcHBlbmQoZXJyb3IpCiAgICAgICAgICAgICAgICBpZiBoaXRzOgogICAgICAgICAgICAgICAgICAgIGhpdHNfYnlfYnJhbmNoW2JyYW5jaC5rZXldID0gaGl0cwogICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgICAgICBicmFuY2hfZXJyb3JzLmFwcGVuZChmInticmFuY2gua2V5fTogZmFsaGEgaW5lc3BlcmFkYSAoe2V9KSIpCgogICAgaWYgbm90IGhpdHNfYnlfYnJhbmNoOgogICAgICAgIHJldHVybiBbXSwgYnJhbmNoX2Vycm9ycywgRmFsc2UsIE5vbmUKCiAgICBjYW5kaWRhdGVfcG9vbCA9IG1pbihSRVJBTktfTUFYX0NBTkRJREFURVMsIG1heCh0b3BfaywgdG9wX2sgKiBSRVJBTktfQ0FORElEQVRFX01VTFRJUExJRVIpKQogICAgZnVzZWRfY2FuZGlkYXRlcyA9IF9ycmZfZnVzZShoaXRzX2J5X2JyYW5jaCwgY2FuZGlkYXRlX3Bvb2wpCiAgICByZXJhbmtlZF9oaXRzLCByZXJhbmtfYXBwbGllZCwgcmVyYW5rX2Vycm9yID0gX2FwcGx5X3JlcmFuayhxdWVyeSwgZnVzZWRfY2FuZGlkYXRlcywgdG9wX2spCiAgICByZXR1cm4gcmVyYW5rZWRfaGl0cywgYnJhbmNoX2Vycm9ycywgcmVyYW5rX2FwcGxpZWQsIHJlcmFua19lcnJvcgoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgU2Vydmlkb3IgTUNQIHZpYSBGYXN0TUNQCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgptY3AgPSBGYXN0TUNQKAogICAgbmFtZT0icmFnLWNvZGViYXNlIiwKICAgIGluc3RydWN0aW9ucz0oCiAgICAgICAgIlNlcnZpZG9yIFJBRyBwYXJhIGJ1c2NhIHNlbcOibnRpY2EgZW0gY8OzZGlnby1mb250ZSBsb2NhbCBjb20gc3Vwb3J0ZSBhIGVuc2VtYmxlIGjDrWJyaWRvLiAiCiAgICAgICAgIk5vIG1vZG8gaHlicmlkLCBhIGJyYW5jaCBkZSBjw7NkaWdvIHVzYSBKaW5hIHYyIGUgYSBkZSBkb2N1bWVudGHDp8OjbyB1c2EgQkdFLiAiCiAgICAgICAgIlVzZSBzZW1hbnRpY19zZWFyY2hfY29kZShxdWVyeSwgdG9wX2ssIG1vZGU9J2Vuc2VtYmxlJykgcGFyYSBjb21iaW5hciBKaW5hK0JHRSBjb20gUlJGIGUgcmVyYW5raW5nLiAiCiAgICAgICAgIlVzZSB1cGRhdGVfZmlsZV9pbmRleCBhcMOzcyBlZGl0YXIgdW0gYXJxdWl2byBwYXJhIG1hbnRlciBhcyBkdWFzIGNvbGXDp8O1ZXMgc2luY3Jvbml6YWRhcy4gIgogICAgICAgICJVc2UgaW5kZXhfc3BlY2lmaWNfZm9sZGVyIHBhcmEgaW5kZXhhw6fDo28gcmVjdXJzaXZhIHNvYiBkZW1hbmRhLiIKICAgICksCikKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIFRvb2wgMTogc2VtYW50aWNfc2VhcmNoX2NvZGUKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCkBtY3AudG9vbCgpCmRlZiBzZW1hbnRpY19zZWFyY2hfY29kZShxdWVyeTogc3RyLCB0b3BfazogaW50ID0gVE9QX0tfUkVTVUxUUywgbW9kZTogc3RyID0gU0VBUkNIX01PREVfREVGQVVMVCkgLT4gc3RyOgogICAgIiIiCiAgICBCdXNjYSBzZW3Dom50aWNhIG5vIMOtbmRpY2UgdmV0b3JpYWwgbG9jYWwuCgogICAgTW9kb3M6CiAgICAtIHNpbmdsZTogdXNhIGFwZW5hcyB1bWEgYnJhbmNoIChKaW5hL0JHRSBjb25mb3JtZSBNQ1BfRU1CRURESU5HX01PREVMOyBubyBoeWJyaWQsIEppbmEgdjIpLgogICAgLSBlbnNlbWJsZTogY29uc3VsdGEgZW0gcGFyYWxlbG8gY29kZV92ZWN0b3JzX2ppbmEgKyBkb2NfdmVjdG9yc19iZ2UsCiAgICAgIGZheiBmdXPDo28gdmlhIFJlY2lwcm9jYWwgUmFuayBGdXNpb24gKFJSRikgZSByZXJhbmtpbmcgbGV2ZS4KCiAgICBBcmdzOgogICAgICAgIHF1ZXJ5OiBEZXNjcmnDp8OjbyBkbyBxdWUgcHJvY3VyYXIuCiAgICAgICAgdG9wX2s6IFF1YW50aWRhZGUgZmluYWwgZGUgcmVzdWx0YWRvcy4KICAgICAgICBtb2RlOiAic2luZ2xlIiAocGFkcsOjbykgb3UgImVuc2VtYmxlIi4KCiAgICBSZXR1cm5zOgogICAgICAgIFJlc3VsdGFkbyB0ZXh0dWFsIGZvcm1hdGFkbyBwYXJhIGNvbnN1bW8gcGVsbyBMTE0uCiAgICAiIiIKICAgIHJhd19xdWVyeSA9IChxdWVyeSBvciAiIikuc3RyaXAoKQogICAgc2VhcmNoX21vZGUgPSAobW9kZSBvciBTRUFSQ0hfTU9ERV9ERUZBVUxUKS5zdHJpcCgpLmxvd2VyKCkKCiAgICBfbG9nX3Rvb2xfdXNhZ2UoCiAgICAgICAgZXZlbnQ9InRvb2xfY2FsbF9zdGFydCIsCiAgICAgICAgdG9vbF9uYW1lPSJzZW1hbnRpY19zZWFyY2hfY29kZSIsCiAgICAgICAgZGV0YWlscz17CiAgICAgICAgICAgICJxdWVyeV9wcmV2aWV3IjogX3NhZmVfcHJldmlldyhyYXdfcXVlcnkpLAogICAgICAgICAgICAicXVlcnlfbGVuIjogbGVuKHJhd19xdWVyeSksCiAgICAgICAgICAgICJ0b3BfayI6IHRvcF9rLAogICAgICAgICAgICAibW9kZSI6IHNlYXJjaF9tb2RlLAogICAgICAgIH0sCiAgICApCgogICAgaWYgbm90IHJhd19xdWVyeToKICAgICAgICBfbG9nX3Rvb2xfdXNhZ2UoCiAgICAgICAgICAgIGV2ZW50PSJ0b29sX2NhbGxfZW5kIiwKICAgICAgICAgICAgdG9vbF9uYW1lPSJzZW1hbnRpY19zZWFyY2hfY29kZSIsCiAgICAgICAgICAgIGRldGFpbHM9eyJzdGF0dXMiOiAiZXJyb3IiLCAicmVhc29uIjogImVtcHR5X3F1ZXJ5In0sCiAgICAgICAgKQogICAgICAgIHJldHVybiAiRXJybzogYSBxdWVyeSBuw6NvIHBvZGUgc2VyIHZhemlhLiIKCiAgICB0b3BfayA9IG1heCgxLCBtaW4odG9wX2ssIDIwKSkKICAgIGlmIHNlYXJjaF9tb2RlIG5vdCBpbiB7InNpbmdsZSIsICJlbnNlbWJsZSJ9OgogICAgICAgIF9sb2dfdG9vbF91c2FnZSgKICAgICAgICAgICAgZXZlbnQ9InRvb2xfY2FsbF9lbmQiLAogICAgICAgICAgICB0b29sX25hbWU9InNlbWFudGljX3NlYXJjaF9jb2RlIiwKICAgICAgICAgICAgZGV0YWlscz17InN0YXR1cyI6ICJlcnJvciIsICJyZWFzb24iOiAiaW52YWxpZF9tb2RlIiwgIm1vZGUiOiBzZWFyY2hfbW9kZX0sCiAgICAgICAgKQogICAgICAgIHJldHVybiAiRXJybzogbW9kZSBpbnbDoWxpZG8uIFVzZSAnc2luZ2xlJyBvdSAnZW5zZW1ibGUnLiIKCiAgICB0cnk6CiAgICAgICAgaWYgc2VhcmNoX21vZGUgPT0gImVuc2VtYmxlIjoKICAgICAgICAgICAgaGl0cywgYnJhbmNoX2Vycm9ycywgcmVyYW5rX2FwcGxpZWQsIHJlcmFua19lcnJvciA9IF9ydW5fZW5zZW1ibGVfbW9kZShyYXdfcXVlcnksIHRvcF9rKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIGhpdHMsIGJyYW5jaF9lcnJvcnMsIHJlcmFua19hcHBsaWVkLCByZXJhbmtfZXJyb3IgPSBfcnVuX3NpbmdsZV9tb2RlKHJhd19xdWVyeSwgdG9wX2spCgogICAgICAgIHJlc3VsdF90ZXh0ID0gX2Zvcm1hdF9mdXNlZF9yZXN1bHRzKAogICAgICAgICAgICBxdWVyeT1yYXdfcXVlcnksCiAgICAgICAgICAgIG1vZGU9c2VhcmNoX21vZGUsCiAgICAgICAgICAgIGhpdHM9aGl0cywKICAgICAgICAgICAgYnJhbmNoX2Vycm9ycz1icmFuY2hfZXJyb3JzLAogICAgICAgICAgICByZXJhbmtfYXBwbGllZD1yZXJhbmtfYXBwbGllZCwKICAgICAgICAgICAgcmVyYW5rX2Vycm9yPXJlcmFua19lcnJvciwKICAgICAgICApCgogICAgICAgIF9sb2dfdG9vbF91c2FnZSgKICAgICAgICAgICAgZXZlbnQ9InRvb2xfY2FsbF9lbmQiLAogICAgICAgICAgICB0b29sX25hbWU9InNlbWFudGljX3NlYXJjaF9jb2RlIiwKICAgICAgICAgICAgZGV0YWlscz17CiAgICAgICAgICAgICAgICAic3RhdHVzIjogIm9rIiwKICAgICAgICAgICAgICAgICJtb2RlIjogc2VhcmNoX21vZGUsCiAgICAgICAgICAgICAgICAicmVzdWx0X2NvdW50IjogbGVuKGhpdHMpLAogICAgICAgICAgICAgICAgImJyYW5jaF9lcnJvcnMiOiBsZW4oYnJhbmNoX2Vycm9ycyksCiAgICAgICAgICAgICAgICAicmVyYW5rX2FwcGxpZWQiOiByZXJhbmtfYXBwbGllZCwKICAgICAgICAgICAgfSwKICAgICAgICApCiAgICAgICAgcmV0dXJuIHJlc3VsdF90ZXh0CiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgX2xvZ190b29sX3VzYWdlKAogICAgICAgICAgICBldmVudD0idG9vbF9jYWxsX2VuZCIsCiAgICAgICAgICAgIHRvb2xfbmFtZT0ic2VtYW50aWNfc2VhcmNoX2NvZGUiLAogICAgICAgICAgICBkZXRhaWxzPXsic3RhdHVzIjogImVycm9yIiwgInJlYXNvbiI6ICJzZWFyY2hfZmFpbGVkIiwgImVycm9yIjogc3RyKGUpLCAibW9kZSI6IHNlYXJjaF9tb2RlfSwKICAgICAgICApCiAgICAgICAgcmV0dXJuIGYiRXJybyBhbyBleGVjdXRhciBidXNjYSBzZW3Dom50aWNhICh7c2VhcmNoX21vZGV9KToge2V9IgoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgVG9vbCAyOiB1cGRhdGVfZmlsZV9pbmRleAojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKQG1jcC50b29sKCkKZGVmIHVwZGF0ZV9maWxlX2luZGV4KGZpbGVfcGF0aDogc3RyKSAtPiBzdHI6CiAgICAiIiIKICAgIEF0dWFsaXphIG8gw61uZGljZSBSQUcgcGFyYSB1bSBhcnF1aXZvIGVzcGVjw61maWNvLgoKICAgIE8gYXJxdWl2byDDqSBjbGFzc2lmaWNhZG8gY29tbyBjw7NkaWdvL2RvYyBlIGluZGV4YWRvIG5hIGNvbGXDp8OjbyBhcHJvcHJpYWRhLgogICAgUGFyYSBleHRlbnPDtWVzIGFtYsOtZ3VhcywgaW5kZXhhIGVtIGFtYmFzIGFzIGNvbGXDp8O1ZXMuCiAgICAiIiIKICAgIGZpbGVwYXRoID0gUGF0aChmaWxlX3BhdGgpLnJlc29sdmUoKQogICAgYWJzX3BhdGggPSBzdHIoZmlsZXBhdGgpCgogICAgX2xvZ190b29sX3VzYWdlKAogICAgICAgIGV2ZW50PSJ0b29sX2NhbGxfc3RhcnQiLAogICAgICAgIHRvb2xfbmFtZT0idXBkYXRlX2ZpbGVfaW5kZXgiLAogICAgICAgIGRldGFpbHM9eyJmaWxlX3BhdGgiOiBhYnNfcGF0aH0sCiAgICApCgogICAgaWYgbm90IGZpbGVwYXRoLmV4aXN0cygpOgogICAgICAgIF9sb2dfdG9vbF91c2FnZSgKICAgICAgICAgICAgZXZlbnQ9InRvb2xfY2FsbF9lbmQiLAogICAgICAgICAgICB0b29sX25hbWU9InVwZGF0ZV9maWxlX2luZGV4IiwKICAgICAgICAgICAgZGV0YWlscz17InN0YXR1cyI6ICJlcnJvciIsICJyZWFzb24iOiAiZmlsZV9ub3RfZm91bmQiLCAiZmlsZV9wYXRoIjogYWJzX3BhdGh9LAogICAgICAgICkKICAgICAgICByZXR1cm4gZiJFcnJvOiBhcnF1aXZvIG7Do28gZW5jb250cmFkbzoge2ZpbGVwYXRofSIKCiAgICBpZiBub3QgZmlsZXBhdGguaXNfZmlsZSgpOgogICAgICAgIF9sb2dfdG9vbF91c2FnZSgKICAgICAgICAgICAgZXZlbnQ9InRvb2xfY2FsbF9lbmQiLAogICAgICAgICAgICB0b29sX25hbWU9InVwZGF0ZV9maWxlX2luZGV4IiwKICAgICAgICAgICAgZGV0YWlscz17InN0YXR1cyI6ICJlcnJvciIsICJyZWFzb24iOiAibm90X2FfZmlsZSIsICJmaWxlX3BhdGgiOiBhYnNfcGF0aH0sCiAgICAgICAgKQogICAgICAgIHJldHVybiBmIkVycm86IG8gY2FtaW5obyBuw6NvIGFwb250YSBwYXJhIHVtIGFycXVpdm86IHtmaWxlcGF0aH0iCgogICAgaWYgZmlsZXBhdGguc3RhdCgpLnN0X3NpemUgPiBNQVhfRklMRV9TSVpFX0JZVEVTOgogICAgICAgIF9sb2dfdG9vbF91c2FnZSgKICAgICAgICAgICAgZXZlbnQ9InRvb2xfY2FsbF9lbmQiLAogICAgICAgICAgICB0b29sX25hbWU9InVwZGF0ZV9maWxlX2luZGV4IiwKICAgICAgICAgICAgZGV0YWlscz17InN0YXR1cyI6ICJlcnJvciIsICJyZWFzb24iOiAiZmlsZV90b29fbGFyZ2UiLCAiZmlsZV9wYXRoIjogYWJzX3BhdGh9LAogICAgICAgICkKICAgICAgICByZXR1cm4gZiJFcnJvOiBhcnF1aXZvIG11aXRvIGdyYW5kZSAoPntNQVhfRklMRV9TSVpFX0JZVEVTIC8vIDEwMjR9S0IpOiB7ZmlsZXBhdGh9IgoKICAgIHNwbGl0dGVyID0gZ2V0X3NwbGl0dGVyKCkKICAgIHRhcmdldHMgPSBfY2xhc3NpZnlfZmlsZV90YXJnZXRzKGZpbGVwYXRoKQoKICAgIGRlbGV0ZWRfcGVyX2JyYW5jaCwgZGVsZXRpb25fZXJyb3JzID0gX3JlbW92ZV9maWxlX2Zyb21fYWxsX2NvbGxlY3Rpb25zKGFic19wYXRoKQoKICAgIGluc2VydGVkX3Blcl9icmFuY2g6IGRpY3Rbc3RyLCBpbnRdID0ge30KICAgIGluZGV4X2Vycm9yczogbGlzdFtzdHJdID0gW10KICAgIGZvciBicmFuY2ggaW4gdGFyZ2V0czoKICAgICAgICB0cnk6CiAgICAgICAgICAgIGluc2VydGVkID0gX2luZGV4X3NpbmdsZV9maWxlX2Zvcl9icmFuY2goCiAgICAgICAgICAgICAgICBmaWxlcGF0aCwKICAgICAgICAgICAgICAgIGJyYW5jaCwKICAgICAgICAgICAgICAgIHNwbGl0dGVyLAogICAgICAgICAgICAgICAgZGVsZXRlX2V4aXN0aW5nPUZhbHNlLCAgIyBqw6EgcmVtb3ZpZG8gZW0gdG9kYXMgYXMgY29sZcOnw7VlcyBhY2ltYQogICAgICAgICAgICApCiAgICAgICAgICAgIGluc2VydGVkX3Blcl9icmFuY2hbYnJhbmNoLmtleV0gPSBpbnNlcnRlZAogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgaW5kZXhfZXJyb3JzLmFwcGVuZChmInticmFuY2gua2V5fToge2V9IikKCiAgICBzdWNjZXNzX2JyYW5jaGVzID0gW2sgZm9yIGssIHYgaW4gaW5zZXJ0ZWRfcGVyX2JyYW5jaC5pdGVtcygpIGlmIHYgPiAwXQoKICAgIGRldGFpbHMgPSB7CiAgICAgICAgInN0YXR1cyI6ICJvayIgaWYgc3VjY2Vzc19icmFuY2hlcyBlbHNlICJlcnJvciIsCiAgICAgICAgImZpbGVfcGF0aCI6IGFic19wYXRoLAogICAgICAgICJ0YXJnZXRzIjogW2Iua2V5IGZvciBiIGluIHRhcmdldHNdLAogICAgICAgICJkZWxldGVkX3Blcl9icmFuY2giOiBkZWxldGVkX3Blcl9icmFuY2gsCiAgICAgICAgImluc2VydGVkX3Blcl9icmFuY2giOiBpbnNlcnRlZF9wZXJfYnJhbmNoLAogICAgICAgICJkZWxldGlvbl9lcnJvcnMiOiBsZW4oZGVsZXRpb25fZXJyb3JzKSwKICAgICAgICAiaW5kZXhfZXJyb3JzIjogbGVuKGluZGV4X2Vycm9ycyksCiAgICB9CiAgICBfbG9nX3Rvb2xfdXNhZ2UoZXZlbnQ9InRvb2xfY2FsbF9lbmQiLCB0b29sX25hbWU9InVwZGF0ZV9maWxlX2luZGV4IiwgZGV0YWlscz1kZXRhaWxzKQoKICAgIGlmIG5vdCBzdWNjZXNzX2JyYW5jaGVzIGFuZCBpbmRleF9lcnJvcnM6CiAgICAgICAgcmV0dXJuICgKICAgICAgICAgICAgIkVycm86IG7Do28gZm9pIHBvc3PDrXZlbCByZWluZGV4YXIgbyBhcnF1aXZvIGVtIG5lbmh1bWEgY29sZcOnw6NvLlxuIgogICAgICAgICAgICBmIkFycXVpdm86IHtmaWxlcGF0aH1cbiIKICAgICAgICAgICAgIkZhbGhhczogIiArICIgfCAiLmpvaW4oaW5kZXhfZXJyb3JzKQogICAgICAgICkKCiAgICBsaW5lcyA9IFsKICAgICAgICAiQXJxdWl2byByZWluZGV4YWRvLiIsCiAgICAgICAgZiIgIEFycXVpdm8gOiB7ZmlsZXBhdGh9IiwKICAgICAgICBmIiAgQ29sZcOnw7VlcyBhbHZvOiB7W2IuY29sbGVjdGlvbl9uYW1lIGZvciBiIGluIHRhcmdldHNdfSIsCiAgICAgICAgZiIgIFJlbW/Dp8O1ZXMgcG9yIGNvbGXDp8Ojbzoge2RlbGV0ZWRfcGVyX2JyYW5jaH0iLAogICAgICAgIGYiICBJbnNlcsOnw7VlcyBwb3IgY29sZcOnw6NvOiB7aW5zZXJ0ZWRfcGVyX2JyYW5jaH0iLAogICAgXQogICAgaWYgZGVsZXRpb25fZXJyb3JzOgogICAgICAgIGxpbmVzLmFwcGVuZCgiICBBdmlzb3MgbmEgcmVtb8Onw6NvOiAiICsgIiB8ICIuam9pbihkZWxldGlvbl9lcnJvcnMpKQogICAgaWYgaW5kZXhfZXJyb3JzOgogICAgICAgIGxpbmVzLmFwcGVuZCgiICBBdmlzb3MgbmEgaW5kZXhhw6fDo286ICIgKyAiIHwgIi5qb2luKGluZGV4X2Vycm9ycykpCiAgICByZXR1cm4gIlxuIi5qb2luKGxpbmVzKQoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgVG9vbCAzOiBkZWxldGVfZmlsZV9pbmRleAojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKQG1jcC50b29sKCkKZGVmIGRlbGV0ZV9maWxlX2luZGV4KGZpbGVfcGF0aDogc3RyKSAtPiBzdHI6CiAgICAiIiIKICAgIFJlbW92ZSB1bSBhcnF1aXZvIGRvIMOtbmRpY2UgZW0gdG9kYXMgYXMgY29sZcOnw7VlcyBnZXJlbmNpYWRhcy4KICAgICIiIgogICAgZmlsZXBhdGggPSBQYXRoKGZpbGVfcGF0aCkucmVzb2x2ZSgpCiAgICBhYnNfcGF0aCA9IHN0cihmaWxlcGF0aCkKCiAgICBfbG9nX3Rvb2xfdXNhZ2UoCiAgICAgICAgZXZlbnQ9InRvb2xfY2FsbF9zdGFydCIsCiAgICAgICAgdG9vbF9uYW1lPSJkZWxldGVfZmlsZV9pbmRleCIsCiAgICAgICAgZGV0YWlscz17ImZpbGVfcGF0aCI6IGFic19wYXRofSwKICAgICkKCiAgICBkZWxldGVkX3Blcl9icmFuY2gsIGVycm9ycyA9IF9yZW1vdmVfZmlsZV9mcm9tX2FsbF9jb2xsZWN0aW9ucyhhYnNfcGF0aCkKICAgIHRvdGFsX2RlbGV0ZWQgPSBzdW0oZGVsZXRlZF9wZXJfYnJhbmNoLnZhbHVlcygpKQoKICAgIF9sb2dfdG9vbF91c2FnZSgKICAgICAgICBldmVudD0idG9vbF9jYWxsX2VuZCIsCiAgICAgICAgdG9vbF9uYW1lPSJkZWxldGVfZmlsZV9pbmRleCIsCiAgICAgICAgZGV0YWlscz17CiAgICAgICAgICAgICJzdGF0dXMiOiAib2siIGlmIHRvdGFsX2RlbGV0ZWQgPiAwIGVsc2UgIndhcm5pbmciLAogICAgICAgICAgICAiZmlsZV9wYXRoIjogYWJzX3BhdGgsCiAgICAgICAgICAgICJkZWxldGVkX3Blcl9icmFuY2giOiBkZWxldGVkX3Blcl9icmFuY2gsCiAgICAgICAgICAgICJlcnJvcnMiOiBsZW4oZXJyb3JzKSwKICAgICAgICB9LAogICAgKQoKICAgIGlmIHRvdGFsX2RlbGV0ZWQgPT0gMDoKICAgICAgICBiYXNlID0gZiJOZW5odW0gY2h1bmsgZW5jb250cmFkbyBwYXJhIG8gYXJxdWl2bzoge2Fic19wYXRofSIKICAgICAgICBpZiBlcnJvcnM6CiAgICAgICAgICAgIGJhc2UgKz0gIlxuRmFsaGFzIHBhcmNpYWlzOiAiICsgIiB8ICIuam9pbihlcnJvcnMpCiAgICAgICAgcmV0dXJuIGJhc2UKCiAgICBvdXQgPSBbCiAgICAgICAgIlJlbW92aWRvIGRvIMOtbmRpY2UgY29tIHN1Y2Vzc28uIiwKICAgICAgICBmIiAgQXJxdWl2byA6IHthYnNfcGF0aH0iLAogICAgICAgIGYiICBEZWxlw6fDtWVzIHBvciBjb2xlw6fDo286IHtkZWxldGVkX3Blcl9icmFuY2h9IiwKICAgIF0KICAgIGlmIGVycm9yczoKICAgICAgICBvdXQuYXBwZW5kKCIgIEF2aXNvczogIiArICIgfCAiLmpvaW4oZXJyb3JzKSkKICAgIHJldHVybiAiXG4iLmpvaW4ob3V0KQoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgVG9vbCA0OiBpbmRleF9zcGVjaWZpY19mb2xkZXIKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCkBtY3AudG9vbCgpCmRlZiBpbmRleF9zcGVjaWZpY19mb2xkZXIoZm9sZGVyX3BhdGg6IHN0cikgLT4gc3RyOgogICAgIiIiCiAgICBJbmRleGEgcmVjdXJzaXZhbWVudGUgdW1hIHBhc3RhIGVtIGNvbGXDp8O1ZXMgc2VwYXJhZGFzIHBvciBkb23DrW5pby4KICAgICIiIgogICAgZm9sZGVyID0gUGF0aChmb2xkZXJfcGF0aCkucmVzb2x2ZSgpCgogICAgX2xvZ190b29sX3VzYWdlKAogICAgICAgIGV2ZW50PSJ0b29sX2NhbGxfc3RhcnQiLAogICAgICAgIHRvb2xfbmFtZT0iaW5kZXhfc3BlY2lmaWNfZm9sZGVyIiwKICAgICAgICBkZXRhaWxzPXsiZm9sZGVyX3BhdGgiOiBzdHIoZm9sZGVyKX0sCiAgICApCgogICAgaWYgbm90IGZvbGRlci5leGlzdHMoKToKICAgICAgICBfbG9nX3Rvb2xfdXNhZ2UoCiAgICAgICAgICAgIGV2ZW50PSJ0b29sX2NhbGxfZW5kIiwKICAgICAgICAgICAgdG9vbF9uYW1lPSJpbmRleF9zcGVjaWZpY19mb2xkZXIiLAogICAgICAgICAgICBkZXRhaWxzPXsic3RhdHVzIjogImVycm9yIiwgInJlYXNvbiI6ICJmb2xkZXJfbm90X2ZvdW5kIiwgImZvbGRlcl9wYXRoIjogc3RyKGZvbGRlcil9LAogICAgICAgICkKICAgICAgICByZXR1cm4gZiJFcnJvOiBwYXN0YSBuw6NvIGVuY29udHJhZGE6IHtmb2xkZXJ9IgoKICAgIGlmIG5vdCBmb2xkZXIuaXNfZGlyKCk6CiAgICAgICAgX2xvZ190b29sX3VzYWdlKAogICAgICAgICAgICBldmVudD0idG9vbF9jYWxsX2VuZCIsCiAgICAgICAgICAgIHRvb2xfbmFtZT0iaW5kZXhfc3BlY2lmaWNfZm9sZGVyIiwKICAgICAgICAgICAgZGV0YWlscz17InN0YXR1cyI6ICJlcnJvciIsICJyZWFzb24iOiAibm90X2FfZm9sZGVyIiwgImZvbGRlcl9wYXRoIjogc3RyKGZvbGRlcil9LAogICAgICAgICkKICAgICAgICByZXR1cm4gZiJFcnJvOiBvIGNhbWluaG8gbsOjbyDDqSB1bSBkaXJldMOzcmlvOiB7Zm9sZGVyfSIKCiAgICBzcGxpdHRlciA9IGdldF9zcGxpdHRlcigpCgogICAgcHJvY2Vzc2VkX2ZpbGVzID0gMAogICAgYnJhbmNoX2ZpbGVfY291bnRzID0ge2tleTogMCBmb3Iga2V5IGluIEJSQU5DSF9TUEVDU30KICAgIGJyYW5jaF9jaHVua19jb3VudHMgPSB7a2V5OiAwIGZvciBrZXkgaW4gQlJBTkNIX1NQRUNTfQogICAgZXJyb3JfY291bnQgPSAwCiAgICBlcnJvcl9zYW1wbGVzOiBsaXN0W3N0cl0gPSBbXQoKICAgIGZvciBmaWxlcGF0aCBpbiBfc2Nhbl9mb2xkZXIoZm9sZGVyKToKICAgICAgICBwcm9jZXNzZWRfZmlsZXMgKz0gMQogICAgICAgIHRhcmdldHMgPSBfY2xhc3NpZnlfZmlsZV90YXJnZXRzKGZpbGVwYXRoKQoKICAgICAgICBmb3IgYnJhbmNoIGluIHRhcmdldHM6CiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIG5fY2h1bmtzID0gX2luZGV4X3NpbmdsZV9maWxlX2Zvcl9icmFuY2goZmlsZXBhdGgsIGJyYW5jaCwgc3BsaXR0ZXIpCiAgICAgICAgICAgICAgICBicmFuY2hfZmlsZV9jb3VudHNbYnJhbmNoLmtleV0gKz0gMQogICAgICAgICAgICAgICAgYnJhbmNoX2NodW5rX2NvdW50c1ticmFuY2gua2V5XSArPSBuX2NodW5rcwogICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgICAgICBlcnJvcl9jb3VudCArPSAxCiAgICAgICAgICAgICAgICBpZiBsZW4oZXJyb3Jfc2FtcGxlcykgPCAxMDoKICAgICAgICAgICAgICAgICAgICBlcnJvcl9zYW1wbGVzLmFwcGVuZChmIntmaWxlcGF0aC5uYW1lfSBbe2JyYW5jaC5rZXl9XToge2V9IikKCiAgICBpZiBwcm9jZXNzZWRfZmlsZXMgPT0gMDoKICAgICAgICBfbG9nX3Rvb2xfdXNhZ2UoCiAgICAgICAgICAgIGV2ZW50PSJ0b29sX2NhbGxfZW5kIiwKICAgICAgICAgICAgdG9vbF9uYW1lPSJpbmRleF9zcGVjaWZpY19mb2xkZXIiLAogICAgICAgICAgICBkZXRhaWxzPXsic3RhdHVzIjogIm9rIiwgImZvbGRlcl9wYXRoIjogc3RyKGZvbGRlciksICJmaWxlc19wcm9jZXNzZWQiOiAwLCAiY2h1bmtzIjogMCwgImVycm9ycyI6IDB9LAogICAgICAgICkKICAgICAgICByZXR1cm4gZiJOZW5odW0gYXJxdWl2byBpbmRleMOhdmVsIGVuY29udHJhZG8gZW06IHtmb2xkZXJ9IgoKICAgIHRvdGFsX2NodW5rcyA9IHN1bShicmFuY2hfY2h1bmtfY291bnRzLnZhbHVlcygpKQoKICAgIF9sb2dfdG9vbF91c2FnZSgKICAgICAgICBldmVudD0idG9vbF9jYWxsX2VuZCIsCiAgICAgICAgdG9vbF9uYW1lPSJpbmRleF9zcGVjaWZpY19mb2xkZXIiLAogICAgICAgIGRldGFpbHM9ewogICAgICAgICAgICAic3RhdHVzIjogIm9rIiwKICAgICAgICAgICAgImZvbGRlcl9wYXRoIjogc3RyKGZvbGRlciksCiAgICAgICAgICAgICJmaWxlc19wcm9jZXNzZWQiOiBwcm9jZXNzZWRfZmlsZXMsCiAgICAgICAgICAgICJjaHVua3MiOiB0b3RhbF9jaHVua3MsCiAgICAgICAgICAgICJlcnJvcnMiOiBlcnJvcl9jb3VudCwKICAgICAgICAgICAgImJyYW5jaF9maWxlX2NvdW50cyI6IGJyYW5jaF9maWxlX2NvdW50cywKICAgICAgICAgICAgImJyYW5jaF9jaHVua19jb3VudHMiOiBicmFuY2hfY2h1bmtfY291bnRzLAogICAgICAgIH0sCiAgICApCgogICAgcmVwb3J0ID0gWwogICAgICAgICJJbmRleGHDp8OjbyBkYSBwYXN0YSBjb25jbHXDrWRhLiIsCiAgICAgICAgZiIgIFBhc3RhOiB7Zm9sZGVyfSIsCiAgICAgICAgZiIgIEFycXVpdm9zIHByb2Nlc3NhZG9zOiB7cHJvY2Vzc2VkX2ZpbGVzfSIsCiAgICAgICAgZiIgIFRvdGFsIGRlIGNodW5rczoge3RvdGFsX2NodW5rc30iLAogICAgICAgIGYiICBBcnF1aXZvcyBwb3IgYnJhbmNoOiB7YnJhbmNoX2ZpbGVfY291bnRzfSIsCiAgICAgICAgZiIgIENodW5rcyBwb3IgYnJhbmNoOiB7YnJhbmNoX2NodW5rX2NvdW50c30iLAogICAgXQoKICAgIGlmIGVycm9yX2NvdW50OgogICAgICAgIHJlcG9ydC5hcHBlbmQoZiIgIEVycm9zICh7ZXJyb3JfY291bnR9KToiKQogICAgICAgIGZvciBlcnIgaW4gZXJyb3Jfc2FtcGxlczoKICAgICAgICAgICAgcmVwb3J0LmFwcGVuZChmIiAgICAtIHtlcnJ9IikKICAgICAgICBpZiBlcnJvcl9jb3VudCA+IGxlbihlcnJvcl9zYW1wbGVzKToKICAgICAgICAgICAgcmVwb3J0LmFwcGVuZChmIiAgICAuLi4gZSBtYWlzIHtlcnJvcl9jb3VudCAtIGxlbihlcnJvcl9zYW1wbGVzKX0gZXJyb3MuIikKCiAgICByZXR1cm4gIlxuIi5qb2luKHJlcG9ydCkKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIFBvbnRvIGRlIGVudHJhZGEKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICBsb2cuaW5mbygiSW5pY2lhbmRvIHNlcnZpZG9yIE1DUCBSQUcgKHN0ZGlvKS4uLiIpCiAgICBsb2cuaW5mbygiQ2hyb21hREI6ICVzOiVzIiwgQ0hST01BX0hPU1QsIENIUk9NQV9QT1JUKQogICAgbG9nLmluZm8oCiAgICAgICAgIkNvbGXDp8O1ZXM6ICVzICglcyksICVzICglcykiLAogICAgICAgIENPTExFQ1RJT05fQ09ERV9KSU5BLAogICAgICAgIEJSQU5DSF9TUEVDU1siamluYV9jb2RlIl0ubW9kZWxfaWQsCiAgICAgICAgQ09MTEVDVElPTl9ET0NfQkdFLAogICAgICAgIEJSQU5DSF9TUEVDU1siYmdlX2RvYyJdLm1vZGVsX2lkLAogICAgKQogICAgbG9nLmluZm8oIk1vZG8gcGFkcsOjbyBkZSBidXNjYTogJXMiLCBTRUFSQ0hfTU9ERV9ERUZBVUxUKQogICAgbG9nLmluZm8oIk1vZGVsbyBzaW5nbGUgcGFkcsOjbzogJXMiLCBCUkFOQ0hfU1BFQ1NbREVGQVVMVF9TSU5HTEVfQlJBTkNIX0tFWV0ubW9kZWxfaWQpCiAgICBsb2cuaW5mbygiUXVhbnRpemFjYW8gSmluYTogJXMiLCBKSU5BX1FVQU5USVpBVElPTikKICAgIGxvZy5pbmZvKCJDb25maWcgZGUgdHVuaW5nIGNhcnJlZ2FkYSBkZTogJXMgKGZvdW5kPSVzKSIsIElOREVYRVJfQ09ORklHX1BBVEgsIGJvb2woSU5ERVhFUl9UVU5JTkdfQ09ORklHKSkKICAgIGxvZy5pbmZvKCJFbWJlZGRpbmcgYmF0Y2ggc2l6ZTogJXMiLCBFTUJFRERJTkdfQkFUQ0hfU0laRSkKICAgIGxvZy5pbmZvKCJDaHVuayBwYXJhbXM6IHNpemU9JXMgb3ZlcmxhcD0lcyIsIENIVU5LX1NJWkUsIENIVU5LX09WRVJMQVApCiAgICBsb2cuaW5mbygiUmVyYW5rZXI6ICVzIChlbmFibGVkPSVzLCBxdWFudD0lcykiLCBSRVJBTktfTU9ERUxfSUQsIFJFUkFOS19FTkFCTEVELCBSRVJBTktFUl9RVUFOVElaQVRJT04pCiAgICBsb2cuaW5mbygiUGFzdGEgZGUgbW9kZWxvcyBsb2NhaXM6ICVzIiwgTU9ERUxfRElSKQogICAgbG9nLmluZm8oIlVzbyBNQ1Agc2Vyw6EgcmVnaXN0cmFkbyBlbTogJXMiLCBNQ1BfVVNBR0VfTE9HX1BBVEgpCgogICAgIyBQcsOpLWFxdWVjZSBzb21lbnRlIGNvbmV4w6NvIENocm9tYTsgbW9kZWxvcyBmaWNhbSBsYXp5IHBhcmEgcG91cGFyIFJBTS4KICAgIHRyeToKICAgICAgICBfZ2V0X2Nocm9tYV9jbGllbnQoKQogICAgICAgIGdldF9jaHJvbWFfY29sbGVjdGlvbihDT0xMRUNUSU9OX0NPREVfSklOQSkKICAgICAgICBnZXRfY2hyb21hX2NvbGxlY3Rpb24oQ09MTEVDVElPTl9ET0NfQkdFKQogICAgICAgIGxvZy5pbmZvKCJDb25leMOjbyBDaHJvbWEgaW5pY2lhbGl6YWRhLiBNb2RlbG9zIHNlcsOjbyBjYXJyZWdhZG9zIHNvYiBkZW1hbmRhLiIpCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgbG9nLmVycm9yKCJGYWxoYSBhbyBpbmljaWFsaXphciBDaHJvbWFEQjogJXMiLCBlKQogICAgICAgIGxvZy5lcnJvcigiTyBzZXJ2aWRvciBjb250aW51YXLDoSwgbWFzIGFzIGZlcnJhbWVudGFzIHJldG9ybmFyw6NvIGVycm8gYXTDqSBvIENocm9tYURCIGVzdGFyIGRpc3BvbsOtdmVsLiIpCgogICAgbWNwLnJ1bih0cmFuc3BvcnQ9InN0ZGlvIikK"
|
|
727
|
+
B64_INDEXER="IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwoiIiIKaW5kZXhlcl9mdWxsLnB5IOKAlCBTY3JpcHQgc3RhbmRhbG9uZSBkZSBpbmRleGHDp8OjbyBkbyBSQUcgbG9jYWwuCgpVc286CiAgICBweXRob24gaW5kZXhlcl9mdWxsLnB5IFtjYW1pbmhvX2RvX3Byb2pldG9dCgpTZSBuZW5odW0gY2FtaW5obyBmb3IgcGFzc2FkbywgdXNhIG8gZGlyZXTDs3JpbyBhdHVhbC4KTyBDaHJvbWFEQiBkZXZlIGVzdGFyIHJvZGFuZG8gdmlhIERvY2tlciBlbSBsb2NhbGhvc3Q6ODAwMC4KIiIiCgppbXBvcnQgb3MKaW1wb3J0IHN5cwppbXBvcnQgaGFzaGxpYgppbXBvcnQgYXJncGFyc2UKaW1wb3J0IHNodXRpbAppbXBvcnQgbG9nZ2luZwppbXBvcnQgZ2MKaW1wb3J0IGpzb24KZnJvbSB0aW1lIGltcG9ydCBwZXJmX2NvdW50ZXIsIHRpbWUKZnJvbSBjb2xsZWN0aW9ucy5hYmMgaW1wb3J0IEl0ZXJhdG9yCmZyb20gcGF0aGxpYiBpbXBvcnQgUGF0aApmcm9tIGRhdGFjbGFzc2VzIGltcG9ydCBkYXRhY2xhc3MKZnJvbSBkYXRldGltZSBpbXBvcnQgZGF0ZXRpbWUKZnJvbSB1cmxsaWIucGFyc2UgaW1wb3J0IHVybHBhcnNlCgojIEV2aXRhIGF2aXNvcyAiYWR2aXNvcnkiIHJ1aWRvc29zIGRvIHRyYW5zZm9ybWVycyBubyBmbHV4byBpbnRlcmF0aXZvLgpvcy5lbnZpcm9uLnNldGRlZmF1bHQoIlRSQU5TRk9STUVSU19OT19BRFZJU09SWV9XQVJOSU5HUyIsICIxIikKCgpjbGFzcyBfVG9yY2hEdHlwZVdhcm5pbmdGaWx0ZXIobG9nZ2luZy5GaWx0ZXIpOgogICAgZGVmIGZpbHRlcihzZWxmLCByZWNvcmQ6IGxvZ2dpbmcuTG9nUmVjb3JkKSAtPiBib29sOgogICAgICAgIHJldHVybiAiYHRvcmNoX2R0eXBlYCBpcyBkZXByZWNhdGVkISBVc2UgYGR0eXBlYCBpbnN0ZWFkISIgbm90IGluIHJlY29yZC5nZXRNZXNzYWdlKCkKCgpmb3IgX2xvZ2dlcl9uYW1lIGluICgidHJhbnNmb3JtZXJzLmNvbmZpZ3VyYXRpb25fdXRpbHMiLCAidHJhbnNmb3JtZXJzLm1vZGVsaW5nX3V0aWxzIik6CiAgICBsb2dnaW5nLmdldExvZ2dlcihfbG9nZ2VyX25hbWUpLmFkZEZpbHRlcihfVG9yY2hEdHlwZVdhcm5pbmdGaWx0ZXIoKSkKCmltcG9ydCBjaHJvbWFkYgpmcm9tIHNlbnRlbmNlX3RyYW5zZm9ybWVycyBpbXBvcnQgU2VudGVuY2VUcmFuc2Zvcm1lcgpmcm9tIGxhbmdjaGFpbl90ZXh0X3NwbGl0dGVycyBpbXBvcnQgUmVjdXJzaXZlQ2hhcmFjdGVyVGV4dFNwbGl0dGVyCmZyb20gdHFkbSBpbXBvcnQgdHFkbQpmcm9tIGRvd25sb2FkX21vZGVsX2Zyb21faHVnZ2luZmFjZSBpbXBvcnQgZG93bmxvYWRfbW9kZWxfd2l0aF9mYWxsYmFjawoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBDb25maWd1cmHDp8O1ZXMgZ2xvYmFpcwojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCmRlZiBfZW52X2ludChuYW1lOiBzdHIsIGRlZmF1bHQ6IGludCwgKiwgbWluX3ZhbHVlOiBpbnQgPSAxKSAtPiBpbnQ6CiAgICByYXcgPSBvcy5lbnZpcm9uLmdldChuYW1lKQogICAgaWYgcmF3IGlzIE5vbmU6CiAgICAgICAgcmV0dXJuIG1heChtaW5fdmFsdWUsIGRlZmF1bHQpCiAgICB0cnk6CiAgICAgICAgcmV0dXJuIG1heChtaW5fdmFsdWUsIGludChyYXcpKQogICAgZXhjZXB0IFZhbHVlRXJyb3I6CiAgICAgICAgcmV0dXJuIG1heChtaW5fdmFsdWUsIGRlZmF1bHQpCgoKZGVmIF9lbnZfc3RyKG5hbWU6IHN0ciwgZGVmYXVsdDogc3RyKSAtPiBzdHI6CiAgICByYXcgPSBvcy5lbnZpcm9uLmdldChuYW1lKQogICAgaWYgcmF3IGlzIE5vbmU6CiAgICAgICAgcmV0dXJuIGRlZmF1bHQKICAgIHN0cmlwcGVkID0gcmF3LnN0cmlwKCkKICAgIHJldHVybiBzdHJpcHBlZCBpZiBzdHJpcHBlZCBlbHNlIGRlZmF1bHQKCgpkZWYgX2V4dHJhY3RfY2hyb21hX2VuZHBvaW50X2Zyb21fY29uZmlnKGNvbmZpZ19wYXlsb2FkOiBvYmplY3QpIC0+IHR1cGxlW3N0ciwgc3RyLCBpbnRdOgogICAgc2NoZW1lID0gImh0dHAiCiAgICBob3N0ID0gImxvY2FsaG9zdCIKICAgIHBvcnQgPSA4MDAwCgogICAgZGVmIF9yZWFkX3NjaGVtZShyYXc6IG9iamVjdCkgLT4gTm9uZToKICAgICAgICBub25sb2NhbCBzY2hlbWUKICAgICAgICBpZiBub3QgaXNpbnN0YW5jZShyYXcsIHN0cik6CiAgICAgICAgICAgIHJldHVybgogICAgICAgIGxvd2VyZWQgPSByYXcuc3RyaXAoKS5sb3dlcigpCiAgICAgICAgaWYgbG93ZXJlZCBpbiB7Imh0dHAiLCAiaHR0cHMifToKICAgICAgICAgICAgc2NoZW1lID0gbG93ZXJlZAoKICAgIGRlZiBfcmVhZF9ob3N0KHJhdzogb2JqZWN0KSAtPiBOb25lOgogICAgICAgIG5vbmxvY2FsIHNjaGVtZSwgaG9zdCwgcG9ydAogICAgICAgIGlmIG5vdCBpc2luc3RhbmNlKHJhdywgc3RyKToKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgY2FuZGlkYXRlID0gcmF3LnN0cmlwKCkKICAgICAgICBpZiBub3QgY2FuZGlkYXRlOgogICAgICAgICAgICByZXR1cm4KICAgICAgICBwYXJzZWQgPSB1cmxwYXJzZShjYW5kaWRhdGUgaWYgIjovLyIgaW4gY2FuZGlkYXRlIGVsc2UgZiIvL3tjYW5kaWRhdGV9IikKICAgICAgICBpZiBwYXJzZWQuc2NoZW1lIGluIHsiaHR0cCIsICJodHRwcyJ9OgogICAgICAgICAgICBzY2hlbWUgPSBwYXJzZWQuc2NoZW1lCiAgICAgICAgaWYgcGFyc2VkLmhvc3RuYW1lOgogICAgICAgICAgICBob3N0ID0gcGFyc2VkLmhvc3RuYW1lCiAgICAgICAgZWxpZiAiOi8vIiBub3QgaW4gY2FuZGlkYXRlOgogICAgICAgICAgICBob3N0ID0gY2FuZGlkYXRlLnN0cmlwKCkuc3RyaXAoIi8iKQogICAgICAgIGlmIHBhcnNlZC5wb3J0IGFuZCAxIDw9IHBhcnNlZC5wb3J0IDw9IDY1NTM1OgogICAgICAgICAgICBwb3J0ID0gcGFyc2VkLnBvcnQKCiAgICBkZWYgX3JlYWRfcG9ydChyYXc6IG9iamVjdCkgLT4gTm9uZToKICAgICAgICBub25sb2NhbCBwb3J0CiAgICAgICAgdHJ5OgogICAgICAgICAgICBwYXJzZWQgPSBpbnQoc3RyKHJhdykuc3RyaXAoKSkKICAgICAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgICAgICByZXR1cm4KICAgICAgICBpZiAxIDw9IHBhcnNlZCA8PSA2NTUzNToKICAgICAgICAgICAgcG9ydCA9IHBhcnNlZAoKICAgIGlmIGlzaW5zdGFuY2UoY29uZmlnX3BheWxvYWQsIGRpY3QpOgogICAgICAgIGNocm9tYV9vYmogPSBjb25maWdfcGF5bG9hZC5nZXQoImNocm9tYSIpCiAgICAgICAgaWYgaXNpbnN0YW5jZShjaHJvbWFfb2JqLCBkaWN0KToKICAgICAgICAgICAgX3JlYWRfc2NoZW1lKGNocm9tYV9vYmouZ2V0KCJzY2hlbWUiKSkKICAgICAgICAgICAgX3JlYWRfaG9zdChjaHJvbWFfb2JqLmdldCgiaG9zdCIpKQogICAgICAgICAgICBfcmVhZF9wb3J0KGNocm9tYV9vYmouZ2V0KCJwb3J0IikpCgogICAgICAgICMgQ29tcGF0aWJpbGlkYWRlIGNvbSBmb3JtYXRvcyBmbGF0IGFudGlnb3MuCiAgICAgICAgX3JlYWRfc2NoZW1lKGNvbmZpZ19wYXlsb2FkLmdldCgiQ0hST01BX1NDSEVNRSIpKQogICAgICAgIF9yZWFkX2hvc3QoY29uZmlnX3BheWxvYWQuZ2V0KCJDSFJPTUFfSE9TVCIpKQogICAgICAgIF9yZWFkX3BvcnQoY29uZmlnX3BheWxvYWQuZ2V0KCJDSFJPTUFfUE9SVCIpKQoKICAgIHJldHVybiBzY2hlbWUsIGhvc3QsIHBvcnQKCgpkZWYgX2xvYWRfY2xpX2Nocm9tYV9kZWZhdWx0cygpIC0+IHR1cGxlW3N0ciwgc3RyLCBpbnRdOgogICAgY29uZmlnX3BhdGggPSBQYXRoKAogICAgICAgIG9zLmVudmlyb24uZ2V0KCJPV05fUkFHX0NMSV9DT05GSUdfRklMRSIsIHN0cihQYXRoLmhvbWUoKSAvICIub3duLXJhZy1jbGkuanNvbiIpKQogICAgKS5leHBhbmR1c2VyKCkKICAgIHRyeToKICAgICAgICBpZiBub3QgY29uZmlnX3BhdGguZXhpc3RzKCk6CiAgICAgICAgICAgIHJldHVybiAoImh0dHAiLCAibG9jYWxob3N0IiwgODAwMCkKICAgICAgICBwYXlsb2FkID0ganNvbi5sb2Fkcyhjb25maWdfcGF0aC5yZWFkX3RleHQoZW5jb2Rpbmc9InV0Zi04IikpCiAgICAgICAgcmV0dXJuIF9leHRyYWN0X2Nocm9tYV9lbmRwb2ludF9mcm9tX2NvbmZpZyhwYXlsb2FkKQogICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICByZXR1cm4gKCJodHRwIiwgImxvY2FsaG9zdCIsIDgwMDApCgpfREVGQVVMVF9DSFJPTUFfU0NIRU1FLCBfREVGQVVMVF9DSFJPTUFfSE9TVCwgX0RFRkFVTFRfQ0hST01BX1BPUlQgPSBfbG9hZF9jbGlfY2hyb21hX2RlZmF1bHRzKCkKQ0hST01BX1NDSEVNRSA9IF9lbnZfc3RyKCJNQ1BfQ0hST01BX1NDSEVNRSIsIF9ERUZBVUxUX0NIUk9NQV9TQ0hFTUUpLmxvd2VyKCkKaWYgQ0hST01BX1NDSEVNRSBub3QgaW4geyJodHRwIiwgImh0dHBzIn06CiAgICBDSFJPTUFfU0NIRU1FID0gX0RFRkFVTFRfQ0hST01BX1NDSEVNRQpDSFJPTUFfSE9TVCA9IF9lbnZfc3RyKCJNQ1BfQ0hST01BX0hPU1QiLCBfREVGQVVMVF9DSFJPTUFfSE9TVCkKQ0hST01BX1BPUlQgPSBfZW52X2ludCgiTUNQX0NIUk9NQV9QT1JUIiwgX0RFRkFVTFRfQ0hST01BX1BPUlQsIG1pbl92YWx1ZT0xKQpDSFJPTUFfU1NMID0gQ0hST01BX1NDSEVNRSA9PSAiaHR0cHMiCkNPTExFQ1RJT05fQ09ERV9KSU5BID0gImNvZGVfdmVjdG9yc19qaW5hIgpDT0xMRUNUSU9OX0RPQ19CR0UgPSAiZG9jX3ZlY3RvcnNfYmdlIgoKIyBQYXN0YXMgZSBleHRlbnPDtWVzIGlnbm9yYWRhcyBkdXJhbnRlIGEgdmFycmVkdXJhCklHTk9SRURfRElSUyA9IHsKICAgICIuZ2l0IiwgIm5vZGVfbW9kdWxlcyIsICJfX3B5Y2FjaGVfXyIsICIudmVudiIsICJ2ZW52IiwgImVudiIsCiAgICAiZGlzdCIsICJidWlsZCIsICJvdXQiLCAiLm5leHQiLCAiLm51eHQiLCAiLmNhY2hlIiwgImNvdmVyYWdlIiwKICAgICIucHl0ZXN0X2NhY2hlIiwgIi5teXB5X2NhY2hlIiwgIi5ydWZmX2NhY2hlIiwgInRhcmdldCIsICJiaW4iLCAib2JqIiwKICAgICIuaWRlYSIsICIudnNjb2RlIiwgIi5EU19TdG9yZSIsICJ2ZW5kb3IiLCAidG1wIiwgInRlbXAiLCAibG9ncyIsCiAgICAiLnJhZ19kYiIsCn0KCklHTk9SRURfRVhURU5TSU9OUyA9IHsKICAgICMgQmluw6FyaW9zIGUgaW1hZ2VucwogICAgIi5wbmciLCAiLmpwZyIsICIuanBlZyIsICIuZ2lmIiwgIi5zdmciLCAiLmljbyIsICIud2VicCIsICIuYm1wIiwKICAgICIubXA0IiwgIi5tcDMiLCAiLndhdiIsICIub2dnIiwgIi5hdmkiLCAiLm1vdiIsCiAgICAjIFBhY290ZXMgZSBjb21waWxhZG9zCiAgICAiLnppcCIsICIudGFyIiwgIi5neiIsICIucmFyIiwgIi43eiIsICIuamFyIiwgIi53YXIiLCAiLmVhciIsCiAgICAiLnB5YyIsICIucHlvIiwgIi5zbyIsICIuZGxsIiwgIi5leGUiLCAiLmJpbiIsCiAgICAjIExvY2tmaWxlcyBlIGdlcmFkb3MKICAgICIubG9jayIsICIuc3VtIiwKICAgICMgQmFuY28gZGUgZGFkb3MKICAgICIuc3FsaXRlIiwgIi5kYiIsICIuc3FsaXRlMyIsCiAgICAjIEZvbnRlcwogICAgIi50dGYiLCAiLndvZmYiLCAiLndvZmYyIiwgIi5lb3QiLAogICAgIyBQREYvRG9jdW1lbnRvcyBiaW7DoXJpb3MKICAgICIucGRmIiwgIi5kb2N4IiwgIi54bHN4IiwgIi5wcHR4IiwKfQoKQ09ERV9FWFRFTlNJT05TID0gewogICAgIi5weSIsICIuanMiLCAiLnRzIiwgIi50c3giLCAiLmpzeCIsICIuamF2YSIsICIuYyIsICIuaCIsICIuY3BwIiwgIi5ocHAiLAogICAgIi5nbyIsICIucnMiLCAiLnJiIiwgIi5waHAiLCAiLmNzIiwgIi5zd2lmdCIsICIua3QiLCAiLmt0cyIsICIuc2NhbGEiLCAiLnNxbCIsCiAgICAiLnNoIiwgIi5iYXNoIiwgIi56c2giLCAiLnBzMSIsICIueWFtbCIsICIueW1sIiwgIi50b21sIiwgIi5pbmkiLCAiLmNvbmYiLAogICAgIi5qc29uIiwgIi54bWwiLCAiLmh0bWwiLCAiLmNzcyIsICIuc2NzcyIsICIuc2FzcyIsICIudnVlIiwgIi5zdmVsdGUiLCAiLmRhcnQiLAogICAgIi5sdWEiLCAiLnIiLCAiLm0iLCAiLm1tIiwKfQoKRE9DX0VYVEVOU0lPTlMgPSB7CiAgICAiLm1kIiwgIi5tZHgiLCAiLnJzdCIsICIudHh0IiwgIi5hZG9jIiwgIi5vcmciLCAiLnRleCIsICIuY3N2IiwKfQoKIyBUYW1hbmhvIG3DoXhpbW8gZGUgYXJxdWl2byAoZXZpdGEgaW5kZXhhciBhcnF1aXZvcyBlbm9ybWVzIGdlcmFkb3MpCk1BWF9GSUxFX1NJWkVfQllURVMgPSA1MDAgKiAxMDI0ICAjIDUwMCBLQgoKIyBQYXLDom1ldHJvcyBkbyBzcGxpdHRlciBlIGJhdGNoIChwZXJmaWwgbG93LW1lbW9yeSBwb3IgcGFkcsOjbykuCkNIVU5LX1NJWkUgPSBfZW52X2ludCgiTUNQX0NIVU5LX1NJWkUiLCAzMDAwLCBtaW5fdmFsdWU9MjU2KQpDSFVOS19PVkVSTEFQID0gbWluKENIVU5LX1NJWkUgLSAxLCBfZW52X2ludCgiTUNQX0NIVU5LX09WRVJMQVAiLCA0MDAsIG1pbl92YWx1ZT0wKSkKRU1CRURESU5HX0JBVENIX1NJWkUgPSBfZW52X2ludCgiTUNQX0VNQkVERElOR19CQVRDSF9TSVpFIiwgNCwgbWluX3ZhbHVlPTEpCkRFRkFVTFRfUEVSRl9QUk9GSUxFID0gImF1dG90dW5lIgpJTkRFWEVSX0NPTkZJR19QQVRIID0gUGF0aCgKICAgIG9zLmVudmlyb24uZ2V0KAogICAgICAgICJNQ1BfSU5ERVhFUl9DT05GSUdfRklMRSIsCiAgICAgICAgc3RyKFBhdGguaG9tZSgpIC8gIi5jYWNoZSIgLyAib3duLXJhZy1jbGkiIC8gImluZGV4ZXJfdHVuaW5nLmpzb24iKSwKICAgICkKKS5leHBhbmR1c2VyKCkKCiMgTW9kZWxvIGRlIGVtYmVkZGluZ3MgKHJvZGEgbmEgQ1BVKQpKSU5BX1YzX0VNQkVERElOR19NT0RFTCA9ICJqaW5hYWkvamluYS1lbWJlZGRpbmdzLXYzIgpKSU5BX1YyX0VNQkVERElOR19NT0RFTCA9ICJqaW5hYWkvamluYS1lbWJlZGRpbmdzLXYyLWJhc2UtY29kZSIKQkdFX0VNQkVERElOR19NT0RFTCA9ICJCQUFJL2JnZS1tMyIKREVGQVVMVF9FTUJFRERJTkdfTU9ERUxfQ0hPSUNFID0gImppbmEiCkRFRkFVTFRfSklOQV9RVUFOVElaQVRJT04gPSAiZHluYW1pYy1pbnQ4IgpNT0RFTF9DQUNIRV9CQVNFX0RJUiA9IFBhdGgoCiAgICBvcy5lbnZpcm9uLmdldCgiTUNQX01PREVMX0RJUiIsIHN0cihQYXRoLmhvbWUoKSAvICIuY2FjaGUiIC8gIm93bi1yYWctY2xpIiAvICJtb2RlbHMiKSkKKS5leHBhbmR1c2VyKCkKSklOQV9SRUNPTU1FTkRFRF9SQU1fR0JfREVGQVVMVCA9IDY0CkpJTkFfUkVDT01NRU5ERURfUkFNX0dCX0RZTkFNSUNfSU5UOCA9IDQ4CkpJTkFfUkVDT01NRU5ERURfU1dBUF9HQiA9IDE2CkpJTkFfTUlOX0FWQUlMQUJMRV9SQU1fR0JfSElOVCA9IDEyCgoKZGVmIF9lbnZfYm9vbChuYW1lOiBzdHIsIGRlZmF1bHQ6IGJvb2wgPSBGYWxzZSkgLT4gYm9vbDoKICAgIHJhdyA9IG9zLmVudmlyb24uZ2V0KG5hbWUpCiAgICBpZiByYXcgaXMgTm9uZToKICAgICAgICByZXR1cm4gZGVmYXVsdAogICAgcmV0dXJuIHJhdy5zdHJpcCgpLmxvd2VyKCkgaW4geyIxIiwgInRydWUiLCAieWVzIiwgIm9uIn0KCgpkZWYgX2NsYW1wKHZhbHVlOiBmbG9hdCwgbG93OiBmbG9hdCwgaGlnaDogZmxvYXQpIC0+IGZsb2F0OgogICAgcmV0dXJuIG1heChsb3csIG1pbihoaWdoLCB2YWx1ZSkpCgoKZGVmIF9pc19tZW1vcnlfcmVsYXRlZF9lcnJvcihleGM6IEV4Y2VwdGlvbikgLT4gYm9vbDoKICAgIGlmIGlzaW5zdGFuY2UoZXhjLCBNZW1vcnlFcnJvcik6CiAgICAgICAgcmV0dXJuIFRydWUKICAgIG1zZyA9IHN0cihleGMpLmxvd2VyKCkKICAgIG1lbW9yeV9tYXJrZXJzID0gKAogICAgICAgICJvdXQgb2YgbWVtb3J5IiwKICAgICAgICAib29tIiwKICAgICAgICAiY2Fubm90IGFsbG9jYXRlIG1lbW9yeSIsCiAgICAgICAgInN0ZDo6YmFkX2FsbG9jIiwKICAgICAgICAiYmFkIGFsbG9jIiwKICAgICAgICAiaW5zdWZmaWNpZW50IG1lbW9yeSIsCiAgICApCiAgICByZXR1cm4gYW55KG1hcmtlciBpbiBtc2cgZm9yIG1hcmtlciBpbiBtZW1vcnlfbWFya2VycykKCgpkZWYgX2lzX2RpbWVuc2lvbl9taXNtYXRjaF9lcnJvcihleGM6IEV4Y2VwdGlvbikgLT4gYm9vbDoKICAgIG1zZyA9IHN0cihleGMpLmxvd2VyKCkKICAgIHJldHVybiAoCiAgICAgICAgImV4cGVjdGluZyBlbWJlZGRpbmcgd2l0aCBkaW1lbnNpb24iIGluIG1zZwogICAgICAgIG9yICgiZW1iZWRkaW5nIiBpbiBtc2cgYW5kICJkaW1lbnNpb24iIGluIG1zZyBhbmQgImdvdCIgaW4gbXNnKQogICAgKQoKCmRlZiBfZm9ybWF0X2V4Y2VwdGlvbihleGM6IEV4Y2VwdGlvbikgLT4gc3RyOgogICAgbWVzc2FnZSA9IHN0cihleGMpLnN0cmlwKCkKICAgIGlmIG1lc3NhZ2U6CiAgICAgICAgcmV0dXJuIG1lc3NhZ2UKICAgIHJldHVybiByZXByKGV4YykKCgpAZGF0YWNsYXNzKGZyb3plbj1UcnVlKQpjbGFzcyBJbmRleFRhcmdldDoKICAgIG1vZGVsX2Nob2ljZTogc3RyCiAgICBjb2xsZWN0aW9uX25hbWU6IHN0cgogICAgbGFiZWw6IHN0cgoKCmRlZiBfcmVzb2x2ZV9tb2RlbF9pZChtb2RlbF9jaG9pY2U6IHN0cikgLT4gc3RyOgogICAgaWYgbW9kZWxfY2hvaWNlID09ICJqaW5hIjoKICAgICAgICByZXR1cm4gSklOQV9WM19FTUJFRERJTkdfTU9ERUwKICAgIGlmIG1vZGVsX2Nob2ljZSA9PSAiamluYS12MiI6CiAgICAgICAgcmV0dXJuIEpJTkFfVjJfRU1CRURESU5HX01PREVMCiAgICBpZiBtb2RlbF9jaG9pY2UgPT0gImJnZSI6CiAgICAgICAgcmV0dXJuIEJHRV9FTUJFRERJTkdfTU9ERUwKICAgIHJhaXNlIFZhbHVlRXJyb3IoZiJNb2RlbG8gbsOjbyBzdXBvcnRhZG86IHttb2RlbF9jaG9pY2V9IikKCgpkZWYgX3Jlc29sdmVfZmFsbGJhY2tfbW9kZWxfaWQobW9kZWxfY2hvaWNlOiBzdHIpIC0+IHN0cjoKICAgIHJldHVybiBCR0VfRU1CRURESU5HX01PREVMCgoKZGVmIF9kZXNjcmliZV9lbWJlZGRpbmdfY2hvaWNlKG1vZGVsX2Nob2ljZTogc3RyKSAtPiBzdHI6CiAgICBpZiBtb2RlbF9jaG9pY2UgPT0gImppbmEiOgogICAgICAgIHJldHVybiBmImppbmEgKHtKSU5BX1YzX0VNQkVERElOR19NT0RFTH0pIgogICAgaWYgbW9kZWxfY2hvaWNlID09ICJiZ2UiOgogICAgICAgIHJldHVybiBmImJnZSAoe0JHRV9FTUJFRERJTkdfTU9ERUx9KSIKICAgIGlmIG1vZGVsX2Nob2ljZSA9PSAiaHlicmlkIjoKICAgICAgICByZXR1cm4gZiJoeWJyaWQgKHtKSU5BX1YyX0VNQkVERElOR19NT0RFTH0gKyB7QkdFX0VNQkVERElOR19NT0RFTH0pIgogICAgcmV0dXJuIG1vZGVsX2Nob2ljZQoKCmRlZiBfcmVzb2x2ZV9pbmRleF90YXJnZXRzKG1vZGVsX2Nob2ljZTogc3RyKSAtPiBsaXN0W0luZGV4VGFyZ2V0XToKICAgIGlmIG1vZGVsX2Nob2ljZSA9PSAiamluYSI6CiAgICAgICAgcmV0dXJuIFsKICAgICAgICAgICAgSW5kZXhUYXJnZXQoCiAgICAgICAgICAgICAgICBtb2RlbF9jaG9pY2U9ImppbmEiLAogICAgICAgICAgICAgICAgY29sbGVjdGlvbl9uYW1lPUNPTExFQ1RJT05fQ09ERV9KSU5BLAogICAgICAgICAgICAgICAgbGFiZWw9IkNvZGUvSmluYSIsCiAgICAgICAgICAgICkKICAgICAgICBdCiAgICBpZiBtb2RlbF9jaG9pY2UgPT0gImJnZSI6CiAgICAgICAgcmV0dXJuIFsKICAgICAgICAgICAgSW5kZXhUYXJnZXQoCiAgICAgICAgICAgICAgICBtb2RlbF9jaG9pY2U9ImJnZSIsCiAgICAgICAgICAgICAgICBjb2xsZWN0aW9uX25hbWU9Q09MTEVDVElPTl9ET0NfQkdFLAogICAgICAgICAgICAgICAgbGFiZWw9IkRvYy9CR0UiLAogICAgICAgICAgICApCiAgICAgICAgXQogICAgaWYgbW9kZWxfY2hvaWNlID09ICJoeWJyaWQiOgogICAgICAgIHJldHVybiBbCiAgICAgICAgICAgIEluZGV4VGFyZ2V0KAogICAgICAgICAgICAgICAgbW9kZWxfY2hvaWNlPSJqaW5hLXYyIiwKICAgICAgICAgICAgICAgIGNvbGxlY3Rpb25fbmFtZT1DT0xMRUNUSU9OX0NPREVfSklOQSwKICAgICAgICAgICAgICAgIGxhYmVsPSJDb2RlL0ppbmEgdjIiLAogICAgICAgICAgICApLAogICAgICAgICAgICBJbmRleFRhcmdldCgKICAgICAgICAgICAgICAgIG1vZGVsX2Nob2ljZT0iYmdlIiwKICAgICAgICAgICAgICAgIGNvbGxlY3Rpb25fbmFtZT1DT0xMRUNUSU9OX0RPQ19CR0UsCiAgICAgICAgICAgICAgICBsYWJlbD0iRG9jL0JHRSIsCiAgICAgICAgICAgICksCiAgICAgICAgXQogICAgcmFpc2UgVmFsdWVFcnJvcihmIk1vZGVsbyBuw6NvIHN1cG9ydGFkbzoge21vZGVsX2Nob2ljZX0iKQoKCmRlZiBfY2xhc3NpZnlfZmlsZV90YXJnZXRzKGZpbGVwYXRoOiBQYXRoLCBtb2RlbF9jaG9pY2U6IHN0cikgLT4gc2V0W3N0cl06CiAgICBpZiBtb2RlbF9jaG9pY2UgIT0gImh5YnJpZCI6CiAgICAgICAgcmV0dXJuIHttb2RlbF9jaG9pY2V9CgogICAgc3VmZml4ID0gZmlsZXBhdGguc3VmZml4Lmxvd2VyKCkKICAgIGlzX2NvZGUgPSBzdWZmaXggaW4gQ09ERV9FWFRFTlNJT05TCiAgICBpc19kb2MgPSBzdWZmaXggaW4gRE9DX0VYVEVOU0lPTlMKCiAgICBpZiBpc19jb2RlIGFuZCBub3QgaXNfZG9jOgogICAgICAgIHJldHVybiB7ImppbmEtdjIifQogICAgaWYgaXNfZG9jIGFuZCBub3QgaXNfY29kZToKICAgICAgICByZXR1cm4geyJiZ2UifQoKICAgICMgRXh0ZW5zw6NvIGRlc2NvbmhlY2lkYS9hbWLDrWd1YTogaW5kZXhhIG5vcyBkb2lzIHJhbW9zIHBhcmEgbWFudGVyIHJlY2FsbC4KICAgIHJldHVybiB7ImppbmEtdjIiLCAiYmdlIn0KCgpkZWYgX21vZGVsX2NhY2hlX2RpcihiYXNlX2RpcjogUGF0aCwgbW9kZWxfaWQ6IHN0cikgLT4gUGF0aDoKICAgIHNhZmVfbmFtZSA9IG1vZGVsX2lkLnJlcGxhY2UoIi8iLCAiX18iKS5yZXBsYWNlKCI6IiwgIl8iKQogICAgcmV0dXJuIGJhc2VfZGlyIC8gc2FmZV9uYW1lCgoKZGVmIF9waWNrX3dpdGhfcHJvbXB0KAogICAgKiwKICAgIGN1cnJlbnRfdmFsdWU6IHN0ciB8IE5vbmUsCiAgICBkZWZhdWx0X3ZhbHVlOiBzdHIsCiAgICB0aXRsZTogc3RyLAogICAgb3B0aW9uczogbGlzdFt0dXBsZVtzdHIsIHN0cl1dLAopIC0+IHN0cjoKICAgIGlmIGN1cnJlbnRfdmFsdWU6CiAgICAgICAgcmV0dXJuIGN1cnJlbnRfdmFsdWUKICAgIGlmIG5vdCBzeXMuc3RkaW4uaXNhdHR5KCk6CiAgICAgICAgcmV0dXJuIGRlZmF1bHRfdmFsdWUKCiAgICBwcmludChmIlxuW0NPTkZJR10ge3RpdGxlfSIpCiAgICBmb3IgaW5kZXgsIChfLCBkZXNjcmlwdGlvbikgaW4gZW51bWVyYXRlKG9wdGlvbnMsIHN0YXJ0PTEpOgogICAgICAgIHByaW50KGYiICB7aW5kZXh9KSB7ZGVzY3JpcHRpb259IikKICAgIHByaW50KGYiICBFbnRlciA9IHBhZHLDo28gKHtkZWZhdWx0X3ZhbHVlfSkiKQoKICAgIGFuc3dlciA9IGlucHV0KCI+IEVzY29saGE6ICIpLnN0cmlwKCkKICAgIGlmIG5vdCBhbnN3ZXI6CiAgICAgICAgcmV0dXJuIGRlZmF1bHRfdmFsdWUKICAgIGlmIGFuc3dlci5pc2RpZ2l0KCk6CiAgICAgICAgaWR4ID0gaW50KGFuc3dlcikgLSAxCiAgICAgICAgaWYgMCA8PSBpZHggPCBsZW4ob3B0aW9ucyk6CiAgICAgICAgICAgIHJldHVybiBvcHRpb25zW2lkeF1bMF0KICAgIGxvd2VyZWQgPSBhbnN3ZXIubG93ZXIoKQogICAgdmFsaWRfa2V5cyA9IHtrIGZvciBrLCBfIGluIG9wdGlvbnN9CiAgICBpZiBsb3dlcmVkIGluIHZhbGlkX2tleXM6CiAgICAgICAgcmV0dXJuIGxvd2VyZWQKICAgIHByaW50KGYiW0FWSVNPXSBPcMOnw6NvIGludsOhbGlkYSAne2Fuc3dlcn0nLiBVc2FuZG8gcGFkcsOjbzoge2RlZmF1bHRfdmFsdWV9IikKICAgIHJldHVybiBkZWZhdWx0X3ZhbHVlCgoKZGVmIHJlc29sdmVfZW1iZWRkaW5nX2NvbmZpZygKICAgIG1vZGVsX2Nob2ljZV9hcmc6IHN0ciB8IE5vbmUsCiAgICBqaW5hX3F1YW50aXphdGlvbl9hcmc6IHN0ciB8IE5vbmUsCiAgICBwZXJzaXN0ZWRfY29uZmlnOiBkaWN0W3N0ciwgb2JqZWN0XSB8IE5vbmUgPSBOb25lLAopIC0+IHR1cGxlW3N0ciwgc3RyXToKICAgIHBlcnNpc3RlZF9jb25maWcgPSBwZXJzaXN0ZWRfY29uZmlnIG9yIHt9CiAgICBtb2RlbF9jaG9pY2VfZnJvbV9jb25maWcgPSBwZXJzaXN0ZWRfY29uZmlnLmdldCgiZW1iZWRkaW5nX21vZGVsIikKICAgIG1vZGVsX2Nob2ljZSA9IG1vZGVsX2Nob2ljZV9hcmcgb3Igb3MuZW52aXJvbi5nZXQoIk1DUF9FTUJFRERJTkdfTU9ERUwiKQogICAgaWYgbm90IG1vZGVsX2Nob2ljZSBhbmQgaXNpbnN0YW5jZShtb2RlbF9jaG9pY2VfZnJvbV9jb25maWcsIHN0cik6CiAgICAgICAgbW9kZWxfY2hvaWNlID0gbW9kZWxfY2hvaWNlX2Zyb21fY29uZmlnCiAgICBpZiBtb2RlbF9jaG9pY2U6CiAgICAgICAgbW9kZWxfY2hvaWNlID0gbW9kZWxfY2hvaWNlLnN0cmlwKCkubG93ZXIoKQogICAgbW9kZWxfY2hvaWNlID0gX3BpY2tfd2l0aF9wcm9tcHQoCiAgICAgICAgY3VycmVudF92YWx1ZT1tb2RlbF9jaG9pY2UsCiAgICAgICAgZGVmYXVsdF92YWx1ZT1ERUZBVUxUX0VNQkVERElOR19NT0RFTF9DSE9JQ0UsCiAgICAgICAgdGl0bGU9IkVzY29saGEgZG8gbW9kZWxvIGRlIGVtYmVkZGluZ3MiLAogICAgICAgIG9wdGlvbnM9WwogICAgICAgICAgICAoCiAgICAgICAgICAgICAgICAiamluYSIsCiAgICAgICAgICAgICAgICBmImppbmEgKHtKSU5BX1YzX0VNQkVERElOR19NT0RFTH0pIC0gZm9jbyBlbSBjw7NkaWdvLiIsCiAgICAgICAgICAgICksCiAgICAgICAgICAgICgKICAgICAgICAgICAgICAgICJiZ2UiLAogICAgICAgICAgICAgICAgZiJiZ2UgKHtCR0VfRU1CRURESU5HX01PREVMfSkgLSBjb250ZcO6ZG8gbWlzdG8uIiwKICAgICAgICAgICAgKSwKICAgICAgICAgICAgKAogICAgICAgICAgICAgICAgImh5YnJpZCIsCiAgICAgICAgICAgICAgICBmImh5YnJpZCAoSmluYSB2MiB7SklOQV9WMl9FTUJFRERJTkdfTU9ERUx9ICsgQkdFKSAtIGR1YXMgY29sZcOnw7Vlcy4iLAogICAgICAgICAgICApLAogICAgICAgIF0sCiAgICApCiAgICBpZiBtb2RlbF9jaG9pY2Ugbm90IGluIHsiamluYSIsICJiZ2UiLCAiaHlicmlkIn06CiAgICAgICAgcHJpbnQoZiJbQVZJU09dIE1DUF9FTUJFRERJTkdfTU9ERUwgaW52w6FsaWRvICd7bW9kZWxfY2hvaWNlfScuIFVzYW5kbyAne0RFRkFVTFRfRU1CRURESU5HX01PREVMX0NIT0lDRX0nLiIpCiAgICAgICAgbW9kZWxfY2hvaWNlID0gREVGQVVMVF9FTUJFRERJTkdfTU9ERUxfQ0hPSUNFCgogICAgcXVhbnRpemF0aW9uX2Zyb21fY29uZmlnID0gcGVyc2lzdGVkX2NvbmZpZy5nZXQoImppbmFfcXVhbnRpemF0aW9uIikKICAgIGppbmFfcXVhbnRpemF0aW9uID0gamluYV9xdWFudGl6YXRpb25fYXJnIG9yIG9zLmVudmlyb24uZ2V0KCJNQ1BfSklOQV9RVUFOVElaQVRJT04iKQogICAgaWYgbm90IGppbmFfcXVhbnRpemF0aW9uIGFuZCBpc2luc3RhbmNlKHF1YW50aXphdGlvbl9mcm9tX2NvbmZpZywgc3RyKToKICAgICAgICBqaW5hX3F1YW50aXphdGlvbiA9IHF1YW50aXphdGlvbl9mcm9tX2NvbmZpZwogICAgaWYgamluYV9xdWFudGl6YXRpb246CiAgICAgICAgamluYV9xdWFudGl6YXRpb24gPSBqaW5hX3F1YW50aXphdGlvbi5zdHJpcCgpLmxvd2VyKCkucmVwbGFjZSgiXyIsICItIikKCiAgICBpZiBtb2RlbF9jaG9pY2UgPT0gImppbmEiOgogICAgICAgIGppbmFfcXVhbnRpemF0aW9uID0gX3BpY2tfd2l0aF9wcm9tcHQoCiAgICAgICAgICAgIGN1cnJlbnRfdmFsdWU9amluYV9xdWFudGl6YXRpb24sCiAgICAgICAgICAgIGRlZmF1bHRfdmFsdWU9REVGQVVMVF9KSU5BX1FVQU5USVpBVElPTiwKICAgICAgICAgICAgdGl0bGU9IlF1YW50aXphY2FvIGRvIEppbmEgKGFwZW5hcyBwYXJhIENQVSkiLAogICAgICAgICAgICBvcHRpb25zPVsKICAgICAgICAgICAgICAgICgiZGVmYXVsdCIsICJkZWZhdWx0IChzZW0gcXVhbnRpemFjYW8pIC0gbWFpb3IgcXVhbGlkYWRlLCBpbmRleGFjYW8gbWFpcyBsZW50YS4iKSwKICAgICAgICAgICAgICAgICgiZHluYW1pYy1pbnQ4IiwgImR5bmFtaWMtaW50OCAtIGluZGV4YWNhbyBtYWlzIHJhcGlkYSBlIG1lbm9yIHVzbyBkZSBSQU0sIGNvbSBwZXF1ZW5hIHBlcmRhIGRlIHF1YWxpZGFkZS4iKSwKICAgICAgICAgICAgXSwKICAgICAgICApCiAgICAgICAgaWYgamluYV9xdWFudGl6YXRpb24gbm90IGluIHsiZGVmYXVsdCIsICJkeW5hbWljLWludDgifToKICAgICAgICAgICAgcHJpbnQoCiAgICAgICAgICAgICAgICBmIltBVklTT10gTUNQX0pJTkFfUVVBTlRJWkFUSU9OIGludsOhbGlkbyAne2ppbmFfcXVhbnRpemF0aW9ufScuICIKICAgICAgICAgICAgICAgIGYiVXNhbmRvICd7REVGQVVMVF9KSU5BX1FVQU5USVpBVElPTn0nLiIKICAgICAgICAgICAgKQogICAgICAgICAgICBqaW5hX3F1YW50aXphdGlvbiA9IERFRkFVTFRfSklOQV9RVUFOVElaQVRJT04KICAgIGVsc2U6CiAgICAgICAgamluYV9xdWFudGl6YXRpb24gPSAiZGVmYXVsdCIKCiAgICByZXR1cm4gbW9kZWxfY2hvaWNlLCBqaW5hX3F1YW50aXphdGlvbgoKCmRlZiBsb2FkX2luZGV4ZXJfdHVuaW5nX2NvbmZpZyhmb3JjZV9yZWNvbmZpZ3VyZTogYm9vbCkgLT4gZGljdFtzdHIsIG9iamVjdF06CiAgICBpZiBmb3JjZV9yZWNvbmZpZ3VyZToKICAgICAgICByZXR1cm4ge30KICAgIHRyeToKICAgICAgICBpZiBub3QgSU5ERVhFUl9DT05GSUdfUEFUSC5leGlzdHMoKToKICAgICAgICAgICAgcmV0dXJuIHt9CiAgICAgICAgZGF0YSA9IGpzb24ubG9hZHMoSU5ERVhFUl9DT05GSUdfUEFUSC5yZWFkX3RleHQoZW5jb2Rpbmc9InV0Zi04IikpCiAgICAgICAgaWYgaXNpbnN0YW5jZShkYXRhLCBkaWN0KToKICAgICAgICAgICAgcmV0dXJuIGRhdGEKICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgcmV0dXJuIHt9CiAgICByZXR1cm4ge30KCgpkZWYgc2F2ZV9pbmRleGVyX3R1bmluZ19jb25maWcoY29uZmlnOiBkaWN0W3N0ciwgb2JqZWN0XSkgLT4gTm9uZToKICAgIHBheWxvYWQgPSB7CiAgICAgICAgKipjb25maWcsCiAgICAgICAgInVwZGF0ZWRfYXQiOiBpbnQodGltZSgpKSwKICAgIH0KICAgIHRyeToKICAgICAgICBJTkRFWEVSX0NPTkZJR19QQVRILnBhcmVudC5ta2RpcihwYXJlbnRzPVRydWUsIGV4aXN0X29rPVRydWUpCiAgICAgICAgSU5ERVhFUl9DT05GSUdfUEFUSC53cml0ZV90ZXh0KAogICAgICAgICAgICBqc29uLmR1bXBzKHBheWxvYWQsIGVuc3VyZV9hc2NpaT1GYWxzZSwgaW5kZW50PTIpICsgIlxuIiwKICAgICAgICAgICAgZW5jb2Rpbmc9InV0Zi04IiwKICAgICAgICApCiAgICAgICAgcHJpbnQoZiJbQ09ORklHXSBDb25maWd1cmHDp8OjbyBwZXJzaXN0aWRhIGVtOiB7SU5ERVhFUl9DT05GSUdfUEFUSH0iKQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIHByaW50KGYiW0FWSVNPXSBOw6NvIGZvaSBwb3Nzw612ZWwgcGVyc2lzdGlyIGNvbmZpZ3VyYcOnw6NvIGVtIHtJTkRFWEVSX0NPTkZJR19QQVRIfToge19mb3JtYXRfZXhjZXB0aW9uKGUpfSIpCgoKZGVmIHJlc29sdmVfcGVyZl9wcm9maWxlKHBlcmZfcHJvZmlsZV9hcmc6IHN0ciB8IE5vbmUsIHBlcnNpc3RlZF9jb25maWc6IGRpY3Rbc3RyLCBvYmplY3RdKSAtPiBzdHI6CiAgICBwcm9maWxlX2Zyb21fY29uZmlnID0gcGVyc2lzdGVkX2NvbmZpZy5nZXQoInBlcmZfcHJvZmlsZSIpCiAgICBwcm9maWxlID0gcGVyZl9wcm9maWxlX2FyZyBvciBvcy5lbnZpcm9uLmdldCgiTUNQX1BFUkZfUFJPRklMRSIpCiAgICBpZiBub3QgcHJvZmlsZSBhbmQgaXNpbnN0YW5jZShwcm9maWxlX2Zyb21fY29uZmlnLCBzdHIpOgogICAgICAgIHByb2ZpbGUgPSBwcm9maWxlX2Zyb21fY29uZmlnCiAgICBpZiBwcm9maWxlOgogICAgICAgIHByb2ZpbGUgPSBwcm9maWxlLnN0cmlwKCkubG93ZXIoKQoKICAgIHByb2ZpbGUgPSBfcGlja193aXRoX3Byb21wdCgKICAgICAgICBjdXJyZW50X3ZhbHVlPXByb2ZpbGUsCiAgICAgICAgZGVmYXVsdF92YWx1ZT1ERUZBVUxUX1BFUkZfUFJPRklMRSwKICAgICAgICB0aXRsZT0iUGVyZmlsIGRlIHBlcmZvcm1hbmNlIGRhIGluZGV4YcOnw6NvIiwKICAgICAgICBvcHRpb25zPVsKICAgICAgICAgICAgKAogICAgICAgICAgICAgICAgImF1dG90dW5lIiwKICAgICAgICAgICAgICAgICJhdXRvdHVuZSAtIGVxdWlsw61icmlvIChyZWNvbWVuZGFkbykuIiwKICAgICAgICAgICAgKSwKICAgICAgICAgICAgKAogICAgICAgICAgICAgICAgIm1heC1wZXJmb3JtYW5jZSIsCiAgICAgICAgICAgICAgICAibWF4LXBlcmZvcm1hbmNlIC0gbcOheGltbyB0aHJvdWdocHV0IChtYWlzIFJBTSkuIiwKICAgICAgICAgICAgKSwKICAgICAgICBdLAogICAgKQogICAgaWYgcHJvZmlsZSBub3QgaW4geyJhdXRvdHVuZSIsICJtYXgtcGVyZm9ybWFuY2UifToKICAgICAgICBwcmludChmIltBVklTT10gUGVyZmlsIGludsOhbGlkbyAne3Byb2ZpbGV9Jy4gVXNhbmRvICd7REVGQVVMVF9QRVJGX1BST0ZJTEV9Jy4iKQogICAgICAgIHByb2ZpbGUgPSBERUZBVUxUX1BFUkZfUFJPRklMRQogICAgcmV0dXJuIHByb2ZpbGUKCgpkZWYgX3BhcnNlX2NvbmZpZ19pbnQoY29uZmlnOiBkaWN0W3N0ciwgb2JqZWN0XSwga2V5OiBzdHIpIC0+IGludCB8IE5vbmU6CiAgICByYXcgPSBjb25maWcuZ2V0KGtleSkKICAgIGlmIGlzaW5zdGFuY2UocmF3LCBpbnQpOgogICAgICAgIHJldHVybiByYXcKICAgIGlmIGlzaW5zdGFuY2UocmF3LCBzdHIpIGFuZCByYXcuaXNkaWdpdCgpOgogICAgICAgIHJldHVybiBpbnQocmF3KQogICAgcmV0dXJuIE5vbmUKCgpkZWYgX3JlYWRfbWVtaW5mb19naWIoKSAtPiB0dXBsZVtmbG9hdCB8IE5vbmUsIGZsb2F0IHwgTm9uZSwgZmxvYXQgfCBOb25lXToKICAgICIiIlJldG9ybmEgKG1lbV90b3RhbCwgbWVtX2F2YWlsYWJsZSwgc3dhcF90b3RhbCkgZW0gR2lCLCBxdWFuZG8gZGlzcG9uw612ZWwuIiIiCiAgICBtZW1fdG90YWxfa2liOiBpbnQgfCBOb25lID0gTm9uZQogICAgbWVtX2F2YWlsYWJsZV9raWI6IGludCB8IE5vbmUgPSBOb25lCiAgICBzd2FwX3RvdGFsX2tpYjogaW50IHwgTm9uZSA9IE5vbmUKCiAgICB0cnk6CiAgICAgICAgZm9yIGxpbmUgaW4gUGF0aCgiL3Byb2MvbWVtaW5mbyIpLnJlYWRfdGV4dChlbmNvZGluZz0idXRmLTgiKS5zcGxpdGxpbmVzKCk6CiAgICAgICAgICAgIGlmIGxpbmUuc3RhcnRzd2l0aCgiTWVtVG90YWw6Iik6CiAgICAgICAgICAgICAgICBtZW1fdG90YWxfa2liID0gaW50KGxpbmUuc3BsaXQoKVsxXSkKICAgICAgICAgICAgZWxpZiBsaW5lLnN0YXJ0c3dpdGgoIk1lbUF2YWlsYWJsZToiKToKICAgICAgICAgICAgICAgIG1lbV9hdmFpbGFibGVfa2liID0gaW50KGxpbmUuc3BsaXQoKVsxXSkKICAgICAgICAgICAgZWxpZiBsaW5lLnN0YXJ0c3dpdGgoIlN3YXBUb3RhbDoiKToKICAgICAgICAgICAgICAgIHN3YXBfdG90YWxfa2liID0gaW50KGxpbmUuc3BsaXQoKVsxXSkKICAgIGV4Y2VwdCAoT1NFcnJvciwgVmFsdWVFcnJvciwgSW5kZXhFcnJvcik6CiAgICAgICAgcmV0dXJuIE5vbmUsIE5vbmUsIE5vbmUKCiAgICB0b19naWIgPSBsYW1iZGEga2liOiAoa2liIC8gKDEwMjQgKiAxMDI0KSkgaWYga2liIGlzIG5vdCBOb25lIGVsc2UgTm9uZQogICAgcmV0dXJuIHRvX2dpYihtZW1fdG90YWxfa2liKSwgdG9fZ2liKG1lbV9hdmFpbGFibGVfa2liKSwgdG9fZ2liKHN3YXBfdG90YWxfa2liKQoKCmRlZiB3YXJuX2lmX2ppbmFfbWVtb3J5X3Jpc2sobW9kZWxfY2hvaWNlOiBzdHIsIGppbmFfcXVhbnRpemF0aW9uOiBzdHIpIC0+IE5vbmU6CiAgICAiIiJNb3N0cmEgYXZpc28gZGUgcmlzY28gZGUgT09NIHBhcmEgbyBtb2RlbG8gSmluYSBlbSBtw6FxdWluYXMgY29tIHBvdWNhIG1lbcOzcmlhLiIiIgogICAgaWYgbW9kZWxfY2hvaWNlIG5vdCBpbiB7ImppbmEiLCAiaHlicmlkIn06CiAgICAgICAgcmV0dXJuCgogICAgbWVtX3RvdGFsX2dpYiwgbWVtX2F2YWlsYWJsZV9naWIsIHN3YXBfdG90YWxfZ2liID0gX3JlYWRfbWVtaW5mb19naWIoKQogICAgaWYgbWVtX3RvdGFsX2dpYiBpcyBOb25lOgogICAgICAgIHJldHVybgoKICAgIHJlY29tbWVuZGVkX3JhbV9naWIgPSAoCiAgICAgICAgSklOQV9SRUNPTU1FTkRFRF9SQU1fR0JfREVGQVVMVAogICAgICAgIGlmIGppbmFfcXVhbnRpemF0aW9uID09ICJkZWZhdWx0IgogICAgICAgIGVsc2UgSklOQV9SRUNPTU1FTkRFRF9SQU1fR0JfRFlOQU1JQ19JTlQ4CiAgICApCgogICAgcmVhc29uczogbGlzdFtzdHJdID0gW10KICAgIGlmIG1lbV90b3RhbF9naWIgPCByZWNvbW1lbmRlZF9yYW1fZ2liOgogICAgICAgIHJlYXNvbnMuYXBwZW5kKAogICAgICAgICAgICBmIlJBTSB0b3RhbCBkZXRlY3RhZGE6IHttZW1fdG90YWxfZ2liOi4xZn0gR2lCIChyZWNvbWVuZGFkbyA+PSB7cmVjb21tZW5kZWRfcmFtX2dpYn0gR2lCIHBhcmEgSmluYS97amluYV9xdWFudGl6YXRpb259KS4iCiAgICAgICAgKQogICAgaWYgc3dhcF90b3RhbF9naWIgaXMgbm90IE5vbmUgYW5kIHN3YXBfdG90YWxfZ2liIDwgSklOQV9SRUNPTU1FTkRFRF9TV0FQX0dCOgogICAgICAgIHJlYXNvbnMuYXBwZW5kKAogICAgICAgICAgICBmIlN3YXAgZGV0ZWN0YWRhOiB7c3dhcF90b3RhbF9naWI6LjFmfSBHaUIgKHJlY29tZW5kYWRvID49IHtKSU5BX1JFQ09NTUVOREVEX1NXQVBfR0J9IEdpQikuIgogICAgICAgICkKICAgIGlmIG1lbV9hdmFpbGFibGVfZ2liIGlzIG5vdCBOb25lIGFuZCBtZW1fYXZhaWxhYmxlX2dpYiA8IEpJTkFfTUlOX0FWQUlMQUJMRV9SQU1fR0JfSElOVDoKICAgICAgICByZWFzb25zLmFwcGVuZCgKICAgICAgICAgICAgZiJSQU0gbGl2cmUgYXR1YWw6IHttZW1fYXZhaWxhYmxlX2dpYjouMWZ9IEdpQiAoYmFpeG8gcGFyYSBhIGNhcmdhIGluaWNpYWwgZG8gSmluYSkuIgogICAgICAgICkKCiAgICBpZiBub3QgcmVhc29uczoKICAgICAgICByZXR1cm4KCiAgICBwcmludCgiW0FWSVNPXSBBbHRvIHJpc2NvIGRlIE9PTSBjb20gSmluYSBuZXN0YSBtw6FxdWluYS9jYXJnYS4iKQogICAgZm9yIHJlYXNvbiBpbiByZWFzb25zOgogICAgICAgIHByaW50KGYiICAgICAgICAtIHtyZWFzb259IikKICAgIHByaW50KCIgICAgICAgIC0gU2Ugb2NvcnJlciAnS2lsbGVkJyAoZXhpdCAxMzcpLCB1c2UgQkdFOiAtLWVtYmVkZGluZy1tb2RlbCBiZ2UiKQogICAgcHJpbnQoIiAgICAgICAgLSBPdSByb2RlIG8gSmluYSBlbSBtw6FxdWluYSBjb20gbWFpcyBSQU0vc3dhcCBlIG1lbm9zIHByb2Nlc3NvcyBjb25jb3JyZW50ZXMuIikKCgpAZGF0YWNsYXNzKGZyb3plbj1UcnVlKQpjbGFzcyBSdW50aW1lSW5kZXhpbmdQYXJhbXM6CiAgICBjaHVua19zaXplOiBpbnQKICAgIGNodW5rX292ZXJsYXA6IGludAogICAgZW1iZWRkaW5nX2JhdGNoX3NpemU6IGludAogICAgcmVhc29uczogbGlzdFtzdHJdCgoKZGVmIF9yZXNvbHZlX21heF9wZXJmb3JtYW5jZV9wYXJhbXMoCiAgICAqLAogICAgY2h1bmtfc2l6ZV9sb2NrZWQ6IGJvb2wsCiAgICBjaHVua19vdmVybGFwX2xvY2tlZDogYm9vbCwKICAgIGJhdGNoX3NpemVfbG9ja2VkOiBib29sLAogICAgY2h1bmtfc2l6ZTogaW50LAogICAgY2h1bmtfb3ZlcmxhcDogaW50LAogICAgZW1iZWRkaW5nX2JhdGNoX3NpemU6IGludCwKKSAtPiBSdW50aW1lSW5kZXhpbmdQYXJhbXM6CiAgICBtZW1fdG90YWxfZ2liLCBtZW1fYXZhaWxhYmxlX2dpYiwgXyA9IF9yZWFkX21lbWluZm9fZ2liKCkKICAgIHJlYXNvbnMgPSBbCiAgICAgICAgIlBlcmZpbCBzZWxlY2lvbmFkbzogbWF4LXBlcmZvcm1hbmNlLiIsCiAgICAgICAgIk1vZG8gcG9kZSBlbGV2YXIgY29uc2lkZXJhdmVsbWVudGUgbyBjb25zdW1vIGRlIG1lbcOzcmlhIGUgY2F1c2FyIGVuY2VycmFtZW50byBwb3IgT09NIChleGl0IDEzNykuIiwKICAgIF0KCiAgICB0dW5lZF9jaHVua19zaXplID0gY2h1bmtfc2l6ZQogICAgdHVuZWRfY2h1bmtfb3ZlcmxhcCA9IGNodW5rX292ZXJsYXAKICAgIHR1bmVkX2JhdGNoID0gZW1iZWRkaW5nX2JhdGNoX3NpemUKCiAgICBpZiBub3QgY2h1bmtfc2l6ZV9sb2NrZWQ6CiAgICAgICAgaWYgbWVtX3RvdGFsX2dpYiBpcyBub3QgTm9uZSBhbmQgbWVtX3RvdGFsX2dpYiA+PSA2NCBhbmQgKG1lbV9hdmFpbGFibGVfZ2liIG9yIDApID49IDE2OgogICAgICAgICAgICB0dW5lZF9jaHVua19zaXplID0gNzAwMAogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHR1bmVkX2NodW5rX3NpemUgPSA2MDAwCiAgICAgICAgcmVhc29ucy5hcHBlbmQoZiJjaHVua19zaXplIGFqdXN0YWRvIHBhcmEge3R1bmVkX2NodW5rX3NpemV9IG5vIHBlcmZpbCBtYXgtcGVyZm9ybWFuY2UuIikKCiAgICBpZiBub3QgY2h1bmtfb3ZlcmxhcF9sb2NrZWQ6CiAgICAgICAgdHVuZWRfY2h1bmtfb3ZlcmxhcCA9IG1pbih0dW5lZF9jaHVua19zaXplIC0gMSwgbWF4KDMwMCwgaW50KHR1bmVkX2NodW5rX3NpemUgKiAwLjE1KSkpCiAgICAgICAgcmVhc29ucy5hcHBlbmQoZiJjaHVua19vdmVybGFwIGFqdXN0YWRvIHBhcmEge3R1bmVkX2NodW5rX292ZXJsYXB9LiIpCgogICAgaWYgbm90IGJhdGNoX3NpemVfbG9ja2VkOgogICAgICAgIGlmIG1lbV90b3RhbF9naWIgaXMgbm90IE5vbmUgYW5kIG1lbV90b3RhbF9naWIgPj0gNjQgYW5kIChtZW1fYXZhaWxhYmxlX2dpYiBvciAwKSA+PSAxNjoKICAgICAgICAgICAgdHVuZWRfYmF0Y2ggPSAyNAogICAgICAgIGVsaWYgbWVtX3RvdGFsX2dpYiBpcyBub3QgTm9uZSBhbmQgbWVtX3RvdGFsX2dpYiA+PSAzMjoKICAgICAgICAgICAgdHVuZWRfYmF0Y2ggPSAxNgogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHR1bmVkX2JhdGNoID0gMTIKICAgICAgICByZWFzb25zLmFwcGVuZChmImVtYmVkZGluZ19iYXRjaF9zaXplIGFqdXN0YWRvIHBhcmEge3R1bmVkX2JhdGNofS4iKQoKICAgIHJldHVybiBSdW50aW1lSW5kZXhpbmdQYXJhbXMoCiAgICAgICAgY2h1bmtfc2l6ZT10dW5lZF9jaHVua19zaXplLAogICAgICAgIGNodW5rX292ZXJsYXA9dHVuZWRfY2h1bmtfb3ZlcmxhcCwKICAgICAgICBlbWJlZGRpbmdfYmF0Y2hfc2l6ZT1tYXgoMSwgdHVuZWRfYmF0Y2gpLAogICAgICAgIHJlYXNvbnM9cmVhc29ucywKICAgICkKCgpkZWYgX3Jlc29sdmVfYXV0b3R1bmVkX3BhcmFtcygKICAgICosCiAgICBtb2RlbDogU2VudGVuY2VUcmFuc2Zvcm1lciwKICAgIGNodW5rX3NpemVfbG9ja2VkOiBib29sLAogICAgY2h1bmtfb3ZlcmxhcF9sb2NrZWQ6IGJvb2wsCiAgICBiYXRjaF9zaXplX2xvY2tlZDogYm9vbCwKICAgIGNodW5rX3NpemU6IGludCwKICAgIGNodW5rX292ZXJsYXA6IGludCwKICAgIGVtYmVkZGluZ19iYXRjaF9zaXplOiBpbnQsCikgLT4gUnVudGltZUluZGV4aW5nUGFyYW1zOgogICAgcmVhc29uczogbGlzdFtzdHJdID0gWyJQZXJmaWwgc2VsZWNpb25hZG86IGF1dG90dW5lIChjdXN0by1iZW5lZsOtY2lvKS4iXQogICAgdmVyYm9zZV9hdXRvdHVuZSA9IF9lbnZfYm9vbCgiTUNQX0FVVE9UVU5FX1ZFUkJPU0UiLCBkZWZhdWx0PUZhbHNlKQoKICAgIHRyeToKICAgICAgICBpbXBvcnQgcHN1dGlsICAjIHR5cGU6IGlnbm9yZQogICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICByZWFzb25zLmFwcGVuZCgicHN1dGlsIGluZGlzcG9uw612ZWw7IG1hbnRlbmRvIHBhcsOibWV0cm9zIGF0dWFpcyBzZW0gYmVuY2htYXJrLiIpCiAgICAgICAgcmV0dXJuIFJ1bnRpbWVJbmRleGluZ1BhcmFtcygKICAgICAgICAgICAgY2h1bmtfc2l6ZT1jaHVua19zaXplLAogICAgICAgICAgICBjaHVua19vdmVybGFwPWNodW5rX292ZXJsYXAsCiAgICAgICAgICAgIGVtYmVkZGluZ19iYXRjaF9zaXplPWVtYmVkZGluZ19iYXRjaF9zaXplLAogICAgICAgICAgICByZWFzb25zPXJlYXNvbnMsCiAgICAgICAgKQoKICAgIHZtID0gcHN1dGlsLnZpcnR1YWxfbWVtb3J5KCkKICAgIHN3YXAgPSBwc3V0aWwuc3dhcF9tZW1vcnkoKQogICAgbWVtX3RvdGFsX2dpYiA9IHZtLnRvdGFsIC8gKDEwMjQqKjMpCiAgICBtZW1fYXZhaWxhYmxlX2dpYiA9IHZtLmF2YWlsYWJsZSAvICgxMDI0KiozKQogICAgc3dhcF90b3RhbF9naWIgPSBzd2FwLnRvdGFsIC8gKDEwMjQqKjMpCgogICAgdGFyZ2V0X3JhbV9wZXJjZW50ID0gX2NsYW1wKAogICAgICAgIGZsb2F0KG9zLmVudmlyb24uZ2V0KCJNQ1BfQVVUT1RVTkVfVEFSR0VUX1JBTV9QRVJDRU5UIiwgIjY4IikpLAogICAgICAgIDYwLjAsCiAgICAgICAgNzUuMCwKICAgICkKICAgIGlmIG1lbV9hdmFpbGFibGVfZ2liIDwgNiBvciBzd2FwX3RvdGFsX2dpYiA8IDQ6CiAgICAgICAgdGFyZ2V0X3JhbV9wZXJjZW50ID0gbWluKHRhcmdldF9yYW1fcGVyY2VudCwgNjMuMCkKICAgIHJlYXNvbnMuYXBwZW5kKAogICAgICAgIGYiTWVtw7NyaWEgZGV0ZWN0YWRhOiB0b3RhbD17bWVtX3RvdGFsX2dpYjouMWZ9IEdpQiwgbGl2cmU9e21lbV9hdmFpbGFibGVfZ2liOi4xZn0gR2lCLCAiCiAgICAgICAgZiJzd2FwPXtzd2FwX3RvdGFsX2dpYjouMWZ9IEdpQiwgYWx2bz17dGFyZ2V0X3JhbV9wZXJjZW50Oi4xZn0lLiIKICAgICkKCiAgICB0dW5lZF9jaHVua19zaXplID0gY2h1bmtfc2l6ZQogICAgdHVuZWRfY2h1bmtfb3ZlcmxhcCA9IGNodW5rX292ZXJsYXAKICAgIHR1bmVkX2JhdGNoID0gZW1iZWRkaW5nX2JhdGNoX3NpemUKCiAgICBpZiBub3QgY2h1bmtfc2l6ZV9sb2NrZWQ6CiAgICAgICAgaWYgbWVtX3RvdGFsX2dpYiA8IDggb3IgbWVtX2F2YWlsYWJsZV9naWIgPCAzOgogICAgICAgICAgICB0dW5lZF9jaHVua19zaXplID0gMTgwMAogICAgICAgIGVsaWYgbWVtX3RvdGFsX2dpYiA8IDE2IG9yIG1lbV9hdmFpbGFibGVfZ2liIDwgNjoKICAgICAgICAgICAgdHVuZWRfY2h1bmtfc2l6ZSA9IDI0MDAKICAgICAgICBlbGlmIG1lbV90b3RhbF9naWIgPCAzMiBvciBtZW1fYXZhaWxhYmxlX2dpYiA8IDEyOgogICAgICAgICAgICB0dW5lZF9jaHVua19zaXplID0gMzIwMAogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHR1bmVkX2NodW5rX3NpemUgPSA0MjAwCiAgICAgICAgcmVhc29ucy5hcHBlbmQoZiJjaHVua19zaXplIGF1dG90dW5hZG8gcGFyYSB7dHVuZWRfY2h1bmtfc2l6ZX0uIikKCiAgICBpZiBub3QgY2h1bmtfb3ZlcmxhcF9sb2NrZWQ6CiAgICAgICAgdHVuZWRfY2h1bmtfb3ZlcmxhcCA9IG1pbih0dW5lZF9jaHVua19zaXplIC0gMSwgbWF4KDEyMCwgaW50KHR1bmVkX2NodW5rX3NpemUgKiAwLjE1KSkpCiAgICAgICAgcmVhc29ucy5hcHBlbmQoZiJjaHVua19vdmVybGFwIGF1dG90dW5hZG8gcGFyYSB7dHVuZWRfY2h1bmtfb3ZlcmxhcH0uIikKCiAgICBpZiBub3QgYmF0Y2hfc2l6ZV9sb2NrZWQ6CiAgICAgICAgbWF4X2NhbmRpZGF0ZSA9IDE2CiAgICAgICAgaWYgbWVtX3RvdGFsX2dpYiA8IDggb3IgbWVtX2F2YWlsYWJsZV9naWIgPCAzIG9yIHN3YXBfdG90YWxfZ2liIDwgMjoKICAgICAgICAgICAgbWF4X2NhbmRpZGF0ZSA9IDIKICAgICAgICBlbGlmIG1lbV90b3RhbF9naWIgPCAxNiBvciBtZW1fYXZhaWxhYmxlX2dpYiA8IDY6CiAgICAgICAgICAgIG1heF9jYW5kaWRhdGUgPSA0CiAgICAgICAgZWxpZiBtZW1fdG90YWxfZ2liIDwgMzIgb3IgbWVtX2F2YWlsYWJsZV9naWIgPCAxMDoKICAgICAgICAgICAgbWF4X2NhbmRpZGF0ZSA9IDgKCiAgICAgICAgY2FuZGlkYXRlcyA9IFsyLCA0LCA2LCA4LCAxMiwgMTZdCiAgICAgICAgY2FuZGlkYXRlcyA9IFtjIGZvciBjIGluIGNhbmRpZGF0ZXMgaWYgYyA8PSBtYXhfY2FuZGlkYXRlXQogICAgICAgIGlmIG5vdCBjYW5kaWRhdGVzOgogICAgICAgICAgICBjYW5kaWRhdGVzID0gWzJdCgogICAgICAgIHByb2Nlc3MgPSBwc3V0aWwuUHJvY2VzcygpCiAgICAgICAgc2FtcGxlX3NpemUgPSBtaW4obWF4KDUxMiwgdHVuZWRfY2h1bmtfc2l6ZSksIDMwMDApCiAgICAgICAgc2FtcGxlX3RleHQgPSAoIiMgYXV0b3R1bmUtc2FtcGxlXG4iICsgKCJ4IiAqIHNhbXBsZV9zaXplKSkKCiAgICAgICAgYmVzdF9iYXRjaCA9IGNhbmRpZGF0ZXNbMF0KICAgICAgICBiZXN0X3Njb3JlID0gLTEuMAogICAgICAgIGJlc3RfbWVtb3J5X3BjdCA9IDEwMC4wCiAgICAgICAgc2VsZWN0ZWRfYmVuY2htYXJrX2xpbmU6IHN0ciB8IE5vbmUgPSBOb25lCiAgICAgICAgYmVuY2htYXJrX2xpbmVzOiBsaXN0W3N0cl0gPSBbXQoKICAgICAgICAjIFdhcm11cCBjdXJ0byBwYXJhIGVzdGFiaWxpemFyIGNhY2hlIGludGVybm8uCiAgICAgICAgdHJ5OgogICAgICAgICAgICBfID0gbW9kZWwuZW5jb2RlKFtzYW1wbGVfdGV4dF0sIHNob3dfcHJvZ3Jlc3NfYmFyPUZhbHNlLCBiYXRjaF9zaXplPTEpCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICAgICAgcGFzcwoKICAgICAgICBmb3IgY2FuZGlkYXRlIGluIGNhbmRpZGF0ZXM6CiAgICAgICAgICAgIGRvY3MgPSBbc2FtcGxlX3RleHRdICogY2FuZGlkYXRlCiAgICAgICAgICAgIGdjLmNvbGxlY3QoKQogICAgICAgICAgICBiZWZvcmVfdm0gPSBwc3V0aWwudmlydHVhbF9tZW1vcnkoKS5wZXJjZW50CiAgICAgICAgICAgIGJlZm9yZV9yc3MgPSBwcm9jZXNzLm1lbW9yeV9pbmZvKCkucnNzIC8gKDEwMjQqKjIpCiAgICAgICAgICAgIHN0YXJ0ZWQgPSBwZXJmX2NvdW50ZXIoKQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBlbWJlZGRpbmdzID0gbW9kZWwuZW5jb2RlKAogICAgICAgICAgICAgICAgICAgIGRvY3MsCiAgICAgICAgICAgICAgICAgICAgc2hvd19wcm9ncmVzc19iYXI9RmFsc2UsCiAgICAgICAgICAgICAgICAgICAgYmF0Y2hfc2l6ZT1jYW5kaWRhdGUsCiAgICAgICAgICAgICAgICApCiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgICAgIGJlbmNobWFya19saW5lcy5hcHBlbmQoZiJiYXRjaD17Y2FuZGlkYXRlfTogZXJybyAoe2V9KSIpCiAgICAgICAgICAgICAgICBjb250aW51ZQoKICAgICAgICAgICAgZWxhcHNlZCA9IG1heChwZXJmX2NvdW50ZXIoKSAtIHN0YXJ0ZWQsIDFlLTYpCiAgICAgICAgICAgIGFmdGVyX3ZtID0gcHN1dGlsLnZpcnR1YWxfbWVtb3J5KCkucGVyY2VudAogICAgICAgICAgICBhZnRlcl9yc3MgPSBwcm9jZXNzLm1lbW9yeV9pbmZvKCkucnNzIC8gKDEwMjQqKjIpCiAgICAgICAgICAgIGRlbCBlbWJlZGRpbmdzCiAgICAgICAgICAgIGdjLmNvbGxlY3QoKQoKICAgICAgICAgICAgdGhyb3VnaHB1dCA9IGNhbmRpZGF0ZSAvIGVsYXBzZWQKICAgICAgICAgICAgc2FmZSA9IGFmdGVyX3ZtIDw9ICh0YXJnZXRfcmFtX3BlcmNlbnQgKyAzLjApCiAgICAgICAgICAgIGJlbmNobWFya19saW5lcy5hcHBlbmQoCiAgICAgICAgICAgICAgICBmImJhdGNoPXtjYW5kaWRhdGV9OiB7dGhyb3VnaHB1dDouMmZ9IGl0ZW5zL3MsIHZtPXthZnRlcl92bTouMWZ9JSwgcnNzX2RlbHRhPXthZnRlcl9yc3MgLSBiZWZvcmVfcnNzOisuMWZ9IE1pQiIKICAgICAgICAgICAgKQoKICAgICAgICAgICAgaWYgc2FmZSBhbmQgdGhyb3VnaHB1dCA+IGJlc3Rfc2NvcmU6CiAgICAgICAgICAgICAgICBiZXN0X3Njb3JlID0gdGhyb3VnaHB1dAogICAgICAgICAgICAgICAgYmVzdF9iYXRjaCA9IGNhbmRpZGF0ZQogICAgICAgICAgICAgICAgYmVzdF9tZW1vcnlfcGN0ID0gYWZ0ZXJfdm0KICAgICAgICAgICAgICAgIHNlbGVjdGVkX2JlbmNobWFya19saW5lID0gYmVuY2htYXJrX2xpbmVzWy0xXQogICAgICAgICAgICBlbGlmIGJlc3Rfc2NvcmUgPCAwIGFuZCBhZnRlcl92bSA8IGJlc3RfbWVtb3J5X3BjdDoKICAgICAgICAgICAgICAgICMgU2UgbmVuaHVtIGNhbmRpZGF0byBmaWNvdSAic2FmZSIsIGVzY29saGUgbyBtZW5vcyBhZ3Jlc3Npdm8gZW0gbWVtw7NyaWEuCiAgICAgICAgICAgICAgICBiZXN0X2JhdGNoID0gY2FuZGlkYXRlCiAgICAgICAgICAgICAgICBiZXN0X21lbW9yeV9wY3QgPSBhZnRlcl92bQogICAgICAgICAgICAgICAgc2VsZWN0ZWRfYmVuY2htYXJrX2xpbmUgPSBiZW5jaG1hcmtfbGluZXNbLTFdCgogICAgICAgICAgICAjIFNlIGrDoSBwYXNzb3UgbXVpdG8gZG8gbGltaXRlLCBldml0YSB0ZW50YXIgYmF0Y2hlcyBtYWlvcmVzLgogICAgICAgICAgICBpZiBhZnRlcl92bSA+IHRhcmdldF9yYW1fcGVyY2VudCArIDguMDoKICAgICAgICAgICAgICAgIGJyZWFrCgogICAgICAgICAgICAjIEV2aXRhIGVzY29saGVyIGNhbmRpZGF0byBxdWUgasOhIGNvbWXDp291IGFjaW1hIGRvIGxpbWl0ZS4KICAgICAgICAgICAgaWYgYmVmb3JlX3ZtID4gdGFyZ2V0X3JhbV9wZXJjZW50ICsgNS4wOgogICAgICAgICAgICAgICAgYnJlYWsKCiAgICAgICAgdHVuZWRfYmF0Y2ggPSBtYXgoMSwgYmVzdF9iYXRjaCkKICAgICAgICBpZiB2ZXJib3NlX2F1dG90dW5lOgogICAgICAgICAgICByZWFzb25zLmV4dGVuZChiZW5jaG1hcmtfbGluZXMpCiAgICAgICAgZWxpZiBzZWxlY3RlZF9iZW5jaG1hcmtfbGluZToKICAgICAgICAgICAgcmVhc29ucy5hcHBlbmQoZiJNaWNyby1iZW5jaG1hcms6IHtzZWxlY3RlZF9iZW5jaG1hcmtfbGluZX0iKQogICAgICAgIHJlYXNvbnMuYXBwZW5kKAogICAgICAgICAgICBmImVtYmVkZGluZ19iYXRjaF9zaXplIGF1dG90dW5hZG8gcGFyYSB7dHVuZWRfYmF0Y2h9IChhbHZvIGRlIG1lbcOzcmlhOiB7dGFyZ2V0X3JhbV9wZXJjZW50Oi4xZn0lKS4iCiAgICAgICAgKQoKICAgIHJldHVybiBSdW50aW1lSW5kZXhpbmdQYXJhbXMoCiAgICAgICAgY2h1bmtfc2l6ZT10dW5lZF9jaHVua19zaXplLAogICAgICAgIGNodW5rX292ZXJsYXA9dHVuZWRfY2h1bmtfb3ZlcmxhcCwKICAgICAgICBlbWJlZGRpbmdfYmF0Y2hfc2l6ZT1tYXgoMSwgdHVuZWRfYmF0Y2gpLAogICAgICAgIHJlYXNvbnM9cmVhc29ucywKICAgICkKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEZ1bsOnw7VlcyBhdXhpbGlhcmVzCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpkZWYgZ2V0X3RleHRfc3BsaXR0ZXIoY2h1bmtfc2l6ZTogaW50LCBjaHVua19vdmVybGFwOiBpbnQpIC0+IFJlY3Vyc2l2ZUNoYXJhY3RlclRleHRTcGxpdHRlcjoKICAgICIiIlJldG9ybmEgbyBzcGxpdHRlciBjb21wYXJ0aWxoYWRvIGNvbSBhcyBjb25maWd1cmHDp8O1ZXMgcGFkcsOjbyBkbyBwcm9qZXRvLiIiIgogICAgcmV0dXJuIFJlY3Vyc2l2ZUNoYXJhY3RlclRleHRTcGxpdHRlcigKICAgICAgICBjaHVua19zaXplPWNodW5rX3NpemUsCiAgICAgICAgY2h1bmtfb3ZlcmxhcD1jaHVua19vdmVybGFwLAogICAgICAgIGxlbmd0aF9mdW5jdGlvbj1sZW4sCiAgICAgICAgc2VwYXJhdG9ycz1bIlxuXG4iLCAiXG4iLCAiICIsICIiXSwKICAgICkKCgpkZWYgbG9hZF9lbWJlZGRpbmdfbW9kZWwobW9kZWxfY2hvaWNlOiBzdHIsIGppbmFfcXVhbnRpemF0aW9uOiBzdHIpIC0+IFNlbnRlbmNlVHJhbnNmb3JtZXI6CiAgICAiIiJDYXJyZWdhIG8gbW9kZWxvIGRlIGVtYmVkZGluZ3MgZm9yw6dhbmRvIHVzbyBkZSBDUFUuIiIiCiAgICBlbWJlZGRpbmdfbW9kZWxfaWQgPSBfcmVzb2x2ZV9tb2RlbF9pZChtb2RlbF9jaG9pY2UpCiAgICBmYWxsYmFja19tb2RlbF9pZCA9IF9yZXNvbHZlX2ZhbGxiYWNrX21vZGVsX2lkKG1vZGVsX2Nob2ljZSkKCiAgICBtb2RlbF9iYXNlX2RpciA9IE1PREVMX0NBQ0hFX0JBU0VfRElSCiAgICBtb2RlbF9iYXNlX2Rpci5ta2RpcihwYXJlbnRzPVRydWUsIGV4aXN0X29rPVRydWUpCiAgICBwcmVmZXJyZWRfbW9kZWxfY2FjaGVfZGlyID0gX21vZGVsX2NhY2hlX2Rpcihtb2RlbF9iYXNlX2RpciwgZW1iZWRkaW5nX21vZGVsX2lkKQoKICAgIHByaW50KGYiWytdIEJhaXhhbmRvIG1vZGVsbyBwcmVmZXJpZG86IHtlbWJlZGRpbmdfbW9kZWxfaWR9IikKICAgIHByaW50KGYiWytdIERpcmV0w7NyaW8gZGUgZG93bmxvYWQvY2FjaGUgZG8gbW9kZWxvOiB7cHJlZmVycmVkX21vZGVsX2NhY2hlX2Rpcn0iKQogICAgc2VsZWN0aW9uID0gZG93bmxvYWRfbW9kZWxfd2l0aF9mYWxsYmFjaygKICAgICAgICBwcmVmZXJyZWRfbW9kZWxfaWQ9ZW1iZWRkaW5nX21vZGVsX2lkLAogICAgICAgIGZhbGxiYWNrX21vZGVsX2lkPWZhbGxiYWNrX21vZGVsX2lkLAogICAgICAgIGxvY2FsX2Rpcj1tb2RlbF9iYXNlX2RpciwKICAgICkKICAgIHNlbGVjdGVkX21vZGVsX2RpciA9IHNlbGVjdGlvbi5sb2NhbF9kaXIKICAgIHByaW50KAogICAgICAgIGYiWytdIE1vZGVsbyBzZWxlY2lvbmFkbzoge3NlbGVjdGlvbi5tb2RlbF9pZH0gIgogICAgICAgIGYiKHByb3ZpZGVyPXtzZWxlY3Rpb24ucHJvdmlkZXJ9LCBwYXRoPXtzZWxlY3RlZF9tb2RlbF9kaXJ9KSIKICAgICkKCiAgICBkZWYgX2NsZWFyX2hmX2R5bmFtaWNfbW9kdWxlc19jYWNoZSgpIC0+IE5vbmU6CiAgICAgICAgY2FjaGVfZGlyID0gUGF0aC5ob21lKCkgLyAiLmNhY2hlIiAvICJodWdnaW5nZmFjZSIgLyAibW9kdWxlcyIgLyAidHJhbnNmb3JtZXJzX21vZHVsZXMiCiAgICAgICAgaWYgY2FjaGVfZGlyLmV4aXN0cygpOgogICAgICAgICAgICBwcmludChmIlshXSBMaW1wYW5kbyBjYWNoZSBkZSBtw7NkdWxvcyBkaW7Dom1pY29zIGRvIEh1Z2dpbmcgRmFjZToge2NhY2hlX2Rpcn0iKQogICAgICAgICAgICBzaHV0aWwucm10cmVlKGNhY2hlX2RpciwgaWdub3JlX2Vycm9ycz1UcnVlKQoKICAgIGRlZiBfbG9hZF9mcm9tX2xvY2FsX2Rpcihtb2RlbF9pZDogc3RyKSAtPiBTZW50ZW5jZVRyYW5zZm9ybWVyOgogICAgICAgICMgTyBtb2RlbG8gZGEgSmluYSBkZXBlbmRlIGRlIGPDs2RpZ28gcmVtb3RvOyBmYWxsYmFjayBub3JtYWxtZW50ZSBuw6NvLgogICAgICAgIHRydXN0X3JlbW90ZV9jb2RlID0gbW9kZWxfaWQuc3RhcnRzd2l0aCgiamluYWFpLyIpCiAgICAgICAgdG9rZW5pemVyX2t3YXJncyA9IHsiZml4X21pc3RyYWxfcmVnZXgiOiBUcnVlfQoKICAgICAgICBkZWYgX2luc3RhbnRpYXRlX21vZGVsKCkgLT4gU2VudGVuY2VUcmFuc2Zvcm1lcjoKICAgICAgICAgICAgcmV0dXJuIFNlbnRlbmNlVHJhbnNmb3JtZXIoCiAgICAgICAgICAgICAgICBzdHIoc2VsZWN0ZWRfbW9kZWxfZGlyKSwKICAgICAgICAgICAgICAgIGRldmljZT0iY3B1IiwKICAgICAgICAgICAgICAgIHRydXN0X3JlbW90ZV9jb2RlPXRydXN0X3JlbW90ZV9jb2RlLAogICAgICAgICAgICAgICAgdG9rZW5pemVyX2t3YXJncz10b2tlbml6ZXJfa3dhcmdzLAogICAgICAgICAgICApCgogICAgICAgIGRlZiBfbG9hZF93aXRoX21pc3RyYWxfcmVnZXhfcGF0Y2goKSAtPiBTZW50ZW5jZVRyYW5zZm9ybWVyOgogICAgICAgICAgICAjIE8gY8OzZGlnbyByZW1vdG8gZGEgSmluYSBpbnN0YW5jaWEgdW0gdG9rZW5pemVyIGludGVybm8gc2VtIHJlcGFzc2FyIHRva2VuaXplcl9rd2FyZ3MuCiAgICAgICAgICAgIGlmIG5vdCB0cnVzdF9yZW1vdGVfY29kZToKICAgICAgICAgICAgICAgIHJldHVybiBfaW5zdGFudGlhdGVfbW9kZWwoKQoKICAgICAgICAgICAgZnJvbSB0cmFuc2Zvcm1lcnMgaW1wb3J0IEF1dG9Nb2RlbCwgQXV0b1Rva2VuaXplcgogICAgICAgICAgICBmcm9tIHRyYW5zZm9ybWVycy5tb2RlbGluZ191dGlscyBpbXBvcnQgUHJlVHJhaW5lZE1vZGVsCgogICAgICAgICAgICBvcmlnaW5hbF9mcm9tX3ByZXRyYWluZWQgPSBBdXRvVG9rZW5pemVyLmZyb21fcHJldHJhaW5lZAogICAgICAgICAgICBvcmlnaW5hbF9tb2RlbF9mcm9tX3ByZXRyYWluZWQgPSBBdXRvTW9kZWwuZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgICAgIG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9wcmV0cmFpbmVkID0gUHJlVHJhaW5lZE1vZGVsLmZyb21fcHJldHJhaW5lZAogICAgICAgICAgICBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fY29uZmlnID0gUHJlVHJhaW5lZE1vZGVsLl9mcm9tX2NvbmZpZwogICAgICAgICAgICBtb2RlbF9yZWZzID0ge3N0cihzZWxlY3RlZF9tb2RlbF9kaXIpLCBzdHIoc2VsZWN0ZWRfbW9kZWxfZGlyLnJlc29sdmUoKSl9CgogICAgICAgICAgICBkZWYgX3BhdGNoZWRfZnJvbV9wcmV0cmFpbmVkKCphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgICAgICAgICBtb2RlbF9yZWYgPSBhcmdzWzBdIGlmIGFyZ3MgZWxzZSBrd2FyZ3MuZ2V0KCJwcmV0cmFpbmVkX21vZGVsX25hbWVfb3JfcGF0aCIpCiAgICAgICAgICAgICAgICBpZiBtb2RlbF9yZWYgaXMgbm90IE5vbmUgYW5kIHN0cihtb2RlbF9yZWYpIGluIG1vZGVsX3JlZnM6CiAgICAgICAgICAgICAgICAgICAga3dhcmdzLnNldGRlZmF1bHQoImZpeF9taXN0cmFsX3JlZ2V4IiwgVHJ1ZSkKICAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbF9mcm9tX3ByZXRyYWluZWQoKmFyZ3MsICoqa3dhcmdzKQoKICAgICAgICAgICAgZGVmIF9wYXRjaGVkX21vZGVsX2Zyb21fcHJldHJhaW5lZCgqYXJncywgKiprd2FyZ3MpOgogICAgICAgICAgICAgICAgbW9kZWxfcmVmID0gYXJnc1swXSBpZiBhcmdzIGVsc2Uga3dhcmdzLmdldCgicHJldHJhaW5lZF9tb2RlbF9uYW1lX29yX3BhdGgiKQogICAgICAgICAgICAgICAgaWYgbW9kZWxfcmVmIGlzIG5vdCBOb25lIGFuZCBzdHIobW9kZWxfcmVmKSBpbiBtb2RlbF9yZWZzIGFuZCAidG9yY2hfZHR5cGUiIGluIGt3YXJnczoKICAgICAgICAgICAgICAgICAgICBrd2FyZ3MgPSBkaWN0KGt3YXJncykKICAgICAgICAgICAgICAgICAgICBpZiAiZHR5cGUiIG5vdCBpbiBrd2FyZ3M6CiAgICAgICAgICAgICAgICAgICAgICAgIGt3YXJnc1siZHR5cGUiXSA9IGt3YXJnc1sidG9yY2hfZHR5cGUiXQogICAgICAgICAgICAgICAgICAgIGt3YXJncy5wb3AoInRvcmNoX2R0eXBlIiwgTm9uZSkKICAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbF9tb2RlbF9mcm9tX3ByZXRyYWluZWQoKmFyZ3MsICoqa3dhcmdzKQoKICAgICAgICAgICAgb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX3ByZXRyYWluZWRfZm4gPSBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fcHJldHJhaW5lZC5fX2Z1bmNfXwoKICAgICAgICAgICAgQGNsYXNzbWV0aG9kCiAgICAgICAgICAgIGRlZiBfcGF0Y2hlZF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fcHJldHJhaW5lZChjbHMsICphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgICAgICAgICBpZiAidG9yY2hfZHR5cGUiIGluIGt3YXJnczoKICAgICAgICAgICAgICAgICAgICBrd2FyZ3MgPSBkaWN0KGt3YXJncykKICAgICAgICAgICAgICAgICAgICBpZiAiZHR5cGUiIG5vdCBpbiBrd2FyZ3M6CiAgICAgICAgICAgICAgICAgICAgICAgIGt3YXJnc1siZHR5cGUiXSA9IGt3YXJnc1sidG9yY2hfZHR5cGUiXQogICAgICAgICAgICAgICAgICAgIGt3YXJncy5wb3AoInRvcmNoX2R0eXBlIiwgTm9uZSkKICAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fcHJldHJhaW5lZF9mbihjbHMsICphcmdzLCAqKmt3YXJncykKCiAgICAgICAgICAgIG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9jb25maWdfZm4gPSBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fY29uZmlnLl9fZnVuY19fCgogICAgICAgICAgICBAY2xhc3NtZXRob2QKICAgICAgICAgICAgZGVmIF9wYXRjaGVkX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9jb25maWcoY2xzLCAqYXJncywgKiprd2FyZ3MpOgogICAgICAgICAgICAgICAgaWYgInRvcmNoX2R0eXBlIiBpbiBrd2FyZ3M6CiAgICAgICAgICAgICAgICAgICAga3dhcmdzID0gZGljdChrd2FyZ3MpCiAgICAgICAgICAgICAgICAgICAgaWYgImR0eXBlIiBub3QgaW4ga3dhcmdzOgogICAgICAgICAgICAgICAgICAgICAgICBrd2FyZ3NbImR0eXBlIl0gPSBrd2FyZ3NbInRvcmNoX2R0eXBlIl0KICAgICAgICAgICAgICAgICAgICBrd2FyZ3MucG9wKCJ0b3JjaF9kdHlwZSIsIE5vbmUpCiAgICAgICAgICAgICAgICByZXR1cm4gb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX2NvbmZpZ19mbihjbHMsICphcmdzLCAqKmt3YXJncykKCiAgICAgICAgICAgIEF1dG9Ub2tlbml6ZXIuZnJvbV9wcmV0cmFpbmVkID0gX3BhdGNoZWRfZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgICAgIEF1dG9Nb2RlbC5mcm9tX3ByZXRyYWluZWQgPSBfcGF0Y2hlZF9tb2RlbF9mcm9tX3ByZXRyYWluZWQKICAgICAgICAgICAgUHJlVHJhaW5lZE1vZGVsLmZyb21fcHJldHJhaW5lZCA9IF9wYXRjaGVkX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgICAgIFByZVRyYWluZWRNb2RlbC5fZnJvbV9jb25maWcgPSBfcGF0Y2hlZF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fY29uZmlnCiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIHJldHVybiBfaW5zdGFudGlhdGVfbW9kZWwoKQogICAgICAgICAgICBmaW5hbGx5OgogICAgICAgICAgICAgICAgQXV0b1Rva2VuaXplci5mcm9tX3ByZXRyYWluZWQgPSBvcmlnaW5hbF9mcm9tX3ByZXRyYWluZWQKICAgICAgICAgICAgICAgIEF1dG9Nb2RlbC5mcm9tX3ByZXRyYWluZWQgPSBvcmlnaW5hbF9tb2RlbF9mcm9tX3ByZXRyYWluZWQKICAgICAgICAgICAgICAgIFByZVRyYWluZWRNb2RlbC5mcm9tX3ByZXRyYWluZWQgPSBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fcHJldHJhaW5lZAogICAgICAgICAgICAgICAgUHJlVHJhaW5lZE1vZGVsLl9mcm9tX2NvbmZpZyA9IG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9jb25maWcKCiAgICAgICAgcHJpbnQoZiJbK10gQ2FycmVnYW5kbyBtb2RlbG8gZGUgZW1iZWRkaW5ncyBhIHBhcnRpciBkZToge3NlbGVjdGVkX21vZGVsX2Rpcn0gKENQVSkuLi4iKQogICAgICAgIHRyeToKICAgICAgICAgICAgcmV0dXJuIF9sb2FkX3dpdGhfbWlzdHJhbF9yZWdleF9wYXRjaCgpCiAgICAgICAgZXhjZXB0IEZpbGVOb3RGb3VuZEVycm9yIGFzIGU6CiAgICAgICAgICAgICMgQ29ycmlnZSBjb3JydXDDp8Ojby9pbmNvbXBsZXR1ZGUgbm8gY2FjaGUgZGluw6JtaWNvIGRvIHRyYW5zZm9ybWVycy4KICAgICAgICAgICAgaWYgdHJ1c3RfcmVtb3RlX2NvZGUgYW5kICJ0cmFuc2Zvcm1lcnNfbW9kdWxlcyIgaW4gc3RyKGUpOgogICAgICAgICAgICAgICAgcHJpbnQoZiJbIV0gQ2FjaGUgZGluw6JtaWNvIGluY29uc2lzdGVudGUgZGV0ZWN0YWRvOiB7ZX0iKQogICAgICAgICAgICAgICAgX2NsZWFyX2hmX2R5bmFtaWNfbW9kdWxlc19jYWNoZSgpCiAgICAgICAgICAgICAgICByZXR1cm4gX2xvYWRfd2l0aF9taXN0cmFsX3JlZ2V4X3BhdGNoKCkKICAgICAgICAgICAgcmFpc2UKCiAgICBkZWYgX2FwcGx5X2ppbmFfcXVhbnRpemF0aW9uX2lmX25lZWRlZChtb2RlbDogU2VudGVuY2VUcmFuc2Zvcm1lciwgbW9kZWxfaWQ6IHN0cikgLT4gU2VudGVuY2VUcmFuc2Zvcm1lcjoKICAgICAgICBpZiBtb2RlbF9pZCAhPSBKSU5BX1YzX0VNQkVERElOR19NT0RFTCBvciBqaW5hX3F1YW50aXphdGlvbiA9PSAiZGVmYXVsdCI6CiAgICAgICAgICAgIHJldHVybiBtb2RlbAogICAgICAgIHRyeToKICAgICAgICAgICAgaW1wb3J0IHRvcmNoCiAgICAgICAgICAgIGltcG9ydCB3YXJuaW5ncwoKICAgICAgICAgICAgcXVhbnRpemVkX2xheWVycyA9IDAKICAgICAgICAgICAgZm9yIG1vZHVsZSBpbiBtb2RlbC5tb2R1bGVzKCk6CiAgICAgICAgICAgICAgICBpZiB0eXBlKG1vZHVsZSkuX19uYW1lX18gIT0gIlBhcmFtZXRyaXplZExpbmVhciI6CiAgICAgICAgICAgICAgICAgICAgY29udGludWUKCiAgICAgICAgICAgICAgICBmbG9hdF9saW5lYXIgPSB0b3JjaC5ubi5MaW5lYXIoCiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmluX2ZlYXR1cmVzLAogICAgICAgICAgICAgICAgICAgIG1vZHVsZS5vdXRfZmVhdHVyZXMsCiAgICAgICAgICAgICAgICAgICAgYmlhcz1tb2R1bGUuYmlhcyBpcyBub3QgTm9uZSwKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIHdpdGggdG9yY2gubm9fZ3JhZCgpOgogICAgICAgICAgICAgICAgICAgIGZsb2F0X2xpbmVhci53ZWlnaHQuY29weV8obW9kdWxlLndlaWdodC5kZXRhY2goKS50byh0b3JjaC5mbG9hdDMyKSkKICAgICAgICAgICAgICAgICAgICBpZiBtb2R1bGUuYmlhcyBpcyBub3QgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgZmxvYXRfbGluZWFyLmJpYXMuY29weV8obW9kdWxlLmJpYXMuZGV0YWNoKCkudG8odG9yY2guZmxvYXQzMikpCgogICAgICAgICAgICAgICAgd2l0aCB3YXJuaW5ncy5jYXRjaF93YXJuaW5ncygpOgogICAgICAgICAgICAgICAgICAgIHdhcm5pbmdzLmZpbHRlcndhcm5pbmdzKCJpZ25vcmUiLCBjYXRlZ29yeT1EZXByZWNhdGlvbldhcm5pbmcpCiAgICAgICAgICAgICAgICAgICAgcXVhbnRpemVkX2xpbmVhciA9IHRvcmNoLnF1YW50aXphdGlvbi5xdWFudGl6ZV9keW5hbWljKAogICAgICAgICAgICAgICAgICAgICAgICB0b3JjaC5ubi5TZXF1ZW50aWFsKGZsb2F0X2xpbmVhciksCiAgICAgICAgICAgICAgICAgICAgICAgIHt0b3JjaC5ubi5MaW5lYXJ9LAogICAgICAgICAgICAgICAgICAgICAgICBkdHlwZT10b3JjaC5xaW50OCwKICAgICAgICAgICAgICAgICAgICApWzBdCgogICAgICAgICAgICAgICAgbW9kdWxlLl9keW5hbWljX2ludDhfbGluZWFyID0gcXVhbnRpemVkX2xpbmVhcgoKICAgICAgICAgICAgICAgIGRlZiBfZm9yd2FyZF9keW5hbWljX2ludDgoc2VsZiwgaW5wdXQsIHRhc2tfaWQ9Tm9uZSwgcmVzaWR1YWw9RmFsc2UpOgogICAgICAgICAgICAgICAgICAgIG91dCA9IHNlbGYuX2R5bmFtaWNfaW50OF9saW5lYXIoaW5wdXQpCiAgICAgICAgICAgICAgICAgICAgaWYgcmVzaWR1YWw6CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXQsIGlucHV0CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dAoKICAgICAgICAgICAgICAgIG1vZHVsZS5mb3J3YXJkID0gX2ZvcndhcmRfZHluYW1pY19pbnQ4Ll9fZ2V0X18obW9kdWxlLCBtb2R1bGUuX19jbGFzc19fKQogICAgICAgICAgICAgICAgcXVhbnRpemVkX2xheWVycyArPSAxCgogICAgICAgICAgICBpZiBxdWFudGl6ZWRfbGF5ZXJzID09IDA6CiAgICAgICAgICAgICAgICBwcmludCgKICAgICAgICAgICAgICAgICAgICAiW0FWSVNPXSBOZW5odW1hIGNhbWFkYSBQYXJhbWV0cml6ZWRMaW5lYXIgZW5jb250cmFkYSBwYXJhIGR5bmFtaWMtaW50ODsgdXNhbmRvIG1vZGVsbyBwYWRyYW8uIgogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgcmV0dXJuIG1vZGVsCgogICAgICAgICAgICBwcmludChmIlsrXSBRdWFudGl6YWNhbyBKaW5hIGFwbGljYWRhOiBkeW5hbWljLWludDggKENQVSwge3F1YW50aXplZF9sYXllcnN9IGNhbWFkYXMpLiIpCiAgICAgICAgICAgIHJldHVybiBtb2RlbAogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgcXVhbnRfZXJyb3I6CiAgICAgICAgICAgIHByaW50KGYiW0FWSVNPXSBGYWxoYSBhbyBhcGxpY2FyIGR5bmFtaWMtaW50OCAoe3F1YW50X2Vycm9yfSk7IHVzYW5kbyBtb2RlbG8gcGFkcmFvLiIpCiAgICAgICAgICAgIHJldHVybiBtb2RlbAoKICAgIHRyeToKICAgICAgICBtb2RlbCA9IF9sb2FkX2Zyb21fbG9jYWxfZGlyKHNlbGVjdGlvbi5tb2RlbF9pZCkKICAgICAgICBtb2RlbCA9IF9hcHBseV9qaW5hX3F1YW50aXphdGlvbl9pZl9uZWVkZWQobW9kZWwsIHNlbGVjdGlvbi5tb2RlbF9pZCkKICAgICAgICBwcmludCgiWytdIE1vZGVsbyBjYXJyZWdhZG8gY29tIHN1Y2Vzc28uIikKICAgICAgICByZXR1cm4gbW9kZWwKICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZmlyc3RfZXJyb3I6CiAgICAgICAgaWYgc2VsZWN0aW9uLm1vZGVsX2lkID09IGZhbGxiYWNrX21vZGVsX2lkOgogICAgICAgICAgICByYWlzZSBSdW50aW1lRXJyb3IoCiAgICAgICAgICAgICAgICBmIkZhbGhhIGFvIGNhcnJlZ2FyIG8gbW9kZWxvIGZhbGxiYWNrICd7ZmFsbGJhY2tfbW9kZWxfaWR9Jzoge2ZpcnN0X2Vycm9yfSIKICAgICAgICAgICAgKSBmcm9tIGZpcnN0X2Vycm9yCgogICAgICAgIHByaW50KAogICAgICAgICAgICBmIlshXSBGYWxoYSBhbyBjYXJyZWdhciAne3NlbGVjdGlvbi5tb2RlbF9pZH0nOiB7X2Zvcm1hdF9leGNlcHRpb24oZmlyc3RfZXJyb3IpfVxuIgogICAgICAgICAgICBmIiAgICBUZW50YW5kbyBmYWxsYmFjayBkZSBjYXJyZWdhbWVudG86IHtmYWxsYmFja19tb2RlbF9pZH0iCiAgICAgICAgKQogICAgICAgIGZhbGxiYWNrX3NlbGVjdGlvbiA9IGRvd25sb2FkX21vZGVsX3dpdGhfZmFsbGJhY2soCiAgICAgICAgICAgIHByZWZlcnJlZF9tb2RlbF9pZD1mYWxsYmFja19tb2RlbF9pZCwKICAgICAgICAgICAgZmFsbGJhY2tfbW9kZWxfaWQ9ZmFsbGJhY2tfbW9kZWxfaWQsCiAgICAgICAgICAgIGxvY2FsX2Rpcj1tb2RlbF9iYXNlX2RpciwKICAgICAgICApCiAgICAgICAgc2VsZWN0ZWRfbW9kZWxfZGlyID0gZmFsbGJhY2tfc2VsZWN0aW9uLmxvY2FsX2RpcgogICAgICAgIHByaW50KAogICAgICAgICAgICBmIlsrXSBNb2RlbG8gc2VsZWNpb25hZG86IHtmYWxsYmFja19zZWxlY3Rpb24ubW9kZWxfaWR9ICIKICAgICAgICAgICAgZiIocHJvdmlkZXI9e2ZhbGxiYWNrX3NlbGVjdGlvbi5wcm92aWRlcn0sIHBhdGg9e3NlbGVjdGVkX21vZGVsX2Rpcn0pIgogICAgICAgICkKICAgICAgICBtb2RlbCA9IF9sb2FkX2Zyb21fbG9jYWxfZGlyKGZhbGxiYWNrX3NlbGVjdGlvbi5tb2RlbF9pZCkKICAgICAgICBtb2RlbCA9IF9hcHBseV9qaW5hX3F1YW50aXphdGlvbl9pZl9uZWVkZWQobW9kZWwsIGZhbGxiYWNrX3NlbGVjdGlvbi5tb2RlbF9pZCkKICAgICAgICBwcmludCgiWytdIE1vZGVsbyBmYWxsYmFjayBjYXJyZWdhZG8gY29tIHN1Y2Vzc28uIikKICAgICAgICByZXR1cm4gbW9kZWwKCgpkZWYgY29ubmVjdF90b19jaHJvbWEoKSAtPiBjaHJvbWFkYi5IdHRwQ2xpZW50OgogICAgIiIiQ29uZWN0YSBhbyBDaHJvbWFEQiB2aWEgSFRUUCBlIHZhbGlkYSBhIGNvbmV4w6NvLiIiIgogICAgdHJ5OgogICAgICAgIGNsaWVudCA9IGNocm9tYWRiLkh0dHBDbGllbnQoaG9zdD1DSFJPTUFfSE9TVCwgcG9ydD1DSFJPTUFfUE9SVCwgc3NsPUNIUk9NQV9TU0wpCiAgICAgICAgIyBGYXogdW0gaGVhcnRiZWF0IHBhcmEgY29uZmlybWFyIHF1ZSBvIHNlcnZpZG9yIGVzdMOhIG5vIGFyCiAgICAgICAgY2xpZW50LmhlYXJ0YmVhdCgpCiAgICAgICAgcHJpbnQoZiJbK10gQ29uZWN0YWRvIGFvIENocm9tYURCIGVtIHtDSFJPTUFfU0NIRU1FfTovL3tDSFJPTUFfSE9TVH06e0NIUk9NQV9QT1JUfSIpCiAgICAgICAgcmV0dXJuIGNsaWVudAogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIHByaW50KGYiW0VSUk9dIE7Do28gZm9pIHBvc3PDrXZlbCBjb25lY3RhciBhbyBDaHJvbWFEQjoge2V9IikKICAgICAgICBwcmludChmIiAgICAgICBFbmRwb2ludCBjb25maWd1cmFkbzoge0NIUk9NQV9TQ0hFTUV9Oi8ve0NIUk9NQV9IT1NUfTp7Q0hST01BX1BPUlR9IikKICAgICAgICBzeXMuZXhpdCgxKQoKCmRlZiBzY2FuX2ZpbGVzKHJvb3RfcGF0aDogUGF0aCkgLT4gSXRlcmF0b3JbUGF0aF06CiAgICAiIiIKICAgIFZhcnJlIHJlY3Vyc2l2YW1lbnRlIG8gZGlyZXTDs3JpbyByYWl6LCByZXRvcm5hbmRvIGVtIHN0cmVhbWluZwogICAgb3MgYXJxdWl2b3MgZGUgdGV4dG8gcmVsZXZhbnRlcyBwYXJhIGluZGV4YcOnw6NvLgogICAgIiIiCiAgICBmb3IgZGlycGF0aCwgZGlybmFtZXMsIGZpbGVuYW1lcyBpbiBvcy53YWxrKHJvb3RfcGF0aCk6CiAgICAgICAgIyBSZW1vdmUgZGlycyBpZ25vcmFkb3MgaW4tcGxhY2UgcGFyYSBxdWUgb3Mud2FsayBuw6NvIGRlc8OnYSBuZWxlcwogICAgICAgIGRpcm5hbWVzWzpdID0gWwogICAgICAgICAgICBkIGZvciBkIGluIGRpcm5hbWVzCiAgICAgICAgICAgIGlmIGQgbm90IGluIElHTk9SRURfRElSUyBhbmQgbm90IGQuc3RhcnRzd2l0aCgiLiIpCiAgICAgICAgXQogICAgICAgIGRpcm5hbWVzLnNvcnQoKQoKICAgICAgICBmb3IgZmlsZW5hbWUgaW4gc29ydGVkKGZpbGVuYW1lcyk6CiAgICAgICAgICAgIGZpbGVwYXRoID0gUGF0aChkaXJwYXRoKSAvIGZpbGVuYW1lCgogICAgICAgICAgICAjIElnbm9yYSBwb3IgZXh0ZW5zw6NvCiAgICAgICAgICAgIGlmIGZpbGVwYXRoLnN1ZmZpeC5sb3dlcigpIGluIElHTk9SRURfRVhURU5TSU9OUzoKICAgICAgICAgICAgICAgIGNvbnRpbnVlCgogICAgICAgICAgICAjIElnbm9yYSBhcnF1aXZvcyBtdWl0byBncmFuZGVzCiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIGlmIGZpbGVwYXRoLnN0YXQoKS5zdF9zaXplID4gTUFYX0ZJTEVfU0laRV9CWVRFUzoKICAgICAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICBleGNlcHQgT1NFcnJvcjoKICAgICAgICAgICAgICAgIGNvbnRpbnVlCgogICAgICAgICAgICB5aWVsZCBmaWxlcGF0aAoKCmRlZiBtYWtlX2NodW5rX2lkKGZpbGVfcGF0aDogc3RyLCBjaHVua19pbmRleDogaW50KSAtPiBzdHI6CiAgICAiIiJHZXJhIHVtIElEIGRldGVybWluw61zdGljbyBwYXJhIGNhZGEgY2h1bmsgYmFzZWFkbyBubyBjYW1pbmhvICsgw61uZGljZS4iIiIKICAgIHJhdyA9IGYie2ZpbGVfcGF0aH06OmNodW5rOjp7Y2h1bmtfaW5kZXh9IgogICAgcmV0dXJuIGhhc2hsaWIubWQ1KHJhdy5lbmNvZGUoKSkuaGV4ZGlnZXN0KCkKCgpkZWYgcmVhZF9maWxlX3NhZmUoZmlsZXBhdGg6IFBhdGgpIC0+IHN0ciB8IE5vbmU6CiAgICAiIiJMw6ogdW0gYXJxdWl2byBkZSB0ZXh0bywgdGVudGFuZG8gbcO6bHRpcGxvcyBlbmNvZGluZ3MuIiIiCiAgICBmb3IgZW5jb2RpbmcgaW4gKCJ1dGYtOCIsICJsYXRpbi0xIiwgImNwMTI1MiIpOgogICAgICAgIHRyeToKICAgICAgICAgICAgcmV0dXJuIGZpbGVwYXRoLnJlYWRfdGV4dChlbmNvZGluZz1lbmNvZGluZykKICAgICAgICBleGNlcHQgVW5pY29kZURlY29kZUVycm9yOgogICAgICAgICAgICBjb250aW51ZQogICAgICAgIGV4Y2VwdCBPU0Vycm9yIGFzIGU6CiAgICAgICAgICAgIHByaW50KGYiICBbQVZJU09dIE7Do28gZm9pIHBvc3PDrXZlbCBsZXIge2ZpbGVwYXRofToge2V9IikKICAgICAgICAgICAgcmV0dXJuIE5vbmUKICAgICMgU2UgbmVuaHVtIGVuY29kaW5nIGZ1bmNpb25vdSwgw6kgcHJvdmF2ZWxtZW50ZSBiaW7DoXJpbyBkaXNmYXLDp2FkbwogICAgcmV0dXJuIE5vbmUKCgpkZWYgZGVsZXRlX2ZpbGVfY2h1bmtzKGNvbGxlY3Rpb246IGNocm9tYWRiLkNvbGxlY3Rpb24sIGZpbGVfcGF0aDogc3RyKSAtPiBOb25lOgogICAgIiIiUmVtb3ZlIHRvZG9zIG9zIGNodW5rcyBkZSB1bSBhcnF1aXZvIGVzcGVjw61maWNvIGRhIGNvbGXDp8Ojby4iIiIKICAgIHRyeToKICAgICAgICAjIFBlZGUgc29tZW50ZSBJRHMgcGFyYSBldml0YXIgbWF0ZXJpYWxpemFyIGRvY3MvbWV0YWRhdGEgbmEgbWVtw7NyaWEuCiAgICAgICAgcmVzdWx0cyA9IGNvbGxlY3Rpb24uZ2V0KHdoZXJlPXsiZmlsZV9wYXRoIjogZmlsZV9wYXRofSwgaW5jbHVkZT1bXSkKICAgICAgICBpZiByZXN1bHRzIGFuZCByZXN1bHRzWyJpZHMiXToKICAgICAgICAgICAgY29sbGVjdGlvbi5kZWxldGUoaWRzPXJlc3VsdHNbImlkcyJdKQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIHByaW50KGYiICBbQVZJU09dIEVycm8gYW8gZGVsZXRhciBjaHVua3MgZGUge2ZpbGVfcGF0aH06IHtfZm9ybWF0X2V4Y2VwdGlvbihlKX0iKQoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgSW5kZXhhw6fDo28gZGUgdW0gw7puaWNvIGFycXVpdm8KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmRlZiBpbmRleF9maWxlKAogICAgZmlsZXBhdGg6IFBhdGgsCiAgICBjb2xsZWN0aW9uOiBjaHJvbWFkYi5Db2xsZWN0aW9uLAogICAgbW9kZWw6IFNlbnRlbmNlVHJhbnNmb3JtZXIsCiAgICBzcGxpdHRlcjogUmVjdXJzaXZlQ2hhcmFjdGVyVGV4dFNwbGl0dGVyLAogICAgcm9vdF9wYXRoOiBQYXRoLAogICAgZW1iZWRkaW5nX2JhdGNoX3NpemU6IGludCwKKSAtPiBpbnQ6CiAgICAiIiIKICAgIEluZGV4YSB1bSDDum5pY28gYXJxdWl2bzogbMOqLCBkaXZpZGUgZW0gY2h1bmtzLCBnZXJhIGVtYmVkZGluZ3MgZSBmYXogdXBzZXJ0LgogICAgUmV0b3JuYSBvIG7Dum1lcm8gZGUgY2h1bmtzIGluZGV4YWRvcy4KICAgICIiIgogICAgY29udGVudCA9IHJlYWRfZmlsZV9zYWZlKGZpbGVwYXRoKQogICAgaWYgbm90IGNvbnRlbnQgb3Igbm90IGNvbnRlbnQuc3RyaXAoKToKICAgICAgICByZXR1cm4gMAoKICAgICMgVXNhIGNhbWluaG8gYWJzb2x1dG8gY29tbyBtZXRhZGFkbwogICAgYWJzX3BhdGggPSBzdHIoZmlsZXBhdGgucmVzb2x2ZSgpKQoKICAgICMgUmVtb3ZlIGNodW5rcyBhbnRpZ29zIGRlc3RlIGFycXVpdm8gKGF0dWFsaXphw6fDo28gaWRlbXBvdGVudGUpCiAgICBkZWxldGVfZmlsZV9jaHVua3MoY29sbGVjdGlvbiwgYWJzX3BhdGgpCgogICAgY2h1bmtzID0gc3BsaXR0ZXIuc3BsaXRfdGV4dChjb250ZW50KQogICAgaWYgbm90IGNodW5rczoKICAgICAgICByZXR1cm4gMAoKICAgIHJlbGF0aXZlX3BhdGggPSBzdHIoZmlsZXBhdGgucmVsYXRpdmVfdG8ocm9vdF9wYXRoKSkKICAgIGluc2VydGVkX2NodW5rcyA9IDAKICAgIGJhdGNoX2lkczogbGlzdFtzdHJdID0gW10KICAgIGJhdGNoX2RvY3M6IGxpc3Rbc3RyXSA9IFtdCiAgICBiYXRjaF9tZXRhZGF0YXM6IGxpc3RbZGljdFtzdHIsIG9iamVjdF1dID0gW10KCiAgICBkZWYgX2ZsdXNoX2JhdGNoKCkgLT4gTm9uZToKICAgICAgICBub25sb2NhbCBpbnNlcnRlZF9jaHVua3MKICAgICAgICBpZiBub3QgYmF0Y2hfaWRzOgogICAgICAgICAgICByZXR1cm4KCiAgICAgICAgZW1iZWRkaW5ncyA9IG1vZGVsLmVuY29kZSgKICAgICAgICAgICAgYmF0Y2hfZG9jcywKICAgICAgICAgICAgc2hvd19wcm9ncmVzc19iYXI9RmFsc2UsCiAgICAgICAgICAgIGJhdGNoX3NpemU9ZW1iZWRkaW5nX2JhdGNoX3NpemUsCiAgICAgICAgKS50b2xpc3QoKQogICAgICAgIGNvbGxlY3Rpb24udXBzZXJ0KAogICAgICAgICAgICBpZHM9YmF0Y2hfaWRzLAogICAgICAgICAgICBlbWJlZGRpbmdzPWVtYmVkZGluZ3MsCiAgICAgICAgICAgIGRvY3VtZW50cz1iYXRjaF9kb2NzLAogICAgICAgICAgICBtZXRhZGF0YXM9YmF0Y2hfbWV0YWRhdGFzLAogICAgICAgICkKICAgICAgICBpbnNlcnRlZF9jaHVua3MgKz0gbGVuKGJhdGNoX2lkcykKICAgICAgICBkZWwgZW1iZWRkaW5ncwogICAgICAgIGJhdGNoX2lkcy5jbGVhcigpCiAgICAgICAgYmF0Y2hfZG9jcy5jbGVhcigpCiAgICAgICAgYmF0Y2hfbWV0YWRhdGFzLmNsZWFyKCkKICAgICAgICBnYy5jb2xsZWN0KCkKCiAgICBmb3IgaSwgY2h1bmsgaW4gZW51bWVyYXRlKGNodW5rcyk6CiAgICAgICAgYmF0Y2hfaWRzLmFwcGVuZChtYWtlX2NodW5rX2lkKGFic19wYXRoLCBpKSkKICAgICAgICBiYXRjaF9kb2NzLmFwcGVuZChjaHVuaykKICAgICAgICBiYXRjaF9tZXRhZGF0YXMuYXBwZW5kKAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAiZmlsZV9wYXRoIjogYWJzX3BhdGgsCiAgICAgICAgICAgICAgICAiY2h1bmtfaW5kZXgiOiBpLAogICAgICAgICAgICAgICAgImZpbGVfbmFtZSI6IGZpbGVwYXRoLm5hbWUsCiAgICAgICAgICAgICAgICAjIENhbWluaG8gcmVsYXRpdm8gw6AgcmFpeiBkbyBwcm9qZXRvIHBhcmEgZXhpYmnDp8OjbyBjb21wYWN0YQogICAgICAgICAgICAgICAgInJlbGF0aXZlX3BhdGgiOiByZWxhdGl2ZV9wYXRoLAogICAgICAgICAgICB9CiAgICAgICAgKQogICAgICAgIGlmIGxlbihiYXRjaF9pZHMpID49IGVtYmVkZGluZ19iYXRjaF9zaXplOgogICAgICAgICAgICBfZmx1c2hfYmF0Y2goKQoKICAgIF9mbHVzaF9iYXRjaCgpCiAgICByZXR1cm4gaW5zZXJ0ZWRfY2h1bmtzCgoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBQb250byBkZSBlbnRyYWRhIHByaW5jaXBhbAojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKZGVmIG1haW4oKToKICAgIHBhcnNlciA9IGFyZ3BhcnNlLkFyZ3VtZW50UGFyc2VyKAogICAgICAgIGRlc2NyaXB0aW9uPSJJbmRleGEgdW0gcHJvamV0byBkZSBjw7NkaWdvIG5vIENocm9tYURCIHBhcmEgUkFHIGxvY2FsLiIKICAgICkKICAgIHBhcnNlci5hZGRfYXJndW1lbnQoCiAgICAgICAgInByb2plY3RfcGF0aCIsCiAgICAgICAgbmFyZ3M9Ij8iLAogICAgICAgIGRlZmF1bHQ9Ii4iLAogICAgICAgIGhlbHA9IkNhbWluaG8gcmFpeiBkbyBwcm9qZXRvIGEgaW5kZXhhciAocGFkcsOjbzogZGlyZXTDs3JpbyBhdHVhbCkiLAogICAgKQogICAgcGFyc2VyLmFkZF9hcmd1bWVudCgKICAgICAgICAiLS1jbGVhciIsCiAgICAgICAgYWN0aW9uPSJzdG9yZV90cnVlIiwKICAgICAgICBoZWxwPSJMaW1wYSB0b2RhIGEgY29sZcOnw6NvIGFudGVzIGRlIHJlaW5kZXhhciIsCiAgICApCiAgICBwYXJzZXIuYWRkX2FyZ3VtZW50KAogICAgICAgICItLWVtYmVkZGluZy1tb2RlbCIsCiAgICAgICAgY2hvaWNlcz1bImppbmEiLCAiYmdlIiwgImh5YnJpZCJdLAogICAgICAgIGhlbHA9KAogICAgICAgICAgICAiTW9kZWxvIGRlIGVtYmVkZGluZ3M6ICdqaW5hJyAoY29kaWdvKSwgIgogICAgICAgICAgICAiJ2JnZScgKGNvbnRldWRvIG1pc3RvKSBvdSAnaHlicmlkJyAoZHVhcyBjb2xlY29lczogSmluYSB2MiArIEJHRSkuIgogICAgICAgICksCiAgICApCiAgICBwYXJzZXIuYWRkX2FyZ3VtZW50KAogICAgICAgICItLWppbmEtcXVhbnRpemF0aW9uIiwKICAgICAgICBjaG9pY2VzPVsiZGVmYXVsdCIsICJkeW5hbWljLWludDgiXSwKICAgICAgICBoZWxwPSJRdWFudGl6YWNhbyBwYXJhIEppbmE6ICdkZWZhdWx0JyAobWFpcyBxdWFsaWRhZGUpIG91ICdkeW5hbWljLWludDgnIChtYWlzIHZlbG9jaWRhZGUpLiIsCiAgICApCiAgICBwYXJzZXIuYWRkX2FyZ3VtZW50KAogICAgICAgICItLXBlcmYtcHJvZmlsZSIsCiAgICAgICAgY2hvaWNlcz1bImF1dG90dW5lIiwgIm1heC1wZXJmb3JtYW5jZSJdLAogICAgICAgIGhlbHA9KAogICAgICAgICAgICAiUGVyZmlsIGRlIHBlcmZvcm1hbmNlIGRhIGluZGV4YcOnw6NvOiAiCiAgICAgICAgICAgICInYXV0b3R1bmUnIChjdXN0by1iZW5lZsOtY2lvKSBvdSAnbWF4LXBlcmZvcm1hbmNlJyAobWFpcyB0aHJvdWdocHV0LCBtYWlvciB1c28gZGUgUkFNKS4iCiAgICAgICAgKSwKICAgICkKICAgIGFyZ3MgPSBwYXJzZXIucGFyc2VfYXJncygpCgogICAgcm9vdF9wYXRoID0gUGF0aChhcmdzLnByb2plY3RfcGF0aCkucmVzb2x2ZSgpCiAgICBpZiBub3Qgcm9vdF9wYXRoLmlzX2RpcigpOgogICAgICAgIHByaW50KGYiW0VSUk9dIENhbWluaG8gbsOjbyBleGlzdGUgb3UgbsOjbyDDqSB1bSBkaXJldMOzcmlvOiB7cm9vdF9wYXRofSIpCiAgICAgICAgc3lzLmV4aXQoMSkKCiAgICBwcmludChmIlxueyc9Jyo2MH0iKQogICAgcHJpbnQoZiIgIFJBRyBJbmRleGVyIOKAlCBQcm9qZXRvOiB7cm9vdF9wYXRofSIpCiAgICBwcmludChmInsnPScqNjB9XG4iKQogICAgaW5kZXhfc3RhcnRlZF9hdCA9IGRhdGV0aW1lLm5vdygpCiAgICBwcmludChmIltJTkZPXSBJbsOtY2lvOiB7aW5kZXhfc3RhcnRlZF9hdC5zdHJmdGltZSgnJVktJW0tJWQgJUg6JU06JVMnKX0iKQoKICAgIGZvcmNlX21vZGVsX3JlY29uZmlndXJlID0gX2Vudl9ib29sKCJNQ1BfRk9SQ0VfTU9ERUxfUkVDT05GSUciLCBkZWZhdWx0PUZhbHNlKQogICAgcGVyc2lzdGVkX2NvbmZpZyA9IGxvYWRfaW5kZXhlcl90dW5pbmdfY29uZmlnKGZvcmNlX21vZGVsX3JlY29uZmlndXJlKQogICAgbW9kZWxfY2hvaWNlLCBqaW5hX3F1YW50aXphdGlvbiA9IHJlc29sdmVfZW1iZWRkaW5nX2NvbmZpZygKICAgICAgICBhcmdzLmVtYmVkZGluZ19tb2RlbCwKICAgICAgICBhcmdzLmppbmFfcXVhbnRpemF0aW9uLAogICAgICAgIHBlcnNpc3RlZF9jb25maWc9cGVyc2lzdGVkX2NvbmZpZywKICAgICkKICAgIHBlcmZfcHJvZmlsZSA9IHJlc29sdmVfcGVyZl9wcm9maWxlKGFyZ3MucGVyZl9wcm9maWxlLCBwZXJzaXN0ZWRfY29uZmlnKQoKICAgIGNodW5rX3NpemVfbG9ja2VkID0gIk1DUF9DSFVOS19TSVpFIiBpbiBvcy5lbnZpcm9uCiAgICBjaHVua19vdmVybGFwX2xvY2tlZCA9ICJNQ1BfQ0hVTktfT1ZFUkxBUCIgaW4gb3MuZW52aXJvbgogICAgYmF0Y2hfc2l6ZV9sb2NrZWQgPSAiTUNQX0VNQkVERElOR19CQVRDSF9TSVpFIiBpbiBvcy5lbnZpcm9uCgogICAgcGVyc2lzdGVkX2NodW5rX3NpemUgPSBfcGFyc2VfY29uZmlnX2ludChwZXJzaXN0ZWRfY29uZmlnLCAiY2h1bmtfc2l6ZSIpCiAgICBwZXJzaXN0ZWRfY2h1bmtfb3ZlcmxhcCA9IF9wYXJzZV9jb25maWdfaW50KHBlcnNpc3RlZF9jb25maWcsICJjaHVua19vdmVybGFwIikKICAgIHBlcnNpc3RlZF9iYXRjaF9zaXplID0gX3BhcnNlX2NvbmZpZ19pbnQocGVyc2lzdGVkX2NvbmZpZywgImVtYmVkZGluZ19iYXRjaF9zaXplIikKCiAgICBlZmZlY3RpdmVfY2h1bmtfc2l6ZSA9IENIVU5LX1NJWkUKICAgIGlmIG5vdCBjaHVua19zaXplX2xvY2tlZCBhbmQgcGVyc2lzdGVkX2NodW5rX3NpemUgaXMgbm90IE5vbmU6CiAgICAgICAgZWZmZWN0aXZlX2NodW5rX3NpemUgPSBtYXgoMjU2LCBwZXJzaXN0ZWRfY2h1bmtfc2l6ZSkKCiAgICBlZmZlY3RpdmVfY2h1bmtfb3ZlcmxhcCA9IENIVU5LX09WRVJMQVAKICAgIGlmIG5vdCBjaHVua19vdmVybGFwX2xvY2tlZCBhbmQgcGVyc2lzdGVkX2NodW5rX292ZXJsYXAgaXMgbm90IE5vbmU6CiAgICAgICAgZWZmZWN0aXZlX2NodW5rX292ZXJsYXAgPSBtYXgoMCwgbWluKGVmZmVjdGl2ZV9jaHVua19zaXplIC0gMSwgcGVyc2lzdGVkX2NodW5rX292ZXJsYXApKQoKICAgIGVmZmVjdGl2ZV9iYXRjaF9zaXplID0gRU1CRURESU5HX0JBVENIX1NJWkUKICAgIGlmIG5vdCBiYXRjaF9zaXplX2xvY2tlZCBhbmQgcGVyc2lzdGVkX2JhdGNoX3NpemUgaXMgbm90IE5vbmU6CiAgICAgICAgZWZmZWN0aXZlX2JhdGNoX3NpemUgPSBtYXgoMSwgcGVyc2lzdGVkX2JhdGNoX3NpemUpCgogICAgcHJpbnQoCiAgICAgICAgZiJbQ09ORklHXSBNb2RlbG8gZXNjb2xoaWRvOiB7bW9kZWxfY2hvaWNlfSAiCiAgICAgICAgZiIoe19kZXNjcmliZV9lbWJlZGRpbmdfY2hvaWNlKG1vZGVsX2Nob2ljZSl9KSIKICAgICkKICAgIGlmIG1vZGVsX2Nob2ljZSA9PSAiamluYSI6CiAgICAgICAgcHJpbnQoZiJbQ09ORklHXSBRdWFudGl6YWNhbyBKaW5hOiB7amluYV9xdWFudGl6YXRpb259IikKICAgIGVsaWYgbW9kZWxfY2hvaWNlID09ICJoeWJyaWQiOgogICAgICAgIHByaW50KCJbQ09ORklHXSBRdWFudGl6YWNhbyBKaW5hOiBuYW8gYXBsaWNhdmVsIG5vIGh5YnJpZCAoSmluYSB2MiArIEJHRSkiKQogICAgZWxzZToKICAgICAgICBwcmludCgiW0NPTkZJR10gUXVhbnRpemFjYW8gSmluYTogbmFvIGFwbGljYXZlbCAobW9kZWxvIEJHRSBzZWxlY2lvbmFkbykiKQogICAgcHJpbnQoZiJbQ09ORklHXSBQZXJmaWwgZGUgcGVyZm9ybWFuY2U6IHtwZXJmX3Byb2ZpbGV9IikKICAgIGlmIHBlcmZfcHJvZmlsZSA9PSAibWF4LXBlcmZvcm1hbmNlIjoKICAgICAgICBwcmludCgKICAgICAgICAgICAgIltBVklTT10gRXN0ZSBtb2RvIHBvZGUgZWxldmFyIGNvbnNpZGVyYXZlbG1lbnRlIG8gY29uc3VtbyBkZSBtZW3Ds3JpYSAiCiAgICAgICAgICAgICJlIGNhdXNhciBlbmNlcnJhbWVudG8gcG9yIE9PTSAoZXhpdCAxMzcpLiIKICAgICAgICApCiAgICB3YXJuX2lmX2ppbmFfbWVtb3J5X3Jpc2sobW9kZWxfY2hvaWNlLCBqaW5hX3F1YW50aXphdGlvbikKCiAgICAjIEluaWNpYWxpemEgY29tcG9uZW50ZXMKICAgIGNsaWVudCA9IGNvbm5lY3RfdG9fY2hyb21hKCkKICAgIHRhcmdldHMgPSBfcmVzb2x2ZV9pbmRleF90YXJnZXRzKG1vZGVsX2Nob2ljZSkKCiAgICAjIE9idMOpbSBvdSByZWNyaWEgYXMgY29sZcOnw7VlcyBlbnZvbHZpZGFzLgogICAgY29sbGVjdGlvbnM6IGRpY3Rbc3RyLCBjaHJvbWFkYi5Db2xsZWN0aW9uXSA9IHt9CiAgICBjb2xsZWN0aW9uX2RpbWVuc2lvbl9yZXNldF9kb25lOiBkaWN0W3N0ciwgYm9vbF0gPSB7fQogICAgZm9yIHRhcmdldCBpbiB0YXJnZXRzOgogICAgICAgIGlmIGFyZ3MuY2xlYXI6CiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIGNsaWVudC5kZWxldGVfY29sbGVjdGlvbih0YXJnZXQuY29sbGVjdGlvbl9uYW1lKQogICAgICAgICAgICAgICAgcHJpbnQoZiJbIV0gQ29sZcOnw6NvICd7dGFyZ2V0LmNvbGxlY3Rpb25fbmFtZX0nIHJlbW92aWRhIHBhcmEgcmVpbmRleGHDp8OjbyBsaW1wYS4iKQogICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgICAgICAgICAgcGFzcwogICAgICAgIGNvbGxlY3Rpb25zW3RhcmdldC5jb2xsZWN0aW9uX25hbWVdID0gY2xpZW50LmdldF9vcl9jcmVhdGVfY29sbGVjdGlvbigKICAgICAgICAgICAgbmFtZT10YXJnZXQuY29sbGVjdGlvbl9uYW1lLAogICAgICAgICAgICBtZXRhZGF0YT17Imhuc3c6c3BhY2UiOiAiY29zaW5lIn0sCiAgICAgICAgKQogICAgICAgIGNvbGxlY3Rpb25fZGltZW5zaW9uX3Jlc2V0X2RvbmVbdGFyZ2V0LmNvbGxlY3Rpb25fbmFtZV0gPSBGYWxzZQoKICAgICMgQ2FycmVnYSBtb2RlbG9zIGRlIGZvcm1hIGxhenkgZSByZWFwcm92ZWl0YSBwb3IgdGFyZ2V0LgogICAgbG9hZGVkX21vZGVsczogZGljdFtzdHIsIFNlbnRlbmNlVHJhbnNmb3JtZXJdID0ge30KICAgIHRvdGFsX2NodW5rcyA9IDAKICAgIGVycm9ycyA9IDAKICAgIGZpbGVzX3NjYW5uZWQgPSAwCiAgICBmaWxlc19wcm9jZXNzZWRfdG90YWwgPSAwCiAgICBjaHVua3NfYnlfY29sbGVjdGlvbiA9IHt0YXJnZXQuY29sbGVjdGlvbl9uYW1lOiAwIGZvciB0YXJnZXQgaW4gdGFyZ2V0c30KICAgIGZpbGVzX2J5X2NvbGxlY3Rpb24gPSB7dGFyZ2V0LmNvbGxlY3Rpb25fbmFtZTogMCBmb3IgdGFyZ2V0IGluIHRhcmdldHN9CiAgICBmaWxlc19lbGlnaWJsZV9ieV9jb2xsZWN0aW9uID0ge3RhcmdldC5jb2xsZWN0aW9uX25hbWU6IDAgZm9yIHRhcmdldCBpbiB0YXJnZXRzfQogICAgZXJyb3JzX2J5X2NvbGxlY3Rpb24gPSB7dGFyZ2V0LmNvbGxlY3Rpb25fbmFtZTogMCBmb3IgdGFyZ2V0IGluIHRhcmdldHN9CiAgICBlcnJvcl9zYW1wbGVzX2J5X2NvbGxlY3Rpb246IGRpY3Rbc3RyLCBsaXN0W3N0cl1dID0ge3RhcmdldC5jb2xsZWN0aW9uX25hbWU6IFtdIGZvciB0YXJnZXQgaW4gdGFyZ2V0c30KICAgIHRhcmdldF9ieV9tb2RlbCA9IHt0YXJnZXQubW9kZWxfY2hvaWNlOiB0YXJnZXQgZm9yIHRhcmdldCBpbiB0YXJnZXRzfQoKICAgICMgQ2FycmVnYSBvIHByaW1laXJvIG1vZGVsbyBhbnRlcyBwYXJhIGF1dG90dW5lIGNvbSBtaWNyby1iZW5jaG1hcmsuCiAgICBwcmltYXJ5X3RhcmdldCA9IHRhcmdldHNbMF0KICAgIHByaW1hcnlfcXVhbnRpemF0aW9uID0gamluYV9xdWFudGl6YXRpb24gaWYgcHJpbWFyeV90YXJnZXQubW9kZWxfY2hvaWNlID09ICJqaW5hIiBlbHNlICJkZWZhdWx0IgogICAgbG9hZGVkX21vZGVsc1twcmltYXJ5X3RhcmdldC5tb2RlbF9jaG9pY2VdID0gbG9hZF9lbWJlZGRpbmdfbW9kZWwocHJpbWFyeV90YXJnZXQubW9kZWxfY2hvaWNlLCBwcmltYXJ5X3F1YW50aXphdGlvbikKICAgIHByaW1hcnlfbW9kZWwgPSBsb2FkZWRfbW9kZWxzW3ByaW1hcnlfdGFyZ2V0Lm1vZGVsX2Nob2ljZV0KCiAgICBpZiBwZXJmX3Byb2ZpbGUgPT0gImF1dG90dW5lIjoKICAgICAgICB0dW5lZCA9IF9yZXNvbHZlX2F1dG90dW5lZF9wYXJhbXMoCiAgICAgICAgICAgIG1vZGVsPXByaW1hcnlfbW9kZWwsCiAgICAgICAgICAgIGNodW5rX3NpemVfbG9ja2VkPWNodW5rX3NpemVfbG9ja2VkLAogICAgICAgICAgICBjaHVua19vdmVybGFwX2xvY2tlZD1jaHVua19vdmVybGFwX2xvY2tlZCwKICAgICAgICAgICAgYmF0Y2hfc2l6ZV9sb2NrZWQ9YmF0Y2hfc2l6ZV9sb2NrZWQsCiAgICAgICAgICAgIGNodW5rX3NpemU9ZWZmZWN0aXZlX2NodW5rX3NpemUsCiAgICAgICAgICAgIGNodW5rX292ZXJsYXA9ZWZmZWN0aXZlX2NodW5rX292ZXJsYXAsCiAgICAgICAgICAgIGVtYmVkZGluZ19iYXRjaF9zaXplPWVmZmVjdGl2ZV9iYXRjaF9zaXplLAogICAgICAgICkKICAgIGVsc2U6CiAgICAgICAgdHVuZWQgPSBfcmVzb2x2ZV9tYXhfcGVyZm9ybWFuY2VfcGFyYW1zKAogICAgICAgICAgICBjaHVua19zaXplX2xvY2tlZD1jaHVua19zaXplX2xvY2tlZCwKICAgICAgICAgICAgY2h1bmtfb3ZlcmxhcF9sb2NrZWQ9Y2h1bmtfb3ZlcmxhcF9sb2NrZWQsCiAgICAgICAgICAgIGJhdGNoX3NpemVfbG9ja2VkPWJhdGNoX3NpemVfbG9ja2VkLAogICAgICAgICAgICBjaHVua19zaXplPWVmZmVjdGl2ZV9jaHVua19zaXplLAogICAgICAgICAgICBjaHVua19vdmVybGFwPWVmZmVjdGl2ZV9jaHVua19vdmVybGFwLAogICAgICAgICAgICBlbWJlZGRpbmdfYmF0Y2hfc2l6ZT1lZmZlY3RpdmVfYmF0Y2hfc2l6ZSwKICAgICAgICApCgogICAgZWZmZWN0aXZlX2NodW5rX3NpemUgPSBtYXgoMjU2LCB0dW5lZC5jaHVua19zaXplKQogICAgZWZmZWN0aXZlX2NodW5rX292ZXJsYXAgPSBtYXgoMCwgbWluKGVmZmVjdGl2ZV9jaHVua19zaXplIC0gMSwgdHVuZWQuY2h1bmtfb3ZlcmxhcCkpCiAgICBlZmZlY3RpdmVfYmF0Y2hfc2l6ZSA9IG1heCgxLCB0dW5lZC5lbWJlZGRpbmdfYmF0Y2hfc2l6ZSkKCiAgICBmb3IgcmVhc29uIGluIHR1bmVkLnJlYXNvbnM6CiAgICAgICAgcHJpbnQoZiJbQ09ORklHXSB7cmVhc29ufSIpCgogICAgcHJpbnQoCiAgICAgICAgZiJbQ09ORklHXSBQYXLDom1ldHJvcyBmaW5haXM6ICIKICAgICAgICBmImNodW5rX3NpemU9e2VmZmVjdGl2ZV9jaHVua19zaXplfSwgY2h1bmtfb3ZlcmxhcD17ZWZmZWN0aXZlX2NodW5rX292ZXJsYXB9LCAiCiAgICAgICAgZiJlbWJlZGRpbmdfYmF0Y2g9e2VmZmVjdGl2ZV9iYXRjaF9zaXplfSIKICAgICkKCiAgICBzYXZlX2luZGV4ZXJfdHVuaW5nX2NvbmZpZygKICAgICAgICB7CiAgICAgICAgICAgICJlbWJlZGRpbmdfbW9kZWwiOiBtb2RlbF9jaG9pY2UsCiAgICAgICAgICAgICJqaW5hX3F1YW50aXphdGlvbiI6IGppbmFfcXVhbnRpemF0aW9uLAogICAgICAgICAgICAicGVyZl9wcm9maWxlIjogcGVyZl9wcm9maWxlLAogICAgICAgICAgICAiY2h1bmtfc2l6ZSI6IGVmZmVjdGl2ZV9jaHVua19zaXplLAogICAgICAgICAgICAiY2h1bmtfb3ZlcmxhcCI6IGVmZmVjdGl2ZV9jaHVua19vdmVybGFwLAogICAgICAgICAgICAiZW1iZWRkaW5nX2JhdGNoX3NpemUiOiBlZmZlY3RpdmVfYmF0Y2hfc2l6ZSwKICAgICAgICB9CiAgICApCgogICAgc3BsaXR0ZXIgPSBnZXRfdGV4dF9zcGxpdHRlcihlZmZlY3RpdmVfY2h1bmtfc2l6ZSwgZWZmZWN0aXZlX2NodW5rX292ZXJsYXApCgogICAgcHJpbnQoZiJcblsrXSBWYXJyZW5kbyBlIGluZGV4YW5kbyBhcnF1aXZvcyBlbToge3Jvb3RfcGF0aH0iKQogICAgZmlsZXMgPSBsaXN0KHNjYW5fZmlsZXMocm9vdF9wYXRoKSkKICAgIGZpbGVzX3NjYW5uZWQgPSBsZW4oZmlsZXMpCiAgICBpZiBmaWxlc19zY2FubmVkID09IDA6CiAgICAgICAgcHJpbnQoIltBVklTT10gTmVuaHVtIGFycXVpdm8gZW5jb250cmFkby4gVmVyaWZpcXVlIG8gY2FtaW5obyBlIG9zIGZpbHRyb3MuIikKICAgICAgICBzeXMuZXhpdCgwKQoKICAgIHByaW50KGYiWytdIHtmaWxlc19zY2FubmVkfSBhcnF1aXZvKHMpIGVsZWfDrXZlbChpcykgcGFyYSBpbmRleGHDp8Ojby4iKQogICAgd2l0aCB0cWRtKAogICAgICAgIHRvdGFsPWZpbGVzX3NjYW5uZWQsCiAgICAgICAgZGVzYz0iSW5kZXhhbmRvIiwKICAgICAgICB1bml0PSJhcnF1aXZvIiwKICAgICAgICBiYXJfZm9ybWF0PSJ7bF9iYXJ9e2Jhcn18IHtuX2ZtdH0ve3RvdGFsX2ZtdH0gW3tlbGFwc2VkfSwge3JhdGVfZm10fV0iLAogICAgKSBhcyBwYmFyOgogICAgICAgIGZvciBmaWxlcGF0aCBpbiBmaWxlczoKICAgICAgICAgICAgdGFyZ2V0X21vZGVscyA9IF9jbGFzc2lmeV9maWxlX3RhcmdldHMoZmlsZXBhdGgsIG1vZGVsX2Nob2ljZSkKCiAgICAgICAgICAgIGZvciB0YXJnZXRfbW9kZWwgaW4gdGFyZ2V0X21vZGVsczoKICAgICAgICAgICAgICAgIHRhcmdldCA9IHRhcmdldF9ieV9tb2RlbC5nZXQodGFyZ2V0X21vZGVsKQogICAgICAgICAgICAgICAgaWYgdGFyZ2V0IGlzIE5vbmU6CiAgICAgICAgICAgICAgICAgICAgY29udGludWUKCiAgICAgICAgICAgICAgICBpZiB0YXJnZXQubW9kZWxfY2hvaWNlIG5vdCBpbiBsb2FkZWRfbW9kZWxzOgogICAgICAgICAgICAgICAgICAgIHRhcmdldF9xdWFudGl6YXRpb24gPSBqaW5hX3F1YW50aXphdGlvbiBpZiB0YXJnZXQubW9kZWxfY2hvaWNlID09ICJqaW5hIiBlbHNlICJkZWZhdWx0IgogICAgICAgICAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkX21vZGVsc1t0YXJnZXQubW9kZWxfY2hvaWNlXSA9IGxvYWRfZW1iZWRkaW5nX21vZGVsKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0Lm1vZGVsX2Nob2ljZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldF9xdWFudGl6YXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGxvYWRfZXJyb3I6CiAgICAgICAgICAgICAgICAgICAgICAgICMgRW0gaHlicmlkLCBwb2RlIGZhbHRhciBSQU0gYW8gbWFudGVyIGRvaXMgbW9kZWxvcyBncmFuZGVzIHNpbXVsdGFuZWFtZW50ZS4KICAgICAgICAgICAgICAgICAgICAgICAgaWYgbW9kZWxfY2hvaWNlID09ICJoeWJyaWQiIGFuZCBsb2FkZWRfbW9kZWxzIGFuZCBfaXNfbWVtb3J5X3JlbGF0ZWRfZXJyb3IobG9hZF9lcnJvcik6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmludCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiW0FWSVNPXSBGYWxoYSBhbyBjYXJyZWdhciBtb2RlbG8gYWRpY2lvbmFsIG5vIGh5YnJpZCBwb3IgbWVtw7NyaWEuICIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTGliZXJhbmRvIG1vZGVsbyBhbnRlcmlvciBlIHRlbnRhbmRvIG5vdmFtZW50ZS4iCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2FkZWRfbW9kZWxzLmNsZWFyKCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdjLmNvbGxlY3QoKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkX21vZGVsc1t0YXJnZXQubW9kZWxfY2hvaWNlXSA9IGxvYWRfZW1iZWRkaW5nX21vZGVsKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldC5tb2RlbF9jaG9pY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0X3F1YW50aXphdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhaXNlCgogICAgICAgICAgICAgICAgbW9kZWwgPSBsb2FkZWRfbW9kZWxzW3RhcmdldC5tb2RlbF9jaG9pY2VdCiAgICAgICAgICAgICAgICBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbdGFyZ2V0LmNvbGxlY3Rpb25fbmFtZV0KICAgICAgICAgICAgICAgIGZpbGVzX2VsaWdpYmxlX2J5X2NvbGxlY3Rpb25bdGFyZ2V0LmNvbGxlY3Rpb25fbmFtZV0gKz0gMQoKICAgICAgICAgICAgICAgIHdoaWxlIFRydWU6CiAgICAgICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgICAgICBuX2NodW5rcyA9IGluZGV4X2ZpbGUoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlcGF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxlY3Rpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwbGl0dGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdF9wYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZW1iZWRkaW5nX2JhdGNoX3NpemU9ZWZmZWN0aXZlX2JhdGNoX3NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgdG90YWxfY2h1bmtzICs9IG5fY2h1bmtzCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVzX3Byb2Nlc3NlZF90b3RhbCArPSAxCiAgICAgICAgICAgICAgICAgICAgICAgIGNodW5rc19ieV9jb2xsZWN0aW9uW3RhcmdldC5jb2xsZWN0aW9uX25hbWVdICs9IG5fY2h1bmtzCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVzX2J5X2NvbGxlY3Rpb25bdGFyZ2V0LmNvbGxlY3Rpb25fbmFtZV0gKz0gMQogICAgICAgICAgICAgICAgICAgICAgICBicmVhawogICAgICAgICAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgICAgICAgICAgICAgIyBGYWxsYmFjayBhdXRvbcOhdGljbyBwYXJhIGV2aXRhciBxdWVicmEgdG90YWwgZW0gbcOhcXVpbmFzIG5vIGxpbWl0ZSBkZSBSQU0uCiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdCBiYXRjaF9zaXplX2xvY2tlZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5kIGVmZmVjdGl2ZV9iYXRjaF9zaXplID4gMQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5kIF9pc19tZW1vcnlfcmVsYXRlZF9lcnJvcihlKQogICAgICAgICAgICAgICAgICAgICAgICApOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3X2JhdGNoID0gbWF4KDEsIGVmZmVjdGl2ZV9iYXRjaF9zaXplIC8vIDIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiBuZXdfYmF0Y2ggPCBlZmZlY3RpdmVfYmF0Y2hfc2l6ZToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cWRtLndyaXRlKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmIiAgW0FKVVNURV0gTWVtw7NyaWEgYWx0YSBlbSB7dGFyZ2V0LmxhYmVsfS4gIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmIkJhdGNoIHJlZHV6aWRvIHtlZmZlY3RpdmVfYmF0Y2hfc2l6ZX0gLT4ge25ld19iYXRjaH0uIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZmZlY3RpdmVfYmF0Y2hfc2l6ZSA9IG5ld19iYXRjaAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdjLmNvbGxlY3QoKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlCgogICAgICAgICAgICAgICAgICAgICAgICBpZiAoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfaXNfZGltZW5zaW9uX21pc21hdGNoX2Vycm9yKGUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmQgbm90IGNvbGxlY3Rpb25fZGltZW5zaW9uX3Jlc2V0X2RvbmVbdGFyZ2V0LmNvbGxlY3Rpb25fbmFtZV0KICAgICAgICAgICAgICAgICAgICAgICAgKToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRxZG0ud3JpdGUoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZiIgIFtBSlVTVEVdIERpbWVuc8OjbyBpbmNvbXBhdMOtdmVsIGRldGVjdGFkYSBlbSAne3RhcmdldC5jb2xsZWN0aW9uX25hbWV9Jy4gIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWNyaWFuZG8gY29sZcOnw6NvIGUgdGVudGFuZG8gbm92YW1lbnRlLiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGllbnQuZGVsZXRlX2NvbGxlY3Rpb24odGFyZ2V0LmNvbGxlY3Rpb25fbmFtZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzcwoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxlY3Rpb25zW3RhcmdldC5jb2xsZWN0aW9uX25hbWVdID0gY2xpZW50LmdldF9vcl9jcmVhdGVfY29sbGVjdGlvbigKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPXRhcmdldC5jb2xsZWN0aW9uX25hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGE9eyJobnN3OnNwYWNlIjogImNvc2luZSJ9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sbGVjdGlvbl9kaW1lbnNpb25fcmVzZXRfZG9uZVt0YXJnZXQuY29sbGVjdGlvbl9uYW1lXSA9IFRydWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdjLmNvbGxlY3QoKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWUKCiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ycyArPSAxCiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yc19ieV9jb2xsZWN0aW9uW3RhcmdldC5jb2xsZWN0aW9uX25hbWVdICs9IDEKICAgICAgICAgICAgICAgICAgICAgICAgaWYgbGVuKGVycm9yX3NhbXBsZXNfYnlfY29sbGVjdGlvblt0YXJnZXQuY29sbGVjdGlvbl9uYW1lXSkgPCAzOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Jfc2FtcGxlc19ieV9jb2xsZWN0aW9uW3RhcmdldC5jb2xsZWN0aW9uX25hbWVdLmFwcGVuZCgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmIntmaWxlcGF0aC5uYW1lfToge19mb3JtYXRfZXhjZXB0aW9uKGUpfSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgdHFkbS53cml0ZShmIiAgW0VSUk9dIHtmaWxlcGF0aH0gW3t0YXJnZXQubGFiZWx9XToge19mb3JtYXRfZXhjZXB0aW9uKGUpfSIpCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrCgogICAgICAgICAgICBwYmFyLnNldF9wb3N0Zml4KHsiY2h1bmtzIjogdG90YWxfY2h1bmtzLCAiYXR1YWwiOiBmaWxlcGF0aC5uYW1lWzoyMF19KQogICAgICAgICAgICBwYmFyLnVwZGF0ZSgxKQoKICAgIGZvciB0YXJnZXQgaW4gdGFyZ2V0czoKICAgICAgICBjb2xsZWN0aW9uX25hbWUgPSB0YXJnZXQuY29sbGVjdGlvbl9uYW1lCiAgICAgICAgZWxpZ2libGUgPSBmaWxlc19lbGlnaWJsZV9ieV9jb2xsZWN0aW9uW2NvbGxlY3Rpb25fbmFtZV0KICAgICAgICBwcm9jZXNzZWQgPSBmaWxlc19ieV9jb2xsZWN0aW9uW2NvbGxlY3Rpb25fbmFtZV0KICAgICAgICB0YXJnZXRfZXJyb3JzID0gZXJyb3JzX2J5X2NvbGxlY3Rpb25bY29sbGVjdGlvbl9uYW1lXQoKICAgICAgICBpZiBlbGlnaWJsZSA9PSAwOgogICAgICAgICAgICBwcmludChmIltBVklTT10gTmVuaHVtIGFycXVpdm8gZWxlZ8OtdmVsIHBhcmEge3RhcmdldC5sYWJlbH07IGV0YXBhIGlnbm9yYWRhLiIpCiAgICAgICAgZWxpZiBwcm9jZXNzZWQgPT0gMCBhbmQgdGFyZ2V0X2Vycm9ycyA+IDA6CiAgICAgICAgICAgIHByaW50KAogICAgICAgICAgICAgICAgZiJbQVZJU09dIHtlbGlnaWJsZX0gYXJxdWl2byhzKSBlbGVnw612ZWwoaXMpIHBhcmEge3RhcmdldC5sYWJlbH0sICIKICAgICAgICAgICAgICAgICJtYXMgdG9kb3MgZmFsaGFyYW0uIgogICAgICAgICAgICApCgogICAgICAgIGlmIHRhcmdldF9lcnJvcnM6CiAgICAgICAgICAgIHByaW50KGYiW0FWSVNPXSB7dGFyZ2V0X2Vycm9yc30gZXJybyhzKSBkdXJhbnRlIGEgaW5kZXhhw6fDo28gZG8gdGFyZ2V0IHt0YXJnZXQubGFiZWx9LiIpCiAgICAgICAgICAgIGZvciBzYW1wbGUgaW4gZXJyb3Jfc2FtcGxlc19ieV9jb2xsZWN0aW9uW2NvbGxlY3Rpb25fbmFtZV06CiAgICAgICAgICAgICAgICBwcmludChmIiAgICAgICAgLSB7c2FtcGxlfSIpCgogICAgaW5kZXhfZmluaXNoZWRfYXQgPSBkYXRldGltZS5ub3coKQogICAgZWxhcHNlZF9zZWNvbmRzID0gaW50KChpbmRleF9maW5pc2hlZF9hdCAtIGluZGV4X3N0YXJ0ZWRfYXQpLnRvdGFsX3NlY29uZHMoKSkKICAgIGVsYXBzZWRfaCA9IGVsYXBzZWRfc2Vjb25kcyAvLyAzNjAwCiAgICBlbGFwc2VkX20gPSAoZWxhcHNlZF9zZWNvbmRzICUgMzYwMCkgLy8gNjAKICAgIGVsYXBzZWRfcyA9IGVsYXBzZWRfc2Vjb25kcyAlIDYwCiAgICBwcmludChmIlxueyc9Jyo2MH0iKQogICAgcHJpbnQoZiIgIEluZGV4YcOnw6NvIGNvbmNsdcOtZGEhIikKICAgIHByaW50KGYiICBJbsOtY2lvICAgICAgICAgICAgICAgOiB7aW5kZXhfc3RhcnRlZF9hdC5zdHJmdGltZSgnJVktJW0tJWQgJUg6JU06JVMnKX0iKQogICAgcHJpbnQoZiIgIEZpbSAgICAgICAgICAgICAgICAgIDoge2luZGV4X2ZpbmlzaGVkX2F0LnN0cmZ0aW1lKCclWS0lbS0lZCAlSDolTTolUycpfSIpCiAgICBwcmludChmIiAgRHVyYcOnw6NvICAgICAgICAgICAgICA6IHtlbGFwc2VkX2g6MDJkfTp7ZWxhcHNlZF9tOjAyZH06e2VsYXBzZWRfczowMmR9IikKICAgIHByaW50KGYiICBBcnF1aXZvcyB2YXJyaWRvcyAgICA6IHtmaWxlc19zY2FubmVkfSIpCiAgICBwcmludChmIiAgQXJxdWl2b3MgcHJvY2Vzc2Fkb3MgOiB7ZmlsZXNfcHJvY2Vzc2VkX3RvdGFsfSIpCiAgICBwcmludChmIiAgVG90YWwgZGUgY2h1bmtzICAgICAgOiB7dG90YWxfY2h1bmtzfSIpCiAgICBwcmludChmIiAgRXJyb3MgICAgICAgICAgICAgICAgOiB7ZXJyb3JzfSIpCiAgICBmb3IgdGFyZ2V0IGluIHRhcmdldHM6CiAgICAgICAgY29sbGVjdGlvbl9uYW1lID0gdGFyZ2V0LmNvbGxlY3Rpb25fbmFtZQogICAgICAgIHByaW50KAogICAgICAgICAgICBmIiAgQ29sZcOnw6NvIENocm9tYURCICAgICA6ICd7Y29sbGVjdGlvbl9uYW1lfScgIgogICAgICAgICAgICBmIihlbGVnw612ZWlzPXtmaWxlc19lbGlnaWJsZV9ieV9jb2xsZWN0aW9uLmdldChjb2xsZWN0aW9uX25hbWUsIDApfSwgIgogICAgICAgICAgICBmImFycXVpdm9zPXtmaWxlc19ieV9jb2xsZWN0aW9uLmdldChjb2xsZWN0aW9uX25hbWUsIDApfSwgIgogICAgICAgICAgICBmImNodW5rcz17Y2h1bmtzX2J5X2NvbGxlY3Rpb24uZ2V0KGNvbGxlY3Rpb25fbmFtZSwgMCl9KSIKICAgICAgICApCiAgICBwcmludChmInsnPScqNjB9XG4iKQoKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICB0cnk6CiAgICAgICAgbWFpbigpCiAgICBleGNlcHQgTWVtb3J5RXJyb3I6CiAgICAgICAgcHJpbnQoCiAgICAgICAgICAgICJbRVJST10gRmFsaGEgZGUgbWVtw7NyaWEgZHVyYW50ZSBhIGluZGV4YcOnw6NvLiAiCiAgICAgICAgICAgICJVc2UgLS1lbWJlZGRpbmctbW9kZWwgYmdlIG91IGV4ZWN1dGUgbyBKaW5hIGVtIG3DoXF1aW5hIGNvbSBtYWlzIFJBTS9zd2FwLiIKICAgICAgICApCiAgICAgICAgc3lzLmV4aXQoMSkK"
|
|
728
|
+
B64_MCP="IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwpmcm9tIF9fZnV0dXJlX18gaW1wb3J0IGFubm90YXRpb25zCiIiIgptY3Bfc2VydmVyLnB5IOKAlCBTZXJ2aWRvciBNQ1AgcGFyYSBSQUcgbG9jYWwgZGUgY29kZWJhc2UuCgpFeHDDtWUgZmVycmFtZW50YXMgZGUgYnVzY2Egc2Vtw6JudGljYSBlIGluZGV4YcOnw6NvIHZpYSBzdGRpbyBwYXJhIG8gQ2xhdWRlIENvZGUgQ0xJLgpDb25lY3RhLXNlIGFvIENocm9tYURCIHJvZGFuZG8gZW0gRG9ja2VyIChsb2NhbGhvc3Q6ODAwMCkuCgpOb3ZpZGFkZTogbW9kbyBow61icmlkbyBlbnNlbWJsZSBjb20gZHVhcyBjb2xlw6fDtWVzIHNlcGFyYWRhcyArIFJSRiArIHJlcmFua2luZyBsZXZlLgoiIiIKCmltcG9ydCBzeXMKaW1wb3J0IG9zCmltcG9ydCBoYXNobGliCmltcG9ydCBqc29uCmltcG9ydCBsb2dnaW5nCmltcG9ydCBnZXRwYXNzCmltcG9ydCBzaHV0aWwKZnJvbSBjb2xsZWN0aW9ucy5hYmMgaW1wb3J0IEl0ZXJhdG9yCmZyb20gY29uY3VycmVudC5mdXR1cmVzIGltcG9ydCBUaHJlYWRQb29sRXhlY3V0b3IsIGFzX2NvbXBsZXRlZApmcm9tIGRhdGFjbGFzc2VzIGltcG9ydCBkYXRhY2xhc3MKZnJvbSBkYXRldGltZSBpbXBvcnQgZGF0ZXRpbWUsIHRpbWV6b25lCmZyb20gcGF0aGxpYiBpbXBvcnQgUGF0aApmcm9tIHVybGxpYi5wYXJzZSBpbXBvcnQgdXJscGFyc2UKCiMgRXZpdGEgbWVuc2FnZW5zIGFkdmlzb3J5IGRvIHRyYW5zZm9ybWVycyBlbSBzdGRlcnIgZHVyYW50ZSBhIGNhcmdhIGRvIG1vZGVsby4Kb3MuZW52aXJvbi5zZXRkZWZhdWx0KCJUUkFOU0ZPUk1FUlNfTk9fQURWSVNPUllfV0FSTklOR1MiLCAiMSIpCgoKY2xhc3MgX1RvcmNoRHR5cGVXYXJuaW5nRmlsdGVyKGxvZ2dpbmcuRmlsdGVyKToKICAgIGRlZiBmaWx0ZXIoc2VsZiwgcmVjb3JkOiBsb2dnaW5nLkxvZ1JlY29yZCkgLT4gYm9vbDoKICAgICAgICByZXR1cm4gImB0b3JjaF9kdHlwZWAgaXMgZGVwcmVjYXRlZCEgVXNlIGBkdHlwZWAgaW5zdGVhZCEiIG5vdCBpbiByZWNvcmQuZ2V0TWVzc2FnZSgpCgoKZm9yIF9sb2dnZXJfbmFtZSBpbiAoInRyYW5zZm9ybWVycy5jb25maWd1cmF0aW9uX3V0aWxzIiwgInRyYW5zZm9ybWVycy5tb2RlbGluZ191dGlscyIpOgogICAgbG9nZ2luZy5nZXRMb2dnZXIoX2xvZ2dlcl9uYW1lKS5hZGRGaWx0ZXIoX1RvcmNoRHR5cGVXYXJuaW5nRmlsdGVyKCkpCgppbXBvcnQgY2hyb21hZGIKZnJvbSBzZW50ZW5jZV90cmFuc2Zvcm1lcnMgaW1wb3J0IENyb3NzRW5jb2RlciwgU2VudGVuY2VUcmFuc2Zvcm1lcgpmcm9tIGxhbmdjaGFpbl90ZXh0X3NwbGl0dGVycyBpbXBvcnQgUmVjdXJzaXZlQ2hhcmFjdGVyVGV4dFNwbGl0dGVyCmZyb20gbWNwLnNlcnZlci5mYXN0bWNwIGltcG9ydCBGYXN0TUNQCmZyb20gZG93bmxvYWRfbW9kZWxfZnJvbV9odWdnaW5mYWNlIGltcG9ydCBkb3dubG9hZF9tb2RlbF93aXRoX2ZhbGxiYWNrCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIENvbmZpZ3VyYcOnw6NvIGRlIGxvZ2dpbmcgKHN0ZGVyciBwYXJhIG7Do28gcG9sdWlyIG8gcHJvdG9jb2xvIHN0ZGlvKQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKbG9nZ2luZy5iYXNpY0NvbmZpZygKICAgIGxldmVsPWxvZ2dpbmcuSU5GTywKICAgIGZvcm1hdD0iW01DUC1SQUddICUoYXNjdGltZSlzICUobGV2ZWxuYW1lKXM6ICUobWVzc2FnZSlzIiwKICAgIHN0cmVhbT1zeXMuc3RkZXJyLAopCmxvZyA9IGxvZ2dpbmcuZ2V0TG9nZ2VyKF9fbmFtZV9fKQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBMb2cgZXN0cnV0dXJhZG8gZGUgdXNvIE1DUCAoSlNPTkwpCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpNQ1BfVVNBR0VfTE9HX1BBVEggPSBQYXRoKAogICAgb3MuZW52aXJvbi5nZXQoIk1DUF9VU0FHRV9MT0ciLCBzdHIoUGF0aC5ob21lKCkgLyAiLnJhZ19kYiIgLyAibWNwX3VzYWdlLmxvZyIpKQopLmV4cGFuZHVzZXIoKQoKCmRlZiBfc2FmZV9wcmV2aWV3KHZhbHVlOiBzdHIsIGxpbWl0OiBpbnQgPSAxMjApIC0+IHN0cjoKICAgIGlmIGxlbih2YWx1ZSkgPD0gbGltaXQ6CiAgICAgICAgcmV0dXJuIHZhbHVlCiAgICByZXR1cm4gdmFsdWVbOmxpbWl0XSArICIuLi5bdHJ1bmNhdGVkXSIKCgpkZWYgX2dldF9wYXJlbnRfY21kbGluZSgpIC0+IHN0cjoKICAgIHBwaWQgPSBvcy5nZXRwcGlkKCkKICAgIGNtZGxpbmVfcGF0aCA9IFBhdGgoZiIvcHJvYy97cHBpZH0vY21kbGluZSIpCiAgICB0cnk6CiAgICAgICAgcmF3ID0gY21kbGluZV9wYXRoLnJlYWRfYnl0ZXMoKQogICAgICAgIGlmIG5vdCByYXc6CiAgICAgICAgICAgIHJldHVybiAidW5rbm93biIKICAgICAgICBwYXJ0cyA9IFtwLmRlY29kZSgidXRmLTgiLCBlcnJvcnM9Imlnbm9yZSIpIGZvciBwIGluIHJhdy5zcGxpdChiIlx4MDAiKSBpZiBwXQogICAgICAgIHJldHVybiAiICIuam9pbihwYXJ0cykgaWYgcGFydHMgZWxzZSAidW5rbm93biIKICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgcmV0dXJuICJ1bmtub3duIgoKCmRlZiBfaW5mZXJfYWN0b3IoKSAtPiBkaWN0W3N0ciwgc3RyXToKICAgIGFjdG9yID0gb3MuZW52aXJvbi5nZXQoIk1DUF9DTElFTlRfTkFNRSIpIG9yIG9zLmVudmlyb24uZ2V0KCJDTEFVREVfVVNFUiIpIG9yIGdldHBhc3MuZ2V0dXNlcigpCiAgICBzb3VyY2UgPSAoCiAgICAgICAgIk1DUF9DTElFTlRfTkFNRSIgaWYgb3MuZW52aXJvbi5nZXQoIk1DUF9DTElFTlRfTkFNRSIpCiAgICAgICAgZWxzZSAiQ0xBVURFX1VTRVIiIGlmIG9zLmVudmlyb24uZ2V0KCJDTEFVREVfVVNFUiIpCiAgICAgICAgZWxzZSAic3lzdGVtX3VzZXIiCiAgICApCiAgICByZXR1cm4gewogICAgICAgICJhY3RvciI6IGFjdG9yLAogICAgICAgICJhY3Rvcl9zb3VyY2UiOiBzb3VyY2UsCiAgICAgICAgImNsaWVudF9wcm9jZXNzIjogX2dldF9wYXJlbnRfY21kbGluZSgpLAogICAgfQoKCmRlZiBfbG9nX3Rvb2xfdXNhZ2UoZXZlbnQ6IHN0ciwgdG9vbF9uYW1lOiBzdHIsIGRldGFpbHM6IGRpY3Rbc3RyLCBvYmplY3RdIHwgTm9uZSA9IE5vbmUpIC0+IE5vbmU6CiAgICB0cnk6CiAgICAgICAgTUNQX1VTQUdFX0xPR19QQVRILnBhcmVudC5ta2RpcihwYXJlbnRzPVRydWUsIGV4aXN0X29rPVRydWUpCiAgICAgICAgcGF5bG9hZDogZGljdFtzdHIsIG9iamVjdF0gPSB7CiAgICAgICAgICAgICJ0aW1lc3RhbXAiOiBkYXRldGltZS5ub3codGltZXpvbmUudXRjKS5pc29mb3JtYXQoKSwKICAgICAgICAgICAgImV2ZW50IjogZXZlbnQsCiAgICAgICAgICAgICJ0b29sIjogdG9vbF9uYW1lLAogICAgICAgICAgICAicGlkIjogb3MuZ2V0cGlkKCksCiAgICAgICAgICAgICoqX2luZmVyX2FjdG9yKCksCiAgICAgICAgfQogICAgICAgIGlmIGRldGFpbHM6CiAgICAgICAgICAgIHBheWxvYWRbImRldGFpbHMiXSA9IGRldGFpbHMKCiAgICAgICAgd2l0aCBNQ1BfVVNBR0VfTE9HX1BBVEgub3BlbigiYSIsIGVuY29kaW5nPSJ1dGYtOCIpIGFzIGY6CiAgICAgICAgICAgIGYud3JpdGUoanNvbi5kdW1wcyhwYXlsb2FkLCBlbnN1cmVfYXNjaWk9VHJ1ZSkgKyAiXG4iKQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIGxvZy53YXJuaW5nKCJGYWxoYSBhbyByZWdpc3RyYXIgdXNvIE1DUCBlbSAlczogJXMiLCBNQ1BfVVNBR0VfTE9HX1BBVEgsIGUpCgoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBDb25maWd1cmHDp8O1ZXMKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCgpJTkRFWEVSX0NPTkZJR19QQVRIID0gUGF0aCgKICAgIG9zLmVudmlyb24uZ2V0KAogICAgICAgICJNQ1BfSU5ERVhFUl9DT05GSUdfRklMRSIsCiAgICAgICAgc3RyKFBhdGguaG9tZSgpIC8gIi5jYWNoZSIgLyAib3duLXJhZy1jbGkiIC8gImluZGV4ZXJfdHVuaW5nLmpzb24iKSwKICAgICkKKS5leHBhbmR1c2VyKCkKCgpkZWYgX2xvYWRfaW5kZXhlcl90dW5pbmdfY29uZmlnKCkgLT4gZGljdFtzdHIsIG9iamVjdF06CiAgICB0cnk6CiAgICAgICAgaWYgbm90IElOREVYRVJfQ09ORklHX1BBVEguZXhpc3RzKCk6CiAgICAgICAgICAgIHJldHVybiB7fQogICAgICAgIHBheWxvYWQgPSBqc29uLmxvYWRzKElOREVYRVJfQ09ORklHX1BBVEgucmVhZF90ZXh0KGVuY29kaW5nPSJ1dGYtOCIpKQogICAgICAgIHJldHVybiBwYXlsb2FkIGlmIGlzaW5zdGFuY2UocGF5bG9hZCwgZGljdCkgZWxzZSB7fQogICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICByZXR1cm4ge30KCgpJTkRFWEVSX1RVTklOR19DT05GSUcgPSBfbG9hZF9pbmRleGVyX3R1bmluZ19jb25maWcoKQoKCmRlZiBfY29uZmlnX3N0cihlbnZfbmFtZTogc3RyLCBjb25maWdfa2V5OiBzdHIsIGRlZmF1bHQ6IHN0cikgLT4gc3RyOgogICAgZW52X3JhdyA9IG9zLmVudmlyb24uZ2V0KGVudl9uYW1lKQogICAgaWYgZW52X3JhdyBpcyBub3QgTm9uZSBhbmQgZW52X3Jhdy5zdHJpcCgpOgogICAgICAgIHJldHVybiBlbnZfcmF3CiAgICBjZmdfcmF3ID0gSU5ERVhFUl9UVU5JTkdfQ09ORklHLmdldChjb25maWdfa2V5KQogICAgaWYgaXNpbnN0YW5jZShjZmdfcmF3LCBzdHIpIGFuZCBjZmdfcmF3LnN0cmlwKCk6CiAgICAgICAgcmV0dXJuIGNmZ19yYXcKICAgIHJldHVybiBkZWZhdWx0CgoKZGVmIF9wYXJzZV9pbnQocmF3OiBvYmplY3QsIGRlZmF1bHQ6IGludCwgKiwgbWluX3ZhbHVlOiBpbnQgPSAxKSAtPiBpbnQ6CiAgICB0cnk6CiAgICAgICAgcGFyc2VkID0gaW50KHN0cihyYXcpLnN0cmlwKCkpCiAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgIHJldHVybiBtYXgobWluX3ZhbHVlLCBkZWZhdWx0KQogICAgcmV0dXJuIG1heChtaW5fdmFsdWUsIHBhcnNlZCkKCgpkZWYgX2V4dHJhY3RfY2hyb21hX2VuZHBvaW50X2Zyb21fY29uZmlnKGNvbmZpZ19wYXlsb2FkOiBvYmplY3QpIC0+IHR1cGxlW3N0ciwgc3RyLCBpbnRdOgogICAgc2NoZW1lID0gImh0dHAiCiAgICBob3N0ID0gImxvY2FsaG9zdCIKICAgIHBvcnQgPSA4MDAwCgogICAgZGVmIF9yZWFkX3NjaGVtZShyYXc6IG9iamVjdCkgLT4gTm9uZToKICAgICAgICBub25sb2NhbCBzY2hlbWUKICAgICAgICBpZiBub3QgaXNpbnN0YW5jZShyYXcsIHN0cik6CiAgICAgICAgICAgIHJldHVybgogICAgICAgIGxvd2VyZWQgPSByYXcuc3RyaXAoKS5sb3dlcigpCiAgICAgICAgaWYgbG93ZXJlZCBpbiB7Imh0dHAiLCAiaHR0cHMifToKICAgICAgICAgICAgc2NoZW1lID0gbG93ZXJlZAoKICAgIGRlZiBfcmVhZF9ob3N0KHJhdzogb2JqZWN0KSAtPiBOb25lOgogICAgICAgIG5vbmxvY2FsIHNjaGVtZSwgaG9zdCwgcG9ydAogICAgICAgIGlmIG5vdCBpc2luc3RhbmNlKHJhdywgc3RyKToKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgY2FuZGlkYXRlID0gcmF3LnN0cmlwKCkKICAgICAgICBpZiBub3QgY2FuZGlkYXRlOgogICAgICAgICAgICByZXR1cm4KICAgICAgICBwYXJzZWQgPSB1cmxwYXJzZShjYW5kaWRhdGUgaWYgIjovLyIgaW4gY2FuZGlkYXRlIGVsc2UgZiIvL3tjYW5kaWRhdGV9IikKICAgICAgICBpZiBwYXJzZWQuc2NoZW1lIGluIHsiaHR0cCIsICJodHRwcyJ9OgogICAgICAgICAgICBzY2hlbWUgPSBwYXJzZWQuc2NoZW1lCiAgICAgICAgaWYgcGFyc2VkLmhvc3RuYW1lOgogICAgICAgICAgICBob3N0ID0gcGFyc2VkLmhvc3RuYW1lCiAgICAgICAgZWxpZiAiOi8vIiBub3QgaW4gY2FuZGlkYXRlOgogICAgICAgICAgICBob3N0ID0gY2FuZGlkYXRlLnN0cmlwKCkuc3RyaXAoIi8iKQogICAgICAgIGlmIHBhcnNlZC5wb3J0IGFuZCAxIDw9IHBhcnNlZC5wb3J0IDw9IDY1NTM1OgogICAgICAgICAgICBwb3J0ID0gcGFyc2VkLnBvcnQKCiAgICBkZWYgX3JlYWRfcG9ydChyYXc6IG9iamVjdCkgLT4gTm9uZToKICAgICAgICBub25sb2NhbCBwb3J0CiAgICAgICAgdHJ5OgogICAgICAgICAgICBwYXJzZWQgPSBpbnQoc3RyKHJhdykuc3RyaXAoKSkKICAgICAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgICAgICByZXR1cm4KICAgICAgICBpZiAxIDw9IHBhcnNlZCA8PSA2NTUzNToKICAgICAgICAgICAgcG9ydCA9IHBhcnNlZAoKICAgIGlmIGlzaW5zdGFuY2UoY29uZmlnX3BheWxvYWQsIGRpY3QpOgogICAgICAgIGNocm9tYV9vYmogPSBjb25maWdfcGF5bG9hZC5nZXQoImNocm9tYSIpCiAgICAgICAgaWYgaXNpbnN0YW5jZShjaHJvbWFfb2JqLCBkaWN0KToKICAgICAgICAgICAgX3JlYWRfc2NoZW1lKGNocm9tYV9vYmouZ2V0KCJzY2hlbWUiKSkKICAgICAgICAgICAgX3JlYWRfaG9zdChjaHJvbWFfb2JqLmdldCgiaG9zdCIpKQogICAgICAgICAgICBfcmVhZF9wb3J0KGNocm9tYV9vYmouZ2V0KCJwb3J0IikpCgogICAgICAgICMgQ29tcGF0aWJpbGlkYWRlIGNvbSBmb3JtYXRvcyBmbGF0IGFudGlnb3MuCiAgICAgICAgX3JlYWRfc2NoZW1lKGNvbmZpZ19wYXlsb2FkLmdldCgiQ0hST01BX1NDSEVNRSIpKQogICAgICAgIF9yZWFkX2hvc3QoY29uZmlnX3BheWxvYWQuZ2V0KCJDSFJPTUFfSE9TVCIpKQogICAgICAgIF9yZWFkX3BvcnQoY29uZmlnX3BheWxvYWQuZ2V0KCJDSFJPTUFfUE9SVCIpKQoKICAgIHJldHVybiBzY2hlbWUsIGhvc3QsIHBvcnQKCgpkZWYgX2xvYWRfY2xpX2Nocm9tYV9kZWZhdWx0cygpIC0+IHR1cGxlW3N0ciwgc3RyLCBpbnRdOgogICAgY29uZmlnX3BhdGggPSBQYXRoKAogICAgICAgIG9zLmVudmlyb24uZ2V0KCJPV05fUkFHX0NMSV9DT05GSUdfRklMRSIsIHN0cihQYXRoLmhvbWUoKSAvICIub3duLXJhZy1jbGkuanNvbiIpKQogICAgKS5leHBhbmR1c2VyKCkKICAgIHRyeToKICAgICAgICBpZiBub3QgY29uZmlnX3BhdGguZXhpc3RzKCk6CiAgICAgICAgICAgIHJldHVybiAoImh0dHAiLCAibG9jYWxob3N0IiwgODAwMCkKICAgICAgICBwYXlsb2FkID0ganNvbi5sb2Fkcyhjb25maWdfcGF0aC5yZWFkX3RleHQoZW5jb2Rpbmc9InV0Zi04IikpCiAgICAgICAgcmV0dXJuIF9leHRyYWN0X2Nocm9tYV9lbmRwb2ludF9mcm9tX2NvbmZpZyhwYXlsb2FkKQogICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICByZXR1cm4gKCJodHRwIiwgImxvY2FsaG9zdCIsIDgwMDApCgoKZGVmIF9jb25maWdfaW50KGVudl9uYW1lOiBzdHIsIGNvbmZpZ19rZXk6IHN0ciwgZGVmYXVsdDogaW50LCAqLCBtaW5fdmFsdWU6IGludCA9IDEpIC0+IGludDoKICAgIGVudl9yYXcgPSBvcy5lbnZpcm9uLmdldChlbnZfbmFtZSkKICAgIGlmIGVudl9yYXcgaXMgbm90IE5vbmUgYW5kIGVudl9yYXcuc3RyaXAoKToKICAgICAgICB0cnk6CiAgICAgICAgICAgIHJldHVybiBtYXgobWluX3ZhbHVlLCBpbnQoZW52X3JhdykpCiAgICAgICAgZXhjZXB0IFZhbHVlRXJyb3I6CiAgICAgICAgICAgIHBhc3MKCiAgICBjZmdfcmF3ID0gSU5ERVhFUl9UVU5JTkdfQ09ORklHLmdldChjb25maWdfa2V5KQogICAgaWYgaXNpbnN0YW5jZShjZmdfcmF3LCBpbnQpOgogICAgICAgIHJldHVybiBtYXgobWluX3ZhbHVlLCBjZmdfcmF3KQogICAgaWYgaXNpbnN0YW5jZShjZmdfcmF3LCBzdHIpOgogICAgICAgIHRyeToKICAgICAgICAgICAgcmV0dXJuIG1heChtaW5fdmFsdWUsIGludChjZmdfcmF3KSkKICAgICAgICBleGNlcHQgVmFsdWVFcnJvcjoKICAgICAgICAgICAgcGFzcwoKICAgIHJldHVybiBtYXgobWluX3ZhbHVlLCBkZWZhdWx0KQoKCl9ERUZBVUxUX0NIUk9NQV9TQ0hFTUUsIF9ERUZBVUxUX0NIUk9NQV9IT1NULCBfREVGQVVMVF9DSFJPTUFfUE9SVCA9IF9sb2FkX2NsaV9jaHJvbWFfZGVmYXVsdHMoKQpDSFJPTUFfU0NIRU1FID0gKAogICAgb3MuZW52aXJvbi5nZXQoIkNIUk9NQV9TQ0hFTUUiKQogICAgb3Igb3MuZW52aXJvbi5nZXQoIk1DUF9DSFJPTUFfU0NIRU1FIikKICAgIG9yIF9ERUZBVUxUX0NIUk9NQV9TQ0hFTUUKKS5zdHJpcCgpLmxvd2VyKCkKaWYgQ0hST01BX1NDSEVNRSBub3QgaW4geyJodHRwIiwgImh0dHBzIn06CiAgICBDSFJPTUFfU0NIRU1FID0gX0RFRkFVTFRfQ0hST01BX1NDSEVNRQpDSFJPTUFfSE9TVCA9ICgKICAgIG9zLmVudmlyb24uZ2V0KCJDSFJPTUFfSE9TVCIpCiAgICBvciBvcy5lbnZpcm9uLmdldCgiTUNQX0NIUk9NQV9IT1NUIikKICAgIG9yIF9ERUZBVUxUX0NIUk9NQV9IT1NUCikuc3RyaXAoKSBvciBfREVGQVVMVF9DSFJPTUFfSE9TVApDSFJPTUFfUE9SVCA9IF9wYXJzZV9pbnQoCiAgICBvcy5lbnZpcm9uLmdldCgiQ0hST01BX1BPUlQiKQogICAgb3Igb3MuZW52aXJvbi5nZXQoIk1DUF9DSFJPTUFfUE9SVCIpCiAgICBvciBfREVGQVVMVF9DSFJPTUFfUE9SVCwKICAgIF9ERUZBVUxUX0NIUk9NQV9QT1JULAogICAgbWluX3ZhbHVlPTEsCikKQ0hST01BX1NTTCA9IENIUk9NQV9TQ0hFTUUgPT0gImh0dHBzIgoKIyBDb2xlw6fDtWVzIHNlcGFyYWRhcyBwb3IgZXNwZWNpYWxpemHDp8OjbyBkZSBlbWJlZGRpbmcKQ09MTEVDVElPTl9DT0RFX0pJTkEgPSAiY29kZV92ZWN0b3JzX2ppbmEiCkNPTExFQ1RJT05fRE9DX0JHRSA9ICJkb2NfdmVjdG9yc19iZ2UiCgpKSU5BX1YzX0VNQkVERElOR19NT0RFTCA9ICJqaW5hYWkvamluYS1lbWJlZGRpbmdzLXYzIgpKSU5BX1YyX0VNQkVERElOR19NT0RFTCA9ICJqaW5hYWkvamluYS1lbWJlZGRpbmdzLXYyLWJhc2UtY29kZSIKQkdFX0VNQkVERElOR19NT0RFTCA9ICJCQUFJL2JnZS1tMyIKCkRFRkFVTFRfRU1CRURESU5HX01PREVMX0NIT0lDRSA9ICJqaW5hIgpERUZBVUxUX0pJTkFfUVVBTlRJWkFUSU9OID0gImR5bmFtaWMtaW50OCIKREVGQVVMVF9TRUFSQ0hfTU9ERSA9ICJzaW5nbGUiICAjIHNpbmdsZSB8IGVuc2VtYmxlCgpfZW1iZWRkaW5nX21vZGVsX2Nob2ljZSA9IF9jb25maWdfc3RyKAogICAgIk1DUF9FTUJFRERJTkdfTU9ERUwiLAogICAgImVtYmVkZGluZ19tb2RlbCIsCiAgICBERUZBVUxUX0VNQkVERElOR19NT0RFTF9DSE9JQ0UsCikuc3RyaXAoKS5sb3dlcigpCmlmIF9lbWJlZGRpbmdfbW9kZWxfY2hvaWNlIG5vdCBpbiB7ImppbmEiLCAiYmdlIiwgImh5YnJpZCJ9OgogICAgbG9nLndhcm5pbmcoCiAgICAgICAgIk1DUF9FTUJFRERJTkdfTU9ERUwgaW52YWxpZG8gJyVzJy4gVXNhbmRvICclcycuIiwKICAgICAgICBfZW1iZWRkaW5nX21vZGVsX2Nob2ljZSwKICAgICAgICBERUZBVUxUX0VNQkVERElOR19NT0RFTF9DSE9JQ0UsCiAgICApCiAgICBfZW1iZWRkaW5nX21vZGVsX2Nob2ljZSA9IERFRkFVTFRfRU1CRURESU5HX01PREVMX0NIT0lDRQoKX3Jhd19qaW5hX3F1YW50aXphdGlvbiA9IF9jb25maWdfc3RyKAogICAgIk1DUF9KSU5BX1FVQU5USVpBVElPTiIsCiAgICAiamluYV9xdWFudGl6YXRpb24iLAogICAgREVGQVVMVF9KSU5BX1FVQU5USVpBVElPTiwKKQpKSU5BX1FVQU5USVpBVElPTiA9IF9yYXdfamluYV9xdWFudGl6YXRpb24uc3RyaXAoKS5sb3dlcigpLnJlcGxhY2UoIl8iLCAiLSIpCmlmIEpJTkFfUVVBTlRJWkFUSU9OIG5vdCBpbiB7ImRlZmF1bHQiLCAiZHluYW1pYy1pbnQ4In06CiAgICBsb2cud2FybmluZygKICAgICAgICAiTUNQX0pJTkFfUVVBTlRJWkFUSU9OIGludmFsaWRvICclcycuIFVzYW5kbyAnJXMnLiIsCiAgICAgICAgSklOQV9RVUFOVElaQVRJT04sCiAgICAgICAgREVGQVVMVF9KSU5BX1FVQU5USVpBVElPTiwKICAgICkKICAgIEpJTkFfUVVBTlRJWkFUSU9OID0gREVGQVVMVF9KSU5BX1FVQU5USVpBVElPTgoKU0VBUkNIX01PREVfREVGQVVMVCA9IG9zLmVudmlyb24uZ2V0KCJNQ1BfU0VBUkNIX01PREUiLCBERUZBVUxUX1NFQVJDSF9NT0RFKS5zdHJpcCgpLmxvd2VyKCkKaWYgU0VBUkNIX01PREVfREVGQVVMVCBub3QgaW4geyJzaW5nbGUiLCAiZW5zZW1ibGUifToKICAgIFNFQVJDSF9NT0RFX0RFRkFVTFQgPSBERUZBVUxUX1NFQVJDSF9NT0RFCgppZiBfZW1iZWRkaW5nX21vZGVsX2Nob2ljZSA9PSAiaHlicmlkIiBhbmQgIk1DUF9TRUFSQ0hfTU9ERSIgbm90IGluIG9zLmVudmlyb246CiAgICAjIE5vIG1vZG8gaMOtYnJpZG8sIG8gY29tcG9ydGFtZW50byBlc3BlcmFkbyBjb3N0dW1hIHNlciBlbnNlbWJsZSBwb3IgcGFkcsOjby4KICAgIFNFQVJDSF9NT0RFX0RFRkFVTFQgPSAiZW5zZW1ibGUiCgpSRVJBTktfTU9ERUxfSUQgPSBvcy5lbnZpcm9uLmdldCgiTUNQX1JFUkFOS19NT0RFTCIsICJjcm9zcy1lbmNvZGVyL21zLW1hcmNvLU1pbmlMTS1MLTYtdjIiKQpSRVJBTktfRU5BQkxFRCA9IG9zLmVudmlyb24uZ2V0KCJNQ1BfUkVSQU5LX0VOQUJMRUQiLCAidHJ1ZSIpLnN0cmlwKCkubG93ZXIoKSBpbiB7IjEiLCAidHJ1ZSIsICJ5ZXMiLCAib24ifQpSRVJBTktfQ0FORElEQVRFX01VTFRJUExJRVIgPSBpbnQob3MuZW52aXJvbi5nZXQoIk1DUF9SRVJBTktfQ0FORElEQVRFX01VTFRJUExJRVIiLCAiMyIpKQpSRVJBTktfTUFYX0NBTkRJREFURVMgPSBpbnQob3MuZW52aXJvbi5nZXQoIk1DUF9SRVJBTktfTUFYX0NBTkRJREFURVMiLCAiNDAiKSkKUkVSQU5LRVJfTUFYX0xFTkdUSCA9IGludChvcy5lbnZpcm9uLmdldCgiTUNQX1JFUkFOS19NQVhfTEVOR1RIIiwgIjUxMiIpKQpSRVJBTktFUl9RVUFOVElaQVRJT04gPSBvcy5lbnZpcm9uLmdldCgiTUNQX1JFUkFOS19RVUFOVElaQVRJT04iLCAiZHluYW1pYy1pbnQ4Iikuc3RyaXAoKS5sb3dlcigpCmlmIFJFUkFOS0VSX1FVQU5USVpBVElPTiBub3QgaW4geyJkZWZhdWx0IiwgImR5bmFtaWMtaW50OCJ9OgogICAgUkVSQU5LRVJfUVVBTlRJWkFUSU9OID0gImR5bmFtaWMtaW50OCIKClJSRl9LID0gaW50KG9zLmVudmlyb24uZ2V0KCJNQ1BfUlJGX0siLCAiNjAiKSkKRU1CRURESU5HX0JBVENIX1NJWkUgPSBfY29uZmlnX2ludCgiTUNQX0VNQkVERElOR19CQVRDSF9TSVpFIiwgImVtYmVkZGluZ19iYXRjaF9zaXplIiwgNCwgbWluX3ZhbHVlPTEpCgpfZW52X21vZGVsX2RpciA9IG9zLmVudmlyb24uZ2V0KCJNQ1BfTU9ERUxfRElSIikKTU9ERUxfRElSID0gKAogICAgUGF0aChfZW52X21vZGVsX2RpcikuZXhwYW5kdXNlcigpCiAgICBpZiBfZW52X21vZGVsX2RpcgogICAgZWxzZSBQYXRoLmhvbWUoKSAvICIuY2FjaGUiIC8gIm93bi1yYWctY2xpIiAvICJtb2RlbHMiCikKCiMgUGFyw6JtZXRyb3MgZG8gc3BsaXR0ZXIgKGFsaW5oYWRvcyBjb20gaW5kZXhlcl9mdWxsLnB5LCBwZXJmaWwgbG93LW1lbW9yeSkKQ0hVTktfU0laRSA9IF9jb25maWdfaW50KCJNQ1BfQ0hVTktfU0laRSIsICJjaHVua19zaXplIiwgMzAwMCwgbWluX3ZhbHVlPTI1NikKQ0hVTktfT1ZFUkxBUCA9IG1pbihDSFVOS19TSVpFIC0gMSwgX2NvbmZpZ19pbnQoIk1DUF9DSFVOS19PVkVSTEFQIiwgImNodW5rX292ZXJsYXAiLCA0MDAsIG1pbl92YWx1ZT0wKSkKCk1BWF9GSUxFX1NJWkVfQllURVMgPSA1MDAgKiAxMDI0ICAjIDUwMCBLQgpUT1BfS19SRVNVTFRTID0gNwpNQVhfUVVFUllfUkVTVUxUUyA9IDMwCgojIEZpbHRyb3MgZGUgdmFycmVkdXJhCklHTk9SRURfRElSUyA9IHsKICAgICIuZ2l0IiwgIm5vZGVfbW9kdWxlcyIsICJfX3B5Y2FjaGVfXyIsICIudmVudiIsICJ2ZW52IiwgImVudiIsCiAgICAiZGlzdCIsICJidWlsZCIsICJvdXQiLCAiLm5leHQiLCAiLm51eHQiLCAiLmNhY2hlIiwgImNvdmVyYWdlIiwKICAgICIucHl0ZXN0X2NhY2hlIiwgIi5teXB5X2NhY2hlIiwgIi5ydWZmX2NhY2hlIiwgInRhcmdldCIsICJiaW4iLCAib2JqIiwKICAgICIuaWRlYSIsICIudnNjb2RlIiwgInZlbmRvciIsICJ0bXAiLCAidGVtcCIsICJsb2dzIiwgIi5yYWdfZGIiLAp9CgpJR05PUkVEX0VYVEVOU0lPTlMgPSB7CiAgICAiLnBuZyIsICIuanBnIiwgIi5qcGVnIiwgIi5naWYiLCAiLnN2ZyIsICIuaWNvIiwgIi53ZWJwIiwgIi5ibXAiLAogICAgIi5tcDQiLCAiLm1wMyIsICIud2F2IiwgIi5vZ2ciLCAiLmF2aSIsICIubW92IiwKICAgICIuemlwIiwgIi50YXIiLCAiLmd6IiwgIi5yYXIiLCAiLjd6IiwgIi5qYXIiLCAiLndhciIsCiAgICAiLnB5YyIsICIucHlvIiwgIi5zbyIsICIuZGxsIiwgIi5leGUiLCAiLmJpbiIsCiAgICAiLmxvY2siLCAiLnN1bSIsICIuc3FsaXRlIiwgIi5kYiIsICIuc3FsaXRlMyIsCiAgICAiLnR0ZiIsICIud29mZiIsICIud29mZjIiLCAiLmVvdCIsCiAgICAiLnBkZiIsICIuZG9jeCIsICIueGxzeCIsICIucHB0eCIsCn0KCkNPREVfRVhURU5TSU9OUyA9IHsKICAgICIucHkiLCAiLmpzIiwgIi50cyIsICIudHN4IiwgIi5qc3giLCAiLmphdmEiLCAiLmMiLCAiLmgiLCAiLmNwcCIsICIuaHBwIiwKICAgICIuZ28iLCAiLnJzIiwgIi5yYiIsICIucGhwIiwgIi5jcyIsICIuc3dpZnQiLCAiLmt0IiwgIi5rdHMiLCAiLnNjYWxhIiwgIi5zcWwiLAogICAgIi5zaCIsICIuYmFzaCIsICIuenNoIiwgIi5wczEiLCAiLnlhbWwiLCAiLnltbCIsICIudG9tbCIsICIuaW5pIiwgIi5jb25mIiwKICAgICIuanNvbiIsICIueG1sIiwgIi5odG1sIiwgIi5jc3MiLCAiLnNjc3MiLCAiLnNhc3MiLCAiLnZ1ZSIsICIuc3ZlbHRlIiwgIi5kYXJ0IiwKICAgICIubHVhIiwgIi5yIiwgIi5tIiwgIi5tbSIsCn0KCkRPQ19FWFRFTlNJT05TID0gewogICAgIi5tZCIsICIubWR4IiwgIi5yc3QiLCAiLnR4dCIsICIuYWRvYyIsICIub3JnIiwgIi50ZXgiLCAiLmNzdiIsCn0KCgpAZGF0YWNsYXNzKGZyb3plbj1UcnVlKQpjbGFzcyBCcmFuY2hTcGVjOgogICAga2V5OiBzdHIKICAgIG1vZGVsX2Nob2ljZTogc3RyCiAgICBtb2RlbF9pZDogc3RyCiAgICBjb2xsZWN0aW9uX25hbWU6IHN0cgogICAgY29udGVudF9kb21haW46IHN0cgogICAgbGFiZWw6IHN0cgoKCkpJTkFfQ09ERV9CUkFOQ0hfTU9ERUxfQ0hPSUNFID0gImppbmFfdjIiIGlmIF9lbWJlZGRpbmdfbW9kZWxfY2hvaWNlID09ICJoeWJyaWQiIGVsc2UgImppbmEiCkpJTkFfQ09ERV9CUkFOQ0hfTU9ERUxfSUQgPSBKSU5BX1YyX0VNQkVERElOR19NT0RFTCBpZiBfZW1iZWRkaW5nX21vZGVsX2Nob2ljZSA9PSAiaHlicmlkIiBlbHNlIEpJTkFfVjNfRU1CRURESU5HX01PREVMCgpCUkFOQ0hfU1BFQ1M6IGRpY3Rbc3RyLCBCcmFuY2hTcGVjXSA9IHsKICAgICJqaW5hX2NvZGUiOiBCcmFuY2hTcGVjKAogICAgICAgIGtleT0iamluYV9jb2RlIiwKICAgICAgICBtb2RlbF9jaG9pY2U9SklOQV9DT0RFX0JSQU5DSF9NT0RFTF9DSE9JQ0UsCiAgICAgICAgbW9kZWxfaWQ9SklOQV9DT0RFX0JSQU5DSF9NT0RFTF9JRCwKICAgICAgICBjb2xsZWN0aW9uX25hbWU9Q09MTEVDVElPTl9DT0RFX0pJTkEsCiAgICAgICAgY29udGVudF9kb21haW49ImNvZGUiLAogICAgICAgIGxhYmVsPSJKaW5hIHYyIENvZGUiIGlmIF9lbWJlZGRpbmdfbW9kZWxfY2hvaWNlID09ICJoeWJyaWQiIGVsc2UgIkppbmEgdjMgQ29kZSIsCiAgICApLAogICAgImJnZV9kb2MiOiBCcmFuY2hTcGVjKAogICAgICAgIGtleT0iYmdlX2RvYyIsCiAgICAgICAgbW9kZWxfY2hvaWNlPSJiZ2UiLAogICAgICAgIG1vZGVsX2lkPUJHRV9FTUJFRERJTkdfTU9ERUwsCiAgICAgICAgY29sbGVjdGlvbl9uYW1lPUNPTExFQ1RJT05fRE9DX0JHRSwKICAgICAgICBjb250ZW50X2RvbWFpbj0iZG9jIiwKICAgICAgICBsYWJlbD0iQkdFIERvY3MiLAogICAgKSwKfQoKREVGQVVMVF9TSU5HTEVfQlJBTkNIX0tFWSA9ICJiZ2VfZG9jIiBpZiBfZW1iZWRkaW5nX21vZGVsX2Nob2ljZSA9PSAiYmdlIiBlbHNlICJqaW5hX2NvZGUiCgoKQGRhdGFjbGFzcwpjbGFzcyBSZXRyaWV2ZWRIaXQ6CiAgICBrZXk6IHN0cgogICAgZG9jdW1lbnQ6IHN0cgogICAgbWV0YWRhdGE6IGRpY3Rbc3RyLCBvYmplY3RdCiAgICBkaXN0YW5jZTogZmxvYXQgfCBOb25lCiAgICBzaW1pbGFyaXR5OiBmbG9hdCB8IE5vbmUKICAgIGJyYW5jaDogQnJhbmNoU3BlYwogICAgcmFuazogaW50CgoKQGRhdGFjbGFzcwpjbGFzcyBGdXNlZEhpdDoKICAgIGtleTogc3RyCiAgICBkb2N1bWVudDogc3RyCiAgICBtZXRhZGF0YTogZGljdFtzdHIsIG9iamVjdF0KICAgIHJyZl9zY29yZTogZmxvYXQKICAgIHNvdXJjZV9kZXRhaWxzOiBkaWN0W3N0ciwgZGljdFtzdHIsIG9iamVjdF1dCiAgICByZXJhbmtfc2NvcmU6IGZsb2F0IHwgTm9uZSA9IE5vbmUKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIFJ1bnRpbWUgY2FjaGVzIChsYXp5IGxvYWRpbmcgcGFyYSBlY29ub21pemFyIFJBTSkKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCl9jaHJvbWFfY2xpZW50OiBjaHJvbWFkYi5IdHRwQ2xpZW50IHwgTm9uZSA9IE5vbmUKX2NvbGxlY3Rpb25zOiBkaWN0W3N0ciwgY2hyb21hZGIuQ29sbGVjdGlvbl0gPSB7fQpfbW9kZWxzOiBkaWN0W3N0ciwgU2VudGVuY2VUcmFuc2Zvcm1lcl0gPSB7fQpfbW9kZWxfbG9hZF9lcnJvcnM6IGRpY3Rbc3RyLCBzdHJdID0ge30KX3NwbGl0dGVyOiBSZWN1cnNpdmVDaGFyYWN0ZXJUZXh0U3BsaXR0ZXIgfCBOb25lID0gTm9uZQpfcmVyYW5rZXI6IENyb3NzRW5jb2RlciB8IE5vbmUgPSBOb25lCl9yZXJhbmtlcl9lcnJvcjogc3RyIHwgTm9uZSA9IE5vbmUKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIENocm9tYSBlIG1vZGVsb3MKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCgpkZWYgX21vZGVsX2NhY2hlX2RpcihiYXNlX2RpcjogUGF0aCwgbW9kZWxfaWQ6IHN0cikgLT4gUGF0aDoKICAgIHNhZmVfbmFtZSA9IG1vZGVsX2lkLnJlcGxhY2UoIi8iLCAiX18iKS5yZXBsYWNlKCI6IiwgIl8iKQogICAgcmV0dXJuIGJhc2VfZGlyIC8gc2FmZV9uYW1lCgoKZGVmIF9nZXRfY2hyb21hX2NsaWVudCgpIC0+IGNocm9tYWRiLkh0dHBDbGllbnQ6CiAgICBnbG9iYWwgX2Nocm9tYV9jbGllbnQKICAgIGlmIF9jaHJvbWFfY2xpZW50IGlzIE5vbmU6CiAgICAgICAgX2Nocm9tYV9jbGllbnQgPSBjaHJvbWFkYi5IdHRwQ2xpZW50KGhvc3Q9Q0hST01BX0hPU1QsIHBvcnQ9Q0hST01BX1BPUlQsIHNzbD1DSFJPTUFfU1NMKQogICAgICAgIF9jaHJvbWFfY2xpZW50LmhlYXJ0YmVhdCgpCiAgICAgICAgbG9nLmluZm8oIkNvbmVjdGFkbyBhbyBDaHJvbWFEQiBlbSAlczovLyVzOiVzIiwgQ0hST01BX1NDSEVNRSwgQ0hST01BX0hPU1QsIENIUk9NQV9QT1JUKQogICAgcmV0dXJuIF9jaHJvbWFfY2xpZW50CgoKZGVmIGdldF9jaHJvbWFfY29sbGVjdGlvbihjb2xsZWN0aW9uX25hbWU6IHN0cikgLT4gY2hyb21hZGIuQ29sbGVjdGlvbjoKICAgIGlmIGNvbGxlY3Rpb25fbmFtZSBpbiBfY29sbGVjdGlvbnM6CiAgICAgICAgcmV0dXJuIF9jb2xsZWN0aW9uc1tjb2xsZWN0aW9uX25hbWVdCgogICAgdHJ5OgogICAgICAgIGNsaWVudCA9IF9nZXRfY2hyb21hX2NsaWVudCgpCiAgICAgICAgY29sbGVjdGlvbiA9IGNsaWVudC5nZXRfb3JfY3JlYXRlX2NvbGxlY3Rpb24oCiAgICAgICAgICAgIG5hbWU9Y29sbGVjdGlvbl9uYW1lLAogICAgICAgICAgICBtZXRhZGF0YT17Imhuc3c6c3BhY2UiOiAiY29zaW5lIn0sCiAgICAgICAgKQogICAgICAgIF9jb2xsZWN0aW9uc1tjb2xsZWN0aW9uX25hbWVdID0gY29sbGVjdGlvbgogICAgICAgIHJldHVybiBjb2xsZWN0aW9uCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgcmFpc2UgUnVudGltZUVycm9yKAogICAgICAgICAgICBmIk7Do28gZm9pIHBvc3PDrXZlbCBhY2Vzc2FyIGEgY29sZcOnw6NvICd7Y29sbGVjdGlvbl9uYW1lfScgbm8gQ2hyb21hREIgIgogICAgICAgICAgICBmIih7Q0hST01BX1NDSEVNRX06Ly97Q0hST01BX0hPU1R9OntDSFJPTUFfUE9SVH0pLiBFcnJvOiB7ZX0iCiAgICAgICAgKQoKCmRlZiBfbG9hZF9zZW50ZW5jZV90cmFuc2Zvcm1lcl9mcm9tX2xvY2FsKG1vZGVsX2lkOiBzdHIsIGxvY2FsX21vZGVsX2RpcjogUGF0aCkgLT4gU2VudGVuY2VUcmFuc2Zvcm1lcjoKICAgIHRydXN0X3JlbW90ZV9jb2RlID0gbW9kZWxfaWQuc3RhcnRzd2l0aCgiamluYWFpLyIpCiAgICB0b2tlbml6ZXJfa3dhcmdzID0geyJmaXhfbWlzdHJhbF9yZWdleCI6IFRydWV9CgogICAgZGVmIF9pbnN0YW50aWF0ZV9tb2RlbCgpIC0+IFNlbnRlbmNlVHJhbnNmb3JtZXI6CiAgICAgICAgcmV0dXJuIFNlbnRlbmNlVHJhbnNmb3JtZXIoCiAgICAgICAgICAgIHN0cihsb2NhbF9tb2RlbF9kaXIpLAogICAgICAgICAgICBkZXZpY2U9ImNwdSIsCiAgICAgICAgICAgIHRydXN0X3JlbW90ZV9jb2RlPXRydXN0X3JlbW90ZV9jb2RlLAogICAgICAgICAgICB0b2tlbml6ZXJfa3dhcmdzPXRva2VuaXplcl9rd2FyZ3MsCiAgICAgICAgKQoKICAgIGRlZiBfY2xlYXJfaGZfZHluYW1pY19tb2R1bGVzX2NhY2hlKCkgLT4gTm9uZToKICAgICAgICBjYWNoZV9kaXIgPSBQYXRoLmhvbWUoKSAvICIuY2FjaGUiIC8gImh1Z2dpbmdmYWNlIiAvICJtb2R1bGVzIiAvICJ0cmFuc2Zvcm1lcnNfbW9kdWxlcyIKICAgICAgICBpZiBjYWNoZV9kaXIuZXhpc3RzKCk6CiAgICAgICAgICAgIGxvZy53YXJuaW5nKCJMaW1wYW5kbyBjYWNoZSBkaW7Dom1pY28gZG8gSHVnZ2luZyBGYWNlIGVtICVzIiwgY2FjaGVfZGlyKQogICAgICAgICAgICBzaHV0aWwucm10cmVlKGNhY2hlX2RpciwgaWdub3JlX2Vycm9ycz1UcnVlKQoKICAgIGRlZiBfbG9hZF93aXRoX2ppbmFfcGF0Y2goKSAtPiBTZW50ZW5jZVRyYW5zZm9ybWVyOgogICAgICAgIGlmIG5vdCB0cnVzdF9yZW1vdGVfY29kZToKICAgICAgICAgICAgcmV0dXJuIF9pbnN0YW50aWF0ZV9tb2RlbCgpCgogICAgICAgIGZyb20gdHJhbnNmb3JtZXJzIGltcG9ydCBBdXRvTW9kZWwsIEF1dG9Ub2tlbml6ZXIKICAgICAgICBmcm9tIHRyYW5zZm9ybWVycy5tb2RlbGluZ191dGlscyBpbXBvcnQgUHJlVHJhaW5lZE1vZGVsCgogICAgICAgIG9yaWdpbmFsX2Zyb21fcHJldHJhaW5lZCA9IEF1dG9Ub2tlbml6ZXIuZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgb3JpZ2luYWxfbW9kZWxfZnJvbV9wcmV0cmFpbmVkID0gQXV0b01vZGVsLmZyb21fcHJldHJhaW5lZAogICAgICAgIG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9wcmV0cmFpbmVkID0gUHJlVHJhaW5lZE1vZGVsLmZyb21fcHJldHJhaW5lZAogICAgICAgIG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9jb25maWcgPSBQcmVUcmFpbmVkTW9kZWwuX2Zyb21fY29uZmlnCiAgICAgICAgbW9kZWxfcmVmcyA9IHtzdHIobG9jYWxfbW9kZWxfZGlyKSwgc3RyKGxvY2FsX21vZGVsX2Rpci5yZXNvbHZlKCkpfQoKICAgICAgICBkZWYgX3BhdGNoZWRfZnJvbV9wcmV0cmFpbmVkKCphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgICAgIG1vZGVsX3JlZiA9IGFyZ3NbMF0gaWYgYXJncyBlbHNlIGt3YXJncy5nZXQoInByZXRyYWluZWRfbW9kZWxfbmFtZV9vcl9wYXRoIikKICAgICAgICAgICAgaWYgbW9kZWxfcmVmIGlzIG5vdCBOb25lIGFuZCBzdHIobW9kZWxfcmVmKSBpbiBtb2RlbF9yZWZzOgogICAgICAgICAgICAgICAga3dhcmdzLnNldGRlZmF1bHQoImZpeF9taXN0cmFsX3JlZ2V4IiwgVHJ1ZSkKICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsX2Zyb21fcHJldHJhaW5lZCgqYXJncywgKiprd2FyZ3MpCgogICAgICAgIGRlZiBfcGF0Y2hlZF9tb2RlbF9mcm9tX3ByZXRyYWluZWQoKmFyZ3MsICoqa3dhcmdzKToKICAgICAgICAgICAgbW9kZWxfcmVmID0gYXJnc1swXSBpZiBhcmdzIGVsc2Uga3dhcmdzLmdldCgicHJldHJhaW5lZF9tb2RlbF9uYW1lX29yX3BhdGgiKQogICAgICAgICAgICBpZiBtb2RlbF9yZWYgaXMgbm90IE5vbmUgYW5kIHN0cihtb2RlbF9yZWYpIGluIG1vZGVsX3JlZnMgYW5kICJ0b3JjaF9kdHlwZSIgaW4ga3dhcmdzOgogICAgICAgICAgICAgICAga3dhcmdzID0gZGljdChrd2FyZ3MpCiAgICAgICAgICAgICAgICBpZiAiZHR5cGUiIG5vdCBpbiBrd2FyZ3M6CiAgICAgICAgICAgICAgICAgICAga3dhcmdzWyJkdHlwZSJdID0ga3dhcmdzWyJ0b3JjaF9kdHlwZSJdCiAgICAgICAgICAgICAgICBrd2FyZ3MucG9wKCJ0b3JjaF9kdHlwZSIsIE5vbmUpCiAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbF9tb2RlbF9mcm9tX3ByZXRyYWluZWQoKmFyZ3MsICoqa3dhcmdzKQoKICAgICAgICBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fcHJldHJhaW5lZF9mbiA9IG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9wcmV0cmFpbmVkLl9fZnVuY19fCgogICAgICAgIEBjbGFzc21ldGhvZAogICAgICAgIGRlZiBfcGF0Y2hlZF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fcHJldHJhaW5lZChjbHMsICphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgICAgIGlmICJ0b3JjaF9kdHlwZSIgaW4ga3dhcmdzOgogICAgICAgICAgICAgICAga3dhcmdzID0gZGljdChrd2FyZ3MpCiAgICAgICAgICAgICAgICBpZiAiZHR5cGUiIG5vdCBpbiBrd2FyZ3M6CiAgICAgICAgICAgICAgICAgICAga3dhcmdzWyJkdHlwZSJdID0ga3dhcmdzWyJ0b3JjaF9kdHlwZSJdCiAgICAgICAgICAgICAgICBrd2FyZ3MucG9wKCJ0b3JjaF9kdHlwZSIsIE5vbmUpCiAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fcHJldHJhaW5lZF9mbihjbHMsICphcmdzLCAqKmt3YXJncykKCiAgICAgICAgb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX2NvbmZpZ19mbiA9IG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9jb25maWcuX19mdW5jX18KCiAgICAgICAgQGNsYXNzbWV0aG9kCiAgICAgICAgZGVmIF9wYXRjaGVkX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9jb25maWcoY2xzLCAqYXJncywgKiprd2FyZ3MpOgogICAgICAgICAgICBpZiAidG9yY2hfZHR5cGUiIGluIGt3YXJnczoKICAgICAgICAgICAgICAgIGt3YXJncyA9IGRpY3Qoa3dhcmdzKQogICAgICAgICAgICAgICAgaWYgImR0eXBlIiBub3QgaW4ga3dhcmdzOgogICAgICAgICAgICAgICAgICAgIGt3YXJnc1siZHR5cGUiXSA9IGt3YXJnc1sidG9yY2hfZHR5cGUiXQogICAgICAgICAgICAgICAga3dhcmdzLnBvcCgidG9yY2hfZHR5cGUiLCBOb25lKQogICAgICAgICAgICByZXR1cm4gb3JpZ2luYWxfcHJldHJhaW5lZF9tb2RlbF9mcm9tX2NvbmZpZ19mbihjbHMsICphcmdzLCAqKmt3YXJncykKCiAgICAgICAgQXV0b1Rva2VuaXplci5mcm9tX3ByZXRyYWluZWQgPSBfcGF0Y2hlZF9mcm9tX3ByZXRyYWluZWQKICAgICAgICBBdXRvTW9kZWwuZnJvbV9wcmV0cmFpbmVkID0gX3BhdGNoZWRfbW9kZWxfZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgUHJlVHJhaW5lZE1vZGVsLmZyb21fcHJldHJhaW5lZCA9IF9wYXRjaGVkX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgUHJlVHJhaW5lZE1vZGVsLl9mcm9tX2NvbmZpZyA9IF9wYXRjaGVkX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9jb25maWcKICAgICAgICB0cnk6CiAgICAgICAgICAgIHJldHVybiBfaW5zdGFudGlhdGVfbW9kZWwoKQogICAgICAgIGZpbmFsbHk6CiAgICAgICAgICAgIEF1dG9Ub2tlbml6ZXIuZnJvbV9wcmV0cmFpbmVkID0gb3JpZ2luYWxfZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgICAgIEF1dG9Nb2RlbC5mcm9tX3ByZXRyYWluZWQgPSBvcmlnaW5hbF9tb2RlbF9mcm9tX3ByZXRyYWluZWQKICAgICAgICAgICAgUHJlVHJhaW5lZE1vZGVsLmZyb21fcHJldHJhaW5lZCA9IG9yaWdpbmFsX3ByZXRyYWluZWRfbW9kZWxfZnJvbV9wcmV0cmFpbmVkCiAgICAgICAgICAgIFByZVRyYWluZWRNb2RlbC5fZnJvbV9jb25maWcgPSBvcmlnaW5hbF9wcmV0cmFpbmVkX21vZGVsX2Zyb21fY29uZmlnCgogICAgdHJ5OgogICAgICAgIHJldHVybiBfbG9hZF93aXRoX2ppbmFfcGF0Y2goKQogICAgZXhjZXB0IEZpbGVOb3RGb3VuZEVycm9yIGFzIGU6CiAgICAgICAgaWYgdHJ1c3RfcmVtb3RlX2NvZGUgYW5kICJ0cmFuc2Zvcm1lcnNfbW9kdWxlcyIgaW4gc3RyKGUpOgogICAgICAgICAgICBsb2cud2FybmluZygiQ2FjaGUgZGluw6JtaWNvIGluY29uc2lzdGVudGUgZGV0ZWN0YWRvOiAlcyIsIGUpCiAgICAgICAgICAgIF9jbGVhcl9oZl9keW5hbWljX21vZHVsZXNfY2FjaGUoKQogICAgICAgICAgICByZXR1cm4gX2xvYWRfd2l0aF9qaW5hX3BhdGNoKCkKICAgICAgICByYWlzZQoKCmRlZiBfYXBwbHlfamluYV9xdWFudGl6YXRpb25faWZfbmVlZGVkKG1vZGVsOiBTZW50ZW5jZVRyYW5zZm9ybWVyLCBtb2RlbF9pZDogc3RyKSAtPiBTZW50ZW5jZVRyYW5zZm9ybWVyOgogICAgaWYgbW9kZWxfaWQgIT0gSklOQV9WM19FTUJFRERJTkdfTU9ERUwgb3IgSklOQV9RVUFOVElaQVRJT04gPT0gImRlZmF1bHQiOgogICAgICAgIHJldHVybiBtb2RlbAoKICAgIHRyeToKICAgICAgICBpbXBvcnQgdG9yY2gKICAgICAgICBpbXBvcnQgd2FybmluZ3MKCiAgICAgICAgcXVhbnRpemVkX2xheWVycyA9IDAKICAgICAgICBmb3IgbW9kdWxlIGluIG1vZGVsLm1vZHVsZXMoKToKICAgICAgICAgICAgaWYgdHlwZShtb2R1bGUpLl9fbmFtZV9fICE9ICJQYXJhbWV0cml6ZWRMaW5lYXIiOgogICAgICAgICAgICAgICAgY29udGludWUKCiAgICAgICAgICAgIGZsb2F0X2xpbmVhciA9IHRvcmNoLm5uLkxpbmVhcigKICAgICAgICAgICAgICAgIG1vZHVsZS5pbl9mZWF0dXJlcywKICAgICAgICAgICAgICAgIG1vZHVsZS5vdXRfZmVhdHVyZXMsCiAgICAgICAgICAgICAgICBiaWFzPW1vZHVsZS5iaWFzIGlzIG5vdCBOb25lLAogICAgICAgICAgICApCiAgICAgICAgICAgIHdpdGggdG9yY2gubm9fZ3JhZCgpOgogICAgICAgICAgICAgICAgZmxvYXRfbGluZWFyLndlaWdodC5jb3B5Xyhtb2R1bGUud2VpZ2h0LmRldGFjaCgpLnRvKHRvcmNoLmZsb2F0MzIpKQogICAgICAgICAgICAgICAgaWYgbW9kdWxlLmJpYXMgaXMgbm90IE5vbmU6CiAgICAgICAgICAgICAgICAgICAgZmxvYXRfbGluZWFyLmJpYXMuY29weV8obW9kdWxlLmJpYXMuZGV0YWNoKCkudG8odG9yY2guZmxvYXQzMikpCgogICAgICAgICAgICB3aXRoIHdhcm5pbmdzLmNhdGNoX3dhcm5pbmdzKCk6CiAgICAgICAgICAgICAgICB3YXJuaW5ncy5maWx0ZXJ3YXJuaW5ncygiaWdub3JlIiwgY2F0ZWdvcnk9RGVwcmVjYXRpb25XYXJuaW5nKQogICAgICAgICAgICAgICAgcXVhbnRpemVkX2xpbmVhciA9IHRvcmNoLnF1YW50aXphdGlvbi5xdWFudGl6ZV9keW5hbWljKAogICAgICAgICAgICAgICAgICAgIHRvcmNoLm5uLlNlcXVlbnRpYWwoZmxvYXRfbGluZWFyKSwKICAgICAgICAgICAgICAgICAgICB7dG9yY2gubm4uTGluZWFyfSwKICAgICAgICAgICAgICAgICAgICBkdHlwZT10b3JjaC5xaW50OCwKICAgICAgICAgICAgICAgIClbMF0KCiAgICAgICAgICAgIG1vZHVsZS5fZHluYW1pY19pbnQ4X2xpbmVhciA9IHF1YW50aXplZF9saW5lYXIKCiAgICAgICAgICAgIGRlZiBfZm9yd2FyZF9keW5hbWljX2ludDgoc2VsZiwgaW5wdXQsIHRhc2tfaWQ9Tm9uZSwgcmVzaWR1YWw9RmFsc2UpOgogICAgICAgICAgICAgICAgb3V0ID0gc2VsZi5fZHluYW1pY19pbnQ4X2xpbmVhcihpbnB1dCkKICAgICAgICAgICAgICAgIGlmIHJlc2lkdWFsOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXQsIGlucHV0CiAgICAgICAgICAgICAgICByZXR1cm4gb3V0CgogICAgICAgICAgICBtb2R1bGUuZm9yd2FyZCA9IF9mb3J3YXJkX2R5bmFtaWNfaW50OC5fX2dldF9fKG1vZHVsZSwgbW9kdWxlLl9fY2xhc3NfXykKICAgICAgICAgICAgcXVhbnRpemVkX2xheWVycyArPSAxCgogICAgICAgIGlmIHF1YW50aXplZF9sYXllcnMgPT0gMDoKICAgICAgICAgICAgbG9nLndhcm5pbmcoIk5lbmh1bWEgY2FtYWRhIFBhcmFtZXRyaXplZExpbmVhciBlbmNvbnRyYWRhIHBhcmEgZHluYW1pYy1pbnQ4IG5vIEppbmEuIikKICAgICAgICAgICAgcmV0dXJuIG1vZGVsCgogICAgICAgIGxvZy5pbmZvKCJRdWFudGl6YWNhbyBKaW5hIGFwbGljYWRhOiBkeW5hbWljLWludDggKENQVSwgJXMgY2FtYWRhcykuIiwgcXVhbnRpemVkX2xheWVycykKICAgICAgICByZXR1cm4gbW9kZWwKICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgcXVhbnRfZXJyb3I6CiAgICAgICAgbG9nLndhcm5pbmcoIkZhbGhhIGFvIGFwbGljYXIgZHluYW1pYy1pbnQ4IG5vIEppbmEgKCVzKTsgdXNhbmRvIG1vZGVsbyBwYWRyYW8uIiwgcXVhbnRfZXJyb3IpCiAgICAgICAgcmV0dXJuIG1vZGVsCgoKZGVmIGdldF9lbWJlZGRpbmdfbW9kZWwobW9kZWxfY2hvaWNlOiBzdHIpIC0+IFNlbnRlbmNlVHJhbnNmb3JtZXI6CiAgICBpZiBtb2RlbF9jaG9pY2UgaW4gX21vZGVsczoKICAgICAgICByZXR1cm4gX21vZGVsc1ttb2RlbF9jaG9pY2VdCgogICAgaWYgbW9kZWxfY2hvaWNlIGluIF9tb2RlbF9sb2FkX2Vycm9yczoKICAgICAgICByYWlzZSBSdW50aW1lRXJyb3IoX21vZGVsX2xvYWRfZXJyb3JzW21vZGVsX2Nob2ljZV0pCgogICAgaWYgbW9kZWxfY2hvaWNlID09ICJqaW5hIjoKICAgICAgICBtb2RlbF9pZCA9IEpJTkFfVjNfRU1CRURESU5HX01PREVMCiAgICBlbGlmIG1vZGVsX2Nob2ljZSA9PSAiamluYV92MiI6CiAgICAgICAgbW9kZWxfaWQgPSBKSU5BX1YyX0VNQkVERElOR19NT0RFTAogICAgZWxpZiBtb2RlbF9jaG9pY2UgPT0gImJnZSI6CiAgICAgICAgbW9kZWxfaWQgPSBCR0VfRU1CRURESU5HX01PREVMCiAgICBlbHNlOgogICAgICAgIHJhaXNlIFJ1bnRpbWVFcnJvcihmIk1vZGVsbyBuw6NvIHN1cG9ydGFkbzoge21vZGVsX2Nob2ljZX0iKQoKICAgIHRyeToKICAgICAgICBNT0RFTF9ESVIubWtkaXIocGFyZW50cz1UcnVlLCBleGlzdF9vaz1UcnVlKQogICAgICAgIHByZWZlcnJlZF9tb2RlbF9jYWNoZV9kaXIgPSBfbW9kZWxfY2FjaGVfZGlyKE1PREVMX0RJUiwgbW9kZWxfaWQpCiAgICAgICAgbG9nLmluZm8oIkNhcnJlZ2FuZG8gZW1iZWRkaW5ncyAnJXMnIGVtIENQVSAoY2FjaGU6ICVzKSIsIG1vZGVsX2lkLCBwcmVmZXJyZWRfbW9kZWxfY2FjaGVfZGlyKQoKICAgICAgICBzZWxlY3Rpb24gPSBkb3dubG9hZF9tb2RlbF93aXRoX2ZhbGxiYWNrKAogICAgICAgICAgICBwcmVmZXJyZWRfbW9kZWxfaWQ9bW9kZWxfaWQsCiAgICAgICAgICAgIGZhbGxiYWNrX21vZGVsX2lkPW1vZGVsX2lkLAogICAgICAgICAgICBsb2NhbF9kaXI9TU9ERUxfRElSLAogICAgICAgICkKICAgICAgICBtb2RlbCA9IF9sb2FkX3NlbnRlbmNlX3RyYW5zZm9ybWVyX2Zyb21fbG9jYWwoc2VsZWN0aW9uLm1vZGVsX2lkLCBzZWxlY3Rpb24ubG9jYWxfZGlyKQogICAgICAgIGlmIG1vZGVsX2Nob2ljZSA9PSAiamluYSI6CiAgICAgICAgICAgIG1vZGVsID0gX2FwcGx5X2ppbmFfcXVhbnRpemF0aW9uX2lmX25lZWRlZChtb2RlbCwgc2VsZWN0aW9uLm1vZGVsX2lkKQoKICAgICAgICBfbW9kZWxzW21vZGVsX2Nob2ljZV0gPSBtb2RlbAogICAgICAgIGxvZy5pbmZvKAogICAgICAgICAgICAiTW9kZWxvIGRlIGVtYmVkZGluZ3MgcHJvbnRvOiAlcyAocHJvdmlkZXI9JXMsIHBhdGg9JXMpIiwKICAgICAgICAgICAgc2VsZWN0aW9uLm1vZGVsX2lkLAogICAgICAgICAgICBzZWxlY3Rpb24ucHJvdmlkZXIsCiAgICAgICAgICAgIHNlbGVjdGlvbi5sb2NhbF9kaXIsCiAgICAgICAgKQogICAgICAgIHJldHVybiBtb2RlbAogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIG1lc3NhZ2UgPSBmIkZhbGhhIGFvIGNhcnJlZ2FyIG1vZGVsbyAne21vZGVsX2Nob2ljZX0nICh7bW9kZWxfaWR9KToge2V9IgogICAgICAgIF9tb2RlbF9sb2FkX2Vycm9yc1ttb2RlbF9jaG9pY2VdID0gbWVzc2FnZQogICAgICAgIHJhaXNlIFJ1bnRpbWVFcnJvcihtZXNzYWdlKQoKCmRlZiBnZXRfcmVyYW5rZXIoKSAtPiBDcm9zc0VuY29kZXIgfCBOb25lOgogICAgZ2xvYmFsIF9yZXJhbmtlciwgX3JlcmFua2VyX2Vycm9yCgogICAgaWYgbm90IFJFUkFOS19FTkFCTEVEOgogICAgICAgIHJldHVybiBOb25lCiAgICBpZiBfcmVyYW5rZXIgaXMgbm90IE5vbmU6CiAgICAgICAgcmV0dXJuIF9yZXJhbmtlcgogICAgaWYgX3JlcmFua2VyX2Vycm9yIGlzIG5vdCBOb25lOgogICAgICAgIHJldHVybiBOb25lCgogICAgdHJ5OgogICAgICAgIE1PREVMX0RJUi5ta2RpcihwYXJlbnRzPVRydWUsIGV4aXN0X29rPVRydWUpCiAgICAgICAgc2VsZWN0aW9uID0gZG93bmxvYWRfbW9kZWxfd2l0aF9mYWxsYmFjaygKICAgICAgICAgICAgcHJlZmVycmVkX21vZGVsX2lkPVJFUkFOS19NT0RFTF9JRCwKICAgICAgICAgICAgZmFsbGJhY2tfbW9kZWxfaWQ9UkVSQU5LX01PREVMX0lELAogICAgICAgICAgICBsb2NhbF9kaXI9TU9ERUxfRElSLAogICAgICAgICkKCiAgICAgICAgcmVyYW5rZXIgPSBDcm9zc0VuY29kZXIoCiAgICAgICAgICAgIHN0cihzZWxlY3Rpb24ubG9jYWxfZGlyKSwKICAgICAgICAgICAgZGV2aWNlPSJjcHUiLAogICAgICAgICAgICBtYXhfbGVuZ3RoPVJFUkFOS0VSX01BWF9MRU5HVEgsCiAgICAgICAgICAgIHRydXN0X3JlbW90ZV9jb2RlPUZhbHNlLAogICAgICAgICkKCiAgICAgICAgaWYgUkVSQU5LRVJfUVVBTlRJWkFUSU9OID09ICJkeW5hbWljLWludDgiOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBpbXBvcnQgdG9yY2gKCiAgICAgICAgICAgICAgICByZXJhbmtlci5tb2RlbCA9IHRvcmNoLnF1YW50aXphdGlvbi5xdWFudGl6ZV9keW5hbWljKAogICAgICAgICAgICAgICAgICAgIHJlcmFua2VyLm1vZGVsLAogICAgICAgICAgICAgICAgICAgIHt0b3JjaC5ubi5MaW5lYXJ9LAogICAgICAgICAgICAgICAgICAgIGR0eXBlPXRvcmNoLnFpbnQ4LAogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgbG9nLmluZm8oIlJlcmFua2VyIGNvbSBxdWFudGl6YWNhbyBkeW5hbWljLWludDggaGFiaWxpdGFkYS4iKQogICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIHF1YW50X2Vycm9yOgogICAgICAgICAgICAgICAgbG9nLndhcm5pbmcoIkZhbGhhIGFvIHF1YW50aXphciByZXJhbmtlciAoJXMpLiBTZWd1aW5kbyBzZW0gcXVhbnRpemFjYW8uIiwgcXVhbnRfZXJyb3IpCgogICAgICAgIF9yZXJhbmtlciA9IHJlcmFua2VyCiAgICAgICAgbG9nLmluZm8oCiAgICAgICAgICAgICJSZXJhbmtlciBwcm9udG86ICVzIChwcm92aWRlcj0lcywgcGF0aD0lcykiLAogICAgICAgICAgICBzZWxlY3Rpb24ubW9kZWxfaWQsCiAgICAgICAgICAgIHNlbGVjdGlvbi5wcm92aWRlciwKICAgICAgICAgICAgc2VsZWN0aW9uLmxvY2FsX2RpciwKICAgICAgICApCiAgICAgICAgcmV0dXJuIF9yZXJhbmtlcgogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIF9yZXJhbmtlcl9lcnJvciA9IHN0cihlKQogICAgICAgIGxvZy53YXJuaW5nKCJSZXJhbmtlciBpbmRpc3BvbsOtdmVsLiBCdXNjYSBzZWd1aXLDoSBzZW0gcmVyYW5raW5nLiBFcnJvOiAlcyIsIGUpCiAgICAgICAgcmV0dXJuIE5vbmUKCgpkZWYgZ2V0X3NwbGl0dGVyKCkgLT4gUmVjdXJzaXZlQ2hhcmFjdGVyVGV4dFNwbGl0dGVyOgogICAgZ2xvYmFsIF9zcGxpdHRlcgogICAgaWYgX3NwbGl0dGVyIGlzIE5vbmU6CiAgICAgICAgX3NwbGl0dGVyID0gUmVjdXJzaXZlQ2hhcmFjdGVyVGV4dFNwbGl0dGVyKAogICAgICAgICAgICBjaHVua19zaXplPUNIVU5LX1NJWkUsCiAgICAgICAgICAgIGNodW5rX292ZXJsYXA9Q0hVTktfT1ZFUkxBUCwKICAgICAgICAgICAgbGVuZ3RoX2Z1bmN0aW9uPWxlbiwKICAgICAgICAgICAgc2VwYXJhdG9ycz1bIlxuXG4iLCAiXG4iLCAiICIsICIiXSwKICAgICAgICApCiAgICByZXR1cm4gX3NwbGl0dGVyCgoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBJbmRleGHDp8OjbyBpbnRlcm5hCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgoKZGVmIF9tYWtlX2NodW5rX2lkKGZpbGVfcGF0aDogc3RyLCBjaHVua19pbmRleDogaW50KSAtPiBzdHI6CiAgICByYXcgPSBmIntmaWxlX3BhdGh9OjpjaHVuazo6e2NodW5rX2luZGV4fSIKICAgIHJldHVybiBoYXNobGliLm1kNShyYXcuZW5jb2RlKCkpLmhleGRpZ2VzdCgpCgoKZGVmIF9tYWtlX3Jlc3VsdF9rZXkobWV0YWRhdGE6IGRpY3Rbc3RyLCBvYmplY3RdLCBmYWxsYmFja19pZDogc3RyKSAtPiBzdHI6CiAgICBmaWxlX3BhdGggPSBzdHIobWV0YWRhdGEuZ2V0KCJmaWxlX3BhdGgiLCAiIikpCiAgICBjaHVua19pbmRleCA9IHN0cihtZXRhZGF0YS5nZXQoImNodW5rX2luZGV4IiwgIiIpKQogICAgaWYgZmlsZV9wYXRoIGFuZCBjaHVua19pbmRleDoKICAgICAgICByZXR1cm4gZiJ7ZmlsZV9wYXRofTo6Y2h1bms6OntjaHVua19pbmRleH0iCiAgICByZXR1cm4gZmFsbGJhY2tfaWQKCgpkZWYgX2RlbGV0ZV9maWxlX2NodW5rcyhjb2xsZWN0aW9uOiBjaHJvbWFkYi5Db2xsZWN0aW9uLCBmaWxlX3BhdGg6IHN0cikgLT4gaW50OgogICAgIyBQZWRlIGFwZW5hcyBJRHMgcGFyYSBuw6NvIG1hdGVyaWFsaXphciBkb2N1bWVudG9zL21ldGFkYXRhIGRlc25lY2Vzc8OhcmlvcyBlbSBSQU0uCiAgICByZXN1bHRzID0gY29sbGVjdGlvbi5nZXQod2hlcmU9eyJmaWxlX3BhdGgiOiBmaWxlX3BhdGh9LCBpbmNsdWRlPVtdKQogICAgaWRzID0gcmVzdWx0cy5nZXQoImlkcyIsIFtdKSBpZiByZXN1bHRzIGVsc2UgW10KICAgIGlmIGlkczoKICAgICAgICBjb2xsZWN0aW9uLmRlbGV0ZShpZHM9aWRzKQogICAgcmV0dXJuIGxlbihpZHMpCgoKZGVmIF9yZWFkX2ZpbGVfc2FmZShmaWxlcGF0aDogUGF0aCkgLT4gc3RyIHwgTm9uZToKICAgIGZvciBlbmNvZGluZyBpbiAoInV0Zi04IiwgImxhdGluLTEiLCAiY3AxMjUyIik6CiAgICAgICAgdHJ5OgogICAgICAgICAgICByZXR1cm4gZmlsZXBhdGgucmVhZF90ZXh0KGVuY29kaW5nPWVuY29kaW5nKQogICAgICAgIGV4Y2VwdCBVbmljb2RlRGVjb2RlRXJyb3I6CiAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgZXhjZXB0IE9TRXJyb3I6CiAgICAgICAgICAgIHJldHVybiBOb25lCiAgICByZXR1cm4gTm9uZQoKCmRlZiBfc2Nhbl9mb2xkZXIoZm9sZGVyX3BhdGg6IFBhdGgpIC0+IEl0ZXJhdG9yW1BhdGhdOgogICAgZm9yIGRpcnBhdGgsIGRpcm5hbWVzLCBmaWxlbmFtZXMgaW4gb3Mud2Fsayhmb2xkZXJfcGF0aCk6CiAgICAgICAgZGlybmFtZXNbOl0gPSBbCiAgICAgICAgICAgIGQgZm9yIGQgaW4gZGlybmFtZXMKICAgICAgICAgICAgaWYgZCBub3QgaW4gSUdOT1JFRF9ESVJTIGFuZCBub3QgZC5zdGFydHN3aXRoKCIuIikKICAgICAgICBdCiAgICAgICAgZGlybmFtZXMuc29ydCgpCiAgICAgICAgZm9yIGZpbGVuYW1lIGluIHNvcnRlZChmaWxlbmFtZXMpOgogICAgICAgICAgICBmcCA9IFBhdGgoZGlycGF0aCkgLyBmaWxlbmFtZQogICAgICAgICAgICBpZiBmcC5zdWZmaXgubG93ZXIoKSBpbiBJR05PUkVEX0VYVEVOU0lPTlM6CiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBpZiBmcC5zdGF0KCkuc3Rfc2l6ZSA+IE1BWF9GSUxFX1NJWkVfQllURVM6CiAgICAgICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgZXhjZXB0IE9TRXJyb3I6CiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICB5aWVsZCBmcAoKCmRlZiBfY2xhc3NpZnlfZmlsZV90YXJnZXRzKGZpbGVwYXRoOiBQYXRoKSAtPiBsaXN0W0JyYW5jaFNwZWNdOgogICAgc3VmZml4ID0gZmlsZXBhdGguc3VmZml4Lmxvd2VyKCkKICAgIGlzX2NvZGUgPSBzdWZmaXggaW4gQ09ERV9FWFRFTlNJT05TCiAgICBpc19kb2MgPSBzdWZmaXggaW4gRE9DX0VYVEVOU0lPTlMKCiAgICBpZiBpc19jb2RlIGFuZCBub3QgaXNfZG9jOgogICAgICAgIHJldHVybiBbQlJBTkNIX1NQRUNTWyJqaW5hX2NvZGUiXV0KICAgIGlmIGlzX2RvYyBhbmQgbm90IGlzX2NvZGU6CiAgICAgICAgcmV0dXJuIFtCUkFOQ0hfU1BFQ1NbImJnZV9kb2MiXV0KCiAgICAjIEFycXVpdm9zIGFtYsOtZ3Vvcy9leHRlbnPDo28gZGVzY29uaGVjaWRhOiBpbmRleGEgZW0gYW1iYXMgcGFyYSBuw6NvIHBlcmRlciByZWNhbGwuCiAgICByZXR1cm4gW0JSQU5DSF9TUEVDU1siamluYV9jb2RlIl0sIEJSQU5DSF9TUEVDU1siYmdlX2RvYyJdXQoKCmRlZiBfaW5kZXhfc2luZ2xlX2ZpbGVfZm9yX2JyYW5jaCgKICAgIGZpbGVwYXRoOiBQYXRoLAogICAgYnJhbmNoOiBCcmFuY2hTcGVjLAogICAgc3BsaXR0ZXI6IFJlY3Vyc2l2ZUNoYXJhY3RlclRleHRTcGxpdHRlciwKICAgICosCiAgICBkZWxldGVfZXhpc3Rpbmc6IGJvb2wgPSBUcnVlLAopIC0+IGludDoKICAgIGNvbnRlbnQgPSBfcmVhZF9maWxlX3NhZmUoZmlsZXBhdGgpCiAgICBpZiBub3QgY29udGVudCBvciBub3QgY29udGVudC5zdHJpcCgpOgogICAgICAgIHJldHVybiAwCgogICAgYWJzX3BhdGggPSBzdHIoZmlsZXBhdGgucmVzb2x2ZSgpKQogICAgbW9kZWwgPSBnZXRfZW1iZWRkaW5nX21vZGVsKGJyYW5jaC5tb2RlbF9jaG9pY2UpCiAgICBjb2xsZWN0aW9uID0gZ2V0X2Nocm9tYV9jb2xsZWN0aW9uKGJyYW5jaC5jb2xsZWN0aW9uX25hbWUpCgogICAgY2h1bmtzID0gc3BsaXR0ZXIuc3BsaXRfdGV4dChjb250ZW50KQogICAgaWYgbm90IGNodW5rczoKICAgICAgICByZXR1cm4gMAoKICAgICMgQXR1YWxpemHDp8OjbyBpZGVtcG90ZW50ZSBwb3IgYXJxdWl2byBlbSBjYWRhIGNvbGXDp8Ojby4KICAgIGlmIGRlbGV0ZV9leGlzdGluZzoKICAgICAgICBfZGVsZXRlX2ZpbGVfY2h1bmtzKGNvbGxlY3Rpb24sIGFic19wYXRoKQoKICAgIGluc2VydGVkX2NodW5rcyA9IDAKICAgIGJhdGNoX2lkczogbGlzdFtzdHJdID0gW10KICAgIGJhdGNoX2RvY3M6IGxpc3Rbc3RyXSA9IFtdCiAgICBiYXRjaF9tZXRhZGF0YXM6IGxpc3RbZGljdFtzdHIsIG9iamVjdF1dID0gW10KCiAgICBkZWYgX2ZsdXNoX2JhdGNoKCkgLT4gTm9uZToKICAgICAgICBub25sb2NhbCBpbnNlcnRlZF9jaHVua3MKICAgICAgICBpZiBub3QgYmF0Y2hfaWRzOgogICAgICAgICAgICByZXR1cm4KICAgICAgICBlbWJlZGRpbmdzID0gbW9kZWwuZW5jb2RlKAogICAgICAgICAgICBiYXRjaF9kb2NzLAogICAgICAgICAgICBzaG93X3Byb2dyZXNzX2Jhcj1GYWxzZSwKICAgICAgICAgICAgYmF0Y2hfc2l6ZT1FTUJFRERJTkdfQkFUQ0hfU0laRSwKICAgICAgICApLnRvbGlzdCgpCiAgICAgICAgY29sbGVjdGlvbi51cHNlcnQoCiAgICAgICAgICAgIGlkcz1iYXRjaF9pZHMsCiAgICAgICAgICAgIGVtYmVkZGluZ3M9ZW1iZWRkaW5ncywKICAgICAgICAgICAgZG9jdW1lbnRzPWJhdGNoX2RvY3MsCiAgICAgICAgICAgIG1ldGFkYXRhcz1iYXRjaF9tZXRhZGF0YXMsCiAgICAgICAgKQogICAgICAgIGluc2VydGVkX2NodW5rcyArPSBsZW4oYmF0Y2hfaWRzKQogICAgICAgIGRlbCBlbWJlZGRpbmdzCiAgICAgICAgYmF0Y2hfaWRzLmNsZWFyKCkKICAgICAgICBiYXRjaF9kb2NzLmNsZWFyKCkKICAgICAgICBiYXRjaF9tZXRhZGF0YXMuY2xlYXIoKQoKICAgIGZvciBpLCBjaHVuayBpbiBlbnVtZXJhdGUoY2h1bmtzKToKICAgICAgICBiYXRjaF9pZHMuYXBwZW5kKF9tYWtlX2NodW5rX2lkKGFic19wYXRoLCBpKSkKICAgICAgICBiYXRjaF9kb2NzLmFwcGVuZChjaHVuaykKICAgICAgICBiYXRjaF9tZXRhZGF0YXMuYXBwZW5kKAogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAiZmlsZV9wYXRoIjogYWJzX3BhdGgsCiAgICAgICAgICAgICAgICAiZmlsZV9uYW1lIjogZmlsZXBhdGgubmFtZSwKICAgICAgICAgICAgICAgICJjaHVua19pbmRleCI6IGksCiAgICAgICAgICAgICAgICAic291cmNlX2NvbGxlY3Rpb24iOiBicmFuY2guY29sbGVjdGlvbl9uYW1lLAogICAgICAgICAgICAgICAgInNvdXJjZV9tb2RlbF9jaG9pY2UiOiBicmFuY2gubW9kZWxfY2hvaWNlLAogICAgICAgICAgICAgICAgInNvdXJjZV9tb2RlbF9pZCI6IGJyYW5jaC5tb2RlbF9pZCwKICAgICAgICAgICAgICAgICJjb250ZW50X2RvbWFpbiI6IGJyYW5jaC5jb250ZW50X2RvbWFpbiwKICAgICAgICAgICAgfQogICAgICAgICkKICAgICAgICBpZiBsZW4oYmF0Y2hfaWRzKSA+PSBFTUJFRERJTkdfQkFUQ0hfU0laRToKICAgICAgICAgICAgX2ZsdXNoX2JhdGNoKCkKCiAgICBfZmx1c2hfYmF0Y2goKQogICAgcmV0dXJuIGluc2VydGVkX2NodW5rcwoKCmRlZiBfcmVtb3ZlX2ZpbGVfZnJvbV9hbGxfY29sbGVjdGlvbnMoYWJzX3BhdGg6IHN0cikgLT4gdHVwbGVbZGljdFtzdHIsIGludF0sIGxpc3Rbc3RyXV06CiAgICBkZWxldGVkX3Blcl9icmFuY2g6IGRpY3Rbc3RyLCBpbnRdID0ge30KICAgIGVycm9yczogbGlzdFtzdHJdID0gW10KCiAgICBmb3IgYnJhbmNoIGluIEJSQU5DSF9TUEVDUy52YWx1ZXMoKToKICAgICAgICB0cnk6CiAgICAgICAgICAgIGNvbGxlY3Rpb24gPSBnZXRfY2hyb21hX2NvbGxlY3Rpb24oYnJhbmNoLmNvbGxlY3Rpb25fbmFtZSkKICAgICAgICAgICAgZGVsZXRlZCA9IF9kZWxldGVfZmlsZV9jaHVua3MoY29sbGVjdGlvbiwgYWJzX3BhdGgpCiAgICAgICAgICAgIGRlbGV0ZWRfcGVyX2JyYW5jaFticmFuY2gua2V5XSA9IGRlbGV0ZWQKICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgIGVycm9ycy5hcHBlbmQoZiJ7YnJhbmNoLmtleX06IHtlfSIpCiAgICByZXR1cm4gZGVsZXRlZF9wZXJfYnJhbmNoLCBlcnJvcnMKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEJ1c2NhIHNlbcOibnRpY2EgaMOtYnJpZGEKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCgpkZWYgX3F1ZXJ5X2JyYW5jaChicmFuY2g6IEJyYW5jaFNwZWMsIHF1ZXJ5OiBzdHIsIG5fcmVzdWx0czogaW50KSAtPiB0dXBsZVtsaXN0W1JldHJpZXZlZEhpdF0sIHN0ciB8IE5vbmVdOgogICAgdHJ5OgogICAgICAgIGNvbGxlY3Rpb24gPSBnZXRfY2hyb21hX2NvbGxlY3Rpb24oYnJhbmNoLmNvbGxlY3Rpb25fbmFtZSkKICAgICAgICBtb2RlbCA9IGdldF9lbWJlZGRpbmdfbW9kZWwoYnJhbmNoLm1vZGVsX2Nob2ljZSkKICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICByZXR1cm4gW10sIGYie2JyYW5jaC5rZXl9OiByZWN1cnNvIGluZGlzcG9uw612ZWwgKHtlfSkiCgogICAgdHJ5OgogICAgICAgIHF1ZXJ5X2VtYmVkZGluZyA9IG1vZGVsLmVuY29kZShbcXVlcnldLCBzaG93X3Byb2dyZXNzX2Jhcj1GYWxzZSkudG9saXN0KCkKICAgICAgICByZXN1bHRzID0gY29sbGVjdGlvbi5xdWVyeSgKICAgICAgICAgICAgcXVlcnlfZW1iZWRkaW5ncz1xdWVyeV9lbWJlZGRpbmcsCiAgICAgICAgICAgIG5fcmVzdWx0cz1uX3Jlc3VsdHMsCiAgICAgICAgICAgIGluY2x1ZGU9WyJkb2N1bWVudHMiLCAibWV0YWRhdGFzIiwgImRpc3RhbmNlcyJdLAogICAgICAgICkKICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICByZXR1cm4gW10sIGYie2JyYW5jaC5rZXl9OiBmYWxoYSBuYSBxdWVyeSAoe2V9KSIKCiAgICBkb2N1bWVudHMgPSByZXN1bHRzLmdldCgiZG9jdW1lbnRzIiwgW1tdXSlbMF0KICAgIG1ldGFkYXRhcyA9IHJlc3VsdHMuZ2V0KCJtZXRhZGF0YXMiLCBbW11dKVswXQogICAgZGlzdGFuY2VzID0gcmVzdWx0cy5nZXQoImRpc3RhbmNlcyIsIFtbXV0pWzBdCiAgICBpZHMgPSByZXN1bHRzLmdldCgiaWRzIiwgW1tdXSlbMF0KCiAgICBoaXRzOiBsaXN0W1JldHJpZXZlZEhpdF0gPSBbXQogICAgZm9yIGlkeCwgKGRvYywgbWV0YSwgZGlzdCkgaW4gZW51bWVyYXRlKHppcChkb2N1bWVudHMsIG1ldGFkYXRhcywgZGlzdGFuY2VzKSwgc3RhcnQ9MSk6CiAgICAgICAgbWV0YWRhdGEgPSBtZXRhIG9yIHt9CiAgICAgICAgZmFsbGJhY2tfaWQgPSBpZHNbaWR4IC0gMV0gaWYgaWR4IC0gMSA8IGxlbihpZHMpIGVsc2UgZiJ7YnJhbmNoLmtleX06e2lkeH0iCiAgICAgICAga2V5ID0gX21ha2VfcmVzdWx0X2tleShtZXRhZGF0YSwgZmFsbGJhY2tfaWQpCgogICAgICAgIHNpbWlsYXJpdHkgPSBOb25lCiAgICAgICAgaWYgZGlzdCBpcyBub3QgTm9uZToKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgc2ltaWxhcml0eSA9IDEuMCAtIGZsb2F0KGRpc3QpCiAgICAgICAgICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgICAgICAgICBzaW1pbGFyaXR5ID0gTm9uZQoKICAgICAgICBoaXRzLmFwcGVuZCgKICAgICAgICAgICAgUmV0cmlldmVkSGl0KAogICAgICAgICAgICAgICAga2V5PWtleSwKICAgICAgICAgICAgICAgIGRvY3VtZW50PShkb2Mgb3IgIiIpLAogICAgICAgICAgICAgICAgbWV0YWRhdGE9bWV0YWRhdGEsCiAgICAgICAgICAgICAgICBkaXN0YW5jZT1mbG9hdChkaXN0KSBpZiBkaXN0IGlzIG5vdCBOb25lIGVsc2UgTm9uZSwKICAgICAgICAgICAgICAgIHNpbWlsYXJpdHk9c2ltaWxhcml0eSwKICAgICAgICAgICAgICAgIGJyYW5jaD1icmFuY2gsCiAgICAgICAgICAgICAgICByYW5rPWlkeCwKICAgICAgICAgICAgKQogICAgICAgICkKCiAgICByZXR1cm4gaGl0cywgTm9uZQoKCmRlZiBfcnJmX2Z1c2UoaGl0c19ieV9icmFuY2g6IGRpY3Rbc3RyLCBsaXN0W1JldHJpZXZlZEhpdF1dLCB0b3BfbGltaXQ6IGludCkgLT4gbGlzdFtGdXNlZEhpdF06CiAgICBmdXNlZDogZGljdFtzdHIsIEZ1c2VkSGl0XSA9IHt9CgogICAgZm9yIGJyYW5jaF9rZXksIGhpdHMgaW4gaGl0c19ieV9icmFuY2guaXRlbXMoKToKICAgICAgICBfID0gYnJhbmNoX2tleQogICAgICAgIGZvciByYW5rLCBoaXQgaW4gZW51bWVyYXRlKGhpdHMsIHN0YXJ0PTEpOgogICAgICAgICAgICBjb250cmlidXRpb24gPSAxLjAgLyAoUlJGX0sgKyByYW5rKQogICAgICAgICAgICBlbnRyeSA9IGZ1c2VkLmdldChoaXQua2V5KQoKICAgICAgICAgICAgaWYgZW50cnkgaXMgTm9uZToKICAgICAgICAgICAgICAgIGVudHJ5ID0gRnVzZWRIaXQoCiAgICAgICAgICAgICAgICAgICAga2V5PWhpdC5rZXksCiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQ9aGl0LmRvY3VtZW50LAogICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhPWRpY3QoaGl0Lm1ldGFkYXRhKSwKICAgICAgICAgICAgICAgICAgICBycmZfc2NvcmU9MC4wLAogICAgICAgICAgICAgICAgICAgIHNvdXJjZV9kZXRhaWxzPXt9LAogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgZnVzZWRbaGl0LmtleV0gPSBlbnRyeQoKICAgICAgICAgICAgZW50cnkucnJmX3Njb3JlICs9IGNvbnRyaWJ1dGlvbgogICAgICAgICAgICBlbnRyeS5zb3VyY2VfZGV0YWlsc1toaXQuYnJhbmNoLmtleV0gPSB7CiAgICAgICAgICAgICAgICAicmFuayI6IHJhbmssCiAgICAgICAgICAgICAgICAiZGlzdGFuY2UiOiBoaXQuZGlzdGFuY2UsCiAgICAgICAgICAgICAgICAic2ltaWxhcml0eSI6IGhpdC5zaW1pbGFyaXR5LAogICAgICAgICAgICAgICAgImNvbGxlY3Rpb24iOiBoaXQuYnJhbmNoLmNvbGxlY3Rpb25fbmFtZSwKICAgICAgICAgICAgICAgICJtb2RlbF9jaG9pY2UiOiBoaXQuYnJhbmNoLm1vZGVsX2Nob2ljZSwKICAgICAgICAgICAgICAgICJtb2RlbF9pZCI6IGhpdC5icmFuY2gubW9kZWxfaWQsCiAgICAgICAgICAgICAgICAiY29udGVudF9kb21haW4iOiBoaXQuYnJhbmNoLmNvbnRlbnRfZG9tYWluLAogICAgICAgICAgICB9CgogICAgICAgICAgICAjIFVzYSBtZXRhZGFkb3MgZG8gaGl0IGNvbSBtZWxob3Igc2ltaWxhcmlkYWRlIGxvY2FsIGNvbW8gYmFzZSBwcmluY2lwYWwuCiAgICAgICAgICAgIGN1cnJlbnRfc2ltID0gZW50cnkubWV0YWRhdGEuZ2V0KCJfYmVzdF9zaW1pbGFyaXR5IiwgLTEwLjApCiAgICAgICAgICAgIGNhbmRpZGF0ZV9zaW0gPSBoaXQuc2ltaWxhcml0eSBpZiBoaXQuc2ltaWxhcml0eSBpcyBub3QgTm9uZSBlbHNlIC0xMC4wCiAgICAgICAgICAgIGlmIGNhbmRpZGF0ZV9zaW0gPiBjdXJyZW50X3NpbToKICAgICAgICAgICAgICAgIGVudHJ5LmRvY3VtZW50ID0gaGl0LmRvY3VtZW50CiAgICAgICAgICAgICAgICBlbnRyeS5tZXRhZGF0YSA9IGRpY3QoaGl0Lm1ldGFkYXRhKQogICAgICAgICAgICAgICAgZW50cnkubWV0YWRhdGFbIl9iZXN0X3NpbWlsYXJpdHkiXSA9IGNhbmRpZGF0ZV9zaW0KCiAgICBmdXNlZF9oaXRzID0gbGlzdChmdXNlZC52YWx1ZXMoKSkKICAgIGZ1c2VkX2hpdHMuc29ydChrZXk9bGFtYmRhIGg6IGgucnJmX3Njb3JlLCByZXZlcnNlPVRydWUpCgogICAgIyBMaW1pdGEgbyBwb29sIGFudGVzIGRvIHJlcmFua2luZyBwYXJhIHJlZHV6aXIgQ1BVL1JBTS4KICAgIHJldHVybiBmdXNlZF9oaXRzWzp0b3BfbGltaXRdCgoKZGVmIF9hcHBseV9yZXJhbmsocXVlcnk6IHN0ciwgZnVzZWRfaGl0czogbGlzdFtGdXNlZEhpdF0sIHRvcF9rOiBpbnQpIC0+IHR1cGxlW2xpc3RbRnVzZWRIaXRdLCBib29sLCBzdHIgfCBOb25lXToKICAgIGlmIG5vdCBmdXNlZF9oaXRzOgogICAgICAgIHJldHVybiBbXSwgRmFsc2UsIE5vbmUKCiAgICByZXJhbmtlciA9IGdldF9yZXJhbmtlcigpCiAgICBpZiByZXJhbmtlciBpcyBOb25lOgogICAgICAgIHJlYXNvbiA9IF9yZXJhbmtlcl9lcnJvciBpZiBfcmVyYW5rZXJfZXJyb3IgZWxzZSAicmVyYW5rZXJfZGVzYWJpbGl0YWRvIgogICAgICAgIHJldHVybiBmdXNlZF9oaXRzWzp0b3Bfa10sIEZhbHNlLCByZWFzb24KCiAgICB0cnk6CiAgICAgICAgcGFpcnMgPSBbKHF1ZXJ5LCBoaXQuZG9jdW1lbnQpIGZvciBoaXQgaW4gZnVzZWRfaGl0c10KICAgICAgICBzY29yZXMgPSByZXJhbmtlci5wcmVkaWN0KHBhaXJzLCBzaG93X3Byb2dyZXNzX2Jhcj1GYWxzZSwgY29udmVydF90b19udW1weT1UcnVlKQoKICAgICAgICBmb3IgaGl0LCBzY29yZSBpbiB6aXAoZnVzZWRfaGl0cywgc2NvcmVzKToKICAgICAgICAgICAgaGl0LnJlcmFua19zY29yZSA9IGZsb2F0KHNjb3JlKQoKICAgICAgICBmdXNlZF9oaXRzLnNvcnQoCiAgICAgICAgICAgIGtleT1sYW1iZGEgaDogKAogICAgICAgICAgICAgICAgaC5yZXJhbmtfc2NvcmUgaWYgaC5yZXJhbmtfc2NvcmUgaXMgbm90IE5vbmUgZWxzZSAtMWU5LAogICAgICAgICAgICAgICAgaC5ycmZfc2NvcmUsCiAgICAgICAgICAgICksCiAgICAgICAgICAgIHJldmVyc2U9VHJ1ZSwKICAgICAgICApCiAgICAgICAgcmV0dXJuIGZ1c2VkX2hpdHNbOnRvcF9rXSwgVHJ1ZSwgTm9uZQogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIHJldHVybiBmdXNlZF9oaXRzWzp0b3Bfa10sIEZhbHNlLCBzdHIoZSkKCgpkZWYgX2Zvcm1hdF9zaW1pbGFyaXR5KHNpbWlsYXJpdHk6IGZsb2F0IHwgTm9uZSkgLT4gc3RyOgogICAgaWYgc2ltaWxhcml0eSBpcyBOb25lOgogICAgICAgIHJldHVybiAibi9hIgogICAgcmV0dXJuIGYie3JvdW5kKHNpbWlsYXJpdHkgKiAxMDAsIDEpfSUiCgoKZGVmIF9mb3JtYXRfZnVzZWRfcmVzdWx0cygKICAgICosCiAgICBxdWVyeTogc3RyLAogICAgbW9kZTogc3RyLAogICAgaGl0czogbGlzdFtGdXNlZEhpdF0sCiAgICBicmFuY2hfZXJyb3JzOiBsaXN0W3N0cl0sCiAgICByZXJhbmtfYXBwbGllZDogYm9vbCwKICAgIHJlcmFua19lcnJvcjogc3RyIHwgTm9uZSwKKSAtPiBzdHI6CiAgICBpZiBub3QgaGl0czoKICAgICAgICBtc2cgPSAiTmVuaHVtIHJlc3VsdGFkbyBlbmNvbnRyYWRvLiBBcyBjb2xlw6fDtWVzIHBvZGVtIGVzdGFyIHZhemlhcy4iCiAgICAgICAgaWYgYnJhbmNoX2Vycm9yczoKICAgICAgICAgICAgbXNnICs9ICJcbkZhbGhhcyBkZXRlY3RhZGFzOiAiICsgIiB8ICIuam9pbihicmFuY2hfZXJyb3JzKQogICAgICAgIHJldHVybiBtc2cKCiAgICBsaW5lczogbGlzdFtzdHJdID0gW2YiIyBSZXN1bHRhZG9zIHBhcmE6ICd7cXVlcnl9JyIsIGYiKipNb2RvOioqIHttb2RlfSJdCgogICAgaWYgYnJhbmNoX2Vycm9yczoKICAgICAgICBsaW5lcy5hcHBlbmQoIioqQXZpc29zIGRlIGJyYW5jaDoqKiAiICsgIiB8ICIuam9pbihicmFuY2hfZXJyb3JzKSkKCiAgICBpZiBtb2RlID09ICJlbnNlbWJsZSI6CiAgICAgICAgaWYgcmVyYW5rX2FwcGxpZWQ6CiAgICAgICAgICAgIGxpbmVzLmFwcGVuZChmIioqUmVyYW5raW5nOioqIGF0aXZvICh7UkVSQU5LX01PREVMX0lEfSkiKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIGxpbmVzLmFwcGVuZChmIioqUmVyYW5raW5nOioqIGluZGlzcG9uw612ZWwgKHtyZXJhbmtfZXJyb3Igb3IgJ3NlbSBkZXRhbGhlcyd9KSIpCgogICAgbGluZXMuYXBwZW5kKCIiKQoKICAgIGZvciBpZHgsIGhpdCBpbiBlbnVtZXJhdGUoaGl0cywgc3RhcnQ9MSk6CiAgICAgICAgbWV0YWRhdGEgPSBkaWN0KGhpdC5tZXRhZGF0YSkKICAgICAgICBtZXRhZGF0YS5wb3AoIl9iZXN0X3NpbWlsYXJpdHkiLCBOb25lKQoKICAgICAgICBmaWxlX3BhdGggPSBzdHIobWV0YWRhdGEuZ2V0KCJmaWxlX3BhdGgiLCAiZGVzY29uaGVjaWRvIikpCiAgICAgICAgY2h1bmtfaW5kZXggPSBtZXRhZGF0YS5nZXQoImNodW5rX2luZGV4IiwgIj8iKQogICAgICAgIGZpbGVfbmFtZSA9IHN0cihtZXRhZGF0YS5nZXQoImZpbGVfbmFtZSIsIFBhdGgoZmlsZV9wYXRoKS5uYW1lIGlmIGZpbGVfcGF0aCAhPSAiZGVzY29uaGVjaWRvIiBlbHNlICI/IikpCgogICAgICAgIHNvdXJjZV9tb2RlbHMgPSBzb3J0ZWQoe3N0cih2LmdldCgibW9kZWxfY2hvaWNlIiwgIj8iKSkgZm9yIHYgaW4gaGl0LnNvdXJjZV9kZXRhaWxzLnZhbHVlcygpfSkKICAgICAgICBzb3VyY2VfY29sbGVjdGlvbnMgPSBzb3J0ZWQoe3N0cih2LmdldCgiY29sbGVjdGlvbiIsICI/IikpIGZvciB2IGluIGhpdC5zb3VyY2VfZGV0YWlscy52YWx1ZXMoKX0pCgogICAgICAgIHNvdXJjZV9wYXJ0czogbGlzdFtzdHJdID0gW10KICAgICAgICBmb3Igc291cmNlX2tleSwgZGV0YWlscyBpbiBzb3J0ZWQoCiAgICAgICAgICAgIGhpdC5zb3VyY2VfZGV0YWlscy5pdGVtcygpLAogICAgICAgICAgICBrZXk9bGFtYmRhIGl0ZW06IGludChpdGVtWzFdLmdldCgicmFuayIsIDk5OTk5OSkpLAogICAgICAgICk6CiAgICAgICAgICAgIHNvdXJjZV9wYXJ0cy5hcHBlbmQoCiAgICAgICAgICAgICAgICBmIntzb3VyY2Vfa2V5fShyYW5rPXtkZXRhaWxzLmdldCgncmFuaycpfSwgc2ltPXtfZm9ybWF0X3NpbWlsYXJpdHkoZGV0YWlscy5nZXQoJ3NpbWlsYXJpdHknKSl9KSIKICAgICAgICAgICAgKQoKICAgICAgICBzbmlwcGV0ID0gaGl0LmRvY3VtZW50LnN0cmlwKCkKICAgICAgICBpZiBsZW4oc25pcHBldCkgPiA4MDA6CiAgICAgICAgICAgIHNuaXBwZXQgPSBzbmlwcGV0Wzo4MDBdICsgIlxuLi4uIFt0cnVuY2Fkb10iCgogICAgICAgIHNjb3JlX2xpbmUgPSBmIlJSRj17aGl0LnJyZl9zY29yZTouNGZ9IgogICAgICAgIGlmIGhpdC5yZXJhbmtfc2NvcmUgaXMgbm90IE5vbmU6CiAgICAgICAgICAgIHNjb3JlX2xpbmUgKz0gZiIgfCByZXJhbms9e2hpdC5yZXJhbmtfc2NvcmU6LjRmfSIKCiAgICAgICAgbGluZXMuYXBwZW5kKGYiIyMgW3tpZHh9XSB7ZmlsZV9wYXRofSIpCiAgICAgICAgbGluZXMuYXBwZW5kKGYiKipTY29yZXM6Kioge3Njb3JlX2xpbmV9IikKICAgICAgICBsaW5lcy5hcHBlbmQoZiIqKkZvbnRlcyBkZSByZWN1cGVyYcOnw6NvOioqIHsnLCAnLmpvaW4oc291cmNlX3BhcnRzKX0iKQogICAgICAgIGxpbmVzLmFwcGVuZCgKICAgICAgICAgICAgIioqTWV0YWRhZG9zIHVuaWZpY2Fkb3M6KiogIgogICAgICAgICAgICBmImZpbGVfbmFtZT17ZmlsZV9uYW1lfSB8IGNodW5rX2luZGV4PXtjaHVua19pbmRleH0gfCAiCiAgICAgICAgICAgIGYic291cmNlX21vZGVscz17c291cmNlX21vZGVsc30gfCBzb3VyY2VfY29sbGVjdGlvbnM9e3NvdXJjZV9jb2xsZWN0aW9uc30iCiAgICAgICAgKQogICAgICAgIGxpbmVzLmFwcGVuZCgiIikKICAgICAgICBsaW5lcy5hcHBlbmQoZiJgYGBcbntzbmlwcGV0fVxuYGBgIikKICAgICAgICBsaW5lcy5hcHBlbmQoIiIpCgogICAgcmV0dXJuICJcbiIuam9pbihsaW5lcykKCgpkZWYgX3J1bl9zaW5nbGVfbW9kZShxdWVyeTogc3RyLCB0b3BfazogaW50KSAtPiB0dXBsZVtsaXN0W0Z1c2VkSGl0XSwgbGlzdFtzdHJdLCBib29sLCBzdHIgfCBOb25lXToKICAgIHByaW1hcnlfYnJhbmNoID0gQlJBTkNIX1NQRUNTW0RFRkFVTFRfU0lOR0xFX0JSQU5DSF9LRVldCgogICAgaGl0cywgZXJyb3IgPSBfcXVlcnlfYnJhbmNoKHByaW1hcnlfYnJhbmNoLCBxdWVyeSwgdG9wX2spCiAgICBlcnJvcnM6IGxpc3Rbc3RyXSA9IFtdCiAgICBpZiBlcnJvcjoKICAgICAgICBlcnJvcnMuYXBwZW5kKGVycm9yKQoKICAgICMgRmFsbGJhY2sgYXV0b23DoXRpY28gcGFyYSBhIGJyYW5jaCBhbHRlcm5hdGl2YSwgcHJlc2VydmFuZG8gZGlzcG9uaWJpbGlkYWRlLgogICAgaWYgbm90IGhpdHM6CiAgICAgICAgZmFsbGJhY2tfYnJhbmNoX2tleSA9ICJiZ2VfZG9jIiBpZiBwcmltYXJ5X2JyYW5jaC5rZXkgPT0gImppbmFfY29kZSIgZWxzZSAiamluYV9jb2RlIgogICAgICAgIGZhbGxiYWNrX2hpdHMsIGZhbGxiYWNrX2Vycm9yID0gX3F1ZXJ5X2JyYW5jaChCUkFOQ0hfU1BFQ1NbZmFsbGJhY2tfYnJhbmNoX2tleV0sIHF1ZXJ5LCB0b3BfaykKICAgICAgICBpZiBmYWxsYmFja19lcnJvcjoKICAgICAgICAgICAgZXJyb3JzLmFwcGVuZChmYWxsYmFja19lcnJvcikKICAgICAgICBpZiBmYWxsYmFja19oaXRzOgogICAgICAgICAgICBoaXRzID0gZmFsbGJhY2tfaGl0cwoKICAgIGlmIG5vdCBoaXRzOgogICAgICAgIHJldHVybiBbXSwgZXJyb3JzLCBGYWxzZSwgTm9uZQoKICAgIGZ1c2VkID0gX3JyZl9mdXNlKHsic2luZ2xlIjogaGl0c30sIHRvcF9rKQogICAgcmV0dXJuIGZ1c2VkLCBlcnJvcnMsIEZhbHNlLCBOb25lCgoKZGVmIF9ydW5fZW5zZW1ibGVfbW9kZShxdWVyeTogc3RyLCB0b3BfazogaW50KSAtPiB0dXBsZVtsaXN0W0Z1c2VkSGl0XSwgbGlzdFtzdHJdLCBib29sLCBzdHIgfCBOb25lXToKICAgIHBlcl9icmFuY2hfayA9IG1pbihNQVhfUVVFUllfUkVTVUxUUywgbWF4KHRvcF9rICogMiwgdG9wX2spKQogICAgYnJhbmNoZXMgPSBbQlJBTkNIX1NQRUNTWyJqaW5hX2NvZGUiXSwgQlJBTkNIX1NQRUNTWyJiZ2VfZG9jIl1dCgogICAgaGl0c19ieV9icmFuY2g6IGRpY3Rbc3RyLCBsaXN0W1JldHJpZXZlZEhpdF1dID0ge30KICAgIGJyYW5jaF9lcnJvcnM6IGxpc3Rbc3RyXSA9IFtdCgogICAgd2l0aCBUaHJlYWRQb29sRXhlY3V0b3IobWF4X3dvcmtlcnM9bGVuKGJyYW5jaGVzKSkgYXMgZXhlY3V0b3I6CiAgICAgICAgZnV0dXJlcyA9IHsKICAgICAgICAgICAgZXhlY3V0b3Iuc3VibWl0KF9xdWVyeV9icmFuY2gsIGJyYW5jaCwgcXVlcnksIHBlcl9icmFuY2hfayk6IGJyYW5jaAogICAgICAgICAgICBmb3IgYnJhbmNoIGluIGJyYW5jaGVzCiAgICAgICAgfQogICAgICAgIGZvciBmdXR1cmUgaW4gYXNfY29tcGxldGVkKGZ1dHVyZXMpOgogICAgICAgICAgICBicmFuY2ggPSBmdXR1cmVzW2Z1dHVyZV0KICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgaGl0cywgZXJyb3IgPSBmdXR1cmUucmVzdWx0KCkKICAgICAgICAgICAgICAgIGlmIGVycm9yOgogICAgICAgICAgICAgICAgICAgIGJyYW5jaF9lcnJvcnMuYXBwZW5kKGVycm9yKQogICAgICAgICAgICAgICAgaWYgaGl0czoKICAgICAgICAgICAgICAgICAgICBoaXRzX2J5X2JyYW5jaFticmFuY2gua2V5XSA9IGhpdHMKICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICAgICAgYnJhbmNoX2Vycm9ycy5hcHBlbmQoZiJ7YnJhbmNoLmtleX06IGZhbGhhIGluZXNwZXJhZGEgKHtlfSkiKQoKICAgIGlmIG5vdCBoaXRzX2J5X2JyYW5jaDoKICAgICAgICByZXR1cm4gW10sIGJyYW5jaF9lcnJvcnMsIEZhbHNlLCBOb25lCgogICAgY2FuZGlkYXRlX3Bvb2wgPSBtaW4oUkVSQU5LX01BWF9DQU5ESURBVEVTLCBtYXgodG9wX2ssIHRvcF9rICogUkVSQU5LX0NBTkRJREFURV9NVUxUSVBMSUVSKSkKICAgIGZ1c2VkX2NhbmRpZGF0ZXMgPSBfcnJmX2Z1c2UoaGl0c19ieV9icmFuY2gsIGNhbmRpZGF0ZV9wb29sKQogICAgcmVyYW5rZWRfaGl0cywgcmVyYW5rX2FwcGxpZWQsIHJlcmFua19lcnJvciA9IF9hcHBseV9yZXJhbmsocXVlcnksIGZ1c2VkX2NhbmRpZGF0ZXMsIHRvcF9rKQogICAgcmV0dXJuIHJlcmFua2VkX2hpdHMsIGJyYW5jaF9lcnJvcnMsIHJlcmFua19hcHBsaWVkLCByZXJhbmtfZXJyb3IKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIFNlcnZpZG9yIE1DUCB2aWEgRmFzdE1DUAojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKbWNwID0gRmFzdE1DUCgKICAgIG5hbWU9InJhZy1jb2RlYmFzZSIsCiAgICBpbnN0cnVjdGlvbnM9KAogICAgICAgICJTZXJ2aWRvciBSQUcgcGFyYSBidXNjYSBzZW3Dom50aWNhIGVtIGPDs2RpZ28tZm9udGUgbG9jYWwgY29tIHN1cG9ydGUgYSBlbnNlbWJsZSBow61icmlkby4gIgogICAgICAgICJObyBtb2RvIGh5YnJpZCwgYSBicmFuY2ggZGUgY8OzZGlnbyB1c2EgSmluYSB2MiBlIGEgZGUgZG9jdW1lbnRhw6fDo28gdXNhIEJHRS4gIgogICAgICAgICJVc2Ugc2VtYW50aWNfc2VhcmNoX2NvZGUocXVlcnksIHRvcF9rLCBtb2RlPSdlbnNlbWJsZScpIHBhcmEgY29tYmluYXIgSmluYStCR0UgY29tIFJSRiBlIHJlcmFua2luZy4gIgogICAgICAgICJVc2UgdXBkYXRlX2ZpbGVfaW5kZXggYXDDs3MgZWRpdGFyIHVtIGFycXVpdm8gcGFyYSBtYW50ZXIgYXMgZHVhcyBjb2xlw6fDtWVzIHNpbmNyb25pemFkYXMuICIKICAgICAgICAiVXNlIGluZGV4X3NwZWNpZmljX2ZvbGRlciBwYXJhIGluZGV4YcOnw6NvIHJlY3Vyc2l2YSBzb2IgZGVtYW5kYS4iCiAgICApLAopCgoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBUb29sIDE6IHNlbWFudGljX3NlYXJjaF9jb2RlCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpAbWNwLnRvb2woKQpkZWYgc2VtYW50aWNfc2VhcmNoX2NvZGUocXVlcnk6IHN0ciwgdG9wX2s6IGludCA9IFRPUF9LX1JFU1VMVFMsIG1vZGU6IHN0ciA9IFNFQVJDSF9NT0RFX0RFRkFVTFQpIC0+IHN0cjoKICAgICIiIgogICAgQnVzY2Egc2Vtw6JudGljYSBubyDDrW5kaWNlIHZldG9yaWFsIGxvY2FsLgoKICAgIE1vZG9zOgogICAgLSBzaW5nbGU6IHVzYSBhcGVuYXMgdW1hIGJyYW5jaCAoSmluYS9CR0UgY29uZm9ybWUgTUNQX0VNQkVERElOR19NT0RFTDsgbm8gaHlicmlkLCBKaW5hIHYyKS4KICAgIC0gZW5zZW1ibGU6IGNvbnN1bHRhIGVtIHBhcmFsZWxvIGNvZGVfdmVjdG9yc19qaW5hICsgZG9jX3ZlY3RvcnNfYmdlLAogICAgICBmYXogZnVzw6NvIHZpYSBSZWNpcHJvY2FsIFJhbmsgRnVzaW9uIChSUkYpIGUgcmVyYW5raW5nIGxldmUuCgogICAgQXJnczoKICAgICAgICBxdWVyeTogRGVzY3Jpw6fDo28gZG8gcXVlIHByb2N1cmFyLgogICAgICAgIHRvcF9rOiBRdWFudGlkYWRlIGZpbmFsIGRlIHJlc3VsdGFkb3MuCiAgICAgICAgbW9kZTogInNpbmdsZSIgKHBhZHLDo28pIG91ICJlbnNlbWJsZSIuCgogICAgUmV0dXJuczoKICAgICAgICBSZXN1bHRhZG8gdGV4dHVhbCBmb3JtYXRhZG8gcGFyYSBjb25zdW1vIHBlbG8gTExNLgogICAgIiIiCiAgICByYXdfcXVlcnkgPSAocXVlcnkgb3IgIiIpLnN0cmlwKCkKICAgIHNlYXJjaF9tb2RlID0gKG1vZGUgb3IgU0VBUkNIX01PREVfREVGQVVMVCkuc3RyaXAoKS5sb3dlcigpCgogICAgX2xvZ190b29sX3VzYWdlKAogICAgICAgIGV2ZW50PSJ0b29sX2NhbGxfc3RhcnQiLAogICAgICAgIHRvb2xfbmFtZT0ic2VtYW50aWNfc2VhcmNoX2NvZGUiLAogICAgICAgIGRldGFpbHM9ewogICAgICAgICAgICAicXVlcnlfcHJldmlldyI6IF9zYWZlX3ByZXZpZXcocmF3X3F1ZXJ5KSwKICAgICAgICAgICAgInF1ZXJ5X2xlbiI6IGxlbihyYXdfcXVlcnkpLAogICAgICAgICAgICAidG9wX2siOiB0b3BfaywKICAgICAgICAgICAgIm1vZGUiOiBzZWFyY2hfbW9kZSwKICAgICAgICB9LAogICAgKQoKICAgIGlmIG5vdCByYXdfcXVlcnk6CiAgICAgICAgX2xvZ190b29sX3VzYWdlKAogICAgICAgICAgICBldmVudD0idG9vbF9jYWxsX2VuZCIsCiAgICAgICAgICAgIHRvb2xfbmFtZT0ic2VtYW50aWNfc2VhcmNoX2NvZGUiLAogICAgICAgICAgICBkZXRhaWxzPXsic3RhdHVzIjogImVycm9yIiwgInJlYXNvbiI6ICJlbXB0eV9xdWVyeSJ9LAogICAgICAgICkKICAgICAgICByZXR1cm4gIkVycm86IGEgcXVlcnkgbsOjbyBwb2RlIHNlciB2YXppYS4iCgogICAgdG9wX2sgPSBtYXgoMSwgbWluKHRvcF9rLCAyMCkpCiAgICBpZiBzZWFyY2hfbW9kZSBub3QgaW4geyJzaW5nbGUiLCAiZW5zZW1ibGUifToKICAgICAgICBfbG9nX3Rvb2xfdXNhZ2UoCiAgICAgICAgICAgIGV2ZW50PSJ0b29sX2NhbGxfZW5kIiwKICAgICAgICAgICAgdG9vbF9uYW1lPSJzZW1hbnRpY19zZWFyY2hfY29kZSIsCiAgICAgICAgICAgIGRldGFpbHM9eyJzdGF0dXMiOiAiZXJyb3IiLCAicmVhc29uIjogImludmFsaWRfbW9kZSIsICJtb2RlIjogc2VhcmNoX21vZGV9LAogICAgICAgICkKICAgICAgICByZXR1cm4gIkVycm86IG1vZGUgaW52w6FsaWRvLiBVc2UgJ3NpbmdsZScgb3UgJ2Vuc2VtYmxlJy4iCgogICAgdHJ5OgogICAgICAgIGlmIHNlYXJjaF9tb2RlID09ICJlbnNlbWJsZSI6CiAgICAgICAgICAgIGhpdHMsIGJyYW5jaF9lcnJvcnMsIHJlcmFua19hcHBsaWVkLCByZXJhbmtfZXJyb3IgPSBfcnVuX2Vuc2VtYmxlX21vZGUocmF3X3F1ZXJ5LCB0b3BfaykKICAgICAgICBlbHNlOgogICAgICAgICAgICBoaXRzLCBicmFuY2hfZXJyb3JzLCByZXJhbmtfYXBwbGllZCwgcmVyYW5rX2Vycm9yID0gX3J1bl9zaW5nbGVfbW9kZShyYXdfcXVlcnksIHRvcF9rKQoKICAgICAgICByZXN1bHRfdGV4dCA9IF9mb3JtYXRfZnVzZWRfcmVzdWx0cygKICAgICAgICAgICAgcXVlcnk9cmF3X3F1ZXJ5LAogICAgICAgICAgICBtb2RlPXNlYXJjaF9tb2RlLAogICAgICAgICAgICBoaXRzPWhpdHMsCiAgICAgICAgICAgIGJyYW5jaF9lcnJvcnM9YnJhbmNoX2Vycm9ycywKICAgICAgICAgICAgcmVyYW5rX2FwcGxpZWQ9cmVyYW5rX2FwcGxpZWQsCiAgICAgICAgICAgIHJlcmFua19lcnJvcj1yZXJhbmtfZXJyb3IsCiAgICAgICAgKQoKICAgICAgICBfbG9nX3Rvb2xfdXNhZ2UoCiAgICAgICAgICAgIGV2ZW50PSJ0b29sX2NhbGxfZW5kIiwKICAgICAgICAgICAgdG9vbF9uYW1lPSJzZW1hbnRpY19zZWFyY2hfY29kZSIsCiAgICAgICAgICAgIGRldGFpbHM9ewogICAgICAgICAgICAgICAgInN0YXR1cyI6ICJvayIsCiAgICAgICAgICAgICAgICAibW9kZSI6IHNlYXJjaF9tb2RlLAogICAgICAgICAgICAgICAgInJlc3VsdF9jb3VudCI6IGxlbihoaXRzKSwKICAgICAgICAgICAgICAgICJicmFuY2hfZXJyb3JzIjogbGVuKGJyYW5jaF9lcnJvcnMpLAogICAgICAgICAgICAgICAgInJlcmFua19hcHBsaWVkIjogcmVyYW5rX2FwcGxpZWQsCiAgICAgICAgICAgIH0sCiAgICAgICAgKQogICAgICAgIHJldHVybiByZXN1bHRfdGV4dAogICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgIF9sb2dfdG9vbF91c2FnZSgKICAgICAgICAgICAgZXZlbnQ9InRvb2xfY2FsbF9lbmQiLAogICAgICAgICAgICB0b29sX25hbWU9InNlbWFudGljX3NlYXJjaF9jb2RlIiwKICAgICAgICAgICAgZGV0YWlscz17InN0YXR1cyI6ICJlcnJvciIsICJyZWFzb24iOiAic2VhcmNoX2ZhaWxlZCIsICJlcnJvciI6IHN0cihlKSwgIm1vZGUiOiBzZWFyY2hfbW9kZX0sCiAgICAgICAgKQogICAgICAgIHJldHVybiBmIkVycm8gYW8gZXhlY3V0YXIgYnVzY2Egc2Vtw6JudGljYSAoe3NlYXJjaF9tb2RlfSk6IHtlfSIKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIFRvb2wgMjogdXBkYXRlX2ZpbGVfaW5kZXgKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCkBtY3AudG9vbCgpCmRlZiB1cGRhdGVfZmlsZV9pbmRleChmaWxlX3BhdGg6IHN0cikgLT4gc3RyOgogICAgIiIiCiAgICBBdHVhbGl6YSBvIMOtbmRpY2UgUkFHIHBhcmEgdW0gYXJxdWl2byBlc3BlY8OtZmljby4KCiAgICBPIGFycXVpdm8gw6kgY2xhc3NpZmljYWRvIGNvbW8gY8OzZGlnby9kb2MgZSBpbmRleGFkbyBuYSBjb2xlw6fDo28gYXByb3ByaWFkYS4KICAgIFBhcmEgZXh0ZW5zw7VlcyBhbWLDrWd1YXMsIGluZGV4YSBlbSBhbWJhcyBhcyBjb2xlw6fDtWVzLgogICAgIiIiCiAgICBmaWxlcGF0aCA9IFBhdGgoZmlsZV9wYXRoKS5yZXNvbHZlKCkKICAgIGFic19wYXRoID0gc3RyKGZpbGVwYXRoKQoKICAgIF9sb2dfdG9vbF91c2FnZSgKICAgICAgICBldmVudD0idG9vbF9jYWxsX3N0YXJ0IiwKICAgICAgICB0b29sX25hbWU9InVwZGF0ZV9maWxlX2luZGV4IiwKICAgICAgICBkZXRhaWxzPXsiZmlsZV9wYXRoIjogYWJzX3BhdGh9LAogICAgKQoKICAgIGlmIG5vdCBmaWxlcGF0aC5leGlzdHMoKToKICAgICAgICBfbG9nX3Rvb2xfdXNhZ2UoCiAgICAgICAgICAgIGV2ZW50PSJ0b29sX2NhbGxfZW5kIiwKICAgICAgICAgICAgdG9vbF9uYW1lPSJ1cGRhdGVfZmlsZV9pbmRleCIsCiAgICAgICAgICAgIGRldGFpbHM9eyJzdGF0dXMiOiAiZXJyb3IiLCAicmVhc29uIjogImZpbGVfbm90X2ZvdW5kIiwgImZpbGVfcGF0aCI6IGFic19wYXRofSwKICAgICAgICApCiAgICAgICAgcmV0dXJuIGYiRXJybzogYXJxdWl2byBuw6NvIGVuY29udHJhZG86IHtmaWxlcGF0aH0iCgogICAgaWYgbm90IGZpbGVwYXRoLmlzX2ZpbGUoKToKICAgICAgICBfbG9nX3Rvb2xfdXNhZ2UoCiAgICAgICAgICAgIGV2ZW50PSJ0b29sX2NhbGxfZW5kIiwKICAgICAgICAgICAgdG9vbF9uYW1lPSJ1cGRhdGVfZmlsZV9pbmRleCIsCiAgICAgICAgICAgIGRldGFpbHM9eyJzdGF0dXMiOiAiZXJyb3IiLCAicmVhc29uIjogIm5vdF9hX2ZpbGUiLCAiZmlsZV9wYXRoIjogYWJzX3BhdGh9LAogICAgICAgICkKICAgICAgICByZXR1cm4gZiJFcnJvOiBvIGNhbWluaG8gbsOjbyBhcG9udGEgcGFyYSB1bSBhcnF1aXZvOiB7ZmlsZXBhdGh9IgoKICAgIGlmIGZpbGVwYXRoLnN0YXQoKS5zdF9zaXplID4gTUFYX0ZJTEVfU0laRV9CWVRFUzoKICAgICAgICBfbG9nX3Rvb2xfdXNhZ2UoCiAgICAgICAgICAgIGV2ZW50PSJ0b29sX2NhbGxfZW5kIiwKICAgICAgICAgICAgdG9vbF9uYW1lPSJ1cGRhdGVfZmlsZV9pbmRleCIsCiAgICAgICAgICAgIGRldGFpbHM9eyJzdGF0dXMiOiAiZXJyb3IiLCAicmVhc29uIjogImZpbGVfdG9vX2xhcmdlIiwgImZpbGVfcGF0aCI6IGFic19wYXRofSwKICAgICAgICApCiAgICAgICAgcmV0dXJuIGYiRXJybzogYXJxdWl2byBtdWl0byBncmFuZGUgKD57TUFYX0ZJTEVfU0laRV9CWVRFUyAvLyAxMDI0fUtCKToge2ZpbGVwYXRofSIKCiAgICBzcGxpdHRlciA9IGdldF9zcGxpdHRlcigpCiAgICB0YXJnZXRzID0gX2NsYXNzaWZ5X2ZpbGVfdGFyZ2V0cyhmaWxlcGF0aCkKCiAgICBkZWxldGVkX3Blcl9icmFuY2gsIGRlbGV0aW9uX2Vycm9ycyA9IF9yZW1vdmVfZmlsZV9mcm9tX2FsbF9jb2xsZWN0aW9ucyhhYnNfcGF0aCkKCiAgICBpbnNlcnRlZF9wZXJfYnJhbmNoOiBkaWN0W3N0ciwgaW50XSA9IHt9CiAgICBpbmRleF9lcnJvcnM6IGxpc3Rbc3RyXSA9IFtdCiAgICBmb3IgYnJhbmNoIGluIHRhcmdldHM6CiAgICAgICAgdHJ5OgogICAgICAgICAgICBpbnNlcnRlZCA9IF9pbmRleF9zaW5nbGVfZmlsZV9mb3JfYnJhbmNoKAogICAgICAgICAgICAgICAgZmlsZXBhdGgsCiAgICAgICAgICAgICAgICBicmFuY2gsCiAgICAgICAgICAgICAgICBzcGxpdHRlciwKICAgICAgICAgICAgICAgIGRlbGV0ZV9leGlzdGluZz1GYWxzZSwgICMgasOhIHJlbW92aWRvIGVtIHRvZGFzIGFzIGNvbGXDp8O1ZXMgYWNpbWEKICAgICAgICAgICAgKQogICAgICAgICAgICBpbnNlcnRlZF9wZXJfYnJhbmNoW2JyYW5jaC5rZXldID0gaW5zZXJ0ZWQKICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgIGluZGV4X2Vycm9ycy5hcHBlbmQoZiJ7YnJhbmNoLmtleX06IHtlfSIpCgogICAgc3VjY2Vzc19icmFuY2hlcyA9IFtrIGZvciBrLCB2IGluIGluc2VydGVkX3Blcl9icmFuY2guaXRlbXMoKSBpZiB2ID4gMF0KCiAgICBkZXRhaWxzID0gewogICAgICAgICJzdGF0dXMiOiAib2siIGlmIHN1Y2Nlc3NfYnJhbmNoZXMgZWxzZSAiZXJyb3IiLAogICAgICAgICJmaWxlX3BhdGgiOiBhYnNfcGF0aCwKICAgICAgICAidGFyZ2V0cyI6IFtiLmtleSBmb3IgYiBpbiB0YXJnZXRzXSwKICAgICAgICAiZGVsZXRlZF9wZXJfYnJhbmNoIjogZGVsZXRlZF9wZXJfYnJhbmNoLAogICAgICAgICJpbnNlcnRlZF9wZXJfYnJhbmNoIjogaW5zZXJ0ZWRfcGVyX2JyYW5jaCwKICAgICAgICAiZGVsZXRpb25fZXJyb3JzIjogbGVuKGRlbGV0aW9uX2Vycm9ycyksCiAgICAgICAgImluZGV4X2Vycm9ycyI6IGxlbihpbmRleF9lcnJvcnMpLAogICAgfQogICAgX2xvZ190b29sX3VzYWdlKGV2ZW50PSJ0b29sX2NhbGxfZW5kIiwgdG9vbF9uYW1lPSJ1cGRhdGVfZmlsZV9pbmRleCIsIGRldGFpbHM9ZGV0YWlscykKCiAgICBpZiBub3Qgc3VjY2Vzc19icmFuY2hlcyBhbmQgaW5kZXhfZXJyb3JzOgogICAgICAgIHJldHVybiAoCiAgICAgICAgICAgICJFcnJvOiBuw6NvIGZvaSBwb3Nzw612ZWwgcmVpbmRleGFyIG8gYXJxdWl2byBlbSBuZW5odW1hIGNvbGXDp8Ojby5cbiIKICAgICAgICAgICAgZiJBcnF1aXZvOiB7ZmlsZXBhdGh9XG4iCiAgICAgICAgICAgICJGYWxoYXM6ICIgKyAiIHwgIi5qb2luKGluZGV4X2Vycm9ycykKICAgICAgICApCgogICAgbGluZXMgPSBbCiAgICAgICAgIkFycXVpdm8gcmVpbmRleGFkby4iLAogICAgICAgIGYiICBBcnF1aXZvIDoge2ZpbGVwYXRofSIsCiAgICAgICAgZiIgIENvbGXDp8O1ZXMgYWx2bzoge1tiLmNvbGxlY3Rpb25fbmFtZSBmb3IgYiBpbiB0YXJnZXRzXX0iLAogICAgICAgIGYiICBSZW1vw6fDtWVzIHBvciBjb2xlw6fDo286IHtkZWxldGVkX3Blcl9icmFuY2h9IiwKICAgICAgICBmIiAgSW5zZXLDp8O1ZXMgcG9yIGNvbGXDp8Ojbzoge2luc2VydGVkX3Blcl9icmFuY2h9IiwKICAgIF0KICAgIGlmIGRlbGV0aW9uX2Vycm9yczoKICAgICAgICBsaW5lcy5hcHBlbmQoIiAgQXZpc29zIG5hIHJlbW/Dp8OjbzogIiArICIgfCAiLmpvaW4oZGVsZXRpb25fZXJyb3JzKSkKICAgIGlmIGluZGV4X2Vycm9yczoKICAgICAgICBsaW5lcy5hcHBlbmQoIiAgQXZpc29zIG5hIGluZGV4YcOnw6NvOiAiICsgIiB8ICIuam9pbihpbmRleF9lcnJvcnMpKQogICAgcmV0dXJuICJcbiIuam9pbihsaW5lcykKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIFRvb2wgMzogZGVsZXRlX2ZpbGVfaW5kZXgKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCkBtY3AudG9vbCgpCmRlZiBkZWxldGVfZmlsZV9pbmRleChmaWxlX3BhdGg6IHN0cikgLT4gc3RyOgogICAgIiIiCiAgICBSZW1vdmUgdW0gYXJxdWl2byBkbyDDrW5kaWNlIGVtIHRvZGFzIGFzIGNvbGXDp8O1ZXMgZ2VyZW5jaWFkYXMuCiAgICAiIiIKICAgIGZpbGVwYXRoID0gUGF0aChmaWxlX3BhdGgpLnJlc29sdmUoKQogICAgYWJzX3BhdGggPSBzdHIoZmlsZXBhdGgpCgogICAgX2xvZ190b29sX3VzYWdlKAogICAgICAgIGV2ZW50PSJ0b29sX2NhbGxfc3RhcnQiLAogICAgICAgIHRvb2xfbmFtZT0iZGVsZXRlX2ZpbGVfaW5kZXgiLAogICAgICAgIGRldGFpbHM9eyJmaWxlX3BhdGgiOiBhYnNfcGF0aH0sCiAgICApCgogICAgZGVsZXRlZF9wZXJfYnJhbmNoLCBlcnJvcnMgPSBfcmVtb3ZlX2ZpbGVfZnJvbV9hbGxfY29sbGVjdGlvbnMoYWJzX3BhdGgpCiAgICB0b3RhbF9kZWxldGVkID0gc3VtKGRlbGV0ZWRfcGVyX2JyYW5jaC52YWx1ZXMoKSkKCiAgICBfbG9nX3Rvb2xfdXNhZ2UoCiAgICAgICAgZXZlbnQ9InRvb2xfY2FsbF9lbmQiLAogICAgICAgIHRvb2xfbmFtZT0iZGVsZXRlX2ZpbGVfaW5kZXgiLAogICAgICAgIGRldGFpbHM9ewogICAgICAgICAgICAic3RhdHVzIjogIm9rIiBpZiB0b3RhbF9kZWxldGVkID4gMCBlbHNlICJ3YXJuaW5nIiwKICAgICAgICAgICAgImZpbGVfcGF0aCI6IGFic19wYXRoLAogICAgICAgICAgICAiZGVsZXRlZF9wZXJfYnJhbmNoIjogZGVsZXRlZF9wZXJfYnJhbmNoLAogICAgICAgICAgICAiZXJyb3JzIjogbGVuKGVycm9ycyksCiAgICAgICAgfSwKICAgICkKCiAgICBpZiB0b3RhbF9kZWxldGVkID09IDA6CiAgICAgICAgYmFzZSA9IGYiTmVuaHVtIGNodW5rIGVuY29udHJhZG8gcGFyYSBvIGFycXVpdm86IHthYnNfcGF0aH0iCiAgICAgICAgaWYgZXJyb3JzOgogICAgICAgICAgICBiYXNlICs9ICJcbkZhbGhhcyBwYXJjaWFpczogIiArICIgfCAiLmpvaW4oZXJyb3JzKQogICAgICAgIHJldHVybiBiYXNlCgogICAgb3V0ID0gWwogICAgICAgICJSZW1vdmlkbyBkbyDDrW5kaWNlIGNvbSBzdWNlc3NvLiIsCiAgICAgICAgZiIgIEFycXVpdm8gOiB7YWJzX3BhdGh9IiwKICAgICAgICBmIiAgRGVsZcOnw7VlcyBwb3IgY29sZcOnw6NvOiB7ZGVsZXRlZF9wZXJfYnJhbmNofSIsCiAgICBdCiAgICBpZiBlcnJvcnM6CiAgICAgICAgb3V0LmFwcGVuZCgiICBBdmlzb3M6ICIgKyAiIHwgIi5qb2luKGVycm9ycykpCiAgICByZXR1cm4gIlxuIi5qb2luKG91dCkKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIFRvb2wgNDogaW5kZXhfc3BlY2lmaWNfZm9sZGVyCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpAbWNwLnRvb2woKQpkZWYgaW5kZXhfc3BlY2lmaWNfZm9sZGVyKGZvbGRlcl9wYXRoOiBzdHIpIC0+IHN0cjoKICAgICIiIgogICAgSW5kZXhhIHJlY3Vyc2l2YW1lbnRlIHVtYSBwYXN0YSBlbSBjb2xlw6fDtWVzIHNlcGFyYWRhcyBwb3IgZG9tw61uaW8uCiAgICAiIiIKICAgIGZvbGRlciA9IFBhdGgoZm9sZGVyX3BhdGgpLnJlc29sdmUoKQoKICAgIF9sb2dfdG9vbF91c2FnZSgKICAgICAgICBldmVudD0idG9vbF9jYWxsX3N0YXJ0IiwKICAgICAgICB0b29sX25hbWU9ImluZGV4X3NwZWNpZmljX2ZvbGRlciIsCiAgICAgICAgZGV0YWlscz17ImZvbGRlcl9wYXRoIjogc3RyKGZvbGRlcil9LAogICAgKQoKICAgIGlmIG5vdCBmb2xkZXIuZXhpc3RzKCk6CiAgICAgICAgX2xvZ190b29sX3VzYWdlKAogICAgICAgICAgICBldmVudD0idG9vbF9jYWxsX2VuZCIsCiAgICAgICAgICAgIHRvb2xfbmFtZT0iaW5kZXhfc3BlY2lmaWNfZm9sZGVyIiwKICAgICAgICAgICAgZGV0YWlscz17InN0YXR1cyI6ICJlcnJvciIsICJyZWFzb24iOiAiZm9sZGVyX25vdF9mb3VuZCIsICJmb2xkZXJfcGF0aCI6IHN0cihmb2xkZXIpfSwKICAgICAgICApCiAgICAgICAgcmV0dXJuIGYiRXJybzogcGFzdGEgbsOjbyBlbmNvbnRyYWRhOiB7Zm9sZGVyfSIKCiAgICBpZiBub3QgZm9sZGVyLmlzX2RpcigpOgogICAgICAgIF9sb2dfdG9vbF91c2FnZSgKICAgICAgICAgICAgZXZlbnQ9InRvb2xfY2FsbF9lbmQiLAogICAgICAgICAgICB0b29sX25hbWU9ImluZGV4X3NwZWNpZmljX2ZvbGRlciIsCiAgICAgICAgICAgIGRldGFpbHM9eyJzdGF0dXMiOiAiZXJyb3IiLCAicmVhc29uIjogIm5vdF9hX2ZvbGRlciIsICJmb2xkZXJfcGF0aCI6IHN0cihmb2xkZXIpfSwKICAgICAgICApCiAgICAgICAgcmV0dXJuIGYiRXJybzogbyBjYW1pbmhvIG7Do28gw6kgdW0gZGlyZXTDs3Jpbzoge2ZvbGRlcn0iCgogICAgc3BsaXR0ZXIgPSBnZXRfc3BsaXR0ZXIoKQoKICAgIHByb2Nlc3NlZF9maWxlcyA9IDAKICAgIGJyYW5jaF9maWxlX2NvdW50cyA9IHtrZXk6IDAgZm9yIGtleSBpbiBCUkFOQ0hfU1BFQ1N9CiAgICBicmFuY2hfY2h1bmtfY291bnRzID0ge2tleTogMCBmb3Iga2V5IGluIEJSQU5DSF9TUEVDU30KICAgIGVycm9yX2NvdW50ID0gMAogICAgZXJyb3Jfc2FtcGxlczogbGlzdFtzdHJdID0gW10KCiAgICBmb3IgZmlsZXBhdGggaW4gX3NjYW5fZm9sZGVyKGZvbGRlcik6CiAgICAgICAgcHJvY2Vzc2VkX2ZpbGVzICs9IDEKICAgICAgICB0YXJnZXRzID0gX2NsYXNzaWZ5X2ZpbGVfdGFyZ2V0cyhmaWxlcGF0aCkKCiAgICAgICAgZm9yIGJyYW5jaCBpbiB0YXJnZXRzOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBuX2NodW5rcyA9IF9pbmRleF9zaW5nbGVfZmlsZV9mb3JfYnJhbmNoKGZpbGVwYXRoLCBicmFuY2gsIHNwbGl0dGVyKQogICAgICAgICAgICAgICAgYnJhbmNoX2ZpbGVfY291bnRzW2JyYW5jaC5rZXldICs9IDEKICAgICAgICAgICAgICAgIGJyYW5jaF9jaHVua19jb3VudHNbYnJhbmNoLmtleV0gKz0gbl9jaHVua3MKICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICAgICAgZXJyb3JfY291bnQgKz0gMQogICAgICAgICAgICAgICAgaWYgbGVuKGVycm9yX3NhbXBsZXMpIDwgMTA6CiAgICAgICAgICAgICAgICAgICAgZXJyb3Jfc2FtcGxlcy5hcHBlbmQoZiJ7ZmlsZXBhdGgubmFtZX0gW3ticmFuY2gua2V5fV06IHtlfSIpCgogICAgaWYgcHJvY2Vzc2VkX2ZpbGVzID09IDA6CiAgICAgICAgX2xvZ190b29sX3VzYWdlKAogICAgICAgICAgICBldmVudD0idG9vbF9jYWxsX2VuZCIsCiAgICAgICAgICAgIHRvb2xfbmFtZT0iaW5kZXhfc3BlY2lmaWNfZm9sZGVyIiwKICAgICAgICAgICAgZGV0YWlscz17InN0YXR1cyI6ICJvayIsICJmb2xkZXJfcGF0aCI6IHN0cihmb2xkZXIpLCAiZmlsZXNfcHJvY2Vzc2VkIjogMCwgImNodW5rcyI6IDAsICJlcnJvcnMiOiAwfSwKICAgICAgICApCiAgICAgICAgcmV0dXJuIGYiTmVuaHVtIGFycXVpdm8gaW5kZXjDoXZlbCBlbmNvbnRyYWRvIGVtOiB7Zm9sZGVyfSIKCiAgICB0b3RhbF9jaHVua3MgPSBzdW0oYnJhbmNoX2NodW5rX2NvdW50cy52YWx1ZXMoKSkKCiAgICBfbG9nX3Rvb2xfdXNhZ2UoCiAgICAgICAgZXZlbnQ9InRvb2xfY2FsbF9lbmQiLAogICAgICAgIHRvb2xfbmFtZT0iaW5kZXhfc3BlY2lmaWNfZm9sZGVyIiwKICAgICAgICBkZXRhaWxzPXsKICAgICAgICAgICAgInN0YXR1cyI6ICJvayIsCiAgICAgICAgICAgICJmb2xkZXJfcGF0aCI6IHN0cihmb2xkZXIpLAogICAgICAgICAgICAiZmlsZXNfcHJvY2Vzc2VkIjogcHJvY2Vzc2VkX2ZpbGVzLAogICAgICAgICAgICAiY2h1bmtzIjogdG90YWxfY2h1bmtzLAogICAgICAgICAgICAiZXJyb3JzIjogZXJyb3JfY291bnQsCiAgICAgICAgICAgICJicmFuY2hfZmlsZV9jb3VudHMiOiBicmFuY2hfZmlsZV9jb3VudHMsCiAgICAgICAgICAgICJicmFuY2hfY2h1bmtfY291bnRzIjogYnJhbmNoX2NodW5rX2NvdW50cywKICAgICAgICB9LAogICAgKQoKICAgIHJlcG9ydCA9IFsKICAgICAgICAiSW5kZXhhw6fDo28gZGEgcGFzdGEgY29uY2x1w61kYS4iLAogICAgICAgIGYiICBQYXN0YToge2ZvbGRlcn0iLAogICAgICAgIGYiICBBcnF1aXZvcyBwcm9jZXNzYWRvczoge3Byb2Nlc3NlZF9maWxlc30iLAogICAgICAgIGYiICBUb3RhbCBkZSBjaHVua3M6IHt0b3RhbF9jaHVua3N9IiwKICAgICAgICBmIiAgQXJxdWl2b3MgcG9yIGJyYW5jaDoge2JyYW5jaF9maWxlX2NvdW50c30iLAogICAgICAgIGYiICBDaHVua3MgcG9yIGJyYW5jaDoge2JyYW5jaF9jaHVua19jb3VudHN9IiwKICAgIF0KCiAgICBpZiBlcnJvcl9jb3VudDoKICAgICAgICByZXBvcnQuYXBwZW5kKGYiICBFcnJvcyAoe2Vycm9yX2NvdW50fSk6IikKICAgICAgICBmb3IgZXJyIGluIGVycm9yX3NhbXBsZXM6CiAgICAgICAgICAgIHJlcG9ydC5hcHBlbmQoZiIgICAgLSB7ZXJyfSIpCiAgICAgICAgaWYgZXJyb3JfY291bnQgPiBsZW4oZXJyb3Jfc2FtcGxlcyk6CiAgICAgICAgICAgIHJlcG9ydC5hcHBlbmQoZiIgICAgLi4uIGUgbWFpcyB7ZXJyb3JfY291bnQgLSBsZW4oZXJyb3Jfc2FtcGxlcyl9IGVycm9zLiIpCgogICAgcmV0dXJuICJcbiIuam9pbihyZXBvcnQpCgoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBQb250byBkZSBlbnRyYWRhCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgbG9nLmluZm8oIkluaWNpYW5kbyBzZXJ2aWRvciBNQ1AgUkFHIChzdGRpbykuLi4iKQogICAgbG9nLmluZm8oIkNocm9tYURCOiAlczovLyVzOiVzIiwgQ0hST01BX1NDSEVNRSwgQ0hST01BX0hPU1QsIENIUk9NQV9QT1JUKQogICAgbG9nLmluZm8oCiAgICAgICAgIkNvbGXDp8O1ZXM6ICVzICglcyksICVzICglcykiLAogICAgICAgIENPTExFQ1RJT05fQ09ERV9KSU5BLAogICAgICAgIEJSQU5DSF9TUEVDU1siamluYV9jb2RlIl0ubW9kZWxfaWQsCiAgICAgICAgQ09MTEVDVElPTl9ET0NfQkdFLAogICAgICAgIEJSQU5DSF9TUEVDU1siYmdlX2RvYyJdLm1vZGVsX2lkLAogICAgKQogICAgbG9nLmluZm8oIk1vZG8gcGFkcsOjbyBkZSBidXNjYTogJXMiLCBTRUFSQ0hfTU9ERV9ERUZBVUxUKQogICAgbG9nLmluZm8oIk1vZGVsbyBzaW5nbGUgcGFkcsOjbzogJXMiLCBCUkFOQ0hfU1BFQ1NbREVGQVVMVF9TSU5HTEVfQlJBTkNIX0tFWV0ubW9kZWxfaWQpCiAgICBsb2cuaW5mbygiUXVhbnRpemFjYW8gSmluYTogJXMiLCBKSU5BX1FVQU5USVpBVElPTikKICAgIGxvZy5pbmZvKCJDb25maWcgZGUgdHVuaW5nIGNhcnJlZ2FkYSBkZTogJXMgKGZvdW5kPSVzKSIsIElOREVYRVJfQ09ORklHX1BBVEgsIGJvb2woSU5ERVhFUl9UVU5JTkdfQ09ORklHKSkKICAgIGxvZy5pbmZvKCJFbWJlZGRpbmcgYmF0Y2ggc2l6ZTogJXMiLCBFTUJFRERJTkdfQkFUQ0hfU0laRSkKICAgIGxvZy5pbmZvKCJDaHVuayBwYXJhbXM6IHNpemU9JXMgb3ZlcmxhcD0lcyIsIENIVU5LX1NJWkUsIENIVU5LX09WRVJMQVApCiAgICBsb2cuaW5mbygiUmVyYW5rZXI6ICVzIChlbmFibGVkPSVzLCBxdWFudD0lcykiLCBSRVJBTktfTU9ERUxfSUQsIFJFUkFOS19FTkFCTEVELCBSRVJBTktFUl9RVUFOVElaQVRJT04pCiAgICBsb2cuaW5mbygiUGFzdGEgZGUgbW9kZWxvcyBsb2NhaXM6ICVzIiwgTU9ERUxfRElSKQogICAgbG9nLmluZm8oIlVzbyBNQ1Agc2Vyw6EgcmVnaXN0cmFkbyBlbTogJXMiLCBNQ1BfVVNBR0VfTE9HX1BBVEgpCgogICAgIyBQcsOpLWFxdWVjZSBzb21lbnRlIGNvbmV4w6NvIENocm9tYTsgbW9kZWxvcyBmaWNhbSBsYXp5IHBhcmEgcG91cGFyIFJBTS4KICAgIHRyeToKICAgICAgICBfZ2V0X2Nocm9tYV9jbGllbnQoKQogICAgICAgIGdldF9jaHJvbWFfY29sbGVjdGlvbihDT0xMRUNUSU9OX0NPREVfSklOQSkKICAgICAgICBnZXRfY2hyb21hX2NvbGxlY3Rpb24oQ09MTEVDVElPTl9ET0NfQkdFKQogICAgICAgIGxvZy5pbmZvKCJDb25leMOjbyBDaHJvbWEgaW5pY2lhbGl6YWRhLiBNb2RlbG9zIHNlcsOjbyBjYXJyZWdhZG9zIHNvYiBkZW1hbmRhLiIpCiAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgbG9nLmVycm9yKCJGYWxoYSBhbyBpbmljaWFsaXphciBDaHJvbWFEQjogJXMiLCBlKQogICAgICAgIGxvZy5lcnJvcigiTyBzZXJ2aWRvciBjb250aW51YXLDoSwgbWFzIGFzIGZlcnJhbWVudGFzIHJldG9ybmFyw6NvIGVycm8gYXTDqSBvIENocm9tYURCIGVzdGFyIGRpc3BvbsOtdmVsLiIpCgogICAgbWNwLnJ1bih0cmFuc3BvcnQ9InN0ZGlvIikK"
|
|
565
729
|
B64_MODEL_DL_HF="IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwpmcm9tIF9fZnV0dXJlX18gaW1wb3J0IGFubm90YXRpb25zCgoiIiIKZG93bmxvYWRfbW9kZWxfZnJvbV9odWdnaW5mYWNlLnB5CgpDYW1hZGEgZGUgZG93bmxvYWQgZGUgbW9kZWxvcyBjb20gcHJpb3JpZGFkZSBkZSBwcm92ZWRvcmVzIGUgZmFsbGJhY2sgZGUgbW9kZWxvLgpGbHV4byBwYWRyw6NvOgoxKSB0ZW50YSBiYWl4YXIgbyBtb2RlbG8gcHJlZmVyaWRvIHZpYSBIdWdnaW5nIEZhY2U7CjIpIHNlIGZhbGhhciwgdGVudGEgcHJvdmVkb3JlcyBhbHRlcm5hdGl2b3MgKHF1YW5kbyBkaXNwb27DrXZlaXMpOwozKSBzZSBvIG1vZGVsbyBwcmVmZXJpZG8gZmFsaGFyIGVtIHRvZG9zIG9zIHByb3ZlZG9yZXMsIHRlbnRhIG1vZGVsbyBmYWxsYmFjay4KIiIiCgpmcm9tIGRhdGFjbGFzc2VzIGltcG9ydCBkYXRhY2xhc3MKaW1wb3J0IGdldHBhc3MKaW1wb3J0IG9zCmZyb20gcGF0aGxpYiBpbXBvcnQgUGF0aAppbXBvcnQgc2h1dGlsCmltcG9ydCBzeXMKZnJvbSB0eXBpbmcgaW1wb3J0IFByb3RvY29sCgoKY2xhc3MgTW9kZWxEb3dubG9hZFN0cmF0ZWd5KFByb3RvY29sKToKICAgIG5hbWU6IHN0cgoKICAgIGRlZiBkb3dubG9hZChzZWxmLCBtb2RlbF9pZDogc3RyLCBsb2NhbF9kaXI6IFBhdGgpIC0+IE5vbmU6CiAgICAgICAgIiIiQmFpeGEgbW9kZWxfaWQgcGFyYSBsb2NhbF9kaXIgb3UgbGV2YW50YSBleGNlw6fDo28uIiIiCgoKY2xhc3MgSHVnZ2luZ0ZhY2VEb3dubG9hZFN0cmF0ZWd5OgogICAgbmFtZSA9ICJodWdnaW5nZmFjZSIKCiAgICBkZWYgZG93bmxvYWQoc2VsZiwgbW9kZWxfaWQ6IHN0ciwgbG9jYWxfZGlyOiBQYXRoKSAtPiBOb25lOgogICAgICAgIGZyb20gaHVnZ2luZ2ZhY2VfaHViIGltcG9ydCBzbmFwc2hvdF9kb3dubG9hZAoKICAgICAgICBoZl90b2tlbiA9IG9zLmVudmlyb24uZ2V0KCJIRl9UT0tFTiIpIG9yIG9zLmVudmlyb24uZ2V0KCJIVUdHSU5HX0ZBQ0VfSFVCX1RPS0VOIikKICAgICAgICBfZG93bmxvYWRfd2l0aF9oZl90b2tlbl9yZWNvdmVyeSgKICAgICAgICAgICAgcmVwb19pZD1tb2RlbF9pZCwKICAgICAgICAgICAgbG9jYWxfZGlyPWxvY2FsX2RpciwKICAgICAgICAgICAgaGZfdG9rZW49aGZfdG9rZW4sCiAgICAgICAgICAgIHNuYXBzaG90X2Rvd25sb2FkPXNuYXBzaG90X2Rvd25sb2FkLAogICAgICAgICkKCgpAZGF0YWNsYXNzKGZyb3plbj1UcnVlKQpjbGFzcyBEb3dubG9hZFNlbGVjdGlvbjoKICAgIG1vZGVsX2lkOiBzdHIKICAgIHByb3ZpZGVyOiBzdHIKICAgIGxvY2FsX2RpcjogUGF0aAoKCmRlZiBfbG9hZF9vcHRpb25hbF9zdHJhdGVnaWVzKCkgLT4gbGlzdFtNb2RlbERvd25sb2FkU3RyYXRlZ3ldOgogICAgc3RyYXRlZ2llczogbGlzdFtNb2RlbERvd25sb2FkU3RyYXRlZ3ldID0gW10KCiAgICB0cnk6CiAgICAgICAgZnJvbSBkb3dubG9hZF9tb2RlbF9mcm9tX21vZGVsc2NvcGUgaW1wb3J0IE1vZGVsU2NvcGVEb3dubG9hZFN0cmF0ZWd5CgogICAgICAgIHN0cmF0ZWdpZXMuYXBwZW5kKE1vZGVsU2NvcGVEb3dubG9hZFN0cmF0ZWd5KCkpCiAgICBleGNlcHQgRXhjZXB0aW9uOgogICAgICAgICMgUHJvdmlkZXIgb3BjaW9uYWw6IGlnbm9yYSBzZSBuw6NvIGVzdGl2ZXIgZGlzcG9uw612ZWwgbm8gYW1iaWVudGUuCiAgICAgICAgcGFzcwoKICAgIHJldHVybiBzdHJhdGVnaWVzCgoKZGVmIGJ1aWxkX2RlZmF1bHRfc3RyYXRlZ2llcygpIC0+IGxpc3RbTW9kZWxEb3dubG9hZFN0cmF0ZWd5XToKICAgICIiIkZhY3Rvcnkgc2ltcGxlczogb3JkZW0gZGUgcHJpb3JpZGFkZSBkZSBwcm92ZWRvcmVzIGRlIGRvd25sb2FkLiIiIgogICAgcmV0dXJuIFtIdWdnaW5nRmFjZURvd25sb2FkU3RyYXRlZ3koKSwgKl9sb2FkX29wdGlvbmFsX3N0cmF0ZWdpZXMoKV0KCgpfTU9ERUxfUkVBRFlfTUFSS0VSID0gIi5kb3dubG9hZF9jb21wbGV0ZSIKCgpkZWYgX3ByZXBhcmVfZGVzdGluYXRpb24obG9jYWxfZGlyOiBQYXRoLCAqLCBjbGVhbjogYm9vbCkgLT4gTm9uZToKICAgIGlmIGNsZWFuIGFuZCBsb2NhbF9kaXIuZXhpc3RzKCk6CiAgICAgICAgc2h1dGlsLnJtdHJlZShsb2NhbF9kaXIpCiAgICBsb2NhbF9kaXIubWtkaXIocGFyZW50cz1UcnVlLCBleGlzdF9vaz1UcnVlKQoKCmRlZiBfbW9kZWxfY2FjaGVfZGlyKGJhc2VfZGlyOiBQYXRoLCBtb2RlbF9pZDogc3RyKSAtPiBQYXRoOgogICAgIyBFdml0YSBjb2xpc8OjbyBkZSBub21lcyBlIG1hbnTDqW0gZGlyZXTDs3JpbyBzZWd1cm8gZW0gcXVhbHF1ZXIgU08uCiAgICBzYWZlX25hbWUgPSBtb2RlbF9pZC5yZXBsYWNlKCIvIiwgIl9fIikucmVwbGFjZSgiOiIsICJfIikKICAgIHJldHVybiBiYXNlX2RpciAvIHNhZmVfbmFtZQoKCmRlZiBfY2FjaGVfcmVhZHkobG9jYWxfZGlyOiBQYXRoKSAtPiBib29sOgogICAgbWFya2VyID0gbG9jYWxfZGlyIC8gX01PREVMX1JFQURZX01BUktFUgogICAgaWYgbm90IG1hcmtlci5leGlzdHMoKSBvciBub3QgbG9jYWxfZGlyLmV4aXN0cygpOgogICAgICAgIHJldHVybiBGYWxzZQogICAgcmV0dXJuIGFueShwLm5hbWUgIT0gX01PREVMX1JFQURZX01BUktFUiBmb3IgcCBpbiBsb2NhbF9kaXIuaXRlcmRpcigpKQoKCmRlZiBfbWFya19jYWNoZV9yZWFkeShsb2NhbF9kaXI6IFBhdGgpIC0+IE5vbmU6CiAgICAobG9jYWxfZGlyIC8gX01PREVMX1JFQURZX01BUktFUikud3JpdGVfdGV4dCgib2tcbiIsIGVuY29kaW5nPSJ1dGYtOCIpCgoKZGVmIF9zdGF0dXNfY29kZV9mcm9tX2Vycm9yKGV4YzogRXhjZXB0aW9uKSAtPiBpbnQgfCBOb25lOgogICAgcmVzcG9uc2UgPSBnZXRhdHRyKGV4YywgInJlc3BvbnNlIiwgTm9uZSkKICAgIGlmIHJlc3BvbnNlIGlzIE5vbmU6CiAgICAgICAgcmV0dXJuIE5vbmUKICAgIHN0YXR1c19jb2RlID0gZ2V0YXR0cihyZXNwb25zZSwgInN0YXR1c19jb2RlIiwgTm9uZSkKICAgIGlmIGlzaW5zdGFuY2Uoc3RhdHVzX2NvZGUsIGludCk6CiAgICAgICAgcmV0dXJuIHN0YXR1c19jb2RlCiAgICByZXR1cm4gTm9uZQoKCmRlZiBfaXNfaW52YWxpZF9oZl90b2tlbl9lcnJvcihleGM6IEV4Y2VwdGlvbikgLT4gYm9vbDoKICAgIG1lc3NhZ2UgPSBzdHIoZXhjKS5sb3dlcigpCiAgICBzdGF0dXNfY29kZSA9IF9zdGF0dXNfY29kZV9mcm9tX2Vycm9yKGV4YykKICAgIHRva2VuX2tleXdvcmRzID0gKCJpbnZhbGlkIHRva2VuIiwgInRva2VuIGlzIGludmFsaWQiLCAidW5hdXRob3JpemVkIiwgIjQwMSIpCiAgICBpZiBzdGF0dXNfY29kZSA9PSA0MDE6CiAgICAgICAgcmV0dXJuIFRydWUKICAgIHJldHVybiBhbnkoa2V5d29yZCBpbiBtZXNzYWdlIGZvciBrZXl3b3JkIGluIHRva2VuX2tleXdvcmRzKQoKCmRlZiBfcHJvbXB0X3JlY292ZXJfaW52YWxpZF9oZl90b2tlbigpIC0+IHR1cGxlW3N0ciwgc3RyIHwgTm9uZV06CiAgICBpZiBub3Qgc3lzLnN0ZGluLmlzYXR0eSgpOgogICAgICAgIHJldHVybiAoIm5vLXRva2VuIiwgTm9uZSkKCiAgICB3aGlsZSBUcnVlOgogICAgICAgIHByaW50KAogICAgICAgICAgICAiWyFdIE8gdG9rZW4gZG8gSHVnZ2luZ0ZhY2UgcGFyZWNlIGludsOhbGlkby4gRXNjb2xoYTogIgogICAgICAgICAgICAiWzFdIGluZm9ybWFyIG5vdm8gdG9rZW4sIFsyXSBjb250aW51YXIgc2VtIHRva2VuLiIsCiAgICAgICAgICAgIGZpbGU9c3lzLnN0ZGVyciwKICAgICAgICApCiAgICAgICAgYW5zd2VyID0gaW5wdXQoIj4gRXNjb2xoYSBbMS8yXTogIikuc3RyaXAoKS5sb3dlcigpCiAgICAgICAgaWYgYW5zd2VyIGluIHsiMSIsICJub3ZvIiwgIm5ldyJ9OgogICAgICAgICAgICBuZXdfdG9rZW4gPSBnZXRwYXNzLmdldHBhc3MoIkNvbGUgbyBub3ZvIEhGX1RPS0VOOiAiKS5zdHJpcCgpCiAgICAgICAgICAgIGlmIG5ld190b2tlbjoKICAgICAgICAgICAgICAgIHJldHVybiAoIm5ldy10b2tlbiIsIG5ld190b2tlbikKICAgICAgICAgICAgcHJpbnQoIlshXSBUb2tlbiB2YXppby4gVGVudGUgbm92YW1lbnRlLiIsIGZpbGU9c3lzLnN0ZGVycikKICAgICAgICAgICAgY29udGludWUKICAgICAgICBpZiBhbnN3ZXIgaW4geyIyIiwgIiIsICJzZW0iLCAibm8ifToKICAgICAgICAgICAgcmV0dXJuICgibm8tdG9rZW4iLCBOb25lKQogICAgICAgIHByaW50KCJbIV0gT3DDp8OjbyBpbnbDoWxpZGEuIERpZ2l0ZSAxIG91IDIuIiwgZmlsZT1zeXMuc3RkZXJyKQoKCmRlZiBfZG93bmxvYWRfd2l0aF9oZl90b2tlbl9yZWNvdmVyeSgKICAgICosCiAgICByZXBvX2lkOiBzdHIsCiAgICBsb2NhbF9kaXI6IFBhdGgsCiAgICBoZl90b2tlbjogc3RyIHwgTm9uZSwKICAgIHNuYXBzaG90X2Rvd25sb2FkLAopIC0+IE5vbmU6CiAgICBhdHRlbXB0X3Rva2VuID0gaGZfdG9rZW4KCiAgICB3aGlsZSBUcnVlOgogICAgICAgIHRyeToKICAgICAgICAgICAgc25hcHNob3RfZG93bmxvYWQoCiAgICAgICAgICAgICAgICByZXBvX2lkPXJlcG9faWQsCiAgICAgICAgICAgICAgICBsb2NhbF9kaXI9c3RyKGxvY2FsX2RpciksCiAgICAgICAgICAgICAgICB0b2tlbj1hdHRlbXB0X3Rva2VuLAogICAgICAgICAgICApCiAgICAgICAgICAgIGlmIGF0dGVtcHRfdG9rZW46CiAgICAgICAgICAgICAgICBvcy5lbnZpcm9uWyJIRl9UT0tFTiJdID0gYXR0ZW1wdF90b2tlbgogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgb3MuZW52aXJvbi5wb3AoIkhGX1RPS0VOIiwgTm9uZSkKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBleGM6CiAgICAgICAgICAgIGlmIGF0dGVtcHRfdG9rZW4gYW5kIF9pc19pbnZhbGlkX2hmX3Rva2VuX2Vycm9yKGV4Yyk6CiAgICAgICAgICAgICAgICBwcmludCgKICAgICAgICAgICAgICAgICAgICAiWyFdIEZhbGhhIGRlIGF1dGVudGljYcOnw6NvIG5vIEh1Z2dpbmdGYWNlIGNvbSBvIHRva2VuIGF0dWFsLiAiCiAgICAgICAgICAgICAgICAgICAgIlZvY8OqIHBvZGUgaW5mb3JtYXIgb3V0cm8gdG9rZW4gb3Ugc2VndWlyIHNlbSB0b2tlbi4iLAogICAgICAgICAgICAgICAgICAgIGZpbGU9c3lzLnN0ZGVyciwKICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgIGFjdGlvbiwgcmVwbGFjZW1lbnQgPSBfcHJvbXB0X3JlY292ZXJfaW52YWxpZF9oZl90b2tlbigpCiAgICAgICAgICAgICAgICBpZiBhY3Rpb24gPT0gIm5ldy10b2tlbiIgYW5kIHJlcGxhY2VtZW50OgogICAgICAgICAgICAgICAgICAgIGF0dGVtcHRfdG9rZW4gPSByZXBsYWNlbWVudAogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlCiAgICAgICAgICAgICAgICBhdHRlbXB0X3Rva2VuID0gTm9uZQogICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgcmFpc2UKCgpkZWYgZG93bmxvYWRfbW9kZWxfd2l0aF9mYWxsYmFjaygKICAgIHByZWZlcnJlZF9tb2RlbF9pZDogc3RyLAogICAgZmFsbGJhY2tfbW9kZWxfaWQ6IHN0ciwKICAgIGxvY2FsX2RpcjogUGF0aCwKICAgIHN0cmF0ZWdpZXM6IGxpc3RbTW9kZWxEb3dubG9hZFN0cmF0ZWd5XSB8IE5vbmUgPSBOb25lLAopIC0+IERvd25sb2FkU2VsZWN0aW9uOgogICAgIiIiCiAgICBUZW50YSBiYWl4YXIgYHByZWZlcnJlZF9tb2RlbF9pZGA7IHNlIGZhbGhhciBlbSB0b2RvcyBvcyBwcm92ZWRvcmVzLAogICAgdGVudGEgYGZhbGxiYWNrX21vZGVsX2lkYC4KICAgICIiIgogICAgYmFzZV9kaXIgPSBsb2NhbF9kaXIuZXhwYW5kdXNlcigpCiAgICBiYXNlX2Rpci5ta2RpcihwYXJlbnRzPVRydWUsIGV4aXN0X29rPVRydWUpCiAgICBwcm92aWRlcnMgPSBzdHJhdGVnaWVzIG9yIGJ1aWxkX2RlZmF1bHRfc3RyYXRlZ2llcygpCiAgICBlcnJvcnM6IGxpc3Rbc3RyXSA9IFtdCgogICAgZm9yIG1vZGVsX2lkIGluIChwcmVmZXJyZWRfbW9kZWxfaWQsIGZhbGxiYWNrX21vZGVsX2lkKToKICAgICAgICBtb2RlbF9sb2NhbF9kaXIgPSBfbW9kZWxfY2FjaGVfZGlyKGJhc2VfZGlyLCBtb2RlbF9pZCkKICAgICAgICBpZiBfY2FjaGVfcmVhZHkobW9kZWxfbG9jYWxfZGlyKToKICAgICAgICAgICAgcmV0dXJuIERvd25sb2FkU2VsZWN0aW9uKAogICAgICAgICAgICAgICAgbW9kZWxfaWQ9bW9kZWxfaWQsCiAgICAgICAgICAgICAgICBwcm92aWRlcj0ibG9jYWwtY2FjaGUiLAogICAgICAgICAgICAgICAgbG9jYWxfZGlyPW1vZGVsX2xvY2FsX2RpciwKICAgICAgICAgICAgKQoKICAgICAgICBmb3Igc3RyYXRlZ3kgaW4gcHJvdmlkZXJzOgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICBwcmludCgKICAgICAgICAgICAgICAgICAgICBmIlsrXSBJbmljaWFuZG8gZG93bmxvYWQgZG8gbW9kZWxvICd7bW9kZWxfaWR9JyB2aWEge3N0cmF0ZWd5Lm5hbWV9IGVtOiB7bW9kZWxfbG9jYWxfZGlyfSIsCiAgICAgICAgICAgICAgICAgICAgZmlsZT1zeXMuc3RkZXJyLAogICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgX3ByZXBhcmVfZGVzdGluYXRpb24obW9kZWxfbG9jYWxfZGlyLCBjbGVhbj1UcnVlKQogICAgICAgICAgICAgICAgc3RyYXRlZ3kuZG93bmxvYWQobW9kZWxfaWQ9bW9kZWxfaWQsIGxvY2FsX2Rpcj1tb2RlbF9sb2NhbF9kaXIpCiAgICAgICAgICAgICAgICBfbWFya19jYWNoZV9yZWFkeShtb2RlbF9sb2NhbF9kaXIpCiAgICAgICAgICAgICAgICByZXR1cm4gRG93bmxvYWRTZWxlY3Rpb24oCiAgICAgICAgICAgICAgICAgICAgbW9kZWxfaWQ9bW9kZWxfaWQsCiAgICAgICAgICAgICAgICAgICAgcHJvdmlkZXI9c3RyYXRlZ3kubmFtZSwKICAgICAgICAgICAgICAgICAgICBsb2NhbF9kaXI9bW9kZWxfbG9jYWxfZGlyLAogICAgICAgICAgICAgICAgKQogICAgICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGV4YzoKICAgICAgICAgICAgICAgIGVycm9ycy5hcHBlbmQoZiJ7c3RyYXRlZ3kubmFtZX06e21vZGVsX2lkfToge2V4Y30iKQoKICAgIHJhaXNlIFJ1bnRpbWVFcnJvcigKICAgICAgICAiRmFsaGEgbm8gZG93bmxvYWQgZG9zIG1vZGVsb3MgZW0gdG9kb3Mgb3MgcHJvdmVkb3JlcyBjb25maWd1cmFkb3MuICIKICAgICAgICArICIgfCAiLmpvaW4oZXJyb3JzKQogICAgKQo="
|
|
566
730
|
B64_MODEL_DL_MS="IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwpmcm9tIF9fZnV0dXJlX18gaW1wb3J0IGFubm90YXRpb25zCgoiIiIKUHJvdmlkZXIgb3BjaW9uYWwgZGUgZG93bmxvYWQgdmlhIE1vZGVsU2NvcGUuClVzYWRvIGFwZW5hcyBzZSBvIHBhY290ZSBgbW9kZWxzY29wZWAgZXN0aXZlciBpbnN0YWxhZG8uCiIiIgoKZnJvbSBwYXRobGliIGltcG9ydCBQYXRoCgoKY2xhc3MgTW9kZWxTY29wZURvd25sb2FkU3RyYXRlZ3k6CiAgICBuYW1lID0gIm1vZGVsc2NvcGUiCgogICAgZGVmIGRvd25sb2FkKHNlbGYsIG1vZGVsX2lkOiBzdHIsIGxvY2FsX2RpcjogUGF0aCkgLT4gTm9uZToKICAgICAgICB0cnk6CiAgICAgICAgICAgIGZyb20gbW9kZWxzY29wZS5odWIuc25hcHNob3RfZG93bmxvYWQgaW1wb3J0IHNuYXBzaG90X2Rvd25sb2FkCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBleGM6CiAgICAgICAgICAgIHJhaXNlIFJ1bnRpbWVFcnJvcigKICAgICAgICAgICAgICAgICJQYWNvdGUgYG1vZGVsc2NvcGVgIGluZGlzcG9uw612ZWwgcGFyYSBwcm92aWRlciBhbHRlcm5hdGl2byIKICAgICAgICAgICAgKSBmcm9tIGV4YwoKICAgICAgICBzbmFwc2hvdF9kb3dubG9hZCgKICAgICAgICAgICAgbW9kZWxfaWQ9bW9kZWxfaWQsCiAgICAgICAgICAgIGxvY2FsX2Rpcj1zdHIobG9jYWxfZGlyKSwKICAgICAgICApCg=="
|
|
567
731
|
|
|
@@ -597,33 +761,72 @@ if ! python3 -m venv --help >/dev/null 2>&1; then
|
|
|
597
761
|
exit 1
|
|
598
762
|
fi
|
|
599
763
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
764
|
+
ensure_own_rag_cli_config
|
|
765
|
+
if CHROMA_CONFIG_RAW="$(load_own_rag_cli_chroma)"; then
|
|
766
|
+
IFS='|' read -r CHROMA_SCHEME CHROMA_HOST CHROMA_PORT <<< "${CHROMA_CONFIG_RAW}"
|
|
603
767
|
fi
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
768
|
+
|
|
769
|
+
if CHROMA_SCHEME_NORMALIZED="$(normalize_scheme "${ENV_CHROMA_SCHEME_RAW}")"; then
|
|
770
|
+
CHROMA_SCHEME="${CHROMA_SCHEME_NORMALIZED}"
|
|
607
771
|
fi
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
772
|
+
|
|
773
|
+
if [[ -n "${ENV_CHROMA_HOST_RAW}" ]]; then
|
|
774
|
+
CHROMA_HOST="$(echo "${ENV_CHROMA_HOST_RAW}" | xargs)"
|
|
775
|
+
fi
|
|
776
|
+
if [[ -z "${CHROMA_HOST}" ]]; then
|
|
777
|
+
CHROMA_HOST="${CHROMA_HOST_DEFAULT}"
|
|
611
778
|
fi
|
|
612
|
-
DOCKER_COMPOSE_CMD="docker compose"
|
|
613
779
|
|
|
614
|
-
if
|
|
615
|
-
|
|
616
|
-
|
|
780
|
+
if CHROMA_PORT_NORMALIZED="$(normalize_port "${ENV_CHROMA_PORT_RAW}")"; then
|
|
781
|
+
CHROMA_PORT="${CHROMA_PORT_NORMALIZED}"
|
|
782
|
+
CHROMA_PORT_FROM_ENV=true
|
|
783
|
+
fi
|
|
784
|
+
|
|
785
|
+
if is_local_chroma_host "${CHROMA_HOST}"; then
|
|
786
|
+
CHROMA_IS_LOCAL=true
|
|
787
|
+
if [[ "${CHROMA_SCHEME}" != "http" ]]; then
|
|
788
|
+
log_warn "ChromaDB local usa HTTP. Ajustando scheme para http."
|
|
789
|
+
CHROMA_SCHEME="http"
|
|
790
|
+
fi
|
|
617
791
|
else
|
|
618
|
-
|
|
792
|
+
CHROMA_IS_LOCAL=false
|
|
619
793
|
fi
|
|
620
794
|
|
|
621
|
-
|
|
795
|
+
if [[ "${CHROMA_IS_LOCAL}" == "true" ]]; then
|
|
796
|
+
if ! command -v docker >/dev/null 2>&1; then
|
|
797
|
+
log_error "$(t docker_missing)"
|
|
798
|
+
exit 1
|
|
799
|
+
fi
|
|
800
|
+
if ! docker info >/dev/null 2>&1; then
|
|
801
|
+
log_error "$(t docker_daemon)"
|
|
802
|
+
exit 1
|
|
803
|
+
fi
|
|
804
|
+
if ! docker compose version >/dev/null 2>&1; then
|
|
805
|
+
log_error "$(t compose_missing)"
|
|
806
|
+
exit 1
|
|
807
|
+
fi
|
|
808
|
+
DOCKER_COMPOSE_CMD="docker compose"
|
|
809
|
+
|
|
810
|
+
if ! command -v curl >/dev/null 2>&1; then
|
|
811
|
+
log_warn "$(t no_curl)"
|
|
812
|
+
HAS_CURL=false
|
|
813
|
+
else
|
|
814
|
+
HAS_CURL=true
|
|
815
|
+
fi
|
|
622
816
|
|
|
623
|
-
if EXISTING_CHROMA_PORT="$(extract_chroma_port_from_compose "${DOCKER_COMPOSE_FILE_PATH}")"; then
|
|
624
|
-
|
|
817
|
+
if EXISTING_CHROMA_PORT="$(extract_chroma_port_from_compose "${DOCKER_COMPOSE_FILE_PATH}")"; then
|
|
818
|
+
if [[ "${CHROMA_PORT_FROM_ENV}" != "true" ]]; then
|
|
819
|
+
CHROMA_PORT="${EXISTING_CHROMA_PORT}"
|
|
820
|
+
fi
|
|
821
|
+
fi
|
|
822
|
+
else
|
|
823
|
+
DOCKER_COMPOSE_CMD=""
|
|
824
|
+
HAS_CURL=false
|
|
825
|
+
log_info "ChromaDB remoto configurado: ${CHROMA_SCHEME}://${CHROMA_HOST}:${CHROMA_PORT} (Docker local será ignorado)."
|
|
625
826
|
fi
|
|
626
827
|
|
|
828
|
+
log_info "$(t prereq_ok)"
|
|
829
|
+
|
|
627
830
|
reset_rag_environment() {
|
|
628
831
|
log_info "$(t reset_start)"
|
|
629
832
|
rm -rf "${VENV_DIR}" "${RAG_DB_DIR}" "${DOCKER_COMPOSE_DIR}" "${MODEL_CACHE_DIR}"
|
|
@@ -692,6 +895,8 @@ run_indexer_with_diagnostics() {
|
|
|
692
895
|
set +e
|
|
693
896
|
TOKENIZERS_PARALLELISM="${tokenizers_parallelism}" \
|
|
694
897
|
MCP_FORCE_MODEL_RECONFIG="${force_model_reconfig}" \
|
|
898
|
+
MCP_CHROMA_SCHEME="${CHROMA_SCHEME}" \
|
|
899
|
+
MCP_CHROMA_HOST="${CHROMA_HOST}" \
|
|
695
900
|
MCP_CHROMA_PORT="${CHROMA_PORT}" \
|
|
696
901
|
"${VENV_PYTHON}" "${EXTRACT_DIR}/indexer_full.py" "${target_project_dir}"
|
|
697
902
|
indexer_status=$?
|
|
@@ -760,47 +965,57 @@ fi
|
|
|
760
965
|
# ---------------------------------------------------------------------------
|
|
761
966
|
log_info "$(t section_chroma)"
|
|
762
967
|
|
|
763
|
-
|
|
968
|
+
if [[ "${CHROMA_IS_LOCAL}" == "true" ]]; then
|
|
969
|
+
mkdir -p "${RAG_DB_DIR}" "${DOCKER_COMPOSE_DIR}"
|
|
764
970
|
|
|
765
|
-
if [[ "$REINSTALL" == "true" ]] || [[ ! -f "${DOCKER_COMPOSE_FILE_PATH}" ]]; then
|
|
766
|
-
|
|
767
|
-
|
|
971
|
+
if [[ "$REINSTALL" == "true" ]] || [[ ! -f "${DOCKER_COMPOSE_FILE_PATH}" ]]; then
|
|
972
|
+
if [[ "${CHROMA_PORT_FROM_ENV}" == "true" ]]; then
|
|
973
|
+
CHROMA_PORT="$(choose_chroma_port_for_install "${CHROMA_PORT_DEFAULT}" "${CHROMA_PORT}")"
|
|
974
|
+
else
|
|
975
|
+
CHROMA_PORT="$(choose_chroma_port_for_install "${CHROMA_PORT_DEFAULT}" "${CHROMA_PORT}")"
|
|
976
|
+
fi
|
|
977
|
+
cp "${EXTRACT_DIR}/docker-compose.yml" "${DOCKER_COMPOSE_FILE_PATH}"
|
|
978
|
+
sed -i '' -E 's/"[0-9]{1,5}:8000"/"'"${CHROMA_PORT}"':8000"/g' "${DOCKER_COMPOSE_FILE_PATH}"
|
|
979
|
+
sed -i '' -E 's|http://localhost:[0-9]{1,5}/api/v1/heartbeat|http://localhost:'"${CHROMA_PORT}"'/api/v1/heartbeat|g' "${DOCKER_COMPOSE_FILE_PATH}"
|
|
980
|
+
log_info "$(t compose_installed) ${DOCKER_COMPOSE_DIR}"
|
|
981
|
+
log_info "$(t chroma_port_selected) ${CHROMA_PORT}"
|
|
768
982
|
else
|
|
769
|
-
|
|
983
|
+
log_info "$(t compose_keep)"
|
|
984
|
+
if EXISTING_CHROMA_PORT="$(extract_chroma_port_from_compose "${DOCKER_COMPOSE_FILE_PATH}")"; then
|
|
985
|
+
CHROMA_PORT="${EXISTING_CHROMA_PORT}"
|
|
986
|
+
fi
|
|
987
|
+
log_info "$(t chroma_port_selected) ${CHROMA_PORT}"
|
|
770
988
|
fi
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
989
|
+
|
|
990
|
+
if docker ps --format '{{.Names}}' | grep -q '^chromadb-rag$'; then
|
|
991
|
+
log_info "$(t chroma_running)"
|
|
992
|
+
else
|
|
993
|
+
log_info "$(t chroma_start)"
|
|
994
|
+
(cd "${DOCKER_COMPOSE_DIR}" && $DOCKER_COMPOSE_CMD up -d)
|
|
995
|
+
|
|
996
|
+
log_info "$(t chroma_wait)"
|
|
997
|
+
WAITED=0
|
|
998
|
+
while true; do
|
|
999
|
+
if [[ "$HAS_CURL" == "true" ]] && curl -sf "http://${CHROMA_HOST}:${CHROMA_PORT}/api/v1/heartbeat" >/dev/null 2>&1; then
|
|
1000
|
+
log_info "$(t chroma_ready) http://${CHROMA_HOST}:${CHROMA_PORT}"
|
|
1001
|
+
break
|
|
1002
|
+
fi
|
|
1003
|
+
if [[ $WAITED -ge 40 ]]; then
|
|
1004
|
+
log_warn "$(t chroma_timeout)"
|
|
1005
|
+
break
|
|
1006
|
+
fi
|
|
1007
|
+
sleep 2
|
|
1008
|
+
WAITED=$((WAITED+2))
|
|
1009
|
+
done
|
|
780
1010
|
fi
|
|
781
|
-
|
|
1011
|
+
else
|
|
1012
|
+
log_info "Usando endpoint remoto do ChromaDB: ${CHROMA_SCHEME}://${CHROMA_HOST}:${CHROMA_PORT}"
|
|
782
1013
|
fi
|
|
783
1014
|
|
|
784
|
-
if
|
|
785
|
-
log_info "$
|
|
1015
|
+
if save_own_rag_cli_chroma "${CHROMA_SCHEME}" "${CHROMA_HOST}" "${CHROMA_PORT}"; then
|
|
1016
|
+
log_info "Config Chroma salva em: ${OWN_RAG_CONFIG_FILE}"
|
|
786
1017
|
else
|
|
787
|
-
|
|
788
|
-
(cd "${DOCKER_COMPOSE_DIR}" && $DOCKER_COMPOSE_CMD up -d)
|
|
789
|
-
|
|
790
|
-
log_info "$(t chroma_wait)"
|
|
791
|
-
WAITED=0
|
|
792
|
-
while true; do
|
|
793
|
-
if [[ "$HAS_CURL" == "true" ]] && curl -sf "http://${CHROMA_HOST}:${CHROMA_PORT}/api/v1/heartbeat" >/dev/null 2>&1; then
|
|
794
|
-
log_info "$(t chroma_ready) http://${CHROMA_HOST}:${CHROMA_PORT}"
|
|
795
|
-
break
|
|
796
|
-
fi
|
|
797
|
-
if [[ $WAITED -ge 40 ]]; then
|
|
798
|
-
log_warn "$(t chroma_timeout)"
|
|
799
|
-
break
|
|
800
|
-
fi
|
|
801
|
-
sleep 2
|
|
802
|
-
WAITED=$((WAITED+2))
|
|
803
|
-
done
|
|
1018
|
+
log_warn "Não foi possível salvar configuração em ${OWN_RAG_CONFIG_FILE}"
|
|
804
1019
|
fi
|
|
805
1020
|
|
|
806
1021
|
# ---------------------------------------------------------------------------
|
|
@@ -812,9 +1027,10 @@ mkdir -p "${BIN_DIR}"
|
|
|
812
1027
|
|
|
813
1028
|
NEEDS_INSTALL=true
|
|
814
1029
|
MCP_WAS_OUTDATED=false
|
|
1030
|
+
MCP_IS_CURRENT=false
|
|
815
1031
|
if [[ -f "${MCP_SERVER_DEST}" ]]; then
|
|
816
1032
|
if cmp -s <(tail -n +2 "${MCP_SERVER_DEST}") <(tail -n +2 "${EXTRACT_DIR}/mcp_server.py"); then
|
|
817
|
-
|
|
1033
|
+
MCP_IS_CURRENT=true
|
|
818
1034
|
else
|
|
819
1035
|
MCP_WAS_OUTDATED=true
|
|
820
1036
|
log_warn "$(t mcp_outdated)"
|
|
@@ -835,11 +1051,16 @@ if [[ -f "${MCP_SERVER_DEST}" ]]; then
|
|
|
835
1051
|
NEEDS_INSTALL=true
|
|
836
1052
|
else
|
|
837
1053
|
NEEDS_INSTALL=false
|
|
838
|
-
log_info "$(t
|
|
1054
|
+
log_info "$(t mcp_keep)"
|
|
839
1055
|
fi
|
|
840
1056
|
fi
|
|
841
1057
|
else
|
|
842
1058
|
NEEDS_INSTALL=false
|
|
1059
|
+
if [[ "${MCP_WAS_OUTDATED}" == "true" ]]; then
|
|
1060
|
+
log_info "$(t mcp_skip)"
|
|
1061
|
+
elif [[ "${MCP_IS_CURRENT}" == "true" ]]; then
|
|
1062
|
+
log_info "$(t mcp_keep)"
|
|
1063
|
+
fi
|
|
843
1064
|
fi
|
|
844
1065
|
fi
|
|
845
1066
|
|
|
@@ -911,7 +1132,7 @@ else
|
|
|
911
1132
|
CFG_PATH="${TARGET_CONFIGS[$i]}"
|
|
912
1133
|
CFG_LABEL="${TARGET_LABELS[$i]}"
|
|
913
1134
|
CHECK_RESULT=$(
|
|
914
|
-
python3 - "${CFG_PATH}" "${MCP_SERVER_DEST}" "${MCP_VERSION}" "${
|
|
1135
|
+
python3 - "${CFG_PATH}" "${MCP_SERVER_DEST}" "${MCP_VERSION}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
|
|
915
1136
|
import json
|
|
916
1137
|
import sys
|
|
917
1138
|
from pathlib import Path
|
|
@@ -919,7 +1140,7 @@ from pathlib import Path
|
|
|
919
1140
|
cfg_path = Path(sys.argv[1]).expanduser()
|
|
920
1141
|
mcp_server_command = sys.argv[2]
|
|
921
1142
|
mcp_version = sys.argv[3]
|
|
922
|
-
|
|
1143
|
+
own_rag_cli_config_file = sys.argv[4]
|
|
923
1144
|
|
|
924
1145
|
try:
|
|
925
1146
|
data = json.loads(cfg_path.read_text(encoding="utf-8"))
|
|
@@ -942,8 +1163,7 @@ desired = {
|
|
|
942
1163
|
"command": mcp_server_command,
|
|
943
1164
|
"args": [],
|
|
944
1165
|
"env": {
|
|
945
|
-
"
|
|
946
|
-
"CHROMA_PORT": chroma_port,
|
|
1166
|
+
"OWN_RAG_CLI_CONFIG_FILE": own_rag_cli_config_file,
|
|
947
1167
|
"TOKENIZERS_PARALLELISM": "false",
|
|
948
1168
|
},
|
|
949
1169
|
"version": mcp_version,
|
|
@@ -997,7 +1217,7 @@ PYEOF
|
|
|
997
1217
|
CFG_LABEL="${PENDING_LABELS[$i]}"
|
|
998
1218
|
|
|
999
1219
|
if ! RESULT=$(
|
|
1000
|
-
python3 - "${CFG_PATH}" "${MCP_SERVER_DEST}" "${MCP_VERSION}" "${
|
|
1220
|
+
python3 - "${CFG_PATH}" "${MCP_SERVER_DEST}" "${MCP_VERSION}" "${OWN_RAG_CONFIG_FILE}" <<'PYEOF'
|
|
1001
1221
|
import json
|
|
1002
1222
|
import sys
|
|
1003
1223
|
from pathlib import Path
|
|
@@ -1005,7 +1225,7 @@ from pathlib import Path
|
|
|
1005
1225
|
cfg_path = Path(sys.argv[1]).expanduser()
|
|
1006
1226
|
mcp_server_command = sys.argv[2]
|
|
1007
1227
|
mcp_version = sys.argv[3]
|
|
1008
|
-
|
|
1228
|
+
own_rag_cli_config_file = sys.argv[4]
|
|
1009
1229
|
|
|
1010
1230
|
try:
|
|
1011
1231
|
data = json.loads(cfg_path.read_text(encoding="utf-8"))
|
|
@@ -1028,8 +1248,7 @@ desired = {
|
|
|
1028
1248
|
"command": mcp_server_command,
|
|
1029
1249
|
"args": [],
|
|
1030
1250
|
"env": {
|
|
1031
|
-
"
|
|
1032
|
-
"CHROMA_PORT": chroma_port,
|
|
1251
|
+
"OWN_RAG_CLI_CONFIG_FILE": own_rag_cli_config_file,
|
|
1033
1252
|
"TOKENIZERS_PARALLELISM": "false",
|
|
1034
1253
|
},
|
|
1035
1254
|
"version": mcp_version,
|
|
@@ -1120,9 +1339,14 @@ echo -e "${BOLD}${GREEN} $(t setup_done)${NC}"
|
|
|
1120
1339
|
echo -e "${BOLD}${GREEN}================================================================${NC}"
|
|
1121
1340
|
echo ""
|
|
1122
1341
|
echo -e " ${GREEN}Venv Python${NC} : ${VENV_DIR}"
|
|
1123
|
-
|
|
1342
|
+
if [[ "${CHROMA_IS_LOCAL}" == "true" ]]; then
|
|
1343
|
+
echo -e " ${GREEN}ChromaDB${NC} : ${CHROMA_SCHEME}://${CHROMA_HOST}:${CHROMA_PORT} (Docker Desktop)"
|
|
1344
|
+
else
|
|
1345
|
+
echo -e " ${GREEN}ChromaDB${NC} : ${CHROMA_SCHEME}://${CHROMA_HOST}:${CHROMA_PORT} (remote)"
|
|
1346
|
+
fi
|
|
1124
1347
|
echo -e " ${GREEN}Dados${NC} : ${RAG_DB_DIR}"
|
|
1125
1348
|
echo -e " ${GREEN}MCP Server${NC} : ${MCP_SERVER_DEST}"
|
|
1349
|
+
echo -e " ${GREEN}Config${NC} : ${OWN_RAG_CONFIG_FILE}"
|
|
1126
1350
|
echo -e " ${GREEN}Projeto${NC} : ${PROJECT_DIR}"
|
|
1127
1351
|
echo ""
|
|
1128
1352
|
echo -e " $(t restart_tools)"
|