openship 0.4.8 → 0.6.0
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 +27 -1
- package/dist/bare-FSUAM5V5.js +23 -0
- package/dist/{bowser-O3AEA6AN.js → bowser-HNOTPGJO.js} +2 -2
- package/dist/{chunk-5MZ624VX.js → chunk-2GWYYHOR.js} +1 -1
- package/dist/chunk-3FYIXVX5.js +8051 -0
- package/dist/{chunk-ILFETZOM.js → chunk-3LDWWY7U.js} +21 -1
- package/dist/{chunk-W73X43R7.js → chunk-3NQQXMDR.js} +3 -3
- package/dist/{chunk-OWED2GRM.js → chunk-42WQABXM.js} +2 -2
- package/dist/{chunk-TYVME3XD.js → chunk-6FH4AXVY.js} +20 -3
- package/dist/{chunk-OXWDY22G.js → chunk-6ODUBKUB.js} +3 -3
- package/dist/{chunk-DYPH4HCI.js → chunk-AO252K7Z.js} +1 -1
- package/dist/{chunk-XPPZ7B2J.js → chunk-B3CE2OMR.js} +14 -12
- package/dist/{chunk-IXCHURVK.js → chunk-DOD2BXHQ.js} +4 -4
- package/dist/{chunk-VWPEKOH6.js → chunk-DRK3MEDS.js} +3 -3
- package/dist/{chunk-V6AN6XLZ.js → chunk-EMXI4UCU.js} +125 -47
- package/dist/{chunk-GKHUSZCD.js → chunk-EP2TNALB.js} +2 -2
- package/dist/{chunk-SLTYVHU7.js → chunk-GUQ3QCJ7.js} +942 -519
- package/dist/chunk-I3DPMTSF.js +29 -0
- package/dist/{chunk-L2VOGB2X.js → chunk-IW2UKBVF.js} +3 -3
- package/dist/{chunk-VDMQJHPI.js → chunk-IXM5245F.js} +228 -13
- package/dist/{chunk-MZ2WEHHY.js → chunk-JIMUYEKN.js} +4 -4
- package/dist/chunk-OGY63DGD.js +705 -0
- package/dist/{chunk-O6ZZF52V.js → chunk-ONKEYSMY.js} +2 -2
- package/dist/{chunk-6APULWSU.js → chunk-OTLSJYAC.js} +1744 -118
- package/dist/{chunk-EI575GHN.js → chunk-PDW4L3NV.js} +3 -3
- package/dist/{chunk-5NYUCONN.js → chunk-PSZSKEPA.js} +33 -51
- package/dist/{chunk-KI2EY3WB.js → chunk-PXKCZB2I.js} +1 -1
- package/dist/{chunk-FXTBHTWY.js → chunk-QEH4QUBX.js} +649 -85
- package/dist/{chunk-6APIPIJY.js → chunk-QWHBRY2K.js} +5 -5
- package/dist/{chunk-6B5YCFFV.js → chunk-RVER2EOO.js} +5 -5
- package/dist/{chunk-Q2CIRAOK.js → chunk-RXQBD4ZY.js} +1 -1
- package/dist/{chunk-TGIINPVM.js → chunk-TWJCLD4W.js} +60 -10
- package/dist/{chunk-4Z5QO7N6.js → chunk-VDDMADOF.js} +3 -3
- package/dist/{chunk-BBHX7T4R.js → chunk-VE2YOK4I.js} +991 -254
- package/dist/{chunk-2D3I5G6P.js → chunk-VZ2ZHPS2.js} +73 -43
- package/dist/{chunk-AVIB7CT7.js → chunk-WNWQBB7F.js} +2 -2
- package/dist/{chunk-FRNAR33O.js → chunk-XZYFZ6A5.js} +3 -3
- package/dist/{chunk-RPHRPFEH.js → chunk-ZCFVHA25.js} +1 -1
- package/dist/{chunk-FPRHYBY2.js → chunk-ZFJXPCQP.js} +1 -1
- package/dist/{chunk-JYGD5WSN.js → chunk-ZWLDLTJP.js} +1 -1
- package/dist/cloud-E5M6VMCG.js +31 -0
- package/dist/{cloud-7QYOGF7F.js → cloud-KRTZ2IL5.js} +3 -3
- package/dist/{detect-AZLOHUFX.js → detect-ALF4GXRX.js} +7 -8
- package/dist/{dist-IQJ6H6UZ.js → dist-BM6NPWIH.js} +3 -3
- package/dist/{dist-es-X3B5QYKB.js → dist-es-2YRDXMUU.js} +6 -6
- package/dist/{dist-es-OSNJBLXB.js → dist-es-CCVZEFRZ.js} +5 -5
- package/dist/{dist-es-VNKHQVIB.js → dist-es-IOH6G4GM.js} +4 -4
- package/dist/{dist-es-RYHIPOTN.js → dist-es-JGBPABJI.js} +14 -14
- package/dist/{dist-es-JSTDUS7Q.js → dist-es-KWSMDPIP.js} +6 -6
- package/dist/{dist-es-5DY7K32L.js → dist-es-UYDDOVZ3.js} +6 -6
- package/dist/{dist-es-WV4AMOII.js → dist-es-XUOR4NQN.js} +8 -8
- package/dist/docker-QECQJ5P4.js +32 -0
- package/dist/docker-edge-executor-62N64MGS.js +17 -0
- package/dist/edge-import-CQWHN2Q3.js +48 -0
- package/dist/ensure-container-edge-MJVXJQG5.js +32 -0
- package/dist/{event-streams-EHRAKL75.js → event-streams-TR4GAC53.js} +4 -4
- package/dist/{executor-XJ6RP4Q2.js → executor-JELARVKC.js} +8 -8
- package/dist/index.js +1209 -560
- package/dist/{loadSso-46FQRIZS.js → loadSso-UGF4JMRK.js} +10 -10
- package/dist/{local-executor-V7U5VOZW.js → local-executor-WOFZD72X.js} +4 -4
- package/dist/nginx-AXGNWRKZ.js +31 -0
- package/dist/node-entry.js +4 -0
- package/dist/{noop-FMMFG2EZ.js → noop-NJ72F46T.js} +3 -3
- package/dist/openresty-lua-IE4P5YQX.js +81 -0
- package/dist/server/index.js +116248 -94749
- package/dist/server/lua/geo_country.lua +31 -6
- package/dist/server/lua/maxminddb.lua +403 -0
- package/dist/server/lua/mgmt_api.lua +431 -68
- package/dist/server/lua/pipe_log.lua +10 -4
- package/dist/server/lua/site_logger.lua +220 -12
- package/dist/server/migrations/0073_project_volumes_object_storage.sql +3 -0
- package/dist/server/migrations/0074_project_compose_path.sql +1 -0
- package/dist/server/migrations/0075_service_command_argv.sql +1 -0
- package/dist/server/migrations/0076_rollback_retention.sql +17 -0
- package/dist/server/migrations/0077_domain_redirect.sql +13 -0
- package/dist/server/migrations/0078_grant_source_scope.sql +30 -0
- package/dist/server/migrations/0079_project_readiness.sql +18 -0
- package/dist/server/migrations/0080_deployment_error_classification.sql +26 -0
- package/dist/server/migrations/0081_project_readiness_repair.sql +34 -0
- package/dist/server/migrations/0082_edge_target_verification.sql +39 -0
- package/dist/server/migrations/0083_service_incident.sql +84 -0
- package/dist/server/migrations/0084_analytics_daily_rollup.sql +72 -0
- package/dist/server/migrations/0085_resource_usage.sql +68 -0
- package/dist/server/migrations/0086_remote_infra_updates.sql +41 -0
- package/dist/server/migrations/0087_server_container_version_columns.sql +17 -0
- package/dist/server/migrations/0088_audit_source_and_settings.sql +27 -0
- package/dist/server/migrations/0089_auto_scan_infra.sql +7 -0
- package/dist/server/migrations/0090_project_collect_paths.sql +18 -0
- package/dist/server/migrations/0091_project_server_id.sql +26 -0
- package/dist/server/migrations/0092_project_internal_alias.sql +13 -0
- package/dist/server/migrations/0093_service_incident_org_index.sql +13 -0
- package/dist/server/migrations/0094_backup_restore_meta.sql +15 -0
- package/dist/server/migrations/0095_backup_restore_cancel.sql +19 -0
- package/dist/server/migrations/0096_backup_policy_retention_defaults.sql +20 -0
- package/dist/server/migrations/0097_update_status_upstream_only.sql +35 -0
- package/dist/server/migrations/meta/_journal.json +175 -0
- package/dist/setup-FA4PW4NU.js +21 -0
- package/dist/{signin-ITOPKKUB.js → signin-3M3UPB6K.js} +10 -10
- package/dist/{sso-oidc-NON2PD7Y.js → sso-oidc-3VDIYOEJ.js} +10 -10
- package/dist/{sts-HHFFSAY2.js → sts-B3WIYLXR.js} +9 -9
- package/package.json +6 -3
- package/dist/bare-JY5Y5ELU.js +0 -23
- package/dist/chunk-SJIFLLX4.js +0 -2931
- package/dist/chunk-VFINNTUL.js +0 -362
- package/dist/cloud-KYWY3RP4.js +0 -30
- package/dist/docker-LODK5Y2S.js +0 -16
- package/dist/docker-edge-executor-VHW3JPJS.js +0 -13
- package/dist/edge-import-ABUDKKJI.js +0 -45
- package/dist/ensure-container-edge-SW6HENSG.js +0 -31
- package/dist/nginx-3L4SIBJA.js +0 -24
- package/dist/openresty-lua-4WLGDSER.js +0 -42
- package/dist/setup-NU6T2PDU.js +0 -20
|
@@ -0,0 +1,705 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
":" //# ; exec "$(command -v node || command -v bun)" "$0" "$@"
|
|
3
|
+
import { createRequire as __ospCreateRequire } from "node:module";
|
|
4
|
+
const require = __ospCreateRequire(import.meta.url);
|
|
5
|
+
import {
|
|
6
|
+
sq
|
|
7
|
+
} from "./chunk-ZFJXPCQP.js";
|
|
8
|
+
import {
|
|
9
|
+
safeErrorMessage
|
|
10
|
+
} from "./chunk-OTLSJYAC.js";
|
|
11
|
+
|
|
12
|
+
// ../../packages/adapters/src/infra/openresty-lua.ts
|
|
13
|
+
import { createHash, randomBytes } from "crypto";
|
|
14
|
+
import { existsSync, readFileSync } from "fs";
|
|
15
|
+
import { dirname, join } from "path";
|
|
16
|
+
import { fileURLToPath } from "url";
|
|
17
|
+
|
|
18
|
+
// ../../packages/adapters/src/infra/lua-embedded.ts
|
|
19
|
+
var EMBEDDED_LUA = {
|
|
20
|
+
"geo_country.lua": "LS0gZ2VvX2NvdW50cnkubHVhCi0tIE1heE1pbmQgR2VvTGl0ZTItQ291bnRyeSBsb29rdXAgd2l0aCBwZXItd29ya2VyIExSVSBjYWNoZS4KLS0KLS0gREIgYW5kIGNhY2hlIGFyZSBwZXItd29ya2VyIG9ubHk6IG9uZSBsb2FkIHBlciB3b3JrZXIsIHNoYXJlZCBieSBhbGwKLS0gcmVxdWVzdHMuIE5vIHJlbG9hZCBwZXIgc3RyZWFtIG9yIHBlciByZXF1ZXN0LgotLQotLSBEZXBlbmRlbmNpZXM6Ci0tICAgTHVhIGJpbmRpbmcg4oCUIGBvcGVuc2hpcC5tYXhtaW5kZGJgLCB2ZW5kb3JlZCBiZXNpZGUgdGhpcyBmaWxlLiBGYWxscyBiYWNrIHRvCi0tICAgICAgICAgICAgICAgICBgcmVzdHkubWF4bWluZGRiYCBmb3IgYSBiYXJlIGJveCB0aGF0IGhhcyB0aGUgb3BtIHBhY2thZ2UKLS0gICAgICAgICAgICAgICAgIGluc3RhbGxlZCBmcm9tIGJlZm9yZSB3ZSB2ZW5kb3JlZCBpdC4KLS0gICBDIGxpYnJhcnkgICDigJQgbGlibWF4bWluZGRiLnNvIChgYXBrIGFkZCBsaWJtYXhtaW5kZGJgIGluIGFwcHMvZWRnZS9Eb2NrZXJmaWxlOwotLSAgICAgICAgICAgICAgICAgaW5zdGFsbEdlb0RlcHMoKSBmb3IgYmFyZSBib3hlcykKLS0gICBEYXRhYmFzZSAgICDigJQgL3Vzci9zaGFyZS9HZW9JUC9HZW9MaXRlMi1Db3VudHJ5Lm1tZGIgKGJha2VkIGludG8gdGhlIGVkZ2UKLS0gICAgICAgICAgICAgICAgIGltYWdlIGZyb20gYXBwcy9hcGkvYXNzZXRzL2dlb2lwLCBzbyBubyBydW50aW1lIGRvd25sb2FkKQotLQotLSBGYWxscyBiYWNrIGdyYWNlZnVsbHkgLSBpZiB0aGUgbGlicmFyeSBvciBkYXRhYmFzZSBpcyBtaXNzaW5nLAotLSBnZXRfY291bnRyeV9jb2RlKCkgcmV0dXJucyBuaWwuICBCb3RoIHNpdGVfbG9nZ2VyLmx1YSBhbmQgcGlwZV9sb2cubHVhCi0tIHdyYXAgdGhpcyBtb2R1bGUgaW4gcGNhbGwocmVxdWlyZSwgLi4uKSBzbyBhIG1pc3NpbmcgREIgbmV2ZXIgY3Jhc2hlcwotLSB0aGUgcmVxdWVzdCBwaXBlbGluZS4gbWdtdF9hcGkgYEdFVCAvc3RhdHVzYCByZXBvcnRzIHdoZXRoZXIgZ2VvIGFjdHVhbGx5Ci0tIHJlc29sdmVkLCBzbyBhIHNpbGVudGx5LWRhcmsgZWRnZSBpcyB2aXNpYmxlIGluc3RlYWQgb2YganVzdCB5aWVsZGluZyBhbgotLSBlbXB0eSBjb3VudHJ5IG1hcC4KCmxvY2FsIF9NID0ge30KCmxvY2FsIERCX1BBVEggPSAiL3Vzci9zaGFyZS9HZW9JUC9HZW9MaXRlMi1Db3VudHJ5Lm1tZGIiCgotLSBWZW5kb3JlZCBjb3B5IGZpcnN0LCBvcG0taW5zdGFsbGVkIGNvcHkgc2Vjb25kLiBgZmZpLmxvYWQoJ2xpYm1heG1pbmRkYicpYAotLSBydW5zIGF0IHJlcXVpcmUgdGltZSBpbiBib3RoLCBzbyBhIG1pc3NpbmcgLnNvIHN1cmZhY2VzIGhlcmUgYXMgbW1kYl9vaz1mYWxzZS4KbG9jYWwgbW1kYl9vaywgbWF4bWluZCA9IHBjYWxsKHJlcXVpcmUsICJvcGVuc2hpcC5tYXhtaW5kZGIiKQppZiBub3QgbW1kYl9vayB0aGVuCiAgICBtbWRiX29rLCBtYXhtaW5kID0gcGNhbGwocmVxdWlyZSwgInJlc3R5Lm1heG1pbmRkYiIpCmVuZApsb2NhbCBscnVjYWNoZV9vaywgbHJ1Y2FjaGUgPSBwY2FsbChyZXF1aXJlLCAicmVzdHkubHJ1Y2FjaGUiKQoKbG9jYWwgY2FjaGUgICAgICAgICAgICAtLSBvbmUgTFJVIHBlciB3b3JrZXIKbG9jYWwgZ2VvX2luaXR0ZWQgPSBmYWxzZSAgLS0gREIgb3BlbmVkIG9uY2UgcGVyIHdvcmtlciBvbiBmaXJzdCBsb29rdXAKLS0gV2h5IGdlbyBpcyBvZmYsIGZvciBgR0VUIC9zdGF0dXNgLiBEaXN0aW5ndWlzaGluZyAibm8gRkZJIGJpbmRpbmcgLyBubyAuc28iCi0tIGZyb20gIm5vIGRhdGFiYXNlIiBtYXR0ZXJzOiB0aGV5IG5lZWQgZGlmZmVyZW50IGZpeGVzLCBhbmQgYm90aCB1c2VkIHRvCi0tIHByZXNlbnQgaWRlbnRpY2FsbHkgYXMgYW4gZW1wdHkgY291bnRyeSBtYXAuCmxvY2FsIGdlb19yZWFzb24gPSAibm90IGluaXRpYWxpc2VkIgoKLS0gSW5pdCBNYXhNaW5kIG9uY2UgcGVyIHdvcmtlcjsgc3Vic2VxdWVudCBsb29rdXBzIChhbnkgc3RyZWFtKSByZXVzZS4KbG9jYWwgZnVuY3Rpb24gZW5zdXJlX2dlb19pbml0KCkKICAgIGlmIGdlb19pbml0dGVkIHRoZW4KICAgICAgICByZXR1cm4gdHJ1ZQogICAgZW5kCiAgICBpZiBub3QgbW1kYl9vayBvciBub3QgbWF4bWluZCB0aGVuCiAgICAgICAgZ2VvX3JlYXNvbiA9ICJtYXhtaW5kZGIgRkZJIGJpbmRpbmcgdW5hdmFpbGFibGUgKGxpYm1heG1pbmRkYi5zbyBtaXNzaW5nPykiCiAgICAgICAgcmV0dXJuIGZhbHNlCiAgICBlbmQKICAgIGxvY2FsIG9rLCBlcnIgPSBtYXhtaW5kLmluaXQoREJfUEFUSCkKICAgIGlmIG5vdCBvayB0aGVuCiAgICAgICAgZ2VvX3JlYXNvbiA9ICJkYXRhYmFzZSB1bnJlYWRhYmxlIGF0ICIgLi4gREJfUEFUSCAuLiAiOiAiIC4uIChlcnIgb3IgInVua25vd24iKQogICAgICAgIG5neC5sb2cobmd4LldBUk4sCiAgICAgICAgICAgICJbZ2VvX2NvdW50cnldIEdlb0xpdGUyIGRhdGFiYXNlIG5vdCBmb3VuZCBhdCAiIC4uIERCX1BBVEggLi4KICAgICAgICAgICAgIiAtIGdlbyBsb29rdXBzIGRpc2FibGVkOiAiIC4uIChlcnIgb3IgInVua25vd24iKSkKICAgICAgICByZXR1cm4gZmFsc2UKICAgIGVuZAogICAgZ2VvX2luaXR0ZWQgPSB0cnVlCiAgICBnZW9fcmVhc29uID0gIm9rIgogICAgbmd4LmxvZyhuZ3guSU5GTywgIltnZW9fY291bnRyeV0gR2VvTGl0ZTItQ291bnRyeSBsb2FkZWQgZnJvbSAiIC4uIERCX1BBVEgpCiAgICByZXR1cm4gdHJ1ZQplbmQKCi0tIENyZWF0ZSBMUlUgY2FjaGUgb25jZSBwZXIgd29ya2VyIChtYXggNTAwMDAgSVBzKS4KbG9jYWwgZnVuY3Rpb24gZ2V0X2NhY2hlKCkKICAgIGlmIGNhY2hlIHRoZW4KICAgICAgICByZXR1cm4gY2FjaGUKICAgIGVuZAogICAgaWYgbm90IGxydWNhY2hlX29rIG9yIG5vdCBscnVjYWNoZSB0aGVuCiAgICAgICAgcmV0dXJuIG5pbAogICAgZW5kCiAgICBsb2NhbCBjLCBlcnIgPSBscnVjYWNoZS5uZXcoNTAwMDApCiAgICBpZiBub3QgYyB0aGVuCiAgICAgICAgcmV0dXJuIG5pbAogICAgZW5kCiAgICBjYWNoZSA9IGMKICAgIHJldHVybiBjYWNoZQplbmQKCi0tLSBHZXQgY291bnRyeSBJU08gY29kZSBmb3IgSVAuIFVzZXMgaW4tbWVtb3J5IExSVSBjYWNoZSB0aGVuIE1heE1pbmQgREIuCi0tIEBwYXJhbSBpcCBzdHJpbmcgKGUuZy4gIjguOC44LjgiKQotLSBAcmV0dXJuIHN0cmluZ3xuaWwgY291bnRyeSBjb2RlIChlLmcuICJVUyIpIG9yIG5pbApmdW5jdGlvbiBfTS5nZXRfY291bnRyeV9jb2RlKGlwKQogICAgaWYgbm90IGlwIG9yIGlwID09ICIiIHRoZW4KICAgICAgICByZXR1cm4gbmlsCiAgICBlbmQKCiAgICBsb2NhbCBjID0gZ2V0X2NhY2hlKCkKICAgIGlmIGMgdGhlbgogICAgICAgIGxvY2FsIGNhY2hlZCA9IGM6Z2V0KGlwKQogICAgICAgIGlmIGNhY2hlZCB+PSBuaWwgdGhlbgogICAgICAgICAgICAtLSBmYWxzZSBtZWFucyAibG9va2VkIHVwLCBubyByZXN1bHQiIC0gYXZvaWRzIHJlcGVhdGVkIERCIG1pc3NlcwogICAgICAgICAgICByZXR1cm4gKGNhY2hlZCA9PSBmYWxzZSkgYW5kIG5pbCBvciBjYWNoZWQKICAgICAgICBlbmQKICAgIGVuZAoKICAgIGlmIG5vdCBlbnN1cmVfZ2VvX2luaXQoKSB0aGVuCiAgICAgICAgaWYgYyB0aGVuIGM6c2V0KGlwLCBmYWxzZSkgZW5kCiAgICAgICAgcmV0dXJuIG5pbAogICAgZW5kCgogICAgbG9jYWwgb2ssIHJlcywgZXJyID0gcGNhbGwobWF4bWluZC5sb29rdXAsIGlwKQogICAgbG9jYWwgY29kZSA9IG5pbAogICAgaWYgb2sgYW5kIHJlcyBhbmQgcmVzLmNvdW50cnkgYW5kIHJlcy5jb3VudHJ5Lmlzb19jb2RlIHRoZW4KICAgICAgICBjb2RlID0gcmVzLmNvdW50cnkuaXNvX2NvZGUKICAgIGVuZAoKICAgIGlmIGMgdGhlbgogICAgICAgIGM6c2V0KGlwLCBjb2RlIG9yIGZhbHNlKQogICAgZW5kCiAgICByZXR1cm4gY29kZQplbmQKCmZ1bmN0aW9uIF9NLmVuc3VyZV9nZW9faW5pdCgpCiAgICByZXR1cm4gZW5zdXJlX2dlb19pbml0KCkKZW5kCgotLS0gSGVhbHRoIGZvciBgR0VUIC9zdGF0dXNgOiBkb2VzIGdlbyBhY3R1YWxseSByZXNvbHZlLCBhbmQgaWYgbm90LCB3aHkuCi0tIEByZXR1cm4gYm9vbGVhbiBhdmFpbGFibGUsIHN0cmluZyByZWFzb24sIHN0cmluZyBkYl9wYXRoCmZ1bmN0aW9uIF9NLnN0YXR1cygpCiAgICBsb2NhbCBvayA9IGVuc3VyZV9nZW9faW5pdCgpCiAgICByZXR1cm4gb2ssIGdlb19yZWFzb24sIERCX1BBVEgKZW5kCgpyZXR1cm4gX00K",
|
|
21
|
+
"maxminddb.lua": "LS0gbWF4bWluZGRiLmx1YSDigJQgVkVORE9SRUQgVEhJUkQtUEFSVFkuIERvIG5vdCBlZGl0OyByZS12ZW5kb3IgaW5zdGVhZC4KLS0KLS0gVXBzdHJlYW06IGFuamlhMDUzMi9sdWEtcmVzdHktbWF4bWluZGRiIHYxLjMuMiAob3BtKS4gTG9hZGVkIGFzCi0tIGBvcGVuc2hpcC5tYXhtaW5kZGJgIChzZWUgZ2VvX2NvdW50cnkubHVhKS4gVmVyYmF0aW0gZXhjZXB0IHRoaXMgaGVhZGVyIGFuZCBPTkUKLS0gbWFya2VkIGNoYW5nZSB0byB0aGUgYGZmaS5sb2FkYCBjYWxsIOKAlCBzZWFyY2ggIk9QRU5TSElQIExPQ0FMIE1PRElGSUNBVElPTiIuCi0tCi0tIFdoeSB2ZW5kb3JlZCByYXRoZXIgdGhhbiBgb3BtIGdldGAgYXQgaW1hZ2UgYnVpbGQ6IGBvcG1gIG5lZWRzIHBlcmwsIHdoaWNoIHRoZQotLSBvcGVucmVzdHkgYWxwaW5lIGJhc2UgZG9lcyBub3Qgc2hpcCwgYW5kIGEgYnVpbGQtdGltZSBmZXRjaCB3b3VsZCBtYWtlIHRoZQotLSBpbWFnZSBub24tcmVwcm9kdWNpYmxlLiBFdmVyeXRoaW5nIGVsc2UgaW4gdGhpcyBkaXJlY3RvcnkgaXMgYWxyZWFkeSBzaGlwcGVkCi0tIGJ5IHVzIChhbmQgYmFzZTY0LWVtYmVkZGVkIGludG8gdGhlIEpTIGJ1bmRsZSksIHNvIGEgcGlubmVkIGNvcHkgaXMgdGhlIGhvdXNlCi0tIHBhdHRlcm4g4oCUIHNhbWUgcmVhc29uaW5nIGFzIHRoZSB2ZW5kb3JlZCBHZW9MaXRlMiBEQiBpbiBhcHBzL2FwaS9hc3NldHMvZ2VvaXAuCi0tCi0tIE5lZWRzIGxpYm1heG1pbmRkYi5zbyBhdCBydW50aW1lIChgYXBrIGFkZCBsaWJtYXhtaW5kZGJgLCBpbiBhcHBzL2VkZ2UvRG9ja2VyZmlsZSkuCi0tIGBmZmkubG9hZGAgYmVsb3cgcnVucyBhdCBSRVFVSVJFIHRpbWUsIHNvIGEgbWlzc2luZyAuc28gdGhyb3dzIG9uIHJlcXVpcmUg4oCUCi0tIGdlb19jb3VudHJ5Lmx1YSBwY2FsbHMgaXQgZm9yIGV4YWN0bHkgdGhhdCByZWFzb24uCi0tCi0tIFJlLXZlbmRvciB3aXRoOgotLSAgIGN1cmwgLWZzU0wgaHR0cHM6Ly9vcG0ub3BlbnJlc3R5Lm9yZy9hcGkvcGtnL3RhcmJhbGwvYW5qaWEwNTMyL2x1YS1yZXN0eS1tYXhtaW5kZGItPHY+Lm9wbS50YXIuZ3ogXAotLSAgICAgfCB0YXIgeHogLU8gJyovbGliL3Jlc3R5L21heG1pbmRkYi5sdWEnID4gcGFja2FnZXMvYWRhcHRlcnMvc3JjL2luZnJhL2x1YS9tYXhtaW5kZGIubHVhCi0tICAgIyB0aGVuIHJlLWFwcGx5IHRoaXMgaGVhZGVyIGFuZCBydW4gYGJ1biBydW4gZW1iZWQ6bHVhYAotLVtbCglDb3B5cmlnaHQgMjAxNy1ub3cgYW5qaWEgKGFuamlhMDUzMkBnbWFpbC5jb20pCgoJTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlICJMaWNlbnNlIik7Cgl5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCglZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKCQlodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKCVVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKCWRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICJBUyBJUyIgQkFTSVMsCglXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KCVNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKCWxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLgpdXQoKLS0gY29weSBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9saWxpZW4xMDEwL2x1YS1yZXN0eS1tYXhtaW5kZGIvYmxvYi9mOTY2MzNlMjQyOGY4ZjdiY2MxZTJhN2EyOGI3NDdiMzMyMzNhOGRiL3Jlc3R5L21heG1pbmRkYi5sdWEjTDUtTDEyCgpsb2NhbCBmZmkgICAgICAgICAgICAgICAgID0gcmVxdWlyZSAoJ2ZmaScpCmxvY2FsIGZmaV9uZXcgICAgICAgICAgICAgPSBmZmkubmV3CmxvY2FsIGZmaV9zdHIgICAgICAgICAgICAgPSBmZmkuc3RyaW5nCmxvY2FsIGZmaV9jYXN0ICAgICAgICAgICAgPSBmZmkuY2FzdApsb2NhbCBmZmlfZ2MgICAgICAgICAgICAgID0gZmZpLmdjCmxvY2FsIEMgICAgICAgICAgICAgICAgICAgPSBmZmkuQwoKbG9jYWwgX00gICAgPXt9Cl9NLl9WRVJTSU9OID0gJzEuMy4yJwpsb2NhbCBtdCA9IHsgX19pbmRleCA9IF9NIH0KCi0tIGNvcHkgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vbGlsaWVuMTAxMC9sdWEtcmVzdHktbWF4bWluZGRiL2Jsb2IvZjk2NjMzZTI0MjhmOGY3YmNjMWUyYTdhMjhiNzQ3YjMzMjMzYThkYi9yZXN0eS9tYXhtaW5kZGIubHVhI0wzNi1MMTI2CmZmaS5jZGVmW1sKCnR5cGVkZWYgbG9uZyBpbnQgc3NpemVfdDsKCnR5cGVkZWYgdW5zaWduZWQgaW50IG1tZGJfdWludDEyOF90IF9fYXR0cmlidXRlX18gKChfX21vZGVfXyhUSSkpKTsKCnR5cGVkZWYgc3RydWN0IE1NREJfZW50cnlfcyB7CiAgc3RydWN0IE1NREJfcyAqbW1kYjsKICB1aW50MzJfdCBvZmZzZXQ7Cn0gTU1EQl9lbnRyeV9zOwoKdHlwZWRlZiBzdHJ1Y3QgTU1EQl9sb29rdXBfcmVzdWx0X3MgewogIGJvb2wgZm91bmRfZW50cnk7CiAgTU1EQl9lbnRyeV9zIGVudHJ5OwogIHVpbnQxNl90IG5ldG1hc2s7Cn0gTU1EQl9sb29rdXBfcmVzdWx0X3M7Cgp0eXBlZGVmIHN0cnVjdCBNTURCX2VudHJ5X2RhdGFfcyB7CiAgYm9vbCBoYXNfZGF0YTsKICB1bmlvbiB7CiAgICB1aW50MzJfdCBwb2ludGVyOwogICAgY29uc3QgY2hhciAqdXRmOF9zdHJpbmc7CiAgICBkb3VibGUgZG91YmxlX3ZhbHVlOwogICAgY29uc3QgdWludDhfdCAqYnl0ZXM7CiAgICB1aW50MTZfdCB1aW50MTY7CiAgICB1aW50MzJfdCB1aW50MzI7CiAgICBpbnQzMl90IGludDMyOwogICAgdWludDY0X3QgdWludDY0OwogICAgbW1kYl91aW50MTI4X3QgdWludDEyODsKICAgIGJvb2wgYm9vbGVhbjsKICAgIGZsb2F0IGZsb2F0X3ZhbHVlOwogIH07CgogIHVpbnQzMl90IG9mZnNldDsKICB1aW50MzJfdCBvZmZzZXRfdG9fbmV4dDsKICB1aW50MzJfdCBkYXRhX3NpemU7CiAgdWludDMyX3QgdHlwZTsKfSBNTURCX2VudHJ5X2RhdGFfczsKCnR5cGVkZWYgc3RydWN0IE1NREJfZW50cnlfZGF0YV9saXN0X3MgewogIE1NREJfZW50cnlfZGF0YV9zIGVudHJ5X2RhdGE7CiAgc3RydWN0IE1NREJfZW50cnlfZGF0YV9saXN0X3MgKm5leHQ7Cn0gTU1EQl9lbnRyeV9kYXRhX2xpc3RfczsKCnR5cGVkZWYgc3RydWN0IE1NREJfZGVzY3JpcHRpb25fcyB7CiAgY29uc3QgY2hhciAqbGFuZ3VhZ2U7CiAgY29uc3QgY2hhciAqZGVzY3JpcHRpb247Cn0gTU1EQl9kZXNjcmlwdGlvbl9zOwoKdHlwZWRlZiBzdHJ1Y3QgTU1EQl9tZXRhZGF0YV9zIHsKICB1aW50MzJfdCBub2RlX2NvdW50OwogIHVpbnQxNl90IHJlY29yZF9zaXplOwogIHVpbnQxNl90IGlwX3ZlcnNpb247CiAgY29uc3QgY2hhciAqZGF0YWJhc2VfdHlwZTsKICBzdHJ1Y3QgewogICAgc2l6ZV90IGNvdW50OwogICAgY29uc3QgY2hhciAqKm5hbWVzOwogIH0gbGFuZ3VhZ2VzOwogIHVpbnQxNl90IGJpbmFyeV9mb3JtYXRfbWFqb3JfdmVyc2lvbjsKICB1aW50MTZfdCBiaW5hcnlfZm9ybWF0X21pbm9yX3ZlcnNpb247CiAgdWludDY0X3QgYnVpbGRfZXBvY2g7CiAgc3RydWN0IHsKICAgIHNpemVfdCBjb3VudDsKICAgIE1NREJfZGVzY3JpcHRpb25fcyAqKmRlc2NyaXB0aW9uczsKICB9IGRlc2NyaXB0aW9uOwp9IE1NREJfbWV0YWRhdGFfczsKCnR5cGVkZWYgc3RydWN0IE1NREJfaXB2NF9zdGFydF9ub2RlX3MgewogIHVpbnQxNl90IG5ldG1hc2s7CiAgdWludDMyX3Qgbm9kZV92YWx1ZTsKfSBNTURCX2lwdjRfc3RhcnRfbm9kZV9zOwoKdHlwZWRlZiBzdHJ1Y3QgTU1EQl9zIHsKICB1aW50MzJfdCBmbGFnczsKICBjb25zdCBjaGFyICpmaWxlbmFtZTsKICBzc2l6ZV90IGZpbGVfc2l6ZTsKICBjb25zdCB1aW50OF90ICpmaWxlX2NvbnRlbnQ7CiAgY29uc3QgdWludDhfdCAqZGF0YV9zZWN0aW9uOwogIHVpbnQzMl90IGRhdGFfc2VjdGlvbl9zaXplOwogIGNvbnN0IHVpbnQ4X3QgKm1ldGFkYXRhX3NlY3Rpb247CiAgdWludDMyX3QgbWV0YWRhdGFfc2VjdGlvbl9zaXplOwogIHVpbnQxNl90IGZ1bGxfcmVjb3JkX2J5dGVfc2l6ZTsKICB1aW50MTZfdCBkZXB0aDsKICBNTURCX2lwdjRfc3RhcnRfbm9kZV9zIGlwdjRfc3RhcnRfbm9kZTsKICBNTURCX21ldGFkYXRhX3MgbWV0YWRhdGE7Cn0gTU1EQl9zOwoKdHlwZWRlZiAgY2hhciAqIHBjaGFyOwoKTU1EQl9sb29rdXBfcmVzdWx0X3MgTU1EQl9sb29rdXBfc3RyaW5nKE1NREJfcyAqY29uc3QgbW1kYiwgICBjb25zdCBjaGFyICpjb25zdCBpcHN0ciwgaW50ICpjb25zdCBnYWlfZXJyb3IsaW50ICpjb25zdCBtbWRiX2Vycm9yKTsKaW50IE1NREJfb3Blbihjb25zdCBjaGFyICpjb25zdCBmaWxlbmFtZSwgdWludDMyX3QgZmxhZ3MsIE1NREJfcyAqY29uc3QgbW1kYik7CmludCBNTURCX2FnZXRfdmFsdWUoTU1EQl9lbnRyeV9zICpjb25zdCBzdGFydCwgIE1NREJfZW50cnlfZGF0YV9zICpjb25zdCBlbnRyeV9kYXRhLCAgY29uc3QgY2hhciAqY29uc3QgKmNvbnN0IHBhdGgpOwpjaGFyICpNTURCX3N0cmVycm9yKGludCBlcnJvcl9jb2RlKTsKCmludCBNTURCX2dldF9lbnRyeV9kYXRhX2xpc3QoTU1EQl9lbnRyeV9zICpzdGFydCwgTU1EQl9lbnRyeV9kYXRhX2xpc3RfcyAqKmNvbnN0IGVudHJ5X2RhdGFfbGlzdCk7CnZvaWQgTU1EQl9mcmVlX2VudHJ5X2RhdGFfbGlzdChNTURCX2VudHJ5X2RhdGFfbGlzdF9zICpjb25zdCBlbnRyeV9kYXRhX2xpc3QpOwp2b2lkIE1NREJfY2xvc2UoTU1EQl9zICpjb25zdCBtbWRiKTsKY29uc3QgY2hhciAqZ2FpX3N0cmVycm9yKGludCBlcnJjb2RlKTsKXV0KCi0tIGVycm9yIGNvZGVzIAotLSBodHRwczovL2dpdGh1Yi5jb20vbWF4bWluZC9saWJtYXhtaW5kZGIvYmxvYi9tYXN0ZXIvaW5jbHVkZS9tYXhtaW5kZGIuaCNMNjYKbG9jYWwgTU1EQl9TVUNDRVNTICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gICAwCmxvY2FsIE1NREJfRklMRV9PUEVOX0VSUk9SICAgICAgICAgICAgICAgICAgICAgICAgICA9ICAgMQpsb2NhbCBNTURCX0NPUlJVUFRfU0VBUkNIX1RSRUVfRVJST1IgICAgICAgICAgICAgICAgPSAgIDIKbG9jYWwgTU1EQl9JTlZBTElEX01FVEFEQVRBX0VSUk9SICAgICAgICAgICAgICAgICAgID0gICAzCmxvY2FsIE1NREJfSU9fRVJST1IgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9ICAgNApsb2NhbCBNTURCX09VVF9PRl9NRU1PUllfRVJST1IgICAgICAgICAgICAgICAgICAgICAgPSAgIDUKbG9jYWwgTU1EQl9VTktOT1dOX0RBVEFCQVNFX0ZPUk1BVF9FUlJPUiAgICAgICAgICAgID0gICA2CmxvY2FsIE1NREJfSU5WQUxJRF9EQVRBX0VSUk9SICAgICAgICAgICAgICAgICAgICAgICA9ICAgNwpsb2NhbCBNTURCX0lOVkFMSURfTE9PS1VQX1BBVEhfRVJST1IgICAgICAgICAgICAgICAgPSAgIDgKbG9jYWwgTU1EQl9MT09LVVBfUEFUSF9ET0VTX05PVF9NQVRDSF9EQVRBX0VSUk9SICAgID0gICA5CmxvY2FsIE1NREJfSU5WQUxJRF9OT0RFX05VTUJFUl9FUlJPUiAgICAgICAgICAgICAgICA9ICAgMTAKbG9jYWwgTU1EQl9JUFY2X0xPT0tVUF9JTl9JUFY0X0RBVEFCQVNFX0VSUk9SICAgICAgID0gICAxMQoKLS0gZGF0YSB0eXBlCi0tIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXhtaW5kL2xpYm1heG1pbmRkYi9ibG9iL21hc3Rlci9pbmNsdWRlL21heG1pbmRkYi5oI0w0MApsb2NhbCBNTURCX0RBVEFfVFlQRV9FWFRFTkRFRCAgICAgICAgICAgICAgICAgICAgICAgPSAgIDAKbG9jYWwgTU1EQl9EQVRBX1RZUEVfUE9JTlRFUiAgICAgICAgICAgICAgICAgICAgICAgID0gICAxCmxvY2FsIE1NREJfREFUQV9UWVBFX1VURjhfU1RSSU5HICAgICAgICAgICAgICAgICAgICA9ICAgMgpsb2NhbCBNTURCX0RBVEFfVFlQRV9ET1VCTEUgICAgICAgICAgICAgICAgICAgICAgICAgPSAgIDMKbG9jYWwgTU1EQl9EQVRBX1RZUEVfQllURVMgICAgICAgICAgICAgICAgICAgICAgICAgID0gICA0CmxvY2FsIE1NREJfREFUQV9UWVBFX1VJTlQxNiAgICAgICAgICAgICAgICAgICAgICAgICA9ICAgNQpsb2NhbCBNTURCX0RBVEFfVFlQRV9VSU5UMzIgICAgICAgICAgICAgICAgICAgICAgICAgPSAgIDYKbG9jYWwgTU1EQl9EQVRBX1RZUEVfTUFQICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gICA3CmxvY2FsIE1NREJfREFUQV9UWVBFX0lOVDMyICAgICAgICAgICAgICAgICAgICAgICAgICA9ICAgOApsb2NhbCBNTURCX0RBVEFfVFlQRV9VSU5UNjQgICAgICAgICAgICAgICAgICAgICAgICAgPSAgIDkKbG9jYWwgTU1EQl9EQVRBX1RZUEVfVUlOVDEyOCAgICAgICAgICAgICAgICAgICAgICAgID0gICAxMApsb2NhbCBNTURCX0RBVEFfVFlQRV9BUlJBWSAgICAgICAgICAgICAgICAgICAgICAgICAgPSAgIDExCmxvY2FsIE1NREJfREFUQV9UWVBFX0NPTlRBSU5FUiAgICAgICAgICAgICAgICAgICAgICA9ICAgMTIKbG9jYWwgTU1EQl9EQVRBX1RZUEVfRU5EX01BUktFUiAgICAgICAgICAgICAgICAgICAgID0gICAxMwpsb2NhbCBNTURCX0RBVEFfVFlQRV9CT09MRUFOICAgICAgICAgICAgICAgICAgICAgICAgPSAgIDE0CmxvY2FsIE1NREJfREFUQV9UWVBFX0ZMT0FUICAgICAgICAgICAgICAgICAgICAgICAgICA9ICAgMTUKCi0tIGNvcHkgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vbGlsaWVuMTAxMC9sdWEtcmVzdHktbWF4bWluZGRiL2Jsb2IvZjk2NjMzZTI0MjhmOGY3YmNjMWUyYTdhMjhiNzQ3YjMzMjMzYThkYi9yZXN0eS9tYXhtaW5kZGIubHVhI0wxMzYtTDEzOAotLSB5b3Ugc2hvdWxkIGluc3RhbGwgdGhlIGxpYm1heG1pbmRkYiB0byB5b3VyIHN5c3RlbQotLQotLSDilIDilIAgT1BFTlNISVAgTE9DQUwgTU9ESUZJQ0FUSU9OICh0aGUgb25seSBkZXZpYXRpb24gZnJvbSB1cHN0cmVhbSkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tIFVwc3RyZWFtIGlzIGBmZmkubG9hZCgnbGlibWF4bWluZGRiJylgLCB3aGljaCByZXNvbHZlcyB0aGUgTElOS0VSIG5hbWUKLS0gYGxpYm1heG1pbmRkYi5zb2Ag4oCUIGFuZCB0aGF0IHVudmVyc2lvbmVkIHN5bWxpbmsgc2hpcHMgaW4gdGhlIC1kZXYgcGFja2FnZSwgbm90Ci0tIHRoZSBydW50aW1lIG9uZS4gQWxwaW5lJ3MgYGxpYm1heG1pbmRkYmAgYW5kIERlYmlhbidzIGBsaWJtYXhtaW5kZGIwYCBib3RoIGdpdmUKLS0gb25seSBgbGlibWF4bWluZGRiLnNvLjBgLCBzbyB0aGUgYmFyZSBuYW1lIGZhaWxzIG9uIGEgbm9ybWFsIHJ1bnRpbWUgaW5zdGFsbCBhbmQKLS0gZ2VvIGdvZXMgc2lsZW50bHkgZGFyayAoZ2VvX2NvdW50cnkgcGNhbGxzIHRoaXMgcmVxdWlyZSkuIFRyeSB0aGUgc29uYW1lIHRvbyBzbwotLSB0aGUgcnVudGltZSBwYWNrYWdlIGFsb25lIGlzIGVub3VnaCBvbiBldmVyeSBkaXN0cm8uCmxvY2FsIG1heG0KZG8KICAgIGxvY2FsIGNhbmRpZGF0ZXMgPSB7ICdsaWJtYXhtaW5kZGInLCAnbGlibWF4bWluZGRiLnNvLjAnLCAnbGlibWF4bWluZGRiLnNvJyB9CiAgICBsb2NhbCBsYXN0X2VycgogICAgZm9yIGkgPSAxLCAjY2FuZGlkYXRlcyBkbwogICAgICAgIGxvY2FsIG9rLCBsaWIgPSBwY2FsbChmZmkubG9hZCwgY2FuZGlkYXRlc1tpXSkKICAgICAgICBpZiBvayB0aGVuIG1heG0gPSBsaWI7IGJyZWFrIGVuZAogICAgICAgIGxhc3RfZXJyID0gbGliCiAgICBlbmQKICAgIGlmIG5vdCBtYXhtIHRoZW4KICAgICAgICBlcnJvcignbGlibWF4bWluZGRiIG5vdCBsb2FkYWJsZSAodHJpZWQgJyAuLiB0YWJsZS5jb25jYXQoY2FuZGlkYXRlcywgJywgJykgLi4KICAgICAgICAgICAgICAnKTogJyAuLiB0b3N0cmluZyhsYXN0X2VyciksIDIpCiAgICBlbmQKZW5kCi0taHR0cHM6Ly9naXRodWIuY29tL21heG1pbmQvbGlibWF4bWluZGRiCmxvY2FsIG1tZGIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IGZmaV9uZXcoJ01NREJfcycpCmxvY2FsIGluaXR0ZWQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IGZhbHNlCgpsb2NhbCBmdW5jdGlvbiBtbWRiX3N0cmVycm9yKHJjKQogICAgcmV0dXJuIGZmaV9zdHIobWF4bS5NTURCX3N0cmVycm9yKHJjKSkKZW5kCgpsb2NhbCBmdW5jdGlvbiBnYWlfc3RyZXJyb3IocmMpCiAgICByZXR1cm4gZmZpX3N0cihDLmdhaV9zdHJlcnJvcihyYykpCmVuZAoKZnVuY3Rpb24gX00uaW5pdChkYmZpbGUpCiAgaWYgbm90IGluaXR0ZWQgdGhlbgogICAgbG9jYWwgbWF4bWluZF9yZWFkeSAgID0gbWF4bS5NTURCX29wZW4oZGJmaWxlLDAsbW1kYikKCiAgICBpZiBtYXhtaW5kX3JlYWR5IH49IE1NREJfU1VDQ0VTUyB0aGVuCiAgICAgICAgcmV0dXJuIG5pbCwgbW1kYl9zdHJlcnJvcihtYXhtaW5kX3JlYWR5KQogICAgZW5kCiAgICAKICAgIGluaXR0ZWQgPSB0cnVlCiAgICAKICAgIGZmaV9nYyhtbWRiLCBtYXhtLk1NREJfY2xvc2UpCiAgZW5kCiAgcmV0dXJuIGluaXR0ZWQKZW5kCgpmdW5jdGlvbiBfTS5pbml0dGVkKCkKICAgIHJldHVybiBpbml0dGVkCmVuZAoKLS0gaHR0cHM6Ly9naXRodWIuY29tL21heG1pbmQvbGlibWF4bWluZGRiL2Jsb2IvbWFzdGVyL3NyYy9tYXhtaW5kZGIuYyNMMTkzOCAKLS0gTE9DQUwgTU1EQl9lbnRyeV9kYXRhX2xpc3RfcyAqZHVtcF9lbnRyeV9kYXRhX2xpc3QoIEZJTEUgKnN0cmVhbSwgTU1EQl9lbnRyeV9kYXRhX2xpc3RfcyAqZW50cnlfZGF0YV9saXN0LCBpbnQgaW5kZW50LCBpbnQgKnN0YXR1cykKbG9jYWwgZnVuY3Rpb24gX2R1bXBfZW50cnlfZGF0YV9saXN0KGVudHJ5X2RhdGFfbGlzdCxzdGF0dXMpCgogIGlmIG5vdCBlbnRyeV9kYXRhX2xpc3QgdGhlbgogICAgcmV0dXJuIG5pbCxNTURCX0lOVkFMSURfREFUQV9FUlJPUgogIGVuZAogIAogIGxvY2FsIGVudHJ5X2RhdGFfaXRlbSA9IGVudHJ5X2RhdGFfbGlzdFswXS5lbnRyeV9kYXRhCiAgbG9jYWwgZGF0YV90eXBlID0gZW50cnlfZGF0YV9pdGVtLnR5cGUKICBsb2NhbCBkYXRhX3NpemUgPSBlbnRyeV9kYXRhX2l0ZW0uZGF0YV9zaXplCiAgbG9jYWwgcmVzdWx0CiAgCiAgaWYgZGF0YV90eXBlID09IE1NREJfREFUQV9UWVBFX01BUCB0aGVuCiAgICByZXN1bHQgPSB7fQogICAgCiAgICBsb2NhbCBzaXplID0gZW50cnlfZGF0YV9pdGVtLmRhdGFfc2l6ZQogICAgCiAgICBlbnRyeV9kYXRhX2xpc3QgPSBlbnRyeV9kYXRhX2xpc3RbMF0ubmV4dAogICAgCiAgICB3aGlsZShzaXplID4gMCBhbmQgZW50cnlfZGF0YV9saXN0KQogICAgZG8gCiAgICAgIGVudHJ5X2RhdGFfaXRlbSA9IGVudHJ5X2RhdGFfbGlzdFswXS5lbnRyeV9kYXRhCiAgICAgIGRhdGFfdHlwZSA9IGVudHJ5X2RhdGFfaXRlbS50eXBlCiAgICAgIGRhdGFfc2l6ZSA9IGVudHJ5X2RhdGFfaXRlbS5kYXRhX3NpemUKICAgICAgCiAgICAgIGlmIE1NREJfREFUQV9UWVBFX1VURjhfU1RSSU5HICB+PSBkYXRhX3R5cGUgdGhlbgogICAgICAgIHJldHVybiBuaWwsTU1EQl9JTlZBTElEX0RBVEFfRVJST1IKICAgICAgZW5kCiAgICAgIAogICAgICBsb2NhbCBrZXkgPSBmZmlfc3RyKGVudHJ5X2RhdGFfaXRlbS51dGY4X3N0cmluZyxkYXRhX3NpemUpCgogICAgICBpZiBub3Qga2V5IHRoZW4KICAgICAgICByZXR1cm4gbmlsLE1NREJfT1VUX09GX01FTU9SWV9FUlJPUgogICAgICBlbmQKICAgICAgCiAgICAgIGxvY2FsIHZhbAogICAgICBlbnRyeV9kYXRhX2xpc3QgPSBlbnRyeV9kYXRhX2xpc3RbMF0ubmV4dAogICAgICBlbnRyeV9kYXRhX2xpc3Qsc3RhdHVzLHZhbCA9IF9kdW1wX2VudHJ5X2RhdGFfbGlzdChlbnRyeV9kYXRhX2xpc3QpCiAgICAgIAogICAgICBpZiBzdGF0dXMgfj0gTU1EQl9TVUNDRVNTIHRoZW4KICAgICAgICByZXR1cm4gbmlsLHN0YXR1cwogICAgICBlbmQKCiAgICAgIHJlc3VsdFtrZXldID0gdmFsCiAgICAgIAogICAgICBzaXplID0gc2l6ZSAtMSAKICAgIGVuZAogICAgCgogIGVsc2VpZiBlbnRyeV9kYXRhX2xpc3RbMF0uZW50cnlfZGF0YS50eXBlID09IE1NREJfREFUQV9UWVBFX0FSUkFZIHRoZW4KICAgIGxvY2FsIHNpemUgPSBlbnRyeV9kYXRhX2xpc3RbMF0uZW50cnlfZGF0YS5kYXRhX3NpemUKICAgIHJlc3VsdCA9IHt9CgogICAgZW50cnlfZGF0YV9saXN0ID0gZW50cnlfZGF0YV9saXN0WzBdLm5leHQKICAgIAogICAgbG9jYWwgaSA9IDEKICAgIHdoaWxlKGkgPD0gc2l6ZSBhbmQgZW50cnlfZGF0YV9saXN0KQogICAgZG8KICAgICAgbG9jYWwgdmFsCiAgICAgIGVudHJ5X2RhdGFfbGlzdCxzdGF0dXMsdmFsID0gX2R1bXBfZW50cnlfZGF0YV9saXN0KGVudHJ5X2RhdGFfbGlzdCkKICAgICAgCiAgICAgIGlmIHN0YXR1cyB+PSBNTURCX1NVQ0NFU1MgdGhlbgogICAgICAgIHJldHVybiBuaWwsbmlsLHZhbAogICAgICBlbmQKICAgICAgCiAgICAgIHJlc3VsdFtpXSA9IHZhbAogICAgICBpID0gaSArIDEKICAgIGVuZAoKICAgIAogIGVsc2UKICAgIGVudHJ5X2RhdGFfaXRlbSA9IGVudHJ5X2RhdGFfbGlzdFswXS5lbnRyeV9kYXRhCiAgICBkYXRhX3R5cGUgPSBlbnRyeV9kYXRhX2l0ZW0udHlwZQogICAgZGF0YV9zaXplID0gZW50cnlfZGF0YV9pdGVtLmRhdGFfc2l6ZQogICAgCiAgICBsb2NhbCB2YWwKICAgIC0tIHN0cmluZyB0eXBlICJrZXkiOiJ2YWwiCiAgICAtLSBvdGhlciB0eXBlICJrZXkiOnZhbAogICAgLS0gZGVmYXVsdCBvdGhlciB0eXBlCiAgICBpZiBkYXRhX3R5cGUgPT0gTU1EQl9EQVRBX1RZUEVfVVRGOF9TVFJJTkcgdGhlbgogICAgICB2YWwgPSBmZmlfc3RyKGVudHJ5X2RhdGFfaXRlbS51dGY4X3N0cmluZyxkYXRhX3NpemUpCiAgICAgIGlmIG5vdCB2YWwgdGhlbgogICAgICAgIHN0YXR1cyA9IE1NREJfT1VUX09GX01FTU9SWV9FUlJPUgogICAgICAgIHJldHVybiBuaWwsc3RhdHVzCiAgICAgIGVuZAogICAgZWxzZWlmIGRhdGFfdHlwZSA9PSBNTURCX0RBVEFfVFlQRV9CWVRFUyB0aGVuCiAgICAgIHZhbCA9IGZmaV9zdHIoZmZpX2Nhc3QoJ2NoYXIgKiAnLGVudHJ5X2RhdGFfaXRlbS5ieXRlcyksZGF0YV9zaXplKQogICAgICBpZiBub3QgdmFsIHRoZW4KICAgICAgICBzdGF0dXMgPSBNTURCX09VVF9PRl9NRU1PUllfRVJST1IKICAgICAgICByZXR1cm4gbmlsLHN0YXR1cwogICAgICBlbmQKICAgIGVsc2VpZiBkYXRhX3R5cGUgPT0gTU1EQl9EQVRBX1RZUEVfRE9VQkxFIHRoZW4KICAgICAgdmFsID0gZW50cnlfZGF0YV9pdGVtLmRvdWJsZV92YWx1ZQogICAgZWxzZWlmIGRhdGFfdHlwZSA9PSBNTURCX0RBVEFfVFlQRV9GTE9BVCB0aGVuCiAgICAgIHZhbCA9IGVudHJ5X2RhdGFfaXRlbS5mbG9hdF92YWx1ZQogICAgZWxzZWlmIGRhdGFfdHlwZSA9PSBNTURCX0RBVEFfVFlQRV9VSU5UMTYgdGhlbgogICAgICB2YWwgPSBlbnRyeV9kYXRhX2l0ZW0udWludDE2CiAgICBlbHNlaWYgZGF0YV90eXBlID09IE1NREJfREFUQV9UWVBFX1VJTlQzMiB0aGVuCiAgICAgIHZhbCA9IGVudHJ5X2RhdGFfaXRlbS51aW50MzIKICAgIGVsc2VpZiBkYXRhX3R5cGUgPT0gTU1EQl9EQVRBX1RZUEVfQk9PTEVBTiB0aGVuCiAgICAgIHZhbCA9IGVudHJ5X2RhdGFfaXRlbS5ib29sZWFuCiAgICBlbHNlaWYgZGF0YV90eXBlID09IE1NREJfREFUQV9UWVBFX1VJTlQ2NCB0aGVuCiAgICAgIHZhbCA9IGVudHJ5X2RhdGFfaXRlbS51aW50NjQKICAgIGVsc2VpZiBkYXRhX3R5cGUgPT0gTU1EQl9EQVRBX1RZUEVfSU5UMzIgdGhlbgogICAgICB2YWwgPSBlbnRyeV9kYXRhX2l0ZW0uaW50MzIKICAgIGVsc2UKICAgICAgcmV0dXJuIG5pbCxNTURCX0lOVkFMSURfREFUQV9FUlJPUgogICAgZW5kCiAgICAKICAgIHJlc3VsdCA9IHZhbAogICAgZW50cnlfZGF0YV9saXN0ID0gZW50cnlfZGF0YV9saXN0WzBdLm5leHQKICBlbmQKCiAgc3RhdHVzID0gTU1EQl9TVUNDRVNTCiAgcmV0dXJuIGVudHJ5X2RhdGFfbGlzdCxzdGF0dXMscmVzdWx0CmVuZAoKZnVuY3Rpb24gX00ubG9va3VwKGlwKQoKICBpZiBub3QgaW5pdHRlZCB0aGVuCiAgICAgIHJldHVybiBuaWwsICJub3QgaW5pdGlhbGl6ZWQiCiAgZW5kCiAgCiAgLS0gY29weSBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9saWxpZW4xMDEwL2x1YS1yZXN0eS1tYXhtaW5kZGIvYmxvYi9mOTY2MzNlMjQyOGY4ZjdiY2MxZTJhN2EyOGI3NDdiMzMyMzNhOGRiL3Jlc3R5L21heG1pbmRkYi5sdWEjTDE1OS1MMTc2CiAgbG9jYWwgZ2FpX2Vycm9yID0gZmZpX25ldygnaW50WzFdJykKICBsb2NhbCBtbWRiX2Vycm9yID0gZmZpX25ldygnaW50WzFdJykKCiAgbG9jYWwgcmVzdWx0ID0gbWF4bS5NTURCX2xvb2t1cF9zdHJpbmcobW1kYixpcCxnYWlfZXJyb3IsbW1kYl9lcnJvcikKCiAgaWYgbW1kYl9lcnJvclswXSB+PSBNTURCX1NVQ0NFU1MgdGhlbgogICAgcmV0dXJuIG5pbCwnbG9va3VwIGZhaWxlZDogJyAuLiBtbWRiX3N0cmVycm9yKG1tZGJfZXJyb3JbMF0pCiAgZW5kCgogIGlmIGdhaV9lcnJvclswXSB+PSBNTURCX1NVQ0NFU1MgdGhlbgogICAgcmV0dXJuIG5pbCwnbG9va3VwIGZhaWxlZDogJyAuLiBnYWlfc3RyZXJyb3IoZ2FpX2Vycm9yWzBdKQogIGVuZAoKICBpZiB0cnVlIH49IHJlc3VsdC5mb3VuZF9lbnRyeSB0aGVuCiAgICByZXR1cm4gbmlsLCdub3QgZm91bmQnCiAgZW5kCgogIGxvY2FsIGVudHJ5X2RhdGFfbGlzdCA9IGZmaV9jYXN0KCdNTURCX2VudHJ5X2RhdGFfbGlzdF9zICoqY29uc3QnLGZmaV9uZXcoIk1NREJfZW50cnlfZGF0YV9saXN0X3MiKSkKCiAgbG9jYWwgc3RhdHVzID0gbWF4bS5NTURCX2dldF9lbnRyeV9kYXRhX2xpc3QocmVzdWx0LmVudHJ5LGVudHJ5X2RhdGFfbGlzdCkKCiAgaWYgc3RhdHVzIH49IE1NREJfU1VDQ0VTUyB0aGVuCiAgICByZXR1cm4gbmlsLCdnZXQgZW50cnkgZGF0YSBmYWlsZWQ6ICcgLi4gbW1kYl9zdHJlcnJvcihzdGF0dXMpCiAgZW5kICAKICAKICBsb2NhbCBoZWFkID0gZW50cnlfZGF0YV9saXN0WzBdIC0tIFNhdmUgc28gdGhpcyBjYW4gYmUgcGFzc2VkIHRvIGZyZWUgZm4uCiAgbG9jYWwgXyxzdGF0dXMscmVzdWx0ID0gX2R1bXBfZW50cnlfZGF0YV9saXN0KGVudHJ5X2RhdGFfbGlzdCkKICBtYXhtLk1NREJfZnJlZV9lbnRyeV9kYXRhX2xpc3QoaGVhZCkKICAKICBpZiBzdGF0dXMgfj0gTU1EQl9TVUNDRVNTIHRoZW4KICAgIHJldHVybiBuaWwsJ2R1bXAgZW50cnkgZGF0YSBmYWlsZWQ6ICcgLi4gbW1kYl9zdHJlcnJvcihzdGF0dXMpCiAgZW5kCiAgCiAgCiAgcmV0dXJuIHJlc3VsdAplbmQKCi0tIGNvcHkgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vbGlsaWVuMTAxMC9sdWEtcmVzdHktbWF4bWluZGRiL2Jsb2IvbWFzdGVyL3Jlc3R5L21heG1pbmRkYi5sdWEjTDIwOAotLSBodHRwczovL3d3dy5tYXhtaW5kLmNvbS9lbi9nZW9pcDItZGF0YWJhc2VzICB5b3Ugc2hvdWxkIGRvd25sb2FkICB0aGUgbW1kYiBmaWxlIGZyb20gbWF4bWluZAogCnJldHVybiBfTTsK",
|
|
22
|
+
"mgmt_api.lua": "LS0gbWdtdF9hcGkubHVhCi0tIFJFU1QgYW5hbHl0aWNzIGVuZHBvaW50cyBiYWNrZWQgYnkgbmd4LnNoYXJlZC5kaWN0LgotLSBJbnRlcm5hbCBtYW5hZ2VtZW50IHBvcnQgb25seSAoMTI3LjAuMC4xOjkxNDUpLgoKbG9jYWwgY2pzb24gPSByZXF1aXJlICJjanNvbi5zYWZlIgoKbG9jYWwgYW5hbHl0aWNzICAgID0gbmd4LnNoYXJlZC5hbmFseXRpY3MKbG9jYWwgcmVxdWVzdF9kYXRhID0gbmd4LnNoYXJlZC5yZXF1ZXN0X2RhdGEKbG9jYWwgdXJpICAgICAgICAgID0gbmd4LnZhci51cmkKCmxvY2FsIGZ1bmN0aW9uIGpzb24oZGF0YSwgY29kZSkKICAgIG5neC5zdGF0dXMgPSBjb2RlIG9yIDIwMAogICAgbmd4LmhlYWRlclsiQ29udGVudC1UeXBlIl0gPSAiYXBwbGljYXRpb24vanNvbiIKICAgIG5neC5zYXkoY2pzb24uZW5jb2RlKGRhdGEpKQogICAgcmV0dXJuIG5neC5leGl0KG5neC5zdGF0dXMpCmVuZAoKbG9jYWwgZnVuY3Rpb24gYmFkKG1zZykKICAgIHJldHVybiBqc29uKHsgZXJyb3IgPSBtc2cgfSwgNDAwKQplbmQKCi0tIOKUgOKUgCBHRVQgL2hlYWx0aCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKLS0gQmFyZSAib2siLCBOT1QgSlNPTi4gcHJvYmVNZ210KCkgaW4gYXBwcy9hcGkvc3JjL2xpYi9wcm9qZWN0LWFuYWx5dGljcy50cwotLSBhc3NlcnRzIGBib2R5LnRyaW0oKSA9PT0gIm9rImAsIHNvIGFueXRoaW5nIHJpY2hlciBoZXJlIHNpbGVudGx5IHJlcG9ydHMgZXZlcnkKLS0gZWRnZSBhcyB1bnJlYWNoYWJsZSBhbmQgc3RvcHMgdGhlIGFuYWx5dGljcyBzY3JhcGUuIFJpY2hlciBkaWFnbm9zdGljcyBnbyBvbgotLSAvc3RhdHVzIGJlbG93LgoKaWYgdXJpID09ICIvaGVhbHRoIiB0aGVuCiAgICBuZ3guc2F5KCJvayIpCiAgICByZXR1cm4gbmd4LmV4aXQoMjAwKQplbmQKCi0tIOKUgOKUgCBHRVQgL3N0YXR1cyAtIGRpYWdub3NhYmxlIGVkZ2UgaGVhbHRoIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAotLSBXaHkgdGhpcyBleGlzdHM6IGdlbyBmYWlsaW5nIGlzIElOVklTSUJMRSBvdGhlcndpc2UuIGdlb19jb3VudHJ5Lmx1YSBwY2FsbHMgaXRzCi0tIEZGSSBiaW5kaW5nIGFuZCByZXR1cm5zIG5pbCBvbiBmYWlsdXJlLCBzbyBhIG1pc3NpbmcgbGlibWF4bWluZGRiLnNvIG9yIGEKLS0gbWlzc2luZyBkYXRhYmFzZSBwcmVzZW50cyBleGFjdGx5IGxpa2UgIm5vYm9keSB2aXNpdGVkIGZyb20gYSBrbm93biBjb3VudHJ5IiDigJQKLS0gYW4gZW1wdHkgbWFwIHdpdGggbm8gZXJyb3IgYW55d2hlcmUuIFRoaXMgcmVwb3J0cyB3aGljaCBpdCBpcy4KLS0KLS0gQWxzbyByZXBvcnRzIHNoYXJlZC1kaWN0IGhlYWRyb29tOiB0aGVzZSB6b25lcyBMUlUtRVZJQ1Qgd2hlbiBmdWxsIHJhdGhlciB0aGFuCi0tIGVycm9yaW5nLCBzbyBhIGZ1bGwgYHZpc2l0b3JzYCB6b25lIHNpbGVudGx5IFVOREVSQ09VTlRTLiBDYWxsZXJzIHN1cmZhY2UgdGhhdAotLSBhcyAiYXBwcm94aW1hdGUiIGluc3RlYWQgb2YgcHJlc2VudGluZyBhbiBldmljdGlvbiBhcnRpZmFjdCBhcyBhIG1lYXN1cmVtZW50LgoKaWYgdXJpID09ICIvc3RhdHVzIiB0aGVuCiAgICBsb2NhbCBnZW9fYXZhaWxhYmxlLCBnZW9fcmVhc29uLCBnZW9fZGIgPSBmYWxzZSwgImdlb19jb3VudHJ5IG1vZHVsZSBub3QgbG9hZGFibGUiLCBuaWwKICAgIGxvY2FsIGdlb19vaywgZ2VvID0gcGNhbGwocmVxdWlyZSwgIm9wZW5zaGlwLmdlb19jb3VudHJ5IikKICAgIGlmIGdlb19vayBhbmQgZ2VvIGFuZCBnZW8uc3RhdHVzIHRoZW4KICAgICAgICBnZW9fYXZhaWxhYmxlLCBnZW9fcmVhc29uLCBnZW9fZGIgPSBnZW8uc3RhdHVzKCkKICAgIGVuZAoKICAgIGxvY2FsIGRpY3RzID0ge30KICAgIGZvciBfLCBuYW1lIGluIGlwYWlycyh7ICJhbmFseXRpY3MiLCAicmVxdWVzdF9kYXRhIiwgInJ1bGVzIiwgInJsX2NvdW50ZXJzIiwgInZpc2l0b3JzIiB9KSBkbwogICAgICAgIGxvY2FsIGQgPSBuZ3guc2hhcmVkW25hbWVdCiAgICAgICAgaWYgZCB0aGVuCiAgICAgICAgICAgIGRpY3RzW25hbWVdID0gewogICAgICAgICAgICAgICAgY2FwYWNpdHkgICA9IGQuY2FwYWNpdHkgYW5kIGQ6Y2FwYWNpdHkoKSBvciBuaWwsCiAgICAgICAgICAgICAgICBmcmVlX3NwYWNlID0gZC5mcmVlX3NwYWNlIGFuZCBkOmZyZWVfc3BhY2UoKSBvciBuaWwsCiAgICAgICAgICAgIH0KICAgICAgICBlbmQKICAgIGVuZAoKICAgIHJldHVybiBqc29uKHsKICAgICAgICBvayAgPSB0cnVlLAogICAgICAgIGdlbyA9IHsgYXZhaWxhYmxlID0gZ2VvX2F2YWlsYWJsZSwgcmVhc29uID0gZ2VvX3JlYXNvbiwgZGIgPSBnZW9fZGIgfSwKICAgICAgICBkaWN0cyA9IGRpY3RzLAogICAgfSkKZW5kCgotLSDilIDilIAgL3J1bGVzIC0gcGVyLXJvdXRlIHJ1bGVzIGNhY2hlICh3cml0dGVuIGJ5IHRoZSBBUEksIHJlYWQgYnkgcnVsZXNfZ3VhcmQpIOKUgOKUgAotLSBQT1NUIC9ydWxlcyAgYm9keTogeyAiaG9zdCI6ICIuLi4iLCAicnVsZXMiOiBbIHsgInBhdGhQcmVmaXgiOiAiLyIsICJzcGVjIjogey4uLn0gfSBdIH0KLS0gICDihpIgcmVwbGFjZXMgdGhlIHJ1bGVzZXQgZm9yIHRoYXQgaG9zdCBpbiB0aGUgYHJ1bGVzYCBzaGFyZWQgZGljdCAocmVsb2FkLWZyZWUpLgotLSAgIEFuIGVtcHR5L2Fic2VudCBgcnVsZXNgIGFycmF5IGNsZWFycyB0aGUgaG9zdC4KLS0gR0VUICAvcnVsZXM/aG9zdD0uLi4gICDihpIgdGhlIHN0b3JlZCBydWxlc2V0IChkZWJ1ZykuCi0tIERFTEVURSAvcnVsZXM/aG9zdD0uLi4g4oaSIGNsZWFyIHRoZSBob3N0J3MgcnVsZXNldC4KLS0gSGFuZGxlZCBCRUZPUkUgdGhlIGFuYWx5dGljcyBndWFyZDogcnVsZXMgdXNlIHRoZWlyIG93biBkaWN0LgotLSDilIDilIAgL2FuYWx5dGljcy9jb25maWcgLSBwZXItaG9zdCBjb2xsZWN0aW9uIHN3aXRjaGVzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAotLQotLSBQT1NUIGJvZHk6IHsgImhvc3RzIjogWyB7ICJob3N0IjogIi4uLiIsICJwYXRocyI6IHRydWV8ZmFsc2UgfSwgLi4uIF0gfQotLSBHRVQgID9ob3N0PS4uLiAg4oaSIHsgaG9zdCwgcGF0aHMgfQotLQotLSBBIExJU1QsIG5vdCBhIHNpbmdsZSBob3N0OiBhIHNoYXJlZCBkaWN0IGlzIFJBTSwgc28gYSBmdWxsIG5naW54IHJlc3RhcnQgKGEgcmVib290LCBhCi0tIGBkb2NrZXIgcmVzdGFydGAsIGEgcGFja2FnZSB1cGdyYWRlKSBlbXB0aWVzIGl0IGFuZCBldmVyeSBob3N0IG9uIHRoZSBib3ggaGFzIHRvIGJlCi0tIHJlLXNldCBhdCBvbmNlLiBgb3BlbnJlc3R5IC1zIHJlbG9hZGAgcHJlc2VydmVzIHRoZSB6b25lIOKAlCB2ZXJpZmllZCDigJQgc28gb25seSBhIHJlYWwKLS0gcmVzdGFydCBsb3NlcyBpdCwgd2hpY2ggaXMgd2h5IHRoZSByZWNvbmNpbGUgYmVsb3cgZXhpc3RzIGFuZCB3aHkgaXQgbmVlZHMgdG8gY29zdCBvbmUKLS0gcm91bmQgdHJpcCBwZXIgc2VydmVyIHJhdGhlciB0aGFuIG9uZSBwZXIgZG9tYWluLgotLQotLSBMaXZlcyBpbiB0aGUgYHJ1bGVzYCB6b25lIHJhdGhlciB0aGFuIGBhbmFseXRpY3NgIGZvciB0aGUgcmVhc29uIHNpdGVfbG9nZ2VyIHN0YXRlczoKLS0gdGhlIGFuYWx5dGljcyB6b25lIGlzIGEgMjU2IE1CIGNodXJuIG9mIGNvdW50ZXJzIHVuZGVyIExSVSBwcmVzc3VyZSwgYW5kIGFuIGV2aWN0ZWQKLS0gY29uZmlnIGZsYWcgd291bGQgc2lsZW50bHkgY2hhbmdlIHdoYXQgaXMgY29sbGVjdGVkLiBUaGlzIHpvbmUgaG9sZHMgYSBmZXcgc21hbGwgdmFsdWVzLgotLQotLSBEZWxpYmVyYXRlbHkgaXRzIG93biBlbmRwb2ludCByYXRoZXIgdGhhbiBhIGZpZWxkIG9uIC9ydWxlczogdGhlIEFQSSBvbmx5IHB1c2hlcyAvcnVsZXMKLS0gZm9yIGhvc3RzIHRoYXQgSEFWRSBydWxlcywgc28gYSBwcm9qZWN0IHdpdGggbm9uZSB3b3VsZCBuZXZlciByZWNlaXZlIHRoaXMgZmxhZy4KLS0KLS0gTm8gVFRMIOKAlCBhIHNoYXJlZCBkaWN0IGlzIFJBTSBhbmQgaXMgbG9zdCBvbiByZXN0YXJ0IGVpdGhlciB3YXksIHNvIHRoZSBBUEkgcmUtcHVzaGVzIG9uCi0tIGV2ZXJ5IHJvdXRlIGFwcGx5IGFuZCB0aGUgZGF0YWJhc2Ugc3RheXMgdGhlIHNvdXJjZSBvZiB0cnV0aC4KaWYgdXJpID09ICIvYW5hbHl0aWNzL2NvbmZpZyIgdGhlbgogICAgbG9jYWwgcnVsZXMgPSBuZ3guc2hhcmVkLnJ1bGVzCiAgICBpZiBub3QgcnVsZXMgdGhlbiByZXR1cm4ganNvbih7IGVycm9yID0gInJ1bGVzIGRpY3QgdW5hdmFpbGFibGUiIH0sIDUwMykgZW5kCiAgICBsb2NhbCBtZXRob2QgPSBuZ3gucmVxLmdldF9tZXRob2QoKQoKICAgIGlmIG1ldGhvZCA9PSAiR0VUIiB0aGVuCiAgICAgICAgbG9jYWwgaG9zdCA9IG5neC52YXIuYXJnX2hvc3QKICAgICAgICBpZiBub3QgaG9zdCBvciBob3N0ID09ICIiIHRoZW4gcmV0dXJuIGJhZCgibWlzc2luZyA/aG9zdD0iKSBlbmQKICAgICAgICBob3N0ID0gaG9zdDpsb3dlcigpCiAgICAgICAgcmV0dXJuIGpzb24oeyBob3N0ID0gaG9zdCwgcGF0aHMgPSBydWxlczpnZXQoImNmZzoiIC4uIGhvc3QgLi4gIjpwYXRocyIpID09IDEgfSkKICAgIGVuZAoKICAgIGlmIG1ldGhvZCA9PSAiUE9TVCIgdGhlbgogICAgICAgIG5neC5yZXEucmVhZF9ib2R5KCkKICAgICAgICBsb2NhbCBib2R5ID0gbmd4LnJlcS5nZXRfYm9keV9kYXRhKCkKICAgICAgICBpZiBub3QgYm9keSB0aGVuIHJldHVybiBiYWQoImVtcHR5IGJvZHkiKSBlbmQKICAgICAgICBsb2NhbCBwYXlsb2FkID0gY2pzb24uZGVjb2RlKGJvZHkpCiAgICAgICAgaWYgdHlwZShwYXlsb2FkKSB+PSAidGFibGUiIG9yIHR5cGUocGF5bG9hZC5ob3N0cykgfj0gInRhYmxlIiB0aGVuCiAgICAgICAgICAgIHJldHVybiBiYWQoImV4cGVjdGVkIHsgaG9zdHM6IFsgeyBob3N0LCBwYXRocyB9IF0gfSIpCiAgICAgICAgZW5kCiAgICAgICAgbG9jYWwgYXBwbGllZCA9IDAKICAgICAgICBmb3IgXywgZW50cnkgaW4gaXBhaXJzKHBheWxvYWQuaG9zdHMpIGRvCiAgICAgICAgICAgIGlmIHR5cGUoZW50cnkpID09ICJ0YWJsZSIgYW5kIGVudHJ5Lmhvc3QgdGhlbgogICAgICAgICAgICAgICAgbG9jYWwga2V5ID0gImNmZzoiIC4uIHRvc3RyaW5nKGVudHJ5Lmhvc3QpOmxvd2VyKCkgLi4gIjpwYXRocyIKICAgICAgICAgICAgICAgIGlmIGVudHJ5LnBhdGhzID09IHRydWUgdGhlbgogICAgICAgICAgICAgICAgICAgIHJ1bGVzOnNldChrZXksIDEpCiAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgLS0gRGVsZXRlZCByYXRoZXIgdGhhbiBzZXQgdG8gMCwgc28gImFic2VudCIgaXMgdGhlIG9ubHkgb2ZmIHN0YXRlIHRoZXJlCiAgICAgICAgICAgICAgICAgICAgLS0gaXMuIFR3byByZXByZXNlbnRhdGlvbnMgb2Ygb2ZmIGlzIGhvdyBhIHJlYWRlciBlbmRzIHVwIHRyZWF0aW5nIG9uZSBvZgogICAgICAgICAgICAgICAgICAgIC0tIHRoZW0gYXMgb24g4oCUIGFuZCBhYnNlbnQgaXMgYWxzbyB3aGF0IGEgcmVzdGFydGVkIGJveCBzdGFydHMgZnJvbSwgc28KICAgICAgICAgICAgICAgICAgICAtLSBvZmYgaGFzIHRvIG1lYW4gZXhhY3RseSB0aGUgc2FtZSB0aGluZyBpbiBib3RoIGNhc2VzLgogICAgICAgICAgICAgICAgICAgIHJ1bGVzOmRlbGV0ZShrZXkpCiAgICAgICAgICAgICAgICBlbmQKICAgICAgICAgICAgICAgIGFwcGxpZWQgPSBhcHBsaWVkICsgMQogICAgICAgICAgICBlbmQKICAgICAgICBlbmQKICAgICAgICByZXR1cm4ganNvbih7IG9rID0gdHJ1ZSwgYXBwbGllZCA9IGFwcGxpZWQgfSkKICAgIGVuZAoKICAgIHJldHVybiBqc29uKHsgZXJyb3IgPSAibWV0aG9kIG5vdCBhbGxvd2VkIiB9LCA0MDUpCmVuZAoKaWYgdXJpID09ICIvcnVsZXMiIHRoZW4KICAgIGxvY2FsIHJ1bGVzID0gbmd4LnNoYXJlZC5ydWxlcwogICAgaWYgbm90IHJ1bGVzIHRoZW4gcmV0dXJuIGpzb24oeyBlcnJvciA9ICJydWxlcyBkaWN0IHVuYXZhaWxhYmxlIiB9LCA1MDMpIGVuZAogICAgbG9jYWwgbWV0aG9kID0gbmd4LnJlcS5nZXRfbWV0aG9kKCkKCiAgICBpZiBtZXRob2QgPT0gIkdFVCIgdGhlbgogICAgICAgIGxvY2FsIGhvc3QgPSBuZ3gudmFyLmFyZ19ob3N0CiAgICAgICAgaWYgbm90IGhvc3Qgb3IgaG9zdCA9PSAiIiB0aGVuIHJldHVybiBiYWQoIm1pc3NpbmcgP2hvc3Q9IikgZW5kCiAgICAgICAgaG9zdCA9IGhvc3Q6bG93ZXIoKQogICAgICAgIGxvY2FsIHJhdyA9IHJ1bGVzOmdldChob3N0KQogICAgICAgIHJldHVybiBqc29uKHsgaG9zdCA9IGhvc3QsIHJ1bGVzID0gcmF3IGFuZCBjanNvbi5kZWNvZGUocmF3KSBvciB7fSB9KQogICAgZW5kCgogICAgaWYgbWV0aG9kID09ICJERUxFVEUiIHRoZW4KICAgICAgICBsb2NhbCBob3N0ID0gbmd4LnZhci5hcmdfaG9zdAogICAgICAgIGlmIG5vdCBob3N0IG9yIGhvc3QgPT0gIiIgdGhlbiByZXR1cm4gYmFkKCJtaXNzaW5nID9ob3N0PSIpIGVuZAogICAgICAgIHJ1bGVzOmRlbGV0ZShob3N0Omxvd2VyKCkpCiAgICAgICAgcmV0dXJuIGpzb24oeyBvayA9IHRydWUgfSkKICAgIGVuZAoKICAgIGlmIG1ldGhvZCA9PSAiUE9TVCIgdGhlbgogICAgICAgIG5neC5yZXEucmVhZF9ib2R5KCkKICAgICAgICBsb2NhbCBib2R5ID0gbmd4LnJlcS5nZXRfYm9keV9kYXRhKCkKICAgICAgICBpZiBub3QgYm9keSB0aGVuIHJldHVybiBiYWQoImVtcHR5IGJvZHkiKSBlbmQKICAgICAgICBsb2NhbCBwYXlsb2FkID0gY2pzb24uZGVjb2RlKGJvZHkpCiAgICAgICAgaWYgdHlwZShwYXlsb2FkKSB+PSAidGFibGUiIG9yIG5vdCBwYXlsb2FkLmhvc3QgdGhlbgogICAgICAgICAgICByZXR1cm4gYmFkKCJleHBlY3RlZCB7IGhvc3QsIHJ1bGVzOiBbLi4uXSB9IikKICAgICAgICBlbmQKICAgICAgICBsb2NhbCBob3N0ID0gdG9zdHJpbmcocGF5bG9hZC5ob3N0KTpsb3dlcigpCiAgICAgICAgbG9jYWwgbGlzdCA9IHBheWxvYWQucnVsZXMKICAgICAgICBpZiB0eXBlKGxpc3QpIH49ICJ0YWJsZSIgb3IgI2xpc3QgPT0gMCB0aGVuCiAgICAgICAgICAgIHJ1bGVzOmRlbGV0ZShob3N0KSAgICAgICAgICAgICAgICAgLS0gZW1wdHkgc2V0ID0gY2xlYXIgdGhlIGhvc3QKICAgICAgICAgICAgcmV0dXJuIGpzb24oeyBvayA9IHRydWUsIGhvc3QgPSBob3N0LCBjb3VudCA9IDAgfSkKICAgICAgICBlbmQKICAgICAgICBsb2NhbCBvaywgZXJyID0gcnVsZXM6c2V0KGhvc3QsIGNqc29uLmVuY29kZShsaXN0KSkKICAgICAgICBpZiBub3Qgb2sgdGhlbiByZXR1cm4ganNvbih7IGVycm9yID0gInNldCBmYWlsZWQ6ICIgLi4gKGVyciBvciAiPyIpIH0sIDUwMCkgZW5kCiAgICAgICAgcmV0dXJuIGpzb24oeyBvayA9IHRydWUsIGhvc3QgPSBob3N0LCBjb3VudCA9ICNsaXN0IH0pCiAgICBlbmQKCiAgICByZXR1cm4ganNvbih7IGVycm9yID0gIm1ldGhvZCBub3QgYWxsb3dlZCIgfSwgNDA1KQplbmQKCmlmIG5vdCBhbmFseXRpY3MgdGhlbgogICAgcmV0dXJuIGpzb24oeyBlcnJvciA9ICJhbmFseXRpY3MgZGljdCB1bmF2YWlsYWJsZSIgfSwgNTAzKQplbmQKCi0tIOKUgOKUgCBQZXItbWludXRlIGNvdW50cnkgaW5kZXgg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tCi0tIHNpdGVfbG9nZ2VyIHdyaXRlcyBvbmUga2V5IHBlciAoZG9tYWluLCBtaW51dGUsIGNvdW50cnkpOiBgYzp7ZG9tYWlufTp7bWlufTp7Q0N9YC4KLS0gUmVhZGluZyB0aGVtIGJhY2sgbmVlZHMga2V5IERJU0NPVkVSWSwgYW5kIGBnZXRfa2V5c2AgaXMgdGhlIG9ubHkgbWVjaGFuaXNtLgotLQotLSBUaGlzIHVzZWQgdG8gc2l0IElOU0lERSB0aGUgcGVyLW1pbnV0ZSBsb29wLCBzbyBhIDI0aCB3aW5kb3cgcmFuIHVwIHRvIDE0NDAKLS0gYGdldF9rZXlzKDEwMDAwKWAgY2FsbHMg4oCUIGVhY2ggYSBmdWxsIHNjYW4gb2YgYSAyNTYgTUIgem9uZSwgZWFjaCBob2xkaW5nIHRoZQotLSBkaWN0IGxvY2sgYWdhaW5zdCBldmVyeSB3b3JrZXIuIE9uZSBzY2FuIHBlciByZXF1ZXN0IGluc3RlYWQsIGJ1Y2tldGVkIGJ5Ci0tIG1pbnV0ZSBpbiBhIHNpbmdsZSBwYXNzOyB0aGUgbG9vcCB0aGVuIGRvZXMgcGxhaW4gdGFibGUgbG9va3Vwcy4KLS0KLS0gYGdldF9rZXlzKDApYCAoYWxsIGtleXMpIHJhdGhlciB0aGFuIDEwMDAwOiB0aGUgY2FwIHNpbGVudGx5IFRSVU5DQVRFRCwgc28gYQotLSBidXN5IGJveCBqdXN0IGxvc3QgY291bnRyaWVzIHdpdGggbm8gZXJyb3IuIFVuYm91bmRlZCBpcyBzYWZlIHByZWNpc2VseSBiZWNhdXNlCi0tIHRoaXMgaXMgbm93IGNhbGxlZCBvbmNlIOKAlCBzZWUgdGhlIGNvbW1lbnQgb24gdGhlIGNhbGwuCi0tLSBSZWFkIGFuIGVudW1lcmFibGUgc2V0IHdyaXR0ZW4gYnkgc2l0ZV9sb2dnZXIncyBpbmRleF9hZGQuCi0tCi0tIFJlcGxhY2VzIGBnZXRfa2V5c2AsIHdoaWNoIHdhbGtlZCBFVkVSWSBrZXkgaW4gdGhlIDI1NiBNQiB6b25lIGhvbGRpbmcgaXRzIGxvY2sg4oCUIGNvc3QKLS0gcHJvcG9ydGlvbmFsIHRvIHpvbmUgcG9wdWxhdGlvbiByYXRoZXIgdGhhbiB0byB0aGUgYW5zd2VyLCBvbiBhIHBhdGggY2FsbGVkIGZvdXIKLS0gZGlmZmVyZW50IHdheXMuIEhlcmUgdGhlIGNvdW50ZXIgc2F5cyBob3cgbWFueSBtZW1iZXJzIGV4aXN0IGFuZCB0aGUgc2xvdHMgbmFtZSB0aGVtLCBzbwotLSBhIHJlYWQgY29zdHMgZXhhY3RseSBhcyBtdWNoIGFzIHRoZSBkYXRhIGl0IHJldHVybnMuCi0tCi0tIE92ZXItcmVhZHMgc2xpZ2h0bHkgYnkgZGVzaWduOiBhIHNsb3QgY2FuIGJlIHdyaXR0ZW4gdHdpY2UgaWYgdHdvIHdvcmtlcnMgcmFjZSBvbiBhCi0tIG1lbWJlcidzIGZpcnN0IHNpZ2h0aW5nLCBhbmQgc2xvdHMgb3V0bGl2ZSBub3RoaW5nIChzYW1lIFRUTCBhcyB0aGVpciBjb3VudGVycykuIEJvdGgKLS0gY29sbGFwc2UgaGFybWxlc3NseSBiZWNhdXNlIHRoZSBjYWxsZXIga2V5cyByZXN1bHRzIGJ5IG1lbWJlci4KbG9jYWwgZnVuY3Rpb24gcmVhZF9pbmRleChjb3VudGVyX2tleSwgc2xvdF9wcmVmaXgpCiAgICBsb2NhbCBuID0gdG9udW1iZXIoYW5hbHl0aWNzOmdldChjb3VudGVyX2tleSkpIG9yIDAKICAgIGlmIG4gPD0gMCB0aGVuIHJldHVybiB7fSBlbmQKICAgIGxvY2FsIG91dCwgc2VlbiA9IHt9LCB7fQogICAgZm9yIGkgPSAxLCBuIGRvCiAgICAgICAgbG9jYWwgbSA9IGFuYWx5dGljczpnZXQoc2xvdF9wcmVmaXggLi4gaSkKICAgICAgICBpZiBtIGFuZCBub3Qgc2VlblttXSB0aGVuCiAgICAgICAgICAgIHNlZW5bbV0gPSB0cnVlCiAgICAgICAgICAgIG91dFsjb3V0ICsgMV0gPSBtCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJldHVybiBvdXQKZW5kCgotLS0gRHJhaW4gYSBjb3VudGVyIFdJVEhPVVQgbG9zaW5nIGEgY29uY3VycmVudCBpbmNyZW1lbnQuCi0tCi0tIFdhcyBgZ2V0YCB0aGVuIGBkZWxldGVgOiBhIHJlcXVlc3QgbGFuZGluZyBiZXR3ZWVuIHRoZSB0d28gaGFkIGl0cyBjb3VudCBkZWxldGVkIGFsb25nCi0tIHdpdGggdGhlIHZhbHVlIHRoYXQgaGFkIGp1c3QgYmVlbiByZWFkLiBTdWJ0cmFjdGluZyBleGFjdGx5IHdoYXQgd2FzIHJlYWQgbGVhdmVzIGFueQotLSBjb25jdXJyZW50IGluY3JlbWVudCBiZWhpbmQgYXMgYSByZXNpZHVhbCB0aGUgbmV4dCBzY3JhcGUgY29sbGVjdHMuCmxvY2FsIGZ1bmN0aW9uIGRyYWluKGtleSkKICAgIGxvY2FsIHYgPSB0b251bWJlcihhbmFseXRpY3M6Z2V0KGtleSkpIG9yIDAKICAgIGlmIHYgfj0gMCB0aGVuIGFuYWx5dGljczppbmNyKGtleSwgLXYpIGVuZAogICAgcmV0dXJuIHYKZW5kCgotLS0gT25lIGRheSdzIHJvbGx1cCBmb3Igb25lIGRvbWFpbiwgcmVhZCB0aHJvdWdoIGl0cyBpbmRleGVzLgotLQotLSBSZXR1cm5zIHRoZSBzYW1lIGBzdWZmaXgg4oaSIHZhbHVlYCBzaGFwZSB0aGUgb2xkIHdob2xlLXpvbmUgY2xhc3NpZmllciBwcm9kdWNlZCwgc28gYm90aAotLSBjYWxsZXJzIHN0YXllZCB1bmNoYW5nZWQ6IGJhcmUgY291bnRyeSBjb2RlcywgYHM6e2NvZGV9YCwgYHA6e3BhdGh9YCwgYHZgLCBgcG5gLgpsb2NhbCBmdW5jdGlvbiByZWFkX3JvbGx1cChkb21haW4sIGRheSkKICAgIGxvY2FsIGdwZnggPSAiZzoiIC4uIGRvbWFpbiAuLiAiOiIgLi4gZGF5IC4uICI6IgogICAgbG9jYWwgb3V0ID0ge30KCiAgICBmb3IgXywgY2MgaW4gaXBhaXJzKHJlYWRfaW5kZXgoZ3BmeCAuLiAiY24iLCBncGZ4IC4uICJjaToiKSkgZG8KICAgICAgICBvdXRbY2NdID0gdG9udW1iZXIoYW5hbHl0aWNzOmdldChncGZ4IC4uIGNjKSkgb3IgMAogICAgZW5kCiAgICBmb3IgXywgY29kZSBpbiBpcGFpcnMocmVhZF9pbmRleChncGZ4IC4uICJzbiIsIGdwZnggLi4gInNpOiIpKSBkbwogICAgICAgIG91dFsiczoiIC4uIGNvZGVdID0gdG9udW1iZXIoYW5hbHl0aWNzOmdldChncGZ4IC4uICJzOiIgLi4gY29kZSkpIG9yIDAKICAgIGVuZAogICAgLS0gYHBuYCBkb3VibGVzIGFzIHRoZSBwYXRoIGluZGV4J3MgY291bnRlciwgc28gcGF0aHMgbmVlZCBubyBzZXBhcmF0ZSBvbmUuIFdoZW4gcGF0aAogICAgLS0gY29sbGVjdGlvbiBpcyBzd2l0Y2hlZCBvZmYgZm9yIHRoaXMgaG9zdCB0aGVyZSBpcyBubyBjb3VudGVyIGFuZCB0aGlzIHJlYWRzIG5vdGhpbmcuCiAgICBmb3IgXywgcGF0aCBpbiBpcGFpcnMocmVhZF9pbmRleChncGZ4IC4uICJwbiIsIGdwZnggLi4gInBpOiIpKSBkbwogICAgICAgIG91dFsicDoiIC4uIHBhdGhdID0gdG9udW1iZXIoYW5hbHl0aWNzOmdldChncGZ4IC4uICJwOiIgLi4gcGF0aCkpIG9yIDAKICAgIGVuZAogICAgLS0gVGhlIG92ZXItY2FwIGJ1Y2tldCBoYXMgYSBmaXhlZCBuYW1lLCBzbyBpdCBpcyBub3QgaW4gdGhlIGluZGV4LgogICAgbG9jYWwgb3RoZXIgPSB0b251bWJlcihhbmFseXRpY3M6Z2V0KGdwZnggLi4gInA6b3RoZXIiKSkKICAgIGlmIG90aGVyIHRoZW4gb3V0WyJwOm90aGVyIl0gPSBvdGhlciBlbmQKCiAgICBsb2NhbCB2ID0gdG9udW1iZXIoYW5hbHl0aWNzOmdldChncGZ4IC4uICJ2IikpCiAgICBpZiB2IHRoZW4gb3V0WyJ2Il0gPSB2IGVuZAogICAgcmV0dXJuIG91dAplbmQKCmxvY2FsIGZ1bmN0aW9uIHNjYW5fY291bnRyeV9pbmRleChkb21haW4sIGZyb21fbSwgdG9fbSkKICAgIC0tIFdhbGtzIHRoZSByZXF1ZXN0ZWQgTUlOVVRFUyBhbmQgcmVhZHMgZWFjaCBvbmUncyBvd24gaW5kZXguIEJvdW5kZWQgYnkgdGhlIHdpbmRvdwogICAgLS0gKGNhcHBlZCBhdCAxNDQwIGJ5IHRoZSBjYWxsZXIpLCBub3QgYnkgaG93IG11Y2ggaXMgaW4gdGhlIHpvbmUuCiAgICBsb2NhbCBieV9taW51dGUgPSB7fQogICAgZm9yIG0gPSBmcm9tX20sIHRvX20gZG8KICAgICAgICBsb2NhbCBtcGZ4ID0gImM6IiAuLiBkb21haW4gLi4gIjoiIC4uIG0gLi4gIjoiCiAgICAgICAgbG9jYWwgY2NzID0gcmVhZF9pbmRleChtcGZ4IC4uICJuIiwgbXBmeCAuLiAiaToiKQogICAgICAgIGlmICNjY3MgPiAwIHRoZW4KICAgICAgICAgICAgbG9jYWwgc2xvdCA9IHt9CiAgICAgICAgICAgIGZvciBpID0gMSwgI2NjcyBkbwogICAgICAgICAgICAgICAgLS0gRnVsbCBrZXksIGJlY2F1c2UgdGhlIGZsdXNoIGRyYWlucyBieSBrZXkuCiAgICAgICAgICAgICAgICBzbG90W2Njc1tpXV0gPSBtcGZ4IC4uIGNjc1tpXQogICAgICAgICAgICBlbmQKICAgICAgICAgICAgYnlfbWludXRlW21dID0gc2xvdAogICAgICAgIGVuZAogICAgZW5kCiAgICByZXR1cm4gYnlfbWludXRlCmVuZAoKLS0tIFNwbGl0IGEgbmFtZXNwYWNlZCBhbmFseXRpY3Mga2V5IGludG8ga2luZCAvIGRvbWFpbiAvIG1pZCAvIHJlc3QuCi0tCi0tIExheW91dHM6IGBjOntkb21haW59OnttaW51dGV9OntDQ31gIGFuZCBgZzp7ZG9tYWlufTp7ZGF5fTp7c3VmZml4fWAuCi0tIFBvc2l0aW9uYWwsIE5PVCBhIGZ1bGwgc3BsaXQgb24gIjoiLCBiZWNhdXNlIGBzdWZmaXhgIGxlZ2l0aW1hdGVseSBjb250YWlucwotLSBjb2xvbnMg4oCUIGEgbm9ybWFsaXplZCBwYXRoIGtleSBsb29rcyBsaWtlIGBnOnguY29tOjIwMjYwODAzOnA6L3VzZXJzLzppZGAuCi0tIEhvc3RuYW1lcyBjYW5ub3QgY29udGFpbiAiOiIsIHNvIHRoZSBmaXJzdCB0aHJlZSBzZXBhcmF0b3JzIGFyZSB1bmFtYmlndW91cy4KbG9jYWwgZnVuY3Rpb24gc3BsaXRfa2V5KGspCiAgICBsb2NhbCBwMSA9IGs6ZmluZCgiOiIsIDEsIHRydWUpCiAgICBpZiBub3QgcDEgdGhlbiByZXR1cm4gbmlsIGVuZAogICAgbG9jYWwgcDIgPSBrOmZpbmQoIjoiLCBwMSArIDEsIHRydWUpCiAgICBpZiBub3QgcDIgdGhlbiByZXR1cm4gbmlsIGVuZAogICAgbG9jYWwgcDMgPSBrOmZpbmQoIjoiLCBwMiArIDEsIHRydWUpCiAgICBpZiBub3QgcDMgdGhlbgogICAgICAgIHJldHVybiBrOnN1YigxLCBwMSAtIDEpLCBrOnN1YihwMSArIDEsIHAyIC0gMSksIGs6c3ViKHAyICsgMSksIG5pbAogICAgZW5kCiAgICByZXR1cm4gazpzdWIoMSwgcDEgLSAxKSwgazpzdWIocDEgKyAxLCBwMiAtIDEpLCBrOnN1YihwMiArIDEsIHAzIC0gMSksIGs6c3ViKHAzICsgMSkKZW5kCgotLS0gUmVhZCBvbmUgbWludXRlJ3MgY291bnRyeSBjb3VudHMgb3V0IG9mIGEgc2Nhbm5lZCBpbmRleC4KLS0gQHBhcmFtIHNsb3QgdGFibGV8bmlsICBDQyDihpIgZnVsbCBkaWN0IGtleSwgZnJvbSBzY2FuX2NvdW50cnlfaW5kZXgKLS0gQHBhcmFtIGRlbCBib29sZWFuICAgICBkcmFpbiBlYWNoIGtleSBhZnRlciByZWFkaW5nIChmbHVzaCBzZW1hbnRpY3MpCi0tIEByZXR1cm4gdGFibGV8bmlsIGNvdW50cywgb3IgbmlsIHdoZW4gdGhlIG1pbnV0ZSBoYWQgbm8gY291bnRyeSBkYXRhCmxvY2FsIGZ1bmN0aW9uIHJlYWRfbWludXRlX2NvdW50cmllcyhzbG90LCBkZWwpCiAgICBpZiBub3Qgc2xvdCB0aGVuIHJldHVybiBuaWwgZW5kCiAgICBsb2NhbCBjb3VudHMsIGFueSA9IHt9LCBmYWxzZQogICAgZm9yIGNjLCBrZXkgaW4gcGFpcnMoc2xvdCkgZG8KICAgICAgICAtLSBgZHJhaW5gIHN1YnRyYWN0cyB3aGF0IGl0IHJlYWQgaW5zdGVhZCBvZiBkZWxldGluZywgc28gYSByZXF1ZXN0IGFycml2aW5nCiAgICAgICAgLS0gbWlkLWZsdXNoIGlzIG5vdCB0aHJvd24gYXdheSB3aXRoIHRoZSB2YWx1ZSB0aGF0IHdhcyBqdXN0IHJlYWQuCiAgICAgICAgY291bnRzW2NjXSA9IGRlbCBhbmQgZHJhaW4oa2V5KSBvciAodG9udW1iZXIoYW5hbHl0aWNzOmdldChrZXkpKSBvciAwKQogICAgICAgIGFueSA9IHRydWUKICAgIGVuZAogICAgcmV0dXJuIGFueSBhbmQgY291bnRzIG9yIG5pbAplbmQKCi0tIOKUgOKUgCBQT1NUIC9hbmFseXRpY3MvY29sbGVjdCAtIHRoZSBTQ1JBUEVSJ3MgZW5kcG9pbnQ6IGV2ZXJ5IGRvbWFpbiwgT05FIHNjYW4g4pSA4pSACi0tCi0tIEJvZHk6IHsgImRheSI6ICJZWVlZTU1ERCIsICJkb21haW5zIjogWyB7ICJkb21haW4iOiAieC5jb20iLCAiZnJvbSI6IE0sICJ0byI6IE0gfSBdIH0KLS0gUmV0dXJuczogeyAiZG9tYWlucyI6IHsgInguY29tIjogeyBidWNrZXRzOiBbLi4uXSwgZmx1c2hlZDogTiwgcm9sbHVwOiB7Li4ufSB9IH0gfQotLQotLSBXaHkgdGhpcyBleGlzdHMgcmF0aGVyIHRoYW4gbG9vcGluZyB0aGUgc2luZ2xlLWRvbWFpbiBlbmRwb2ludHM6Ci0tCi0tIGBnZXRfa2V5c2AgaXMgdGhlIG9ubHkga2V5LWRpc2NvdmVyeSBtZWNoYW5pc20gYSBzaGFyZWQgZGljdCBvZmZlcnMsIGl0IHdhbGtzIHRoZQotLSBXSE9MRSB6b25lLCBhbmQgaXQgaG9sZHMgdGhlIGRpY3QgbG9jayBhZ2FpbnN0IGV2ZXJ5IG5naW54IHdvcmtlciB3aGlsZSBpdCBkb2VzLgotLSBUaGUgc2NyYXBlciBuZWVkcyBib3RoIHRoZSBwZXItbWludXRlIGNvdW50cmllcyAoZmx1c2gpIGFuZCB0aGUgZGFpbHkgcm9sbHVwIGZvcgotLSBlYWNoIGRvbWFpbiwgc28gY2FsbGluZyB0aGUgcGVyLWRvbWFpbiBlbmRwb2ludHMgY29zdCAyTisxIHVuYm91bmRlZCBzY2FucyBvZiBhCi0tIDI1NiBNQiB6b25lIOKAlCBwbHVzIDJOKzEgU1NIL2V4ZWMgcm91bmQgdHJpcHMg4oCUIGV2ZXJ5IHN3ZWVwLiBPbiBhIDUwLWRvbWFpbiBib3gKLS0gdGhhdCBpcyAxMDEgZnVsbCBzY2FucyBhbmQgMTAxIHJvdW5kIHRyaXBzLCBvbiBhIHNjaGVkdWxlLCB0byBjb2xsZWN0IGRhdGEgdGhhdAotLSBvbmUgcGFzcyBhbHJlYWR5IGhhcyBpbiBoYW5kLgotLQotLSBTbzogb25lIGBnZXRfa2V5cygwKWAsIGNsYXNzaWZ5IGV2ZXJ5IGtleSBieSAoa2luZCwgZG9tYWluKSBpbiBhIHNpbmdsZSBwYXNzLCB0aGVuCi0tIHNlcnZlIGFsbCBkb21haW5zIGZyb20gdGhlIGluLW1lbW9yeSBpbmRleC4gMk4rMSBzY2FucyDihpIgMSwgYW5kIDJOKzEgcm91bmQgdHJpcHMKLS0g4oaSIDEuIFRoZSBwZXItZG9tYWluIEdFVCBlbmRwb2ludHMgc3RheSBmb3IgdGhlIFJFQUQgcGF0aCwgd2hlcmUgYSBwYWdlIHZpZXcgd2FudHMKLS0gb25lIGRvbWFpbidzIGxpdmUgdGFpbCBhbmQgYSBzaW5nbGUgc2NhbiBpcyB0aGUgaG9uZXN0IGNvc3QuCi0tCi0tIEZsdXNoIHNlbWFudGljcyBhcmUgdW5jaGFuZ2VkIGFuZCBzdGlsbCBhdG9taWMgcGVyIGtleTogbWludXRlIGNvdW50ZXJzIGFuZCB0aGVpcgotLSBjb3VudHJ5IGtleXMgYXJlIGRlbGV0ZWQgYXMgdGhleSBhcmUgcmVhZCwgc28gYSBidWNrZXQgaXMgaGFuZGVkIHRvIGV4YWN0bHkgb25lCi0tIGNhbGxlciBubyBtYXR0ZXIgaG93IG1hbnkgY29sbGVjdG9ycyByYWNlLiBUaGUgZGFpbHkgcm9sbHVwIGlzIHJlYWQtb25seSDigJQgdGhlCi0tIGVkZ2Uga2VlcHMgcnVubmluZyB0b3RhbHMgZm9yIHRoZSBkYXksIGFuZCBkZWxldGluZyB0aGVtIHdvdWxkIGxvc2UgdGhlIHRvdGFscyBmb3IKLS0gZXZlcnkgbGF0ZXIgc2NyYXBlIG9mIHRoZSBzYW1lIGRheS4KCmlmIHVyaSA9PSAiL2FuYWx5dGljcy9jb2xsZWN0IiBhbmQgbmd4LnJlcS5nZXRfbWV0aG9kKCkgPT0gIlBPU1QiIHRoZW4KICAgIG5neC5yZXEucmVhZF9ib2R5KCkKICAgIGxvY2FsIGJvZHkgPSBuZ3gucmVxLmdldF9ib2R5X2RhdGEoKQogICAgaWYgbm90IGJvZHkgdGhlbiByZXR1cm4gYmFkKCJlbXB0eSBib2R5IikgZW5kCiAgICBsb2NhbCBwYXlsb2FkID0gY2pzb24uZGVjb2RlKGJvZHkpCiAgICBpZiB0eXBlKHBheWxvYWQpIH49ICJ0YWJsZSIgb3IgdHlwZShwYXlsb2FkLmRvbWFpbnMpIH49ICJ0YWJsZSIgdGhlbgogICAgICAgIHJldHVybiBiYWQoJ2V4cGVjdGVkIHsgZGF5LCBkb21haW5zOiBbe2RvbWFpbiwgZnJvbSwgdG99XSB9JykKICAgIGVuZAoKICAgIGxvY2FsIGRheSA9IHBheWxvYWQuZGF5CiAgICBpZiB0eXBlKGRheSkgfj0gInN0cmluZyIgb3IgI2RheSB+PSA4IHRoZW4gZGF5ID0gb3MuZGF0ZSgiISVZJW0lZCIpIGVuZAoKICAgIC0tIFJlcXVlc3RlZCBkb21haW5zIOKGkiB0aGVpciBtaW51dGUgd2luZG93LiBBbHNvIHRoZSBtZW1iZXJzaGlwIHRlc3QgdGhlIHNjYW4KICAgIC0tIHVzZXMsIHNvIGFuIHVucmVxdWVzdGVkIGRvbWFpbidzIGtleXMgYXJlIHNraXBwZWQgd2l0aG91dCBhIHN0cmluZyBjb21wYXJlCiAgICAtLSBwZXIgZG9tYWluLgogICAgbG9jYWwgd2FudCwgb3JkZXIgPSB7fSwge30KICAgIGZvciBpID0gMSwgI3BheWxvYWQuZG9tYWlucyBkbwogICAgICAgIGxvY2FsIGQgPSBwYXlsb2FkLmRvbWFpbnNbaV0KICAgICAgICBpZiB0eXBlKGQpID09ICJ0YWJsZSIgYW5kIHR5cGUoZC5kb21haW4pID09ICJzdHJpbmciIGFuZCBkLmRvbWFpbiB+PSAiIiB0aGVuCiAgICAgICAgICAgIGxvY2FsIG5hbWUgPSBkLmRvbWFpbjpsb3dlcigpCiAgICAgICAgICAgIGxvY2FsIGZyb21fbSwgdG9fbSA9IHRvbnVtYmVyKGQuZnJvbSksIHRvbnVtYmVyKGQudG8pCiAgICAgICAgICAgIGlmIGZyb21fbSBhbmQgdG9fbSB0aGVuCiAgICAgICAgICAgICAgICBpZiB0b19tIC0gZnJvbV9tID4gMTQ0MCB0aGVuIHRvX20gPSBmcm9tX20gKyAxNDQwIGVuZCAtLSBjYXAgYXQgMjRoCiAgICAgICAgICAgICAgICBpZiBub3Qgd2FudFtuYW1lXSB0aGVuIG9yZGVyWyNvcmRlciArIDFdID0gbmFtZSBlbmQKICAgICAgICAgICAgICAgIHdhbnRbbmFtZV0gPSB7IGZyb20gPSBmcm9tX20sIHRvID0gdG9fbSB9CiAgICAgICAgICAgIGVuZAogICAgICAgIGVuZAogICAgZW5kCiAgICBpZiAjb3JkZXIgPT0gMCB0aGVuIHJldHVybiBqc29uKHsgZG9tYWlucyA9IHt9IH0pIGVuZAoKICAgIC0tIOKUgOKUgCBQZXItZG9tYWluIGluZGV4IHJlYWRzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAogICAgLS0KICAgIC0tIFdhcyBhIHNpbmdsZSBgZ2V0X2tleXMoMClgIHBhc3MgY2xhc3NpZnlpbmcgZXZlcnkga2V5IGluIHRoZSB6b25lLiBPbmUgc2NhbiBpcyBiZXR0ZXIKICAgIC0tIHRoYW4gMk4rMSwgYnV0IGl0IHN0aWxsIHdhbGtlZCBrZXlzIGJlbG9uZ2luZyB0byBkb21haW5zIG5vYm9keSBhc2tlZCBhYm91dCwgYW5kIGhlbGQKICAgIC0tIHRoZSB6b25lIGxvY2sgd2hpbGUgZG9pbmcgaXQuIE5vdyBlYWNoIHJlcXVlc3RlZCBkb21haW4gcmVhZHMgb25seSBpdHMgb3duIGluZGV4ZXMuCiAgICBsb2NhbCBjb3VudHJpZXMgPSB7fSAgIC0tIGRvbWFpbiDihpIgbWludXRlIOKGkiBDQyDihpIgZGljdCBrZXkKICAgIGxvY2FsIHJvbGx1cHMgPSB7fSAgICAgLS0gZG9tYWluIOKGkiBzdWZmaXgg4oaSIHZhbHVlCiAgICBmb3IgaSA9IDEsICNvcmRlciBkbwogICAgICAgIGxvY2FsIGRvbWFpbiA9IG9yZGVyW2ldCiAgICAgICAgbG9jYWwgdyA9IHdhbnRbZG9tYWluXQogICAgICAgIGNvdW50cmllc1tkb21haW5dID0gc2Nhbl9jb3VudHJ5X2luZGV4KGRvbWFpbiwgdy5mcm9tLCB3LnRvKQogICAgICAgIHJvbGx1cHNbZG9tYWluXSA9IHJlYWRfcm9sbHVwKGRvbWFpbiwgZGF5KQogICAgZW5kCgogICAgLS0g4pSA4pSAIFNlcnZlIGVhY2ggZG9tYWluIGZyb20gdGhlIGluZGV4IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAogICAgbG9jYWwgb3V0ID0ge30KICAgIGZvciBpID0gMSwgI29yZGVyIGRvCiAgICAgICAgbG9jYWwgZG9tYWluID0gb3JkZXJbaV0KICAgICAgICBsb2NhbCB3ID0gd2FudFtkb21haW5dCiAgICAgICAgbG9jYWwgY2lkeCA9IGNvdW50cmllc1tkb21haW5dIG9yIHt9CgogICAgICAgIGxvY2FsIGJ1Y2tldHMsIGZsdXNoZWQgPSB7fSwgMAogICAgICAgIGZvciBtID0gdy5mcm9tLCB3LnRvIGRvCiAgICAgICAgICAgIGxvY2FsIHAgPSAiczoiIC4uIGRvbWFpbiAuLiAiOiIgLi4gbQogICAgICAgICAgICAtLSBEcmFpbiBGSVJTVCwgdGhlbiBkZWNpZGU6IGBkcmFpbmAgcmV0dXJucyB3aGF0IGl0IHRvb2ssIGFuZCBhIGNvdW50ZXIgbGVmdAogICAgICAgICAgICAtLSBhdCAwIGJ5IGFuIGVhcmxpZXIgZmx1c2ggbXVzdCBub3QgZW1pdCBhIGJ1Y2tldCBvZiB6ZXJvcy4gKFplcm8gaXMgdHJ1dGh5IGluCiAgICAgICAgICAgIC0tIEx1YSwgc28gdGhlIG9sZCBgaWYgciB0aGVuYCB3b3VsZCBoYXZlIHN0YXJ0ZWQgZG9pbmcgZXhhY3RseSB0aGF0IHRoZSBtb21lbnQKICAgICAgICAgICAgLS0ga2V5cyBzdG9wcGVkIGJlaW5nIGRlbGV0ZWQuKQogICAgICAgICAgICBsb2NhbCByID0gZHJhaW4ocCAuLiAiOnIiKQogICAgICAgICAgICBpZiByID4gMCB0aGVuCiAgICAgICAgICAgICAgICBsb2NhbCBydF91cyA9IGRyYWluKHAgLi4gIjp0IikKICAgICAgICAgICAgICAgIGJ1Y2tldHNbI2J1Y2tldHMgKyAxXSA9IHsKICAgICAgICAgICAgICAgICAgICBtaW51dGUgICAgICAgICAgPSBtLAogICAgICAgICAgICAgICAgICAgIHJlcXVlc3RzICAgICAgICA9IHIsCiAgICAgICAgICAgICAgICAgICAgdW5pcXVlX3JlcXVlc3RzID0gZHJhaW4ocCAuLiAiOnUiKSwKICAgICAgICAgICAgICAgICAgICBiYW5kd2lkdGhfaW4gICAgPSBkcmFpbihwIC4uICI6aSIpLAogICAgICAgICAgICAgICAgICAgIGJhbmR3aWR0aF9vdXQgICA9IGRyYWluKHAgLi4gIjpvIiksCiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2VfdGltZSAgID0gcnRfdXMgLyAxMDAwMDAwLAogICAgICAgICAgICAgICAgICAgIGNvdW50cmllcyAgICAgICA9IHJlYWRfbWludXRlX2NvdW50cmllcyhjaWR4W21dLCB0cnVlKSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZsdXNoZWQgPSBmbHVzaGVkICsgMQogICAgICAgICAgICBlbmQKICAgICAgICBlbmQKCiAgICAgICAgLS0gRGFpbHkgcm9sbHVwLCBzYW1lIGtleSBjbGFzc2lmaWNhdGlvbiB0aGUgc2luZ2xlLWRvbWFpbiBlbmRwb2ludCB1c2VzLgogICAgICAgIGxvY2FsIGdlbywgcGF0aHMsIHN0YXR1c2VzLCB2aXNpdG9ycyA9IHt9LCB7fSwge30sIDAKICAgICAgICBmb3Igc3VmZml4LCB2IGluIHBhaXJzKHJvbGx1cHNbZG9tYWluXSBvciB7fSkgZG8KICAgICAgICAgICAgaWYgc3VmZml4ID09ICJ2IiB0aGVuCiAgICAgICAgICAgICAgICB2aXNpdG9ycyA9IHYKICAgICAgICAgICAgZWxzZWlmIHN1ZmZpeDpzdWIoMSwgMikgPT0gInA6IiB0aGVuCiAgICAgICAgICAgICAgICBwYXRoc1tzdWZmaXg6c3ViKDMpXSA9IHYKICAgICAgICAgICAgZWxzZWlmIHN1ZmZpeDpzdWIoMSwgMikgPT0gInM6IiB0aGVuCiAgICAgICAgICAgICAgICBzdGF0dXNlc1tzdWZmaXg6c3ViKDMpXSA9IHYKICAgICAgICAgICAgZWxzZWlmIHN1ZmZpeDptYXRjaCgiXiV1JXUkIikgdGhlbgogICAgICAgICAgICAgICAgZ2VvW3N1ZmZpeF0gPSB2CiAgICAgICAgICAgIGVuZAogICAgICAgICAgICAtLSBBbnl0aGluZyBlbHNlIChgcG5gKSBpcyBib29ra2VlcGluZzogbmV2ZXIgcmVwb3J0ZWQgYXMgYSBjb3VudHJ5LgogICAgICAgIGVuZAoKICAgICAgICBvdXRbZG9tYWluXSA9IHsKICAgICAgICAgICAgYnVja2V0cyA9IGJ1Y2tldHMsCiAgICAgICAgICAgIGZsdXNoZWQgPSBmbHVzaGVkLAogICAgICAgICAgICByb2xsdXAgID0gewogICAgICAgICAgICAgICAgZGF5ID0gZGF5LCBjb3VudHJpZXMgPSBnZW8sIHZpc2l0b3JzID0gdmlzaXRvcnMsCiAgICAgICAgICAgICAgICBwYXRocyA9IHBhdGhzLCBzdGF0dXNlcyA9IHN0YXR1c2VzLAogICAgICAgICAgICB9LAogICAgICAgIH0KICAgIGVuZAoKICAgIHJldHVybiBqc29uKHsgZGF5ID0gZGF5LCBkb21haW5zID0gb3V0IH0pCmVuZAoKLS0g4pSA4pSAIEdFVCAvYW5hbHl0aWNzIC0gbWludXRlLWJ1Y2tldCB0aW1lIHNlcmllcyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKLS0gP2RvbWFpbj1leGFtcGxlLmNvbSZmcm9tPUVQT0NIX01JTiZ0bz1FUE9DSF9NSU4KCmlmIHVyaSA9PSAiL2FuYWx5dGljcyIgdGhlbgogICAgbG9jYWwgZG9tYWluID0gbmd4LnZhci5hcmdfZG9tYWluCiAgICBpZiBub3QgZG9tYWluIG9yIGRvbWFpbiA9PSAiIiB0aGVuIHJldHVybiBiYWQoIm1pc3NpbmcgP2RvbWFpbj0iKSBlbmQKICAgIGRvbWFpbiA9IGRvbWFpbjpsb3dlcigpCgogICAgbG9jYWwgZnJvbV9tID0gdG9udW1iZXIobmd4LnZhci5hcmdfZnJvbSkKICAgIGxvY2FsIHRvX20gICA9IHRvbnVtYmVyKG5neC52YXIuYXJnX3RvKQogICAgaWYgbm90IGZyb21fbSBvciBub3QgdG9fbSB0aGVuCiAgICAgICAgcmV0dXJuIGJhZCgibWlzc2luZyA/ZnJvbT0gYW5kID90bz0gKGVwb2NoIG1pbnV0ZXMpIikKICAgIGVuZAogICAgLS0gQ2FwIGF0IDI0aAogICAgaWYgdG9fbSAtIGZyb21fbSA+IDE0NDAgdGhlbiB0b19tID0gZnJvbV9tICsgMTQ0MCBlbmQKCiAgICAtLSBPTkUgc2NhbiBmb3IgdGhlIHdob2xlIHdpbmRvdyAoc2VlIHNjYW5fY291bnRyeV9pbmRleCkuCiAgICBsb2NhbCBjb3VudHJ5X2luZGV4ID0gc2Nhbl9jb3VudHJ5X2luZGV4KGRvbWFpbiwgZnJvbV9tLCB0b19tKQoKICAgIGxvY2FsIGJ1Y2tldHMgPSB7fQogICAgZm9yIG0gPSBmcm9tX20sIHRvX20gZG8KICAgICAgICBsb2NhbCBwID0gInM6IiAuLiBkb21haW4gLi4gIjoiIC4uIG0KICAgICAgICBsb2NhbCByID0gYW5hbHl0aWNzOmdldChwIC4uICI6ciIpCiAgICAgICAgaWYgciB0aGVuCiAgICAgICAgICAgIC0tIFJlc3BvbnNlIHRpbWUgc3RvcmVkIGFzIG1pY3Jvc2Vjb25kcywgY29udmVydCB0byBzZWNvbmRzIChmbG9hdCkKICAgICAgICAgICAgbG9jYWwgcnRfdXMgPSBhbmFseXRpY3M6Z2V0KHAgLi4gIjp0Iikgb3IgMAogICAgICAgICAgICBidWNrZXRzWyNidWNrZXRzICsgMV0gPSB7CiAgICAgICAgICAgICAgICBtaW51dGUgICAgICAgICAgID0gbSwKICAgICAgICAgICAgICAgIHJlcXVlc3RzICAgICAgICAgPSByLAogICAgICAgICAgICAgICAgdW5pcXVlX3JlcXVlc3RzICA9IGFuYWx5dGljczpnZXQocCAuLiAiOnUiKSBvciAwLAogICAgICAgICAgICAgICAgYmFuZHdpZHRoX2luICAgICA9IGFuYWx5dGljczpnZXQocCAuLiAiOmkiKSBvciAwLAogICAgICAgICAgICAgICAgYmFuZHdpZHRoX291dCAgICA9IGFuYWx5dGljczpnZXQocCAuLiAiOm8iKSBvciAwLAogICAgICAgICAgICAgICAgcmVzcG9uc2VfdGltZSAgICA9IHJ0X3VzIC8gMTAwMDAwMCwKICAgICAgICAgICAgICAgIGNvdW50cmllcyAgICAgICAgPSByZWFkX21pbnV0ZV9jb3VudHJpZXMoY291bnRyeV9pbmRleFttXSwgZmFsc2UpLAogICAgICAgICAgICB9CiAgICAgICAgZW5kCiAgICBlbmQKCiAgICByZXR1cm4ganNvbih7IGRvbWFpbiA9IGRvbWFpbiwgYnVja2V0cyA9IGJ1Y2tldHMgfSkKZW5kCgotLSDilIDilIAgUE9TVCAvYW5hbHl0aWNzL2ZsdXNoIC0gcmVhZCArIGRlbGV0ZSBtaW51dGUgYnVja2V0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKLS0gU2FtZSBhcyBHRVQgL2FuYWx5dGljcyBidXQgZGVsZXRlcyB0aGUgcmV0dXJuZWQgYnVja2V0cyBmcm9tIHNoYXJlZCBtZW1vcnkuCi0tIFVzZWQgYnkgdGhlIHNjcmFwZXIgdG8gYXRvbWljYWxseSBtb3ZlIGRhdGEgZnJvbSBPcGVuUmVzdHkg4oaSIERCLgotLSA/ZG9tYWluPWV4YW1wbGUuY29tJmZyb209RVBPQ0hfTUlOJnRvPUVQT0NIX01JTgoKaWYgdXJpID09ICIvYW5hbHl0aWNzL2ZsdXNoIiBhbmQgbmd4LnJlcS5nZXRfbWV0aG9kKCkgPT0gIlBPU1QiIHRoZW4KICAgIGxvY2FsIGRvbWFpbiA9IG5neC52YXIuYXJnX2RvbWFpbgogICAgaWYgbm90IGRvbWFpbiBvciBkb21haW4gPT0gIiIgdGhlbiByZXR1cm4gYmFkKCJtaXNzaW5nID9kb21haW49IikgZW5kCiAgICBkb21haW4gPSBkb21haW46bG93ZXIoKQoKICAgIGxvY2FsIGZyb21fbSA9IHRvbnVtYmVyKG5neC52YXIuYXJnX2Zyb20pCiAgICBsb2NhbCB0b19tICAgPSB0b251bWJlcihuZ3gudmFyLmFyZ190bykKICAgIGlmIG5vdCBmcm9tX20gb3Igbm90IHRvX20gdGhlbgogICAgICAgIHJldHVybiBiYWQoIm1pc3NpbmcgP2Zyb209IGFuZCA/dG89IChlcG9jaCBtaW51dGVzKSIpCiAgICBlbmQKICAgIGlmIHRvX20gLSBmcm9tX20gPiAxNDQwIHRoZW4gdG9fbSA9IGZyb21fbSArIDE0NDAgZW5kCgogICAgLS0gT05FIHNjYW4gZm9yIHRoZSB3aG9sZSB3aW5kb3cgKHNlZSBzY2FuX2NvdW50cnlfaW5kZXgpLgogICAgbG9jYWwgY291bnRyeV9pbmRleCA9IHNjYW5fY291bnRyeV9pbmRleChkb21haW4sIGZyb21fbSwgdG9fbSkKCiAgICBsb2NhbCBidWNrZXRzID0ge30KICAgIGxvY2FsIGZsdXNoZWQgPSAwCiAgICBmb3IgbSA9IGZyb21fbSwgdG9fbSBkbwogICAgICAgIGxvY2FsIHAgPSAiczoiIC4uIGRvbWFpbiAuLiAiOiIgLi4gbQogICAgICAgIC0tIERyYWluLCBkb24ndCBkZWxldGUg4oCUIHNlZSBgZHJhaW5gLiBBIGNvdW50ZXIgYWxyZWFkeSBhdCAwIGlzIG5vdCBhIGJ1Y2tldC4KICAgICAgICBsb2NhbCByID0gZHJhaW4ocCAuLiAiOnIiKQogICAgICAgIGlmIHIgPiAwIHRoZW4KICAgICAgICAgICAgbG9jYWwgcnRfdXMgPSBkcmFpbihwIC4uICI6dCIpCiAgICAgICAgICAgIGJ1Y2tldHNbI2J1Y2tldHMgKyAxXSA9IHsKICAgICAgICAgICAgICAgIG1pbnV0ZSAgICAgICAgICAgPSBtLAogICAgICAgICAgICAgICAgcmVxdWVzdHMgICAgICAgICA9IHIsCiAgICAgICAgICAgICAgICB1bmlxdWVfcmVxdWVzdHMgID0gZHJhaW4ocCAuLiAiOnUiKSwKICAgICAgICAgICAgICAgIGJhbmR3aWR0aF9pbiAgICAgPSBkcmFpbihwIC4uICI6aSIpLAogICAgICAgICAgICAgICAgYmFuZHdpZHRoX291dCAgICA9IGRyYWluKHAgLi4gIjpvIiksCiAgICAgICAgICAgICAgICByZXNwb25zZV90aW1lICAgID0gcnRfdXMgLyAxMDAwMDAwLAogICAgICAgICAgICAgICAgLS0gRHJhaW5lZCB0b286IHRoaXMgZW5kcG9pbnQgaGFuZHMgdGhlIG1pbnV0ZSB0byB0aGUgREIsIHNvIHRoZSBjb3VudHJ5CiAgICAgICAgICAgICAgICAtLSBrZXlzIG11c3QgZ28gd2l0aCBpdCBvciB0aGV5IHdvdWxkIGJlIGNvdW50ZWQgdHdpY2UuCiAgICAgICAgICAgICAgICBjb3VudHJpZXMgICAgICAgID0gcmVhZF9taW51dGVfY291bnRyaWVzKGNvdW50cnlfaW5kZXhbbV0sIHRydWUpLAogICAgICAgICAgICB9CiAgICAgICAgICAgIGZsdXNoZWQgPSBmbHVzaGVkICsgMQogICAgICAgIGVuZAogICAgZW5kCgogICAgcmV0dXJuIGpzb24oeyBkb21haW4gPSBkb21haW4sIGJ1Y2tldHMgPSBidWNrZXRzLCBmbHVzaGVkID0gZmx1c2hlZCB9KQplbmQKCi0tIOKUgOKUgCBHRVQgL2FuYWx5dGljcy90b3RhbHMgLSBsaWZldGltZSBjb3VudGVycyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKLS0gP2RvbWFpbj1leGFtcGxlLmNvbSAgICAgIOKGkiBzaW5nbGUgZG9tYWluCi0tIChubyBkb21haW4pICAgICAgICAgICAgICDihpIgYWxsIGtub3duIGRvbWFpbnMKCmlmIHVyaSA9PSAiL2FuYWx5dGljcy90b3RhbHMiIHRoZW4KICAgIGxvY2FsIGRvbWFpbiA9IG5neC52YXIuYXJnX2RvbWFpbgoKICAgIGlmIG5vdCBkb21haW4gb3IgZG9tYWluID09ICIiIHRoZW4KICAgICAgICAtLSBUaGUgc2NyYXBlcidzIGRvbWFpbi1kaXNjb3ZlcnkgY2FsbC4gUmVhZCBmcm9tIHRoZSBgZG5gL2BkaTpgIGluZGV4IHRoYXQKICAgICAgICAtLSBzaXRlX2xvZ2dlciBhcHBlbmRzIHRvIHRoZSBmaXJzdCB0aW1lIGl0IGV2ZXIgc2VlcyBhIGhvc3QsIHNvIHRoaXMgbm8gbG9uZ2VyCiAgICAgICAgLS0gd2Fsa3MgdGhlIHpvbmUuIEl0IHdhcyB0aGUgd29yc3QgcGxhY2UgZm9yIGEgc2NhbjogYSBjYXAgaGVyZSBzaWxlbnRseSBkcm9wcGVkCiAgICAgICAgLS0gd2hvbGUgZG9tYWlucyBmcm9tIGV2ZXJ5IHN1YnNlcXVlbnQgZmx1c2guCiAgICAgICAgbG9jYWwgZG9tYWlucyA9IHt9CiAgICAgICAgZm9yIF8sIGQgaW4gaXBhaXJzKHJlYWRfaW5kZXgoImRuIiwgImRpOiIpKSBkbwogICAgICAgICAgICAtLSBBIGhvc3QgY2FuIGJlIGluZGV4ZWQgYnV0IGhhdmUgaGFkIGl0cyBsaWZldGltZSB0b3RhbHMgZXZpY3RlZDsgcmVwb3J0IGl0CiAgICAgICAgICAgIC0tIHdpdGggemVyb3MgcmF0aGVyIHRoYW4gb21pdHRpbmcgaXQsIHNvIHRoZSBzY3JhcGVyIHN0aWxsIGFza3MgZm9yIGl0cyBidWNrZXRzLgogICAgICAgICAgICBkb21haW5zWyNkb21haW5zICsgMV0gPSB7CiAgICAgICAgICAgICAgICBkb21haW4gICAgICAgID0gZCwKICAgICAgICAgICAgICAgIHJlcXVlc3RzICAgICAgPSBhbmFseXRpY3M6Z2V0KCJ0OiIgLi4gZCAuLiAiOnIiKSBvciAwLAogICAgICAgICAgICAgICAgYmFuZHdpZHRoX2luICA9IGFuYWx5dGljczpnZXQoInQ6IiAuLiBkIC4uICI6aSIpIG9yIDAsCiAgICAgICAgICAgICAgICBiYW5kd2lkdGhfb3V0ID0gYW5hbHl0aWNzOmdldCgidDoiIC4uIGQgLi4gIjpvIikgb3IgMCwKICAgICAgICAgICAgfQogICAgICAgIGVuZAogICAgICAgIHJldHVybiBqc29uKHsgZG9tYWlucyA9IGRvbWFpbnMgfSkKICAgIGVuZAoKICAgIGRvbWFpbiA9IGRvbWFpbjpsb3dlcigpCiAgICByZXR1cm4ganNvbih7CiAgICAgICAgZG9tYWluICAgICAgICA9IGRvbWFpbiwKICAgICAgICByZXF1ZXN0cyAgICAgID0gYW5hbHl0aWNzOmdldCgidDoiIC4uIGRvbWFpbiAuLiAiOnIiKSBvciAwLAogICAgICAgIGJhbmR3aWR0aF9pbiAgPSBhbmFseXRpY3M6Z2V0KCJ0OiIgLi4gZG9tYWluIC4uICI6aSIpIG9yIDAsCiAgICAgICAgYmFuZHdpZHRoX291dCA9IGFuYWx5dGljczpnZXQoInQ6IiAuLiBkb21haW4gLi4gIjpvIikgb3IgMCwKICAgIH0pCmVuZAoKLS0g4pSA4pSAIEdFVCAvYW5hbHl0aWNzL2dlbyAtIGRhaWx5IHJvbGx1cCBmb3IgYSBkYXkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tID9kb21haW49ZXhhbXBsZS5jb20mZGF5PVlZWVlNTURECi0tCi0tIE5hbWVkIC9nZW8gZm9yIGNvbXBhdGliaWxpdHk7IGl0IG5vdyByZXR1cm5zIHRoZSB3aG9sZSBkYWlseSByb2xsdXAg4oCUIGNvdW50cmllcywKLS0gZGlzdGluY3QgdmlzaXRvcnMsIHRvcCBwYXRocywgc3RhdHVzLWNvZGUgbWl4LiBPbmUgc2NhbiBzZXJ2ZXMgYWxsIGZvdXI6IHRoZXkKLS0gc2hhcmUgdGhlIGBnOntkb21haW59OntkYXl9OmAgcHJlZml4IHByZWNpc2VseSBzbyBhIHJlYWRlciBuZXZlciBuZWVkcyBhIHNlY29uZAotLSBwYXNzIG92ZXIgdGhlIHpvbmUuCi0tCi0tIEtleSBsYXlvdXQgdW5kZXIgdGhhdCBwcmVmaXggKHdyaXR0ZW4gYnkgc2l0ZV9sb2dnZXIubHVhKToKLS0gICA8Q0M+ICAgICAgICAgICAgRVhBQ1RMWSB0d28gdXBwZXJjYXNlIGxldHRlcnMg4oaSIGNvdW50cnkgaGl0IGNvdW50Ci0tICAgdiAgICAgICAgICAgICAgIGRpc3RpbmN0IHZpc2l0b3JzIHRvZGF5Ci0tICAgcDo8cGF0aD4gICAgICAgIHBhdGggY291bnRlcgotLSAgIHBuICAgICAgICAgICAgICBkaXN0aW5jdC1wYXRoIGNvdW50ZXIgKGNhcmRpbmFsaXR5IGNhcCBib29ra2VlcGluZykKLS0gICBzOjxzdGF0dXM+ICAgICAgc3RhdHVzLWNvZGUgY291bnRlcgotLQotLSBDb3VudHJ5IG1hdGNoaW5nIGlzIHN0cmljdCAoXiV1JXUkKSByYXRoZXIgdGhhbiAid2hhdGV2ZXIncyBsZWZ0IjogYSBib29ra2VlcGluZwotLSBrZXkgbGlrZSBgcG5gIHdvdWxkIG90aGVyd2lzZSBzdXJmYWNlIGFzIGEgY291bnRyeSBuYW1lZCAicG4iIGFuZCBnZXQgcGxvdHRlZC4KCmlmIHVyaSA9PSAiL2FuYWx5dGljcy9nZW8iIHRoZW4KICAgIGxvY2FsIGRvbWFpbiA9IG5neC52YXIuYXJnX2RvbWFpbgogICAgaWYgbm90IGRvbWFpbiBvciBkb21haW4gPT0gIiIgdGhlbiByZXR1cm4gYmFkKCJtaXNzaW5nID9kb21haW49IikgZW5kCiAgICBkb21haW4gPSBkb21haW46bG93ZXIoKQoKICAgIGxvY2FsIGRheSA9IG5neC52YXIuYXJnX2RheQogICAgaWYgbm90IGRheSBvciAjZGF5IH49IDggdGhlbgogICAgICAgIGRheSA9IG9zLmRhdGUoIiElWSVtJWQiKQogICAgZW5kCgogICAgLS0gUmVhZCB0aHJvdWdoIHRoZSB3cml0ZS10aW1lIGluZGV4ZXMg4oCUIHNhbWUgaGVscGVyIC9hbmFseXRpY3MvY29sbGVjdCB1c2VzLCBzbyB0aGUgdHdvCiAgICAtLSBlbmRwb2ludHMgY2Fubm90IGRpc2FncmVlIGFib3V0IHdoYXQgYSBkYXkgY29udGFpbnMuIFJlcGxhY2VzIGEgYGdldF9rZXlzKDApYCB0aGF0CiAgICAtLSB3YWxrZWQgdGhlIHdob2xlIHpvbmUgdG8gZmluZCBrZXlzIHVuZGVyIG9uZSBwcmVmaXguCiAgICBsb2NhbCByb2xsdXAgPSByZWFkX3JvbGx1cChkb21haW4sIGRheSkKICAgIGxvY2FsIGNvdW50cmllcywgcGF0aHMsIHN0YXR1c2VzID0ge30sIHt9LCB7fQogICAgbG9jYWwgdmlzaXRvcnMgPSB0b251bWJlcihyb2xsdXBbInYiXSkgb3IgMAogICAgZm9yIHN1ZmZpeCwgdiBpbiBwYWlycyhyb2xsdXApIGRvCiAgICAgICAgaWYgc3VmZml4ID09ICJ2IiBvciBzdWZmaXggPT0gInBuIiB0aGVuCiAgICAgICAgICAgIC0tIGJvb2trZWVwaW5nLCBub3QgZGF0YQogICAgICAgIGVsc2VpZiBzdWZmaXg6c3ViKDEsIDIpID09ICJwOiIgdGhlbgogICAgICAgICAgICBwYXRoc1tzdWZmaXg6c3ViKDMpXSA9IHYKICAgICAgICBlbHNlaWYgc3VmZml4OnN1YigxLCAyKSA9PSAiczoiIHRoZW4KICAgICAgICAgICAgc3RhdHVzZXNbc3VmZml4OnN1YigzKV0gPSB2CiAgICAgICAgZWxzZWlmIHN1ZmZpeDptYXRjaCgiXiV1JXUkIikgdGhlbgogICAgICAgICAgICAtLSBDb3VudHJ5IGNvZGVzIG9ubHkuIEFueXRoaW5nIGVsc2UgdW5kZXIgdGhpcyBwcmVmaXggaXMgYm9va2tlZXBpbmcsIGFuZAogICAgICAgICAgICAtLSBsZXR0aW5nIG9uZSB0aHJvdWdoIG1hZGUgYHBuYCBwbG90IGFzIGEgY291bnRyeSBhbmQgc2tldyBldmVyeSBwZXJjZW50YWdlLgogICAgICAgICAgICBjb3VudHJpZXNbc3VmZml4XSA9IHYKICAgICAgICBlbmQKICAgIGVuZAogICAgcmV0dXJuIGpzb24oewogICAgICAgIGRvbWFpbiAgICA9IGRvbWFpbiwKICAgICAgICBkYXkgICAgICAgPSBkYXksCiAgICAgICAgY291bnRyaWVzID0gY291bnRyaWVzLAogICAgICAgIHZpc2l0b3JzICA9IHZpc2l0b3JzLAogICAgICAgIHBhdGhzICAgICA9IHBhdGhzLAogICAgICAgIHN0YXR1c2VzICA9IHN0YXR1c2VzLAogICAgfSkKZW5kCgotLSDilIDilIAgR0VUIC9sb2dzL3JlY2VudCAtIHJhdyByZXF1ZXN0IHJpbmcgYnVmZmVyIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAotLSA/ZG9tYWluPWV4YW1wbGUuY29tJmxpbWl0PTUwCgppZiB1cmkgPT0gIi9sb2dzL3JlY2VudCIgdGhlbgogICAgaWYgbm90IHJlcXVlc3RfZGF0YSB0aGVuCiAgICAgICAgcmV0dXJuIGpzb24oeyBlcnJvciA9ICJyZXF1ZXN0X2RhdGEgZGljdCB1bmF2YWlsYWJsZSIgfSwgNTAzKQogICAgZW5kCgogICAgbG9jYWwgZG9tYWluID0gbmd4LnZhci5hcmdfZG9tYWluCiAgICBpZiBub3QgZG9tYWluIG9yIGRvbWFpbiA9PSAiIiB0aGVuIHJldHVybiBiYWQoIm1pc3NpbmcgP2RvbWFpbj0iKSBlbmQKICAgIGRvbWFpbiA9IGRvbWFpbjpsb3dlcigpCgogICAgbG9jYWwgbGltaXQgPSBtYXRoLm1pbih0b251bWJlcihuZ3gudmFyLmFyZ19saW1pdCkgb3IgNTAsIDEwMDApCiAgICBsb2NhbCBzZXEgICA9IHJlcXVlc3RfZGF0YTpnZXQoInJsb2c6IiAuLiBkb21haW4gLi4gIjpzZXEiKSBvciAwCiAgICBsb2NhbCBvdXQgICA9IHt9CgogICAgZm9yIGkgPSAwLCBsaW1pdCAtIDEgZG8KICAgICAgICBsb2NhbCBzbG90ID0gKHNlcSAtIGkpICUgMTAwMAogICAgICAgIGlmIHNsb3QgPCAwIHRoZW4gc2xvdCA9IHNsb3QgKyAxMDAwIGVuZAogICAgICAgIGxvY2FsIHJhdyA9IHJlcXVlc3RfZGF0YTpnZXQoInJsb2c6IiAuLiBkb21haW4gLi4gIjoiIC4uIHNsb3QpCiAgICAgICAgaWYgcmF3IHRoZW4gb3V0WyNvdXQgKyAxXSA9IHJhdyBlbmQKICAgIGVuZAoKICAgIC0tIFJldHVybiBwcmUtZW5jb2RlZCBKU09OIGVudHJpZXMgYXMgYSBKU09OIGFycmF5CiAgICBuZ3guaGVhZGVyWyJDb250ZW50LVR5cGUiXSA9ICJhcHBsaWNhdGlvbi9qc29uIgogICAgbmd4LnByaW50KCJbIikKICAgIGZvciBpZHgsIGVudHJ5IGluIGlwYWlycyhvdXQpIGRvCiAgICAgICAgaWYgaWR4ID4gMSB0aGVuIG5neC5wcmludCgiLCIpIGVuZAogICAgICAgIG5neC5wcmludChlbnRyeSkKICAgIGVuZAogICAgbmd4LnNheSgiXSIpCiAgICByZXR1cm4gbmd4LmV4aXQoMjAwKQplbmQKCi0tIOKUgOKUgCA0MDQg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACnJldHVybiBqc29uKHsgZXJyb3IgPSAibm90IGZvdW5kIiB9LCA0MDQpCg==",
|
|
23
|
+
"pipe_log.lua": "LS0gcGlwZV9sb2cubHVhCi0tIFB1c2ggcmVxdWVzdCBsb2cgaW50byBzaGFyZWQgZGljdCBxdWV1ZSBsb2dfcGlwZTpxOntob3N0fSBmb3IgL3N0cmVhbSBTU0UuCi0tIFBheWxvYWQgc2hhcGUgbWF0Y2hlcyByZXF1ZXN0TG9nZ2VyLmpzIChpZCwgaXAsIGNvdW50cnkgd2hlbiBrbm93biwKLS0gdGltZXN0YW1wLCBkYXRlLCB1cmksIG1ldGhvZCwgc3RhdHVzLCB1c2VyQWdlbnQsIHJlcXVlc3RTaXplLCByZXNwb25zZVNpemUsCi0tIHJlc3BvbnNlVGltZSkuCi0tCi0tIENhbGxlZCB2aWEgbmd4LnRpbWVyLmF0IGZyb20gc2l0ZV9sb2dnZXIgKHByZW1hdHVyZSBpcyBmaXJzdCBhcmcpLgoKbG9jYWwgY2pzb24gPSByZXF1aXJlICJjanNvbi5zYWZlIgoKbG9jYWwgU1VCX1BSRUZJWCAgID0gImxvZ19waXBlOnN1YjoiCmxvY2FsIFFVRVVFX1BSRUZJWCA9ICJsb2dfcGlwZTpxOiIKbG9jYWwgUVVFVUVfTUFYX0xFTiA9IDIwMDAKCi0tIFNBRkUgTE9BRDogR2VvSVAgKHBlci13b3JrZXIsIGNhY2hlZCBieSByZXF1aXJlKQpsb2NhbCBnZW9fb2ssIGdlbyA9IHBjYWxsKHJlcXVpcmUsICJvcGVuc2hpcC5nZW9fY291bnRyeSIpCmlmIG5vdCBnZW9fb2sgdGhlbiBnZW8gPSBuaWwgZW5kCgotLSBSZXVzZWQgcGF5bG9hZCB0YWJsZSBwZXIgd29ya2VyIChjbGVhcmVkIGFmdGVyIGVuY29kZSB0byBhdm9pZCBHQyBwcmVzc3VyZSkKbG9jYWwgcGF5bG9hZCA9IHt9CgotLSBgY2NgIGlzIHRoZSBjb3VudHJ5IHNpdGVfbG9nZ2VyIGFscmVhZHkgcmVzb2x2ZWQgZm9yIHRoaXMgcmVxdWVzdC4gUGFzc2VkIGluIHJhdGhlcgotLSB0aGFuIGxvb2tlZCB1cCBhZ2Fpbjogb25lIG1tZGIgaGl0IHBlciByZXF1ZXN0LCBhbmQgdGhlIGxpdmUgZnJhbWUgY2FuIG5ldmVyIGRpc2FncmVlCi0tIHdpdGggdGhlIHJvbGx1cCBvciB0aGUgcmluZyBidWZmZXIgYWJvdXQgd2hlcmUgYSBoaXQgY2FtZSBmcm9tLgpsb2NhbCBmdW5jdGlvbiBwaXBlX3JlcXVlc3RfbG9nKHByZW1hdHVyZSwgaG9zdCwgaXAsIHRzLCB1YSwgdXJpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcV9sZW4sIGJ5dGVzLCBydCwgbWV0aG9kLCBzdGF0dXMsIGNjKQogICAgaWYgcHJlbWF0dXJlIHRoZW4gcmV0dXJuIGVuZAoKICAgIGxvY2FsIHNoID0gbmd4LnNoYXJlZC5yZXF1ZXN0X2RhdGEKICAgIGlmIG5vdCBzaCB0aGVuIHJldHVybiBlbmQKCiAgICAtLSBEb3VibGUtY2hlY2sgc3Vic2NyaWJlciBpcyBzdGlsbCBhY3RpdmUgKGd1YXJkIGFnYWluc3QgcmFjZSkKICAgIGlmIG5vdCBzaDpnZXQoU1VCX1BSRUZJWCAuLiBob3N0KSB0aGVuIHJldHVybiBlbmQKCiAgICBwY2FsbChmdW5jdGlvbigpCiAgICAgICAgLS0gRmFsbHMgYmFjayB0byBpdHMgb3duIGxvb2t1cCBvbmx5IGlmIHRoZSBjYWxsZXIgcGFzc2VkIG5vdGhpbmcsIHdoaWNoIGhhcHBlbnMKICAgICAgICAtLSB3aGVuIGEgYm94IGlzIG1pZC1kZXBsb3kgYW5kIHN0aWxsIGhhcyB0aGUgcHJldmlvdXMgc2l0ZV9sb2dnZXIuCiAgICAgICAgbG9jYWwgY291bnRyeSA9IGNjCiAgICAgICAgaWYgKG5vdCBjb3VudHJ5IG9yIGNvdW50cnkgPT0gIiIpIGFuZCBnZW8gYW5kIGdlby5nZXRfY291bnRyeV9jb2RlIHRoZW4KICAgICAgICAgICAgbG9jYWwgb2tfY2MsIHJlcyA9IHBjYWxsKGdlby5nZXRfY291bnRyeV9jb2RlLCBpcCkKICAgICAgICAgICAgaWYgb2tfY2MgdGhlbiBjb3VudHJ5ID0gcmVzIGVuZAogICAgICAgIGVuZAoKICAgICAgICBwYXlsb2FkLmlkICAgICAgICAgICA9IHN0cmluZy5mb3JtYXQoIiUuM2YtJWQiLCB0cywgbWF0aC5yYW5kb20oMTAwMDAsIDk5OTk5KSkKICAgICAgICBwYXlsb2FkLmhvc3QgICAgICAgICA9IGhvc3QKICAgICAgICBwYXlsb2FkLmlwICAgICAgICAgICA9IGlwCiAgICAgICAgaWYgY291bnRyeSBhbmQgdHlwZShjb3VudHJ5KSA9PSAic3RyaW5nIiBhbmQgY291bnRyeSB+PSAiIiB0aGVuCiAgICAgICAgICAgIHBheWxvYWQuY291bnRyeSA9IGNvdW50cnkKICAgICAgICBlbmQKICAgICAgICBwYXlsb2FkLnRpbWVzdGFtcCAgICA9IHRzCiAgICAgICAgcGF5bG9hZC5kYXRlICAgICAgICAgPSBvcy5kYXRlKCIhJVktJW0tJWQgJUg6JU06JVMiLCB0cykKICAgICAgICBwYXlsb2FkLnVyaSAgICAgICAgICA9IHVyaQogICAgICAgIHBheWxvYWQubWV0aG9kICAgICAgID0gbWV0aG9kIG9yICJHRVQiCiAgICAgICAgcGF5bG9hZC5zdGF0dXMgICAgICAgPSB0b251bWJlcihzdGF0dXMpIG9yIDAKICAgICAgICBwYXlsb2FkLnVzZXJBZ2VudCAgICA9IHVhIG9yICIiCiAgICAgICAgcGF5bG9hZC5yZXF1ZXN0U2l6ZSAgPSB0b251bWJlcihyZXFfbGVuKSBvciAwCiAgICAgICAgcGF5bG9hZC5yZXNwb25zZVNpemUgPSB0b251bWJlcihieXRlcykgb3IgMAogICAgICAgIHBheWxvYWQucmVzcG9uc2VUaW1lID0gdG9udW1iZXIocnQpIG9yIDAKCiAgICAgICAgbG9jYWwgYm9keSA9IGNqc29uLmVuY29kZShwYXlsb2FkKQoKICAgICAgICAtLSBDbGVhciBwYXlsb2FkIHRhYmxlIGZvciBuZXh0IHJldXNlCiAgICAgICAgZm9yIGsgaW4gcGFpcnMocGF5bG9hZCkgZG8gcGF5bG9hZFtrXSA9IG5pbCBlbmQKCiAgICAgICAgaWYgbm90IGJvZHkgdGhlbiByZXR1cm4gZW5kCgogICAgICAgIGxvY2FsIHFrZXkgPSBRVUVVRV9QUkVGSVggLi4gaG9zdAogICAgICAgIHNoOmxwdXNoKHFrZXksIGJvZHkpCiAgICAgICAgaWYgc2g6bGxlbihxa2V5KSA+IFFVRVVFX01BWF9MRU4gdGhlbgogICAgICAgICAgICBzaDpycG9wKHFrZXkpCiAgICAgICAgZW5kCiAgICBlbmQpCmVuZAoKcmV0dXJuIHsKICAgIHBpcGVfcmVxdWVzdF9sb2cgPSBwaXBlX3JlcXVlc3RfbG9nLAp9Cg==",
|
|
24
|
+
"pipe_stream.lua": "LS0gcGlwZV9zdHJlYW0ubHVhCi0tIGNvbnRlbnRfYnlfbHVhOiBTU0UgZW5kcG9pbnQgZm9yIHJlYWwtdGltZSByZXF1ZXN0IGxvZyBzdHJlYW1pbmcuCi0tIEdFVCAvbG9ncy9zdHJlYW0/ZG9tYWluPWV4YW1wbGUuY29tCi0tIEludGVybmFsIG9ubHkgLSAxMjcuMC4wLjE6OTE0NQoKbG9jYWwgc2ggPSBuZ3guc2hhcmVkLnJlcXVlc3RfZGF0YQppZiBub3Qgc2ggdGhlbgogICAgbmd4LnN0YXR1cyA9IDUwMwogICAgbmd4LnNheSgic2hhcmVkIGRpY3QgdW5hdmFpbGFibGUiKQogICAgcmV0dXJuIG5neC5leGl0KDUwMykKZW5kCgpsb2NhbCBkb21haW4gPSBuZ3gudmFyLmFyZ19kb21haW4KaWYgbm90IGRvbWFpbiBvciBkb21haW4gPT0gIiIgdGhlbgogICAgbmd4LnN0YXR1cyA9IDQwMAogICAgbmd4LnNheSgibWlzc2luZyA/ZG9tYWluPSBwYXJhbWV0ZXIiKQogICAgcmV0dXJuIG5neC5leGl0KDQwMCkKZW5kCgpkb21haW4gPSBkb21haW46bG93ZXIoKQppZiBkb21haW46c3ViKDEsIDQpID09ICJ3d3cuIiB0aGVuIGRvbWFpbiA9IGRvbWFpbjpzdWIoNSkgZW5kCgpsb2NhbCBTVUJfS0VZICAgPSAibG9nX3BpcGU6c3ViOiIgLi4gZG9tYWluCmxvY2FsIFFVRVVFX0tFWSA9ICJsb2dfcGlwZTpxOiIgICAuLiBkb21haW4KCi0tIENsZWFyIHN0YWxlIHF1ZXVlIGVudHJpZXMsIG1hcmsgc3Vic2NyaWJlciBhY3RpdmUKc2g6ZGVsZXRlKFFVRVVFX0tFWSkKc2g6c2V0KFNVQl9LRVksIHRydWUsIDMwKQoKbmd4LmhlYWRlclsiQ29udGVudC1UeXBlIl0gICAgICA9ICJ0ZXh0L2V2ZW50LXN0cmVhbSIKbmd4LmhlYWRlclsiQ2FjaGUtQ29udHJvbCJdICAgICA9ICJuby1jYWNoZSwgbm8tc3RvcmUiCm5neC5oZWFkZXJbIkNvbm5lY3Rpb24iXSAgICAgICAgPSAia2VlcC1hbGl2ZSIKbmd4LmhlYWRlclsiWC1BY2NlbC1CdWZmZXJpbmciXSA9ICJubyIKCi0tIFNlbmQgaW5pdGlhbCBTU0UgY29tbWVudCBzbyB0aGUgZmlyc3QgZmx1c2ggaGFzIGRhdGEuCi0tIFdpdGhvdXQgdGhpcywgbmd4LmZsdXNoIG9uIGFuIGVtcHR5IGJ1ZmZlciBzZW5kcyBjaHVua2VkLUVPRiAoMFxyXG5cclxuKQotLSBhbmQgdGVybWluYXRlcyB0aGUgcmVzcG9uc2UgaW1tZWRpYXRlbHkuCm5neC5wcmludCgiOiBjb25uZWN0ZWRcblxuIikKaWYgbm90IG5neC5mbHVzaCh0cnVlKSB0aGVuCiAgICBzaDpkZWxldGUoU1VCX0tFWSkKICAgIHJldHVybgplbmQKCmxvY2FsIHN0YXJ0ZWQgID0gbmd4Lm5vdygpCmxvY2FsIGxhc3RfaGIgID0gc3RhcnRlZApsb2NhbCBsYXN0X3JlZiA9IHN0YXJ0ZWQKCndoaWxlIHRydWUgZG8KICAgIC0tIE1heCAxIGhvdXIgcGVyIGNvbm5lY3Rpb24KICAgIGlmIG5neC5ub3coKSAtIHN0YXJ0ZWQgPiAzNjAwIHRoZW4KICAgICAgICBzaDpkZWxldGUoU1VCX0tFWSkKICAgICAgICByZXR1cm4KICAgIGVuZAoKICAgIC0tIERyYWluIHVwIHRvIDEwMCBxdWV1ZWQgZW50cmllcyBwZXIgY3ljbGUKICAgIGxvY2FsIHNlbnQgPSAwCiAgICB3aGlsZSBzZW50IDwgMTAwIGRvCiAgICAgICAgbG9jYWwgZW50cnkgPSBzaDpycG9wKFFVRVVFX0tFWSkKICAgICAgICBpZiBub3QgZW50cnkgdGhlbiBicmVhayBlbmQKICAgICAgICBuZ3gucHJpbnQoImV2ZW50OiByZXF1ZXN0XG5kYXRhOiAiLCBlbnRyeSwgIlxuXG4iKQogICAgICAgIHNlbnQgPSBzZW50ICsgMQogICAgZW5kCgogICAgaWYgc2VudCA+IDAgdGhlbgogICAgICAgIGlmIG5vdCBuZ3guZmx1c2godHJ1ZSkgdGhlbgogICAgICAgICAgICBzaDpkZWxldGUoU1VCX0tFWSkKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgZW5kCiAgICBlbmQKCiAgICBsb2NhbCBub3cgPSBuZ3gubm93KCkKCiAgICAtLSBIZWFydGJlYXQgZXZlcnkgMTVzCiAgICBpZiBub3cgLSBsYXN0X2hiID4gMTUgdGhlbgogICAgICAgIG5neC5wcmludCgiOiBwaW5nXG5cbiIpCiAgICAgICAgaWYgbm90IG5neC5mbHVzaCh0cnVlKSB0aGVuCiAgICAgICAgICAgIHNoOmRlbGV0ZShTVUJfS0VZKQogICAgICAgICAgICByZXR1cm4KICAgICAgICBlbmQKICAgICAgICBsYXN0X2hiID0gbm93CiAgICBlbmQKCiAgICAtLSBSZWZyZXNoIHN1YnNjcmliZXIgVFRMIGV2ZXJ5IDEwcwogICAgaWYgbm93IC0gbGFzdF9yZWYgPiAxMCB0aGVuCiAgICAgICAgc2g6c2V0KFNVQl9LRVksIHRydWUsIDMwKQogICAgICAgIGxhc3RfcmVmID0gbm93CiAgICBlbmQKCiAgICBuZ3guc2xlZXAoMC4wNSkKZW5kCg==",
|
|
25
|
+
"rules_guard.lua": "LS0gcnVsZXNfZ3VhcmQubHVhCi0tIGFjY2Vzc19ieV9sdWEgZHJpdmVyOiBlbmZvcmNlIHBlci1yb3V0ZSBydWxlcyAobWV0aG9kIMK3IElQL0NJRFIgYWxsb3ctZGVueSDCtwotLSBjb3VudHJ5IGFsbG93L2JhbiDCtyBiYWQgdXNlci1hZ2VudCDCtyBob3RsaW5rIMK3IHJhdGUtbGltaXQpIGZvciB0aGUgcmVxdWVzdCdzCi0tIGhvc3QuIFJ1bGVzIGFyZSBwdXNoZWQgcmVsb2FkLWZyZWUgYnkgbWdtdF9hcGkgYFBPU1QgL3J1bGVzYDsgdGhlIERCCi0tIGByb3V0ZV9ydWxlYCB0YWJsZSBpcyB0aGUgc291cmNlIG9mIHRydXRoLiBBbGwgcGFyc2luZy9jb21waWxpbmcvbWF0Y2hpbmcKLS0gbGl2ZXMgaW4gb3BlbnNoaXAucnVsZXNfbGliIChsb2FkZWQgT05DRSBwZXIgd29ya2VyKSDigJQgdGhpcyBmaWxlIGlzIHJlLXJ1bgotLSBldmVyeSByZXF1ZXN0IHNvIGl0IHN0YXlzIG1pbmltYWwuIFNlZSBydWxlc19saWIubHVhIGZvciB0aGUgY29tcGlsZWQgc2hhcGUuCi0tCi0tIEVuZm9yY2VtZW50IHVzZXMgdGhlIGNvbm5lY3RpbmcgcGVlciAobmd4LnZhci5yZW1vdGVfYWRkcik7IGZyb250IGEgcmVhbF9pcAotLSBjb25maWcgaWYgYmVoaW5kIGEgdHJ1c3RlZCBwcm94eS4gTm8gdXNlci1zdXBwbGllZCB2YWx1ZSBpcyBldmVyIHVzZWQgYXMgYQotLSBMdWEgcGF0dGVybiBvciB3cml0dGVuIGludG8gYSByZXNwb25zZSBoZWFkZXIuCgpsb2NhbCBydWxlcyA9IG5neC5zaGFyZWQucnVsZXMKaWYgbm90IHJ1bGVzIHRoZW4gcmV0dXJuIGVuZAoKLS0gUmF0ZS1saW1pdCBjb3VudGVycyBsaXZlIGluIHRoZWlyIE9XTiBkaWN0IHNvIGEgaGlnaC1jYXJkaW5hbGl0eSBmbG9vZCAoYSBuZXcKLS0gcmw6IGtleSBwZXIgc291cmNlIElQIHBlciBzZWNvbmQpIGNhbid0IExSVS1ldmljdCB0aGUgcnVsZXNldHMgYW5kIHNpbGVudGx5Ci0tIGRpc2FibGUgZW5mb3JjZW1lbnQuIEZhbGwgYmFjayB0byBgcnVsZXNgIG9uIGEgYm94IHdob3NlIGNvbmZpZyBwcmVkYXRlcyB0aGUKLS0gc2VwYXJhdGUgZGljdCAoc3RpbGwgd29ya3MsIGp1c3Qgc2hhcmVzIHRoZSB6b25lIHVudGlsIHRoZSBuZXh0IHJlbG9hZCkuCmxvY2FsIGNvdW50ZXJzID0gbmd4LnNoYXJlZC5ybF9jb3VudGVycyBvciBydWxlcwoKbG9jYWwgaG9zdCA9IG5neC52YXIuaG9zdAppZiBub3QgaG9zdCB0aGVuIHJldHVybiBlbmQKCmxvY2FsIHJhdyA9IHJ1bGVzOmdldChob3N0KQppZiBub3QgcmF3IHRoZW4gcmV0dXJuIGVuZCAgICAgICAgICAtLSBmYXN0IHBhdGg6IG5vdGhpbmcgY29uZmlndXJlZCBmb3IgdGhpcyBob3N0Cgpsb2NhbCBsaWIgPSByZXF1aXJlICJvcGVuc2hpcC5ydWxlc19saWIiCmxvY2FsIGVudHJpZXMgPSBsaWIuZ2V0KGhvc3QsIHJhdykKbG9jYWwgbiA9ICNlbnRyaWVzCmlmIG4gPT0gMCB0aGVuIHJldHVybiBlbmQKCi0tIOKUgOKUgCBMb25nZXN0IG1hdGNoaW5nIHBhdGhQcmVmaXggd2lucyDilIDilIAKbG9jYWwgdXJpID0gbmd4LnZhci51cmkgb3IgIi8iCmxvY2FsIGNob3NlbiwgY2hvc2VuX2xlbiA9IG5pbCwgLTEKZm9yIGkgPSAxLCBuIGRvCiAgICBsb2NhbCBlID0gZW50cmllc1tpXQogICAgbG9jYWwgcCA9IGUucGF0aFByZWZpeAogICAgaWYgcCA9PSBuaWwgb3IgcCA9PSAiIiBvciBwID09ICIvIiB0aGVuCiAgICAgICAgaWYgY2hvc2VuX2xlbiA8IDAgdGhlbiBjaG9zZW4sIGNob3Nlbl9sZW4gPSBlLCAwIGVuZAogICAgZWxzZWlmIHVyaSA9PSBwIG9yIHN0cmluZy5zdWIodXJpLCAxLCAjcCkgPT0gcCB0aGVuCiAgICAgICAgaWYgI3AgPiBjaG9zZW5fbGVuIHRoZW4gY2hvc2VuLCBjaG9zZW5fbGVuID0gZSwgI3AgZW5kCiAgICBlbmQKZW5kCmlmIG5vdCBjaG9zZW4gdGhlbiByZXR1cm4gZW5kCgpsb2NhbCBzcGVjID0gY2hvc2VuLnNwZWMKbG9jYWwgZGVueV9zdGF0dXMgPSBzcGVjLmJsb2NrU3RhdHVzIG9yIDQwMwoKbG9jYWwgaXBzID0gbmd4LnZhci5yZW1vdGVfYWRkciBvciAiMC4wLjAuMCIKbG9jYWwgaXBpID0gbGliLmlwdjRfdG9faW50KGlwcykKCi0tIENvdW50cnkgcmVzb2x2ZWQgYXQgbW9zdCBvbmNlIHBlciByZXF1ZXN0IChvbmx5IHdoZW4gYSBjb3VudHJ5IHJ1bGUgZXhpc3RzKS4KbG9jYWwgY291bnRyeV9jYWNoZQpsb2NhbCBmdW5jdGlvbiBjb3VudHJ5X29mKCkKICAgIGlmIGNvdW50cnlfY2FjaGUgPT0gbmlsIHRoZW4KICAgICAgICBsb2NhbCBvaywgZ2VvID0gcGNhbGwocmVxdWlyZSwgIm9wZW5zaGlwLmdlb19jb3VudHJ5IikKICAgICAgICBjb3VudHJ5X2NhY2hlID0gKG9rIGFuZCBnZW8gYW5kIGdlby5nZXRfY291bnRyeV9jb2RlKGlwcykpIG9yIGZhbHNlCiAgICBlbmQKICAgIHJldHVybiBjb3VudHJ5X2NhY2hlIG9yIG5pbAplbmQKCi0tIOKUgOKUgCAxLiBBY2Nlc3M6IG1ldGhvZCBhbGxvdy1saXN0LCBJUCBhbGxvdy9kZW55LCBjb3VudHJ5IGFsbG93LWxpc3Qg4pSA4pSACmxvY2FsIGFjY2VzcyA9IHNwZWMuYWNjZXNzCmlmIGFjY2VzcyB0aGVuCiAgICBpZiBhY2Nlc3MubWV0aG9kcyBhbmQgbm90IGFjY2Vzcy5tZXRob2RzW25neC5yZXEuZ2V0X21ldGhvZCgpXSB0aGVuCiAgICAgICAgcmV0dXJuIG5neC5leGl0KGRlbnlfc3RhdHVzKQogICAgZW5kCiAgICBpZiBsaWIubWF0Y2hfY29tcGlsZWQoYWNjZXNzLmRlbnksIGlwaSwgaXBzKSB0aGVuIHJldHVybiBuZ3guZXhpdChkZW55X3N0YXR1cykgZW5kCiAgICBpZiBhY2Nlc3MuYWxsb3cgYW5kIG5vdCBsaWIubWF0Y2hfY29tcGlsZWQoYWNjZXNzLmFsbG93LCBpcGksIGlwcykgdGhlbgogICAgICAgIHJldHVybiBuZ3guZXhpdChkZW55X3N0YXR1cykKICAgIGVuZAogICAgLS0gQWxsb3ctbGlzdDogYW4gdW5yZXNvbHZlZCBjb3VudHJ5IGlzIG5vdCBvbiB0aGUgbGlzdCDihpIgYmxvY2tlZCAoZGVmYXVsdC1kZW55KS4KICAgIGlmIGFjY2Vzcy5hbGxvd0NvdW50cmllcyBhbmQgbm90IGFjY2Vzcy5hbGxvd0NvdW50cmllc1tjb3VudHJ5X29mKCkgb3IgIiJdIHRoZW4KICAgICAgICByZXR1cm4gbmd4LmV4aXQoZGVueV9zdGF0dXMpCiAgICBlbmQKZW5kCgotLSDilIDilIAgMi4gQmFuOiBJUC9DSURSLCBjb3VudHJ5LCB1c2VyLWFnZW50IOKUgOKUgApsb2NhbCBiYW4gPSBzcGVjLmJhbgppZiBiYW4gdGhlbgogICAgaWYgbGliLm1hdGNoX2NvbXBpbGVkKGJhbi5pcHMsIGlwaSwgaXBzKSBvciBsaWIubWF0Y2hfY29tcGlsZWQoYmFuLmNpZHJzLCBpcGksIGlwcykgdGhlbgogICAgICAgIHJldHVybiBuZ3guZXhpdChkZW55X3N0YXR1cykKICAgIGVuZAogICAgaWYgYmFuLmNvdW50cmllcyB0aGVuCiAgICAgICAgbG9jYWwgY2MgPSBjb3VudHJ5X29mKCkKICAgICAgICAtLSBGYWlsIENMT1NFRCAobWF0Y2hlcyB0aGUgYWxsb3ctbGlzdCBhYm92ZSk6IGlmIGdlbyBpcyB1bmF2YWlsYWJsZSB3ZQogICAgICAgIC0tIGNhbm5vdCBwcm92ZSB0aGUgY2xpZW50IGlzIE5PVCBmcm9tIGEgYmFubmVkIGNvdW50cnksIHNvIGJsb2NrIHJhdGhlcgogICAgICAgIC0tIHRoYW4gc2lsZW50bHkgbGV0dGluZyBiYW5uZWQgdHJhZmZpYyB0aHJvdWdoLiBBIGJsb2NrZWQgaG9zdCBpcyBhIGxvdWQKICAgICAgICAtLSBzaWduYWwgdG8gZml4IGdlbzsgZmFpbC1vcGVuIHdvdWxkIGJlIGEgc2lsZW50IHNlY3VyaXR5IGhvbGUuCiAgICAgICAgaWYgbm90IGNjIHRoZW4KICAgICAgICAgICAgbmd4LmxvZyhuZ3guV0FSTiwgInJ1bGVzX2d1YXJkOiBjb3VudHJ5IGJhbiBhY3RpdmUgYnV0IGdlbyB1bmF2YWlsYWJsZSDigJQgYmxvY2tpbmcgKGZhaWwtY2xvc2VkKSIpCiAgICAgICAgICAgIHJldHVybiBuZ3guZXhpdChkZW55X3N0YXR1cykKICAgICAgICBlbmQKICAgICAgICBpZiBiYW4uY291bnRyaWVzW2NjXSB0aGVuIHJldHVybiBuZ3guZXhpdChkZW55X3N0YXR1cykgZW5kCiAgICBlbmQKICAgIGlmIGJhbi5lbXB0eVVBIG9yIGJhbi51YXMgdGhlbgogICAgICAgIGxvY2FsIHVhID0gbmd4LnZhci5odHRwX3VzZXJfYWdlbnQKICAgICAgICBpZiBiYW4uZW1wdHlVQSBhbmQgKHVhID09IG5pbCBvciB1YSA9PSAiIikgdGhlbiByZXR1cm4gbmd4LmV4aXQoZGVueV9zdGF0dXMpIGVuZAogICAgICAgIGlmIGJhbi51YXMgYW5kIHVhIGFuZCB1YSB+PSAiIiB0aGVuCiAgICAgICAgICAgIGxvY2FsIHVhbCA9IHN0cmluZy5sb3dlcih1YSkKICAgICAgICAgICAgZm9yIGkgPSAxLCAjYmFuLnVhcyBkbwogICAgICAgICAgICAgICAgaWYgc3RyaW5nLmZpbmQodWFsLCBiYW4udWFzW2ldLCAxLCB0cnVlKSB0aGVuIHJldHVybiBuZ3guZXhpdChkZW55X3N0YXR1cykgZW5kCiAgICAgICAgICAgIGVuZAogICAgICAgIGVuZAogICAgZW5kCmVuZAoKLS0g4pSA4pSAIDMuIEhvdGxpbms6IG9ubHkgbGlzdGVkIHJlZmVyZXIgaG9zdHMgKGVtcHR5IHJlZmVyZXIgcGVyIGFsbG93RW1wdHkpIOKUgOKUgApsb2NhbCBob3QgPSBzcGVjLmhvdGxpbmsKaWYgaG90IHRoZW4KICAgIGxvY2FsIHJlZiA9IG5neC52YXIuaHR0cF9yZWZlcmVyCiAgICBpZiByZWYgPT0gbmlsIG9yIHJlZiA9PSAiIiB0aGVuCiAgICAgICAgaWYgbm90IGhvdC5hbGxvd0VtcHR5IHRoZW4gcmV0dXJuIG5neC5leGl0KGRlbnlfc3RhdHVzKSBlbmQKICAgIGVsc2UKICAgICAgICBsb2NhbCByaG9zdCA9IHN0cmluZy5tYXRjaChyZWYsICJeJXcrOi8vKFteL10rKSIpICAgICAgICAgIC0tIGF1dGhvcml0eQogICAgICAgIGlmIHJob3N0IHRoZW4gcmhvc3QgPSBzdHJpbmcubG93ZXIoc3RyaW5nLm1hdGNoKHJob3N0LCAiXihbXjpdKykiKSBvciByaG9zdCkgZW5kIC0tIHN0cmlwIDpwb3J0CiAgICAgICAgaWYgbm90IChyaG9zdCBhbmQgaG90LnJlZmVyZXJzW3Job3N0XSkgdGhlbiByZXR1cm4gbmd4LmV4aXQoZGVueV9zdGF0dXMpIGVuZAogICAgZW5kCmVuZAoKLS0g4pSA4pSAIDQuIFJhdGUgbGltaXQg4oCUIGZpeGVkIDFzIHdpbmRvdyBwZXIgKGhvc3QsIHBhdGgsIGlwKSDilIDilIAKbG9jYWwgcmwgPSBzcGVjLnJsCmlmIHJsIHRoZW4KICAgIGxvY2FsIGtleSA9ICJybDoiIC4uIGhvc3QgLi4gIjoiIC4uIChjaG9zZW4ucGF0aFByZWZpeCBvciAiLyIpIC4uICI6IiAuLiBpcHMKICAgICAgICAuLiAiOiIgLi4gbWF0aC5mbG9vcihuZ3gubm93KCkpCiAgICBsb2NhbCBjID0gY291bnRlcnM6aW5jcihrZXksIDEsIDAsIDIpICAtLSBpbml0IDAsIDJzIFRUTCDihpIgc2VsZi1leHBpcmluZyBidWNrZXRzCiAgICBpZiBjIGFuZCBjID4gcmwubGltaXQgdGhlbgogICAgICAgIG5neC5oZWFkZXJbIlJldHJ5LUFmdGVyIl0gPSAiMSIKICAgICAgICByZXR1cm4gbmd4LmV4aXQocmwuc3RhdHVzKQogICAgZW5kCmVuZAo=",
|
|
26
|
+
"rules_lib.lua": "LS0gcnVsZXNfbGliLmx1YQotLSBQZXItd29ya2VyIGhlbHBlcnMgKyBwYXJzZWQtcnVsZSBjYWNoZSBmb3IgcnVsZXNfZ3VhcmQubHVhIChhY2Nlc3MgcGhhc2UpLgotLSBMb2FkZWQgT05DRSBwZXIgd29ya2VyIHZpYSByZXF1aXJlKCJvcGVuc2hpcC5ydWxlc19saWIiKS4gVGhlIGFjY2VzcyBmaWxlIGlzCi0tIHJlLWV4ZWN1dGVkIG9uIGV2ZXJ5IHJlcXVlc3QsIHNvIGFsbCBwYXJzaW5nL2NvbXBpbGluZy9tYXRjaGluZyBsaXZlcyBoZXJlIHRvCi0tIGF2b2lkIHJlLWNyZWF0aW5nIGNsb3N1cmVzIGFuZCByZS1kZWNvZGluZyBKU09OIG9uIHRoZSBob3QgcGF0aC4KLS0KLS0gU2hhcmVkLWRpY3QgdmFsdWUgYHJ1bGVzW2hvc3RdYCA9IEpTT04gYXJyYXkgb2YgeyBwYXRoUHJlZml4LCBzcGVjIH0gd2hlcmUKLS0gc3BlYyBtYXRjaGVzIEByZXBvL2NvcmUgUm91dGVSdWxlU3BlYy4gcGFyc2UoKSBkZWNvZGVzICsgcHJlY29tcGlsZXMgQ0lEUnMgdG8KLS0gaW50ZWdlcnMsIGxvd2VyY2FzZXMgVUEvcmVmZXJlciBuZWVkbGVzLCBhbmQgYnVpbGRzIE8oMSkgc2V0cyBmb3IKLS0gY291bnRyaWVzL21ldGhvZHMgT05DRTsgdGhlIGNvbXBpbGVkIHJlc3VsdCBpcyBMUlUtY2FjaGVkIHBlciBob3N0IGFuZCByZXVzZWQKLS0gdW50aWwgdGhlIHJhdyBzdHJpbmcgY2hhbmdlcyAocnVsZSBlZGl0cyBhcmUgcmFyZSwgcmVxdWVzdHMgYXJlIGhvdCkuCi0tCi0tIFNFQ1VSSVRZOiBub3RoaW5nIGhlcmUgdHVybnMgYSBydWxlIHZhbHVlIGludG8gTHVhIGNvZGUgb3IgYSBMdWEgcGF0dGVybi4KLS0gU3RyaW5ncyBhcmUgY29tcGFyZWQgd2l0aCBgPT1gL3NldC1sb29rdXBzOyB1c2VyLWFnZW50IG1hdGNoaW5nIGlzCi0tIHN0cmluZy5maW5kKGhheSwgbmVlZGxlLCAxLCB0cnVlKSDigJQgUExBSU4sIG5ldmVyIGEgcmVnZXguCgpsb2NhbCBjanNvbiA9IHJlcXVpcmUgImNqc29uLnNhZmUiCmxvY2FsIGxydWNhY2hlID0gcmVxdWlyZSAicmVzdHkubHJ1Y2FjaGUiCgpsb2NhbCBNID0ge30KCmxvY2FsIGNhY2hlID0gbHJ1Y2FjaGUubmV3KDEwMjQpIC0tIGNvbXBpbGVkIHJ1bGVzLCBwZXIgd29ya2VyLCB+MTAyNCBob3N0cwoKLS0g4pSA4pSAIElQdjQgaGVscGVycyDilIDilIAKbG9jYWwgZnVuY3Rpb24gaXB2NF90b19pbnQocykKICAgIGxvY2FsIGEsIGIsIGMsIGQgPSBzdHJpbmcubWF0Y2gocywgIl4oJWQrKSUuKCVkKyklLiglZCspJS4oJWQrKSQiKQogICAgaWYgbm90IGEgdGhlbiByZXR1cm4gbmlsIGVuZAogICAgYSwgYiwgYywgZCA9IHRvbnVtYmVyKGEpLCB0b251bWJlcihiKSwgdG9udW1iZXIoYyksIHRvbnVtYmVyKGQpCiAgICBpZiBhID4gMjU1IG9yIGIgPiAyNTUgb3IgYyA+IDI1NSBvciBkID4gMjU1IHRoZW4gcmV0dXJuIG5pbCBlbmQKICAgIHJldHVybiBhICogMTY3NzcyMTYgKyBiICogNjU1MzYgKyBjICogMjU2ICsgZAplbmQKTS5pcHY0X3RvX2ludCA9IGlwdjRfdG9faW50CgotLSBQcmVjb21waWxlIGEgQ0lEUiAvIGJhcmUtSVAgc3RyaW5nIGludG8gYSBjaGVhcCBtYXRjaCBkZXNjcmlwdG9yLgpsb2NhbCBmdW5jdGlvbiBjb21waWxlX2NpZHIocykKICAgIGxvY2FsIGJhc2UsIGJpdHMgPSBzdHJpbmcubWF0Y2gocywgIl4oW14vXSspLyglZCspJCIpCiAgICBpZiBiYXNlIHRoZW4KICAgICAgICBiaXRzID0gdG9udW1iZXIoYml0cykKICAgICAgICBsb2NhbCBiYXNlaSA9IGlwdjRfdG9faW50KGJhc2UpCiAgICAgICAgaWYgbm90IGJhc2VpIG9yIGJpdHMgPCAwIG9yIGJpdHMgPiAzMiB0aGVuIHJldHVybiB7IGV4YWN0ID0gcyB9IGVuZAogICAgICAgIGlmIGJpdHMgPT0gMCB0aGVuIHJldHVybiB7IGFsbCA9IHRydWUgfSBlbmQKICAgICAgICBsb2NhbCBkaXYgPSAyIF4gKDMyIC0gYml0cykgLS0gY29tcGFyZSB0aGUgdG9wIGBiaXRzYCBiaXRzCiAgICAgICAgcmV0dXJuIHsgbmV0ID0gbWF0aC5mbG9vcihiYXNlaSAvIGRpdiksIGRpdiA9IGRpdiB9CiAgICBlbmQKICAgIGxvY2FsIGkgPSBpcHY0X3RvX2ludChzKQogICAgaWYgaSB0aGVuIHJldHVybiB7IGlwID0gaSB9IGVuZAogICAgcmV0dXJuIHsgZXhhY3QgPSBzIH0gLS0gSVB2NiAvIHVucGFyc2VhYmxlIOKGkiBsaXRlcmFsIHN0cmluZyBjb21wYXJlCmVuZAoKbG9jYWwgZnVuY3Rpb24gY29tcGlsZV9saXN0KGxpc3QpCiAgICBpZiB0eXBlKGxpc3QpIH49ICJ0YWJsZSIgdGhlbiByZXR1cm4gbmlsIGVuZAogICAgbG9jYWwgb3V0LCBuID0ge30sIDAKICAgIGZvciBfLCBzIGluIGlwYWlycyhsaXN0KSBkbwogICAgICAgIGlmIHR5cGUocykgPT0gInN0cmluZyIgYW5kIHMgfj0gIiIgdGhlbgogICAgICAgICAgICBuID0gbiArIDEKICAgICAgICAgICAgb3V0W25dID0gY29tcGlsZV9jaWRyKHMpCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJldHVybiBuID4gMCBhbmQgb3V0IG9yIG5pbAplbmQKCi0tIE1hdGNoIGEgY2xpZW50IChpbnQgZm9ybSBgaXBpYCwgbWF5IGJlIG5pbCBmb3Igbm9uLUlQdjQ7IHJhdyBgaXBzYCkgYWdhaW5zdCBhCi0tIGNvbXBpbGVkIENJRFIvSVAgbGlzdC4KbG9jYWwgZnVuY3Rpb24gbWF0Y2hfY29tcGlsZWQoY29tcGlsZWQsIGlwaSwgaXBzKQogICAgaWYgbm90IGNvbXBpbGVkIHRoZW4gcmV0dXJuIGZhbHNlIGVuZAogICAgZm9yIGkgPSAxLCAjY29tcGlsZWQgZG8KICAgICAgICBsb2NhbCBjID0gY29tcGlsZWRbaV0KICAgICAgICBpZiBjLmFsbCB0aGVuCiAgICAgICAgICAgIHJldHVybiB0cnVlCiAgICAgICAgZWxzZWlmIGMuaXAgdGhlbgogICAgICAgICAgICBpZiBpcGkgYW5kIGlwaSA9PSBjLmlwIHRoZW4gcmV0dXJuIHRydWUgZW5kCiAgICAgICAgZWxzZWlmIGMubmV0IHRoZW4KICAgICAgICAgICAgaWYgaXBpIGFuZCBtYXRoLmZsb29yKGlwaSAvIGMuZGl2KSA9PSBjLm5ldCB0aGVuIHJldHVybiB0cnVlIGVuZAogICAgICAgIGVsc2VpZiBjLmV4YWN0ID09IGlwcyB0aGVuCiAgICAgICAgICAgIHJldHVybiB0cnVlCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJldHVybiBmYWxzZQplbmQKTS5tYXRjaF9jb21waWxlZCA9IG1hdGNoX2NvbXBpbGVkCgpsb2NhbCBmdW5jdGlvbiBsb3dlcl9saXN0KGxpc3QpCiAgICBpZiB0eXBlKGxpc3QpIH49ICJ0YWJsZSIgdGhlbiByZXR1cm4gbmlsIGVuZAogICAgbG9jYWwgb3V0LCBuID0ge30sIDAKICAgIGZvciBfLCBzIGluIGlwYWlycyhsaXN0KSBkbwogICAgICAgIGlmIHR5cGUocykgPT0gInN0cmluZyIgYW5kIHMgfj0gIiIgdGhlbgogICAgICAgICAgICBuID0gbiArIDEKICAgICAgICAgICAgb3V0W25dID0gc3RyaW5nLmxvd2VyKHMpCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJldHVybiBuID4gMCBhbmQgb3V0IG9yIG5pbAplbmQKCi0tIEJ1aWxkIGFuIE8oMSkgbG9va3VwIHNldCBmcm9tIGEgc3RyaW5nIGxpc3QgKG9wdGlvbmFsbHkgbG93ZXJjYXNlZCkuCmxvY2FsIGZ1bmN0aW9uIHRvX3NldChsaXN0LCBsb3dlcikKICAgIGlmIHR5cGUobGlzdCkgfj0gInRhYmxlIiB0aGVuIHJldHVybiBuaWwgZW5kCiAgICBsb2NhbCBzZXQsIGFueSA9IHt9LCBmYWxzZQogICAgZm9yIF8sIHMgaW4gaXBhaXJzKGxpc3QpIGRvCiAgICAgICAgaWYgdHlwZShzKSA9PSAic3RyaW5nIiBhbmQgcyB+PSAiIiB0aGVuCiAgICAgICAgICAgIHNldFtsb3dlciBhbmQgc3RyaW5nLmxvd2VyKHMpIG9yIHNdID0gdHJ1ZQogICAgICAgICAgICBhbnkgPSB0cnVlCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJldHVybiBhbnkgYW5kIHNldCBvciBuaWwKZW5kCgotLSBDb21waWxlIG9uZSBSb3V0ZVJ1bGVTcGVjIGludG8gYSBmYXN0LW1hdGNoIHNoYXBlLgpsb2NhbCBmdW5jdGlvbiBjb21waWxlX3NwZWMoc3BlYykKICAgIGlmIHR5cGUoc3BlYykgfj0gInRhYmxlIiB0aGVuIHJldHVybiB7IGJsb2NrU3RhdHVzID0gNDAzIH0gZW5kCiAgICBsb2NhbCBvdXQgPSB7fQoKICAgIGxvY2FsIHJsID0gc3BlYy5yYXRlTGltaXQKICAgIGxvY2FsIHJwcyA9IHJsIGFuZCB0b251bWJlcihybC5ycHMpCiAgICBpZiBycHMgYW5kIHJwcyA+IDAgdGhlbgogICAgICAgIG91dC5ybCA9IHsKICAgICAgICAgICAgbGltaXQgPSBtYXRoLmZsb29yKHJwcykgKyBtYXRoLmZsb29yKHRvbnVtYmVyKHJsLmJ1cnN0KSBvciAwKSwKICAgICAgICAgICAgc3RhdHVzID0gdG9udW1iZXIocmwuc3RhdHVzKSBvciA0MjksCiAgICAgICAgfQogICAgZW5kCgogICAgbG9jYWwgYmFuID0gc3BlYy5iYW4KICAgIGlmIHR5cGUoYmFuKSA9PSAidGFibGUiIHRoZW4KICAgICAgICBvdXQuYmFuID0gewogICAgICAgICAgICBpcHMgPSBjb21waWxlX2xpc3QoYmFuLmlwcyksCiAgICAgICAgICAgIGNpZHJzID0gY29tcGlsZV9saXN0KGJhbi5jaWRycyksCiAgICAgICAgICAgIGNvdW50cmllcyA9IHRvX3NldChiYW4uY291bnRyaWVzKSwKICAgICAgICAgICAgdWFzID0gbG93ZXJfbGlzdChiYW4udXNlckFnZW50cyksCiAgICAgICAgICAgIGVtcHR5VUEgPSBiYW4uZW1wdHlVc2VyQWdlbnQgPT0gdHJ1ZSwKICAgICAgICB9CiAgICBlbmQKCiAgICBsb2NhbCBhY2MgPSBzcGVjLmFjY2VzcwogICAgaWYgdHlwZShhY2MpID09ICJ0YWJsZSIgdGhlbgogICAgICAgIG91dC5hY2Nlc3MgPSB7CiAgICAgICAgICAgIGFsbG93ID0gY29tcGlsZV9saXN0KGFjYy5hbGxvd0NpZHJzKSwKICAgICAgICAgICAgZGVueSA9IGNvbXBpbGVfbGlzdChhY2MuZGVueUNpZHJzKSwKICAgICAgICAgICAgYWxsb3dDb3VudHJpZXMgPSB0b19zZXQoYWNjLmFsbG93Q291bnRyaWVzKSwKICAgICAgICAgICAgbWV0aG9kcyA9IHRvX3NldChhY2MubWV0aG9kcyksCiAgICAgICAgfQogICAgZW5kCgogICAgbG9jYWwgaG90ID0gc3BlYy5ob3RsaW5rCiAgICBpZiB0eXBlKGhvdCkgPT0gInRhYmxlIiB0aGVuCiAgICAgICAgbG9jYWwgcmVmcyA9IHRvX3NldChob3QuYWxsb3dSZWZlcmVycywgdHJ1ZSkKICAgICAgICBpZiByZWZzIHRoZW4KICAgICAgICAgICAgb3V0LmhvdGxpbmsgPSB7IHJlZmVyZXJzID0gcmVmcywgYWxsb3dFbXB0eSA9IGhvdC5hbGxvd0VtcHR5IH49IGZhbHNlIH0KICAgICAgICBlbmQKICAgIGVuZAoKICAgIG91dC5ibG9ja1N0YXR1cyA9ICh0eXBlKHNwZWMuYmxvY2spID09ICJ0YWJsZSIgYW5kIHRvbnVtYmVyKHNwZWMuYmxvY2suc3RhdHVzKSkgb3IgNDAzCiAgICByZXR1cm4gb3V0CmVuZAoKbG9jYWwgZnVuY3Rpb24gcGFyc2UocmF3KQogICAgbG9jYWwgZW50cmllcyA9IGNqc29uLmRlY29kZShyYXcpCiAgICBpZiB0eXBlKGVudHJpZXMpIH49ICJ0YWJsZSIgdGhlbiByZXR1cm4ge30gZW5kCiAgICBsb2NhbCBvdXQsIG4gPSB7fSwgMAogICAgZm9yIF8sIGUgaW4gaXBhaXJzKGVudHJpZXMpIGRvCiAgICAgICAgaWYgdHlwZShlKSA9PSAidGFibGUiIHRoZW4KICAgICAgICAgICAgbiA9IG4gKyAxCiAgICAgICAgICAgIG91dFtuXSA9IHsgcGF0aFByZWZpeCA9IGUucGF0aFByZWZpeCwgc3BlYyA9IGNvbXBpbGVfc3BlYyhlLnNwZWMpIH0KICAgICAgICBlbmQKICAgIGVuZAogICAgcmV0dXJuIG91dAplbmQKCi0tIExSVS1jYWNoZWQgcGFyc2U6IHJldXNlIHRoZSBjb21waWxlZCBmb3JtIHVudGlsIHRoZSByYXcgZGljdCBzdHJpbmcgY2hhbmdlcy4KZnVuY3Rpb24gTS5nZXQoaG9zdCwgcmF3KQogICAgbG9jYWwgaGl0ID0gY2FjaGU6Z2V0KGhvc3QpCiAgICBpZiBoaXQgYW5kIGhpdC5yYXcgPT0gcmF3IHRoZW4gcmV0dXJuIGhpdC5wYXJzZWQgZW5kCiAgICBsb2NhbCBwYXJzZWQgPSBwYXJzZShyYXcpCiAgICBjYWNoZTpzZXQoaG9zdCwgeyByYXcgPSByYXcsIHBhcnNlZCA9IHBhcnNlZCB9KQogICAgcmV0dXJuIHBhcnNlZAplbmQKCnJldHVybiBNCg==",
|
|
27
|
+
"site_logger.lua": "LS0gc2l0ZV9sb2dnZXIubHVhCi0tIE9wZW5SZXN0eSBsb2dfYnlfbHVhIC0gcnVucyBBRlRFUiB0aGUgcmVzcG9uc2UgaXMgc2VudC4KLS0gUHVyZSBzaGFyZWQtZGljdCBhbmFseXRpY3MuICBObyBSZWRpcywgbm8gdGltZXJzIGZvciBjb3VudGVycywgbm8gYmF0Y2hpbmcuCi0tIEV2ZXJ5IGluY3IoKSBpcyBhdG9taWMgYWNyb3NzIHdvcmtlcnMuCi0tCi0tIFNoYXJlZCBkaWN0IGtleSBzY2hlbWEgKGFuYWx5dGljcyB6b25lKToKLS0gICBzOntkb21haW59OntlcG9jaF9taW59OnIgICAgICAgIHJlcXVlc3QgY291bnQgICAgICAgICAgICAgICAoVFRMIDI0aCkKLS0gICBzOntkb21haW59OntlcG9jaF9taW59OmkgICAgICAgIGJhbmR3aWR0aCBpbiAgYnl0ZXMgICAgICAgICAoVFRMIDI0aCkKLS0gICBzOntkb21haW59OntlcG9jaF9taW59Om8gICAgICAgIGJhbmR3aWR0aCBvdXQgYnl0ZXMgICAgICAgICAoVFRMIDI0aCkKLS0gICBzOntkb21haW59OntlcG9jaF9taW59OnQgICAgICAgIHJlc3BvbnNlIHRpbWUgc3VtIChzZWNvbmRzKSAoVFRMIDI0aCkKLS0gICBzOntkb21haW59OntlcG9jaF9taW59OnUgICAgICAgIHBhZ2UgKG5vbi1zdGF0aWMpIHJlcXVlc3RzICAoVFRMIDI0aCkKLS0gICBjOntkb21haW59OntlcG9jaF9taW59OntDQ30gICAgIGNvdW50cnkgcGVyIG1pbnV0ZSAgICAgICAgICAoVFRMIDI0aCkKLS0gICB0Ontkb21haW59OnIgLyA6aSAvIDpvICAgICAgICAgIGxpZmV0aW1lIHRvdGFscyAgICAgICAgICAgICAobm8gVFRMKQotLSAgIGQ6e2RvbWFpbn0gICAgICAgICAgICAgICAgICAgICAgZG9tYWluIGluZGV4IG1hcmtlciAgICAgICAgIChubyBUVEwpCi0tCi0tICAgRGFpbHkgcm9sbHVwLCBhbGwgdW5kZXIgb25lIGBnOntkb21haW59OntZWVlZTU1ERH06YCBwcmVmaXggc28gbWdtdF9hcGkncwotLSAgIC9hbmFseXRpY3MvZ2VvIHNlcnZlcyB0aGUgd2hvbGUgZGF5IGluIGEgU0lOR0xFIGRpY3Qgc2NhbjoKLS0gICBnOntkb21haW59OntZWVlZTU1ERH06e0NDfSAgICAgIGNvdW50cnkgaGl0IGNvdW50ICAgICAgICAgICAoVFRMIDQ4aCkKLS0gICBnOntkb21haW59OntZWVlZTU1ERH06diAgICAgICAgIGRpc3RpbmN0IHZpc2l0b3JzICAgICAgICAgICAoVFRMIDQ4aCkKLS0gICBnOntkb21haW59OntZWVlZTU1ERH06cDp7cGF0aH0gIHBhdGggaGl0IGNvdW50ICAgICAgICAgICAgICAoVFRMIDQ4aCkKLS0gICBnOntkb21haW59OntZWVlZTU1ERH06czp7Y29kZX0gIHN0YXR1cy1jb2RlIGNvdW50ICAgICAgICAgICAoVFRMIDQ4aCkKLS0KLS0gU2hhcmVkIGRpY3Qga2V5IHNjaGVtYSAodmlzaXRvcnMgem9uZSk6Ci0tICAgdnNhbHQ6e1lZWVlNTUREfSAgICAgICAgICAgICAgICBwZXItZGF5IGhhc2ggc2FsdCAgICAgICAgICAgKFRUTCA0OGgpCi0tICAgdmQ6e2RvbWFpbn06e1lZWVlNTUREfTp7aGFzaH0gICBkaXN0aW5jdC12aXNpdG9yIG1hcmtlciAgICAgKFRUTCA0OGgpCi0tCi0tIFNoYXJlZCBkaWN0IGtleSBzY2hlbWEgKHJlcXVlc3RfZGF0YSB6b25lKToKLS0gICBybG9nOntkb21haW59OnNlcSAgICAgICAgICAgICAgIG1vbm90b25pYyB3cml0ZSBwb2ludGVyCi0tICAgcmxvZzp7ZG9tYWlufTp7c2xvdH0gICAgICAgICAgICBKU09OIGVudHJ5IChyaW5nIGJ1ZikgICAgICAgKFRUTCAxaCkKLS0gICBsb2dfcGlwZTpzdWI6e2RvbWFpbn0gICAgICAgICAgIGxpdmUgc3Vic2NyaWJlciBmbGFnICAgICAgICAoVFRMIDMwcykKLS0gICBsb2dfcGlwZTpxOntkb21haW59ICAgICAgICAgICAgIGxpdmUgbG9nIHF1ZXVlIGVudHJpZXMKLS0KLS0gTk9URSBvbiBgOnVgIOKAlCBpdCBjb3VudHMgbm9uLXN0YXRpYyBSRVFVRVNUUywgbm90IHBlb3BsZS4gSXQgd2FzIHN1cmZhY2VkIGFzCi0tICJ1bmlxdWUgSVBzIiBhbGwgdGhlIHdheSB0byB0aGUgZGFzaGJvYXJkLCB3aGljaCBpdCBuZXZlciB3YXMuIFJlYWwgZGlzdGluY3QKLS0gdmlzaXRvcnMgYXJlIHRoZSBgdmQ6YC9gOnZgIHBhaXIgYmVsb3cuCgpsb2NhbCBjanNvbiA9IHJlcXVpcmUgImNqc29uLnNhZmUiCgotLSBTQUZFIExPQUQ6IEdlb0lQIE1vZHVsZSAocGVyLXdvcmtlciwgY2FjaGVkIGJ5IHJlcXVpcmUpCmxvY2FsIGdlb19vaywgZ2VvID0gcGNhbGwocmVxdWlyZSwgIm9wZW5zaGlwLmdlb19jb3VudHJ5IikKaWYgbm90IGdlb19vayB0aGVuCiAgICBnZW8gPSBuaWwKICAgIG5neC5sb2cobmd4LldBUk4sICJbc2l0ZV9sb2dnZXJdIGdlb19jb3VudHJ5IG1vZHVsZSBub3QgYXZhaWxhYmxlLiBHZW9JUCBkaXNhYmxlZC4iKQplbmQKCi0tIFNBRkUgTE9BRDogUGlwZSBtb2R1bGUgKHBlci13b3JrZXIsIGNhY2hlZCBieSByZXF1aXJlKQpsb2NhbCBwaXBlX29rLCBwaXBlX2xvZyA9IHBjYWxsKHJlcXVpcmUsICJvcGVuc2hpcC5waXBlX2xvZyIpCmlmIG5vdCBwaXBlX29rIHRoZW4gcGlwZV9sb2cgPSBuaWwgZW5kCgpsb2NhbCBhbmFseXRpY3MgICAgPSBuZ3guc2hhcmVkLmFuYWx5dGljcwpsb2NhbCByZXF1ZXN0X2RhdGEgPSBuZ3guc2hhcmVkLnJlcXVlc3RfZGF0YQotLSBQZXItaG9zdCBlZGdlIGNvbmZpZywgcHVzaGVkIGJ5IHRoZSBBUEkgKHNlZSBtZ210X2FwaSdzIC9hbmFseXRpY3MvY29uZmlnKS4KLS0KLS0gVGhlIGBydWxlc2Agem9uZSwgTk9UIGBhbmFseXRpY3NgOiB0aGlzIGhvbGRzIGEgaGFuZGZ1bCBvZiBzbWFsbCBjb25maWcgdmFsdWVzIGFuZCBpcwotLSBuZXZlciB1bmRlciBldmljdGlvbiBwcmVzc3VyZSwgd2hlcmVhcyB0aGUgYW5hbHl0aWNzIHpvbmUgaXMgYSAyNTYgTUIgY2h1cm4gb2YgY291bnRlcnMuCi0tIEFuIGV2aWN0ZWQgZmxhZyB0aGVyZSB3b3VsZCBzaWxlbnRseSBzdG9wIHBhdGggY29sbGVjdGlvbiB3aXRoIG5vdGhpbmcgdG8gZXhwbGFpbiB3aHkuCmxvY2FsIHJ1bGVzX2RpY3QgICA9IG5neC5zaGFyZWQucnVsZXMKLS0gT3B0aW9uYWw6IGEgYm94IHdob3NlIG5naW54LmNvbmYgcHJlZGF0ZXMgdGhpcyB6b25lIGtlZXBzIHdvcmtpbmcsIGp1c3Qgd2l0aG91dAotLSBkaXN0aW5jdC12aXNpdG9yIGNvdW50cy4gTmV2ZXIgYXNzdW1lIGEgZGljdCBleGlzdHMuCmxvY2FsIHZpc2l0b3JzICAgICA9IG5neC5zaGFyZWQudmlzaXRvcnMKaWYgbm90IGFuYWx5dGljcyBvciBub3QgcmVxdWVzdF9kYXRhIHRoZW4gcmV0dXJuIGVuZAoKLS0g4pSA4pSAIEhlbHBlcnMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACgpsb2NhbCBmdW5jdGlvbiBub3JtYWxpemUoaG9zdCkKICAgIGlmIG5vdCBob3N0IHRoZW4gcmV0dXJuIG5pbCBlbmQKICAgIGxvY2FsIGggPSBob3N0Omxvd2VyKCkKICAgIGlmIGg6c3ViKDEsIDQpID09ICJ3d3cuIiB0aGVuIGggPSBoOnN1Yig1KSBlbmQKICAgIHJldHVybiBoCmVuZAoKbG9jYWwgX2RheSA9IHsgc3RyID0gIiIsIHRzID0gMCB9CmxvY2FsIGZ1bmN0aW9uIHRvZGF5KCkKICAgIGxvY2FsIG5vdyA9IG5neC5ub3coKQogICAgaWYgbm93IC0gX2RheS50cyA+IDYwIHRoZW4KICAgICAgICBfZGF5LnN0ciA9IG9zLmRhdGUoIiElWSVtJWQiLCBub3cpCiAgICAgICAgX2RheS50cyA9IG5vdwogICAgZW5kCiAgICByZXR1cm4gX2RheS5zdHIKZW5kCgotLSBGYXN0IGNoZWNrIGlmIFVSSSBpcyBhIHN0YXRpYyBhc3NldCAoZm9yIHVuaXF1ZV9yZXF1ZXN0cyBjb3VudGVyKQpsb2NhbCBmdW5jdGlvbiBpc19zdGF0aWNfYXNzZXQodSkKICAgIGxvY2FsIGxvd2VyID0gdTpsb3dlcigpCgogICAgLS0gU3RhdGljIGZpbGUgZXh0ZW5zaW9ucwogICAgaWYgbG93ZXI6bWF0Y2goIiUuanMkIikgb3IgbG93ZXI6bWF0Y2goIiUuY3NzJCIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiJS5qcGckIikgb3IgbG93ZXI6bWF0Y2goIiUuanBlZyQiKSBvcgogICAgICAgbG93ZXI6bWF0Y2goIiUucG5nJCIpIG9yIGxvd2VyOm1hdGNoKCIlLmdpZiQiKSBvcgogICAgICAgbG93ZXI6bWF0Y2goIiUuc3ZnJCIpIG9yIGxvd2VyOm1hdGNoKCIlLndlYnAkIikgb3IKICAgICAgIGxvd2VyOm1hdGNoKCIlLmljbyQiKSBvciBsb3dlcjptYXRjaCgiJS5ibXAkIikgb3IKICAgICAgIGxvd2VyOm1hdGNoKCIlLndvZmYyPyQiKSBvciBsb3dlcjptYXRjaCgiJS50dGYkIikgb3IKICAgICAgIGxvd2VyOm1hdGNoKCIlLmVvdCQiKSBvciBsb3dlcjptYXRjaCgiJS5vdGYkIikgb3IKICAgICAgIGxvd2VyOm1hdGNoKCIlLm1wNCQiKSBvciBsb3dlcjptYXRjaCgiJS53ZWJtJCIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiJS5tcDMkIikgb3IgbG93ZXI6bWF0Y2goIiUud2F2JCIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiJS5wZGYkIikgb3IgbG93ZXI6bWF0Y2goIiUuemlwJCIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiJS50YXIkIikgb3IgbG93ZXI6bWF0Y2goIiUuZ3okIikgb3IKICAgICAgIGxvd2VyOm1hdGNoKCIlLnhtbCQiKSBvciBsb3dlcjptYXRjaCgiJS5qc29uJCIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiJS50eHQkIikgb3IgbG93ZXI6bWF0Y2goIiUubWFwJCIpIHRoZW4KICAgICAgICByZXR1cm4gdHJ1ZQogICAgZW5kCgogICAgLS0gQ29tbW9uIHN0YXRpYyBwYXRocwogICAgaWYgbG93ZXI6bWF0Y2goIl4vX25leHQvc3RhdGljLyIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiXi9zdGF0aWMvIikgb3IKICAgICAgIGxvd2VyOm1hdGNoKCJeL2Fzc2V0cy8iKSBvcgogICAgICAgbG93ZXI6bWF0Y2goIl4vcHVibGljLyIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiL2Zhdmljb24lLmljbyIpIHRoZW4KICAgICAgICByZXR1cm4gdHJ1ZQogICAgZW5kCgogICAgcmV0dXJuIGZhbHNlCmVuZAoKLS0gQ29sbGFwc2UgYSByZXF1ZXN0IFVSSSBpbnRvIGEgbG93LWNhcmRpbmFsaXR5IGJ1Y2tldCBzdWl0YWJsZSBhcyBhIGRpY3Qga2V5LgotLSBXaXRob3V0IHRoaXMsICJ0b3AgcGF0aHMiIGlzIHVuYm91bmRlZDogZXZlcnkgP3Rva2VuPSwgZXZlcnkgL29yZGVycy80ODIxOSwgYW5kCi0tIGV2ZXJ5IDQwNCBhIHNjYW5uZXIgcHJvYmVzIG1pbnRzIGEgcGVybWFuZW50IGtleSwgYW5kIHRoZSBhbmFseXRpY3Mgem9uZQotLSBMUlUtZXZpY3RzIHJlYWwgY291bnRlcnMgdG8gc3RvcmUganVuay4KbG9jYWwgZnVuY3Rpb24gbm9ybWFsaXplX3BhdGgodSkKICAgIC0tIFF1ZXJ5IHN0cmluZyBjYXJyaWVzIGlkcy90b2tlbnMgYW5kIG5ldmVyIGlkZW50aWZpZXMgdGhlIHJvdXRlLgogICAgbG9jYWwgcGF0aCA9IHU6bWF0Y2goIl4oW14/I10qKSIpIG9yIHUKICAgIGlmIHBhdGggPT0gIiIgdGhlbiByZXR1cm4gIi8iIGVuZAogICAgLS0gTnVtZXJpYyBhbmQgVVVJRC9oZXggc2VnbWVudHMgYXJlIGlkcywgbm90IHJvdXRlczogL29yZGVycy80ODIxOSBhbmQKICAgIC0tIC9vcmRlcnMvNDgyMjAgYXJlIG9uZSBwYXRoLgogICAgcGF0aCA9IHBhdGg6Z3N1YigiLyVkKyIsICIvOmlkIikKICAgIHBhdGggPSBwYXRoOmdzdWIoIi8leCV4JXgleCV4JXgleCV4JS0/JXgqJS0/JXgqJS0/JXgqJS0/JXgqIiwgIi86aWQiKQogICAgLS0gQm91bmQgdGhlIGtleSBpdHNlbGYg4oCUIGEgbG9uZyBVUkkgbXVzdCBub3QgYmVjb21lIGEgbG9uZyBrZXkuCiAgICBpZiAjcGF0aCA+IDEyMCB0aGVuIHBhdGggPSBwYXRoOnN1YigxLCAxMjApIC4uICLigKYiIGVuZAogICAgcmV0dXJuIHBhdGgKZW5kCgotLSDilIDilIAgRW51bWVyYWJsZSBzZXRzLCB3aXRob3V0IGEgem9uZSBzY2FuIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAotLQotLSBSZWFkaW5nIHRoZXNlIGNvdW50ZXJzIGJhY2sgdXNlZCB0byBuZWVkIGtleSBESVNDT1ZFUlksIGFuZCBhIHNoYXJlZCBkaWN0IG9mZmVycyBleGFjdGx5Ci0tIG9uZSBtZWNoYW5pc20gZm9yIHRoYXQ6IGBnZXRfa2V5c2AsIHdoaWNoIHdhbGtzIEVWRVJZIGtleSBpbiB0aGUgem9uZSBob2xkaW5nIGl0cyBsb2NrLgotLSBDb3N0IHNjYWxlZCB3aXRoIGhvdyBtdWNoIHdhcyBpbiB0aGUgMjU2IE1CIHpvbmUsIG5vdCB3aXRoIHdoYXQgd2FzIGJlaW5nIGFza2VkIGZvciwgYW5kCi0tIGl0IHJhbiBvbiB0aGUgbWdtdCBwYXRoIGZvdXIgZGlmZmVyZW50IHdheXMuCi0tCi0tIFNvIGV2ZXJ5IHVuYm91bmRlZCBzZXQgbm93IGNhcnJpZXMgaXRzIG93biBpbmRleDogYSBjb3VudGVyIHBsdXMgbnVtYmVyZWQgc2xvdHMuCi0tCi0tICAgICA8Y291bnRlcj4gICAgICAgIGhvdyBtYW55IGRpc3RpbmN0IG1lbWJlcnMKLS0gICAgIDxwcmVmaXg+PG4+ICAgICAgdGhlIG4tdGggbWVtYmVyCi0tCi0tIEEgcmVhZGVyIHJlYWRzIHRoZSBjb3VudGVyIGFuZCB0aGVuIHJlYWRzIHNsb3RzIDEuLm4uIEJvdW5kZWQgYnkgdGhlIGFuc3dlci4KLS0KLS0gVGhlIHdyaXRlIG9ubHkgaGFwcGVucyBvbiBhIG1lbWJlcidzIEZJUlNUIHNpZ2h0aW5nLCBzbyBzdGVhZHkgc3RhdGUgY29zdHMgbm90aGluZzogdGhlCi0tIG1pbGxpb250aCByZXF1ZXN0IGZyb20gR2VybWFueSB0b2RheSB0YWtlcyB0aGUgcGxhaW4gYGluY3JgIHBhdGggYW5kIHRvdWNoZXMgbm8gaW5kZXguCmxvY2FsIGZ1bmN0aW9uIGluZGV4X2FkZChjb3VudGVyX2tleSwgc2xvdF9wcmVmaXgsIG1lbWJlciwgdHRsKQogICAgbG9jYWwgbiA9IGFuYWx5dGljczppbmNyKGNvdW50ZXJfa2V5LCAxLCAwLCB0dGwpCiAgICBpZiBuIHRoZW4gYW5hbHl0aWNzOnNldChzbG90X3ByZWZpeCAuLiBuLCBtZW1iZXIsIHR0bCkgZW5kCmVuZAoKLS0tIEFkZCAxIHRvIGEgY291bnRlciwgY3JlYXRpbmcgaXQgKHdpdGggVFRMKSBhbmQgaW5kZXhpbmcgaXQgb24gZmlyc3Qgc2lnaHRpbmcuCi0tCi0tIGBpbmNyYCB3aXRoIG5vIGBpbml0YCByZXR1cm5zIG5pbCBmb3IgYW4gYWJzZW50IGtleSwgd2hpY2ggZG91YmxlcyBhcyB0aGUgZXhpc3RlbmNlCi0tIHByb2JlIOKAlCBzbyB0aGUgY29tbW9uIGNhc2UgaXMgT05FIGhhc2ggb3BlcmF0aW9uLiBUVEwgaXMgc2V0IGJ5IHRoZSBjcmVhdGluZyBgc2FmZV9hZGRgCi0tIHJhdGhlciB0aGFuIHBhc3NlZCB0byBgaW5jcmA6IHNoZGljdCByZWplY3RzIGBpbml0X3R0bGAgd2l0aG91dCBgaW5pdGAsIGFuZCB0aGF0IHJhaXNlcyBhCi0tIEx1YSBlcnJvciB3aGljaCBhYm9ydHMgdGhlIHdob2xlIGxvZyBoYW5kbGVyIChpdCBoYXMgc2lsZW50bHkgemVyb2VkIGV2ZXJ5IGNvdW50ZXIgYmVsb3cKLS0gaXQgYmVmb3JlKS4KbG9jYWwgZnVuY3Rpb24gYnVtcF9pbmRleGVkKGtleSwgdHRsLCBjb3VudGVyX2tleSwgc2xvdF9wcmVmaXgsIG1lbWJlcikKICAgIGlmIGFuYWx5dGljczppbmNyKGtleSwgMSkgdGhlbiByZXR1cm4gZW5kCiAgICBpZiBhbmFseXRpY3M6c2FmZV9hZGQoa2V5LCAxLCB0dGwpIHRoZW4KICAgICAgICBpbmRleF9hZGQoY291bnRlcl9rZXksIHNsb3RfcHJlZml4LCBtZW1iZXIsIHR0bCkKICAgIGVsc2UKICAgICAgICAtLSBBbm90aGVyIHdvcmtlciBjcmVhdGVkIGl0IGJldHdlZW4gb3VyIHByb2JlIGFuZCBvdXIgYWRkOyBvdXIgKzEgc3RpbGwgY291bnRzLgogICAgICAgIGFuYWx5dGljczppbmNyKGtleSwgMSkKICAgIGVuZAplbmQKCmxvY2FsIFJJTkcgICA9IDEwMDAKbG9jYWwgRDI0SCAgID0gODY0MDAKbG9jYWwgRDQ4SCAgID0gMTcyODAwCmxvY2FsIEQxSCAgICA9IDM2MDAKCi0tIERpc3RpbmN0IHBhdGhzIHRyYWNrZWQgcGVyIGRvbWFpbiBwZXIgZGF5LiBQYXN0IHRoaXMgdGhlIHRhaWwgZm9sZHMgaW50bwotLSAib3RoZXIiIHJhdGhlciB0aGFuIGdyb3dpbmcgdGhlIHpvbmUg4oCUIGEgVVJMLWZ1enppbmcgYm90IGlzIGNhcHBlZCBhdCBvbmUKLS0gZXh0cmEga2V5LCBub3QgdGhvdXNhbmRzLgpsb2NhbCBQQVRIX0NBUkRJTkFMSVRZX0NBUCA9IDIwMDAKCi0tIOKUgOKUgCBDYXB0dXJlIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAoKbG9jYWwgaG9zdCA9IG5vcm1hbGl6ZShuZ3gudmFyLmhvc3QpCmlmIG5vdCBob3N0IHRoZW4gcmV0dXJuIGVuZAoKbG9jYWwgaXAgICAgICA9IG5neC52YXIucmVtb3RlX2FkZHIgICAgb3IgIjAuMC4wLjAiCmxvY2FsIHRzICAgICAgPSBuZ3gubm93KCkKbG9jYWwgdWEgICAgICA9IG5neC52YXIuaHR0cF91c2VyX2FnZW50IG9yICIiCmxvY2FsIHVyaSAgICAgPSBuZ3gudmFyLnJlcXVlc3RfdXJpICAgIG9yICIvIgpsb2NhbCByZXFfbGVuID0gdG9udW1iZXIobmd4LnZhci5yZXF1ZXN0X2xlbmd0aCkgb3IgMApsb2NhbCBieXRlcyAgID0gdG9udW1iZXIobmd4LnZhci5ieXRlc19zZW50KSAgICAgb3IgMApsb2NhbCBydCAgICAgID0gdG9udW1iZXIobmd4LnZhci5yZXF1ZXN0X3RpbWUpICAgb3IgMCAgLS0gc2Vjb25kcyAoZmxvYXQpCmxvY2FsIG1ldGhvZCAgPSBuZ3gudmFyLnJlcXVlc3RfbWV0aG9kIG9yICJHRVQiCmxvY2FsIHN0YXR1cyAgPSBuZ3gudmFyLnN0YXR1cyAgICAgICAgIG9yICIwIgoKLS0gQ2xpZW50IGNvdW50cnksIHJlc29sdmVkIE9OQ0UgcGVyIHJlcXVlc3QuCi0tCi0tIEhvaXN0ZWQgb3V0IG9mIHRoZSBnZW8gYmxvY2sgYmVjYXVzZSBUSFJFRSBjb25zdW1lcnMgbmVlZCBpdCDigJQgdGhlIGRhaWx5L3Blci1taW51dGUKLS0gcm9sbHVwcywgdGhlIHJhdyByaW5nIGJ1ZmZlciBiZWhpbmQgL2xvZ3MvcmVjZW50LCBhbmQgdGhlIGxpdmUgU1NFIHBpcGUuIEl0IHVzZWQgdG8gYmUKLS0gbG9va2VkIHVwIGluc2lkZSB0aGUgcm9sbHVwIGFuZCBhZ2FpbiBpbnNpZGUgcGlwZV9sb2csIHNvIHRoZSByaW5nIGJ1ZmZlciBoYWQgbm8KLS0gY291bnRyeSBhdCBhbGw6IGEgcmVxdWVzdC1sb2cgbGlzdCBzaG93ZWQgZmxhZ3Mgb24gcm93cyB0aGF0IGFycml2ZWQgbGl2ZSBhbmQgbm9uZSBvbgotLSByb3dzIGJhY2tmaWxsZWQgZnJvbSAvbG9ncy9yZWNlbnQsIGZvciB0aGUgc2FtZSB0cmFmZmljLgotLQotLSBwY2FsbCdkIGJlY2F1c2UgYSBjb3JydXB0IG9yIHBhcnRpYWxseS13cml0dGVuIG1tZGIgbWFrZXMgdGhlIGxvb2t1cCByYWlzZSwgYW5kIGFuCi0tIGVycm9yIGhlcmUgd291bGQgYWJvcnQgZXZlcnkgY291bnRlciBiZWxvdyBpdCAoc2VlIHRoZSBzZWN0aW9uIGhlYWRlcikuCmxvY2FsIGNjID0gbmlsCmlmIGdlbyBhbmQgZ2VvLmdldF9jb3VudHJ5X2NvZGUgdGhlbgogICAgbG9jYWwgb2tfY2MsIHJlcyA9IHBjYWxsKGdlby5nZXRfY291bnRyeV9jb2RlLCBpcCkKICAgIGlmIG9rX2NjIGFuZCB0eXBlKHJlcykgPT0gInN0cmluZyIgYW5kIHJlcyB+PSAiIiB0aGVuIGNjID0gcmVzIGVuZAplbmQKCi0tIOKUgOKUgCAxLiBNaW51dGUtYnVja2V0IGNvdW50ZXJzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAoKbG9jYWwgbWludXRlID0gbWF0aC5mbG9vcih0cyAvIDYwKQpsb2NhbCBwID0gInM6IiAuLiBob3N0IC4uICI6IiAuLiBtaW51dGUKCmFuYWx5dGljczppbmNyKHAgLi4gIjpyIiwgMSwgICAgICAwLCBEMjRIKQphbmFseXRpY3M6aW5jcihwIC4uICI6aSIsIHJlcV9sZW4sIDAsIEQyNEgpCmFuYWx5dGljczppbmNyKHAgLi4gIjpvIiwgYnl0ZXMsICAgMCwgRDI0SCkKCi0tIFJlc3BvbnNlIHRpbWUgYXMgZmxvYXQgc2Vjb25kcyAobWF0Y2hlcyBvcmlnaW5hbCBwcmVjaXNpb24pCmlmIHJ0ID4gMCB0aGVuCiAgICAtLSBzYWZlX2FkZCBpbml0aWFsaXplcywgaW5jciBhZGRzIC0gZW11bGF0ZSBISU5DUkJZRkxPQVQgd2l0aCBpbnRlZ2VyIG1pY3JvcwogICAgbG9jYWwgcnRfdXMgPSBtYXRoLmZsb29yKHJ0ICogMTAwMDAwMCkKICAgIGFuYWx5dGljczppbmNyKHAgLi4gIjp0IiwgcnRfdXMsIDAsIEQyNEgpCmVuZAoKLS0gVW5pcXVlIChub24tc3RhdGljKSByZXF1ZXN0IGNvdW50ZXIKaWYgbm90IGlzX3N0YXRpY19hc3NldCh1cmkpIHRoZW4KICAgIGFuYWx5dGljczppbmNyKHAgLi4gIjp1IiwgMSwgMCwgRDI0SCkKZW5kCgotLSDilIDilIAgMi4gTGlmZXRpbWUgdG90YWxzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAoKYW5hbHl0aWNzOmluY3IoInQ6IiAuLiBob3N0IC4uICI6ciIsIDEsICAgICAgIDApCmFuYWx5dGljczppbmNyKCJ0OiIgLi4gaG9zdCAuLiAiOmkiLCByZXFfbGVuLCAwKQphbmFseXRpY3M6aW5jcigidDoiIC4uIGhvc3QgLi4gIjpvIiwgYnl0ZXMsICAgMCkKCi0tIERvbWFpbiBpbmRleC4gYHNhZmVfYWRkYCByZXR1cm5pbmcgdHJ1ZSBtZWFucyB0aGlzIGlzIHRoZSBmaXJzdCByZXF1ZXN0IHRoaXMgYm94IGhhcwotLSBldmVyIHNlZW4gZm9yIHRoZSBob3N0LCB3aGljaCBpcyBleGFjdGx5IHdoZW4gdGhlIGVudW1lcmFibGUgaW5kZXggbmVlZHMgYXBwZW5kaW5nIOKAlAotLSBzbyBkb21haW4gZGlzY292ZXJ5IG5vIGxvbmdlciBjb3N0cyBhIHpvbmUgc2NhbiBlaXRoZXIuCmlmIGFuYWx5dGljczpzYWZlX2FkZCgiZDoiIC4uIGhvc3QsIDEpIHRoZW4KICAgIGluZGV4X2FkZCgiZG4iLCAiZGk6IiwgaG9zdCkKZW5kCgotLSDilIDilIAgMy4gRGFpbHkgcm9sbHVwOiBnZW8sIHZpc2l0b3JzLCBwYXRocywgc3RhdHVzZXMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tCi0tIEVhY2ggc3ViLWJsb2NrIGlzIHBjYWxsJ2QgU0VQQVJBVEVMWSwgYW5kIHRoYXQgaXMgbG9hZC1iZWFyaW5nIHJhdGhlciB0aGFuCi0tIGRlZmVuc2l2ZSBoYWJpdC4gQSByYWlzZWQgZXJyb3IgaW4gbG9nX2J5X2x1YSBhYm9ydHMgdGhlIHJlbWFpbmRlciBvZiB0aGUKLS0gaGFuZGxlciwgc28gb25lIGJhZCBzaGRpY3QgY2FsbCBzaWxlbnRseSB6ZXJvZXMgZXZlcnkgY291bnRlciB3cml0dGVuIGFmdGVyIGl0IOKAlAotLSB3aGljaCBpcyBleGFjdGx5IHdoYXQgYW4gYGluY3IoLi4uLCBuaWwsIHR0bClgIGhlcmUgZGlkOiBwYXRocyBBTkQgc3RhdHVzZXMgcmVhZAotLSBhcyAibm8gdHJhZmZpYyIgd2hpbGUgcmVxdWVzdHMgYW5kIGJhbmR3aWR0aCBsb29rZWQgcGVyZmVjdC4gSXNvbGF0aW5nIHRoZW0KLS0gbWVhbnMgYSBmdXR1cmUgZWRpdCBjYW4gbG9zZSBhdCBtb3N0IGl0cyBvd24gbWV0cmljLgoKbG9jYWwgZGF5ICA9IHRvZGF5KCkKbG9jYWwgZ3BmeCA9ICJnOiIgLi4gaG9zdCAuLiAiOiIgLi4gZGF5IC4uICI6IgoKLS0gM2EuIEdlb0lQLiBgY2NgIHdhcyByZXNvbHZlZCBvbmNlIGFib3ZlIGFuZCBpcyByZXVzZWQgYnkgdGhlIHJpbmcgYnVmZmVyIGFuZCB0aGUKLS0gbGl2ZSBwaXBlLCBzbyBhIHJlcXVlc3QgY29zdHMgZXhhY3RseSBvbmUgbW1kYiBsb29rdXAgbm8gbWF0dGVyIGhvdyBtYW55IGNvbnN1bWVycwotLSByZXBvcnQgaXRzIGNvdW50cnkuCmlmIGNjIHRoZW4KICAgIHBjYWxsKGZ1bmN0aW9uKCkKICAgICAgICAtLSBEYWlseSBnZW8gKGZvciAvYW5hbHl0aWNzL2dlbyBlbmRwb2ludCkKICAgICAgICBidW1wX2luZGV4ZWQoZ3BmeCAuLiBjYywgRDQ4SCwgZ3BmeCAuLiAiY24iLCBncGZ4IC4uICJjaToiLCBjYykKICAgICAgICAtLSBQZXItbWludXRlIGdlbyAoZm9yIHRoZSB0aW1lLXNlcmllcyBjb3VudHJ5IGJyZWFrZG93bikuIEluZGV4ZWQgcGVyIE1JTlVURSwgc28KICAgICAgICAtLSB0aGUgc2NyYXBlciByZWFkcyBvbmx5IHRoZSBtaW51dGVzIGluIGl0cyB3aW5kb3cuCiAgICAgICAgbG9jYWwgbXBmeCA9ICJjOiIgLi4gaG9zdCAuLiAiOiIgLi4gbWludXRlIC4uICI6IgogICAgICAgIGJ1bXBfaW5kZXhlZChtcGZ4IC4uIGNjLCBEMjRILCBtcGZ4IC4uICJuIiwgbXBmeCAuLiAiaToiLCBjYykKICAgIGVuZCkKZW5kCgotLSAzYi4gRGlzdGluY3QgdmlzaXRvcnMg4oCUIGEgQ09VTlQsIG5ldmVyIGFuIGlkZW50aXR5LgotLQotLSBUaGUgYWRkcmVzcyBpcyBoYXNoZWQgd2l0aCBhIHNhbHQgdGhhdCBpcyBnZW5lcmF0ZWQgb24gdGhpcyBib3gsIHJvdGF0ZXMgZGFpbHksCi0tIGFuZCBpcyBuZXZlciB3cml0dGVuIGFueXdoZXJlIGJ1dCB0aGlzIHNoYXJlZCBkaWN0LCBzbyB0aGUgbWFya2VyIGtleXMgYXJlIG5vdAotLSByZXZlcnNpYmxlIHRvIGFuIElQIGFuZCBhcmUgd29ydGhsZXNzIHRoZSBuZXh0IGRheS4gT25seSB0aGUgcmVzdWx0aW5nIGNvdW50ZXIKLS0gaXMgZXZlciBmbHVzaGVkIHRvIFBvc3RncmVzOyBubyBwZXItdmlzaXRvciByb3cgZXhpc3RzIGF0IGFueSBsYXllci4gVGhhdCBpcwotLSB3aGF0IGxldHMgdXMgcmVwb3J0IHJlYWwgdmlzaXRvciBudW1iZXJzIHdoaWxlIHN0aWxsIG5vdCBjb2xsZWN0aW5nIGJlaGF2aW91cmFsCi0tIGFuYWx5dGljcyBvbiBhbnlvbmUncyBlbmQgdXNlcnMuCi0tCi0tIFBlciBEQVksIG5vdCBwZXIgbWludXRlOiBhIHBlci1taW51dGUgc2V0IGlzIH4xNDQweCB0aGUga2V5cyBmb3IgYSBudW1iZXIKLS0gbm9ib2R5IHJlYWRzLCBhbmQgd291bGQgZXZpY3QgdGhlIGNvdW50ZXJzIGl0IGV4aXN0cyB0byBhbm5vdGF0ZS4KcGNhbGwoZnVuY3Rpb24oKQppZiB2aXNpdG9ycyB0aGVuCiAgICBsb2NhbCBzYWx0X2tleSA9ICJ2c2FsdDoiIC4uIGRheQogICAgbG9jYWwgc2FsdCA9IHZpc2l0b3JzOmdldChzYWx0X2tleSkKICAgIGlmIG5vdCBzYWx0IHRoZW4KICAgICAgICAtLSBGaXJzdCB3cml0ZXIgd2luczsgYSByYWNpbmcgd29ya2VyJ3Mgc2FmZV9hZGQgZmFpbHMgYW5kIGl0IHJlLXJlYWRzLiBUaGUKICAgICAgICAtLSBzYWx0IG9ubHkgaGFzIHRvIGJlIHVucHJlZGljdGFibGUgYW5kIHN0YWJsZSBmb3IgdGhlIGRheS4KICAgICAgICBzYWx0ID0gdG9zdHJpbmcobmd4Lm5vdygpKSAuLiB0b3N0cmluZyhtYXRoLnJhbmRvbSgxLCAyMTQ3NDgzNjQ3KSkKICAgICAgICBsb2NhbCBvayA9IHZpc2l0b3JzOnNhZmVfYWRkKHNhbHRfa2V5LCBzYWx0LCBENDhIKQogICAgICAgIGlmIG5vdCBvayB0aGVuIHNhbHQgPSB2aXNpdG9yczpnZXQoc2FsdF9rZXkpIG9yIHNhbHQgZW5kCiAgICBlbmQKICAgIC0tIHNhZmVfYWRkIGlzIHRoZSBkZWR1cDogaXQgc3VjY2VlZHMgT05MWSBvbiB0aGlzIHZpc2l0b3IncyBmaXJzdCByZXF1ZXN0CiAgICAtLSB0b2RheSwgc28gdGhlIGNvdW50ZXIgYmVsb3cgaW5jcmVtZW50cyBleGFjdGx5IG9uY2UgcGVyIGRpc3RpbmN0IHZpc2l0b3IuCiAgICBsb2NhbCBtYXJrZXIgPSAidmQ6IiAuLiBob3N0IC4uICI6IiAuLiBkYXkgLi4gIjoiIC4uIG5neC5jcmMzMl9sb25nKHNhbHQgLi4gaXApCiAgICBpZiB2aXNpdG9yczpzYWZlX2FkZChtYXJrZXIsIDEsIEQ0OEgpIHRoZW4KICAgICAgICBhbmFseXRpY3M6aW5jcihncGZ4IC4uICJ2IiwgMSwgMCwgRDQ4SCkKICAgIGVuZAplbmQKZW5kKQoKLS0gM2MuIFRvcCBwYXRocyDigJQgT1BULUlOLCBub24tc3RhdGljIG9ubHksIG5vcm1hbGl6ZWQgYW5kIGNhcmRpbmFsaXR5LWNhcHBlZC4KLS0KLS0gT2ZmIHVubGVzcyB0aGUgcHJvamVjdCB0dXJuZWQgaXQgb24sIGJlY2F1c2UgdGhpcyBvbmUgYmxvY2sgaXMgdGhlIG1vc3QgZXhwZW5zaXZlIHRoaW5nCi0tIHRoZSBsb2cgaGFuZGxlciBkb2VzLiBNZWFzdXJlZCBvbiB0aGUgc2hpcHBlZCBlZGdlIGltYWdlLCBwZXIgcmVxdWVzdDoKLS0KLS0gICAgIHBhdGhzICh3aG9sZSBibG9jaykgICAgICAgIDEuNzIgdXMgICAgICA8LSA1NyUgb2YgdGhlIGNvdW50ZXIgcGF0aAotLSAgICAgICBvZiB3aGljaCBzdHJpbmcgd29yayAgICAgMS4zOCB1cyAgICAgIG5vcm1hbGl6ZV9wYXRoICsgaXNfc3RhdGljX2Fzc2V0Ci0tICAgICBtaW51dGUgYnVja2V0cyAoNSBpbmNyKSAgICAwLjYxIHVzCi0tICAgICBjb3VudHJ5ICgyIGluY3IpICAgICAgICAgICAwLjI0IHVzCi0tICAgICBzdGF0dXMgKDEgaW5jcikgICAgICAgICAgICAwLjE0IHVzCi0tICAgICB0aGlzIGZsYWcgcmVhZCAoMSBnZXQpICAgICAwLjA3IHVzCi0tCi0tIFNvIHRoZSBnYXRlIGNvc3RzIDAuMDcgdXMgYW5kIHNhdmVzIDEuNzIgdXMg4oCUIHRoZSBjb3VudGVyIHBhdGggZHJvcHMgZnJvbSB+My4wIHVzIHRvCi0tIH4xLjM1IHVzIHdpdGggcGF0aHMgb2ZmLiBJdCBpcyBhbHNvIHRoZSBoaWdoZXN0LWNhcmRpbmFsaXR5IGRpbWVuc2lvbiAodXAgdG8KLS0gUEFUSF9DQVJESU5BTElUWV9DQVAga2V5cyBwZXIgZG9tYWluIHBlciBkYXksIGFnYWluc3QgfjIwMCBjb3VudHJpZXMgYW5kIGEgZmV3IGRvemVuCi0tIHN0YXR1c2VzKSBhbmQgdGhlIGxhcmdlc3QgY29sdW1uIGluIHRoZSBkYWlseSByb2xsdXAuCi0tCi0tIEFic2VudCBmbGFnID0gb2ZmLiBBIGJveCB3aG9zZSBkaWN0IHdhcyBqdXN0IHJlc3RhcnRlZCB0aGVyZWZvcmUgY29sbGVjdHMgbm90aGluZyB1bnRpbAotLSB0aGUgQVBJIHJlLXB1c2hlcywgd2hpY2ggaXMgdGhlIHNhZmUgZGlyZWN0aW9uOiBubyBkYXRhIGJlYXRzIGRhdGEgbm9ib2R5IGFza2VkIHRvIHBheQotLSBmb3IuIFRoZSBEQiBpcyB0aGUgc291cmNlIG9mIHRydXRoIGFuZCByZS1wdXNoZXMgb24gZXZlcnkgcm91dGUgYXBwbHkuCmxvY2FsIGNvbGxlY3RfcGF0aHMgPSBydWxlc19kaWN0IGFuZCBydWxlc19kaWN0OmdldCgiY2ZnOiIgLi4gaG9zdCAuLiAiOnBhdGhzIikKCnBjYWxsKGZ1bmN0aW9uKCkKaWYgY29sbGVjdF9wYXRocyBhbmQgbm90IGlzX3N0YXRpY19hc3NldCh1cmkpIHRoZW4KICAgIC0tIEhvaXN0ZWQ6IG5vcm1hbGl6ZV9wYXRoIGlzIHRoZSBzaW5nbGUgbW9zdCBleHBlbnNpdmUgY2FsbCBpbiB0aGlzIGhhbmRsZXIgKH4xLjQgdXMKICAgIC0tIG9mIHN0cmluZyB3b3JrKSwgc28gaXQgcnVucyBleGFjdGx5IG9uY2UgZXZlbiB0aG91Z2ggYm90aCB0aGUgY291bnRlciBrZXkgYW5kIHRoZQogICAgLS0gaW5kZXggc2xvdCBuZWVkIGl0cyByZXN1bHQuCiAgICBsb2NhbCBub3JtID0gbm9ybWFsaXplX3BhdGgodXJpKQogICAgbG9jYWwgcGF0aF9rZXkgPSBncGZ4IC4uICJwOiIgLi4gbm9ybQogICAgLS0gaW5jci10aGVuLWFkZDogdGhlIGhvdCBwYXRoIGlzIE9ORSBoYXNoIGhpdCBvbiBhbiBleGlzdGluZyBrZXkuIGBpbmNyYCB3aXRoCiAgICAtLSBubyBpbml0IHJldHVybnMgbmlsIGZvciBhbiBhYnNlbnQga2V5LCB3aGljaCBkb3VibGVzIGFzIHRoZSBleGlzdGVuY2UgcHJvYmUsCiAgICAtLSBzbyBvbmx5IGEgcGF0aCB1bnNlZW4gdG9kYXkgcmVhY2hlcyB0aGUgY2FwIGNoZWNrIGJlbG93LgogICAgLS0KICAgIC0tIERlbGliZXJhdGVseSBubyBpbml0X3R0bCBoZXJlOiBzaGRpY3QgcmVqZWN0cyBpbml0X3R0bCB1bmxlc3MgaW5pdCBpcyBhbHNvCiAgICAtLSBnaXZlbiAoIidpbml0X3R0bCcgbXVzdCBiZSB1c2VkIHdpdGggJ2luaXQnIiksIGFuZCB0aGF0IHJhaXNlcyBhIEx1YSBlcnJvcgogICAgLS0gd2hpY2ggYWJvcnRzIHRoZSB3aG9sZSBsb2cgaGFuZGxlciDigJQgdGFraW5nIHRoZSBzdGF0dXMgY291bnRlcnMgYmVsb3cgZG93bgogICAgLS0gd2l0aCBpdC4gVGhlIFRUTCBpcyBzZXQgYnkgdGhlIHNhZmVfYWRkIG9uIHRoZSBjcmVhdGluZyByZXF1ZXN0IGluc3RlYWQuCiAgICBpZiBub3QgYW5hbHl0aWNzOmluY3IocGF0aF9rZXksIDEpIHRoZW4KICAgICAgICBsb2NhbCBkaXN0aW5jdCA9IGFuYWx5dGljczppbmNyKGdwZnggLi4gInBuIiwgMSwgMCwgRDQ4SCkgb3IgMAogICAgICAgIGlmIGRpc3RpbmN0ID4gUEFUSF9DQVJESU5BTElUWV9DQVAgdGhlbgogICAgICAgICAgICBhbmFseXRpY3M6aW5jcihncGZ4IC4uICJwOm90aGVyIiwgMSwgMCwgRDQ4SCkKICAgICAgICBlbHNlCiAgICAgICAgICAgIC0tIGBwbmAgd2FzIGFscmVhZHkgdGhlIGRpc3RpbmN0LXBhdGggY291bnRlciwgc28gdGhlIHNsb3RzIGp1c3QgZ2l2ZSBpdCBhbgogICAgICAgICAgICAtLSBlbnVtZXJhYmxlIHNpZGUuIFN0b3JlZCBXSVRIT1VUIHRoZSAicDoiIHByZWZpeDsgdGhlIHJlYWRlciBhZGRzIGl0IGJhY2suCiAgICAgICAgICAgIGlmIGFuYWx5dGljczpzYWZlX2FkZChwYXRoX2tleSwgMSwgRDQ4SCkgdGhlbgogICAgICAgICAgICAgICAgYW5hbHl0aWNzOnNldChncGZ4IC4uICJwaToiIC4uIGRpc3RpbmN0LCBub3JtLCBENDhIKQogICAgICAgICAgICBlbmQKICAgICAgICBlbmQKICAgIGVuZAplbmQKZW5kKQoKLS0gM2QuIFN0YXR1cy1jb2RlIG1peC4gQm91bmRlZCBieSBjb25zdHJ1Y3Rpb24gKGEgZmV3IGRvemVuIGNvZGVzKS4KcGNhbGwoZnVuY3Rpb24oKQogICAgYnVtcF9pbmRleGVkKGdwZnggLi4gInM6IiAuLiBzdGF0dXMsIEQ0OEgsIGdwZnggLi4gInNuIiwgZ3BmeCAuLiAic2k6Iiwgc3RhdHVzKQplbmQpCgotLSDilIDilIAgNC4gUmF3IHJlcXVlc3QgcmluZyBidWZmZXIg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACgpwY2FsbChmdW5jdGlvbigpCiAgICBsb2NhbCBva19qLCBqID0gcGNhbGwoY2pzb24uZW5jb2RlLCB7CiAgICAgICAgaXAgICAgID0gaXAsCiAgICAgICAgLS0gbmlsIGlzIHNpbXBseSBvbWl0dGVkIGJ5IGNqc29uLCBzbyBhIGJveCB3aXRoIG5vIEdlb0lQIHdyaXRlcyB0aGUgc2FtZSBzaGFwZQogICAgICAgIC0tIG1pbnVzIHRoaXMga2V5IHJhdGhlciB0aGFuIGEgbnVsbCB0aGUgcmVhZGVyIGhhcyB0byBzcGVjaWFsLWNhc2UuCiAgICAgICAgY291bnRyeSA9IGNjLAogICAgICAgIHRzICAgICA9IHRzLAogICAgICAgIG1ldGhvZCA9IG1ldGhvZCwKICAgICAgICBzdGF0dXMgPSBzdGF0dXMsCiAgICAgICAgdXJpICAgID0gdXJpLAogICAgICAgIHVhICAgICA9IHVhLAogICAgICAgIGJ3X2luICA9IHJlcV9sZW4sCiAgICAgICAgYndfb3V0ID0gYnl0ZXMsCiAgICAgICAgcnQgICAgID0gcnQsCiAgICB9KQogICAgaWYgb2tfaiBhbmQgaiB0aGVuCiAgICAgICAgbG9jYWwgc2VxICA9IHJlcXVlc3RfZGF0YTppbmNyKCJybG9nOiIgLi4gaG9zdCAuLiAiOnNlcSIsIDEsIDApCiAgICAgICAgbG9jYWwgc2xvdCA9IHNlcSAlIFJJTkcKICAgICAgICByZXF1ZXN0X2RhdGE6c2V0KCJybG9nOiIgLi4gaG9zdCAuLiAiOiIgLi4gc2xvdCwgaiwgRDFIKQogICAgZW5kCmVuZCkKCi0tIOKUgOKUgCA1LiBMaXZlLWxvZyBwaXBlIChvbmx5IHdoZW4gYSBzdWJzY3JpYmVyIGlzIHdhdGNoaW5nKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKLS0gRmlyZSB2aWEgdGltZXIgdG8gYXZvaWQgYmxvY2tpbmcgdGhlIGxvZyBwaGFzZQoKaWYgcGlwZV9sb2cgYW5kIHBpcGVfbG9nLnBpcGVfcmVxdWVzdF9sb2cKICAgYW5kIHJlcXVlc3RfZGF0YTpnZXQoImxvZ19waXBlOnN1YjoiIC4uIGhvc3QpIHRoZW4KICAgIG5neC50aW1lci5hdCgwLCBwaXBlX2xvZy5waXBlX3JlcXVlc3RfbG9nLAogICAgICAgICAgICAgICAgIGhvc3QsIGlwLCB0cywgdWEsIHVyaSwgcmVxX2xlbiwgYnl0ZXMsIHJ0LCBtZXRob2QsIHN0YXR1cywgY2MpCmVuZAo=",
|
|
28
|
+
"webhook_handler.lua": "LS0gd2ViaG9va19oYW5kbGVyLmx1YQotLSBIYW5kbGVzIGluY29taW5nIHdlYmhvb2sgZXZlbnRzIGZvcndhcmRlZCBmcm9tIHRoZSBTYWFTIGVkZ2UuCi0tIEludGVybmFsIG1hbmFnZW1lbnQgcG9ydCBvbmx5ICgxMjcuMC4wLjE6OTE0NSkuCi0tCi0tIFJvdXRlczoKLS0gICBQT1NUIC9faG9va3MvcHVzaCAgICAgICAgICAtIHJlY2VpdmUgYSBmb3J3YXJkZWQgR2l0SHViIHB1c2ggZXZlbnQKLS0gICBHRVQgIC9faG9va3MvcGVuZGluZyAgICAgICAtIGZldGNoIHN0b3JlZCBldmVudHMgKGZvciBsb2NhbCBhcHAgcG9sbGluZykKLS0gICBQT1NUIC9faG9va3MvYWNrICAgICAgICAgICAtIGFja25vd2xlZGdlIGNvbnN1bWVkIGV2ZW50cwotLQotLSBCZWhhdmlvciBvbiBQT1NUIC9faG9va3MvcHVzaDoKLS0gICAxLiBUcnkgdG8gcHJveHkgdG8gYSBsb2NhbCBPcGVuc2hpcCBBUEkgKGNvbmZpZ3VyYWJsZSB2aWEgWC1PcGVuc2hpcC1VcmwgaGVhZGVyKQotLSAgIDIuIElmIE9wZW5zaGlwIGlzIG5vdCByZWFjaGFibGUsIHN0b3JlIHRoZSBldmVudCBpbiBzaGFyZWQgZGljdCBmb3IgbGF0ZXIgcG9sbGluZwoKbG9jYWwgY2pzb24gPSByZXF1aXJlICJjanNvbi5zYWZlIgoKbG9jYWwgd2ViaG9va19ldmVudHMgPSBuZ3guc2hhcmVkLndlYmhvb2tfZXZlbnRzCmxvY2FsIHVyaSAgICAgICAgICAgID0gbmd4LnZhci51cmkKbG9jYWwgbWV0aG9kICAgICAgICAgPSBuZ3gucmVxLmdldF9tZXRob2QoKQoKbG9jYWwgZnVuY3Rpb24ganNvbl9yZXNwb25zZShkYXRhLCBjb2RlKQogICAgbmd4LnN0YXR1cyA9IGNvZGUgb3IgMjAwCiAgICBuZ3guaGVhZGVyWyJDb250ZW50LVR5cGUiXSA9ICJhcHBsaWNhdGlvbi9qc29uIgogICAgbmd4LnNheShjanNvbi5lbmNvZGUoZGF0YSkpCiAgICByZXR1cm4gbmd4LmV4aXQobmd4LnN0YXR1cykKZW5kCgotLSDilIDilIAgUE9TVCAvX2hvb2tzL3B1c2gg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tIFJlY2VpdmVzIGZvcndhcmRlZCB3ZWJob29rIHBheWxvYWQgZnJvbSBTYWFTLgotLSBIZWFkZXJzOgotLSAgIFgtT3BlbnNoaXAtVXJsOiBodHRwOi8vMTI3LjAuMC4xOjM0NTYgKGlmIE9wZW5zaGlwIHJ1bnMgb24gdGhpcyBzZXJ2ZXIpCi0tICAgWC1Ib29rLUlkOiB0aGUgc3Vic2NyaXB0aW9uIGhvb2tJZCAoZm9yIGNvcnJlbGF0aW9uKQoKaWYgdXJpID09ICIvX2hvb2tzL3B1c2giIGFuZCBtZXRob2QgPT0gIlBPU1QiIHRoZW4KICAgIG5neC5yZXEucmVhZF9ib2R5KCkKICAgIGxvY2FsIGJvZHkgPSBuZ3gucmVxLmdldF9ib2R5X2RhdGEoKQogICAgaWYgbm90IGJvZHkgdGhlbgogICAgICAgIHJldHVybiBqc29uX3Jlc3BvbnNlKHsgZXJyb3IgPSAiZW1wdHkgYm9keSIgfSwgNDAwKQogICAgZW5kCgogICAgbG9jYWwgb3BlbnNoaXBfdXJsID0gbmd4LnJlcS5nZXRfaGVhZGVycygpWyJ4LW9wZW5zaGlwLXVybCJdCgogICAgLS0gSWYgT3BlbnNoaXAgcnVucyBvbiB0aGlzIHNlcnZlciwgcHJveHkgZGlyZWN0bHkKICAgIGlmIG9wZW5zaGlwX3VybCBhbmQgb3BlbnNoaXBfdXJsIH49ICIiIHRoZW4KICAgICAgICBsb2NhbCBodHRwID0gcmVxdWlyZSAicmVzdHkuaHR0cCIKICAgICAgICBsb2NhbCBodHRwYyA9IGh0dHAubmV3KCkKICAgICAgICBodHRwYzpzZXRfdGltZW91dCg1MDAwKQoKICAgICAgICBsb2NhbCB0YXJnZXQgPSBvcGVuc2hpcF91cmwgLi4gIi9hcGkvd2ViaG9va3MvcHVzaCIKICAgICAgICBsb2NhbCByZXMsIGVyciA9IGh0dHBjOnJlcXVlc3RfdXJpKHRhcmdldCwgewogICAgICAgICAgICBtZXRob2QgID0gIlBPU1QiLAogICAgICAgICAgICBib2R5ICAgID0gYm9keSwKICAgICAgICAgICAgaGVhZGVycyA9IHsKICAgICAgICAgICAgICAgIFsiQ29udGVudC1UeXBlIl0gPSAiYXBwbGljYXRpb24vanNvbiIsCiAgICAgICAgICAgICAgICBbIlgtSG9vay1JZCJdICAgID0gbmd4LnJlcS5nZXRfaGVhZGVycygpWyJ4LWhvb2staWQiXSBvciAiIiwKICAgICAgICAgICAgfSwKICAgICAgICB9KQoKICAgICAgICBpZiByZXMgYW5kIHJlcy5zdGF0dXMgPCA1MDAgdGhlbgogICAgICAgICAgICAtLSBPcGVuc2hpcCBoYW5kbGVkIGl0ICgyeHggb3IgNHh4KQogICAgICAgICAgICByZXR1cm4ganNvbl9yZXNwb25zZSh7IG9rID0gdHJ1ZSwgcHJveGllZCA9IHRydWUsIHN0YXR1cyA9IHJlcy5zdGF0dXMgfSkKICAgICAgICBlbmQKCiAgICAgICAgLS0gT3BlbnNoaXAgdW5yZWFjaGFibGUgb3IgZXJyb3JlZCAtIGZhbGwgdGhyb3VnaCB0byBzdG9yZQogICAgZW5kCgogICAgLS0gU3RvcmUgZm9yIGxhdGVyIHBvbGxpbmcgYnkgbG9jYWwvZGVza3RvcCBhcHAKICAgIGxvY2FsIGV2ZW50X2lkID0gbmd4Lm5vdygpIC4uICI6IiAuLiBtYXRoLnJhbmRvbSgxMDAwMDAsIDk5OTk5OSkKICAgIGxvY2FsIGV2ZW50ID0gY2pzb24uZW5jb2RlKHsKICAgICAgICBpZCAgICAgICA9IGV2ZW50X2lkLAogICAgICAgIGhvb2tfaWQgID0gbmd4LnJlcS5nZXRfaGVhZGVycygpWyJ4LWhvb2staWQiXSBvciAiIiwKICAgICAgICBwYXlsb2FkICA9IGJvZHksCiAgICAgICAgcmVjZWl2ZWQgPSBuZ3gubm93KCksCiAgICB9KQoKICAgIC0tIFVzZSBhIHNsb3QtYmFzZWQgcmluZyBidWZmZXIgKG1heCAyMDAgZXZlbnRzKQogICAgbG9jYWwgbWF4X2V2ZW50cyA9IDIwMAogICAgbG9jYWwgaWR4ID0gd2ViaG9va19ldmVudHM6aW5jcigiX2lkeCIsIDEsIDApIG9yIDAKICAgIGxvY2FsIHNsb3QgPSAoaWR4ICUgbWF4X2V2ZW50cykKICAgIHdlYmhvb2tfZXZlbnRzOnNldCgiZXZ0OiIgLi4gc2xvdCwgZXZlbnQsIDM2MDApIC0tIDFoIFRUTAogICAgd2ViaG9va19ldmVudHM6c2V0KCJfY291bnQiLCBtYXRoLm1pbihpZHgsIG1heF9ldmVudHMpKQoKICAgIHJldHVybiBqc29uX3Jlc3BvbnNlKHsgb2sgPSB0cnVlLCBzdG9yZWQgPSB0cnVlLCBldmVudF9pZCA9IGV2ZW50X2lkIH0pCmVuZAoKLS0g4pSA4pSAIEdFVCAvX2hvb2tzL3BlbmRpbmcg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tIFJldHVybnMgc3RvcmVkIHdlYmhvb2sgZXZlbnRzIGZvciBsb2NhbCBhcHAgdG8gY29uc3VtZS4KCmlmIHVyaSA9PSAiL19ob29rcy9wZW5kaW5nIiBhbmQgbWV0aG9kID09ICJHRVQiIHRoZW4KICAgIGlmIG5vdCB3ZWJob29rX2V2ZW50cyB0aGVuCiAgICAgICAgcmV0dXJuIGpzb25fcmVzcG9uc2UoeyBldmVudHMgPSB7fSB9KQogICAgZW5kCgogICAgbG9jYWwgY291bnQgPSB3ZWJob29rX2V2ZW50czpnZXQoIl9jb3VudCIpIG9yIDAKICAgIGxvY2FsIGlkeCAgID0gd2ViaG9va19ldmVudHM6Z2V0KCJfaWR4Iikgb3IgMAogICAgbG9jYWwgZXZlbnRzID0ge30KCiAgICAtLSBSZWFkIGFsbCBzdG9yZWQgZXZlbnRzIChuZXdlc3QgZmlyc3QpCiAgICBsb2NhbCBtYXhfZXZlbnRzID0gMjAwCiAgICBsb2NhbCBzdGFydCA9IG1hdGgubWF4KDAsIGlkeCAtIGNvdW50KQogICAgZm9yIGkgPSBzdGFydCwgaWR4IC0gMSBkbwogICAgICAgIGxvY2FsIHNsb3QgPSBpICUgbWF4X2V2ZW50cwogICAgICAgIGxvY2FsIHJhdyA9IHdlYmhvb2tfZXZlbnRzOmdldCgiZXZ0OiIgLi4gc2xvdCkKICAgICAgICBpZiByYXcgdGhlbgogICAgICAgICAgICBsb2NhbCBwYXJzZWQgPSBjanNvbi5kZWNvZGUocmF3KQogICAgICAgICAgICBpZiBwYXJzZWQgdGhlbgogICAgICAgICAgICAgICAgZXZlbnRzWyNldmVudHMgKyAxXSA9IHBhcnNlZAogICAgICAgICAgICBlbmQKICAgICAgICBlbmQKICAgIGVuZAoKICAgIHJldHVybiBqc29uX3Jlc3BvbnNlKHsgZXZlbnRzID0gZXZlbnRzIH0pCmVuZAoKLS0g4pSA4pSAIFBPU1QgL19ob29rcy9hY2sg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tIEFja25vd2xlZGdlIGV2ZW50cyBoYXZlIGJlZW4gY29uc3VtZWQgLSBjbGVhcnMgdGhlIHN0b3JlLgoKaWYgdXJpID09ICIvX2hvb2tzL2FjayIgYW5kIG1ldGhvZCA9PSAiUE9TVCIgdGhlbgogICAgaWYgd2ViaG9va19ldmVudHMgdGhlbgogICAgICAgIHdlYmhvb2tfZXZlbnRzOmZsdXNoX2FsbCgpCiAgICAgICAgd2ViaG9va19ldmVudHM6Zmx1c2hfZXhwaXJlZCgpCiAgICBlbmQKICAgIHJldHVybiBqc29uX3Jlc3BvbnNlKHsgb2sgPSB0cnVlIH0pCmVuZAoKLS0g4pSA4pSAIEZhbGxiYWNrIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgApyZXR1cm4ganNvbl9yZXNwb25zZSh7IGVycm9yID0gIm5vdCBmb3VuZCIgfSwgNDA0KQo="
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// ../../packages/adapters/src/infra/cloudflare-ips.generated.ts
|
|
32
|
+
var CLOUDFLARE_IPV4 = [
|
|
33
|
+
"173.245.48.0/20",
|
|
34
|
+
"103.21.244.0/22",
|
|
35
|
+
"103.22.200.0/22",
|
|
36
|
+
"103.31.4.0/22",
|
|
37
|
+
"141.101.64.0/18",
|
|
38
|
+
"108.162.192.0/18",
|
|
39
|
+
"190.93.240.0/20",
|
|
40
|
+
"188.114.96.0/20",
|
|
41
|
+
"197.234.240.0/22",
|
|
42
|
+
"198.41.128.0/17",
|
|
43
|
+
"162.158.0.0/15",
|
|
44
|
+
"104.16.0.0/13",
|
|
45
|
+
"104.24.0.0/14",
|
|
46
|
+
"172.64.0.0/13",
|
|
47
|
+
"131.0.72.0/22"
|
|
48
|
+
];
|
|
49
|
+
var CLOUDFLARE_IPV6 = [
|
|
50
|
+
"2400:cb00::/32",
|
|
51
|
+
"2606:4700::/32",
|
|
52
|
+
"2803:f800::/32",
|
|
53
|
+
"2405:b500::/32",
|
|
54
|
+
"2405:8100::/32",
|
|
55
|
+
"2a06:98c0::/29",
|
|
56
|
+
"2c0f:f248::/32"
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
// ../../packages/adapters/src/infra/edge-real-ip.ts
|
|
60
|
+
var EDGE_REAL_IP_CONF_NAME = "openship-real-ip.conf";
|
|
61
|
+
function edgeRealIpHeader() {
|
|
62
|
+
const raw = process.env.OPENSHIP_EDGE_REAL_IP_HEADER?.trim();
|
|
63
|
+
if (raw && /^[A-Za-z0-9-]{1,64}$/.test(raw)) return raw;
|
|
64
|
+
return "CF-Connecting-IP";
|
|
65
|
+
}
|
|
66
|
+
function edgeTrustedProxies() {
|
|
67
|
+
const raw = process.env.OPENSHIP_EDGE_TRUSTED_PROXIES?.trim();
|
|
68
|
+
if (!raw) return [];
|
|
69
|
+
const CIDR = /^(?:(?:\d{1,3}\.){3}\d{1,3}|[0-9a-fA-F:]+)(?:\/\d{1,3})?$/;
|
|
70
|
+
return raw.split(/[,\s]+/).map((s) => s.trim()).filter((s) => s.length > 0 && s.length <= 64 && CIDR.test(s));
|
|
71
|
+
}
|
|
72
|
+
function edgeRealIpConf() {
|
|
73
|
+
const header = edgeRealIpHeader();
|
|
74
|
+
const extra = edgeTrustedProxies();
|
|
75
|
+
const lines = [
|
|
76
|
+
"# Openship \u2014 recover the real client address from a trusted front proxy.",
|
|
77
|
+
"#",
|
|
78
|
+
"# GENERATED. Source: packages/adapters/src/infra/edge-real-ip.ts",
|
|
79
|
+
"#",
|
|
80
|
+
"# Without this, remote_addr is the PROXY on any box behind Cloudflare or a load",
|
|
81
|
+
"# balancer, which silently breaks four things at once: visitor country resolves to",
|
|
82
|
+
"# the PoP, distinct-visitor counts collapse toward the number of PoPs, per-IP rate",
|
|
83
|
+
"# limits put the whole planet behind one PoP in a single bucket, and IP bans ban a",
|
|
84
|
+
"# PoP instead of a visitor.",
|
|
85
|
+
"#",
|
|
86
|
+
"# set_real_ip_from does NOT mean 'trust this header'. It means 'trust this header",
|
|
87
|
+
"# only when the TCP peer is one of these addresses'. Someone hitting the origin",
|
|
88
|
+
"# directly with a forged header is not connecting FROM Cloudflare, so the header is",
|
|
89
|
+
"# ignored and their real address stands. The trust is anchored to who opened the",
|
|
90
|
+
`# socket, which a client cannot forge.`,
|
|
91
|
+
"#",
|
|
92
|
+
`# The header is ${header}.`,
|
|
93
|
+
...header.toLowerCase() === "cf-connecting-ip" ? [
|
|
94
|
+
"# Cloudflare OVERWRITES CF-Connecting-IP, so its value holds nothing the client",
|
|
95
|
+
"# supplied. It deliberately is NOT X-Forwarded-For: Cloudflare APPENDS to that",
|
|
96
|
+
"# one, so XFF arrives as '<client-controlled>, <real client>' and reading it",
|
|
97
|
+
"# left-to-right would let a visitor choose their own apparent address \u2014 and",
|
|
98
|
+
"# with it their rate-limit bucket and which ban rules miss them."
|
|
99
|
+
] : [
|
|
100
|
+
"# NOT the default (CF-Connecting-IP) \u2014 set via OPENSHIP_EDGE_REAL_IP_HEADER.",
|
|
101
|
+
"# If this is X-Forwarded-For, note that proxies APPEND to it, so the header is",
|
|
102
|
+
"# partly client-controlled; real_ip_recursive below is what makes nginx walk it",
|
|
103
|
+
"# from the right and stop at the last untrusted hop, which is the real client."
|
|
104
|
+
],
|
|
105
|
+
"",
|
|
106
|
+
`real_ip_header ${header};`,
|
|
107
|
+
"",
|
|
108
|
+
"# Walk a multi-hop header from the RIGHT, skipping trusted addresses. Inert for a",
|
|
109
|
+
"# single-value header like CF-Connecting-IP; load-bearing for X-Forwarded-For, where",
|
|
110
|
+
"# the left-hand entries are whatever the client sent.",
|
|
111
|
+
"real_ip_recursive on;",
|
|
112
|
+
"",
|
|
113
|
+
`# Cloudflare's published edge ranges (${CLOUDFLARE_IPV4.length} v4 + ${CLOUDFLARE_IPV6.length} v6).`,
|
|
114
|
+
"# Trusted unconditionally, which is safe by construction: on a box that is not behind",
|
|
115
|
+
"# Cloudflare no peer ever matches, so every line here is inert. Refresh with",
|
|
116
|
+
"# `bun run update:cloudflare-ips`.",
|
|
117
|
+
...CLOUDFLARE_IPV4.map((c) => `set_real_ip_from ${c};`),
|
|
118
|
+
...CLOUDFLARE_IPV6.map((c) => `set_real_ip_from ${c};`)
|
|
119
|
+
];
|
|
120
|
+
if (extra.length > 0) {
|
|
121
|
+
lines.push(
|
|
122
|
+
"",
|
|
123
|
+
"# Operator-declared proxies (OPENSHIP_EDGE_TRUSTED_PROXIES). Each of these can set",
|
|
124
|
+
"# the header above and be believed, so keep the list to hosts you control.",
|
|
125
|
+
...extra.map((c) => `set_real_ip_from ${c};`)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return lines.join("\n") + "\n";
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ../../packages/adapters/src/infra/edge-not-found.ts
|
|
132
|
+
var EDGE_UNROUTED_SENTINEL = "openship-edge-unrouted";
|
|
133
|
+
var HTML_FRAGMENTS = [
|
|
134
|
+
`<!doctype html>`,
|
|
135
|
+
`<!--${EDGE_UNROUTED_SENTINEL}-->`,
|
|
136
|
+
`<html lang="en">`,
|
|
137
|
+
`<head>`,
|
|
138
|
+
`<meta charset="utf-8">`,
|
|
139
|
+
`<meta name="viewport" content="width=device-width,initial-scale=1">`,
|
|
140
|
+
// An unrouted host must never enter a search index under our page.
|
|
141
|
+
`<meta name="robots" content="noindex,nofollow">`,
|
|
142
|
+
`<title>Service not found</title>`,
|
|
143
|
+
`<style>`,
|
|
144
|
+
// Matches the dashboard's theme: a neutral black-on-white scale, mirrored for
|
|
145
|
+
// dark. No webfont, no image, no external request — the page must render on a
|
|
146
|
+
// box whose only working listener is the one serving it. Colours are `rgb()`,
|
|
147
|
+
// never `#rrggbb`: see the no-`#` invariant in the header.
|
|
148
|
+
`:root{color-scheme:light dark}`,
|
|
149
|
+
`*{box-sizing:border-box}`,
|
|
150
|
+
`body{margin:0;min-height:100vh;display:flex;align-items:center;justify-content:center;background:rgb(255,255,255);color:rgba(0,0,0,.66);font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased}`,
|
|
151
|
+
`main{width:100%;max-width:32rem;padding:2.5rem 1.5rem;text-align:center}`,
|
|
152
|
+
// The muted scale is .56, not the .4–.52 it started at: black at .52 on white is
|
|
153
|
+
// 4.3:1 and at .4 is 2.9:1, both under WCAG AA's 4.5:1 for text this small, and
|
|
154
|
+
// this is the most-seen page the edge serves. .56 ≈ 4.75:1.
|
|
155
|
+
`.tag{display:inline-flex;align-items:center;gap:.5rem;margin-bottom:1.25rem;padding:.25rem .625rem;border:1px solid rgba(0,0,0,.1);border-radius:999px;font-size:12px;color:rgba(0,0,0,.56)}`,
|
|
156
|
+
`.dot{width:6px;height:6px;border-radius:50%;background:rgb(224,169,10)}`,
|
|
157
|
+
`h1{margin:0 0 .5rem;font-size:1.375rem;font-weight:600;letter-spacing:-.01em;color:rgba(0,0,0,.92)}`,
|
|
158
|
+
`p{margin:0 auto 1.5rem;max-width:26rem}`,
|
|
159
|
+
`ul{display:inline-block;margin:0;padding:0;list-style:none;text-align:left;font-size:13.5px;color:rgba(0,0,0,.56)}`,
|
|
160
|
+
`li{position:relative;padding:.2rem 0 .2rem 1rem}`,
|
|
161
|
+
`li::before{content:"";position:absolute;left:0;top:.75em;width:4px;height:4px;border-radius:50%;background:rgba(0,0,0,.25)}`,
|
|
162
|
+
`footer{margin-top:2.25rem;font-size:12px;color:rgba(0,0,0,.56)}`,
|
|
163
|
+
`@media(prefers-color-scheme:dark){`,
|
|
164
|
+
`body{background:rgb(10,10,10);color:rgba(255,255,255,.66)}`,
|
|
165
|
+
`.tag{border-color:rgba(255,255,255,.12);color:rgba(255,255,255,.56)}`,
|
|
166
|
+
`h1{color:rgba(255,255,255,.95)}`,
|
|
167
|
+
`ul{color:rgba(255,255,255,.56)}`,
|
|
168
|
+
`li::before{background:rgba(255,255,255,.28)}`,
|
|
169
|
+
`footer{color:rgba(255,255,255,.56)}`,
|
|
170
|
+
`}`,
|
|
171
|
+
`</style>`,
|
|
172
|
+
`</head>`,
|
|
173
|
+
`<body>`,
|
|
174
|
+
`<main>`,
|
|
175
|
+
`<span class="tag"><span class="dot"></span>404 · no route</span>`,
|
|
176
|
+
`<h1>Service not found</h1>`,
|
|
177
|
+
// "reachable, but nothing is configured" is the whole message: it separates a
|
|
178
|
+
// down app from an address that was never wired up, which is the distinction a
|
|
179
|
+
// raw TLS error or a stock 404 destroys.
|
|
180
|
+
`<p>This server is reachable, but no application is configured for the address you requested.</p>`,
|
|
181
|
+
`<ul>`,
|
|
182
|
+
`<li>Check the address for a typo</li>`,
|
|
183
|
+
`<li>The deployment may have been removed or renamed</li>`,
|
|
184
|
+
`<li>A newly added domain can take a few minutes to start serving</li>`,
|
|
185
|
+
`</ul>`,
|
|
186
|
+
`<footer>Served by Openship</footer>`,
|
|
187
|
+
`</main>`,
|
|
188
|
+
`</body>`,
|
|
189
|
+
`</html>`
|
|
190
|
+
];
|
|
191
|
+
var EDGE_NOT_FOUND_HTML = HTML_FRAGMENTS.join("");
|
|
192
|
+
var EDGE_NOT_FOUND_LOCATION = ` server_tokens off;
|
|
193
|
+
|
|
194
|
+
location / {
|
|
195
|
+
types { }
|
|
196
|
+
default_type text/html;
|
|
197
|
+
return 404 '${EDGE_NOT_FOUND_HTML}';
|
|
198
|
+
}`;
|
|
199
|
+
|
|
200
|
+
// ../../packages/adapters/src/infra/openresty-lua.ts
|
|
201
|
+
var OPENRESTY_LUA_DIR = "/usr/local/openresty/site/lualib/openship";
|
|
202
|
+
var LUA_LOGGER_PATH = `${OPENRESTY_LUA_DIR}/site_logger.lua`;
|
|
203
|
+
var RULES_GUARD_PATH = `${OPENRESTY_LUA_DIR}/rules_guard.lua`;
|
|
204
|
+
var OPENRESTY_MGMT_PORT = 9145;
|
|
205
|
+
var OPENRESTY_SITE_LUALIB = OPENRESTY_LUA_DIR.replace(/\/[^/]+$/, "");
|
|
206
|
+
var EDGE_LUA_PACKAGE_PATH = `${OPENRESTY_SITE_LUALIB}/?.lua;;`;
|
|
207
|
+
var EDGE_SERVER_NAMES_HASH_BUCKET_SIZE = 128;
|
|
208
|
+
var EDGE_SHARED_DICTS = [
|
|
209
|
+
/** Analytics counters. */
|
|
210
|
+
{ name: "analytics", size: "256m" },
|
|
211
|
+
/** Raw-log ring buffers + the live-log pipe. */
|
|
212
|
+
{ name: "request_data", size: "128m" },
|
|
213
|
+
/** Per-route rules cache: written reload-free by mgmt_api `POST /rules`, read
|
|
214
|
+
* by rules_guard.lua in the access phase. The DB (route_rule) is the source
|
|
215
|
+
* of truth, so losing this dict costs a re-push, not a ruleset. */
|
|
216
|
+
{ name: "rules", size: "32m" },
|
|
217
|
+
/** Rate-limit COUNTERS, kept apart from `rules` so a high-cardinality flood (a
|
|
218
|
+
* fresh key per source IP per second) can't LRU-evict the rulesets and
|
|
219
|
+
* silently disable enforcement mid-attack.
|
|
220
|
+
*
|
|
221
|
+
* 32m, matching openresty module migration 1.1.0, which raises it from the
|
|
222
|
+
* original 16m on boxes already installed. Both must state the same target: a
|
|
223
|
+
* fresh install writes THIS value, so leaving it at 16m meant a new box got the
|
|
224
|
+
* size the migration exists to correct — and only bare boxes that consented to
|
|
225
|
+
* the migration would ever reach 32m. The migration stays because the
|
|
226
|
+
* `grep || sed` convergence below is append-only and cannot resize an existing
|
|
227
|
+
* directive; `edge-shared-dicts.test.ts` pins the two together. */
|
|
228
|
+
{ name: "rl_counters", size: "32m" },
|
|
229
|
+
/**
|
|
230
|
+
* Distinct-visitor sets. One key per (domain, day, salted-IP hash) — high
|
|
231
|
+
* cardinality and short-lived, so it gets its own zone for the same reason
|
|
232
|
+
* `rl_counters` does: a busy day's visitor set must not LRU-evict the analytics
|
|
233
|
+
* counters or the rulesets.
|
|
234
|
+
*
|
|
235
|
+
* Privacy: keys hold a per-day-salted hash, never an address, and only the
|
|
236
|
+
* resulting COUNT is ever flushed to Postgres. Nothing that identifies a visitor
|
|
237
|
+
* leaves the box — see the visitor block in site_logger.lua.
|
|
238
|
+
*
|
|
239
|
+
* 64m ≈ 1M distinct visitors/day. Past that the zone LRU-evicts and the count
|
|
240
|
+
* UNDERSTATES; `GET /status` reports free_space so a reader can mark it
|
|
241
|
+
* approximate rather than present an eviction artifact as a measurement.
|
|
242
|
+
*/
|
|
243
|
+
{ name: "visitors", size: "64m" }
|
|
244
|
+
];
|
|
245
|
+
function parseNginxVersion(raw) {
|
|
246
|
+
const m = raw.match(/nginx version:\s*\S*?\/(\d+)\.(\d+)\.(\d+)/i);
|
|
247
|
+
if (!m) return void 0;
|
|
248
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
249
|
+
}
|
|
250
|
+
var OPENRESTY_DEFAULT_PATHS = {
|
|
251
|
+
bin: "/usr/local/openresty/bin/openresty",
|
|
252
|
+
confPath: "/usr/local/openresty/nginx/conf/nginx.conf",
|
|
253
|
+
confDir: "/usr/local/openresty/nginx/conf",
|
|
254
|
+
sitesDir: "/usr/local/openresty/nginx/conf/sites-enabled",
|
|
255
|
+
pidPath: "/usr/local/openresty/nginx/logs/nginx.pid"
|
|
256
|
+
};
|
|
257
|
+
var EDGE_DEFAULT_CERT_DIRNAME = "openship-default-cert";
|
|
258
|
+
function edgeDefaultCertPaths(confDir) {
|
|
259
|
+
const dir = `${confDir}/${EDGE_DEFAULT_CERT_DIRNAME}`;
|
|
260
|
+
return { dir, certPath: `${dir}/fullchain.pem`, keyPath: `${dir}/privkey.pem` };
|
|
261
|
+
}
|
|
262
|
+
var EDGE_DEFAULT_CERT_CN = "openship-edge-default";
|
|
263
|
+
var EDGE_HOST_STATE_DIR = "/var/lib/openship/edge";
|
|
264
|
+
var EDGE_CONTAINER_MOUNTS = [
|
|
265
|
+
{ host: `${EDGE_HOST_STATE_DIR}/sites-enabled`, container: OPENRESTY_DEFAULT_PATHS.sitesDir },
|
|
266
|
+
{ host: "/etc/letsencrypt", container: "/etc/letsencrypt" },
|
|
267
|
+
{ host: `${EDGE_HOST_STATE_DIR}/acme`, container: "/var/www/acme" },
|
|
268
|
+
{ host: "/opt/openship/static", container: "/opt/openship/static" }
|
|
269
|
+
];
|
|
270
|
+
var EDGE_HOST_PATHS = {
|
|
271
|
+
bin: OPENRESTY_DEFAULT_PATHS.bin,
|
|
272
|
+
confPath: OPENRESTY_DEFAULT_PATHS.confPath,
|
|
273
|
+
confDir: OPENRESTY_DEFAULT_PATHS.confDir,
|
|
274
|
+
sitesDir: `${EDGE_HOST_STATE_DIR}/sites-enabled`,
|
|
275
|
+
pidPath: OPENRESTY_DEFAULT_PATHS.pidPath
|
|
276
|
+
};
|
|
277
|
+
var KNOWN_CONF_PATHS = [
|
|
278
|
+
"/usr/local/openresty/nginx/conf/nginx.conf",
|
|
279
|
+
"/etc/openresty/nginx.conf",
|
|
280
|
+
"/etc/nginx/nginx.conf"
|
|
281
|
+
];
|
|
282
|
+
async function detectOpenRestyPaths(executor) {
|
|
283
|
+
const raw = await executor.exec("openresty -V 2>&1 || true");
|
|
284
|
+
const parseFlag = (flag) => {
|
|
285
|
+
const m = raw.match(new RegExp(`--${flag}=([^\\s]+)`));
|
|
286
|
+
return m ? m[1] : null;
|
|
287
|
+
};
|
|
288
|
+
const bin = parseFlag("sbin-path") ?? OPENRESTY_DEFAULT_PATHS.bin;
|
|
289
|
+
let confPath = parseFlag("conf-path") ?? OPENRESTY_DEFAULT_PATHS.confPath;
|
|
290
|
+
const pidPath = parseFlag("pid-path") ?? OPENRESTY_DEFAULT_PATHS.pidPath;
|
|
291
|
+
if (!await executor.exists(confPath)) {
|
|
292
|
+
let found = false;
|
|
293
|
+
for (const candidate of KNOWN_CONF_PATHS) {
|
|
294
|
+
if (candidate !== confPath && await executor.exists(candidate)) {
|
|
295
|
+
confPath = candidate;
|
|
296
|
+
found = true;
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (!found) {
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const confDir = confPath.replace(/\/[^/]+$/, "");
|
|
304
|
+
const nginxVersion = parseNginxVersion(raw);
|
|
305
|
+
return {
|
|
306
|
+
bin,
|
|
307
|
+
confPath,
|
|
308
|
+
confDir,
|
|
309
|
+
sitesDir: `${confDir}/sites-enabled`,
|
|
310
|
+
pidPath,
|
|
311
|
+
...nginxVersion ? { nginxVersion } : {}
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
function buildReloadCommand(paths, opts = {}) {
|
|
315
|
+
if (opts.containerEdge) {
|
|
316
|
+
return `${paths.bin} -t 2>&1 || exit 1
|
|
317
|
+
${paths.bin} -s reload 2>&1 || exit 1`;
|
|
318
|
+
}
|
|
319
|
+
return `${paths.bin} -t 2>&1 || exit 1
|
|
320
|
+
|
|
321
|
+
reload_err=$(${paths.bin} -s reload 2>&1) && exit 0
|
|
322
|
+
|
|
323
|
+
if [ "$(cat /proc/1/comm 2>/dev/null)" = "openresty" ] || [ "$(cat /proc/1/comm 2>/dev/null)" = "nginx" ]; then
|
|
324
|
+
echo "openresty reload failed and openresty is PID 1 (containerized edge) \u2014 not killing it; the container supervisor owns restarts." >&2
|
|
325
|
+
echo "$reload_err" >&2
|
|
326
|
+
exit 1
|
|
327
|
+
fi
|
|
328
|
+
|
|
329
|
+
if [ -f ${paths.pidPath} ] && kill -0 "$(cat ${paths.pidPath} 2>/dev/null)" 2>/dev/null; then
|
|
330
|
+
echo "openresty (pid $(cat ${paths.pidPath})) is running but refused -s reload" >&2
|
|
331
|
+
exit 1
|
|
332
|
+
fi
|
|
333
|
+
|
|
334
|
+
rm -f ${paths.pidPath}
|
|
335
|
+
${paths.bin}`;
|
|
336
|
+
}
|
|
337
|
+
async function ensureEdgeDefaultCert(executor, confDir) {
|
|
338
|
+
const { dir, certPath, keyPath } = edgeDefaultCertPaths(confDir);
|
|
339
|
+
try {
|
|
340
|
+
if (await executor.exists(certPath) && await executor.exists(keyPath)) {
|
|
341
|
+
return { certPath, keyPath };
|
|
342
|
+
}
|
|
343
|
+
} catch {
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
const staging = `${dir}.staging-${process.pid}-${randomBytes(4).toString("hex")}`;
|
|
347
|
+
try {
|
|
348
|
+
await executor.mkdir(staging);
|
|
349
|
+
await executor.exec(
|
|
350
|
+
`openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -days 3650 -subj ${sq(`/CN=${EDGE_DEFAULT_CERT_CN}`)} -keyout ${sq(`${staging}/privkey.pem`)} -out ${sq(`${staging}/fullchain.pem`)} 2>/dev/null`
|
|
351
|
+
);
|
|
352
|
+
await executor.exec(`chmod 600 ${sq(`${staging}/privkey.pem`)}`);
|
|
353
|
+
await executor.mkdir(dir);
|
|
354
|
+
await executor.exec(
|
|
355
|
+
`mv -f ${sq(`${staging}/fullchain.pem`)} ${sq(`${staging}/privkey.pem`)} ${sq(dir)}/`
|
|
356
|
+
);
|
|
357
|
+
if (!await executor.exists(certPath) || !await executor.exists(keyPath)) return null;
|
|
358
|
+
return { certPath, keyPath };
|
|
359
|
+
} catch (err) {
|
|
360
|
+
console.warn(
|
|
361
|
+
`[openresty] could not create the edge's default certificate \u2014 an unrouted HTTPS host will get a TLS error instead of the "service not found" page (is openssl installed?): ${safeErrorMessage(err)}`
|
|
362
|
+
);
|
|
363
|
+
return null;
|
|
364
|
+
} finally {
|
|
365
|
+
await executor.rm(staging).catch(() => void 0);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
async function ensureOpenRestyConfig(executor, paths) {
|
|
369
|
+
await executor.mkdir(paths.sitesDir);
|
|
370
|
+
await executor.mkdir("/var/www/acme");
|
|
371
|
+
const pidDir = paths.pidPath.replace(/\/[^/]+$/, "");
|
|
372
|
+
await executor.mkdir(pidDir);
|
|
373
|
+
const defaultCert = await ensureEdgeDefaultCert(executor, paths.confDir);
|
|
374
|
+
await executor.writeFile(`${paths.sitesDir}/_management.conf`, MANAGEMENT_BLOCK);
|
|
375
|
+
await executor.writeFile(`${paths.sitesDir}/_default.conf`, edgeDefaultCatchAllConf(defaultCert));
|
|
376
|
+
if (!await executor.exists(paths.confPath)) {
|
|
377
|
+
await executor.mkdir(paths.confDir);
|
|
378
|
+
await executor.writeFile(
|
|
379
|
+
paths.confPath,
|
|
380
|
+
MINIMAL_NGINX_CONF(paths.confDir, paths.sitesDir)
|
|
381
|
+
);
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
const hasCorrectInclude = await executor.exec(`grep -qF 'include ${paths.sitesDir}/' ${paths.confPath}`).then(() => true).catch(() => false);
|
|
385
|
+
if (!hasCorrectInclude) {
|
|
386
|
+
const hasWrongInclude = await executor.exec(`grep -q 'include.*sites-enabled' ${paths.confPath}`).then(() => true).catch(() => false);
|
|
387
|
+
if (hasWrongInclude) {
|
|
388
|
+
await executor.exec(
|
|
389
|
+
`sed -i 's|include.*/sites-enabled/\\*\\.conf;|include ${paths.sitesDir}/*.conf;|' ${paths.confPath}`
|
|
390
|
+
);
|
|
391
|
+
} else {
|
|
392
|
+
await executor.exec(
|
|
393
|
+
`sed -i '/http *{/a \\ include ${paths.sitesDir}/*.conf;' ${paths.confPath}`
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
function MINIMAL_NGINX_CONF(confDir, sitesDir) {
|
|
399
|
+
return `# Auto-generated by Openship - safe to extend
|
|
400
|
+
worker_processes auto;
|
|
401
|
+
events {
|
|
402
|
+
worker_connections 1024;
|
|
403
|
+
}
|
|
404
|
+
http {
|
|
405
|
+
include ${confDir}/mime.types;
|
|
406
|
+
default_type application/octet-stream;
|
|
407
|
+
sendfile on;
|
|
408
|
+
keepalive_timeout 65;
|
|
409
|
+
# See EDGE_SERVER_NAMES_HASH_BUCKET_SIZE \u2014 the 64-byte default fails
|
|
410
|
+
# \`nginx -t\` outright for any server_name past ~63 chars, refusing the reload
|
|
411
|
+
# and wedging every route on the box, not just the long one.
|
|
412
|
+
server_names_hash_bucket_size ${EDGE_SERVER_NAMES_HASH_BUCKET_SIZE};
|
|
413
|
+
include ${sitesDir}/*.conf;
|
|
414
|
+
}
|
|
415
|
+
`;
|
|
416
|
+
}
|
|
417
|
+
var GEOIP_DIR = "/usr/share/GeoIP";
|
|
418
|
+
var GEOIP_DB_PATH = `${GEOIP_DIR}/GeoLite2-Country.mmdb`;
|
|
419
|
+
var GEOIP_DB_URL = process.env.OPENSHIP_GEOIP_URL?.trim() || "https://raw.githubusercontent.com/oblien/openship/main/apps/api/assets/geoip/GeoLite2-Country.mmdb";
|
|
420
|
+
var LUA_SRC_DIR = process.env.OPENSHIP_LUA_DIR?.trim() || join(dirname(fileURLToPath(import.meta.url)), "lua");
|
|
421
|
+
var VHOST_REFERENCED_LUA = ["rules_guard.lua", "rules_lib.lua", "site_logger.lua"];
|
|
422
|
+
function luaSourceAvailable() {
|
|
423
|
+
return VHOST_REFERENCED_LUA.every(
|
|
424
|
+
(f) => EMBEDDED_LUA[f] !== void 0 || existsSync(join(LUA_SRC_DIR, f))
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
function readLua(filename) {
|
|
428
|
+
const onDisk = join(LUA_SRC_DIR, filename);
|
|
429
|
+
if (existsSync(onDisk)) return readFileSync(onDisk, "utf-8");
|
|
430
|
+
const embedded = EMBEDDED_LUA[filename];
|
|
431
|
+
if (embedded !== void 0) return Buffer.from(embedded, "base64").toString("utf-8");
|
|
432
|
+
throw new Error(
|
|
433
|
+
`Lua script "${filename}" not found on disk (${LUA_SRC_DIR}) or in EMBEDDED_LUA \u2014 add it to packages/adapters/src/infra/lua/ and run \`bun run embed:lua\`.`
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
var EDGE_MGMT_SERVER_BLOCK = `server {
|
|
437
|
+
listen 127.0.0.1:${OPENRESTY_MGMT_PORT};
|
|
438
|
+
|
|
439
|
+
# Long-running Lua content handlers need generous timeouts
|
|
440
|
+
send_timeout 3600s;
|
|
441
|
+
keepalive_timeout 3600s;
|
|
442
|
+
lua_check_client_abort on;
|
|
443
|
+
|
|
444
|
+
# SSE live-log stream (long-lived connection)
|
|
445
|
+
location = /logs/stream {
|
|
446
|
+
content_by_lua_file ${OPENRESTY_LUA_DIR}/pipe_stream.lua;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
# REST analytics + health (short-lived)
|
|
450
|
+
location / {
|
|
451
|
+
content_by_lua_file ${OPENRESTY_LUA_DIR}/mgmt_api.lua;
|
|
452
|
+
}
|
|
453
|
+
}`;
|
|
454
|
+
var MANAGEMENT_BLOCK = `# Openship internal management - analytics & live-log streaming
|
|
455
|
+
# Auto-generated - do not edit manually
|
|
456
|
+
${EDGE_MGMT_SERVER_BLOCK}
|
|
457
|
+
`;
|
|
458
|
+
var ACME_HTTP01_PORT = 49180;
|
|
459
|
+
var ACME_CHALLENGE_LOCATION = ` location /.well-known/acme-challenge/ {
|
|
460
|
+
proxy_pass http://127.0.0.1:${ACME_HTTP01_PORT};
|
|
461
|
+
proxy_set_header Host $host;
|
|
462
|
+
}`;
|
|
463
|
+
var EDGE_CHALLENGE_URL_PREFIX = "/.well-known/oblien-proxy-challenge/";
|
|
464
|
+
var EDGE_CHALLENGE_ROOT = "/var/www/acme/oblien";
|
|
465
|
+
var EDGE_CHALLENGE_DIR = `${EDGE_CHALLENGE_ROOT}${EDGE_CHALLENGE_URL_PREFIX}`.replace(/\/$/, "");
|
|
466
|
+
var EDGE_CHALLENGE_HOST_DIR = `${EDGE_HOST_STATE_DIR}/acme/oblien${EDGE_CHALLENGE_URL_PREFIX}`.replace(
|
|
467
|
+
/\/$/,
|
|
468
|
+
""
|
|
469
|
+
);
|
|
470
|
+
var EDGE_CHALLENGE_LOCATION = ` location ${EDGE_CHALLENGE_URL_PREFIX} {
|
|
471
|
+
root ${EDGE_CHALLENGE_ROOT};
|
|
472
|
+
default_type text/plain;
|
|
473
|
+
try_files $uri =404;
|
|
474
|
+
}`;
|
|
475
|
+
function edgeChallengeVhostConf(host) {
|
|
476
|
+
return `# Auto-generated by Openship - do not edit manually
|
|
477
|
+
# openship-oblien-challenge: answers ${EDGE_CHALLENGE_URL_PREFIX}<token> for
|
|
478
|
+
# Host: ${host}, so Openship Cloud's shared edge can prove this box controls that
|
|
479
|
+
# routing target. Everything else gets the shared not-found page - this is
|
|
480
|
+
# scaffolding, not a site.
|
|
481
|
+
server {
|
|
482
|
+
listen 80;
|
|
483
|
+
server_name ${host};
|
|
484
|
+
|
|
485
|
+
${EDGE_CHALLENGE_LOCATION}
|
|
486
|
+
|
|
487
|
+
${EDGE_NOT_FOUND_LOCATION}
|
|
488
|
+
}
|
|
489
|
+
`;
|
|
490
|
+
}
|
|
491
|
+
var EDGE_HTTPS_REJECT_BLOCK = `# HTTPS catch-all. WITHOUT a 443 default_server, nginx serves the first-loaded
|
|
492
|
+
# 443 vhost to any request whose SNI matches no server_name - so a domain we do
|
|
493
|
+
# NOT route (removed / never-added / just pointed at this IP) silently gets some
|
|
494
|
+
# other app's cert + backend. That is cross-serving, a security hole. Owning the
|
|
495
|
+
# 443 default closes it: an unrouted host is answered HERE, never by a fallthrough.
|
|
496
|
+
#
|
|
497
|
+
# This is the no-certificate variant, used only when the placeholder cert could not
|
|
498
|
+
# be created. It refuses the handshake, so the visitor gets a raw TLS error and a
|
|
499
|
+
# Cloudflare-proxied host gets error 525 - correct, but unfriendly. See
|
|
500
|
+
# edgeHttpsDefaultBlock. ssl_reject_handshake (OpenResty/nginx >= 1.19.4; our
|
|
501
|
+
# installer pulls the newest LTS) needs no certificate.
|
|
502
|
+
server {
|
|
503
|
+
listen 443 ssl default_server;
|
|
504
|
+
ssl_reject_handshake on;
|
|
505
|
+
}`;
|
|
506
|
+
function edgeHttpsDefaultBlock(cert) {
|
|
507
|
+
if (!cert) return EDGE_HTTPS_REJECT_BLOCK;
|
|
508
|
+
return `# HTTPS catch-all. WITHOUT a 443 default_server, nginx serves the first-loaded
|
|
509
|
+
# 443 vhost to any request whose SNI matches no server_name - so a domain we do
|
|
510
|
+
# NOT route (removed / never-added / just pointed at this IP) silently gets some
|
|
511
|
+
# other app's cert + backend. That is cross-serving, a security hole. Owning the
|
|
512
|
+
# 443 default closes it: an unrouted host is answered HERE, never by a fallthrough.
|
|
513
|
+
#
|
|
514
|
+
# The cert below belongs to no domain and is trusted by nothing - it exists so the
|
|
515
|
+
# handshake COMPLETES and the request can be answered with a page instead of
|
|
516
|
+
# ERR_SSL_UNRECOGNIZED_NAME_ALERT (Cloudflare "Full" reports the refusal as error
|
|
517
|
+
# 525; "Full (Strict)" validates the cert and will still show 526). Keep this block a
|
|
518
|
+
# dead end: no proxy_pass, no root, no HSTS, no reuse of a real certificate - that is
|
|
519
|
+
# what stops it from becoming the cross-serving it prevents. And never set
|
|
520
|
+
# ssl_certificate at http scope: this block would inherit a real domain's cert.
|
|
521
|
+
server {
|
|
522
|
+
listen 443 ssl default_server;
|
|
523
|
+
server_name _;
|
|
524
|
+
|
|
525
|
+
ssl_certificate ${cert.certPath};
|
|
526
|
+
ssl_certificate_key ${cert.keyPath};
|
|
527
|
+
|
|
528
|
+
${EDGE_NOT_FOUND_LOCATION}
|
|
529
|
+
}`;
|
|
530
|
+
}
|
|
531
|
+
function edgeDefaultCatchAllConf(cert) {
|
|
532
|
+
return `# Openship default catch-all - prevents the stock OpenResty welcome page AND
|
|
533
|
+
# stops an unmatched Host/SNI from being served the first real vhost by default.
|
|
534
|
+
# Auto-generated - do not edit manually
|
|
535
|
+
server {
|
|
536
|
+
listen 80 default_server;
|
|
537
|
+
server_name _;
|
|
538
|
+
|
|
539
|
+
${ACME_CHALLENGE_LOCATION}
|
|
540
|
+
|
|
541
|
+
${EDGE_NOT_FOUND_LOCATION}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
${edgeHttpsDefaultBlock(cert)}
|
|
545
|
+
`;
|
|
546
|
+
}
|
|
547
|
+
var LUA_SCRIPTS = [
|
|
548
|
+
"site_logger.lua",
|
|
549
|
+
"pipe_log.lua",
|
|
550
|
+
"pipe_stream.lua",
|
|
551
|
+
"mgmt_api.lua",
|
|
552
|
+
"geo_country.lua",
|
|
553
|
+
// Vendored FFI binding geo_country requires as `openship.maxminddb`. Ships with
|
|
554
|
+
// the rest so a bare box needs no `opm get` (which needs perl) — see the file
|
|
555
|
+
// header. Flat, like every other script: ensureLuaScripts writes this list into
|
|
556
|
+
// one directory and its presence scan is a plain `ls -1`.
|
|
557
|
+
"maxminddb.lua",
|
|
558
|
+
"rules_lib.lua",
|
|
559
|
+
"rules_guard.lua"
|
|
560
|
+
];
|
|
561
|
+
var LUA_VERSION_MARKER = `${OPENRESTY_LUA_DIR}/.openship-lua-version`;
|
|
562
|
+
function luaBundleHash() {
|
|
563
|
+
const h = createHash("sha256");
|
|
564
|
+
for (const name of LUA_SCRIPTS) {
|
|
565
|
+
h.update(name);
|
|
566
|
+
h.update("\0");
|
|
567
|
+
h.update(readLua(name));
|
|
568
|
+
h.update("\0");
|
|
569
|
+
}
|
|
570
|
+
return h.digest("hex");
|
|
571
|
+
}
|
|
572
|
+
async function ensureLuaScripts(executor, paths) {
|
|
573
|
+
try {
|
|
574
|
+
if (!luaSourceAvailable()) {
|
|
575
|
+
console.error(
|
|
576
|
+
"[openresty] Lua unavailable in this build (not on disk or embedded) \u2014 edge rules/logging disabled. Run `bun run embed:lua` in packages/adapters."
|
|
577
|
+
);
|
|
578
|
+
return { repaired: [], available: false };
|
|
579
|
+
}
|
|
580
|
+
const expected = luaBundleHash();
|
|
581
|
+
await executor.mkdir(OPENRESTY_LUA_DIR);
|
|
582
|
+
const listing = await executor.exec(`ls -1 '${OPENRESTY_LUA_DIR}' 2>/dev/null || true`).catch(() => "");
|
|
583
|
+
const present = new Set(listing.split("\n").map((s) => s.trim()).filter(Boolean));
|
|
584
|
+
const missing = LUA_SCRIPTS.filter((name) => !present.has(name));
|
|
585
|
+
const onBoxVersion = (await executor.readFile(LUA_VERSION_MARKER).catch(() => "")).trim();
|
|
586
|
+
if (missing.length === 0 && onBoxVersion === expected) {
|
|
587
|
+
return { repaired: [], available: true };
|
|
588
|
+
}
|
|
589
|
+
for (const name of LUA_SCRIPTS) {
|
|
590
|
+
await executor.writeFile(`${OPENRESTY_LUA_DIR}/${name}`, readLua(name));
|
|
591
|
+
}
|
|
592
|
+
await executor.writeFile(LUA_VERSION_MARKER, expected);
|
|
593
|
+
const reason = missing.length ? `missing: ${missing.join(", ")}` : "version changed";
|
|
594
|
+
console.warn(`[openresty] (re)installed Lua (${reason}) \u2014 reloading edge.`);
|
|
595
|
+
await executor.exec(buildReloadCommand(paths)).catch((err) => {
|
|
596
|
+
console.error(`[openresty] reload after Lua (re)install failed: ${safeErrorMessage(err)}`);
|
|
597
|
+
});
|
|
598
|
+
return { repaired: missing.length ? missing : [...LUA_SCRIPTS], available: true };
|
|
599
|
+
} catch (err) {
|
|
600
|
+
console.error(`[openresty] ensureLuaScripts failed (deploy continues): ${safeErrorMessage(err)}`);
|
|
601
|
+
return { repaired: [], available: false };
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
async function installGeoDeps(executor) {
|
|
605
|
+
try {
|
|
606
|
+
const hasPkg = async (cmd) => {
|
|
607
|
+
try {
|
|
608
|
+
await executor.exec(`command -v ${cmd}`);
|
|
609
|
+
return true;
|
|
610
|
+
} catch {
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
if (await hasPkg("apt-get")) {
|
|
615
|
+
await executor.exec(
|
|
616
|
+
"apt-get update -qq && apt-get install -y -qq libmaxminddb0 libmaxminddb-dev"
|
|
617
|
+
);
|
|
618
|
+
} else if (await hasPkg("dnf")) {
|
|
619
|
+
await executor.exec("dnf install -y libmaxminddb libmaxminddb-devel");
|
|
620
|
+
} else if (await hasPkg("yum")) {
|
|
621
|
+
await executor.exec("yum install -y libmaxminddb libmaxminddb-devel");
|
|
622
|
+
} else if (await hasPkg("apk")) {
|
|
623
|
+
await executor.exec("apk add --no-cache libmaxminddb");
|
|
624
|
+
}
|
|
625
|
+
} catch {
|
|
626
|
+
}
|
|
627
|
+
try {
|
|
628
|
+
const exists = await executor.exists(GEOIP_DB_PATH);
|
|
629
|
+
if (!exists) {
|
|
630
|
+
await executor.mkdir(GEOIP_DIR);
|
|
631
|
+
await executor.exec(
|
|
632
|
+
`curl -fsSL -o ${GEOIP_DB_PATH} "${GEOIP_DB_URL}"`
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
} catch {
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
async function deployLuaScripts(executor, paths) {
|
|
639
|
+
await installGeoDeps(executor);
|
|
640
|
+
if (!luaSourceAvailable()) {
|
|
641
|
+
throw new Error(
|
|
642
|
+
`OpenResty Lua is unavailable in this build \u2014 not on disk (LUA_SRC_DIR=${LUA_SRC_DIR}) and not in EMBEDDED_LUA. The edge scripts (rules_guard.lua/site_logger.lua) can't be installed. Run \`bun run embed:lua\` in packages/adapters to regenerate lua-embedded.ts.`
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
await executor.mkdir(OPENRESTY_LUA_DIR);
|
|
646
|
+
for (const name of LUA_SCRIPTS) {
|
|
647
|
+
await executor.writeFile(
|
|
648
|
+
`${OPENRESTY_LUA_DIR}/${name}`,
|
|
649
|
+
readLua(name)
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
await ensureOpenRestyConfig(executor, paths);
|
|
653
|
+
for (const dict of EDGE_SHARED_DICTS) {
|
|
654
|
+
await executor.exec(
|
|
655
|
+
`grep -q 'lua_shared_dict ${dict.name} ' ${paths.confPath} || sed -i '/http *{/a \\ lua_shared_dict ${dict.name} ${dict.size};' ${paths.confPath}`
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
await executor.exec(
|
|
659
|
+
`grep -q 'lua_package_path' ${paths.confPath} || sed -i '/http *{/a \\ lua_package_path "${EDGE_LUA_PACKAGE_PATH}";' ${paths.confPath}`
|
|
660
|
+
);
|
|
661
|
+
const realIpPath = `${paths.confDir}/${EDGE_REAL_IP_CONF_NAME}`;
|
|
662
|
+
await executor.writeFile(realIpPath, edgeRealIpConf());
|
|
663
|
+
await executor.exec(
|
|
664
|
+
`grep -q '${EDGE_REAL_IP_CONF_NAME}' '${paths.confPath}' || sed -i '/http *{/a \\ include ${realIpPath};' '${paths.confPath}'`
|
|
665
|
+
);
|
|
666
|
+
await executor.exec(buildReloadCommand(paths));
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
export {
|
|
670
|
+
OPENRESTY_LUA_DIR,
|
|
671
|
+
LUA_LOGGER_PATH,
|
|
672
|
+
RULES_GUARD_PATH,
|
|
673
|
+
OPENRESTY_MGMT_PORT,
|
|
674
|
+
EDGE_LUA_PACKAGE_PATH,
|
|
675
|
+
EDGE_SERVER_NAMES_HASH_BUCKET_SIZE,
|
|
676
|
+
EDGE_SHARED_DICTS,
|
|
677
|
+
parseNginxVersion,
|
|
678
|
+
OPENRESTY_DEFAULT_PATHS,
|
|
679
|
+
EDGE_DEFAULT_CERT_DIRNAME,
|
|
680
|
+
edgeDefaultCertPaths,
|
|
681
|
+
EDGE_DEFAULT_CERT_CN,
|
|
682
|
+
EDGE_HOST_STATE_DIR,
|
|
683
|
+
EDGE_CONTAINER_MOUNTS,
|
|
684
|
+
EDGE_HOST_PATHS,
|
|
685
|
+
detectOpenRestyPaths,
|
|
686
|
+
buildReloadCommand,
|
|
687
|
+
ensureOpenRestyConfig,
|
|
688
|
+
GEOIP_DIR,
|
|
689
|
+
GEOIP_DB_PATH,
|
|
690
|
+
luaSourceAvailable,
|
|
691
|
+
EDGE_MGMT_SERVER_BLOCK,
|
|
692
|
+
ACME_HTTP01_PORT,
|
|
693
|
+
ACME_CHALLENGE_LOCATION,
|
|
694
|
+
EDGE_CHALLENGE_URL_PREFIX,
|
|
695
|
+
EDGE_CHALLENGE_ROOT,
|
|
696
|
+
EDGE_CHALLENGE_DIR,
|
|
697
|
+
EDGE_CHALLENGE_HOST_DIR,
|
|
698
|
+
EDGE_CHALLENGE_LOCATION,
|
|
699
|
+
edgeChallengeVhostConf,
|
|
700
|
+
EDGE_HTTPS_REJECT_BLOCK,
|
|
701
|
+
edgeHttpsDefaultBlock,
|
|
702
|
+
edgeDefaultCatchAllConf,
|
|
703
|
+
ensureLuaScripts,
|
|
704
|
+
deployLuaScripts
|
|
705
|
+
};
|