summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKali Kaneko <kali@leap.se>2018-02-27 01:52:59 +0100
committerKali Kaneko <kali@leap.se>2018-03-02 03:54:14 +0100
commit031a2044a77153b6c2a3e111de17827c8395ea1e (patch)
tree3c013eb9d03366630aa04fe98cee78ae90ba79b0
parentc9fbec21b700c25d35a03b12df1adbb65f67ff12 (diff)
[pkg] install helpers from snap
-rw-r--r--Makefile2
-rw-r--r--pkg/riseupvpn/Makefile5
-rw-r--r--pkg/riseupvpn/TODO5
-rwxr-xr-xpkg/riseupvpn/pack_installers35
-rw-r--r--pkg/riseupvpn/snap/gui/riseup-vpn.desktop14
-rw-r--r--pkg/riseupvpn/snap/gui/riseupvpn.svg80
-rwxr-xr-xpkg/riseupvpn/snap/hooks/install648
-rwxr-xr-xpkg/riseupvpn/snap/hooks/remove7
-rw-r--r--pkg/riseupvpn/snap/snapcraft.yaml16
9 files changed, 803 insertions, 9 deletions
diff --git a/Makefile b/Makefile
index ed8848b1..1132732f 100644
--- a/Makefile
+++ b/Makefile
@@ -73,7 +73,7 @@ test_functional_graphical_wip:
install_helpers:
# if there's no sudo, assumming this is running as root by the CI
test -f $(SUDO) && sudo cp $(BITMASK_ROOT) /usr/local/sbin/ || cp $(BITMASK_ROOT) /usr/local/sbin/
- test -f $(SUDO) && sudo cp $(POLKIT_POLICY) /usr/share/polkit-1/actions/se.bitmask.bundle.policy || cp $(POLKIT_POLICY) /usr/share/polkit-1/actions/se.bitmask.bundle.policy
+ test -f $(SUDO) && sudo cp $(POLKIT_POLICY) /usr/share/polkit-1/actions/se.leap.bitmask.bundle.policy || cp $(POLKIT_POLICY) /usr/share/polkit-1/actions/se.leap.bitmask.bundle.policy
install_pixelated:
pip install leap.pixelated leap.pixelated-www
diff --git a/pkg/riseupvpn/Makefile b/pkg/riseupvpn/Makefile
index 47985e28..ab2b7793 100644
--- a/pkg/riseupvpn/Makefile
+++ b/pkg/riseupvpn/Makefile
@@ -1,4 +1,5 @@
-build:
+build: installers
+ # for speeding up build, see https://tribaal.io/making-lxd-fly-on-ubuntu-as-well.html
sudo snapcraft cleanbuild
install:
sudo snap install riseup-vpn_*.snap --dangerous --classic
@@ -6,3 +7,5 @@ uninstall:
sudo snap remove riseup-vpn
init-lxd:
sudo lxd init
+installers:
+ ./pack_installers
diff --git a/pkg/riseupvpn/TODO b/pkg/riseupvpn/TODO
index 2288e7e4..ac310d66 100644
--- a/pkg/riseupvpn/TODO
+++ b/pkg/riseupvpn/TODO
@@ -1,4 +1,5 @@
-[ ] copy libzmq.so.5 library to the binary path (HACK, ask in forums).
[ ] install polkit helpers
[ ] install bitmask root in its place (can classic confinement install something in the global path? does this produce conflicts with proper debs?)
-[ ] add a desktop file entry
+[x] add icon
+[x] add a desktop file entry
+[x] copy libzmq.so.5 library to the binary path (HACK, ask in forums).
diff --git a/pkg/riseupvpn/pack_installers b/pkg/riseupvpn/pack_installers
new file mode 100755
index 00000000..693a9543
--- /dev/null
+++ b/pkg/riseupvpn/pack_installers
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+import os
+import subprocess
+from base64 import encodestring as encode
+HELPDIR = '../../src/leap/bitmask/vpn/helpers/linux/'
+INSTALL = './snap/hooks/install'
+
+with open(os.path.join(HELPDIR, 'bitmask-root')) as bmroot:
+ b64_bmroot = encode(bmroot.read())
+
+with open(os.path.join(HELPDIR, 'se.leap.bitmask.bundle.policy')) as polkit:
+ b64_polkit = encode(polkit.read())
+
+with open(INSTALL, 'w') as install:
+ install.write('#!/usr/bin/env python\n')
+ install.write('# This helper installs bitmask-root and polkit policy file\n')
+ install.write('import subprocess\n')
+ install.write('from base64 import decodestring as decode\n')
+ install.write("""
+BMROOT = \"\"\"{bmroot}\"\"\"
+POLKIT = \"\"\"{polkit}\"\"\"
+BMROOT_DEST = "/usr/local/sbin/bitmask-root"
+with open(BMROOT_DEST, "w") as bmroot:
+ lines = str(decode(BMROOT)).split("\\n")
+ for line in lines:
+ bmroot.write(line + "\\n")
+with open('/usr/share/polkit-1/actions/se.leap.bitmask.bundle.policy', 'w') as polkit:
+ lines = str(decode(POLKIT)).split("\\n")
+ for line in lines:
+ polkit.write(line + "\\n")
+""".format(bmroot=b64_bmroot, polkit=b64_polkit))
+ install.write('subprocess.Popen(["chmod", "+x", BMROOT_DEST])\n')
+
+subprocess.Popen(["chmod", "+x", INSTALL])
+print("done packing installers")
diff --git a/pkg/riseupvpn/snap/gui/riseup-vpn.desktop b/pkg/riseupvpn/snap/gui/riseup-vpn.desktop
new file mode 100644
index 00000000..1d586e74
--- /dev/null
+++ b/pkg/riseupvpn/snap/gui/riseup-vpn.desktop
@@ -0,0 +1,14 @@
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=RiseupVPN
+Comment=Anonymous VPN
+Comment[es]=VPN Anonima
+Comment[de]=Secure Communication
+Exec=/snap/bin/riseup-vpn.launcher
+Terminal=false
+Icon=riseup-vpn
+Categories=Network;Application;
+StartupNotify=true
+Keywords=VPN;riseup;leap
+
diff --git a/pkg/riseupvpn/snap/gui/riseupvpn.svg b/pkg/riseupvpn/snap/gui/riseupvpn.svg
new file mode 100644
index 00000000..a19c6c61
--- /dev/null
+++ b/pkg/riseupvpn/snap/gui/riseupvpn.svg
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="128"
+ height="128"
+ viewBox="0 0 33.866666 33.866668"
+ version="1.1"
+ id="svg896"
+ inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
+ sodipodi:docname="riseupvpn-launcher.svg">
+ <defs
+ id="defs890" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#d7d7d7"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="5.12"
+ inkscape:cx="26.899914"
+ inkscape:cy="56.22909"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ units="px"
+ inkscape:window-width="1869"
+ inkscape:window-height="1025"
+ inkscape:window-x="51"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1">
+ <inkscape:grid
+ type="xygrid"
+ id="grid1471"
+ empspacing="4" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata893">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-263.13332)">
+ <path
+ style="fill:#006cb2;fill-opacity:1;stroke-width:0.26458335"
+ d="M 15.617988,295.66418 C 9.9401302,292.50672 5.6959906,287.52131 4.7342129,282.87951 4.4622971,281.56718 4.4516145,281.24899 4.4519256,274.47112 l 2.394e-4,-6.47461 0.5616386,-0.36177 c 2.3734615,-1.52883 4.8841786,-2.55103 7.4419094,-3.06699 5.221864,-1.05337 10.639669,0.003 15.485448,3.16684 l 0.398232,0.25998 v 6.50684 c 0,6.8044 -0.01093,7.13134 -0.280843,8.43104 -0.956329,4.6043 -4.632206,9.09553 -10.057782,12.28874 -1.576255,0.9277 -1.527525,0.91863 -2.382844,0.44299 z"
+ id="path5137"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csccssscssscc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#007cc3;fill-opacity:1;stroke-width:0.26458335"
+ d="m 16.396917,264.17336 c -1.317958,-4.7e-4 -2.635612,0.13103 -3.941076,0.39437 -2.5577318,0.51596 -5.068528,1.53812 -7.4419895,3.06696 l -0.5615828,0.36177 -4.707e-4,6.47466 c -2.394e-4,6.77787 0.010371,7.096 0.2822554,8.40832 0.9617776,4.64181 5.2059168,9.62724 10.8837756,12.7847 h 1.19e-4 c 0.368953,0.20517 0.569745,0.32326 0.805249,0.31706 v -31.80747 c -0.0088,-2e-5 -0.01755,-4.8e-4 -0.02641,-4.8e-4 z"
+ id="path887" />
+ <path
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458338"
+ d="m 16.989143,272.54844 c 0,0 -0.315707,-0.61165 -0.336761,-0.69601 -0.02106,-0.0844 -0.189431,-0.94909 -0.189431,-0.94909 l 0.210485,-0.37963 0.463046,-0.696 0.673531,-0.52727 0.168377,-0.0633 1.620684,-0.61164 0.147331,-0.14764 -0.168385,-0.25308 -0.231523,-0.12655 -0.424879,-0.10907 -1.064407,-0.10907 -0.825967,0.007 -0.568293,0.12654 -0.505146,-0.18981 -0.63143,-0.0844 -0.9261,-0.0211 -0.463054,-0.0211 -0.778761,0.29527 -1.178677,1.37091 -0.147339,0.52727 -0.08418,0.464 -0.399908,0.86473 -0.252577,0.82254 -0.126285,0.88582 v 0.18982 l -0.610384,0.92799 -0.336761,0.69601 v 0.99126 l 0.10523,2.04581 0.189431,0.73821 0.378861,0.6749 0.4841,0.44292 0.210477,0.8647 0.799815,1.77155 0.947154,1.13886 0.06311,0.0633 0.336761,1.70835 -1.157623,2.10911 -0.363408,0.28169 -0.272426,0.22054 -0.467179,-0.0129 -0.260603,0.13452 -0.316122,0.0134 -0.190994,0.19047 -0.408963,-0.0616 -0.4044091,-0.0196 -0.311982,0.24606 -0.044916,0.36556 0.207365,-0.23472 0.3488649,-0.10158 0.03654,0.33552 0.5512672,-0.18726 0.316122,-0.0134 0.557721,0.0667 c 0,0 0.483518,-0.0316 0.567216,-0.0407 0.0837,-0.009 0.597276,0.0411 0.597276,0.0411 l 0.376644,-0.041 0.199723,0.0844 0.267456,-0.0716 0.290265,0.13818 0.418488,-0.0455 0.05401,-0.28169 -0.01596,-0.14678 0.28571,0.0962 0.232049,0.18692 0.150642,0.21701 -0.0088,-0.27495 -0.182953,-0.31946 c 0,0 -0.125159,-0.17737 -0.208857,-0.16824 -0.0837,0.009 -0.408971,-0.0616 -0.408971,-0.0616 l -0.223321,0.088 -0.243857,-0.10085 -0.239677,0.13226 -0.220665,-0.0822 -0.106491,-0.20049 -0.153322,-0.0471 0.164763,-0.42962 0.378861,-0.52859 0.505146,-0.84364 0.442,-0.5273 0.168385,-0.21088 c 0,0 0.210477,-0.31633 0.210477,-0.40071 0,-0.0844 0.04212,-0.97016 0.04212,-0.97016 l -0.273623,-0.56947 -0.126285,-0.46402 2.441546,0.59059 h 0.147331 l 2.083731,1.49744 0.294669,0.37959 0.10523,1.49729 -0.04212,0.33746 -0.147338,0.27419 -0.105358,0.16875 -0.09101,0.23675 -0.06215,0.1583 -0.386712,0.11988 -0.393086,-0.0709 -0.238209,-0.0294 -0.437428,0.0633 -0.184118,0.19713 -0.07084,0.24475 0.05712,0.24744 0.09172,-0.24769 0.124641,-0.16724 0.121984,-0.0388 0.0094,0.21174 0.163957,0.10406 0.338995,-0.15563 0.166646,-0.0242 0.05409,0.22658 0.508999,-0.01 0.345035,-0.11394 0.282886,0.0443 0.410893,0.047 0.142823,-0.0417 0.112881,-0.10156 0.182442,0.37841 0.0024,-0.42654 -0.176722,-0.48581 -0.256358,-0.15463 0.04324,-0.12712 -0.189423,-0.35849 0.02106,-1.37079 1.052392,1.2444 1.389154,1.09674 c 0,0 0.947146,0.33749 1.03133,0.33749 0.08419,0 0.736677,-0.0844 0.736677,-0.0844 l 0.420954,-0.69598 -0.315715,-0.94908 0.126284,-0.31642 -0.673531,-0.88574 -1.426794,-1.45279 -0.341213,-1.14141 0.02106,-0.78037 -0.315707,-0.82257 -0.357816,-0.65376 0.210477,-0.65377 -0.168377,-0.94904 -0.717785,-1.61568 0.265151,-0.0448 -0.444984,-0.77034 0.289101,-0.0918 -0.508218,-0.82847 0.213764,-0.11524 -0.380944,-0.62543 0.124202,-0.0696 -0.460971,-0.37337 0.168384,-0.0875 -1.199723,-0.84051 z"
+ id="path5892"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csccccccccccccccccccccccccccccccccccccccccccccccccccccccscccccccccccccsccccccccccccscccccccccccccccccccccccccccccccccccccccccccscccccccccccccccccccccccc" />
+ </g>
+</svg>
diff --git a/pkg/riseupvpn/snap/hooks/install b/pkg/riseupvpn/snap/hooks/install
new file mode 100755
index 00000000..6d8a9d03
--- /dev/null
+++ b/pkg/riseupvpn/snap/hooks/install
@@ -0,0 +1,648 @@
+#!/usr/bin/env python
+# This helper installs bitmask-root and polkit policy file
+import subprocess
+from base64 import decodestring as decode
+
+BMROOT = """IyEvdXNyL2Jpbi9weXRob24yLjcKIyAtKi0gY29kaW5nOiB1dGYtOCAtKi0KIwojIENvcHlyaWdo
+dCAoQykgMjAxNCBMRUFQCiMKIyBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNh
+biByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQojIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0
+aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5CiMgdGhlIEZyZWUg
+U29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IK
+IyAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgojCiMgVGhpcyBwcm9ncmFtIGlz
+IGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCiMgYnV0IFdJ
+VEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YK
+IyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBT
+ZWUgdGhlCiMgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KIwoj
+IFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1Ymxp
+YyBMaWNlbnNlCiMgYWxvbmcgd2l0aCB0aGlzIHByb2dyYW0uICBJZiBub3QsIHNlZSA8aHR0cDov
+L3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uCiMKIiIiClRoaXMgaXMgYSBwcml2aWxlZ2VkIGhlbHBl
+ciBzY3JpcHQgZm9yIHNhZmVseSBydW5uaW5nIGNlcnRhaW4gY29tbWFuZHMgYXMgcm9vdC4KSXQg
+c2hvdWxkIG9ubHkgYmUgY2FsbGVkIGJ5IHRoZSBCaXRtYXNrIGFwcGxpY2F0aW9uLgoKRXhwZWN0
+ZWQgcGF0aHM6CgogIFdoZW4gaW5zdGFsbGVkIGJ5IGRpc3RybyBwYXRoOgogICAgL3Vzci9zYmlu
+L2JpdG1hc2stcm9vdAoKICBXaGVuIGluc3RhbGxlZCBieSBidW5kbGUgb3IgZnJvbSBnaXQ6CiAg
+ICAvdXNyL2xvY2FsL3NiaW4vYml0bWFzay1yb290CgpVU0FHRToKICBiaXRtYXNrLXJvb3QgZmly
+ZXdhbGwgc3RvcAogIGJpdG1hc2stcm9vdCBmaXJld2FsbCBzdGFydCBbcmVzdGFydF0gR0FURVdB
+WTEgR0FURVdBWTIgLi4uCiAgYml0bWFzay1yb290IG9wZW52cG4gc3RvcAogIGJpdG1hc2stcm9v
+dCBvcGVudnBuIHN0YXJ0IENPTkZJRzEgQ09ORklHMSAuLi4KICBiaXRtYXNrLXJvb3QgZnctZW1h
+aWwgc3RvcAogIGJpdG1hc2stcm9vdCBmdy1lbWFpbCBzdGFydCB1aWQKCkFsbCBhY3Rpb25zIHJl
+dHVybiBleGl0IGNvZGUgMCBmb3Igc3VjY2Vzcywgbm9uLXplcm8gb3RoZXJ3aXNlLgoKVGhlIGBv
+cGVudnBuIHN0YXJ0YCBhY3Rpb24gaXMgc3BlY2lhbDogaXQgY2FsbHMgZXhlYyBvbiBvcGVudnBu
+IGFuZCByZXBsYWNlcwp0aGUgY3VycmVudCBwcm9jZXNzLiBJZiB0aGUgYHJlc3RhcnRgIHBhcmFt
+ZXRlciBpcyBwYXNzZWQsIHRoZSBmaXJld2FsbCB3aWxsCm5vdCBiZSB0ZWFyZWQgZG93biBpbiB0
+aGUgY2FzZSBvZiBhbiBlcnJvciBkdXJpbmcgbGF1bmNoLgoiIiIKIyBUT0RPIHNob3VsZCBiZSB0
+ZXN0ZWQgd2l0aCBweXRob24zLCB3aGljaCBjYW4gYmUgdGhlIGRlZmF1bHQgb24gc29tZSBkaXN0
+cm8uCmZyb20gX19mdXR1cmVfXyBpbXBvcnQgcHJpbnRfZnVuY3Rpb24KaW1wb3J0IG9zCmltcG9y
+dCByZQppbXBvcnQgc2lnbmFsCmltcG9ydCBzb2NrZXQKaW1wb3J0IHN5c2xvZwppbXBvcnQgc3Vi
+cHJvY2VzcwppbXBvcnQgc3lzCmltcG9ydCBzdGF0CmltcG9ydCB0cmFjZWJhY2sKCmNtZGNoZWNr
+ID0gc3VicHJvY2Vzcy5jaGVja19vdXRwdXQKCiMKIyBDT05TVEFOVFMKIwoKCmRlZiBnZXRfbm9f
+Z3JvdXBfbmFtZSgpOgogICAgIiIiCiAgICBSZXR1cm4gdGhlIHJpZ2h0IGdyb3VwIG5hbWUgdG8g
+dXNlIGZvciB0aGUgY3VycmVudCBPUy4KICAgIEV4YW1wbGVzOgogICAgICAgIC0gVWJ1bnR1OiBu
+b2dyb3VwCiAgICAgICAgLSBBcmNoOiBub2JvZHkKCiAgICA6cnR5cGU6IHN0ciBvciBOb25lCiAg
+ICAiIiIKICAgIGltcG9ydCBncnAKICAgIHRyeToKICAgICAgICBncnAuZ2V0Z3JuYW0oJ25vYm9k
+eScpCiAgICAgICAgcmV0dXJuICdub2JvZHknCiAgICBleGNlcHQgS2V5RXJyb3I6CiAgICAgICAg
+dHJ5OgogICAgICAgICAgICBncnAuZ2V0Z3JuYW0oJ25vZ3JvdXAnKQogICAgICAgICAgICByZXR1
+cm4gJ25vZ3JvdXAnCiAgICAgICAgZXhjZXB0IEtleUVycm9yOgogICAgICAgICAgICByZXR1cm4g
+Tm9uZQoKClZFUlNJT04gPSAiOCIKU0NSSVBUID0gImJpdG1hc2stcm9vdCIKTkFNRVNFUlZFUl9U
+Q1AgPSAiMTAuNDEuMC4xIgpOQU1FU0VSVkVSX1VEUCA9ICIxMC40Mi4wLjEiCiMgZm9yIHRoZSB0
+aW1lIGJlaW5nLCB3ZSdyZSBoYXJkY29kaW5nIHRjcCBvbiBjb25uZWN0aW9uIHBhcmFtcy4KTkFN
+RVNFUlZFUiA9IE5BTUVTRVJWRVJfVENQCkJJVE1BU0tfQ0hBSU4gPSAiYml0bWFzayIKQklUTUFT
+S19DSEFJTl9OQVRfT1VUID0gImJpdG1hc2siCkJJVE1BU0tfQ0hBSU5fTkFUX1BPU1QgPSAiYml0
+bWFza19wb3N0cm91dGluZyIKQklUTUFTS19DSEFJTl9FTUFJTCA9ICJiaXRtYXNrX2VtYWlsIgpC
+SVRNQVNLX0NIQUlOX0VNQUlMX09VVCA9ICJiaXRtYXNrX2VtYWlsX291dHB1dCIKTE9DQUxfSU5U
+RVJGQUNFID0gImxvIgpJTUFQX1BPUlQgPSAiMTk4NCIKU01UUF9QT1JUID0gIjIwMTMiCgpJUCA9
+ICIvc2Jpbi9pcCIKSVBUQUJMRVMgPSAiL3NiaW4vaXB0YWJsZXMiCklQNlRBQkxFUyA9ICIvc2Jp
+bi9pcDZ0YWJsZXMiCgpPUEVOVlBOX1VTRVIgPSAibm9ib2R5IgpPUEVOVlBOX0dST1VQID0gZ2V0
+X25vX2dyb3VwX25hbWUoKQpMRUFQT1BFTlZQTiA9ICJMRUFQT1BFTlZQTiIKT1BFTlZQTl9TWVNU
+RU1fQklOID0gIi91c3Ivc2Jpbi9vcGVudnBuIiAgIyBEZWJpYW4gbG9jYXRpb24KT1BFTlZQTl9M
+RUFQX0JJTiA9ICIvdXNyL2xvY2FsL3NiaW4vbGVhcC1vcGVudnBuIiAgIyBpbnN0YWxsZWQgYnkg
+YnVuZGxlCgpGSVhFRF9GTEFHUyA9IFsKICAgICItLXNldGVudiIsICJMRUFQT1BFTlZQTiIsICIx
+IiwKICAgICItLW5vYmluZCIsCiAgICAiLS1jbGllbnQiLAogICAgIi0tZGV2IiwgInR1biIsCiAg
+ICAiLS10bHMtY2xpZW50IiwKICAgICItLXJlbW90ZS1jZXJ0LXRscyIsICJzZXJ2ZXIiLAogICAg
+Ii0tbWFuYWdlbWVudC1zaWduYWwiLAogICAgIi0tc2NyaXB0LXNlY3VyaXR5IiwgIjEiLAogICAg
+Ii0tdXNlciIsICJub2JvZHkiLAogICAgIi0tcGVyc2lzdC1rZXkiLAogICAgIi0tcGVyc2lzdC1s
+b2NhbC1pcCIsCl0KCmlmIE9QRU5WUE5fR1JPVVAgaXMgbm90IE5vbmU6CiAgICBGSVhFRF9GTEFH
+Uy5leHRlbmQoWyItLWdyb3VwIiwgT1BFTlZQTl9HUk9VUF0pCgpBTExPV0VEX0ZMQUdTID0gewog
+ICAgIi0tcmVtb3RlIjogWyJJUCIsICJOVU1CRVIiLCAiUFJPVE8iXSwKICAgICItLXRscy1jaXBo
+ZXIiOiBbIkNJUEhFUiJdLAogICAgIi0tY2lwaGVyIjogWyJDSVBIRVIiXSwKICAgICItLWF1dGgi
+OiBbIkNJUEhFUiJdLAogICAgIi0tbWFuYWdlbWVudCI6IFsiRElSIiwgIlVOSVhTT0NLRVQiXSwK
+ICAgICItLW1hbmFnZW1lbnQtY2xpZW50LXVzZXIiOiBbIlVTRVIiXSwKICAgICItLWNlcnQiOiBb
+IkZJTEUiXSwKICAgICItLWtleSI6IFsiRklMRSJdLAogICAgIi0tY2EiOiBbIkZJTEUiXSwKICAg
+ICItLWZyYWdtZW50IjogWyJOVU1CRVIiXSwKICAgICItLWtlZXBhbGl2ZSI6IFsiTlVNQkVSIiwg
+Ik5VTUJFUiJdLAogICAgIi0tdmVyYiI6IFsiTlVNQkVSIl0sCn0KClBBUkFNX0ZPUk1BVFMgPSB7
+CiAgICAiTlVNQkVSIjogbGFtYmRhIHM6IHJlLm1hdGNoKCJeXGQrJCIsIHMpLAogICAgIlBST1RP
+IjogbGFtYmRhIHM6IHJlLm1hdGNoKCJeKHRjcHx1ZHB8dGNwNHx1ZHA0KSQiLCBzKSwKICAgICJJ
+UCI6IGxhbWJkYSBzOiBpc192YWxpZF9hZGRyZXNzKHMpLAogICAgIkNJUEhFUiI6IGxhbWJkYSBz
+OiByZS5tYXRjaCgiXltBLVowLTktXSskIiwgcyksCiAgICAiVVNFUiI6IGxhbWJkYSBzOiByZS5t
+YXRjaCgKICAgICAgICAiXlthLXpBLVowLTlfXC5cQF1bYS16QS1aMC05X1wtXC5cQF0qXCQ/JCIs
+IHMpLCAgIyBJRUVFIFN0ZCAxMDAzLjEtMjAwMQogICAgIkZJTEUiOiBsYW1iZGEgczogb3MucGF0
+aC5pc2ZpbGUocyksCiAgICAiRElSIjogbGFtYmRhIHM6IG9zLnBhdGguaXNkaXIob3MucGF0aC5z
+cGxpdChzKVswXSksCiAgICAiVU5JWFNPQ0tFVCI6IGxhbWJkYSBzOiBzID09ICJ1bml4IiwKICAg
+ICJVSUQiOiBsYW1iZGEgczogcmUubWF0Y2goIl5bYS16QS1aMC05XSskIiwgcykKfQoKIyBEZXRl
+cm1pbmUgUXViZXMgT1MgdmVyc2lvbiwgaWYgYW55ClFVQkVTX1BST1hZID0gb3MucGF0aC5leGlz
+dHMoIi92YXIvcnVuL3F1YmVzL3RoaXMtaXMtcHJveHl2bSIpCmlmIG9zLnBhdGguaXNkaXIoIi9l
+dGMvcXViZXMiKToKICAgIFFVQkVTX0NGRyA9ICIvcncvY29uZmlnLyIKICAgIFFVQkVTX0lQSE9P
+SyA9IFFVQkVTX0NGRyArICJxdWJlcy1pcC1jaGFuZ2UtaG9vayIKICAgIFFVQkVTX0ZXX1NDUklQ
+VCA9IFFVQkVTX0NGRyArICJxdWJlcy1maXJld2FsbC11c2VyLXNjcmlwdCIKICAgIGlmIHN1YnBy
+b2Nlc3MuY2FsbChbSVBUQUJMRVMsICItLWxpc3QiLCAiUUJTLUZPUldBUkQiXSkgPT0gMDoKICAg
+ICAgICBRVUJFU19WRVIgPSA0CiAgICBlbHNlOgogICAgICAgIFFVQkVTX1ZFUiA9IDMKZWxzZToK
+ICAgICMgbm90IGEgUXViZXMgc3lzdGVtCiAgICBRVUJFU19WRVIgPSAwCgoKREVCVUcgPSBvcy5n
+ZXRlbnYoIkRFQlVHIikKVEVTVCA9IG9zLmdldGVudigiVEVTVCIpCgppZiBERUJVRzoKICAgIGlt
+cG9ydCBsb2dnaW5nCiAgICBmb3JtYXR0ZXIgPSBsb2dnaW5nLkZvcm1hdHRlcigKICAgICAgICAi
+JShhc2N0aW1lKXMgLSAlKG5hbWUpcyAtICUobGV2ZWxuYW1lKXMgLSAlKG1lc3NhZ2UpcyIpCiAg
+ICBjaCA9IGxvZ2dpbmcuU3RyZWFtSGFuZGxlcigpCiAgICBjaC5zZXRMZXZlbChsb2dnaW5nLkRF
+QlVHKQogICAgY2guc2V0Rm9ybWF0dGVyKGZvcm1hdHRlcikKICAgIGxvZ2dlciA9IGxvZ2dpbmcu
+Z2V0TG9nZ2VyKF9fbmFtZV9fKQogICAgbG9nZ2VyLnNldExldmVsKGxvZ2dpbmcuREVCVUcpCiAg
+ICBsb2dnZXIuYWRkSGFuZGxlcihjaCkKCnN5c2xvZy5vcGVubG9nKFNDUklQVCkKCiMKIyBVVElM
+SVRZCiMKCgpkZWYgaXNfdmFsaWRfYWRkcmVzcyh2YWx1ZSk6CiAgICAiIiIKICAgIFZhbGlkYXRl
+IHRoYXQgdGhlIHBhc3NlZCBpcCBpcyBhIHZhbGlkIElQIGFkZHJlc3MuCgogICAgOnBhcmFtIHZh
+bHVlOiB0aGUgdmFsdWUgdG8gYmUgdmFsaWRhdGVkCiAgICA6dHlwZSB2YWx1ZTogc3RyCiAgICA6
+cnR5cGU6IGJvb2wKICAgICIiIgogICAgdHJ5OgogICAgICAgIHNvY2tldC5pbmV0X2F0b24odmFs
+dWUpCiAgICAgICAgcmV0dXJuIFRydWUKICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgbG9n
+KCIlczogRVJST1I6IE1BTEZPUk1FRCBJUDogJXMhIiAlIChTQ1JJUFQsIHZhbHVlKSkKICAgICAg
+ICByZXR1cm4gRmFsc2UKCgpkZWYgc3BsaXRfbGlzdChfbGlzdCwgcmVnZXgpOgogICAgIiIiCiAg
+ICBTcGxpdCBhIGxpc3QgYmFzZWQgb24gYSByZWdleDoKICAgIGUuZy4gc3BsaXRfbGlzdChbInh4
+IiwgInl5IiwgIngxIiwgInp6Il0sICJeeCIpID0+IFtbInh4IiwgInl5Il0sIFsieDEiLAogICAg
+Inp6Il1dCgogICAgOnBhcmFtIF9saXN0OiB0aGUgbGlzdCB0byBiZSBzcGxpdC4KICAgIDp0eXBl
+IF9saXN0OiBsaXN0CiAgICA6cGFyYW0gcmVnZXg6IHRoZSByZWdleCBleHByZXNzaW9uIHRvIGZp
+bHRlciB3aXRoLgogICAgOnR5cGUgcmVnZXg6IHN0cgoKICAgIDpydHlwZTogbGlzdAogICAgIiIi
+CiAgICBpZiBub3QgaGFzYXR0cihyZWdleCwgIm1hdGNoIik6CiAgICAgICAgcmVnZXggPSByZS5j
+b21waWxlKHJlZ2V4KQogICAgcmVzdWx0ID0gW10KICAgIGkgPSAwCiAgICBpZiBub3QgX2xpc3Q6
+CiAgICAgICAgcmV0dXJuIHJlc3VsdAogICAgd2hpbGUgVHJ1ZToKICAgICAgICBpZiByZWdleC5t
+YXRjaChfbGlzdFtpXSk6CiAgICAgICAgICAgIHJlc3VsdC5hcHBlbmQoW10pCiAgICAgICAgICAg
+IHdoaWxlIFRydWU6CiAgICAgICAgICAgICAgICByZXN1bHRbLTFdLmFwcGVuZChfbGlzdFtpXSkK
+ICAgICAgICAgICAgICAgIGkgKz0gMQogICAgICAgICAgICAgICAgaWYgaSA+PSBsZW4oX2xpc3Qp
+IG9yIHJlZ2V4Lm1hdGNoKF9saXN0W2ldKToKICAgICAgICAgICAgICAgICAgICBicmVhawogICAg
+ICAgIGVsc2U6CiAgICAgICAgICAgIGkgKz0gMQogICAgICAgIGlmIGkgPj0gbGVuKF9saXN0KToK
+ICAgICAgICAgICAgYnJlYWsKICAgIHJldHVybiByZXN1bHQKCgpkZWYgZ2V0X3Byb2Nlc3NfbGlz
+dCgpOgogICAgIiIiCiAgICBHZXQgYSBwcm9jZXNzIGxpc3QgYnkgcmVhZGluZyBgL3Byb2NgIGZp
+bGVzeXN0ZW0uCgogICAgOnJldHVybjogYSBsaXN0IG9mIHR1cGxlcywgZWFjaCBjb250YWluaW5n
+IHBpZCBhbmQgY29tbWFuZCBzdHJpbmcuCiAgICA6cnR5cGU6IHR1cGxlIGlmIGxpc3RzCiAgICAi
+IiIKICAgIHJlcyA9IFtdCiAgICBwaWRzID0gW3BpZCBmb3IgcGlkIGluIG9zLmxpc3RkaXIoJy9w
+cm9jJykgaWYgcGlkLmlzZGlnaXQoKV0KCiAgICBmb3IgcGlkIGluIHBpZHM6CiAgICAgICAgdHJ5
+OgogICAgICAgICAgICByZXMuYXBwZW5kKChwaWQsIG9wZW4oCiAgICAgICAgICAgICAgICBvcy5w
+YXRoLmpvaW4oCiAgICAgICAgICAgICAgICAgICAgJy9wcm9jJywgcGlkLCAnY21kbGluZScpLCAn
+cmInKS5yZWFkKCkpKQogICAgICAgIGV4Y2VwdCBJT0Vycm9yOiAgIyBwcm9jIGhhcyBhbHJlYWR5
+IHRlcm1pbmF0ZWQKICAgICAgICAgICAgY29udGludWUKICAgIHJldHVybiBmaWx0ZXIoTm9uZSwg
+cmVzKQoKCmRlZiBydW4oY29tbWFuZCwgKmFyZ3MsICoqb3B0aW9ucyk6CiAgICAiIiIKICAgIFJ1
+biBhbiBleHRlcm5hbCBjb21tYW5kLgoKICAgIE9wdGlvbnM6CgogICAgICBgY2hlY2tgOiBJZiBU
+cnVlLCBjaGVjayB0aGUgY29tbWFuZCdzIG91dHB1dC4gYmFpbCBpZiBub24temVyby4gKHRoZQog
+ICAgICAgICAgICAgICBkZWZhdWx0IGlzIHRydWUgdW5sZXNzIGRldGFjaCBvciBpbnB1dCBpcyB0
+cnVlKQogICAgICBgZXhpdGNvZGVgOiBsaWtlIGBjaGVja2AsIGJ1dCByZXR1cm4gZXhpdGNvZGUg
+aW5zdGVhZCBvZiBiYWlsaW5nLgogICAgICBgZGV0YWNoYDogSWYgVHJ1ZSwgcnVuIGluIGRldGFj
+aGVkIHByb2Nlc3MuCiAgICAgIGBpbnB1dGA6IElmIFRydWUsIG9wZW4gY29tbWFuZCBmb3Igd3Jp
+dGluZyBzdHJlYW0gdG8sIHJldHVybmluZyB0aGUgUG9wZW4KICAgICAgICAgICAgICAgb2JqZWN0
+LgogICAgICBgdGhyb3dgOiBJZiBUcnVlLCByYWlzZSBhbiBleGNlcHRpb24gaWYgdGhlcmUgaXMg
+YW4gZXJyb3IgaW5zdGVhZAogICAgICAgICAgICAgICBvZiBiYWlsaW5nLgogICAgIiIiCiAgICBw
+YXJ0cyA9IFtjb21tYW5kXQogICAgcGFydHMuZXh0ZW5kKGFyZ3MpCiAgICBkZWJ1ZygiJXMgcnVu
+OiAlcyAiICUgKFNDUklQVCwgIiAiLmpvaW4ocGFydHMpKSkKCiAgICBfY2hlY2sgPSBvcHRpb25z
+LmdldCgiY2hlY2siLCBUcnVlKQogICAgX2RldGFjaCA9IG9wdGlvbnMuZ2V0KCJkZXRhY2giLCBG
+YWxzZSkKICAgIF9pbnB1dCA9IG9wdGlvbnMuZ2V0KCJpbnB1dCIsIEZhbHNlKQogICAgX2V4aXRj
+b2RlID0gb3B0aW9ucy5nZXQoImV4aXRjb2RlIiwgRmFsc2UpCiAgICBfdGhyb3cgPSBvcHRpb25z
+LmdldCgidGhyb3ciLCBGYWxzZSkKCiAgICBpZiBub3QgKF9jaGVjayBvciBfdGhyb3cpIG9yIF9k
+ZXRhY2ggb3IgX2lucHV0OgogICAgICAgIGlmIF9pbnB1dDoKICAgICAgICAgICAgcmV0dXJuIHN1
+YnByb2Nlc3MuUG9wZW4ocGFydHMsIHN0ZGluPXN1YnByb2Nlc3MuUElQRSkKICAgICAgICBlbHNl
+OgogICAgICAgICAgICBzdWJwcm9jZXNzLlBvcGVuKHBhcnRzKQogICAgICAgICAgICByZXR1cm4g
+Tm9uZQogICAgZWxzZToKICAgICAgICB0cnk6CiAgICAgICAgICAgIGRldm51bGwgPSBvcGVuKCcv
+ZGV2L251bGwnLCAndycpCiAgICAgICAgICAgIHN1YnByb2Nlc3MuY2hlY2tfY2FsbChwYXJ0cywg
+c3Rkb3V0PWRldm51bGwsIHN0ZGVycj1kZXZudWxsKQogICAgICAgICAgICByZXR1cm4gMAogICAg
+ICAgIGV4Y2VwdCBzdWJwcm9jZXNzLkNhbGxlZFByb2Nlc3NFcnJvciBhcyBleGM6CiAgICAgICAg
+ICAgIGlmIF9leGl0Y29kZToKICAgICAgICAgICAgICAgIGlmIGV4Yy5yZXR1cm5jb2RlICE9IDE6
+CiAgICAgICAgICAgICAgICAgICAgIyAwIG9yIDEgaXMgdG8gYmUgZXhwZWN0ZWQsIGJ1dCBhbnl0
+aGluZyBlbHNlCiAgICAgICAgICAgICAgICAgICAgIyBzaG91bGQgYmUgbG9nZ2VkLgogICAgICAg
+ICAgICAgICAgICAgIGRlYnVnKCJFUlJPUjogQ291bGQgbm90IHJ1biAlczogJXMiICUKICAgICAg
+ICAgICAgICAgICAgICAgICAgICAoZXhjLmNtZCwgZXhjLm91dHB1dCksIGV4Y2VwdGlvbj1leGMp
+CiAgICAgICAgICAgICAgICByZXR1cm4gZXhjLnJldHVybmNvZGUKICAgICAgICAgICAgZWxpZiBf
+dGhyb3c6CiAgICAgICAgICAgICAgICByYWlzZSBleGMKICAgICAgICAgICAgZWxzZToKICAgICAg
+ICAgICAgICAgIGJhaWwoIkVSUk9SOiBDb3VsZCBub3QgcnVuICVzOiAlcyIgJSAoZXhjLmNtZCwg
+ZXhjLm91dHB1dCksCiAgICAgICAgICAgICAgICAgICAgIGV4Y2VwdGlvbj1leGMpCgoKZGVmIGxv
+Zyhtc2c9Tm9uZSwgZXhjZXB0aW9uPU5vbmUsIHByaW9yaXR5PXN5c2xvZy5MT0dfSU5GTyk6CiAg
+ICAiIiIKICAgIHByaW50IGFuZCBsb2cgd2FybmluZyBtZXNzYWdlIG9yIGV4Y2VwdGlvbi4KCiAg
+ICA6cGFyYW0gbXNnOiBvcHRpb25hbCBlcnJvciBtZXNzYWdlLgogICAgOnR5cGUgbXNnOiBzdHIK
+ICAgIDpwYXJhbSBtc2c6IG9wdGlvbmFsIGV4Y2VwdGlvbi4KICAgIDp0eXBlIG1zZzogRXhjZXB0
+aW9uCiAgICA6cGFyYW0gbXNnOiBzeXNsb2cgbGV2ZWwKICAgIDp0eXBlIG1zZzogb25lIG9mIExP
+R19FTUVSRywgTE9HX0FMRVJULCBMT0dfQ1JJVCwgTE9HX0VSUiwKICAgICAgICAgICAgICAgTE9H
+X1dBUk5JTkcsIExPR19OT1RJQ0UsIExPR19JTkZPLCBMT0dfREVCVUcKICAgICIiIgogICAgaWYg
+bXNnIGlzIG5vdCBOb25lOgogICAgICAgIHByaW50KCIlczogJXMiICUgKFNDUklQVCwgbXNnKSkK
+ICAgICAgICBzeXNsb2cuc3lzbG9nKHByaW9yaXR5LCBtc2cpCiAgICBpZiBleGNlcHRpb24gaXMg
+bm90IE5vbmU6CiAgICAgICAgaWYgVEVTVCBvciBERUJVRzoKICAgICAgICAgICAgdHJhY2ViYWNr
+LnByaW50X2V4YygpCiAgICAgICAgc3lzbG9nLnN5c2xvZyhwcmlvcml0eSwgdHJhY2ViYWNrLmZv
+cm1hdF9leGMoKSkKCgpkZWYgZGVidWcobXNnPU5vbmUsIGV4Y2VwdGlvbj1Ob25lKToKICAgICIi
+IgogICAgSnVzdCBsaWtlIGxvZywgYnV0IGlzIHNraXBwZWQgdW5sZXNzIERFQlVHLiBVc2Ugc3lz
+bG9nLkxPR19JTkZPCiAgICBldmVuIGZvciBkZWJ1ZyBtZXNzYWdlcyAod2UgZG9uJ3Qgd2FudCB0
+byBtaXNzIHRoZW0pLgogICAgIiIiCiAgICBpZiBURVNUIG9yIERFQlVHOgogICAgICAgIGxvZyht
+c2csIGV4Y2VwdGlvbikKCgpkZWYgYmFpbChtc2c9Tm9uZSwgZXhjZXB0aW9uPU5vbmUpOgogICAg
+IiIiCiAgICBhYm5vcm1hbCBleGl0LiBsaWtlIGxvZygpLCBidXQgZXhpdHMgd2l0aCBlcnJvciBz
+dGF0dXMgY29kZS4KICAgICIiIgogICAgbG9nKG1zZywgZXhjZXB0aW9uKQogICAgZXhpdCgxKQoK
+IwojIE9QRU5WUE4KIwoKCmRlZiBnZXRfb3BlbnZwbl9iaW4oKToKICAgICIiIgogICAgUmV0dXJu
+IHRoZSBwYXRoIGZvciBlaXRoZXIgdGhlIHN5c3RlbSBvcGVudnBuIG9yIHRoZSBvbmUgdGhlCiAg
+ICBidW5kbGUgaGFzIHB1dCB0aGVyZS4KICAgICIiIgogICAgaWYgb3MucGF0aC5pc2ZpbGUoT1BF
+TlZQTl9TWVNURU1fQklOKToKICAgICAgICByZXR1cm4gT1BFTlZQTl9TWVNURU1fQklOCgogICAg
+IyB0aGUgYnVuZGxlIG9wdGlvbiBzaG91bGQgYmUgcmVtb3ZlZCBmcm9tIHRoZSBkZWJpYW4gcGFj
+a2FnZS4KICAgIGlmIG9zLnBhdGguaXNmaWxlKE9QRU5WUE5fTEVBUF9CSU4pOgogICAgICAgIHJl
+dHVybiBPUEVOVlBOX0xFQVBfQklOCgoKZGVmIHBhcnNlX29wZW52cG5fZmxhZ3MoYXJncyk6CiAg
+ICAiIiIKICAgIFRha2UgYXJndW1lbnQgbGlzdCBmcm9tIHRoZSBjb21tYW5kIGxpbmUgYW5kIHBh
+cnNlIGl0LCBvbmx5IGFsbG93aW5nIHNvbWUKICAgIGNvbmZpZ3VyYXRpb24gZmxhZ3MuCgogICAg
+OnR5cGUgYXJnczogbGlzdAogICAgIiIiCiAgICByZXN1bHQgPSBbXQogICAgdHJ5OgogICAgICAg
+IGZvciBmbGFnIGluIHNwbGl0X2xpc3QoYXJncywgIl4tLSIpOgogICAgICAgICAgICBmbGFnX25h
+bWUgPSBmbGFnWzBdCiAgICAgICAgICAgIGlmIGZsYWdfbmFtZSBpbiBBTExPV0VEX0ZMQUdTOgog
+ICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChmbGFnX25hbWUpCiAgICAgICAgICAgICAgICBy
+ZXF1aXJlZF9wYXJhbXMgPSBBTExPV0VEX0ZMQUdTW2ZsYWdfbmFtZV0KICAgICAgICAgICAgICAg
+IGlmIHJlcXVpcmVkX3BhcmFtczoKICAgICAgICAgICAgICAgICAgICAjIGZsYXR0ZW4gaWYgc2Vw
+YXJhdGVkIGJ5IHNwYWNlcwogICAgICAgICAgICAgICAgICAgIGZsYWdfcGFyYW1zID0gW2kgZm9y
+IHN1Ymxpc3QgaW4gbWFwKAogICAgICAgICAgICAgICAgICAgICAgICBsYW1iZGEgczogcy5zcGxp
+dCgpLCBmbGFnWzE6XSkgZm9yIGkgaW4gc3VibGlzdF0KICAgICAgICAgICAgICAgICAgICBpZiBs
+ZW4oZmxhZ19wYXJhbXMpICE9IGxlbihyZXF1aXJlZF9wYXJhbXMpOgogICAgICAgICAgICAgICAg
+ICAgICAgICBsb2coIiVzOiBFUlJPUjogbm90IGVub3VnaCBwYXJhbXMgZm9yICVzIiAlCiAgICAg
+ICAgICAgICAgICAgICAgICAgICAgICAoU0NSSVBULCBmbGFnX25hbWUpKQogICAgICAgICAgICAg
+ICAgICAgICAgICByZXR1cm4gTm9uZQogICAgICAgICAgICAgICAgICAgIGZvciBwYXJhbSwgcGFy
+YW1fdHlwZSBpbiB6aXAoZmxhZ19wYXJhbXMsIHJlcXVpcmVkX3BhcmFtcyk6CiAgICAgICAgICAg
+ICAgICAgICAgICAgIGlmIFBBUkFNX0ZPUk1BVFNbcGFyYW1fdHlwZV0ocGFyYW0pOgogICAgICAg
+ICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmFwcGVuZChwYXJhbSkKICAgICAgICAgICAgICAg
+ICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZygiJXM6IEVSUk9S
+OiBCYWQgYXJndW1lbnQgJXMiICUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoU0NS
+SVBULCBwYXJhbSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gTm9uZQogICAg
+ICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgbG9nKCJXQVJOSU5HOiB1bnJlY29nbml6ZWQg
+b3BlbnZwbiBmbGFnICVzIiAlIGZsYWdfbmFtZSkKICAgICAgICByZXR1cm4gcmVzdWx0CiAgICBl
+eGNlcHQgRXhjZXB0aW9uIGFzIGV4YzoKICAgICAgICBsb2coIiVzOiBFUlJPUiBQQVJTSU5HIEZM
+QUdTOiAlcyIgJSAoU0NSSVBULCBleGMpKQogICAgICAgIGlmIERFQlVHOgogICAgICAgICAgICBs
+b2dnZXIuZXhjZXB0aW9uKGV4YykKICAgICAgICByZXR1cm4gTm9uZQoKCmRlZiBvcGVudnBuX3N0
+YXJ0KGFyZ3MpOgogICAgIiIiCiAgICBMYXVuY2ggb3BlbnZwbiwgc2FuaXRpemluZyBpbnB1dCwg
+YW5kIHJlcGxhY2luZyB0aGUgY3VycmVudCBwcm9jZXNzIHdpdGgKICAgIHRoZSBvcGVudnBuIHBy
+b2Nlc3MuCgogICAgOnBhcmFtIGFyZ3M6IGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gb3BlbnZw
+bgogICAgOnR5cGUgYXJnczogbGlzdAogICAgIiIiCiAgICBvcGVudnBuX2ZsYWdzID0gcGFyc2Vf
+b3BlbnZwbl9mbGFncyhhcmdzKQogICAgaWYgb3BlbnZwbl9mbGFnczoKICAgICAgICBPUEVOVlBO
+ID0gZ2V0X29wZW52cG5fYmluKCkKICAgICAgICBmbGFncyA9IFtPUEVOVlBOXSArIEZJWEVEX0ZM
+QUdTICsgb3BlbnZwbl9mbGFncwogICAgICAgIGlmIERFQlVHOgogICAgICAgICAgICBsb2coIiVz
+OiBydW5uaW5nIG9wZW52cG4gd2l0aCBmbGFnczoiICUgKFNDUklQVCwpKQogICAgICAgICAgICBs
+b2coZmxhZ3MpCiAgICAgICAgIyBub3RlOiBmaXJzdCBhcmd1bWVudCB0byBjb21tYW5kIGlzIGln
+bm9yZWQsIGJ1dCBjdXN0b21hcmlseSBzZXQgdG8KICAgICAgICAjIHRoZSBjb21tYW5kLgogICAg
+ICAgIG9zLmV4ZWN2KE9QRU5WUE4sIGZsYWdzKQogICAgZWxzZToKICAgICAgICBiYWlsKCdFUlJP
+UjogY291bGQgbm90IHBhcnNlIG9wZW52cG4gb3B0aW9ucycpCgoKZGVmIG9wZW52cG5fc3RvcChh
+cmdzKToKICAgICIiIgogICAgU3RvcCB0aGUgb3BlbnZwbiB0aGF0IGhhcyBsaWtlbHkgYmVlbiBs
+YXVuY2hlZCBieSBiaXRtYXNrLgoKICAgIDpwYXJhbSBhcmdzOiBhcmd1bWVudHMgdG8gb3BlbnZw
+bgogICAgOnR5cGUgYXJnczogbGlzdAogICAgIiIiCiAgICBwbGlzdCA9IGdldF9wcm9jZXNzX2xp
+c3QoKQogICAgT1BFTlZQTl9CSU4gPSBnZXRfb3BlbnZwbl9iaW4oKQogICAgZm91bmRfbGVhcF9v
+cGVudnBuID0gZmlsdGVyKAogICAgICAgIGxhbWJkYSAocCwgcyk6IHMuc3RhcnRzd2l0aChPUEVO
+VlBOX0JJTikgYW5kIExFQVBPUEVOVlBOIGluIHMsCiAgICAgICAgcGxpc3QpCgogICAgaWYgZm91
+bmRfbGVhcF9vcGVudnBuOgogICAgICAgIHBpZCA9IGZvdW5kX2xlYXBfb3BlbnZwblswXVswXQog
+ICAgICAgIG9zLmtpbGwoaW50KHBpZCksIHNpZ25hbC5TSUdURVJNKQoKIwojIEZJUkVXQUxMCiMK
+CgpkZWYgZ2V0X2dhdGV3YXlzKGdhdGV3YXlzKToKICAgICIiIgogICAgRmlsdGVyIGEgcGFzc2Vk
+IHNlcXVlbmNlIG9mIGdhdGV3YXlzLCByZXR1cm5pbmcgb25seSB0aGUgdmFsaWQgb25lcy4KCiAg
+ICA6cGFyYW0gZ2F0ZXdheXM6IGEgc2VxdWVuY2Ugb2YgZ2F0ZXdheXMgdG8gZmlsdGVyLgogICAg
+OnR5cGUgZ2F0ZXdheXM6IGl0ZXJhYmxlCiAgICA6cnR5cGU6IGl0ZXJhYmxlCiAgICAiIiIKICAg
+IHJlc3VsdCA9IGZpbHRlcihpc192YWxpZF9hZGRyZXNzLCBnYXRld2F5cykKICAgIGlmIG5vdCBy
+ZXN1bHQ6CiAgICAgICAgYmFpbCgiRVJST1I6IE5vIHZhbGlkIGdhdGV3YXlzIHNwZWNpZmllZCIp
+CiAgICBlbHNlOgogICAgICAgIHJldHVybiByZXN1bHQKCgpkZWYgZ2V0X2RlZmF1bHRfZGV2aWNl
+KCk6CiAgICAiIiIKICAgIFJldHJpZXZlIHRoZSBjdXJyZW50IGRlZmF1bHQgbmV0d29yayBkZXZp
+Y2UuCgogICAgOnJ0eXBlOiBzdHIKICAgICIiIgogICAgcm91dGVzID0gc3VicHJvY2Vzcy5jaGVj
+a19vdXRwdXQoW0lQLCAicm91dGUiLCAic2hvdyJdKQogICAgbWF0Y2ggPSByZS5zZWFyY2goIl5k
+ZWZhdWx0IC4qZGV2IChbXlxzXSopIC4qJCIsIHJvdXRlcywgZmxhZ3M9cmUuTSkKICAgIGlmIG1h
+dGNoIGFuZCBtYXRjaC5ncm91cHMoKToKICAgICAgICByZXR1cm4gbWF0Y2guZ3JvdXAoMSkKICAg
+IGVsc2U6CiAgICAgICAgYmFpbCgiQ291bGQgbm90IGZpbmQgZGVmYXVsdCBkZXZpY2UiKQoKCmRl
+ZiBnZXRfbG9jYWxfbmV0d29ya19pcHY0KGRldmljZSk6CiAgICAiIiIKICAgIEdldCB0aGUgbG9j
+YWwgaXB2NCBhZGRyZXMgZm9yIGEgZ2l2ZW4gZGV2aWNlLgoKICAgIDpwYXJhbSBkZXZpY2U6CiAg
+ICA6dHlwZSBkZXZpY2U6IHN0cgogICAgIiIiCiAgICBhZGRyZXNzZXMgPSBjbWRjaGVjayhbSVAs
+ICItbyIsICJhZGRyZXNzIiwgInNob3ciLCAiZGV2IiwgZGV2aWNlXSkKICAgIG1hdGNoID0gcmUu
+c2VhcmNoKCJeLippbmV0IChbXiBdKikgLiokIiwgYWRkcmVzc2VzLCBmbGFncz1yZS5NKQogICAg
+aWYgbWF0Y2ggYW5kIG1hdGNoLmdyb3VwcygpOgogICAgICAgIHJldHVybiBtYXRjaC5ncm91cCgx
+KQogICAgZWxzZToKICAgICAgICByZXR1cm4gTm9uZQoKCmRlZiBnZXRfbG9jYWxfbmV0d29ya19p
+cHY2KGRldmljZSk6CiAgICAiIiIKICAgIEdldCB0aGUgbG9jYWwgaXB2NiBhZGRyZXMgZm9yIGEg
+Z2l2ZW4gZGV2aWNlLgoKICAgIDpwYXJhbSBkZXZpY2U6CiAgICA6dHlwZSBkZXZpY2U6IHN0cgog
+ICAgIiIiCiAgICBhZGRyZXNzZXMgPSBjbWRjaGVjayhbSVAsICItbyIsICJhZGRyZXNzIiwgInNo
+b3ciLCAiZGV2IiwgZGV2aWNlXSkKICAgIG1hdGNoID0gcmUuc2VhcmNoKCJeLippbmV0NiAoW14g
+XSopIC4qJCIsIGFkZHJlc3NlcywgZmxhZ3M9cmUuTSkKICAgIGlmIG1hdGNoIGFuZCBtYXRjaC5n
+cm91cHMoKToKICAgICAgICByZXR1cm4gbWF0Y2guZ3JvdXAoMSkKICAgIGVsc2U6CiAgICAgICAg
+cmV0dXJuIE5vbmUKCgpkZWYgcnVuX2lwdGFibGVfd2l0aF9jaGVjayhjbWQsICphcmdzLCAqKm9w
+dGlvbnMpOgogICAgIiIiCiAgICBSdW4gYW4gaXB0YWJsZXMgY29tbWFuZCBjaGVja2luZyB0byBz
+ZWUgaWYgaXQgc2hvdWxkOgogICAgICBmb3IgLS1hcHBlbmQ6IHJ1biBvbmx5IGlmIHJ1bGUgZG9l
+cyBub3QgYWxyZWFkeSBleGlzdC4KICAgICAgZm9yIC0taW5zZXJ0OiBydW4gb25seSBpZiBydWxl
+IGRvZXMgbm90IGFscmVhZHkgZXhpc3QuCiAgICAgIGZvciAtLWRlbGV0ZTogcnVuIG9ubHkgaWYg
+cnVsZSBkb2VzIGV4aXN0LgogICAgb3RoZXIgY29tbWFuZHMgYXJlIHJ1biBub3JtYWxseS4KICAg
+ICIiIgogICAgaWYgIi0taW5zZXJ0IiBpbiBhcmdzOgogICAgICAgIGNoZWNrX2FyZ3MgPSBbYXJn
+LnJlcGxhY2UoIi0taW5zZXJ0IiwgIi0tY2hlY2siKSBmb3IgYXJnIGluIGFyZ3NdCiAgICAgICAg
+Y2hlY2tfY29kZSA9IHJ1bihjbWQsICpjaGVja19hcmdzLCBleGl0Y29kZT1UcnVlKQogICAgICAg
+IGlmIGNoZWNrX2NvZGUgIT0gMDoKICAgICAgICAgICAgcnVuKGNtZCwgKmFyZ3MsICoqb3B0aW9u
+cykKICAgIGVsaWYgIi0tYXBwZW5kIiBpbiBhcmdzOgogICAgICAgIGNoZWNrX2FyZ3MgPSBbYXJn
+LnJlcGxhY2UoIi0tYXBwZW5kIiwgIi0tY2hlY2siKSBmb3IgYXJnIGluIGFyZ3NdCiAgICAgICAg
+Y2hlY2tfY29kZSA9IHJ1bihjbWQsICpjaGVja19hcmdzLCBleGl0Y29kZT1UcnVlKQogICAgICAg
+IGlmIGNoZWNrX2NvZGUgIT0gMDoKICAgICAgICAgICAgcnVuKGNtZCwgKmFyZ3MsICoqb3B0aW9u
+cykKICAgIGVsaWYgIi0tZGVsZXRlIiBpbiBhcmdzOgogICAgICAgIGNoZWNrX2FyZ3MgPSBbYXJn
+LnJlcGxhY2UoIi0tZGVsZXRlIiwgIi0tY2hlY2siKSBmb3IgYXJnIGluIGFyZ3NdCiAgICAgICAg
+Y2hlY2tfY29kZSA9IHJ1bihjbWQsICpjaGVja19hcmdzLCBleGl0Y29kZT1UcnVlKQogICAgICAg
+IGlmIGNoZWNrX2NvZGUgPT0gMDoKICAgICAgICAgICAgcnVuKGNtZCwgKmFyZ3MsICoqb3B0aW9u
+cykKICAgIGVsc2U6CiAgICAgICAgcnVuKGNtZCwgKmFyZ3MsICoqb3B0aW9ucykKCgpkZWYgaXB0
+YWJsZXMoKmFyZ3MsICoqb3B0aW9ucyk6CiAgICAiIiIKICAgIFJ1biBpcHRhYmxlczQgYW5kIGlw
+dGFibGVzNi4KICAgICIiIgogICAgaXA0dGFibGVzKCphcmdzLCAqKm9wdGlvbnMpCiAgICBpcDZ0
+YWJsZXMoKmFyZ3MsICoqb3B0aW9ucykKCgpkZWYgaXA0dGFibGVzKCphcmdzLCAqKm9wdGlvbnMp
+OgogICAgIiIiCiAgICBSdW4gaXB0YWJsZXM0IHdpdGggY2hlY2tzLgogICAgIiIiCiAgICBydW5f
+aXB0YWJsZV93aXRoX2NoZWNrKElQVEFCTEVTLCAqYXJncywgKipvcHRpb25zKQoKCmRlZiBpcDZ0
+YWJsZXMoKmFyZ3MsICoqb3B0aW9ucyk6CiAgICAiIiIKICAgIFJ1biBpcHRhYmxlczYgd2l0aCBj
+aGVja3MuCiAgICAiIiIKICAgIHJ1bl9pcHRhYmxlX3dpdGhfY2hlY2soSVA2VEFCTEVTLCAqYXJn
+cywgKipvcHRpb25zKQoKIwojIE5PVEU6IHRoZXNlIHRlc3RzIHRvIHNlZSBpZiBhIGNoYWluIGV4
+aXN0cyBtaWdodCBpbmNvcnJlY3RseSByZXR1cm4gZmFsc2UuCiMgVGhpcyBoYXBwZW5zIHdoZW4g
+dGhlcmUgaXMgYW4gZXJyb3IgaW4gY2FsbGluZyBgaXB0YWJsZXMgLS1saXN0IGJpdG1hc2tgLgoj
+CiMgRm9yIHRoaXMgcmVhc29uLCB3aGVuIHN0b3BwaW5nIHRoZSBmaXJld2FsbCwgd2UgZG8gbm90
+IHRydXN0IHRoZQojIG91dHB1dCBvZiBpcHZ4X2NoYWluX2V4aXN0cygpIGJ1dCBpbnN0ZWFkIGFs
+d2F5cyBhdHRlbXB0IHRvIGRlbGV0ZQojIHRoZSBjaGFpbi4KIwoKCmRlZiBpcHY0X2NoYWluX2V4
+aXN0cyhjaGFpbiwgdGFibGU9Tm9uZSk6CiAgICAiIiIKICAgIENoZWNrIGlmIGEgZ2l2ZW4gY2hh
+aW4gZXhpc3RzLiBPbmx5IHJldHVybnMgdHJ1ZSBpZiBpdCBhY3R1YWxseSBleGlzdHMsCiAgICBi
+dXQgbWlnaHQgcmV0dXJuIGZhbHNlIGlmIGl0IGV4aXN0cyBhbmQgaXB0YWJsZXMgZmFpbGVkIHRv
+IHJ1bi4KCiAgICA6cGFyYW0gY2hhaW46IHRoZSBjaGFpbiB0byBjaGVjayBhZ2FpbnN0CiAgICA6
+dHlwZSBjaGFpbjogc3RyCiAgICA6cnR5cGU6IGJvb2wKICAgICIiIgogICAgaWYgdGFibGUgaXMg
+bm90IE5vbmU6CiAgICAgICAgY29kZSA9IHJ1bihJUFRBQkxFUywgIi10IiwgdGFibGUsCiAgICAg
+ICAgICAgICAgICAgICAiLS1saXN0IiwgY2hhaW4sICItLW51bWVyaWMiLCBleGl0Y29kZT1UcnVl
+KQogICAgZWxzZToKICAgICAgICBjb2RlID0gcnVuKElQVEFCTEVTLCAiLS1saXN0IiwgY2hhaW4s
+ICItLW51bWVyaWMiLCBleGl0Y29kZT1UcnVlKQogICAgaWYgY29kZSA9PSAwOgogICAgICAgIHJl
+dHVybiBUcnVlCiAgICBlbGlmIGNvZGUgPT0gMToKICAgICAgICByZXR1cm4gRmFsc2UKICAgIGVs
+c2U6CiAgICAgICAgbG9nKCJFUlJPUjogQ291bGQgbm90IGRldGVybWluZSBzdGF0ZSBvZiBpcHRh
+YmxlIGNoYWluIikKICAgICAgICByZXR1cm4gRmFsc2UKCgpkZWYgaXB2Nl9jaGFpbl9leGlzdHMo
+Y2hhaW4pOgogICAgIiIiCiAgICBzZWUgaXB2NF9jaGFpbl9leGlzdHMoKQoKICAgIDpwYXJhbSBj
+aGFpbjogdGhlIGNoYWluIHRvIGNoZWNrIGFnYWluc3QKICAgIDp0eXBlIGNoYWluOiBzdHIKICAg
+IDpydHlwZTogYm9vbAogICAgIiIiCiAgICBjb2RlID0gcnVuKElQNlRBQkxFUywgIi0tbGlzdCIs
+IGNoYWluLCAiLS1udW1lcmljIiwgZXhpdGNvZGU9VHJ1ZSkKICAgIGlmIGNvZGUgPT0gMDoKICAg
+ICAgICByZXR1cm4gVHJ1ZQogICAgZWxpZiBjb2RlID09IDE6CiAgICAgICAgcmV0dXJuIEZhbHNl
+CiAgICBlbHNlOgogICAgICAgIGxvZygiRVJST1I6IENvdWxkIG5vdCBkZXRlcm1pbmUgc3RhdGUg
+b2YgaXB0YWJsZSBjaGFpbiIpCiAgICAgICAgcmV0dXJuIEZhbHNlCgoKZGVmIGVuYWJsZV9pcF9m
+b3J3YXJkaW5nKCk6CiAgICAiIiIKICAgIGlwX2Zvd2FyZGluZyBtdXN0IGJlIGVuYWJsZWQgZm9y
+IHRoZSBmaXJld2FsbCB0byB3b3JrLgogICAgIiIiCiAgICB3aXRoIG9wZW4oJy9wcm9jL3N5cy9u
+ZXQvaXB2NC9pcF9mb3J3YXJkJywgJ3cnKSBhcyBmOgogICAgICAgIGYud3JpdGUoJzFcbicpCgoK
+ZGVmIGZpcmV3YWxsX3N0YXJ0KGFyZ3MpOgogICAgIiIiCiAgICBCcmluZyB1cCB0aGUgZmlyZXdh
+bGwuCgogICAgOnBhcmFtIGFyZ3M6IGxpc3Qgb2YgZ2F0ZXdheXMsIHRvIGJlIHNhbml0aXplZC4K
+ICAgIDp0eXBlIGFyZ3M6IGxpc3QKICAgICIiIgogICAgZGVmYXVsdF9kZXZpY2UgPSBnZXRfZGVm
+YXVsdF9kZXZpY2UoKQogICAgbG9jYWxfbmV0d29ya19pcHY0ID0gZ2V0X2xvY2FsX25ldHdvcmtf
+aXB2NChkZWZhdWx0X2RldmljZSkKICAgIGxvY2FsX25ldHdvcmtfaXB2NiA9IGdldF9sb2NhbF9u
+ZXR3b3JrX2lwdjYoZGVmYXVsdF9kZXZpY2UpCiAgICBnYXRld2F5cyA9IGdldF9nYXRld2F5cyhh
+cmdzKQoKICAgICMgYWRkIGN1c3RvbSBjaGFpbiAiYml0bWFzayIgdG8gZnJvbnQgb2YgT1VUUFVU
+IGNoYWluIGZvciBib3RoCiAgICAjIHRoZSAnZmlsdGVyJyBhbmQgdGhlICduYXQnIHRhYmxlcy4K
+ICAgIGlmIG5vdCBpcHY0X2NoYWluX2V4aXN0cyhCSVRNQVNLX0NIQUlOKToKICAgICAgICBpcDR0
+YWJsZXMoIi0tbmV3LWNoYWluIiwgQklUTUFTS19DSEFJTikKICAgIGlmIG5vdCBpcHY0X2NoYWlu
+X2V4aXN0cyhCSVRNQVNLX0NIQUlOX05BVF9PVVQsICduYXQnKToKICAgICAgICBpcDR0YWJsZXMo
+Ii0tdGFibGUiLCAibmF0IiwgIi0tbmV3LWNoYWluIiwgQklUTUFTS19DSEFJTl9OQVRfT1VUKQog
+ICAgaWYgbm90IGlwdjRfY2hhaW5fZXhpc3RzKEJJVE1BU0tfQ0hBSU5fTkFUX1BPU1QsICduYXQn
+KToKICAgICAgICBpcDR0YWJsZXMoIi0tdGFibGUiLCAibmF0IiwgIi0tbmV3LWNoYWluIiwgQklU
+TUFTS19DSEFJTl9OQVRfUE9TVCkKICAgIGlmIG5vdCBpcHY2X2NoYWluX2V4aXN0cyhCSVRNQVNL
+X0NIQUlOKToKICAgICAgICBpcDZ0YWJsZXMoIi0tbmV3LWNoYWluIiwgQklUTUFTS19DSEFJTikK
+ICAgIGlwNHRhYmxlcygiLS10YWJsZSIsICJuYXQiLCAiLS1pbnNlcnQiLCAiT1VUUFVUIiwKICAg
+ICAgICAgICAgICAiLS1qdW1wIiwgQklUTUFTS19DSEFJTl9OQVRfT1VUKQogICAgaXA0dGFibGVz
+KCItLXRhYmxlIiwgIm5hdCIsICItLWluc2VydCIsICJQT1NUUk9VVElORyIsCiAgICAgICAgICAg
+ICAgIi0tanVtcCIsIEJJVE1BU0tfQ0hBSU5fTkFUX1BPU1QpCiAgICBpcHRhYmxlcygiLS1pbnNl
+cnQiLCAiT1VUUFVUIiwgIi0tanVtcCIsIEJJVE1BU0tfQ0hBSU4pCgogICAgIyByb3V0ZSBhbGwg
+aXB2NCBETlMgb3ZlciBWUE4KICAgICMgKG5vdGU6IE5BVCBkb2VzIG5vdCB3b3JrIHdpdGggaXB2
+NiB1bnRpbCBrZXJuZWwgMy43KQogICAgZW5hYmxlX2lwX2ZvcndhcmRpbmcoKQogICAgaWYgUVVC
+RVNfUFJPWFkgYW5kIFFVQkVTX1ZFUiA+PSAzOgogICAgICAgICMgcmV3cml0ZSBETlMgcGFja2V0
+cyBmb3IgVlBOIEROUzsgUXViZXMgcHJlY29uZmlndXJlcyBtYXNxdWVyYWRlCiAgICAgICAgaXA0
+dGFibGVzKCItdCIsICJuYXQiLCAiLS1mbHVzaCIsICJQUi1RQlMiKQogICAgICAgIGlwNHRhYmxl
+cygiLXQiLCAibmF0IiwgIi0tYXBwZW5kIiwgIlBSLVFCUyIsICItcCIsICJ1ZHAiLAogICAgICAg
+ICAgICAgICAgICAiLS1kcG9ydCIsICI1MyIsICItLWp1bXAiLCAiRE5BVCIsICItLXRvIiwgTkFN
+RVNFUlZFUisiOjUzIikKICAgICAgICBpcDR0YWJsZXMoIi10IiwgIm5hdCIsICItLWFwcGVuZCIs
+ICJQUi1RQlMiLCAiLXAiLCAidGNwIiwKICAgICAgICAgICAgICAgICAgIi0tZHBvcnQiLCAiNTMi
+LCAiLS1qdW1wIiwgIkROQVQiLCAiLS10byIsIE5BTUVTRVJWRVIrIjo1MyIpCiAgICBlbHNlOgog
+ICAgICAgICMgYWxsb3cgZG5zIHRvIGxvY2FsaG9zdAogICAgICAgIGlwNHRhYmxlcygiLXQiLCAi
+bmF0IiwgIi0tYXBwZW5kIiwgQklUTUFTS19DSEFJTiwgIi0tcHJvdG9jb2wiLCAidWRwIiwKICAg
+ICAgICAgICAgICAgICAgIi0tZGVzdCIsICIxMjcuMC4xLjEsMTI3LjAuMC4xLDEyNy4wLjAuNTMi
+LCAiLS1kcG9ydCIsICI1MyIsCiAgICAgICAgICAgICAgICAgICItLWp1bXAiLCAiQUNDRVBUIikK
+ICAgICAgICAjIHJld3JpdGUgYWxsIG91dGdvaW5nIHBhY2tldHMgdG8gdXNlIFZQTiBETlMgc2Vy
+dmVyCiAgICAgICAgIyAoRE5TIGRvZXMgc29tZXRpbWVzIHVzZSBUQ1AhKQogICAgICAgIGlwNHRh
+YmxlcygiLXQiLCAibmF0IiwgIi0tYXBwZW5kIiwgQklUTUFTS19DSEFJTl9OQVRfT1VULCAiLXAi
+LCAidWRwIiwKICAgICAgICAgICAgICAgICAgIi0tZHBvcnQiLCAiNTMiLCAiLS1qdW1wIiwgIkRO
+QVQiLCAiLS10byIsIE5BTUVTRVJWRVIrIjo1MyIpCiAgICAgICAgaXA0dGFibGVzKCItdCIsICJu
+YXQiLCAiLS1hcHBlbmQiLCBCSVRNQVNLX0NIQUlOX05BVF9PVVQsICItcCIsICJ0Y3AiLAogICAg
+ICAgICAgICAgICAgICAiLS1kcG9ydCIsICI1MyIsICItLWp1bXAiLCAiRE5BVCIsICItLXRvIiwg
+TkFNRVNFUlZFUisiOjUzIikKICAgICAgICAjIGVuYWJsZSBtYXNxdWVyYWRpbmcsIHNvIHRoYXQg
+RE5TIHBhY2tldHMgcmV3cml0dGVuIGJ5IEROQVQgd2lsbAogICAgICAgICMgaGF2ZSB0aGUgY29y
+cmVjdCBzb3VyY2UgSVBzLiBBcHBseSBtYXNxdWVyYWRlIG9ubHkgdG8gdGhlIE5BTUVTRVJWRVIs
+CiAgICAgICAgIyB3ZSBkb24ndCB3YW50IHRvIGFwcGx5IGl0IHRvIHRoZSBsb2NhbGhvc3QgZG5z
+IHJlc29sdmVyLgogICAgICAgIGlwNHRhYmxlcygiLXQiLCAibmF0IiwgIi0tYXBwZW5kIiwgQklU
+TUFTS19DSEFJTl9OQVRfUE9TVCwKICAgICAgICAgICAgICAgICAgIi0tZGVzdCIsIE5BTUVTRVJW
+RVIsCiAgICAgICAgICAgICAgICAgICItLXByb3RvY29sIiwgInVkcCIsICItLWRwb3J0IiwgIjUz
+IiwgIi0tanVtcCIsICJNQVNRVUVSQURFIikKICAgICAgICBpcDR0YWJsZXMoIi10IiwgIm5hdCIs
+ICItLWFwcGVuZCIsIEJJVE1BU0tfQ0hBSU5fTkFUX1BPU1QsCiAgICAgICAgICAgICAgICAgICIt
+LWRlc3QiLCBOQU1FU0VSVkVSLAogICAgICAgICAgICAgICAgICAiLS1wcm90b2NvbCIsICJ0Y3Ai
+LCAiLS1kcG9ydCIsICI1MyIsICItLWp1bXAiLCAiTUFTUVVFUkFERSIpCgogICAgIyBhbGxvdyBs
+b2NhbCBuZXR3b3JrIHRyYWZmaWMKICAgIGlmIGxvY2FsX25ldHdvcmtfaXB2NDoKICAgICAgICAj
+IGFsbG93IGxvY2FsIG5ldHdvcmsgZGVzdGluYXRpb25zCiAgICAgICAgaXA0dGFibGVzKCItLWFw
+cGVuZCIsIEJJVE1BU0tfQ0hBSU4sCiAgICAgICAgICAgICAgICAgICItLWRlc3RpbmF0aW9uIiwg
+bG9jYWxfbmV0d29ya19pcHY0LCAiLW8iLCBkZWZhdWx0X2RldmljZSwKICAgICAgICAgICAgICAg
+ICAgIi0tanVtcCIsICJBQ0NFUFQiKQogICAgICAgICMgYWxsb3cgbG9jYWwgbmV0d29yayBzb3Vy
+Y2VzIGZvciBETlMKICAgICAgICAjIChyZXF1aXJlZCB0byBhbGxvdyBsb2NhbCBuZXR3b3JrIERO
+UyB0aGF0IGdldHMgcmV3cml0dGVuIGJ5IE5BVAogICAgICAgICMgIHRvIGdldCBwYXNzZWQgdGhy
+b3VnaCBzbyB0aGF0IE1BU1FVRVJBREUgY2FuIHNldCBjb3JyZWN0IHNvdXJjZSBJUCkKICAgICAg
+ICBpcDR0YWJsZXMoIi0tYXBwZW5kIiwgQklUTUFTS19DSEFJTiwKICAgICAgICAgICAgICAgICAg
+Ii0tc291cmNlIiwgbG9jYWxfbmV0d29ya19pcHY0LCAiLW8iLCBkZWZhdWx0X2RldmljZSwKICAg
+ICAgICAgICAgICAgICAgIi1wIiwgInVkcCIsICItLWRwb3J0IiwgIjUzIiwgIi0tanVtcCIsICJB
+Q0NFUFQiKQogICAgICAgIGlwNHRhYmxlcygiLS1hcHBlbmQiLCBCSVRNQVNLX0NIQUlOLAogICAg
+ICAgICAgICAgICAgICAiLS1zb3VyY2UiLCBsb2NhbF9uZXR3b3JrX2lwdjQsICItbyIsIGRlZmF1
+bHRfZGV2aWNlLAogICAgICAgICAgICAgICAgICAiLXAiLCAidGNwIiwgIi0tZHBvcnQiLCAiNTMi
+LCAiLS1qdW1wIiwgIkFDQ0VQVCIpCiAgICAgICAgIyBhbGxvdyBtdWx0aWNhc3QgU2ltcGxlIFNl
+cnZpY2UgRGlzY292ZXJ5IFByb3RvY29sCiAgICAgICAgaXA0dGFibGVzKCItLWFwcGVuZCIsIEJJ
+VE1BU0tfQ0hBSU4sCiAgICAgICAgICAgICAgICAgICItLXByb3RvY29sIiwgInVkcCIsCiAgICAg
+ICAgICAgICAgICAgICItLWRlc3RpbmF0aW9uIiwgIjIzOS4yNTUuMjU1LjI1MCIsICItLWRwb3J0
+IiwgIjE5MDAiLAogICAgICAgICAgICAgICAgICAiLW8iLCBkZWZhdWx0X2RldmljZSwgIi0tanVt
+cCIsICJSRVRVUk4iKQogICAgICAgICMgYWxsb3cgbXVsdGljYXN0IEJvbmpvdXIvbUROUwogICAg
+ICAgIGlwNHRhYmxlcygiLS1hcHBlbmQiLCBCSVRNQVNLX0NIQUlOLAogICAgICAgICAgICAgICAg
+ICAiLS1wcm90b2NvbCIsICJ1ZHAiLAogICAgICAgICAgICAgICAgICAiLS1kZXN0aW5hdGlvbiIs
+ICIyMjQuMC4wLjI1MSIsICItLWRwb3J0IiwgIjUzNTMiLAogICAgICAgICAgICAgICAgICAiLW8i
+LCBkZWZhdWx0X2RldmljZSwgIi0tanVtcCIsICJSRVRVUk4iKQogICAgaWYgbG9jYWxfbmV0d29y
+a19pcHY2OgogICAgICAgIGlwNnRhYmxlcygiLS1hcHBlbmQiLCBCSVRNQVNLX0NIQUlOLAogICAg
+ICAgICAgICAgICAgICAiLS1kZXN0aW5hdGlvbiIsIGxvY2FsX25ldHdvcmtfaXB2NiwgIi1vIiwg
+ZGVmYXVsdF9kZXZpY2UsCiAgICAgICAgICAgICAgICAgICItLWp1bXAiLCAiQUNDRVBUIikKICAg
+ICAgICAjIGFsbG93IG11bHRpY2FzdCBTaW1wbGUgU2VydmljZSBEaXNjb3ZlcnkgUHJvdG9jb2wK
+ICAgICAgICBpcDZ0YWJsZXMoIi0tYXBwZW5kIiwgQklUTUFTS19DSEFJTiwKICAgICAgICAgICAg
+ICAgICAgIi0tcHJvdG9jb2wiLCAidWRwIiwKICAgICAgICAgICAgICAgICAgIi0tZGVzdGluYXRp
+b24iLCAiRkYwNTo6QyIsICItLWRwb3J0IiwgIjE5MDAiLAogICAgICAgICAgICAgICAgICAiLW8i
+LCBkZWZhdWx0X2RldmljZSwgIi0tanVtcCIsICJSRVRVUk4iKQogICAgICAgICMgYWxsb3cgbXVs
+dGljYXN0IEJvbmpvdXIvbUROUwogICAgICAgIGlwNnRhYmxlcygiLS1hcHBlbmQiLCBCSVRNQVNL
+X0NIQUlOLAogICAgICAgICAgICAgICAgICAiLS1wcm90b2NvbCIsICJ1ZHAiLAogICAgICAgICAg
+ICAgICAgICAiLS1kZXN0aW5hdGlvbiIsICJGRjAyOjpGQiIsICItLWRwb3J0IiwgIjUzNTMiLAog
+ICAgICAgICAgICAgICAgICAiLW8iLCBkZWZhdWx0X2RldmljZSwgIi0tanVtcCIsICJSRVRVUk4i
+KQoKICAgICMgYWxsb3cgaXB2NCB0cmFmZmljIHRvIGdhdGV3YXlzCiAgICBmb3IgZ2F0ZXdheSBp
+biBnYXRld2F5czoKICAgICAgICBpcDR0YWJsZXMoIi0tYXBwZW5kIiwgQklUTUFTS19DSEFJTiwg
+Ii0tZGVzdGluYXRpb24iLCBnYXRld2F5LAogICAgICAgICAgICAgICAgICAiLW8iLCBkZWZhdWx0
+X2RldmljZSwgIi0tanVtcCIsICJBQ0NFUFQiKQoKICAgICMgbG9nIHJlamVjdGVkIHBhY2tldHMg
+dG8gc3lzbG9nCiAgICBpZiBERUJVRzoKICAgICAgICBpcHRhYmxlcygiLS1hcHBlbmQiLCBCSVRN
+QVNLX0NIQUlOLCAiLW8iLCBkZWZhdWx0X2RldmljZSwKICAgICAgICAgICAgICAgICAiLS1qdW1w
+IiwgIkxPRyIsICItLWxvZy1wcmVmaXgiLCAiaXB0YWJsZXMgZGVuaWVkOiAiLAogICAgICAgICAg
+ICAgICAgICItLWxvZy1sZXZlbCIsICI3IikKCiAgICAjIGZvciBub3csIGVuc3VyZSBhbGwgb3Ro
+ZXIgaXB2NiBwYWNrZXRzIGdldCByZWplY3RlZCAocmVnYXJkbGVzcyBvZgogICAgIyBkZXZpY2Up
+LiBub3Qgc3VyZSB3aHksIGJ1dCAiLXAgYW55IiBkb2Vzbid0IHdvcmsuCiAgICBpcDZ0YWJsZXMo
+Ii0tYXBwZW5kIiwgQklUTUFTS19DSEFJTiwgIi1wIiwgInRjcCIsICItLWp1bXAiLCAiUkVKRUNU
+IikKICAgIGlwNnRhYmxlcygiLS1hcHBlbmQiLCBCSVRNQVNLX0NIQUlOLCAiLXAiLCAidWRwIiwg
+Ii0tanVtcCIsICJSRUpFQ1QiKQoKICAgICMgcmVqZWN0IGFsbCBvdGhlciBpcHY0IHNlbnQgb3Zl
+ciB0aGUgZGVmYXVsdCBkZXZpY2UKICAgIGlwNHRhYmxlcygiLS1hcHBlbmQiLCBCSVRNQVNLX0NI
+QUlOLCAiLW8iLAogICAgICAgICAgICAgIGRlZmF1bHRfZGV2aWNlLCAiLS1qdW1wIiwgIlJFSkVD
+VCIpCgogICAgIyBPbiBRdWJlcyBPUywgYWRkIGFudGktbGVhayBydWxlcyBmb3IgcHJveHlWTSBx
+dWJlcy1maXJld2FsbC5zZXJ2aWNlCiAgICAjIE11c3Qgc3RheSBvbiAndG9wJyBvZiBjaGFpbiEK
+ICAgIGlmIFFVQkVTX1BST1hZIGFuZCBRVUJFU19WRVIgPj0gMyBhbmQgcnVuKCJncmVwIiwgXAog
+ICAgICAgICJpbnN0YWxsZWRcIGJ5XCAiICsgU0NSSVBULCBRVUJFU19GV19TQ1JJUFQsIGV4aXRj
+b2RlPVRydWUpICE9IDA6CiAgICAgICAgd2l0aCBvcGVuKFFVQkVTX0ZXX1NDUklQVCwgbW9kZT0i
+dyIpIGFzIHFmaWxlOgogICAgICAgICAgICBxZmlsZS53cml0ZSgiIyEvYmluL3NoXG4iKQogICAg
+ICAgICAgICBxZmlsZS53cml0ZSgiIyBBbnRpLWxlYWsgcnVsZXMgaW5zdGFsbGVkIGJ5ICIgKyBT
+Q1JJUFQgKyAiICIgXAogICAgICAgICAgICArIFZFUlNJT04gKyAiXG4iKQogICAgICAgICAgICBx
+ZmlsZS53cml0ZSgiaXB0YWJsZXMgLS1pbnNlcnQgRk9SV0FSRCAtaSBldGgwIC1qIERST1BcbiIp
+CiAgICAgICAgICAgIHFmaWxlLndyaXRlKCJpcHRhYmxlcyAtLWluc2VydCBGT1JXQVJEIC1vIGV0
+aDAgLWogRFJPUFxuIikKICAgICAgICAgICAgcWZpbGUud3JpdGUoImlwNnRhYmxlcyAtLWluc2Vy
+dCBGT1JXQVJEIC1pIGV0aDAgLWogRFJPUFxuIikKICAgICAgICAgICAgcWZpbGUud3JpdGUoImlw
+NnRhYmxlcyAtLWluc2VydCBGT1JXQVJEIC1vIGV0aDAgLWogRFJPUFxuIikKICAgICAgICAgICAg
+cWZpbGUud3JpdGUoImlwdGFibGVzIC0taW5zZXJ0IElOUFVUIC1pIHR1bisgLWogRFJPUFxuIikK
+ICAgICAgICAgICAgcWZpbGUud3JpdGUoImlwNnRhYmxlcyAtLWluc2VydCBJTlBVVCAtaSB0dW4r
+IC1qIERST1BcbiIpCiAgICAgICAgb3MuY2htb2QoUVVCRVNfRldfU0NSSVBULCBzdGF0LlNfSVJX
+WFUpCiAgICAgICAgaWYgbm90IG9zLnBhdGguZXhpc3RzKFFVQkVTX0lQSE9PSyk6CiAgICAgICAg
+ICAgIG9zLnN5bWxpbmsoUVVCRVNfRldfU0NSSVBULCBRVUJFU19JUEhPT0spCiAgICAgICAgaWYg
+UVVCRVNfVkVSID09IDQ6CiAgICAgICAgICAgIHJ1bihRVUJFU19GV19TQ1JJUFQpCiAgICAgICAg
+ZWxpZiBRVUJFU19WRVIgPT0gMzoKICAgICAgICAgICAgcnVuKCJzeXN0ZW1jdGwiLCAicmVzdGFy
+dCIsICJxdWJlcy1maXJld2FsbC5zZXJ2aWNlIikKCgpkZWYgZmlyZXdhbGxfc3RvcCgpOgogICAg
+IiIiCiAgICBTdG9wIHRoZSBmaXJld2FsbC4gQmVjYXVzZSB3ZSByZWFsbHkgcmVhbGx5IGFsd2F5
+cyB3YW50IHRoZSBmaXJld2FsbCB0bwogICAgYmUgc3RvcHBlZCBpZiBhdCBhbGwgcG9zc2libGUs
+IHRoaXMgZnVuY3Rpb24gaXMgY2F1dGlvdXMgYW5kIGNvbnRhaW5zIGEKICAgIGxvdCBvZiB0cnlz
+IGFuZCBleGNlcHRzLgoKICAgIElmIHRoZXJlIHdlcmUgYW55IHByb2JsZW1zLCB3ZSByYWlzZSBh
+biBleGNlcHRpb24gYXQgdGhlIGVuZC4gVGhpcyBhbGxvd3MKICAgIHRoZSBjYWxsaW5nIGNvZGUg
+dG8gcmV0cnkgc3RvcHBpbmcgdGhlIGZpcmV3YWxsLiBTdG9wcGluZyB0aGUgZmlyZXdhbGwKICAg
+IGNhbiBmYWlsIGlmIGlwdGFibGVzIGlzIGJlaW5nIHJ1biBieSBhbm90aGVyIHByb2Nlc3MgKG9u
+bHkgb25lIGlwdGFibGVzCiAgICBjb21tYW5kIGNhbiBiZSBydW4gYXQgYSB0aW1lKS4KICAgICIi
+IgogICAgb2sgPSBUcnVlCgogICAgIyAtdCBmaWx0ZXIgLUQgT1VUUFVUIC1qIGJpdG1hc2sKICAg
+IHRyeToKICAgICAgICBpcHRhYmxlcygiLS1kZWxldGUiLCAiT1VUUFVUIiwgIi0tanVtcCIsIEJJ
+VE1BU0tfQ0hBSU4sIHRocm93PVRydWUpCiAgICBleGNlcHQgc3VicHJvY2Vzcy5DYWxsZWRQcm9j
+ZXNzRXJyb3IgYXMgZXhjOgogICAgICAgIGRlYnVnKCJJTkZPOiBub3QgYWJsZSB0byByZW1vdmUg
+Yml0bWFzayBmaXJld2FsbCBmcm9tIE9VVFBVVCBjaGFpbiAiCiAgICAgICAgICAgICAgIihtYXli
+ZSBpdCBpcyBhbHJlYWR5IHJlbW92ZWQ/KSIsIGV4YykKICAgICAgICBvayA9IEZhbHNlCgogICAg
+IyAtdCBuYXQgLUQgT1VUUFVUIC1qIGJpdG1hc2sKICAgIHRyeToKICAgICAgICBpcDR0YWJsZXMo
+Ii10IiwgIm5hdCIsICItLWRlbGV0ZSIsICJPVVRQVVQiLAogICAgICAgICAgICAgICAgICAiLS1q
+dW1wIiwgQklUTUFTS19DSEFJTl9OQVRfT1VULCB0aHJvdz1UcnVlKQogICAgZXhjZXB0IHN1YnBy
+b2Nlc3MuQ2FsbGVkUHJvY2Vzc0Vycm9yIGFzIGV4YzoKICAgICAgICBkZWJ1ZygiSU5GTzogbm90
+IGFibGUgdG8gcmVtb3ZlIGJpdG1hc2sgZmlyZXdhbGwgZnJvbSBPVVRQVVQgY2hhaW4gIgogICAg
+ICAgICAgICAgICJpbiAnbmF0JyB0YWJsZSAobWF5YmUgaXQgaXMgYWxyZWFkeSByZW1vdmVkPyki
+LCBleGMpCiAgICAgICAgb2sgPSBGYWxzZQoKICAgICMgLXQgbmF0IC1EIFBPU1RST1VUSU5HIC1q
+IGJpdG1hc2tfcG9zdHJvdXRpbmcKICAgIHRyeToKICAgICAgICBpcDR0YWJsZXMoIi10IiwgIm5h
+dCIsICItLWRlbGV0ZSIsICJQT1NUUk9VVElORyIsCiAgICAgICAgICAgICAgICAgICItLWp1bXAi
+LCBCSVRNQVNLX0NIQUlOX05BVF9QT1NULCB0aHJvdz1UcnVlKQogICAgZXhjZXB0IHN1YnByb2Nl
+c3MuQ2FsbGVkUHJvY2Vzc0Vycm9yIGFzIGV4YzoKICAgICAgICBkZWJ1ZygiSU5GTzogbm90IGFi
+bGUgdG8gcmVtb3ZlIGJpdG1hc2sgZmlyZXdhbGwgZnJvbSBQT1NUUk9VVElORyAiCiAgICAgICAg
+ICAgICAgImNoYWluIGluICduYXQnIHRhYmxlIChtYXliZSBpdCBpcyBhbHJlYWR5IHJlbW92ZWQ/
+KSIsIGV4YykKICAgICAgICBvayA9IEZhbHNlCgogICAgIyAtdCBmaWx0ZXIgLS1kZWxldGUtY2hh
+aW4gYml0bWFzawogICAgdHJ5OgogICAgICAgIGlwNHRhYmxlcygiLS1mbHVzaCIsIEJJVE1BU0tf
+Q0hBSU4sIHRocm93PVRydWUpCiAgICAgICAgaXA0dGFibGVzKCItLWRlbGV0ZS1jaGFpbiIsIEJJ
+VE1BU0tfQ0hBSU4sIHRocm93PVRydWUpCiAgICBleGNlcHQgc3VicHJvY2Vzcy5DYWxsZWRQcm9j
+ZXNzRXJyb3IgYXMgZXhjOgogICAgICAgIGRlYnVnKCJJTkZPOiBub3QgYWJsZSB0byBmbHVzaCBh
+bmQgZGVsZXRlIGJpdG1hc2sgaXB2NCBmaXJld2FsbCAiCiAgICAgICAgICAgICAgImNoYWluICht
+YXliZSBpdCBpcyBhbHJlYWR5IGRlc3Ryb3llZD8pIiwgZXhjKQogICAgICAgIG9rID0gRmFsc2UK
+CiAgICAjIC10IG5hdCAtLWRlbGV0ZS1jaGFpbiBiaXRtYXNrCiAgICB0cnk6CiAgICAgICAgaXA0
+dGFibGVzKCItdCIsICJuYXQiLCAiLS1mbHVzaCIsIEJJVE1BU0tfQ0hBSU5fTkFUX09VVCwgdGhy
+b3c9VHJ1ZSkKICAgICAgICBpcDR0YWJsZXMoIi10IiwgIm5hdCIsICItLWRlbGV0ZS1jaGFpbiIs
+CiAgICAgICAgICAgICAgICAgIEJJVE1BU0tfQ0hBSU5fTkFUX09VVCwgdGhyb3c9VHJ1ZSkKICAg
+IGV4Y2VwdCBzdWJwcm9jZXNzLkNhbGxlZFByb2Nlc3NFcnJvciBhcyBleGM6CiAgICAgICAgZGVi
+dWcoIklORk86IG5vdCBhYmxlIHRvIGZsdXNoIGFuZCBkZWxldGUgYml0bWFzayBpcHY0IGZpcmV3
+YWxsICIKICAgICAgICAgICAgICAiY2hhaW4gaW4gJ25hdCcgdGFibGUgKG1heWJlIGl0IGlzIGFs
+cmVhZHkgZGVzdHJveWVkPykiLCBleGMpCiAgICAgICAgb2sgPSBGYWxzZQoKICAgICMgLXQgbmF0
+IC0tZGVsZXRlLWNoYWluIGJpdG1hc2tfcG9zdHJvdXRpbmcKICAgIHRyeToKICAgICAgICBpcDR0
+YWJsZXMoIi10IiwgIm5hdCIsICItLWZsdXNoIiwgQklUTUFTS19DSEFJTl9OQVRfUE9TVCwgdGhy
+b3c9VHJ1ZSkKICAgICAgICBpcDR0YWJsZXMoIi10IiwgIm5hdCIsICItLWRlbGV0ZS1jaGFpbiIs
+CiAgICAgICAgICAgICAgICAgIEJJVE1BU0tfQ0hBSU5fTkFUX1BPU1QsIHRocm93PVRydWUpCiAg
+ICBleGNlcHQgc3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3IgYXMgZXhjOgogICAgICAgIGRl
+YnVnKCJJTkZPOiBub3QgYWJsZSB0byBmbHVzaCBhbmQgZGVsZXRlIGJpdG1hc2sgaXB2NCBmaXJl
+d2FsbCAiCiAgICAgICAgICAgICAgImNoYWluIGluICduYXQnIHRhYmxlIChtYXliZSBpdCBpcyBh
+bHJlYWR5IGRlc3Ryb3llZD8pIiwgZXhjKQogICAgICAgIG9rID0gRmFsc2UKCiAgICAjIC10IGZp
+bHRlciAtLWRlbGV0ZS1jaGFpbiBiaXRtYXNrIChpcHY2KQogICAgdHJ5OgogICAgICAgIGlwNnRh
+YmxlcygiLS1mbHVzaCIsIEJJVE1BU0tfQ0hBSU4sIHRocm93PVRydWUpCiAgICAgICAgaXA2dGFi
+bGVzKCItLWRlbGV0ZS1jaGFpbiIsIEJJVE1BU0tfQ0hBSU4sIHRocm93PVRydWUpCiAgICBleGNl
+cHQgc3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJyb3IgYXMgZXhjOgogICAgICAgIGRlYnVnKCJJ
+TkZPOiBub3QgYWJsZSB0byBmbHVzaCBhbmQgZGVsZXRlIGJpdG1hc2sgaXB2NiBmaXJld2FsbCAi
+CiAgICAgICAgICAgICAgImNoYWluIChtYXliZSBpdCBpcyBhbHJlYWR5IGRlc3Ryb3llZD8pIiwg
+ZXhjKQogICAgICAgIG9rID0gRmFsc2UKCiAgICBpZiBub3QgKG9rIG9yIGlwdjRfY2hhaW5fZXhp
+c3RzIG9yIGlwdjZfY2hhaW5fZXhpc3RzKToKICAgICAgICByYWlzZSBFeGNlcHRpb24oImZpcmV3
+YWxsIG1pZ2h0IHN0aWxsIGJlIGxlZnQgdXAuICIKICAgICAgICAgICAgICAgICAgICAgICAgIlBs
+ZWFzZSB0cnkgYGZpcmV3YWxsIHN0b3BgIGFnYWluLiIpCgoKZGVmIGZ3X2VtYWlsX3N0YXJ0KGFy
+Z3MpOgogICAgIiIiCiAgICBCcmluZyB1cCB0aGUgZW1haWwgZmlyZXdhbGwuCgogICAgOnBhcmFt
+IGFyZ3M6IHRoZSB1c2VyIHVpZCBvZiB0aGUgYml0bWFzayBwcm9jZXNzCiAgICA6dHlwZSBhcmdz
+OiBsaXN0CiAgICAiIiIKICAgICMgYWRkIGN1c3RvbSBjaGFpbiAiYml0bWFza19lbWFpbCIgdG8g
+ZnJvbnQgb2YgSU5QVVQgY2hhaW4KICAgIGlmIG5vdCBpcHY0X2NoYWluX2V4aXN0cyhCSVRNQVNL
+X0NIQUlOX0VNQUlMKToKICAgICAgICBpcDR0YWJsZXMoIi0tbmV3LWNoYWluIiwgQklUTUFTS19D
+SEFJTl9FTUFJTCkKICAgIGlmIG5vdCBpcHY2X2NoYWluX2V4aXN0cyhCSVRNQVNLX0NIQUlOX0VN
+QUlMKToKICAgICAgICBpcDZ0YWJsZXMoIi0tbmV3LWNoYWluIiwgQklUTUFTS19DSEFJTl9FTUFJ
+TCkKICAgIGlwdGFibGVzKCItLWluc2VydCIsICJJTlBVVCIsICItLWp1bXAiLCBCSVRNQVNLX0NI
+QUlOX0VNQUlMKQoKICAgICMgYWRkIGN1c3RvbSBjaGFpbiAiYml0bWFza19lbWFpbF9vdXRwdXQi
+IHRvIGZyb250IG9mIE9VVFBVVCBjaGFpbgogICAgaWYgbm90IGlwdjRfY2hhaW5fZXhpc3RzKEJJ
+VE1BU0tfQ0hBSU5fRU1BSUxfT1VUKToKICAgICAgICBpcDR0YWJsZXMoIi0tbmV3LWNoYWluIiwg
+QklUTUFTS19DSEFJTl9FTUFJTF9PVVQpCiAgICBpZiBub3QgaXB2Nl9jaGFpbl9leGlzdHMoQklU
+TUFTS19DSEFJTl9FTUFJTF9PVVQpOgogICAgICAgIGlwNnRhYmxlcygiLS1uZXctY2hhaW4iLCBC
+SVRNQVNLX0NIQUlOX0VNQUlMX09VVCkKICAgIGlwdGFibGVzKCItLWluc2VydCIsICJPVVRQVVQi
+LCAiLS1qdW1wIiwgQklUTUFTS19DSEFJTl9FTUFJTF9PVVQpCgogICAgIyBEaXNhYmxlIHRoZSBh
+Y2Nlc3MgdG8gaW1hcCBhbmQgc210cCBmcm9tIG91dHNpZGUKICAgIGlwdGFibGVzKCItLWFwcGVu
+ZCIsIEJJVE1BU0tfQ0hBSU5fRU1BSUwsCiAgICAgICAgICAgICAiLS1pbi1pbnRlcmZhY2UiLCBM
+T0NBTF9JTlRFUkZBQ0UsICItLXByb3RvY29sIiwgInRjcCIsCiAgICAgICAgICAgICAiLS1kcG9y
+dCIsIElNQVBfUE9SVCwgIi0tanVtcCIsICJBQ0NFUFQiKQogICAgaXB0YWJsZXMoIi0tYXBwZW5k
+IiwgQklUTUFTS19DSEFJTl9FTUFJTCwKICAgICAgICAgICAgICItLWluLWludGVyZmFjZSIsIExP
+Q0FMX0lOVEVSRkFDRSwgIi0tcHJvdG9jb2wiLCAidGNwIiwKICAgICAgICAgICAgICItLWRwb3J0
+IiwgU01UUF9QT1JULCAiLS1qdW1wIiwgIkFDQ0VQVCIpCiAgICBpcHRhYmxlcygiLS1hcHBlbmQi
+LCBCSVRNQVNLX0NIQUlOX0VNQUlMLAogICAgICAgICAgICAgIi0tcHJvdG9jb2wiLCAidGNwIiwg
+Ii0tZHBvcnQiLCBJTUFQX1BPUlQsICItLWp1bXAiLCAiUkVKRUNUIikKICAgIGlwdGFibGVzKCIt
+LWFwcGVuZCIsIEJJVE1BU0tfQ0hBSU5fRU1BSUwsCiAgICAgICAgICAgICAiLS1wcm90b2NvbCIs
+ICJ0Y3AiLCAiLS1kcG9ydCIsIFNNVFBfUE9SVCwgIi0tanVtcCIsICJSRUpFQ1QiKQoKICAgIGlm
+IG5vdCBhcmdzIG9yIG5vdCBQQVJBTV9GT1JNQVRTWyJVSUQiXShhcmdzWzBdKToKICAgICAgICBy
+YWlzZSBFeGNlcHRpb24oIk5vIHVpZCBnaXZlbiIpCiAgICB1aWQgPSBhcmdzWzBdCgogICAgIyBP
+bmx5IHRoZSB1bml4ICd1aWQnIGhhdmUgYWNjZXNzIHRvIHRoZSBlbWFpbCBpbWFwIGFuZCBzbXRw
+IHBvcnRzCiAgICBpcHRhYmxlcygiLS1hcHBlbmQiLCBCSVRNQVNLX0NIQUlOX0VNQUlMX09VVCwK
+ICAgICAgICAgICAgICItLW91dC1pbnRlcmZhY2UiLCBMT0NBTF9JTlRFUkZBQ0UsCiAgICAgICAg
+ICAgICAiLS1tYXRjaCIsICJvd25lciIsICItLXVpZC1vd25lciIsIHVpZCwgIi0tcHJvdG9jb2wi
+LCAidGNwIiwKICAgICAgICAgICAgICItLWRwb3J0IiwgSU1BUF9QT1JULCAiLS1qdW1wIiwgIkFD
+Q0VQVCIpCiAgICBpcHRhYmxlcygiLS1hcHBlbmQiLCBCSVRNQVNLX0NIQUlOX0VNQUlMX09VVCwK
+ICAgICAgICAgICAgICItLW91dC1pbnRlcmZhY2UiLCBMT0NBTF9JTlRFUkZBQ0UsCiAgICAgICAg
+ICAgICAiLS1tYXRjaCIsICJvd25lciIsICItLXVpZC1vd25lciIsIHVpZCwgIi0tcHJvdG9jb2wi
+LCAidGNwIiwKICAgICAgICAgICAgICItLWRwb3J0IiwgU01UUF9QT1JULCAiLS1qdW1wIiwgIkFD
+Q0VQVCIpCiAgICBpcHRhYmxlcygiLS1hcHBlbmQiLCBCSVRNQVNLX0NIQUlOX0VNQUlMX09VVCwK
+ICAgICAgICAgICAgICItLW91dC1pbnRlcmZhY2UiLCBMT0NBTF9JTlRFUkZBQ0UsCiAgICAgICAg
+ICAgICAiLS1wcm90b2NvbCIsICJ0Y3AiLCAiLS1kcG9ydCIsIElNQVBfUE9SVCwgIi0tanVtcCIs
+ICJSRUpFQ1QiKQogICAgaXB0YWJsZXMoIi0tYXBwZW5kIiwgQklUTUFTS19DSEFJTl9FTUFJTF9P
+VVQsCiAgICAgICAgICAgICAiLS1vdXQtaW50ZXJmYWNlIiwgTE9DQUxfSU5URVJGQUNFLAogICAg
+ICAgICAgICAgIi0tcHJvdG9jb2wiLCAidGNwIiwgIi0tZHBvcnQiLCBTTVRQX1BPUlQsICItLWp1
+bXAiLCAiUkVKRUNUIikKCgpkZWYgZndfZW1haWxfc3RvcCgpOgogICAgIiIiCiAgICBTdG9wIHRo
+ZSBlbWFpbCBmaXJld2FsbC4KICAgICIiIgogICAgb2sgPSBUcnVlCgogICAgdHJ5OgogICAgICAg
+IGlwdGFibGVzKCItLWRlbGV0ZSIsICJJTlBVVCIsICItLWp1bXAiLCBCSVRNQVNLX0NIQUlOX0VN
+QUlMLAogICAgICAgICAgICAgICAgIHRocm93PVRydWUpCiAgICBleGNlcHQgc3VicHJvY2Vzcy5D
+YWxsZWRQcm9jZXNzRXJyb3IgYXMgZXhjOgogICAgICAgIGRlYnVnKCJJTkZPOiBub3QgYWJsZSB0
+byByZW1vdmUgYml0bWFzayBlbWFpbCBmaXJld2FsbCBmcm9tIElOUFVUICIKICAgICAgICAgICAg
+ICAiY2hhaW4gKG1heWJlIGl0IGlzIGFscmVhZHkgcmVtb3ZlZD8pIiwgZXhjKQogICAgICAgIG9r
+ID0gRmFsc2UKCiAgICB0cnk6CiAgICAgICAgaXB0YWJsZXMoIi0tZGVsZXRlIiwgIk9VVFBVVCIs
+ICItLWp1bXAiLCBCSVRNQVNLX0NIQUlOX0VNQUlMX09VVCwKICAgICAgICAgICAgICAgICB0aHJv
+dz1UcnVlKQogICAgZXhjZXB0IHN1YnByb2Nlc3MuQ2FsbGVkUHJvY2Vzc0Vycm9yIGFzIGV4YzoK
+ICAgICAgICBkZWJ1ZygiSU5GTzogbm90IGFibGUgdG8gcmVtb3ZlIGJpdG1hc2sgZW1haWwgZmly
+ZXdhbGwgZnJvbSBPVVRQVVQgIgogICAgICAgICAgICAgICJjaGFpbiAobWF5YmUgaXQgaXMgYWxy
+ZWFkeSByZW1vdmVkPykiLCBleGMpCiAgICAgICAgb2sgPSBGYWxzZQoKICAgIHRyeToKICAgICAg
+ICBpcDR0YWJsZXMoIi0tZmx1c2giLCBCSVRNQVNLX0NIQUlOX0VNQUlMLCB0aHJvdz1UcnVlKQog
+ICAgICAgIGlwNHRhYmxlcygiLS1kZWxldGUtY2hhaW4iLCBCSVRNQVNLX0NIQUlOX0VNQUlMLCB0
+aHJvdz1UcnVlKQogICAgZXhjZXB0IHN1YnByb2Nlc3MuQ2FsbGVkUHJvY2Vzc0Vycm9yIGFzIGV4
+YzoKICAgICAgICBkZWJ1ZygiSU5GTzogbm90IGFibGUgdG8gZmx1c2ggYW5kIGRlbGV0ZSBiaXRt
+YXNrIGlwdjQgZW1haWwgZmlyZXdhbGwgIgogICAgICAgICAgICAgICJjaGFpbiAobWF5YmUgaXQg
+aXMgYWxyZWFkeSBkZXN0cm95ZWQ/KSIsIGV4YykKICAgICAgICBvayA9IEZhbHNlCgogICAgdHJ5
+OgogICAgICAgIGlwNnRhYmxlcygiLS1mbHVzaCIsIEJJVE1BU0tfQ0hBSU5fRU1BSUwsIHRocm93
+PVRydWUpCiAgICAgICAgaXA2dGFibGVzKCItLWRlbGV0ZS1jaGFpbiIsIEJJVE1BU0tfQ0hBSU5f
+RU1BSUwsIHRocm93PVRydWUpCiAgICBleGNlcHQgc3VicHJvY2Vzcy5DYWxsZWRQcm9jZXNzRXJy
+b3IgYXMgZXhjOgogICAgICAgIGRlYnVnKCJJTkZPOiBub3QgYWJsZSB0byBmbHVzaCBhbmQgZGVs
+ZXRlIGJpdG1hc2sgaXB2NiBlbWFpbCBmaXJld2FsbCAiCiAgICAgICAgICAgICAgImNoYWluICht
+YXliZSBpdCBpcyBhbHJlYWR5IGRlc3Ryb3llZD8pIiwgZXhjKQogICAgICAgIG9rID0gRmFsc2UK
+CiAgICB0cnk6CiAgICAgICAgaXA0dGFibGVzKCItLWZsdXNoIiwgQklUTUFTS19DSEFJTl9FTUFJ
+TF9PVVQsIHRocm93PVRydWUpCiAgICAgICAgaXA0dGFibGVzKCItLWRlbGV0ZS1jaGFpbiIsIEJJ
+VE1BU0tfQ0hBSU5fRU1BSUxfT1VULCB0aHJvdz1UcnVlKQogICAgZXhjZXB0IHN1YnByb2Nlc3Mu
+Q2FsbGVkUHJvY2Vzc0Vycm9yIGFzIGV4YzoKICAgICAgICBkZWJ1ZygiSU5GTzogbm90IGFibGUg
+dG8gZmx1c2ggYW5kIGRlbGV0ZSBiaXRtYXNrIGlwdjQgZW1haWwgZmlyZXdhbGwgIgogICAgICAg
+ICAgICAgICJjaGFpbiAobWF5YmUgaXQgaXMgYWxyZWFkeSBkZXN0cm95ZWQ/KSIsIGV4YykKICAg
+ICAgICBvayA9IEZhbHNlCgogICAgdHJ5OgogICAgICAgIGlwNnRhYmxlcygiLS1mbHVzaCIsIEJJ
+VE1BU0tfQ0hBSU5fRU1BSUxfT1VULCB0aHJvdz1UcnVlKQogICAgICAgIGlwNnRhYmxlcygiLS1k
+ZWxldGUtY2hhaW4iLCBCSVRNQVNLX0NIQUlOX0VNQUlMX09VVCwgdGhyb3c9VHJ1ZSkKICAgIGV4
+Y2VwdCBzdWJwcm9jZXNzLkNhbGxlZFByb2Nlc3NFcnJvciBhcyBleGM6CiAgICAgICAgZGVidWco
+IklORk86IG5vdCBhYmxlIHRvIGZsdXNoIGFuZCBkZWxldGUgYml0bWFzayBpcHY2IGVtYWlsIGZp
+cmV3YWxsICIKICAgICAgICAgICAgICAiY2hhaW4gKG1heWJlIGl0IGlzIGFscmVhZHkgZGVzdHJv
+eWVkPykiLCBleGMpCiAgICAgICAgb2sgPSBGYWxzZQoKICAgIGlmIG5vdCAob2sgb3IgaXB2NF9j
+aGFpbl9leGlzdHMgb3IgaXB2Nl9jaGFpbl9leGlzdHMpOgogICAgICAgIHJhaXNlIEV4Y2VwdGlv
+bigiZW1haWwgZmlyZXdhbGwgbWlnaHQgc3RpbGwgYmUgbGVmdCB1cC4gIgogICAgICAgICAgICAg
+ICAgICAgICAgICAiUGxlYXNlIHRyeSBgZnctZW1haWwgc3RvcGAgYWdhaW4uIikKCgojCiMgTUFJ
+TgojCgoKZGVmIG1haW4oKToKICAgICIiIgogICAgRW50cnkgcG9pbnQgZm9yIGNtZGxpbmUgZXhl
+Y3V0aW9uLgogICAgIiIiCiAgICAjIFRPRE8gdXNlIGFyZ3BhcnNlIGluc3RlYWQuCgogICAgaWYg
+bGVuKHN5cy5hcmd2KSA+PSAyOgogICAgICAgIGNvbW1hbmQgPSAiXyIuam9pbihzeXMuYXJndlsx
+OjNdKQogICAgICAgIGFyZ3MgPSBzeXMuYXJndlszOl0KCiAgICAgICAgaXNfcmVzdGFydCA9IEZh
+bHNlCiAgICAgICAgaWYgYXJncyBhbmQgYXJnc1swXSA9PSAicmVzdGFydCI6CiAgICAgICAgICAg
+IGlzX3Jlc3RhcnQgPSBUcnVlCiAgICAgICAgICAgIGFyZ3MucmVtb3ZlKCdyZXN0YXJ0JykKCiAg
+ICAgICAgaWYgY29tbWFuZCA9PSAidmVyc2lvbiI6CiAgICAgICAgICAgIHByaW50KFZFUlNJT04p
+CiAgICAgICAgICAgIGV4aXQoMCkKCiAgICAgICAgaWYgb3MuZ2V0dWlkKCkgIT0gMDoKICAgICAg
+ICAgICAgYmFpbCgiRVJST1I6IG11c3QgYmUgcnVuIGFzIHJvb3QiKQoKICAgICAgICBpZiBjb21t
+YW5kID09ICJvcGVudnBuX3N0YXJ0IjoKICAgICAgICAgICAgb3BlbnZwbl9zdGFydChhcmdzKQoK
+ICAgICAgICBlbGlmIGNvbW1hbmQgPT0gIm9wZW52cG5fc3RvcCI6CiAgICAgICAgICAgIG9wZW52
+cG5fc3RvcChhcmdzKQoKICAgICAgICBlbGlmIGNvbW1hbmQgPT0gImZpcmV3YWxsX3N0YXJ0IjoK
+ICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgZmlyZXdhbGxfc3RhcnQoYXJncykKICAg
+ICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBleDoKICAgICAgICAgICAgICAgIGlmIG5vdCBp
+c19yZXN0YXJ0OgogICAgICAgICAgICAgICAgICAgIGZpcmV3YWxsX3N0b3AoKQogICAgICAgICAg
+ICAgICAgYmFpbCgiRVJST1I6IGNvdWxkIG5vdCBzdGFydCBmaXJld2FsbCIsIGV4KQoKICAgICAg
+ICBlbGlmIGNvbW1hbmQgPT0gImZpcmV3YWxsX3N0b3AiOgogICAgICAgICAgICB0cnk6CiAgICAg
+ICAgICAgICAgICBmaXJld2FsbF9zdG9wKCkKICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBh
+cyBleDoKICAgICAgICAgICAgICAgIGJhaWwoIkVSUk9SOiBjb3VsZCBub3Qgc3RvcCBmaXJld2Fs
+bCIsIGV4KQoKICAgICAgICBlbGlmIGNvbW1hbmQgPT0gImZpcmV3YWxsX2lzdXAiOgogICAgICAg
+ICAgICBpZiBpcHY0X2NoYWluX2V4aXN0cyhCSVRNQVNLX0NIQUlOKToKICAgICAgICAgICAgICAg
+ICMgdG9vIHZlcmJvc2Ugc2luY2UgYml0bWFzayBwb2xscyB0aGlzCiAgICAgICAgICAgICAgICBw
+YXNzCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBiYWlsKCJJTkZPOiBiaXRtYXNr
+IGZpcmV3YWxsIGlzIGRvd24iKQoKICAgICAgICBlbGlmIGNvbW1hbmQgPT0gImZ3LWVtYWlsX3N0
+YXJ0IjoKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgZndfZW1haWxfc3RhcnQoYXJn
+cykKICAgICAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBleDoKICAgICAgICAgICAgICAgIGlm
+IG5vdCBpc19yZXN0YXJ0OgogICAgICAgICAgICAgICAgICAgIGZ3X2VtYWlsX3N0b3AoKQogICAg
+ICAgICAgICAgICAgYmFpbCgiRVJST1I6IGNvdWxkIG5vdCBzdGFydCBlbWFpbCBmaXJld2FsbCIs
+IGV4KQoKICAgICAgICBlbGlmIGNvbW1hbmQgPT0gImZ3LWVtYWlsX3N0b3AiOgogICAgICAgICAg
+ICB0cnk6CiAgICAgICAgICAgICAgICBmd19lbWFpbF9zdG9wKCkKICAgICAgICAgICAgZXhjZXB0
+IEV4Y2VwdGlvbiBhcyBleDoKICAgICAgICAgICAgICAgIGJhaWwoIkVSUk9SOiBjb3VsZCBub3Qg
+c3RvcCBlbWFpbCBmaXJld2FsbCIsIGV4KQoKICAgICAgICBlbGlmIGNvbW1hbmQgPT0gImZ3LWVt
+YWlsX2lzdXAiOgogICAgICAgICAgICBpZiBpcHY0X2NoYWluX2V4aXN0cyhCSVRNQVNLX0NIQUlO
+X0VNQUlMKToKICAgICAgICAgICAgICAgIGxvZygiJXM6IElORk86IGJpdG1hc2sgZW1haWwgZmly
+ZXdhbGwgaXMgdXAiICUgKFNDUklQVCwpKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAg
+ICAgYmFpbCgiSU5GTzogYml0bWFzayBlbWFpbCBmaXJld2FsbCBpcyBkb3duIikKCiAgICAgICAg
+ZWxzZToKICAgICAgICAgICAgYmFpbCgiRVJST1I6IE5vIHN1Y2ggY29tbWFuZCIpCiAgICBlbHNl
+OgogICAgICAgIGJhaWwoIkVSUk9SOiBObyBzdWNoIGNvbW1hbmQiKQoKCmlmIF9fbmFtZV9fID09
+ICJfX21haW5fXyI6CiAgICBkZWJ1ZygiICIuam9pbihzeXMuYXJndikpCiAgICBtYWluKCkKICAg
+IGV4aXQoMCkK
+"""
+POLKIT = """PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBvbGljeWNv
+bmZpZyBQVUJMSUMKICItLy9mcmVlZGVza3RvcC8vRFREIFBvbGljeUtpdCBQb2xpY3kgQ29uZmln
+dXJhdGlvbiAxLjAvL0VOIgogImh0dHA6Ly93d3cuZnJlZWRlc2t0b3Aub3JnL3N0YW5kYXJkcy9Q
+b2xpY3lLaXQvMS9wb2xpY3ljb25maWcuZHRkIj4KPHBvbGljeWNvbmZpZz4KCiAgPHZlbmRvcj5M
+RUFQIFByb2plY3Q8L3ZlbmRvcj4KICA8dmVuZG9yX3VybD5odHRwOi8vbGVhcC5zZS88L3ZlbmRv
+cl91cmw+CgogIDxhY3Rpb24gaWQ9InNlLmxlYXAuYml0bWFzay5idW5kbGUucG9saWN5Ij4KICAg
+IDxkZXNjcmlwdGlvbj5SdW5zIGJpdG1hc2sgaGVscGVyIHRvIGxhdW5jaCBmaXJld2FsbCBhbmQg
+b3BlbnZwbiAoYnVuZGxlIHZlcnNpb24pPC9kZXNjcmlwdGlvbj4KICAgIDxkZXNjcmlwdGlvbiB4
+bWw6bGFuZz0iZXMiPkVqZWN1dGEgZWwgYXNpc3RlbnRlIGRlIGJpdG1hc2sgcGFyYSBsYW56YXIg
+ZWwgZmlyZXdhbGwgeSBvcGVudnBuICh2ZXJzaW9uIGJ1bmRsZSk8L2Rlc2NyaXB0aW9uPgogICAg
+PG1lc3NhZ2U+Qml0bWFzayBuZWVkcyB0aGF0IHlvdSBhdXRoZW50aWNhdGUgdG8gc3RhcnQ8L21l
+c3NhZ2U+CiAgICA8bWVzc2FnZSB4bWw6bGFuZz0iZXMiPkJpdG1hc2sgbmVjZXNpdGEgYXV0b3Jp
+emFjaW9uIHBhcmEgY29tZW56YXI8L21lc3NhZ2U+CiAgICA8aWNvbl9uYW1lPnBhY2thZ2UteC1n
+ZW5lcmljPC9pY29uX25hbWU+IAogICAgPGRlZmF1bHRzPgogICAgICA8YWxsb3dfYW55Pnllczwv
+YWxsb3dfYW55PgogICAgICA8YWxsb3dfaW5hY3RpdmU+eWVzPC9hbGxvd19pbmFjdGl2ZT4KICAg
+ICAgPGFsbG93X2FjdGl2ZT55ZXM8L2FsbG93X2FjdGl2ZT4KICAgIDwvZGVmYXVsdHM+CiAgICA8
+YW5ub3RhdGUga2V5PSJvcmcuZnJlZWRlc2t0b3AucG9saWN5a2l0LmV4ZWMucGF0aCI+L3Vzci9s
+b2NhbC9zYmluL2JpdG1hc2stcm9vdDwvYW5ub3RhdGU+CiAgPC9hY3Rpb24+CjwvcG9saWN5Y29u
+ZmlnPgo=
+"""
+BMROOT_DEST = "/usr/local/sbin/bitmask-root"
+with open(BMROOT_DEST, "w") as bmroot:
+ lines = str(decode(BMROOT)).split("\n")
+ for line in lines:
+ bmroot.write(line + "\n")
+with open('/usr/share/polkit-1/actions/se.leap.bitmask.bundle.policy', 'w') as polkit:
+ lines = str(decode(POLKIT)).split("\n")
+ for line in lines:
+ polkit.write(line + "\n")
+subprocess.Popen(["chmod", "+x", BMROOT_DEST])
diff --git a/pkg/riseupvpn/snap/hooks/remove b/pkg/riseupvpn/snap/hooks/remove
new file mode 100755
index 00000000..c7442a26
--- /dev/null
+++ b/pkg/riseupvpn/snap/hooks/remove
@@ -0,0 +1,7 @@
+#!/bin/sh
+set -e
+
+echo "Executing remove hook for RiseupVPN"
+rm "/usr/local/sbin/bitmask-root"
+rm "/usr/share/polkit-1/actions/se.leap.bitmask.bundle.policy"
+echo "done"
diff --git a/pkg/riseupvpn/snap/snapcraft.yaml b/pkg/riseupvpn/snap/snapcraft.yaml
index 024bdf3b..f358615b 100644
--- a/pkg/riseupvpn/snap/snapcraft.yaml
+++ b/pkg/riseupvpn/snap/snapcraft.yaml
@@ -8,8 +8,8 @@ description: |
Just click on it. And don't forget to donate.
grade: devel # must be 'stable' to release into candidate/stable channels
-#confinement: devmode #classic # use 'strict' once you have the right plugs and slots
confinement: classic
+icon: snap/gui/riseupvpn.svg
parts:
@@ -17,7 +17,7 @@ parts:
plugin: python
python-version: python2
source-branch: snap
- # XXX change to leap/master
+ # XXX change to leap/master when merged
source: https://0xacab.org/kali/bitmask-dev.git
requirements: pkg/requirements-vpn.pip
stage-packages:
@@ -31,11 +31,13 @@ parts:
plugin: nil
stage-packages:
- openvpn
+ # TODO copy openvpn to /usr/local/sbin
bitmask-systray:
plugin: go
source: https://0xacab.org/leap/bitmask-systray.git
build-packages:
- pkg-config
+ - patchelf
- libzmq5
- libzmq3-dev
- libsodium-dev
@@ -45,16 +47,20 @@ parts:
- libzmq5
- libsodium18
- libappindicator3-1
+ install: |
+ TRIPLET_PATH="$SNAPCRAFT_PART_INSTALL/usr/lib/$(gcc -print-multiarch)"
+ LIBZMQ=$(readlink -n $TRIPLET_PATH/libzmq.so.5)
+ LIBSOD=$(readlink -n $TRIPLET_PATH/libsodium.so.18)
+ ln -s "../usr/lib/$(gcc -print-multiarch)/$LIBZMQ" $SNAPCRAFT_PART_INSTALL/bin/libzmq.so.5
+ ln -s "../usr/lib/$(gcc -print-multiarch)/$LIBSOD" $SNAPCRAFT_PART_INSTALL/bin/libsodium.so.18
+ patchelf --set-rpath /snap/riseup-vpn/current/bin/ $SNAPCRAFT_PART_INSTALL/bin/bitmask-systray.git
desktop-gtk3:
prime: ['*']
apps:
bitmask-systray:
command: ./bin/bitmask-systray.git
- plugs: [x11, network]
launcher:
command: ./bin/bitmask_anonvpn
- plugs: [x11, network]
bitmaskd:
command: ./bin/bitmaskd
- plugs: [network]