@rakay-technology/kraft 0.7.4
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 +263 -0
- package/dist/bare-HL2GUYE2.js +27 -0
- package/dist/bowser-HNOTPGJO.js +2825 -0
- package/dist/chunk-3CJLKL6E.js +124 -0
- package/dist/chunk-3NQQXMDR.js +2098 -0
- package/dist/chunk-42WQABXM.js +439 -0
- package/dist/chunk-5GPXMTE4.js +25 -0
- package/dist/chunk-AJ4QZLZ2.js +1069 -0
- package/dist/chunk-AO252K7Z.js +137 -0
- package/dist/chunk-BQMFIXHI.js +975 -0
- package/dist/chunk-DM3PKWDC.js +2453 -0
- package/dist/chunk-DOD2BXHQ.js +1364 -0
- package/dist/chunk-DRK3MEDS.js +2870 -0
- package/dist/chunk-EW4PHKB2.js +13914 -0
- package/dist/chunk-HMJUFZK7.js +340 -0
- package/dist/chunk-I2TOOF2A.js +517 -0
- package/dist/chunk-I3DPMTSF.js +29 -0
- package/dist/chunk-JSCZT76F.js +2588 -0
- package/dist/chunk-MNV2QFHW.js +138 -0
- package/dist/chunk-MOLPYPVH.js +2529 -0
- package/dist/chunk-N4OALTFK.js +295 -0
- package/dist/chunk-OFXBNFNL.js +458 -0
- package/dist/chunk-ONKEYSMY.js +1388 -0
- package/dist/chunk-PDW4L3NV.js +17 -0
- package/dist/chunk-PNNXWA2A.js +1947 -0
- package/dist/chunk-PNRPKRJU.js +11105 -0
- package/dist/chunk-PVOWHIND.js +26781 -0
- package/dist/chunk-PXKCZB2I.js +46 -0
- package/dist/chunk-PZVKPCKE.js +475 -0
- package/dist/chunk-QWHBRY2K.js +4945 -0
- package/dist/chunk-RFOBMHQ7.js +338 -0
- package/dist/chunk-RHLNVZMS.js +28 -0
- package/dist/chunk-RVER2EOO.js +577 -0
- package/dist/chunk-S3QBGGVP.js +81 -0
- package/dist/chunk-TAML5WMA.js +198 -0
- package/dist/chunk-THTEUDBC.js +3188 -0
- package/dist/chunk-WYNM7L22.js +329 -0
- package/dist/chunk-XGCG4MD5.js +102 -0
- package/dist/chunk-XVKUFMIB.js +148 -0
- package/dist/chunk-XZYFZ6A5.js +50 -0
- package/dist/chunk-Y7PVJUXJ.js +2275 -0
- package/dist/chunk-YRSZPVMB.js +306 -0
- package/dist/chunk-YZUKHG3S.js +362 -0
- package/dist/chunk-ZVFS4LUA.js +116 -0
- package/dist/chunk-ZWLDLTJP.js +1417 -0
- package/dist/detect-676SNZK4.js +48 -0
- package/dist/dist-es-2YRDXMUU.js +73 -0
- package/dist/dist-es-CCVZEFRZ.js +91 -0
- package/dist/dist-es-EDUSMF6Q.js +488 -0
- package/dist/dist-es-IOH6G4GM.js +380 -0
- package/dist/dist-es-KWSMDPIP.js +26 -0
- package/dist/dist-es-UYDDOVZ3.js +173 -0
- package/dist/dist-es-XUOR4NQN.js +321 -0
- package/dist/docker-GOT3Q7DJ.js +41 -0
- package/dist/docker-edge-executor-VO6JHHW2.js +19 -0
- package/dist/edge-import-NFCHIW7G.js +50 -0
- package/dist/edge-preflight-QUJ757C6.js +45 -0
- package/dist/ensure-container-edge-Q7IZXHGM.js +38 -0
- package/dist/event-streams-TR4GAC53.js +46 -0
- package/dist/executor-GKXKN52K.js +42 -0
- package/dist/host-channel-preflight-Z6HYSPKO.js +48 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +9469 -0
- package/dist/loadSso-UGF4JMRK.js +581 -0
- package/dist/local-executor-OMMDKXCM.js +13 -0
- package/dist/nginx-VITTWZZU.js +42 -0
- package/dist/node-bootstrap.js +277 -0
- package/dist/node-entry.js +55 -0
- package/dist/noop-CLLJHCPL.js +11 -0
- package/dist/openresty-lua-6I3Z6PEQ.js +90 -0
- package/dist/privilege-UQAI2HV4.js +20 -0
- package/dist/server/engine/ChangeLog +2289 -0
- package/dist/server/engine/Documentations +5 -0
- package/dist/server/engine/LICENSE +674 -0
- package/dist/server/engine/README.md +34 -0
- package/dist/server/engine/conf/amavisd +150 -0
- package/dist/server/engine/conf/clamav +71 -0
- package/dist/server/engine/conf/core +632 -0
- package/dist/server/engine/conf/dovecot +151 -0
- package/dist/server/engine/conf/fail2ban +72 -0
- package/dist/server/engine/conf/global +698 -0
- package/dist/server/engine/conf/iredapd +52 -0
- package/dist/server/engine/conf/logwatch +28 -0
- package/dist/server/engine/conf/postfix +97 -0
- package/dist/server/engine/conf/postgresql +93 -0
- package/dist/server/engine/conf/spamassassin +39 -0
- package/dist/server/engine/dialog/config_via_dialog.sh +258 -0
- package/dist/server/engine/dialog/optional_components.sh +122 -0
- package/dist/server/engine/dialog/pgsql_config.sh +52 -0
- package/dist/server/engine/dialog/virtual_domain_config.sh +94 -0
- package/dist/server/engine/functions/amavisd.sh +267 -0
- package/dist/server/engine/functions/backend.sh +85 -0
- package/dist/server/engine/functions/clamav.sh +100 -0
- package/dist/server/engine/functions/cleanup.sh +393 -0
- package/dist/server/engine/functions/dovecot.sh +583 -0
- package/dist/server/engine/functions/fail2ban.sh +209 -0
- package/dist/server/engine/functions/iredapd.sh +356 -0
- package/dist/server/engine/functions/optional_components.sh +24 -0
- package/dist/server/engine/functions/packages.sh +522 -0
- package/dist/server/engine/functions/packages_freebsd.sh +179 -0
- package/dist/server/engine/functions/postfix.sh +457 -0
- package/dist/server/engine/functions/postgresql.sh +239 -0
- package/dist/server/engine/functions/spamassassin.sh +49 -0
- package/dist/server/engine/functions/system_accounts.sh +128 -0
- package/dist/server/engine/iRedMail.sh +144 -0
- package/dist/server/engine/pkgs/get_all.sh +338 -0
- package/dist/server/engine/pkgs/pkgs.freebsd.sha256 +3 -0
- package/dist/server/engine/pkgs/pkgs.openbsd.sha256 +6 -0
- package/dist/server/engine/pkgs/pkgs.sha256 +1 -0
- package/dist/server/engine/samples/amavisd/amavisd.conf +702 -0
- package/dist/server/engine/samples/amavisd/amavisd.mysql +278 -0
- package/dist/server/engine/samples/amavisd/amavisd.pgsql +253 -0
- package/dist/server/engine/samples/amavisd/amavisd.schema +942 -0
- package/dist/server/engine/samples/amavisd/default_spam_policy.sql +46 -0
- package/dist/server/engine/samples/dovecot/dovecot-2.4-mariadb.conf +758 -0
- package/dist/server/engine/samples/dovecot/dovecot-2.4-openldap.conf +767 -0
- package/dist/server/engine/samples/dovecot/dovecot-2.4-pgsql.conf +762 -0
- package/dist/server/engine/samples/dovecot/dovecot-last-login.conf +50 -0
- package/dist/server/engine/samples/dovecot/dovecot-ldap.conf +21 -0
- package/dist/server/engine/samples/dovecot/dovecot-share-folder.conf +22 -0
- package/dist/server/engine/samples/dovecot/dovecot-sql.conf +28 -0
- package/dist/server/engine/samples/dovecot/dovecot-used-quota.conf +13 -0
- package/dist/server/engine/samples/dovecot/dovecot.conf +484 -0
- package/dist/server/engine/samples/dovecot/dovecot.sieve +7 -0
- package/dist/server/engine/samples/dovecot/dovecot2-quota-warning.sh +38 -0
- package/dist/server/engine/samples/dovecot/sql/imap_share_folder.mysql +16 -0
- package/dist/server/engine/samples/dovecot/sql/last_login.mysql +12 -0
- package/dist/server/engine/samples/dovecot/sql/used_quota.mysql +26 -0
- package/dist/server/engine/samples/dovecot/systemd/override.conf +3 -0
- package/dist/server/engine/samples/fail2ban/action.d/banned_db.conf +9 -0
- package/dist/server/engine/samples/fail2ban/bin/fail2ban_banned_db +268 -0
- package/dist/server/engine/samples/fail2ban/fail2ban.local +17 -0
- package/dist/server/engine/samples/fail2ban/filter.d/dovecot.iredmail.conf +5 -0
- package/dist/server/engine/samples/fail2ban/filter.d/postfix-pregreet.iredmail.conf +16 -0
- package/dist/server/engine/samples/fail2ban/filter.d/postfix.iredmail.conf +18 -0
- package/dist/server/engine/samples/fail2ban/filter.d/roundcube.iredmail.conf +9 -0
- package/dist/server/engine/samples/fail2ban/jail.d/dovecot.local +8 -0
- package/dist/server/engine/samples/fail2ban/jail.d/nginx-http-auth.local +8 -0
- package/dist/server/engine/samples/fail2ban/jail.d/postfix-pregreet.local +9 -0
- package/dist/server/engine/samples/fail2ban/jail.d/postfix.local +8 -0
- package/dist/server/engine/samples/fail2ban/jail.d/roundcube.local +9 -0
- package/dist/server/engine/samples/fail2ban/jail.d/sogo.local +8 -0
- package/dist/server/engine/samples/fail2ban/jail.d/sshd.local +11 -0
- package/dist/server/engine/samples/fail2ban/jail.local +6 -0
- package/dist/server/engine/samples/fail2ban/openbsd/rc +27 -0
- package/dist/server/engine/samples/fail2ban/sql/fail2ban.mysql +49 -0
- package/dist/server/engine/samples/fail2ban/sql/fail2ban.pgsql +48 -0
- package/dist/server/engine/samples/firewall/firewalld/services/ssh.xml +6 -0
- package/dist/server/engine/samples/firewall/firewalld/zones/iredmail.xml +15 -0
- package/dist/server/engine/samples/firewall/iptables/ip6tables.init.debian +362 -0
- package/dist/server/engine/samples/firewall/iptables/ip6tables.rules +53 -0
- package/dist/server/engine/samples/firewall/iptables/iptables.init.debian +363 -0
- package/dist/server/engine/samples/firewall/iptables/iptables.rules +54 -0
- package/dist/server/engine/samples/firewall/nftables.conf +58 -0
- package/dist/server/engine/samples/freebsd/newsyslog.conf.d/dovecot.conf +3 -0
- package/dist/server/engine/samples/freebsd/newsyslog.conf.d/iredapd.conf +1 -0
- package/dist/server/engine/samples/freebsd/newsyslog.conf.d/mlmmjadmin.conf +1 -0
- package/dist/server/engine/samples/freebsd/newsyslog.conf.d/php-fpm.conf +2 -0
- package/dist/server/engine/samples/freebsd/newsyslog.conf.d/slapd.conf +1 -0
- package/dist/server/engine/samples/freebsd/syslog.d/dovecot.conf +2 -0
- package/dist/server/engine/samples/freebsd/syslog.d/fail2ban.conf +2 -0
- package/dist/server/engine/samples/freebsd/syslog.d/iredapd.conf +2 -0
- package/dist/server/engine/samples/freebsd/syslog.d/mlmmjadmin.conf +2 -0
- package/dist/server/engine/samples/freebsd/syslog.d/php-fpm.conf +2 -0
- package/dist/server/engine/samples/freebsd/syslog.d/slapd.conf +2 -0
- package/dist/server/engine/samples/iredmail/iredmail.mysql +491 -0
- package/dist/server/engine/samples/iredmail/iredmail.pgsql +465 -0
- package/dist/server/engine/samples/iredmail/iredmail.schema +456 -0
- package/dist/server/engine/samples/iredmail/used_quota_triggers_dovecot_2.3.pgsql +40 -0
- package/dist/server/engine/samples/iredmail/used_quota_triggers_dovecot_2.4.pgsql +18 -0
- package/dist/server/engine/samples/logrotate/dovecot +13 -0
- package/dist/server/engine/samples/logrotate/iredapd +13 -0
- package/dist/server/engine/samples/logrotate/mlmmjadmin +13 -0
- package/dist/server/engine/samples/logrotate/openldap +19 -0
- package/dist/server/engine/samples/logrotate/php-fpm +13 -0
- package/dist/server/engine/samples/openbsd/ldapd.conf +58 -0
- package/dist/server/engine/samples/openbsd/pf.conf +28 -0
- package/dist/server/engine/samples/postfix/command_filter.pcre +3 -0
- package/dist/server/engine/samples/postfix/freebsd/mailer.conf +9 -0
- package/dist/server/engine/samples/postfix/helo_access.pcre +180 -0
- package/dist/server/engine/samples/postfix/ldap/catchall_maps.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/recipient_bcc_maps_domain.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/recipient_bcc_maps_user.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/relay_domains.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/sender_bcc_maps_domain.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/sender_bcc_maps_user.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/sender_dependent_relayhost_maps_domain.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/sender_dependent_relayhost_maps_user.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/sender_login_maps.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/transport_maps_domain.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/transport_maps_user.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/virtual_alias_maps.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/virtual_group_maps.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/virtual_group_members_maps.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/virtual_mailbox_domains.cf +11 -0
- package/dist/server/engine/samples/postfix/ldap/virtual_mailbox_maps.cf +12 -0
- package/dist/server/engine/samples/postfix/main.cf +282 -0
- package/dist/server/engine/samples/postfix/main.cf.amavisd +7 -0
- package/dist/server/engine/samples/postfix/main.cf.dovecot +8 -0
- package/dist/server/engine/samples/postfix/main.cf.ldap +39 -0
- package/dist/server/engine/samples/postfix/main.cf.mlmmj +5 -0
- package/dist/server/engine/samples/postfix/main.cf.mysql +39 -0
- package/dist/server/engine/samples/postfix/main.cf.pgsql +39 -0
- package/dist/server/engine/samples/postfix/main.cf.postscreen +30 -0
- package/dist/server/engine/samples/postfix/master.cf +101 -0
- package/dist/server/engine/samples/postfix/mysql/catchall_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/domain_alias_catchall_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/domain_alias_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/recipient_bcc_maps_domain.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/recipient_bcc_maps_user.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/relay_domains.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/sender_bcc_maps_domain.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/sender_bcc_maps_user.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/sender_dependent_relayhost_maps.cf +6 -0
- package/dist/server/engine/samples/postfix/mysql/sender_login_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/transport_maps_domain.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/transport_maps_maillist.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/transport_maps_user.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/virtual_alias_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/virtual_mailbox_domains.cf +5 -0
- package/dist/server/engine/samples/postfix/mysql/virtual_mailbox_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/catchall_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/domain_alias_catchall_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/domain_alias_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/recipient_bcc_maps_domain.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/recipient_bcc_maps_user.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/relay_domains.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/sender_bcc_maps_domain.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/sender_bcc_maps_user.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/sender_dependent_relayhost_maps.cf +6 -0
- package/dist/server/engine/samples/postfix/pgsql/sender_login_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/transport_maps_domain.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/transport_maps_maillist.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/transport_maps_user.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/virtual_alias_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/virtual_mailbox_domains.cf +5 -0
- package/dist/server/engine/samples/postfix/pgsql/virtual_mailbox_maps.cf +5 -0
- package/dist/server/engine/samples/postfix/postscreen_access.cidr +6 -0
- package/dist/server/engine/samples/postgresql/sql/add_first_domain_and_user.sql +34 -0
- package/dist/server/engine/samples/postgresql/sql/grant_permissions.sql +14 -0
- package/dist/server/engine/samples/postgresql/sql/init_vmail_db.sql +15 -0
- package/dist/server/engine/samples/rsyslog.d/1-iredmail-dovecot.conf +23 -0
- package/dist/server/engine/samples/rsyslog.d/1-iredmail-fail2ban.conf +2 -0
- package/dist/server/engine/samples/rsyslog.d/1-iredmail-iredapd.conf +12 -0
- package/dist/server/engine/samples/rsyslog.d/1-iredmail-mlmmjadmin.conf +12 -0
- package/dist/server/engine/samples/rsyslog.d/1-iredmail-openldap.conf +2 -0
- package/dist/server/engine/samples/rsyslog.d/1-iredmail-phpfpm.conf +3 -0
- package/dist/server/engine/samples/spamassassin/local.cf +186 -0
- package/dist/server/engine/samples/spamassassin/razor.conf +1 -0
- package/dist/server/engine/samples/systemd/clamd.service.d/override.conf +2 -0
- package/dist/server/engine/samples/systemd/mariadb.service.d/override.conf +3 -0
- package/dist/server/engine/samples/systemd/slapd.service.d/override.conf +6 -0
- package/dist/server/engine/samples/yum/CentOS-Linux-AppStream.repo +6 -0
- package/dist/server/engine/samples/yum/CentOS-Linux-PowerTools.repo +6 -0
- package/dist/server/engine/samples/yum/CentOS-Stream-AppStream.repo +7 -0
- package/dist/server/engine/samples/yum/CentOS-Stream-PowerTools.repo +7 -0
- package/dist/server/engine/samples/yum/symas-openldap.repo +6 -0
- package/dist/server/engine/tools/add_enabled_service.py +60 -0
- package/dist/server/engine/tools/backup_mysql.sh +238 -0
- package/dist/server/engine/tools/backup_openldap.sh +230 -0
- package/dist/server/engine/tools/backup_pgsql.sh +217 -0
- package/dist/server/engine/tools/backup_sogo.sh +156 -0
- package/dist/server/engine/tools/create_mail_user_OpenLDAP.py +335 -0
- package/dist/server/engine/tools/create_mail_user_OpenLDAP.sh +287 -0
- package/dist/server/engine/tools/create_mail_user_SQL.sh +127 -0
- package/dist/server/engine/tools/enable_postscreen.sh +144 -0
- package/dist/server/engine/tools/fail2ban_unban_ip.sh +39 -0
- package/dist/server/engine/tools/find_sasl_login_ip.sh +20 -0
- package/dist/server/engine/tools/find_top_sasl_usernames.sh +28 -0
- package/dist/server/engine/tools/generate_ssl_keys.sh +85 -0
- package/dist/server/engine/tools/kill_high_cpu_sogo_process.sh +32 -0
- package/dist/server/engine/tools/ldap_assign_user_to_groups.py +151 -0
- package/dist/server/engine/tools/ldap_move_members_to_another_group.py +129 -0
- package/dist/server/engine/tools/migrate_sql_alias_table.py +177 -0
- package/dist/server/engine/update/0.9.8/amavisd.mysql +29 -0
- package/dist/server/engine/update/0.9.8/amavisd.pgsql +39 -0
- package/dist/server/engine/update/0.9.8/iredmail.mysql +53 -0
- package/dist/server/engine/update/0.9.8/iredmail.pgsql +61 -0
- package/dist/server/engine/update/0.9.9/iredmail.mysql +2 -0
- package/dist/server/engine/update/0.9.9/iredmail.pgsql +2 -0
- package/dist/server/engine/update/1.0/iredmail.mysql +2 -0
- package/dist/server/engine/update/1.0/iredmail.pgsql +2 -0
- package/dist/server/engine/update/1.2/last_login.mysql +16 -0
- package/dist/server/engine/update/1.4.0/iredmail.mysql +22 -0
- package/dist/server/engine/update/1.4.0/iredmail.pgsql +20 -0
- package/dist/server/engine/update/1.4.1/iredmail.mysql +3 -0
- package/dist/server/engine/update/1.4.1/iredmail.pgsql +3 -0
- package/dist/server/engine/update/1.4.1/sogo.mysql +11 -0
- package/dist/server/engine/update/1.4.1/sogo.pgsql +30 -0
- package/dist/server/engine/update/1.4.1/update-ldap.py +66 -0
- package/dist/server/engine/update/1.4.2/iredmail.mysql +9 -0
- package/dist/server/engine/update/1.4.2/iredmail.pgsql +9 -0
- package/dist/server/engine/update/1.4.2/sogo.pgsql +30 -0
- package/dist/server/engine/update/1.6.0/sogo_view.pgsql +27 -0
- package/dist/server/engine/update/1.6.3/iredmail.mysql +1 -0
- package/dist/server/engine/update/1.7.0/fail2ban.mysql +11 -0
- package/dist/server/engine/update/1.7.0/fail2ban.pgsql +12 -0
- package/dist/server/engine/update/1.7.1/amavisd.mysql +1 -0
- package/dist/server/engine/update/1.7.2/vmail.mysql +30 -0
- package/dist/server/engine/update/1.7.3/deleted_mailboxes.mysql +43 -0
- package/dist/server/engine/update/1.7.3/iredadmin.mysql +26 -0
- package/dist/server/engine/update/1.7.3/vmail.mysql +79 -0
- package/dist/server/engine/update/1.7.3/vmail.pgsql +9 -0
- package/dist/server/engine/update/README.md +1 -0
- package/dist/server/engine/update/ldap/README.md +39 -0
- package/dist/server/engine/update/ldap/update-ldap-dovecot-2.3.py +69 -0
- package/dist/server/index.js +349016 -0
- package/dist/server/lua/geo_country.lua +127 -0
- package/dist/server/lua/maxminddb.lua +403 -0
- package/dist/server/lua/mgmt_api.lua +654 -0
- package/dist/server/lua/pipe_stream.lua +103 -0
- package/dist/server/lua/rules_guard.lua +132 -0
- package/dist/server/lua/rules_lib.lua +176 -0
- package/dist/server/lua/site_logger.lua +405 -0
- package/dist/server/lua/webhook_handler.lua +126 -0
- package/dist/server/migrations/0000_init.sql +666 -0
- package/dist/server/migrations/0001_brief_tomorrow_man.sql +47 -0
- package/dist/server/migrations/0002_funny_dazzler.sql +2 -0
- package/dist/server/migrations/0003_third_killer_shrike.sql +1 -0
- package/dist/server/migrations/0004_session_active_org_not_null.sql +10 -0
- package/dist/server/migrations/0005_warm_amazoness.sql +3 -0
- package/dist/server/migrations/0006_lumpy_joystick.sql +1 -0
- package/dist/server/migrations/0007_outgoing_maginty.sql +2 -0
- package/dist/server/migrations/0008_frozen_cutover.sql +3 -0
- package/dist/server/migrations/0009_credits_billing.sql +142 -0
- package/dist/server/migrations/0010_credit_grant_dedupe.sql +14 -0
- package/dist/server/migrations/0011_remove_credit_ledger.sql +23 -0
- package/dist/server/migrations/0012_smart_deploys_and_git_rollback.sql +81 -0
- package/dist/server/migrations/0013_fix_check_run_rollup_unique.sql +38 -0
- package/dist/server/migrations/0014_default_rollback_git.sql +9 -0
- package/dist/server/migrations/0015_billing_idempotency_grants.sql +41 -0
- package/dist/server/migrations/0016_github_auth_high_findings.sql +30 -0
- package/dist/server/migrations/0017_spooky_rumiko_fujikawa.sql +6 -0
- package/dist/server/migrations/0018_calm_shatterstar.sql +1 -0
- package/dist/server/migrations/0019_rename_workspace_install_to_prepare.sql +1 -0
- package/dist/server/migrations/0020_uneven_the_renegades.sql +13 -0
- package/dist/server/migrations/0021_shiny_firestar.sql +2 -0
- package/dist/server/migrations/0022_version_on_success_backfill.sql +6 -0
- package/dist/server/migrations/0023_productive_gorilla_man.sql +17 -0
- package/dist/server/migrations/0024_sleepy_peter_quill.sql +2 -0
- package/dist/server/migrations/0025_smooth_blue_shield.sql +1 -0
- package/dist/server/migrations/0026_mail_backup_source.sql +11 -0
- package/dist/server/migrations/0027_opposite_anthem.sql +6 -0
- package/dist/server/migrations/0028_stale_rogue.sql +18 -0
- package/dist/server/migrations/0029_bouncy_loners.sql +16 -0
- package/dist/server/migrations/0030_bright_darkstar.sql +6 -0
- package/dist/server/migrations/0031_conscious_catseye.sql +13 -0
- package/dist/server/migrations/0032_wet_mimic.sql +51 -0
- package/dist/server/migrations/0033_eminent_molly_hayes.sql +2 -0
- package/dist/server/migrations/0034_nervous_surge.sql +1 -0
- package/dist/server/migrations/0035_thankful_morgan_stark.sql +1 -0
- package/dist/server/migrations/0036_gorgeous_scalphunter.sql +17 -0
- package/dist/server/migrations/0037_clever_makkari.sql +28 -0
- package/dist/server/migrations/0038_young_magneto.sql +1 -0
- package/dist/server/migrations/0039_secret_lady_ursula.sql +15 -0
- package/dist/server/migrations/0040_sharp_red_wolf.sql +16 -0
- package/dist/server/migrations/0041_round_spyke.sql +4 -0
- package/dist/server/migrations/0042_dapper_havok.sql +1 -0
- package/dist/server/migrations/0043_fast_sharon_ventura.sql +15 -0
- package/dist/server/migrations/0044_amused_shape.sql +8 -0
- package/dist/server/migrations/0045_amusing_korath.sql +1 -0
- package/dist/server/migrations/0046_white_harrier.sql +35 -0
- package/dist/server/migrations/0047_sloppy_strong_guy.sql +2 -0
- package/dist/server/migrations/0048_funny_emma_frost.sql +2 -0
- package/dist/server/migrations/0049_nappy_piledriver.sql +3 -0
- package/dist/server/migrations/0050_add_service_deployment_image_digest.sql +1 -0
- package/dist/server/migrations/0051_add_update_status.sql +19 -0
- package/dist/server/migrations/0052_add_notice_target.sql +2 -0
- package/dist/server/migrations/0053_colossal_sandman.sql +14 -0
- package/dist/server/migrations/0054_add_instance_smtp.sql +5 -0
- package/dist/server/migrations/0055_rainy_klaw.sql +22 -0
- package/dist/server/migrations/0056_moaning_daredevil.sql +2 -0
- package/dist/server/migrations/0057_complete_prism.sql +18 -0
- package/dist/server/migrations/0058_add_server_is_local.sql +1 -0
- package/dist/server/migrations/0059_legal_fixer.sql +18 -0
- package/dist/server/migrations/0060_add_route_strategy_host_port.sql +3 -0
- package/dist/server/migrations/0061_notification_default_multi_kind.sql +3 -0
- package/dist/server/migrations/0062_add_incoming_webhook.sql +21 -0
- package/dist/server/migrations/0063_add_migration_logs.sql +1 -0
- package/dist/server/migrations/0064_add_migration_partial.sql +2 -0
- package/dist/server/migrations/0065_custom_app_template.sql +14 -0
- package/dist/server/migrations/0066_ensure_migration_partial_columns.sql +2 -0
- package/dist/server/migrations/0067_webhook_delivery.sql +28 -0
- package/dist/server/migrations/0068_add_migration_target_volumes.sql +1 -0
- package/dist/server/migrations/0069_add_project_composite_routes.sql +1 -0
- package/dist/server/migrations/0070_forward_git_to_server.sql +1 -0
- package/dist/server/migrations/0071_gh_device_token.sql +3 -0
- package/dist/server/migrations/0072_gh_device_token_method.sql +1 -0
- 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/0098_instance_product_mode.sql +12 -0
- package/dist/server/migrations/0099_mail_webmail_project.sql +24 -0
- package/dist/server/migrations/0100_server_ssh_private_key.sql +11 -0
- package/dist/server/migrations/0101_mail_resume_step.sql +12 -0
- package/dist/server/migrations/0102_project_workload_axes.sql +19 -0
- package/dist/server/migrations/0103_dns_credential.sql +41 -0
- package/dist/server/migrations/0104_instance_host_control.sql +15 -0
- package/dist/server/migrations/0105_mail_inbound_rules.sql +80 -0
- package/dist/server/migrations/0106_mcp_call_tracking.sql +23 -0
- package/dist/server/migrations/0107_build_minute_metering_indexes.sql +20 -0
- package/dist/server/migrations/0108_credential.sql +68 -0
- package/dist/server/migrations/0109_service_build_args.sql +9 -0
- package/dist/server/migrations/0110_service_deployment_host_ports.sql +18 -0
- package/dist/server/migrations/0111_host_port_claim.sql +381 -0
- package/dist/server/migrations/0112_backup_run_execution_lease.sql +12 -0
- package/dist/server/migrations/0113_docker_migration_execution_lease.sql +11 -0
- package/dist/server/migrations/0114_build_session_execution_lease_index.sql +6 -0
- package/dist/server/migrations/0115_orphan_target_key.sql +3 -0
- package/dist/server/migrations/0116_domain_ssl_challenge.sql +2 -0
- package/dist/server/migrations/0117_github_installation_workspace_scope.sql +24 -0
- package/dist/server/migrations/0118_git_sources.sql +66 -0
- package/dist/server/migrations/0119_backup_run_batch.sql +8 -0
- package/dist/server/migrations/0120_domain_primary_unique.sql +24 -0
- package/dist/server/migrations/0121_host_port_claim_overlap.sql +14 -0
- package/dist/server/migrations/0122_data_transfer_staging.sql +45 -0
- package/dist/server/migrations/0123_drop_cloud_infra.sql +7 -0
- package/dist/server/migrations/0124_mail_dmarc_report.sql +23 -0
- package/dist/server/migrations/0125_server_security_snapshot.sql +22 -0
- package/dist/server/migrations/meta/0000_snapshot.json +4848 -0
- package/dist/server/migrations/meta/0001_snapshot.json +4991 -0
- package/dist/server/migrations/meta/0002_snapshot.json +5013 -0
- package/dist/server/migrations/meta/0003_snapshot.json +5020 -0
- package/dist/server/migrations/meta/0004_snapshot.json +5020 -0
- package/dist/server/migrations/meta/0005_snapshot.json +5039 -0
- package/dist/server/migrations/meta/0006_snapshot.json +5045 -0
- package/dist/server/migrations/meta/0007_snapshot.json +5057 -0
- package/dist/server/migrations/meta/0016_snapshot.json +6053 -0
- package/dist/server/migrations/meta/0017_snapshot.json +6091 -0
- package/dist/server/migrations/meta/0018_snapshot.json +6098 -0
- package/dist/server/migrations/meta/0019_snapshot.json +6098 -0
- package/dist/server/migrations/meta/0020_snapshot.json +6201 -0
- package/dist/server/migrations/meta/0021_snapshot.json +6213 -0
- package/dist/server/migrations/meta/0022_snapshot.json +6213 -0
- package/dist/server/migrations/meta/0023_snapshot.json +6331 -0
- package/dist/server/migrations/meta/0024_snapshot.json +6343 -0
- package/dist/server/migrations/meta/0025_snapshot.json +6350 -0
- package/dist/server/migrations/meta/0026_snapshot.json +6440 -0
- package/dist/server/migrations/meta/0027_snapshot.json +6447 -0
- package/dist/server/migrations/meta/0028_snapshot.json +6581 -0
- package/dist/server/migrations/meta/0029_snapshot.json +6710 -0
- package/dist/server/migrations/meta/0030_snapshot.json +6748 -0
- package/dist/server/migrations/meta/0031_snapshot.json +6859 -0
- package/dist/server/migrations/meta/0032_snapshot.json +7222 -0
- package/dist/server/migrations/meta/0033_snapshot.json +7249 -0
- package/dist/server/migrations/meta/0034_snapshot.json +7255 -0
- package/dist/server/migrations/meta/0035_snapshot.json +7262 -0
- package/dist/server/migrations/meta/0036_snapshot.json +7392 -0
- package/dist/server/migrations/meta/0037_snapshot.json +7602 -0
- package/dist/server/migrations/meta/0038_snapshot.json +7609 -0
- package/dist/server/migrations/meta/0039_snapshot.json +7714 -0
- package/dist/server/migrations/meta/0040_snapshot.json +7820 -0
- package/dist/server/migrations/meta/0041_snapshot.json +7833 -0
- package/dist/server/migrations/meta/0042_snapshot.json +7839 -0
- package/dist/server/migrations/meta/0043_snapshot.json +7938 -0
- package/dist/server/migrations/meta/0044_snapshot.json +7982 -0
- package/dist/server/migrations/meta/0045_snapshot.json +7989 -0
- package/dist/server/migrations/meta/0046_snapshot.json +8263 -0
- package/dist/server/migrations/meta/0047_snapshot.json +8275 -0
- package/dist/server/migrations/meta/0048_snapshot.json +8289 -0
- package/dist/server/migrations/meta/0049_snapshot.json +8308 -0
- package/dist/server/migrations/meta/0050_snapshot.json +8314 -0
- package/dist/server/migrations/meta/0051_snapshot.json +8460 -0
- package/dist/server/migrations/meta/0052_snapshot.json +8472 -0
- package/dist/server/migrations/meta/0053_snapshot.json +8556 -0
- package/dist/server/migrations/meta/0054_snapshot.json +8586 -0
- package/dist/server/migrations/meta/0055_snapshot.json +8756 -0
- package/dist/server/migrations/meta/0056_snapshot.json +8777 -0
- package/dist/server/migrations/meta/0057_snapshot.json +8904 -0
- package/dist/server/migrations/meta/0058_snapshot.json +8911 -0
- package/dist/server/migrations/meta/0059_snapshot.json +9061 -0
- package/dist/server/migrations/meta/0060_snapshot.json +9081 -0
- package/dist/server/migrations/meta/_journal.json +888 -0
- package/dist/server/pglite/pglite.data +0 -0
- package/dist/server/pglite/pglite.wasm +0 -0
- package/dist/setup-JWKZIECM.js +25 -0
- package/dist/signin-3M3UPB6K.js +667 -0
- package/dist/ssh-client-NWQVRCV7.js +29 -0
- package/dist/sso-oidc-3VDIYOEJ.js +834 -0
- package/dist/sts-B3WIYLXR.js +1426 -0
- package/dist/up-P5DMQ5YO.js +55 -0
- package/package.json +58 -0
|
@@ -0,0 +1,975 @@
|
|
|
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
|
+
describeProcess,
|
|
7
|
+
probeListeningPortOwners
|
|
8
|
+
} from "./chunk-WYNM7L22.js";
|
|
9
|
+
import {
|
|
10
|
+
envOps,
|
|
11
|
+
opScript
|
|
12
|
+
} from "./chunk-YRSZPVMB.js";
|
|
13
|
+
import {
|
|
14
|
+
resolveEnvironment
|
|
15
|
+
} from "./chunk-OFXBNFNL.js";
|
|
16
|
+
import {
|
|
17
|
+
sq
|
|
18
|
+
} from "./chunk-MNV2QFHW.js";
|
|
19
|
+
import {
|
|
20
|
+
SYSTEM,
|
|
21
|
+
answered,
|
|
22
|
+
refused,
|
|
23
|
+
safeErrorMessage
|
|
24
|
+
} from "./chunk-PVOWHIND.js";
|
|
25
|
+
|
|
26
|
+
// ../../packages/adapters/src/infra/openresty-lua.ts
|
|
27
|
+
import { createHash, randomBytes } from "crypto";
|
|
28
|
+
import { existsSync, readFileSync } from "fs";
|
|
29
|
+
import { dirname, join } from "path";
|
|
30
|
+
import { fileURLToPath } from "url";
|
|
31
|
+
|
|
32
|
+
// ../../packages/adapters/src/infra/lua-embedded.ts
|
|
33
|
+
var EMBEDDED_LUA = {
|
|
34
|
+
"geo_country.lua": "LS0gZ2VvX2NvdW50cnkubHVhCi0tIE1heE1pbmQgR2VvTGl0ZTItQ291bnRyeSBsb29rdXAgd2l0aCBwZXItd29ya2VyIExSVSBjYWNoZS4KLS0KLS0gREIgYW5kIGNhY2hlIGFyZSBwZXItd29ya2VyIG9ubHk6IG9uZSBsb2FkIHBlciB3b3JrZXIsIHNoYXJlZCBieSBhbGwKLS0gcmVxdWVzdHMuIE5vIHJlbG9hZCBwZXIgc3RyZWFtIG9yIHBlciByZXF1ZXN0LgotLQotLSBEZXBlbmRlbmNpZXM6Ci0tICAgTHVhIGJpbmRpbmcg4oCUIGBrcmFmdC5tYXhtaW5kZGJgLCB2ZW5kb3JlZCBiZXNpZGUgdGhpcyBmaWxlLiBGYWxscyBiYWNrIHRvCi0tICAgICAgICAgICAgICAgICBgcmVzdHkubWF4bWluZGRiYCBmb3IgYSBiYXJlIGJveCB0aGF0IGhhcyB0aGUgb3BtIHBhY2thZ2UKLS0gICAgICAgICAgICAgICAgIGluc3RhbGxlZCBmcm9tIGJlZm9yZSB3ZSB2ZW5kb3JlZCBpdC4KLS0gICBDIGxpYnJhcnkgICDigJQgbGlibWF4bWluZGRiLnNvIChgYXBrIGFkZCBsaWJtYXhtaW5kZGJgIGluIGFwcHMvZWRnZS9Eb2NrZXJmaWxlOwotLSAgICAgICAgICAgICAgICAgaW5zdGFsbEdlb0RlcHMoKSBmb3IgYmFyZSBib3hlcykKLS0gICBEYXRhYmFzZSAgICDigJQgL3Vzci9zaGFyZS9HZW9JUC9HZW9MaXRlMi1Db3VudHJ5Lm1tZGIgKGJha2VkIGludG8gdGhlIGVkZ2UKLS0gICAgICAgICAgICAgICAgIGltYWdlIGZyb20gYXBwcy9hcGkvYXNzZXRzL2dlb2lwLCBzbyBubyBydW50aW1lIGRvd25sb2FkKQotLQotLSBGYWxscyBiYWNrIGdyYWNlZnVsbHkgLSBpZiB0aGUgbGlicmFyeSBvciBkYXRhYmFzZSBpcyBtaXNzaW5nLAotLSBnZXRfY291bnRyeV9jb2RlKCkgcmV0dXJucyBuaWwuICBzaXRlX2xvZ2dlci5sdWEgd3JhcHMgdGhpcyBtb2R1bGUgaW4KLS0gcGNhbGwocmVxdWlyZSwgLi4uKSBzbyBhIG1pc3NpbmcgREIgbmV2ZXIgY3Jhc2hlcyB0aGUgcmVxdWVzdCBwaXBlbGluZQotLSAodGhlIGNvdW50cnkgaXQgcmVzb2x2ZXMgZmxvd3MgaW50byB0aGUgcmluZyBidWZmZXIsIGFuZCBmcm9tIHRoZXJlIHRvCi0tIGJvdGggL2xvZ3MvcmVjZW50IGFuZCB0aGUgbGl2ZSBTU0Ugc3RyZWFtKS4gbWdtdF9hcGkgYEdFVCAvc3RhdHVzYCByZXBvcnRzIHdoZXRoZXIgZ2VvIGFjdHVhbGx5Ci0tIHJlc29sdmVkLCBzbyBhIHNpbGVudGx5LWRhcmsgZWRnZSBpcyB2aXNpYmxlIGluc3RlYWQgb2YganVzdCB5aWVsZGluZyBhbgotLSBlbXB0eSBjb3VudHJ5IG1hcC4KCmxvY2FsIF9NID0ge30KCmxvY2FsIERCX1BBVEggPSAiL3Vzci9zaGFyZS9HZW9JUC9HZW9MaXRlMi1Db3VudHJ5Lm1tZGIiCgotLSBWZW5kb3JlZCBjb3B5IGZpcnN0LCBvcG0taW5zdGFsbGVkIGNvcHkgc2Vjb25kLiBgZmZpLmxvYWQoJ2xpYm1heG1pbmRkYicpYAotLSBydW5zIGF0IHJlcXVpcmUgdGltZSBpbiBib3RoLCBzbyBhIG1pc3NpbmcgLnNvIHN1cmZhY2VzIGhlcmUgYXMgbW1kYl9vaz1mYWxzZS4KbG9jYWwgbW1kYl9vaywgbWF4bWluZCA9IHBjYWxsKHJlcXVpcmUsICJrcmFmdC5tYXhtaW5kZGIiKQppZiBub3QgbW1kYl9vayB0aGVuCiAgICBtbWRiX29rLCBtYXhtaW5kID0gcGNhbGwocmVxdWlyZSwgInJlc3R5Lm1heG1pbmRkYiIpCmVuZApsb2NhbCBscnVjYWNoZV9vaywgbHJ1Y2FjaGUgPSBwY2FsbChyZXF1aXJlLCAicmVzdHkubHJ1Y2FjaGUiKQoKbG9jYWwgY2FjaGUgICAgICAgICAgICAtLSBvbmUgTFJVIHBlciB3b3JrZXIKbG9jYWwgZ2VvX2luaXR0ZWQgPSBmYWxzZSAgLS0gREIgb3BlbmVkIG9uY2UgcGVyIHdvcmtlciBvbiBmaXJzdCBsb29rdXAKLS0gV2h5IGdlbyBpcyBvZmYsIGZvciBgR0VUIC9zdGF0dXNgLiBEaXN0aW5ndWlzaGluZyAibm8gRkZJIGJpbmRpbmcgLyBubyAuc28iCi0tIGZyb20gIm5vIGRhdGFiYXNlIiBtYXR0ZXJzOiB0aGV5IG5lZWQgZGlmZmVyZW50IGZpeGVzLCBhbmQgYm90aCB1c2VkIHRvCi0tIHByZXNlbnQgaWRlbnRpY2FsbHkgYXMgYW4gZW1wdHkgY291bnRyeSBtYXAuCmxvY2FsIGdlb19yZWFzb24gPSAibm90IGluaXRpYWxpc2VkIgoKLS0gSW5pdCBNYXhNaW5kIG9uY2UgcGVyIHdvcmtlcjsgc3Vic2VxdWVudCBsb29rdXBzIChhbnkgc3RyZWFtKSByZXVzZS4KbG9jYWwgZnVuY3Rpb24gZW5zdXJlX2dlb19pbml0KCkKICAgIGlmIGdlb19pbml0dGVkIHRoZW4KICAgICAgICByZXR1cm4gdHJ1ZQogICAgZW5kCiAgICBpZiBub3QgbW1kYl9vayBvciBub3QgbWF4bWluZCB0aGVuCiAgICAgICAgZ2VvX3JlYXNvbiA9ICJtYXhtaW5kZGIgRkZJIGJpbmRpbmcgdW5hdmFpbGFibGUgKGxpYm1heG1pbmRkYi5zbyBtaXNzaW5nPykiCiAgICAgICAgcmV0dXJuIGZhbHNlCiAgICBlbmQKICAgIGxvY2FsIG9rLCBlcnIgPSBtYXhtaW5kLmluaXQoREJfUEFUSCkKICAgIGlmIG5vdCBvayB0aGVuCiAgICAgICAgZ2VvX3JlYXNvbiA9ICJkYXRhYmFzZSB1bnJlYWRhYmxlIGF0ICIgLi4gREJfUEFUSCAuLiAiOiAiIC4uIChlcnIgb3IgInVua25vd24iKQogICAgICAgIG5neC5sb2cobmd4LldBUk4sCiAgICAgICAgICAgICJbZ2VvX2NvdW50cnldIEdlb0xpdGUyIGRhdGFiYXNlIG5vdCBmb3VuZCBhdCAiIC4uIERCX1BBVEggLi4KICAgICAgICAgICAgIiAtIGdlbyBsb29rdXBzIGRpc2FibGVkOiAiIC4uIChlcnIgb3IgInVua25vd24iKSkKICAgICAgICByZXR1cm4gZmFsc2UKICAgIGVuZAogICAgZ2VvX2luaXR0ZWQgPSB0cnVlCiAgICBnZW9fcmVhc29uID0gIm9rIgogICAgbmd4LmxvZyhuZ3guSU5GTywgIltnZW9fY291bnRyeV0gR2VvTGl0ZTItQ291bnRyeSBsb2FkZWQgZnJvbSAiIC4uIERCX1BBVEgpCiAgICByZXR1cm4gdHJ1ZQplbmQKCi0tIENyZWF0ZSBMUlUgY2FjaGUgb25jZSBwZXIgd29ya2VyIChtYXggNTAwMDAgSVBzKS4KbG9jYWwgZnVuY3Rpb24gZ2V0X2NhY2hlKCkKICAgIGlmIGNhY2hlIHRoZW4KICAgICAgICByZXR1cm4gY2FjaGUKICAgIGVuZAogICAgaWYgbm90IGxydWNhY2hlX29rIG9yIG5vdCBscnVjYWNoZSB0aGVuCiAgICAgICAgcmV0dXJuIG5pbAogICAgZW5kCiAgICBsb2NhbCBjLCBlcnIgPSBscnVjYWNoZS5uZXcoNTAwMDApCiAgICBpZiBub3QgYyB0aGVuCiAgICAgICAgcmV0dXJuIG5pbAogICAgZW5kCiAgICBjYWNoZSA9IGMKICAgIHJldHVybiBjYWNoZQplbmQKCi0tLSBHZXQgY291bnRyeSBJU08gY29kZSBmb3IgSVAuIFVzZXMgaW4tbWVtb3J5IExSVSBjYWNoZSB0aGVuIE1heE1pbmQgREIuCi0tIEBwYXJhbSBpcCBzdHJpbmcgKGUuZy4gIjguOC44LjgiKQotLSBAcmV0dXJuIHN0cmluZ3xuaWwgY291bnRyeSBjb2RlIChlLmcuICJVUyIpIG9yIG5pbApmdW5jdGlvbiBfTS5nZXRfY291bnRyeV9jb2RlKGlwKQogICAgaWYgbm90IGlwIG9yIGlwID09ICIiIHRoZW4KICAgICAgICByZXR1cm4gbmlsCiAgICBlbmQKCiAgICBsb2NhbCBjID0gZ2V0X2NhY2hlKCkKICAgIGlmIGMgdGhlbgogICAgICAgIGxvY2FsIGNhY2hlZCA9IGM6Z2V0KGlwKQogICAgICAgIGlmIGNhY2hlZCB+PSBuaWwgdGhlbgogICAgICAgICAgICAtLSBmYWxzZSBtZWFucyAibG9va2VkIHVwLCBubyByZXN1bHQiIC0gYXZvaWRzIHJlcGVhdGVkIERCIG1pc3NlcwogICAgICAgICAgICByZXR1cm4gKGNhY2hlZCA9PSBmYWxzZSkgYW5kIG5pbCBvciBjYWNoZWQKICAgICAgICBlbmQKICAgIGVuZAoKICAgIGlmIG5vdCBlbnN1cmVfZ2VvX2luaXQoKSB0aGVuCiAgICAgICAgaWYgYyB0aGVuIGM6c2V0KGlwLCBmYWxzZSkgZW5kCiAgICAgICAgcmV0dXJuIG5pbAogICAgZW5kCgogICAgbG9jYWwgb2ssIHJlcywgZXJyID0gcGNhbGwobWF4bWluZC5sb29rdXAsIGlwKQogICAgbG9jYWwgY29kZSA9IG5pbAogICAgaWYgb2sgYW5kIHJlcyBhbmQgcmVzLmNvdW50cnkgYW5kIHJlcy5jb3VudHJ5Lmlzb19jb2RlIHRoZW4KICAgICAgICBjb2RlID0gcmVzLmNvdW50cnkuaXNvX2NvZGUKICAgIGVuZAoKICAgIGlmIGMgdGhlbgogICAgICAgIGM6c2V0KGlwLCBjb2RlIG9yIGZhbHNlKQogICAgZW5kCiAgICByZXR1cm4gY29kZQplbmQKCmZ1bmN0aW9uIF9NLmVuc3VyZV9nZW9faW5pdCgpCiAgICByZXR1cm4gZW5zdXJlX2dlb19pbml0KCkKZW5kCgotLS0gSGVhbHRoIGZvciBgR0VUIC9zdGF0dXNgOiBkb2VzIGdlbyBhY3R1YWxseSByZXNvbHZlLCBhbmQgaWYgbm90LCB3aHkuCi0tIEByZXR1cm4gYm9vbGVhbiBhdmFpbGFibGUsIHN0cmluZyByZWFzb24sIHN0cmluZyBkYl9wYXRoCmZ1bmN0aW9uIF9NLnN0YXR1cygpCiAgICBsb2NhbCBvayA9IGVuc3VyZV9nZW9faW5pdCgpCiAgICByZXR1cm4gb2ssIGdlb19yZWFzb24sIERCX1BBVEgKZW5kCgpyZXR1cm4gX00K",
|
|
35
|
+
"maxminddb.lua": "LS0gbWF4bWluZGRiLmx1YSDigJQgVkVORE9SRUQgVEhJUkQtUEFSVFkuIERvIG5vdCBlZGl0OyByZS12ZW5kb3IgaW5zdGVhZC4KLS0KLS0gVXBzdHJlYW06IGFuamlhMDUzMi9sdWEtcmVzdHktbWF4bWluZGRiIHYxLjMuMiAob3BtKS4gTG9hZGVkIGFzCi0tIGBrcmFmdC5tYXhtaW5kZGJgIChzZWUgZ2VvX2NvdW50cnkubHVhKS4gVmVyYmF0aW0gZXhjZXB0IHRoaXMgaGVhZGVyIGFuZCBPTkUKLS0gbWFya2VkIGNoYW5nZSB0byB0aGUgYGZmaS5sb2FkYCBjYWxsIOKAlCBzZWFyY2ggIktSQUZUIExPQ0FMIE1PRElGSUNBVElPTiIuCi0tCi0tIFdoeSB2ZW5kb3JlZCByYXRoZXIgdGhhbiBgb3BtIGdldGAgYXQgaW1hZ2UgYnVpbGQ6IGBvcG1gIG5lZWRzIHBlcmwsIHdoaWNoIHRoZQotLSBvcGVucmVzdHkgYWxwaW5lIGJhc2UgZG9lcyBub3Qgc2hpcCwgYW5kIGEgYnVpbGQtdGltZSBmZXRjaCB3b3VsZCBtYWtlIHRoZQotLSBpbWFnZSBub24tcmVwcm9kdWNpYmxlLiBFdmVyeXRoaW5nIGVsc2UgaW4gdGhpcyBkaXJlY3RvcnkgaXMgYWxyZWFkeSBzaGlwcGVkCi0tIGJ5IHVzIChhbmQgYmFzZTY0LWVtYmVkZGVkIGludG8gdGhlIEpTIGJ1bmRsZSksIHNvIGEgcGlubmVkIGNvcHkgaXMgdGhlIGhvdXNlCi0tIHBhdHRlcm4g4oCUIHNhbWUgcmVhc29uaW5nIGFzIHRoZSB2ZW5kb3JlZCBHZW9MaXRlMiBEQiBpbiBhcHBzL2FwaS9hc3NldHMvZ2VvaXAuCi0tCi0tIE5lZWRzIGxpYm1heG1pbmRkYi5zbyBhdCBydW50aW1lIChgYXBrIGFkZCBsaWJtYXhtaW5kZGJgLCBpbiBhcHBzL2VkZ2UvRG9ja2VyZmlsZSkuCi0tIGBmZmkubG9hZGAgYmVsb3cgcnVucyBhdCBSRVFVSVJFIHRpbWUsIHNvIGEgbWlzc2luZyAuc28gdGhyb3dzIG9uIHJlcXVpcmUg4oCUCi0tIGdlb19jb3VudHJ5Lmx1YSBwY2FsbHMgaXQgZm9yIGV4YWN0bHkgdGhhdCByZWFzb24uCi0tCi0tIFJlLXZlbmRvciB3aXRoOgotLSAgIGN1cmwgLWZzU0wgaHR0cHM6Ly9vcG0ub3BlbnJlc3R5Lm9yZy9hcGkvcGtnL3RhcmJhbGwvYW5qaWEwNTMyL2x1YS1yZXN0eS1tYXhtaW5kZGItPHY+Lm9wbS50YXIuZ3ogXAotLSAgICAgfCB0YXIgeHogLU8gJyovbGliL3Jlc3R5L21heG1pbmRkYi5sdWEnID4gcGFja2FnZXMvYWRhcHRlcnMvc3JjL2luZnJhL2x1YS9tYXhtaW5kZGIubHVhCi0tICAgIyB0aGVuIHJlLWFwcGx5IHRoaXMgaGVhZGVyIGFuZCBydW4gYGJ1biBydW4gZW1iZWQ6bHVhYAotLVtbCglDb3B5cmlnaHQgMjAxNy1ub3cgYW5qaWEgKGFuamlhMDUzMkBnbWFpbC5jb20pCgoJTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlICJMaWNlbnNlIik7Cgl5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCglZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKCQlodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKCVVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKCWRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICJBUyBJUyIgQkFTSVMsCglXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KCVNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKCWxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLgpdXQoKLS0gY29weSBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9saWxpZW4xMDEwL2x1YS1yZXN0eS1tYXhtaW5kZGIvYmxvYi9mOTY2MzNlMjQyOGY4ZjdiY2MxZTJhN2EyOGI3NDdiMzMyMzNhOGRiL3Jlc3R5L21heG1pbmRkYi5sdWEjTDUtTDEyCgpsb2NhbCBmZmkgICAgICAgICAgICAgICAgID0gcmVxdWlyZSAoJ2ZmaScpCmxvY2FsIGZmaV9uZXcgICAgICAgICAgICAgPSBmZmkubmV3CmxvY2FsIGZmaV9zdHIgICAgICAgICAgICAgPSBmZmkuc3RyaW5nCmxvY2FsIGZmaV9jYXN0ICAgICAgICAgICAgPSBmZmkuY2FzdApsb2NhbCBmZmlfZ2MgICAgICAgICAgICAgID0gZmZpLmdjCmxvY2FsIEMgICAgICAgICAgICAgICAgICAgPSBmZmkuQwoKbG9jYWwgX00gICAgPXt9Cl9NLl9WRVJTSU9OID0gJzEuMy4yJwpsb2NhbCBtdCA9IHsgX19pbmRleCA9IF9NIH0KCi0tIGNvcHkgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vbGlsaWVuMTAxMC9sdWEtcmVzdHktbWF4bWluZGRiL2Jsb2IvZjk2NjMzZTI0MjhmOGY3YmNjMWUyYTdhMjhiNzQ3YjMzMjMzYThkYi9yZXN0eS9tYXhtaW5kZGIubHVhI0wzNi1MMTI2CmZmaS5jZGVmW1sKCnR5cGVkZWYgbG9uZyBpbnQgc3NpemVfdDsKCnR5cGVkZWYgdW5zaWduZWQgaW50IG1tZGJfdWludDEyOF90IF9fYXR0cmlidXRlX18gKChfX21vZGVfXyhUSSkpKTsKCnR5cGVkZWYgc3RydWN0IE1NREJfZW50cnlfcyB7CiAgc3RydWN0IE1NREJfcyAqbW1kYjsKICB1aW50MzJfdCBvZmZzZXQ7Cn0gTU1EQl9lbnRyeV9zOwoKdHlwZWRlZiBzdHJ1Y3QgTU1EQl9sb29rdXBfcmVzdWx0X3MgewogIGJvb2wgZm91bmRfZW50cnk7CiAgTU1EQl9lbnRyeV9zIGVudHJ5OwogIHVpbnQxNl90IG5ldG1hc2s7Cn0gTU1EQl9sb29rdXBfcmVzdWx0X3M7Cgp0eXBlZGVmIHN0cnVjdCBNTURCX2VudHJ5X2RhdGFfcyB7CiAgYm9vbCBoYXNfZGF0YTsKICB1bmlvbiB7CiAgICB1aW50MzJfdCBwb2ludGVyOwogICAgY29uc3QgY2hhciAqdXRmOF9zdHJpbmc7CiAgICBkb3VibGUgZG91YmxlX3ZhbHVlOwogICAgY29uc3QgdWludDhfdCAqYnl0ZXM7CiAgICB1aW50MTZfdCB1aW50MTY7CiAgICB1aW50MzJfdCB1aW50MzI7CiAgICBpbnQzMl90IGludDMyOwogICAgdWludDY0X3QgdWludDY0OwogICAgbW1kYl91aW50MTI4X3QgdWludDEyODsKICAgIGJvb2wgYm9vbGVhbjsKICAgIGZsb2F0IGZsb2F0X3ZhbHVlOwogIH07CgogIHVpbnQzMl90IG9mZnNldDsKICB1aW50MzJfdCBvZmZzZXRfdG9fbmV4dDsKICB1aW50MzJfdCBkYXRhX3NpemU7CiAgdWludDMyX3QgdHlwZTsKfSBNTURCX2VudHJ5X2RhdGFfczsKCnR5cGVkZWYgc3RydWN0IE1NREJfZW50cnlfZGF0YV9saXN0X3MgewogIE1NREJfZW50cnlfZGF0YV9zIGVudHJ5X2RhdGE7CiAgc3RydWN0IE1NREJfZW50cnlfZGF0YV9saXN0X3MgKm5leHQ7Cn0gTU1EQl9lbnRyeV9kYXRhX2xpc3RfczsKCnR5cGVkZWYgc3RydWN0IE1NREJfZGVzY3JpcHRpb25fcyB7CiAgY29uc3QgY2hhciAqbGFuZ3VhZ2U7CiAgY29uc3QgY2hhciAqZGVzY3JpcHRpb247Cn0gTU1EQl9kZXNjcmlwdGlvbl9zOwoKdHlwZWRlZiBzdHJ1Y3QgTU1EQl9tZXRhZGF0YV9zIHsKICB1aW50MzJfdCBub2RlX2NvdW50OwogIHVpbnQxNl90IHJlY29yZF9zaXplOwogIHVpbnQxNl90IGlwX3ZlcnNpb247CiAgY29uc3QgY2hhciAqZGF0YWJhc2VfdHlwZTsKICBzdHJ1Y3QgewogICAgc2l6ZV90IGNvdW50OwogICAgY29uc3QgY2hhciAqKm5hbWVzOwogIH0gbGFuZ3VhZ2VzOwogIHVpbnQxNl90IGJpbmFyeV9mb3JtYXRfbWFqb3JfdmVyc2lvbjsKICB1aW50MTZfdCBiaW5hcnlfZm9ybWF0X21pbm9yX3ZlcnNpb247CiAgdWludDY0X3QgYnVpbGRfZXBvY2g7CiAgc3RydWN0IHsKICAgIHNpemVfdCBjb3VudDsKICAgIE1NREJfZGVzY3JpcHRpb25fcyAqKmRlc2NyaXB0aW9uczsKICB9IGRlc2NyaXB0aW9uOwp9IE1NREJfbWV0YWRhdGFfczsKCnR5cGVkZWYgc3RydWN0IE1NREJfaXB2NF9zdGFydF9ub2RlX3MgewogIHVpbnQxNl90IG5ldG1hc2s7CiAgdWludDMyX3Qgbm9kZV92YWx1ZTsKfSBNTURCX2lwdjRfc3RhcnRfbm9kZV9zOwoKdHlwZWRlZiBzdHJ1Y3QgTU1EQl9zIHsKICB1aW50MzJfdCBmbGFnczsKICBjb25zdCBjaGFyICpmaWxlbmFtZTsKICBzc2l6ZV90IGZpbGVfc2l6ZTsKICBjb25zdCB1aW50OF90ICpmaWxlX2NvbnRlbnQ7CiAgY29uc3QgdWludDhfdCAqZGF0YV9zZWN0aW9uOwogIHVpbnQzMl90IGRhdGFfc2VjdGlvbl9zaXplOwogIGNvbnN0IHVpbnQ4X3QgKm1ldGFkYXRhX3NlY3Rpb247CiAgdWludDMyX3QgbWV0YWRhdGFfc2VjdGlvbl9zaXplOwogIHVpbnQxNl90IGZ1bGxfcmVjb3JkX2J5dGVfc2l6ZTsKICB1aW50MTZfdCBkZXB0aDsKICBNTURCX2lwdjRfc3RhcnRfbm9kZV9zIGlwdjRfc3RhcnRfbm9kZTsKICBNTURCX21ldGFkYXRhX3MgbWV0YWRhdGE7Cn0gTU1EQl9zOwoKdHlwZWRlZiAgY2hhciAqIHBjaGFyOwoKTU1EQl9sb29rdXBfcmVzdWx0X3MgTU1EQl9sb29rdXBfc3RyaW5nKE1NREJfcyAqY29uc3QgbW1kYiwgICBjb25zdCBjaGFyICpjb25zdCBpcHN0ciwgaW50ICpjb25zdCBnYWlfZXJyb3IsaW50ICpjb25zdCBtbWRiX2Vycm9yKTsKaW50IE1NREJfb3Blbihjb25zdCBjaGFyICpjb25zdCBmaWxlbmFtZSwgdWludDMyX3QgZmxhZ3MsIE1NREJfcyAqY29uc3QgbW1kYik7CmludCBNTURCX2FnZXRfdmFsdWUoTU1EQl9lbnRyeV9zICpjb25zdCBzdGFydCwgIE1NREJfZW50cnlfZGF0YV9zICpjb25zdCBlbnRyeV9kYXRhLCAgY29uc3QgY2hhciAqY29uc3QgKmNvbnN0IHBhdGgpOwpjaGFyICpNTURCX3N0cmVycm9yKGludCBlcnJvcl9jb2RlKTsKCmludCBNTURCX2dldF9lbnRyeV9kYXRhX2xpc3QoTU1EQl9lbnRyeV9zICpzdGFydCwgTU1EQl9lbnRyeV9kYXRhX2xpc3RfcyAqKmNvbnN0IGVudHJ5X2RhdGFfbGlzdCk7CnZvaWQgTU1EQl9mcmVlX2VudHJ5X2RhdGFfbGlzdChNTURCX2VudHJ5X2RhdGFfbGlzdF9zICpjb25zdCBlbnRyeV9kYXRhX2xpc3QpOwp2b2lkIE1NREJfY2xvc2UoTU1EQl9zICpjb25zdCBtbWRiKTsKY29uc3QgY2hhciAqZ2FpX3N0cmVycm9yKGludCBlcnJjb2RlKTsKXV0KCi0tIGVycm9yIGNvZGVzIAotLSBodHRwczovL2dpdGh1Yi5jb20vbWF4bWluZC9saWJtYXhtaW5kZGIvYmxvYi9tYXN0ZXIvaW5jbHVkZS9tYXhtaW5kZGIuaCNMNjYKbG9jYWwgTU1EQl9TVUNDRVNTICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gICAwCmxvY2FsIE1NREJfRklMRV9PUEVOX0VSUk9SICAgICAgICAgICAgICAgICAgICAgICAgICA9ICAgMQpsb2NhbCBNTURCX0NPUlJVUFRfU0VBUkNIX1RSRUVfRVJST1IgICAgICAgICAgICAgICAgPSAgIDIKbG9jYWwgTU1EQl9JTlZBTElEX01FVEFEQVRBX0VSUk9SICAgICAgICAgICAgICAgICAgID0gICAzCmxvY2FsIE1NREJfSU9fRVJST1IgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9ICAgNApsb2NhbCBNTURCX09VVF9PRl9NRU1PUllfRVJST1IgICAgICAgICAgICAgICAgICAgICAgPSAgIDUKbG9jYWwgTU1EQl9VTktOT1dOX0RBVEFCQVNFX0ZPUk1BVF9FUlJPUiAgICAgICAgICAgID0gICA2CmxvY2FsIE1NREJfSU5WQUxJRF9EQVRBX0VSUk9SICAgICAgICAgICAgICAgICAgICAgICA9ICAgNwpsb2NhbCBNTURCX0lOVkFMSURfTE9PS1VQX1BBVEhfRVJST1IgICAgICAgICAgICAgICAgPSAgIDgKbG9jYWwgTU1EQl9MT09LVVBfUEFUSF9ET0VTX05PVF9NQVRDSF9EQVRBX0VSUk9SICAgID0gICA5CmxvY2FsIE1NREJfSU5WQUxJRF9OT0RFX05VTUJFUl9FUlJPUiAgICAgICAgICAgICAgICA9ICAgMTAKbG9jYWwgTU1EQl9JUFY2X0xPT0tVUF9JTl9JUFY0X0RBVEFCQVNFX0VSUk9SICAgICAgID0gICAxMQoKLS0gZGF0YSB0eXBlCi0tIGh0dHBzOi8vZ2l0aHViLmNvbS9tYXhtaW5kL2xpYm1heG1pbmRkYi9ibG9iL21hc3Rlci9pbmNsdWRlL21heG1pbmRkYi5oI0w0MApsb2NhbCBNTURCX0RBVEFfVFlQRV9FWFRFTkRFRCAgICAgICAgICAgICAgICAgICAgICAgPSAgIDAKbG9jYWwgTU1EQl9EQVRBX1RZUEVfUE9JTlRFUiAgICAgICAgICAgICAgICAgICAgICAgID0gICAxCmxvY2FsIE1NREJfREFUQV9UWVBFX1VURjhfU1RSSU5HICAgICAgICAgICAgICAgICAgICA9ICAgMgpsb2NhbCBNTURCX0RBVEFfVFlQRV9ET1VCTEUgICAgICAgICAgICAgICAgICAgICAgICAgPSAgIDMKbG9jYWwgTU1EQl9EQVRBX1RZUEVfQllURVMgICAgICAgICAgICAgICAgICAgICAgICAgID0gICA0CmxvY2FsIE1NREJfREFUQV9UWVBFX1VJTlQxNiAgICAgICAgICAgICAgICAgICAgICAgICA9ICAgNQpsb2NhbCBNTURCX0RBVEFfVFlQRV9VSU5UMzIgICAgICAgICAgICAgICAgICAgICAgICAgPSAgIDYKbG9jYWwgTU1EQl9EQVRBX1RZUEVfTUFQICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gICA3CmxvY2FsIE1NREJfREFUQV9UWVBFX0lOVDMyICAgICAgICAgICAgICAgICAgICAgICAgICA9ICAgOApsb2NhbCBNTURCX0RBVEFfVFlQRV9VSU5UNjQgICAgICAgICAgICAgICAgICAgICAgICAgPSAgIDkKbG9jYWwgTU1EQl9EQVRBX1RZUEVfVUlOVDEyOCAgICAgICAgICAgICAgICAgICAgICAgID0gICAxMApsb2NhbCBNTURCX0RBVEFfVFlQRV9BUlJBWSAgICAgICAgICAgICAgICAgICAgICAgICAgPSAgIDExCmxvY2FsIE1NREJfREFUQV9UWVBFX0NPTlRBSU5FUiAgICAgICAgICAgICAgICAgICAgICA9ICAgMTIKbG9jYWwgTU1EQl9EQVRBX1RZUEVfRU5EX01BUktFUiAgICAgICAgICAgICAgICAgICAgID0gICAxMwpsb2NhbCBNTURCX0RBVEFfVFlQRV9CT09MRUFOICAgICAgICAgICAgICAgICAgICAgICAgPSAgIDE0CmxvY2FsIE1NREJfREFUQV9UWVBFX0ZMT0FUICAgICAgICAgICAgICAgICAgICAgICAgICA9ICAgMTUKCi0tIGNvcHkgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vbGlsaWVuMTAxMC9sdWEtcmVzdHktbWF4bWluZGRiL2Jsb2IvZjk2NjMzZTI0MjhmOGY3YmNjMWUyYTdhMjhiNzQ3YjMzMjMzYThkYi9yZXN0eS9tYXhtaW5kZGIubHVhI0wxMzYtTDEzOAotLSB5b3Ugc2hvdWxkIGluc3RhbGwgdGhlIGxpYm1heG1pbmRkYiB0byB5b3VyIHN5c3RlbQotLQotLSDilIDilIAgS1JBRlQgTE9DQUwgTU9ESUZJQ0FUSU9OICh0aGUgb25seSBkZXZpYXRpb24gZnJvbSB1cHN0cmVhbSkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tIFVwc3RyZWFtIGlzIGBmZmkubG9hZCgnbGlibWF4bWluZGRiJylgLCB3aGljaCByZXNvbHZlcyB0aGUgTElOS0VSIG5hbWUKLS0gYGxpYm1heG1pbmRkYi5zb2Ag4oCUIGFuZCB0aGF0IHVudmVyc2lvbmVkIHN5bWxpbmsgc2hpcHMgaW4gdGhlIC1kZXYgcGFja2FnZSwgbm90Ci0tIHRoZSBydW50aW1lIG9uZS4gQWxwaW5lJ3MgYGxpYm1heG1pbmRkYmAgYW5kIERlYmlhbidzIGBsaWJtYXhtaW5kZGIwYCBib3RoIGdpdmUKLS0gb25seSBgbGlibWF4bWluZGRiLnNvLjBgLCBzbyB0aGUgYmFyZSBuYW1lIGZhaWxzIG9uIGEgbm9ybWFsIHJ1bnRpbWUgaW5zdGFsbCBhbmQKLS0gZ2VvIGdvZXMgc2lsZW50bHkgZGFyayAoZ2VvX2NvdW50cnkgcGNhbGxzIHRoaXMgcmVxdWlyZSkuIFRyeSB0aGUgc29uYW1lIHRvbyBzbwotLSB0aGUgcnVudGltZSBwYWNrYWdlIGFsb25lIGlzIGVub3VnaCBvbiBldmVyeSBkaXN0cm8uCmxvY2FsIG1heG0KZG8KICAgIGxvY2FsIGNhbmRpZGF0ZXMgPSB7ICdsaWJtYXhtaW5kZGInLCAnbGlibWF4bWluZGRiLnNvLjAnLCAnbGlibWF4bWluZGRiLnNvJyB9CiAgICBsb2NhbCBsYXN0X2VycgogICAgZm9yIGkgPSAxLCAjY2FuZGlkYXRlcyBkbwogICAgICAgIGxvY2FsIG9rLCBsaWIgPSBwY2FsbChmZmkubG9hZCwgY2FuZGlkYXRlc1tpXSkKICAgICAgICBpZiBvayB0aGVuIG1heG0gPSBsaWI7IGJyZWFrIGVuZAogICAgICAgIGxhc3RfZXJyID0gbGliCiAgICBlbmQKICAgIGlmIG5vdCBtYXhtIHRoZW4KICAgICAgICBlcnJvcignbGlibWF4bWluZGRiIG5vdCBsb2FkYWJsZSAodHJpZWQgJyAuLiB0YWJsZS5jb25jYXQoY2FuZGlkYXRlcywgJywgJykgLi4KICAgICAgICAgICAgICAnKTogJyAuLiB0b3N0cmluZyhsYXN0X2VyciksIDIpCiAgICBlbmQKZW5kCi0taHR0cHM6Ly9naXRodWIuY29tL21heG1pbmQvbGlibWF4bWluZGRiCmxvY2FsIG1tZGIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IGZmaV9uZXcoJ01NREJfcycpCmxvY2FsIGluaXR0ZWQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IGZhbHNlCgpsb2NhbCBmdW5jdGlvbiBtbWRiX3N0cmVycm9yKHJjKQogICAgcmV0dXJuIGZmaV9zdHIobWF4bS5NTURCX3N0cmVycm9yKHJjKSkKZW5kCgpsb2NhbCBmdW5jdGlvbiBnYWlfc3RyZXJyb3IocmMpCiAgICByZXR1cm4gZmZpX3N0cihDLmdhaV9zdHJlcnJvcihyYykpCmVuZAoKZnVuY3Rpb24gX00uaW5pdChkYmZpbGUpCiAgaWYgbm90IGluaXR0ZWQgdGhlbgogICAgbG9jYWwgbWF4bWluZF9yZWFkeSAgID0gbWF4bS5NTURCX29wZW4oZGJmaWxlLDAsbW1kYikKCiAgICBpZiBtYXhtaW5kX3JlYWR5IH49IE1NREJfU1VDQ0VTUyB0aGVuCiAgICAgICAgcmV0dXJuIG5pbCwgbW1kYl9zdHJlcnJvcihtYXhtaW5kX3JlYWR5KQogICAgZW5kCiAgICAKICAgIGluaXR0ZWQgPSB0cnVlCiAgICAKICAgIGZmaV9nYyhtbWRiLCBtYXhtLk1NREJfY2xvc2UpCiAgZW5kCiAgcmV0dXJuIGluaXR0ZWQKZW5kCgpmdW5jdGlvbiBfTS5pbml0dGVkKCkKICAgIHJldHVybiBpbml0dGVkCmVuZAoKLS0gaHR0cHM6Ly9naXRodWIuY29tL21heG1pbmQvbGlibWF4bWluZGRiL2Jsb2IvbWFzdGVyL3NyYy9tYXhtaW5kZGIuYyNMMTkzOCAKLS0gTE9DQUwgTU1EQl9lbnRyeV9kYXRhX2xpc3RfcyAqZHVtcF9lbnRyeV9kYXRhX2xpc3QoIEZJTEUgKnN0cmVhbSwgTU1EQl9lbnRyeV9kYXRhX2xpc3RfcyAqZW50cnlfZGF0YV9saXN0LCBpbnQgaW5kZW50LCBpbnQgKnN0YXR1cykKbG9jYWwgZnVuY3Rpb24gX2R1bXBfZW50cnlfZGF0YV9saXN0KGVudHJ5X2RhdGFfbGlzdCxzdGF0dXMpCgogIGlmIG5vdCBlbnRyeV9kYXRhX2xpc3QgdGhlbgogICAgcmV0dXJuIG5pbCxNTURCX0lOVkFMSURfREFUQV9FUlJPUgogIGVuZAogIAogIGxvY2FsIGVudHJ5X2RhdGFfaXRlbSA9IGVudHJ5X2RhdGFfbGlzdFswXS5lbnRyeV9kYXRhCiAgbG9jYWwgZGF0YV90eXBlID0gZW50cnlfZGF0YV9pdGVtLnR5cGUKICBsb2NhbCBkYXRhX3NpemUgPSBlbnRyeV9kYXRhX2l0ZW0uZGF0YV9zaXplCiAgbG9jYWwgcmVzdWx0CiAgCiAgaWYgZGF0YV90eXBlID09IE1NREJfREFUQV9UWVBFX01BUCB0aGVuCiAgICByZXN1bHQgPSB7fQogICAgCiAgICBsb2NhbCBzaXplID0gZW50cnlfZGF0YV9pdGVtLmRhdGFfc2l6ZQogICAgCiAgICBlbnRyeV9kYXRhX2xpc3QgPSBlbnRyeV9kYXRhX2xpc3RbMF0ubmV4dAogICAgCiAgICB3aGlsZShzaXplID4gMCBhbmQgZW50cnlfZGF0YV9saXN0KQogICAgZG8gCiAgICAgIGVudHJ5X2RhdGFfaXRlbSA9IGVudHJ5X2RhdGFfbGlzdFswXS5lbnRyeV9kYXRhCiAgICAgIGRhdGFfdHlwZSA9IGVudHJ5X2RhdGFfaXRlbS50eXBlCiAgICAgIGRhdGFfc2l6ZSA9IGVudHJ5X2RhdGFfaXRlbS5kYXRhX3NpemUKICAgICAgCiAgICAgIGlmIE1NREJfREFUQV9UWVBFX1VURjhfU1RSSU5HICB+PSBkYXRhX3R5cGUgdGhlbgogICAgICAgIHJldHVybiBuaWwsTU1EQl9JTlZBTElEX0RBVEFfRVJST1IKICAgICAgZW5kCiAgICAgIAogICAgICBsb2NhbCBrZXkgPSBmZmlfc3RyKGVudHJ5X2RhdGFfaXRlbS51dGY4X3N0cmluZyxkYXRhX3NpemUpCgogICAgICBpZiBub3Qga2V5IHRoZW4KICAgICAgICByZXR1cm4gbmlsLE1NREJfT1VUX09GX01FTU9SWV9FUlJPUgogICAgICBlbmQKICAgICAgCiAgICAgIGxvY2FsIHZhbAogICAgICBlbnRyeV9kYXRhX2xpc3QgPSBlbnRyeV9kYXRhX2xpc3RbMF0ubmV4dAogICAgICBlbnRyeV9kYXRhX2xpc3Qsc3RhdHVzLHZhbCA9IF9kdW1wX2VudHJ5X2RhdGFfbGlzdChlbnRyeV9kYXRhX2xpc3QpCiAgICAgIAogICAgICBpZiBzdGF0dXMgfj0gTU1EQl9TVUNDRVNTIHRoZW4KICAgICAgICByZXR1cm4gbmlsLHN0YXR1cwogICAgICBlbmQKCiAgICAgIHJlc3VsdFtrZXldID0gdmFsCiAgICAgIAogICAgICBzaXplID0gc2l6ZSAtMSAKICAgIGVuZAogICAgCgogIGVsc2VpZiBlbnRyeV9kYXRhX2xpc3RbMF0uZW50cnlfZGF0YS50eXBlID09IE1NREJfREFUQV9UWVBFX0FSUkFZIHRoZW4KICAgIGxvY2FsIHNpemUgPSBlbnRyeV9kYXRhX2xpc3RbMF0uZW50cnlfZGF0YS5kYXRhX3NpemUKICAgIHJlc3VsdCA9IHt9CgogICAgZW50cnlfZGF0YV9saXN0ID0gZW50cnlfZGF0YV9saXN0WzBdLm5leHQKICAgIAogICAgbG9jYWwgaSA9IDEKICAgIHdoaWxlKGkgPD0gc2l6ZSBhbmQgZW50cnlfZGF0YV9saXN0KQogICAgZG8KICAgICAgbG9jYWwgdmFsCiAgICAgIGVudHJ5X2RhdGFfbGlzdCxzdGF0dXMsdmFsID0gX2R1bXBfZW50cnlfZGF0YV9saXN0KGVudHJ5X2RhdGFfbGlzdCkKICAgICAgCiAgICAgIGlmIHN0YXR1cyB+PSBNTURCX1NVQ0NFU1MgdGhlbgogICAgICAgIHJldHVybiBuaWwsbmlsLHZhbAogICAgICBlbmQKICAgICAgCiAgICAgIHJlc3VsdFtpXSA9IHZhbAogICAgICBpID0gaSArIDEKICAgIGVuZAoKICAgIAogIGVsc2UKICAgIGVudHJ5X2RhdGFfaXRlbSA9IGVudHJ5X2RhdGFfbGlzdFswXS5lbnRyeV9kYXRhCiAgICBkYXRhX3R5cGUgPSBlbnRyeV9kYXRhX2l0ZW0udHlwZQogICAgZGF0YV9zaXplID0gZW50cnlfZGF0YV9pdGVtLmRhdGFfc2l6ZQogICAgCiAgICBsb2NhbCB2YWwKICAgIC0tIHN0cmluZyB0eXBlICJrZXkiOiJ2YWwiCiAgICAtLSBvdGhlciB0eXBlICJrZXkiOnZhbAogICAgLS0gZGVmYXVsdCBvdGhlciB0eXBlCiAgICBpZiBkYXRhX3R5cGUgPT0gTU1EQl9EQVRBX1RZUEVfVVRGOF9TVFJJTkcgdGhlbgogICAgICB2YWwgPSBmZmlfc3RyKGVudHJ5X2RhdGFfaXRlbS51dGY4X3N0cmluZyxkYXRhX3NpemUpCiAgICAgIGlmIG5vdCB2YWwgdGhlbgogICAgICAgIHN0YXR1cyA9IE1NREJfT1VUX09GX01FTU9SWV9FUlJPUgogICAgICAgIHJldHVybiBuaWwsc3RhdHVzCiAgICAgIGVuZAogICAgZWxzZWlmIGRhdGFfdHlwZSA9PSBNTURCX0RBVEFfVFlQRV9CWVRFUyB0aGVuCiAgICAgIHZhbCA9IGZmaV9zdHIoZmZpX2Nhc3QoJ2NoYXIgKiAnLGVudHJ5X2RhdGFfaXRlbS5ieXRlcyksZGF0YV9zaXplKQogICAgICBpZiBub3QgdmFsIHRoZW4KICAgICAgICBzdGF0dXMgPSBNTURCX09VVF9PRl9NRU1PUllfRVJST1IKICAgICAgICByZXR1cm4gbmlsLHN0YXR1cwogICAgICBlbmQKICAgIGVsc2VpZiBkYXRhX3R5cGUgPT0gTU1EQl9EQVRBX1RZUEVfRE9VQkxFIHRoZW4KICAgICAgdmFsID0gZW50cnlfZGF0YV9pdGVtLmRvdWJsZV92YWx1ZQogICAgZWxzZWlmIGRhdGFfdHlwZSA9PSBNTURCX0RBVEFfVFlQRV9GTE9BVCB0aGVuCiAgICAgIHZhbCA9IGVudHJ5X2RhdGFfaXRlbS5mbG9hdF92YWx1ZQogICAgZWxzZWlmIGRhdGFfdHlwZSA9PSBNTURCX0RBVEFfVFlQRV9VSU5UMTYgdGhlbgogICAgICB2YWwgPSBlbnRyeV9kYXRhX2l0ZW0udWludDE2CiAgICBlbHNlaWYgZGF0YV90eXBlID09IE1NREJfREFUQV9UWVBFX1VJTlQzMiB0aGVuCiAgICAgIHZhbCA9IGVudHJ5X2RhdGFfaXRlbS51aW50MzIKICAgIGVsc2VpZiBkYXRhX3R5cGUgPT0gTU1EQl9EQVRBX1RZUEVfQk9PTEVBTiB0aGVuCiAgICAgIHZhbCA9IGVudHJ5X2RhdGFfaXRlbS5ib29sZWFuCiAgICBlbHNlaWYgZGF0YV90eXBlID09IE1NREJfREFUQV9UWVBFX1VJTlQ2NCB0aGVuCiAgICAgIHZhbCA9IGVudHJ5X2RhdGFfaXRlbS51aW50NjQKICAgIGVsc2VpZiBkYXRhX3R5cGUgPT0gTU1EQl9EQVRBX1RZUEVfSU5UMzIgdGhlbgogICAgICB2YWwgPSBlbnRyeV9kYXRhX2l0ZW0uaW50MzIKICAgIGVsc2UKICAgICAgcmV0dXJuIG5pbCxNTURCX0lOVkFMSURfREFUQV9FUlJPUgogICAgZW5kCiAgICAKICAgIHJlc3VsdCA9IHZhbAogICAgZW50cnlfZGF0YV9saXN0ID0gZW50cnlfZGF0YV9saXN0WzBdLm5leHQKICBlbmQKCiAgc3RhdHVzID0gTU1EQl9TVUNDRVNTCiAgcmV0dXJuIGVudHJ5X2RhdGFfbGlzdCxzdGF0dXMscmVzdWx0CmVuZAoKZnVuY3Rpb24gX00ubG9va3VwKGlwKQoKICBpZiBub3QgaW5pdHRlZCB0aGVuCiAgICAgIHJldHVybiBuaWwsICJub3QgaW5pdGlhbGl6ZWQiCiAgZW5kCiAgCiAgLS0gY29weSBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9saWxpZW4xMDEwL2x1YS1yZXN0eS1tYXhtaW5kZGIvYmxvYi9mOTY2MzNlMjQyOGY4ZjdiY2MxZTJhN2EyOGI3NDdiMzMyMzNhOGRiL3Jlc3R5L21heG1pbmRkYi5sdWEjTDE1OS1MMTc2CiAgbG9jYWwgZ2FpX2Vycm9yID0gZmZpX25ldygnaW50WzFdJykKICBsb2NhbCBtbWRiX2Vycm9yID0gZmZpX25ldygnaW50WzFdJykKCiAgbG9jYWwgcmVzdWx0ID0gbWF4bS5NTURCX2xvb2t1cF9zdHJpbmcobW1kYixpcCxnYWlfZXJyb3IsbW1kYl9lcnJvcikKCiAgaWYgbW1kYl9lcnJvclswXSB+PSBNTURCX1NVQ0NFU1MgdGhlbgogICAgcmV0dXJuIG5pbCwnbG9va3VwIGZhaWxlZDogJyAuLiBtbWRiX3N0cmVycm9yKG1tZGJfZXJyb3JbMF0pCiAgZW5kCgogIGlmIGdhaV9lcnJvclswXSB+PSBNTURCX1NVQ0NFU1MgdGhlbgogICAgcmV0dXJuIG5pbCwnbG9va3VwIGZhaWxlZDogJyAuLiBnYWlfc3RyZXJyb3IoZ2FpX2Vycm9yWzBdKQogIGVuZAoKICBpZiB0cnVlIH49IHJlc3VsdC5mb3VuZF9lbnRyeSB0aGVuCiAgICByZXR1cm4gbmlsLCdub3QgZm91bmQnCiAgZW5kCgogIGxvY2FsIGVudHJ5X2RhdGFfbGlzdCA9IGZmaV9jYXN0KCdNTURCX2VudHJ5X2RhdGFfbGlzdF9zICoqY29uc3QnLGZmaV9uZXcoIk1NREJfZW50cnlfZGF0YV9saXN0X3MiKSkKCiAgbG9jYWwgc3RhdHVzID0gbWF4bS5NTURCX2dldF9lbnRyeV9kYXRhX2xpc3QocmVzdWx0LmVudHJ5LGVudHJ5X2RhdGFfbGlzdCkKCiAgaWYgc3RhdHVzIH49IE1NREJfU1VDQ0VTUyB0aGVuCiAgICByZXR1cm4gbmlsLCdnZXQgZW50cnkgZGF0YSBmYWlsZWQ6ICcgLi4gbW1kYl9zdHJlcnJvcihzdGF0dXMpCiAgZW5kICAKICAKICBsb2NhbCBoZWFkID0gZW50cnlfZGF0YV9saXN0WzBdIC0tIFNhdmUgc28gdGhpcyBjYW4gYmUgcGFzc2VkIHRvIGZyZWUgZm4uCiAgbG9jYWwgXyxzdGF0dXMscmVzdWx0ID0gX2R1bXBfZW50cnlfZGF0YV9saXN0KGVudHJ5X2RhdGFfbGlzdCkKICBtYXhtLk1NREJfZnJlZV9lbnRyeV9kYXRhX2xpc3QoaGVhZCkKICAKICBpZiBzdGF0dXMgfj0gTU1EQl9TVUNDRVNTIHRoZW4KICAgIHJldHVybiBuaWwsJ2R1bXAgZW50cnkgZGF0YSBmYWlsZWQ6ICcgLi4gbW1kYl9zdHJlcnJvcihzdGF0dXMpCiAgZW5kCiAgCiAgCiAgcmV0dXJuIHJlc3VsdAplbmQKCi0tIGNvcHkgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vbGlsaWVuMTAxMC9sdWEtcmVzdHktbWF4bWluZGRiL2Jsb2IvbWFzdGVyL3Jlc3R5L21heG1pbmRkYi5sdWEjTDIwOAotLSBodHRwczovL3d3dy5tYXhtaW5kLmNvbS9lbi9nZW9pcDItZGF0YWJhc2VzICB5b3Ugc2hvdWxkIGRvd25sb2FkICB0aGUgbW1kYiBmaWxlIGZyb20gbWF4bWluZAogCnJldHVybiBfTTsK",
|
|
36
|
+
"mgmt_api.lua": "LS0gbWdtdF9hcGkubHVhCi0tIFJFU1QgYW5hbHl0aWNzIGVuZHBvaW50cyBiYWNrZWQgYnkgbmd4LnNoYXJlZC5kaWN0LgotLSBJbnRlcm5hbCBtYW5hZ2VtZW50IHBvcnQgb25seSAoMTI3LjAuMC4xOjkxNDUpLgoKbG9jYWwgY2pzb24gPSByZXF1aXJlICJjanNvbi5zYWZlIgoKbG9jYWwgYW5hbHl0aWNzICAgID0gbmd4LnNoYXJlZC5hbmFseXRpY3MKbG9jYWwgcmVxdWVzdF9kYXRhID0gbmd4LnNoYXJlZC5yZXF1ZXN0X2RhdGEKbG9jYWwgdXJpICAgICAgICAgID0gbmd4LnZhci51cmkKCmxvY2FsIGZ1bmN0aW9uIGpzb24oZGF0YSwgY29kZSkKICAgIG5neC5zdGF0dXMgPSBjb2RlIG9yIDIwMAogICAgbmd4LmhlYWRlclsiQ29udGVudC1UeXBlIl0gPSAiYXBwbGljYXRpb24vanNvbiIKICAgIG5neC5zYXkoY2pzb24uZW5jb2RlKGRhdGEpKQogICAgcmV0dXJuIG5neC5leGl0KG5neC5zdGF0dXMpCmVuZAoKbG9jYWwgZnVuY3Rpb24gYmFkKG1zZykKICAgIHJldHVybiBqc29uKHsgZXJyb3IgPSBtc2cgfSwgNDAwKQplbmQKCi0tIOKUgOKUgCBHRVQgL2hlYWx0aCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKLS0gQmFyZSAib2siLCBOT1QgSlNPTi4gcHJvYmVNZ210KCkgaW4gYXBwcy9hcGkvc3JjL2xpYi9wcm9qZWN0LWFuYWx5dGljcy50cwotLSBhc3NlcnRzIGBib2R5LnRyaW0oKSA9PT0gIm9rImAsIHNvIGFueXRoaW5nIHJpY2hlciBoZXJlIHNpbGVudGx5IHJlcG9ydHMgZXZlcnkKLS0gZWRnZSBhcyB1bnJlYWNoYWJsZSBhbmQgc3RvcHMgdGhlIGFuYWx5dGljcyBzY3JhcGUuIFJpY2hlciBkaWFnbm9zdGljcyBnbyBvbgotLSAvc3RhdHVzIGJlbG93LgoKaWYgdXJpID09ICIvaGVhbHRoIiB0aGVuCiAgICBuZ3guc2F5KCJvayIpCiAgICByZXR1cm4gbmd4LmV4aXQoMjAwKQplbmQKCi0tIOKUgOKUgCBHRVQgL3N0YXR1cyAtIGRpYWdub3NhYmxlIGVkZ2UgaGVhbHRoIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAotLSBXaHkgdGhpcyBleGlzdHM6IGdlbyBmYWlsaW5nIGlzIElOVklTSUJMRSBvdGhlcndpc2UuIGdlb19jb3VudHJ5Lmx1YSBwY2FsbHMgaXRzCi0tIEZGSSBiaW5kaW5nIGFuZCByZXR1cm5zIG5pbCBvbiBmYWlsdXJlLCBzbyBhIG1pc3NpbmcgbGlibWF4bWluZGRiLnNvIG9yIGEKLS0gbWlzc2luZyBkYXRhYmFzZSBwcmVzZW50cyBleGFjdGx5IGxpa2UgIm5vYm9keSB2aXNpdGVkIGZyb20gYSBrbm93biBjb3VudHJ5IiDigJQKLS0gYW4gZW1wdHkgbWFwIHdpdGggbm8gZXJyb3IgYW55d2hlcmUuIFRoaXMgcmVwb3J0cyB3aGljaCBpdCBpcy4KLS0KLS0gQWxzbyByZXBvcnRzIHNoYXJlZC1kaWN0IGhlYWRyb29tOiB0aGVzZSB6b25lcyBMUlUtRVZJQ1Qgd2hlbiBmdWxsIHJhdGhlciB0aGFuCi0tIGVycm9yaW5nLCBzbyBhIGZ1bGwgYHZpc2l0b3JzYCB6b25lIHNpbGVudGx5IFVOREVSQ09VTlRTLiBDYWxsZXJzIHN1cmZhY2UgdGhhdAotLSBhcyAiYXBwcm94aW1hdGUiIGluc3RlYWQgb2YgcHJlc2VudGluZyBhbiBldmljdGlvbiBhcnRpZmFjdCBhcyBhIG1lYXN1cmVtZW50LgoKaWYgdXJpID09ICIvc3RhdHVzIiB0aGVuCiAgICBsb2NhbCBnZW9fYXZhaWxhYmxlLCBnZW9fcmVhc29uLCBnZW9fZGIgPSBmYWxzZSwgImdlb19jb3VudHJ5IG1vZHVsZSBub3QgbG9hZGFibGUiLCBuaWwKICAgIGxvY2FsIGdlb19vaywgZ2VvID0gcGNhbGwocmVxdWlyZSwgImtyYWZ0Lmdlb19jb3VudHJ5IikKICAgIGlmIGdlb19vayBhbmQgZ2VvIGFuZCBnZW8uc3RhdHVzIHRoZW4KICAgICAgICBnZW9fYXZhaWxhYmxlLCBnZW9fcmVhc29uLCBnZW9fZGIgPSBnZW8uc3RhdHVzKCkKICAgIGVuZAoKICAgIGxvY2FsIGRpY3RzID0ge30KICAgIGZvciBfLCBuYW1lIGluIGlwYWlycyh7ICJhbmFseXRpY3MiLCAicmVxdWVzdF9kYXRhIiwgInJ1bGVzIiwgInJsX2NvdW50ZXJzIiwgInZpc2l0b3JzIiB9KSBkbwogICAgICAgIGxvY2FsIGQgPSBuZ3guc2hhcmVkW25hbWVdCiAgICAgICAgaWYgZCB0aGVuCiAgICAgICAgICAgIGRpY3RzW25hbWVdID0gewogICAgICAgICAgICAgICAgY2FwYWNpdHkgICA9IGQuY2FwYWNpdHkgYW5kIGQ6Y2FwYWNpdHkoKSBvciBuaWwsCiAgICAgICAgICAgICAgICBmcmVlX3NwYWNlID0gZC5mcmVlX3NwYWNlIGFuZCBkOmZyZWVfc3BhY2UoKSBvciBuaWwsCiAgICAgICAgICAgIH0KICAgICAgICBlbmQKICAgIGVuZAoKICAgIHJldHVybiBqc29uKHsKICAgICAgICBvayAgPSB0cnVlLAogICAgICAgIGdlbyA9IHsgYXZhaWxhYmxlID0gZ2VvX2F2YWlsYWJsZSwgcmVhc29uID0gZ2VvX3JlYXNvbiwgZGIgPSBnZW9fZGIgfSwKICAgICAgICBkaWN0cyA9IGRpY3RzLAogICAgfSkKZW5kCgotLSDilIDilIAgL3J1bGVzIC0gcGVyLXJvdXRlIHJ1bGVzIGNhY2hlICh3cml0dGVuIGJ5IHRoZSBBUEksIHJlYWQgYnkgcnVsZXNfZ3VhcmQpIOKUgOKUgAotLSBQT1NUIC9ydWxlcyAgYm9keTogeyAiaG9zdCI6ICIuLi4iLCAicnVsZXMiOiBbIHsgInBhdGhQcmVmaXgiOiAiLyIsICJzcGVjIjogey4uLn0gfSBdIH0KLS0gICDihpIgcmVwbGFjZXMgdGhlIHJ1bGVzZXQgZm9yIHRoYXQgaG9zdCBpbiB0aGUgYHJ1bGVzYCBzaGFyZWQgZGljdCAocmVsb2FkLWZyZWUpLgotLSAgIEFuIGVtcHR5L2Fic2VudCBgcnVsZXNgIGFycmF5IGNsZWFycyB0aGUgaG9zdC4KLS0gR0VUICAvcnVsZXM/aG9zdD0uLi4gICDihpIgdGhlIHN0b3JlZCBydWxlc2V0IChkZWJ1ZykuCi0tIERFTEVURSAvcnVsZXM/aG9zdD0uLi4g4oaSIGNsZWFyIHRoZSBob3N0J3MgcnVsZXNldC4KLS0gSGFuZGxlZCBCRUZPUkUgdGhlIGFuYWx5dGljcyBndWFyZDogcnVsZXMgdXNlIHRoZWlyIG93biBkaWN0LgotLSDilIDilIAgL2FuYWx5dGljcy9jb25maWcgLSBwZXItaG9zdCBjb2xsZWN0aW9uIHN3aXRjaGVzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAotLQotLSBQT1NUIGJvZHk6IHsgImhvc3RzIjogWyB7ICJob3N0IjogIi4uLiIsICJwYXRocyI6IHRydWV8ZmFsc2UgfSwgLi4uIF0gfQotLSBHRVQgID9ob3N0PS4uLiAg4oaSIHsgaG9zdCwgcGF0aHMgfQotLQotLSBBIExJU1QsIG5vdCBhIHNpbmdsZSBob3N0OiBhIHNoYXJlZCBkaWN0IGlzIFJBTSwgc28gYSBmdWxsIG5naW54IHJlc3RhcnQgKGEgcmVib290LCBhCi0tIGBkb2NrZXIgcmVzdGFydGAsIGEgcGFja2FnZSB1cGdyYWRlKSBlbXB0aWVzIGl0IGFuZCBldmVyeSBob3N0IG9uIHRoZSBib3ggaGFzIHRvIGJlCi0tIHJlLXNldCBhdCBvbmNlLiBgb3BlbnJlc3R5IC1zIHJlbG9hZGAgcHJlc2VydmVzIHRoZSB6b25lIOKAlCB2ZXJpZmllZCDigJQgc28gb25seSBhIHJlYWwKLS0gcmVzdGFydCBsb3NlcyBpdCwgd2hpY2ggaXMgd2h5IHRoZSByZWNvbmNpbGUgYmVsb3cgZXhpc3RzIGFuZCB3aHkgaXQgbmVlZHMgdG8gY29zdCBvbmUKLS0gcm91bmQgdHJpcCBwZXIgc2VydmVyIHJhdGhlciB0aGFuIG9uZSBwZXIgZG9tYWluLgotLQotLSBMaXZlcyBpbiB0aGUgYHJ1bGVzYCB6b25lIHJhdGhlciB0aGFuIGBhbmFseXRpY3NgIGZvciB0aGUgcmVhc29uIHNpdGVfbG9nZ2VyIHN0YXRlczoKLS0gdGhlIGFuYWx5dGljcyB6b25lIGlzIGEgMjU2IE1CIGNodXJuIG9mIGNvdW50ZXJzIHVuZGVyIExSVSBwcmVzc3VyZSwgYW5kIGFuIGV2aWN0ZWQKLS0gY29uZmlnIGZsYWcgd291bGQgc2lsZW50bHkgY2hhbmdlIHdoYXQgaXMgY29sbGVjdGVkLiBUaGlzIHpvbmUgaG9sZHMgYSBmZXcgc21hbGwgdmFsdWVzLgotLQotLSBEZWxpYmVyYXRlbHkgaXRzIG93biBlbmRwb2ludCByYXRoZXIgdGhhbiBhIGZpZWxkIG9uIC9ydWxlczogdGhlIEFQSSBvbmx5IHB1c2hlcyAvcnVsZXMKLS0gZm9yIGhvc3RzIHRoYXQgSEFWRSBydWxlcywgc28gYSBwcm9qZWN0IHdpdGggbm9uZSB3b3VsZCBuZXZlciByZWNlaXZlIHRoaXMgZmxhZy4KLS0KLS0gTm8gVFRMIOKAlCBhIHNoYXJlZCBkaWN0IGlzIFJBTSBhbmQgaXMgbG9zdCBvbiByZXN0YXJ0IGVpdGhlciB3YXksIHNvIHRoZSBBUEkgcmUtcHVzaGVzIG9uCi0tIGV2ZXJ5IHJvdXRlIGFwcGx5IGFuZCB0aGUgZGF0YWJhc2Ugc3RheXMgdGhlIHNvdXJjZSBvZiB0cnV0aC4KaWYgdXJpID09ICIvYW5hbHl0aWNzL2NvbmZpZyIgdGhlbgogICAgbG9jYWwgcnVsZXMgPSBuZ3guc2hhcmVkLnJ1bGVzCiAgICBpZiBub3QgcnVsZXMgdGhlbiByZXR1cm4ganNvbih7IGVycm9yID0gInJ1bGVzIGRpY3QgdW5hdmFpbGFibGUiIH0sIDUwMykgZW5kCiAgICBsb2NhbCBtZXRob2QgPSBuZ3gucmVxLmdldF9tZXRob2QoKQoKICAgIGlmIG1ldGhvZCA9PSAiR0VUIiB0aGVuCiAgICAgICAgbG9jYWwgaG9zdCA9IG5neC52YXIuYXJnX2hvc3QKICAgICAgICBpZiBub3QgaG9zdCBvciBob3N0ID09ICIiIHRoZW4gcmV0dXJuIGJhZCgibWlzc2luZyA/aG9zdD0iKSBlbmQKICAgICAgICBob3N0ID0gaG9zdDpsb3dlcigpCiAgICAgICAgcmV0dXJuIGpzb24oeyBob3N0ID0gaG9zdCwgcGF0aHMgPSBydWxlczpnZXQoImNmZzoiIC4uIGhvc3QgLi4gIjpwYXRocyIpID09IDEgfSkKICAgIGVuZAoKICAgIGlmIG1ldGhvZCA9PSAiUE9TVCIgdGhlbgogICAgICAgIG5neC5yZXEucmVhZF9ib2R5KCkKICAgICAgICBsb2NhbCBib2R5ID0gbmd4LnJlcS5nZXRfYm9keV9kYXRhKCkKICAgICAgICBpZiBub3QgYm9keSB0aGVuIHJldHVybiBiYWQoImVtcHR5IGJvZHkiKSBlbmQKICAgICAgICBsb2NhbCBwYXlsb2FkID0gY2pzb24uZGVjb2RlKGJvZHkpCiAgICAgICAgaWYgdHlwZShwYXlsb2FkKSB+PSAidGFibGUiIG9yIHR5cGUocGF5bG9hZC5ob3N0cykgfj0gInRhYmxlIiB0aGVuCiAgICAgICAgICAgIHJldHVybiBiYWQoImV4cGVjdGVkIHsgaG9zdHM6IFsgeyBob3N0LCBwYXRocyB9IF0gfSIpCiAgICAgICAgZW5kCiAgICAgICAgbG9jYWwgYXBwbGllZCA9IDAKICAgICAgICBmb3IgXywgZW50cnkgaW4gaXBhaXJzKHBheWxvYWQuaG9zdHMpIGRvCiAgICAgICAgICAgIGlmIHR5cGUoZW50cnkpID09ICJ0YWJsZSIgYW5kIGVudHJ5Lmhvc3QgdGhlbgogICAgICAgICAgICAgICAgbG9jYWwga2V5ID0gImNmZzoiIC4uIHRvc3RyaW5nKGVudHJ5Lmhvc3QpOmxvd2VyKCkgLi4gIjpwYXRocyIKICAgICAgICAgICAgICAgIGlmIGVudHJ5LnBhdGhzID09IHRydWUgdGhlbgogICAgICAgICAgICAgICAgICAgIHJ1bGVzOnNldChrZXksIDEpCiAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgLS0gRGVsZXRlZCByYXRoZXIgdGhhbiBzZXQgdG8gMCwgc28gImFic2VudCIgaXMgdGhlIG9ubHkgb2ZmIHN0YXRlIHRoZXJlCiAgICAgICAgICAgICAgICAgICAgLS0gaXMuIFR3byByZXByZXNlbnRhdGlvbnMgb2Ygb2ZmIGlzIGhvdyBhIHJlYWRlciBlbmRzIHVwIHRyZWF0aW5nIG9uZSBvZgogICAgICAgICAgICAgICAgICAgIC0tIHRoZW0gYXMgb24g4oCUIGFuZCBhYnNlbnQgaXMgYWxzbyB3aGF0IGEgcmVzdGFydGVkIGJveCBzdGFydHMgZnJvbSwgc28KICAgICAgICAgICAgICAgICAgICAtLSBvZmYgaGFzIHRvIG1lYW4gZXhhY3RseSB0aGUgc2FtZSB0aGluZyBpbiBib3RoIGNhc2VzLgogICAgICAgICAgICAgICAgICAgIHJ1bGVzOmRlbGV0ZShrZXkpCiAgICAgICAgICAgICAgICBlbmQKICAgICAgICAgICAgICAgIGFwcGxpZWQgPSBhcHBsaWVkICsgMQogICAgICAgICAgICBlbmQKICAgICAgICBlbmQKICAgICAgICByZXR1cm4ganNvbih7IG9rID0gdHJ1ZSwgYXBwbGllZCA9IGFwcGxpZWQgfSkKICAgIGVuZAoKICAgIHJldHVybiBqc29uKHsgZXJyb3IgPSAibWV0aG9kIG5vdCBhbGxvd2VkIiB9LCA0MDUpCmVuZAoKaWYgdXJpID09ICIvcnVsZXMiIHRoZW4KICAgIGxvY2FsIHJ1bGVzID0gbmd4LnNoYXJlZC5ydWxlcwogICAgaWYgbm90IHJ1bGVzIHRoZW4gcmV0dXJuIGpzb24oeyBlcnJvciA9ICJydWxlcyBkaWN0IHVuYXZhaWxhYmxlIiB9LCA1MDMpIGVuZAogICAgbG9jYWwgbWV0aG9kID0gbmd4LnJlcS5nZXRfbWV0aG9kKCkKCiAgICBpZiBtZXRob2QgPT0gIkdFVCIgdGhlbgogICAgICAgIGxvY2FsIGhvc3QgPSBuZ3gudmFyLmFyZ19ob3N0CiAgICAgICAgaWYgbm90IGhvc3Qgb3IgaG9zdCA9PSAiIiB0aGVuIHJldHVybiBiYWQoIm1pc3NpbmcgP2hvc3Q9IikgZW5kCiAgICAgICAgaG9zdCA9IGhvc3Q6bG93ZXIoKQogICAgICAgIGxvY2FsIHJhdyA9IHJ1bGVzOmdldChob3N0KQogICAgICAgIHJldHVybiBqc29uKHsgaG9zdCA9IGhvc3QsIHJ1bGVzID0gcmF3IGFuZCBjanNvbi5kZWNvZGUocmF3KSBvciB7fSB9KQogICAgZW5kCgogICAgaWYgbWV0aG9kID09ICJERUxFVEUiIHRoZW4KICAgICAgICBsb2NhbCBob3N0ID0gbmd4LnZhci5hcmdfaG9zdAogICAgICAgIGlmIG5vdCBob3N0IG9yIGhvc3QgPT0gIiIgdGhlbiByZXR1cm4gYmFkKCJtaXNzaW5nID9ob3N0PSIpIGVuZAogICAgICAgIHJ1bGVzOmRlbGV0ZShob3N0Omxvd2VyKCkpCiAgICAgICAgcmV0dXJuIGpzb24oeyBvayA9IHRydWUgfSkKICAgIGVuZAoKICAgIGlmIG1ldGhvZCA9PSAiUE9TVCIgdGhlbgogICAgICAgIG5neC5yZXEucmVhZF9ib2R5KCkKICAgICAgICBsb2NhbCBib2R5ID0gbmd4LnJlcS5nZXRfYm9keV9kYXRhKCkKICAgICAgICBpZiBub3QgYm9keSB0aGVuIHJldHVybiBiYWQoImVtcHR5IGJvZHkiKSBlbmQKICAgICAgICBsb2NhbCBwYXlsb2FkID0gY2pzb24uZGVjb2RlKGJvZHkpCiAgICAgICAgaWYgdHlwZShwYXlsb2FkKSB+PSAidGFibGUiIG9yIG5vdCBwYXlsb2FkLmhvc3QgdGhlbgogICAgICAgICAgICByZXR1cm4gYmFkKCJleHBlY3RlZCB7IGhvc3QsIHJ1bGVzOiBbLi4uXSB9IikKICAgICAgICBlbmQKICAgICAgICBsb2NhbCBob3N0ID0gdG9zdHJpbmcocGF5bG9hZC5ob3N0KTpsb3dlcigpCiAgICAgICAgbG9jYWwgbGlzdCA9IHBheWxvYWQucnVsZXMKICAgICAgICBpZiB0eXBlKGxpc3QpIH49ICJ0YWJsZSIgb3IgI2xpc3QgPT0gMCB0aGVuCiAgICAgICAgICAgIHJ1bGVzOmRlbGV0ZShob3N0KSAgICAgICAgICAgICAgICAgLS0gZW1wdHkgc2V0ID0gY2xlYXIgdGhlIGhvc3QKICAgICAgICAgICAgcmV0dXJuIGpzb24oeyBvayA9IHRydWUsIGhvc3QgPSBob3N0LCBjb3VudCA9IDAgfSkKICAgICAgICBlbmQKICAgICAgICBsb2NhbCBvaywgZXJyID0gcnVsZXM6c2V0KGhvc3QsIGNqc29uLmVuY29kZShsaXN0KSkKICAgICAgICBpZiBub3Qgb2sgdGhlbiByZXR1cm4ganNvbih7IGVycm9yID0gInNldCBmYWlsZWQ6ICIgLi4gKGVyciBvciAiPyIpIH0sIDUwMCkgZW5kCiAgICAgICAgcmV0dXJuIGpzb24oeyBvayA9IHRydWUsIGhvc3QgPSBob3N0LCBjb3VudCA9ICNsaXN0IH0pCiAgICBlbmQKCiAgICByZXR1cm4ganNvbih7IGVycm9yID0gIm1ldGhvZCBub3QgYWxsb3dlZCIgfSwgNDA1KQplbmQKCmlmIG5vdCBhbmFseXRpY3MgdGhlbgogICAgcmV0dXJuIGpzb24oeyBlcnJvciA9ICJhbmFseXRpY3MgZGljdCB1bmF2YWlsYWJsZSIgfSwgNTAzKQplbmQKCi0tIOKUgOKUgCBQZXItbWludXRlIGNvdW50cnkgaW5kZXgg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tCi0tIHNpdGVfbG9nZ2VyIHdyaXRlcyBvbmUga2V5IHBlciAoZG9tYWluLCBtaW51dGUsIGNvdW50cnkpOiBgYzp7ZG9tYWlufTp7bWlufTp7Q0N9YC4KLS0gUmVhZGluZyB0aGVtIGJhY2sgbmVlZHMga2V5IERJU0NPVkVSWSwgYW5kIGBnZXRfa2V5c2AgaXMgdGhlIG9ubHkgbWVjaGFuaXNtLgotLQotLSBUaGlzIHVzZWQgdG8gc2l0IElOU0lERSB0aGUgcGVyLW1pbnV0ZSBsb29wLCBzbyBhIDI0aCB3aW5kb3cgcmFuIHVwIHRvIDE0NDAKLS0gYGdldF9rZXlzKDEwMDAwKWAgY2FsbHMg4oCUIGVhY2ggYSBmdWxsIHNjYW4gb2YgYSAyNTYgTUIgem9uZSwgZWFjaCBob2xkaW5nIHRoZQotLSBkaWN0IGxvY2sgYWdhaW5zdCBldmVyeSB3b3JrZXIuIE9uZSBzY2FuIHBlciByZXF1ZXN0IGluc3RlYWQsIGJ1Y2tldGVkIGJ5Ci0tIG1pbnV0ZSBpbiBhIHNpbmdsZSBwYXNzOyB0aGUgbG9vcCB0aGVuIGRvZXMgcGxhaW4gdGFibGUgbG9va3Vwcy4KLS0KLS0gYGdldF9rZXlzKDApYCAoYWxsIGtleXMpIHJhdGhlciB0aGFuIDEwMDAwOiB0aGUgY2FwIHNpbGVudGx5IFRSVU5DQVRFRCwgc28gYQotLSBidXN5IGJveCBqdXN0IGxvc3QgY291bnRyaWVzIHdpdGggbm8gZXJyb3IuIFVuYm91bmRlZCBpcyBzYWZlIHByZWNpc2VseSBiZWNhdXNlCi0tIHRoaXMgaXMgbm93IGNhbGxlZCBvbmNlIOKAlCBzZWUgdGhlIGNvbW1lbnQgb24gdGhlIGNhbGwuCi0tLSBSZWFkIGFuIGVudW1lcmFibGUgc2V0IHdyaXR0ZW4gYnkgc2l0ZV9sb2dnZXIncyBpbmRleF9hZGQuCi0tCi0tIFJlcGxhY2VzIGBnZXRfa2V5c2AsIHdoaWNoIHdhbGtlZCBFVkVSWSBrZXkgaW4gdGhlIDI1NiBNQiB6b25lIGhvbGRpbmcgaXRzIGxvY2sg4oCUIGNvc3QKLS0gcHJvcG9ydGlvbmFsIHRvIHpvbmUgcG9wdWxhdGlvbiByYXRoZXIgdGhhbiB0byB0aGUgYW5zd2VyLCBvbiBhIHBhdGggY2FsbGVkIGZvdXIKLS0gZGlmZmVyZW50IHdheXMuIEhlcmUgdGhlIGNvdW50ZXIgc2F5cyBob3cgbWFueSBtZW1iZXJzIGV4aXN0IGFuZCB0aGUgc2xvdHMgbmFtZSB0aGVtLCBzbwotLSBhIHJlYWQgY29zdHMgZXhhY3RseSBhcyBtdWNoIGFzIHRoZSBkYXRhIGl0IHJldHVybnMuCi0tCi0tIE92ZXItcmVhZHMgc2xpZ2h0bHkgYnkgZGVzaWduOiBhIHNsb3QgY2FuIGJlIHdyaXR0ZW4gdHdpY2UgaWYgdHdvIHdvcmtlcnMgcmFjZSBvbiBhCi0tIG1lbWJlcidzIGZpcnN0IHNpZ2h0aW5nLCBhbmQgc2xvdHMgb3V0bGl2ZSBub3RoaW5nIChzYW1lIFRUTCBhcyB0aGVpciBjb3VudGVycykuIEJvdGgKLS0gY29sbGFwc2UgaGFybWxlc3NseSBiZWNhdXNlIHRoZSBjYWxsZXIga2V5cyByZXN1bHRzIGJ5IG1lbWJlci4KbG9jYWwgZnVuY3Rpb24gcmVhZF9pbmRleChjb3VudGVyX2tleSwgc2xvdF9wcmVmaXgpCiAgICBsb2NhbCBuID0gdG9udW1iZXIoYW5hbHl0aWNzOmdldChjb3VudGVyX2tleSkpIG9yIDAKICAgIGlmIG4gPD0gMCB0aGVuIHJldHVybiB7fSBlbmQKICAgIGxvY2FsIG91dCwgc2VlbiA9IHt9LCB7fQogICAgZm9yIGkgPSAxLCBuIGRvCiAgICAgICAgbG9jYWwgbSA9IGFuYWx5dGljczpnZXQoc2xvdF9wcmVmaXggLi4gaSkKICAgICAgICBpZiBtIGFuZCBub3Qgc2VlblttXSB0aGVuCiAgICAgICAgICAgIHNlZW5bbV0gPSB0cnVlCiAgICAgICAgICAgIG91dFsjb3V0ICsgMV0gPSBtCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJldHVybiBvdXQKZW5kCgotLS0gRHJhaW4gYSBjb3VudGVyIFdJVEhPVVQgbG9zaW5nIGEgY29uY3VycmVudCBpbmNyZW1lbnQuCi0tCi0tIFdhcyBgZ2V0YCB0aGVuIGBkZWxldGVgOiBhIHJlcXVlc3QgbGFuZGluZyBiZXR3ZWVuIHRoZSB0d28gaGFkIGl0cyBjb3VudCBkZWxldGVkIGFsb25nCi0tIHdpdGggdGhlIHZhbHVlIHRoYXQgaGFkIGp1c3QgYmVlbiByZWFkLiBTdWJ0cmFjdGluZyBleGFjdGx5IHdoYXQgd2FzIHJlYWQgbGVhdmVzIGFueQotLSBjb25jdXJyZW50IGluY3JlbWVudCBiZWhpbmQgYXMgYSByZXNpZHVhbCB0aGUgbmV4dCBzY3JhcGUgY29sbGVjdHMuCmxvY2FsIGZ1bmN0aW9uIGRyYWluKGtleSkKICAgIGxvY2FsIHYgPSB0b251bWJlcihhbmFseXRpY3M6Z2V0KGtleSkpIG9yIDAKICAgIGlmIHYgfj0gMCB0aGVuIGFuYWx5dGljczppbmNyKGtleSwgLXYpIGVuZAogICAgcmV0dXJuIHYKZW5kCgotLS0gT25lIGRheSdzIHJvbGx1cCBmb3Igb25lIGRvbWFpbiwgcmVhZCB0aHJvdWdoIGl0cyBpbmRleGVzLgotLQotLSBSZXR1cm5zIHRoZSBzYW1lIGBzdWZmaXgg4oaSIHZhbHVlYCBzaGFwZSB0aGUgb2xkIHdob2xlLXpvbmUgY2xhc3NpZmllciBwcm9kdWNlZCwgc28gYm90aAotLSBjYWxsZXJzIHN0YXllZCB1bmNoYW5nZWQ6IGJhcmUgY291bnRyeSBjb2RlcywgYHM6e2NvZGV9YCwgYHA6e3BhdGh9YCwgYHZgLCBgcG5gLgpsb2NhbCBmdW5jdGlvbiByZWFkX3JvbGx1cChkb21haW4sIGRheSkKICAgIGxvY2FsIGdwZnggPSAiZzoiIC4uIGRvbWFpbiAuLiAiOiIgLi4gZGF5IC4uICI6IgogICAgbG9jYWwgb3V0ID0ge30KCiAgICBmb3IgXywgY2MgaW4gaXBhaXJzKHJlYWRfaW5kZXgoZ3BmeCAuLiAiY24iLCBncGZ4IC4uICJjaToiKSkgZG8KICAgICAgICBvdXRbY2NdID0gdG9udW1iZXIoYW5hbHl0aWNzOmdldChncGZ4IC4uIGNjKSkgb3IgMAogICAgZW5kCiAgICBmb3IgXywgY29kZSBpbiBpcGFpcnMocmVhZF9pbmRleChncGZ4IC4uICJzbiIsIGdwZnggLi4gInNpOiIpKSBkbwogICAgICAgIG91dFsiczoiIC4uIGNvZGVdID0gdG9udW1iZXIoYW5hbHl0aWNzOmdldChncGZ4IC4uICJzOiIgLi4gY29kZSkpIG9yIDAKICAgIGVuZAogICAgLS0gYHBuYCBkb3VibGVzIGFzIHRoZSBwYXRoIGluZGV4J3MgY291bnRlciwgc28gcGF0aHMgbmVlZCBubyBzZXBhcmF0ZSBvbmUuIFdoZW4gcGF0aAogICAgLS0gY29sbGVjdGlvbiBpcyBzd2l0Y2hlZCBvZmYgZm9yIHRoaXMgaG9zdCB0aGVyZSBpcyBubyBjb3VudGVyIGFuZCB0aGlzIHJlYWRzIG5vdGhpbmcuCiAgICBmb3IgXywgcGF0aCBpbiBpcGFpcnMocmVhZF9pbmRleChncGZ4IC4uICJwbiIsIGdwZnggLi4gInBpOiIpKSBkbwogICAgICAgIG91dFsicDoiIC4uIHBhdGhdID0gdG9udW1iZXIoYW5hbHl0aWNzOmdldChncGZ4IC4uICJwOiIgLi4gcGF0aCkpIG9yIDAKICAgIGVuZAogICAgLS0gVGhlIG92ZXItY2FwIGJ1Y2tldCBoYXMgYSBmaXhlZCBuYW1lLCBzbyBpdCBpcyBub3QgaW4gdGhlIGluZGV4LgogICAgbG9jYWwgb3RoZXIgPSB0b251bWJlcihhbmFseXRpY3M6Z2V0KGdwZnggLi4gInA6b3RoZXIiKSkKICAgIGlmIG90aGVyIHRoZW4gb3V0WyJwOm90aGVyIl0gPSBvdGhlciBlbmQKCiAgICBsb2NhbCB2ID0gdG9udW1iZXIoYW5hbHl0aWNzOmdldChncGZ4IC4uICJ2IikpCiAgICBpZiB2IHRoZW4gb3V0WyJ2Il0gPSB2IGVuZAogICAgcmV0dXJuIG91dAplbmQKCmxvY2FsIGZ1bmN0aW9uIHNjYW5fY291bnRyeV9pbmRleChkb21haW4sIGZyb21fbSwgdG9fbSkKICAgIC0tIFdhbGtzIHRoZSByZXF1ZXN0ZWQgTUlOVVRFUyBhbmQgcmVhZHMgZWFjaCBvbmUncyBvd24gaW5kZXguIEJvdW5kZWQgYnkgdGhlIHdpbmRvdwogICAgLS0gKGNhcHBlZCBhdCAxNDQwIGJ5IHRoZSBjYWxsZXIpLCBub3QgYnkgaG93IG11Y2ggaXMgaW4gdGhlIHpvbmUuCiAgICBsb2NhbCBieV9taW51dGUgPSB7fQogICAgZm9yIG0gPSBmcm9tX20sIHRvX20gZG8KICAgICAgICBsb2NhbCBtcGZ4ID0gImM6IiAuLiBkb21haW4gLi4gIjoiIC4uIG0gLi4gIjoiCiAgICAgICAgbG9jYWwgY2NzID0gcmVhZF9pbmRleChtcGZ4IC4uICJuIiwgbXBmeCAuLiAiaToiKQogICAgICAgIGlmICNjY3MgPiAwIHRoZW4KICAgICAgICAgICAgbG9jYWwgc2xvdCA9IHt9CiAgICAgICAgICAgIGZvciBpID0gMSwgI2NjcyBkbwogICAgICAgICAgICAgICAgLS0gRnVsbCBrZXksIGJlY2F1c2UgdGhlIGZsdXNoIGRyYWlucyBieSBrZXkuCiAgICAgICAgICAgICAgICBzbG90W2Njc1tpXV0gPSBtcGZ4IC4uIGNjc1tpXQogICAgICAgICAgICBlbmQKICAgICAgICAgICAgYnlfbWludXRlW21dID0gc2xvdAogICAgICAgIGVuZAogICAgZW5kCiAgICByZXR1cm4gYnlfbWludXRlCmVuZAoKLS0tIFNwbGl0IGEgbmFtZXNwYWNlZCBhbmFseXRpY3Mga2V5IGludG8ga2luZCAvIGRvbWFpbiAvIG1pZCAvIHJlc3QuCi0tCi0tIExheW91dHM6IGBjOntkb21haW59OnttaW51dGV9OntDQ31gIGFuZCBgZzp7ZG9tYWlufTp7ZGF5fTp7c3VmZml4fWAuCi0tIFBvc2l0aW9uYWwsIE5PVCBhIGZ1bGwgc3BsaXQgb24gIjoiLCBiZWNhdXNlIGBzdWZmaXhgIGxlZ2l0aW1hdGVseSBjb250YWlucwotLSBjb2xvbnMg4oCUIGEgbm9ybWFsaXplZCBwYXRoIGtleSBsb29rcyBsaWtlIGBnOnguY29tOjIwMjYwODAzOnA6L3VzZXJzLzppZGAuCi0tIEhvc3RuYW1lcyBjYW5ub3QgY29udGFpbiAiOiIsIHNvIHRoZSBmaXJzdCB0aHJlZSBzZXBhcmF0b3JzIGFyZSB1bmFtYmlndW91cy4KbG9jYWwgZnVuY3Rpb24gc3BsaXRfa2V5KGspCiAgICBsb2NhbCBwMSA9IGs6ZmluZCgiOiIsIDEsIHRydWUpCiAgICBpZiBub3QgcDEgdGhlbiByZXR1cm4gbmlsIGVuZAogICAgbG9jYWwgcDIgPSBrOmZpbmQoIjoiLCBwMSArIDEsIHRydWUpCiAgICBpZiBub3QgcDIgdGhlbiByZXR1cm4gbmlsIGVuZAogICAgbG9jYWwgcDMgPSBrOmZpbmQoIjoiLCBwMiArIDEsIHRydWUpCiAgICBpZiBub3QgcDMgdGhlbgogICAgICAgIHJldHVybiBrOnN1YigxLCBwMSAtIDEpLCBrOnN1YihwMSArIDEsIHAyIC0gMSksIGs6c3ViKHAyICsgMSksIG5pbAogICAgZW5kCiAgICByZXR1cm4gazpzdWIoMSwgcDEgLSAxKSwgazpzdWIocDEgKyAxLCBwMiAtIDEpLCBrOnN1YihwMiArIDEsIHAzIC0gMSksIGs6c3ViKHAzICsgMSkKZW5kCgotLS0gUmVhZCBvbmUgbWludXRlJ3MgY291bnRyeSBjb3VudHMgb3V0IG9mIGEgc2Nhbm5lZCBpbmRleC4KLS0gQHBhcmFtIHNsb3QgdGFibGV8bmlsICBDQyDihpIgZnVsbCBkaWN0IGtleSwgZnJvbSBzY2FuX2NvdW50cnlfaW5kZXgKLS0gQHBhcmFtIGRlbCBib29sZWFuICAgICBkcmFpbiBlYWNoIGtleSBhZnRlciByZWFkaW5nIChmbHVzaCBzZW1hbnRpY3MpCi0tIEByZXR1cm4gdGFibGV8bmlsIGNvdW50cywgb3IgbmlsIHdoZW4gdGhlIG1pbnV0ZSBoYWQgbm8gY291bnRyeSBkYXRhCmxvY2FsIGZ1bmN0aW9uIHJlYWRfbWludXRlX2NvdW50cmllcyhzbG90LCBkZWwpCiAgICBpZiBub3Qgc2xvdCB0aGVuIHJldHVybiBuaWwgZW5kCiAgICBsb2NhbCBjb3VudHMsIGFueSA9IHt9LCBmYWxzZQogICAgZm9yIGNjLCBrZXkgaW4gcGFpcnMoc2xvdCkgZG8KICAgICAgICAtLSBgZHJhaW5gIHN1YnRyYWN0cyB3aGF0IGl0IHJlYWQgaW5zdGVhZCBvZiBkZWxldGluZywgc28gYSByZXF1ZXN0IGFycml2aW5nCiAgICAgICAgLS0gbWlkLWZsdXNoIGlzIG5vdCB0aHJvd24gYXdheSB3aXRoIHRoZSB2YWx1ZSB0aGF0IHdhcyBqdXN0IHJlYWQuCiAgICAgICAgY291bnRzW2NjXSA9IGRlbCBhbmQgZHJhaW4oa2V5KSBvciAodG9udW1iZXIoYW5hbHl0aWNzOmdldChrZXkpKSBvciAwKQogICAgICAgIGFueSA9IHRydWUKICAgIGVuZAogICAgcmV0dXJuIGFueSBhbmQgY291bnRzIG9yIG5pbAplbmQKCi0tIOKUgOKUgCBQT1NUIC9hbmFseXRpY3MvY29sbGVjdCAtIHRoZSBTQ1JBUEVSJ3MgZW5kcG9pbnQ6IGV2ZXJ5IGRvbWFpbiwgT05FIHNjYW4g4pSA4pSACi0tCi0tIEJvZHk6IHsgImRheSI6ICJZWVlZTU1ERCIsICJkb21haW5zIjogWyB7ICJkb21haW4iOiAieC5jb20iLCAiZnJvbSI6IE0sICJ0byI6IE0gfSBdIH0KLS0gUmV0dXJuczogeyAiZG9tYWlucyI6IHsgInguY29tIjogeyBidWNrZXRzOiBbLi4uXSwgZmx1c2hlZDogTiwgcm9sbHVwOiB7Li4ufSB9IH0gfQotLQotLSBXaHkgdGhpcyBleGlzdHMgcmF0aGVyIHRoYW4gbG9vcGluZyB0aGUgc2luZ2xlLWRvbWFpbiBlbmRwb2ludHM6Ci0tCi0tIGBnZXRfa2V5c2AgaXMgdGhlIG9ubHkga2V5LWRpc2NvdmVyeSBtZWNoYW5pc20gYSBzaGFyZWQgZGljdCBvZmZlcnMsIGl0IHdhbGtzIHRoZQotLSBXSE9MRSB6b25lLCBhbmQgaXQgaG9sZHMgdGhlIGRpY3QgbG9jayBhZ2FpbnN0IGV2ZXJ5IG5naW54IHdvcmtlciB3aGlsZSBpdCBkb2VzLgotLSBUaGUgc2NyYXBlciBuZWVkcyBib3RoIHRoZSBwZXItbWludXRlIGNvdW50cmllcyAoZmx1c2gpIGFuZCB0aGUgZGFpbHkgcm9sbHVwIGZvcgotLSBlYWNoIGRvbWFpbiwgc28gY2FsbGluZyB0aGUgcGVyLWRvbWFpbiBlbmRwb2ludHMgY29zdCAyTisxIHVuYm91bmRlZCBzY2FucyBvZiBhCi0tIDI1NiBNQiB6b25lIOKAlCBwbHVzIDJOKzEgU1NIL2V4ZWMgcm91bmQgdHJpcHMg4oCUIGV2ZXJ5IHN3ZWVwLiBPbiBhIDUwLWRvbWFpbiBib3gKLS0gdGhhdCBpcyAxMDEgZnVsbCBzY2FucyBhbmQgMTAxIHJvdW5kIHRyaXBzLCBvbiBhIHNjaGVkdWxlLCB0byBjb2xsZWN0IGRhdGEgdGhhdAotLSBvbmUgcGFzcyBhbHJlYWR5IGhhcyBpbiBoYW5kLgotLQotLSBTbzogb25lIGBnZXRfa2V5cygwKWAsIGNsYXNzaWZ5IGV2ZXJ5IGtleSBieSAoa2luZCwgZG9tYWluKSBpbiBhIHNpbmdsZSBwYXNzLCB0aGVuCi0tIHNlcnZlIGFsbCBkb21haW5zIGZyb20gdGhlIGluLW1lbW9yeSBpbmRleC4gMk4rMSBzY2FucyDihpIgMSwgYW5kIDJOKzEgcm91bmQgdHJpcHMKLS0g4oaSIDEuIFRoZSBwZXItZG9tYWluIEdFVCBlbmRwb2ludHMgc3RheSBmb3IgdGhlIFJFQUQgcGF0aCwgd2hlcmUgYSBwYWdlIHZpZXcgd2FudHMKLS0gb25lIGRvbWFpbidzIGxpdmUgdGFpbCBhbmQgYSBzaW5nbGUgc2NhbiBpcyB0aGUgaG9uZXN0IGNvc3QuCi0tCi0tIEZsdXNoIHNlbWFudGljcyBhcmUgdW5jaGFuZ2VkIGFuZCBzdGlsbCBhdG9taWMgcGVyIGtleTogbWludXRlIGNvdW50ZXJzIGFuZCB0aGVpcgotLSBjb3VudHJ5IGtleXMgYXJlIGRlbGV0ZWQgYXMgdGhleSBhcmUgcmVhZCwgc28gYSBidWNrZXQgaXMgaGFuZGVkIHRvIGV4YWN0bHkgb25lCi0tIGNhbGxlciBubyBtYXR0ZXIgaG93IG1hbnkgY29sbGVjdG9ycyByYWNlLiBUaGUgZGFpbHkgcm9sbHVwIGlzIHJlYWQtb25seSDigJQgdGhlCi0tIGVkZ2Uga2VlcHMgcnVubmluZyB0b3RhbHMgZm9yIHRoZSBkYXksIGFuZCBkZWxldGluZyB0aGVtIHdvdWxkIGxvc2UgdGhlIHRvdGFscyBmb3IKLS0gZXZlcnkgbGF0ZXIgc2NyYXBlIG9mIHRoZSBzYW1lIGRheS4KCmlmIHVyaSA9PSAiL2FuYWx5dGljcy9jb2xsZWN0IiBhbmQgbmd4LnJlcS5nZXRfbWV0aG9kKCkgPT0gIlBPU1QiIHRoZW4KICAgIG5neC5yZXEucmVhZF9ib2R5KCkKICAgIGxvY2FsIGJvZHkgPSBuZ3gucmVxLmdldF9ib2R5X2RhdGEoKQogICAgaWYgbm90IGJvZHkgdGhlbiByZXR1cm4gYmFkKCJlbXB0eSBib2R5IikgZW5kCiAgICBsb2NhbCBwYXlsb2FkID0gY2pzb24uZGVjb2RlKGJvZHkpCiAgICBpZiB0eXBlKHBheWxvYWQpIH49ICJ0YWJsZSIgb3IgdHlwZShwYXlsb2FkLmRvbWFpbnMpIH49ICJ0YWJsZSIgdGhlbgogICAgICAgIHJldHVybiBiYWQoJ2V4cGVjdGVkIHsgZGF5LCBkb21haW5zOiBbe2RvbWFpbiwgZnJvbSwgdG99XSB9JykKICAgIGVuZAoKICAgIGxvY2FsIGRheSA9IHBheWxvYWQuZGF5CiAgICBpZiB0eXBlKGRheSkgfj0gInN0cmluZyIgb3IgI2RheSB+PSA4IHRoZW4gZGF5ID0gb3MuZGF0ZSgiISVZJW0lZCIpIGVuZAoKICAgIC0tIFJlcXVlc3RlZCBkb21haW5zIOKGkiB0aGVpciBtaW51dGUgd2luZG93LiBBbHNvIHRoZSBtZW1iZXJzaGlwIHRlc3QgdGhlIHNjYW4KICAgIC0tIHVzZXMsIHNvIGFuIHVucmVxdWVzdGVkIGRvbWFpbidzIGtleXMgYXJlIHNraXBwZWQgd2l0aG91dCBhIHN0cmluZyBjb21wYXJlCiAgICAtLSBwZXIgZG9tYWluLgogICAgbG9jYWwgd2FudCwgb3JkZXIgPSB7fSwge30KICAgIGZvciBpID0gMSwgI3BheWxvYWQuZG9tYWlucyBkbwogICAgICAgIGxvY2FsIGQgPSBwYXlsb2FkLmRvbWFpbnNbaV0KICAgICAgICBpZiB0eXBlKGQpID09ICJ0YWJsZSIgYW5kIHR5cGUoZC5kb21haW4pID09ICJzdHJpbmciIGFuZCBkLmRvbWFpbiB+PSAiIiB0aGVuCiAgICAgICAgICAgIGxvY2FsIG5hbWUgPSBkLmRvbWFpbjpsb3dlcigpCiAgICAgICAgICAgIGxvY2FsIGZyb21fbSwgdG9fbSA9IHRvbnVtYmVyKGQuZnJvbSksIHRvbnVtYmVyKGQudG8pCiAgICAgICAgICAgIGlmIGZyb21fbSBhbmQgdG9fbSB0aGVuCiAgICAgICAgICAgICAgICBpZiB0b19tIC0gZnJvbV9tID4gMTQ0MCB0aGVuIHRvX20gPSBmcm9tX20gKyAxNDQwIGVuZCAtLSBjYXAgYXQgMjRoCiAgICAgICAgICAgICAgICBpZiBub3Qgd2FudFtuYW1lXSB0aGVuIG9yZGVyWyNvcmRlciArIDFdID0gbmFtZSBlbmQKICAgICAgICAgICAgICAgIHdhbnRbbmFtZV0gPSB7IGZyb20gPSBmcm9tX20sIHRvID0gdG9fbSB9CiAgICAgICAgICAgIGVuZAogICAgICAgIGVuZAogICAgZW5kCiAgICBpZiAjb3JkZXIgPT0gMCB0aGVuIHJldHVybiBqc29uKHsgZG9tYWlucyA9IHt9IH0pIGVuZAoKICAgIC0tIOKUgOKUgCBQZXItZG9tYWluIGluZGV4IHJlYWRzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAogICAgLS0KICAgIC0tIFdhcyBhIHNpbmdsZSBgZ2V0X2tleXMoMClgIHBhc3MgY2xhc3NpZnlpbmcgZXZlcnkga2V5IGluIHRoZSB6b25lLiBPbmUgc2NhbiBpcyBiZXR0ZXIKICAgIC0tIHRoYW4gMk4rMSwgYnV0IGl0IHN0aWxsIHdhbGtlZCBrZXlzIGJlbG9uZ2luZyB0byBkb21haW5zIG5vYm9keSBhc2tlZCBhYm91dCwgYW5kIGhlbGQKICAgIC0tIHRoZSB6b25lIGxvY2sgd2hpbGUgZG9pbmcgaXQuIE5vdyBlYWNoIHJlcXVlc3RlZCBkb21haW4gcmVhZHMgb25seSBpdHMgb3duIGluZGV4ZXMuCiAgICBsb2NhbCBjb3VudHJpZXMgPSB7fSAgIC0tIGRvbWFpbiDihpIgbWludXRlIOKGkiBDQyDihpIgZGljdCBrZXkKICAgIGxvY2FsIHJvbGx1cHMgPSB7fSAgICAgLS0gZG9tYWluIOKGkiBzdWZmaXgg4oaSIHZhbHVlCiAgICBmb3IgaSA9IDEsICNvcmRlciBkbwogICAgICAgIGxvY2FsIGRvbWFpbiA9IG9yZGVyW2ldCiAgICAgICAgbG9jYWwgdyA9IHdhbnRbZG9tYWluXQogICAgICAgIGNvdW50cmllc1tkb21haW5dID0gc2Nhbl9jb3VudHJ5X2luZGV4KGRvbWFpbiwgdy5mcm9tLCB3LnRvKQogICAgICAgIHJvbGx1cHNbZG9tYWluXSA9IHJlYWRfcm9sbHVwKGRvbWFpbiwgZGF5KQogICAgZW5kCgogICAgLS0g4pSA4pSAIFNlcnZlIGVhY2ggZG9tYWluIGZyb20gdGhlIGluZGV4IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAogICAgbG9jYWwgb3V0ID0ge30KICAgIGZvciBpID0gMSwgI29yZGVyIGRvCiAgICAgICAgbG9jYWwgZG9tYWluID0gb3JkZXJbaV0KICAgICAgICBsb2NhbCB3ID0gd2FudFtkb21haW5dCiAgICAgICAgbG9jYWwgY2lkeCA9IGNvdW50cmllc1tkb21haW5dIG9yIHt9CgogICAgICAgIGxvY2FsIGJ1Y2tldHMsIGZsdXNoZWQgPSB7fSwgMAogICAgICAgIGZvciBtID0gdy5mcm9tLCB3LnRvIGRvCiAgICAgICAgICAgIGxvY2FsIHAgPSAiczoiIC4uIGRvbWFpbiAuLiAiOiIgLi4gbQogICAgICAgICAgICAtLSBEcmFpbiBGSVJTVCwgdGhlbiBkZWNpZGU6IGBkcmFpbmAgcmV0dXJucyB3aGF0IGl0IHRvb2ssIGFuZCBhIGNvdW50ZXIgbGVmdAogICAgICAgICAgICAtLSBhdCAwIGJ5IGFuIGVhcmxpZXIgZmx1c2ggbXVzdCBub3QgZW1pdCBhIGJ1Y2tldCBvZiB6ZXJvcy4gKFplcm8gaXMgdHJ1dGh5IGluCiAgICAgICAgICAgIC0tIEx1YSwgc28gdGhlIG9sZCBgaWYgciB0aGVuYCB3b3VsZCBoYXZlIHN0YXJ0ZWQgZG9pbmcgZXhhY3RseSB0aGF0IHRoZSBtb21lbnQKICAgICAgICAgICAgLS0ga2V5cyBzdG9wcGVkIGJlaW5nIGRlbGV0ZWQuKQogICAgICAgICAgICBsb2NhbCByID0gZHJhaW4ocCAuLiAiOnIiKQogICAgICAgICAgICBpZiByID4gMCB0aGVuCiAgICAgICAgICAgICAgICBsb2NhbCBydF91cyA9IGRyYWluKHAgLi4gIjp0IikKICAgICAgICAgICAgICAgIGJ1Y2tldHNbI2J1Y2tldHMgKyAxXSA9IHsKICAgICAgICAgICAgICAgICAgICBtaW51dGUgICAgICAgICAgPSBtLAogICAgICAgICAgICAgICAgICAgIHJlcXVlc3RzICAgICAgICA9IHIsCiAgICAgICAgICAgICAgICAgICAgdW5pcXVlX3JlcXVlc3RzID0gZHJhaW4ocCAuLiAiOnUiKSwKICAgICAgICAgICAgICAgICAgICBiYW5kd2lkdGhfaW4gICAgPSBkcmFpbihwIC4uICI6aSIpLAogICAgICAgICAgICAgICAgICAgIGJhbmR3aWR0aF9vdXQgICA9IGRyYWluKHAgLi4gIjpvIiksCiAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2VfdGltZSAgID0gcnRfdXMgLyAxMDAwMDAwLAogICAgICAgICAgICAgICAgICAgIGNvdW50cmllcyAgICAgICA9IHJlYWRfbWludXRlX2NvdW50cmllcyhjaWR4W21dLCB0cnVlKSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZsdXNoZWQgPSBmbHVzaGVkICsgMQogICAgICAgICAgICBlbmQKICAgICAgICBlbmQKCiAgICAgICAgLS0gRGFpbHkgcm9sbHVwLCBzYW1lIGtleSBjbGFzc2lmaWNhdGlvbiB0aGUgc2luZ2xlLWRvbWFpbiBlbmRwb2ludCB1c2VzLgogICAgICAgIGxvY2FsIGdlbywgcGF0aHMsIHN0YXR1c2VzLCB2aXNpdG9ycyA9IHt9LCB7fSwge30sIDAKICAgICAgICBmb3Igc3VmZml4LCB2IGluIHBhaXJzKHJvbGx1cHNbZG9tYWluXSBvciB7fSkgZG8KICAgICAgICAgICAgaWYgc3VmZml4ID09ICJ2IiB0aGVuCiAgICAgICAgICAgICAgICB2aXNpdG9ycyA9IHYKICAgICAgICAgICAgZWxzZWlmIHN1ZmZpeDpzdWIoMSwgMikgPT0gInA6IiB0aGVuCiAgICAgICAgICAgICAgICBwYXRoc1tzdWZmaXg6c3ViKDMpXSA9IHYKICAgICAgICAgICAgZWxzZWlmIHN1ZmZpeDpzdWIoMSwgMikgPT0gInM6IiB0aGVuCiAgICAgICAgICAgICAgICBzdGF0dXNlc1tzdWZmaXg6c3ViKDMpXSA9IHYKICAgICAgICAgICAgZWxzZWlmIHN1ZmZpeDptYXRjaCgiXiV1JXUkIikgdGhlbgogICAgICAgICAgICAgICAgZ2VvW3N1ZmZpeF0gPSB2CiAgICAgICAgICAgIGVuZAogICAgICAgICAgICAtLSBBbnl0aGluZyBlbHNlIChgcG5gKSBpcyBib29ra2VlcGluZzogbmV2ZXIgcmVwb3J0ZWQgYXMgYSBjb3VudHJ5LgogICAgICAgIGVuZAoKICAgICAgICBvdXRbZG9tYWluXSA9IHsKICAgICAgICAgICAgYnVja2V0cyA9IGJ1Y2tldHMsCiAgICAgICAgICAgIGZsdXNoZWQgPSBmbHVzaGVkLAogICAgICAgICAgICByb2xsdXAgID0gewogICAgICAgICAgICAgICAgZGF5ID0gZGF5LCBjb3VudHJpZXMgPSBnZW8sIHZpc2l0b3JzID0gdmlzaXRvcnMsCiAgICAgICAgICAgICAgICBwYXRocyA9IHBhdGhzLCBzdGF0dXNlcyA9IHN0YXR1c2VzLAogICAgICAgICAgICB9LAogICAgICAgIH0KICAgIGVuZAoKICAgIHJldHVybiBqc29uKHsgZGF5ID0gZGF5LCBkb21haW5zID0gb3V0IH0pCmVuZAoKLS0g4pSA4pSAIEdFVCAvYW5hbHl0aWNzIC0gbWludXRlLWJ1Y2tldCB0aW1lIHNlcmllcyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKLS0gP2RvbWFpbj1leGFtcGxlLmNvbSZmcm9tPUVQT0NIX01JTiZ0bz1FUE9DSF9NSU4KCmlmIHVyaSA9PSAiL2FuYWx5dGljcyIgdGhlbgogICAgbG9jYWwgZG9tYWluID0gbmd4LnZhci5hcmdfZG9tYWluCiAgICBpZiBub3QgZG9tYWluIG9yIGRvbWFpbiA9PSAiIiB0aGVuIHJldHVybiBiYWQoIm1pc3NpbmcgP2RvbWFpbj0iKSBlbmQKICAgIGRvbWFpbiA9IGRvbWFpbjpsb3dlcigpCgogICAgbG9jYWwgZnJvbV9tID0gdG9udW1iZXIobmd4LnZhci5hcmdfZnJvbSkKICAgIGxvY2FsIHRvX20gICA9IHRvbnVtYmVyKG5neC52YXIuYXJnX3RvKQogICAgaWYgbm90IGZyb21fbSBvciBub3QgdG9fbSB0aGVuCiAgICAgICAgcmV0dXJuIGJhZCgibWlzc2luZyA/ZnJvbT0gYW5kID90bz0gKGVwb2NoIG1pbnV0ZXMpIikKICAgIGVuZAogICAgLS0gQ2FwIGF0IDI0aAogICAgaWYgdG9fbSAtIGZyb21fbSA+IDE0NDAgdGhlbiB0b19tID0gZnJvbV9tICsgMTQ0MCBlbmQKCiAgICAtLSBPTkUgc2NhbiBmb3IgdGhlIHdob2xlIHdpbmRvdyAoc2VlIHNjYW5fY291bnRyeV9pbmRleCkuCiAgICBsb2NhbCBjb3VudHJ5X2luZGV4ID0gc2Nhbl9jb3VudHJ5X2luZGV4KGRvbWFpbiwgZnJvbV9tLCB0b19tKQoKICAgIGxvY2FsIGJ1Y2tldHMgPSB7fQogICAgZm9yIG0gPSBmcm9tX20sIHRvX20gZG8KICAgICAgICBsb2NhbCBwID0gInM6IiAuLiBkb21haW4gLi4gIjoiIC4uIG0KICAgICAgICBsb2NhbCByID0gYW5hbHl0aWNzOmdldChwIC4uICI6ciIpCiAgICAgICAgaWYgciB0aGVuCiAgICAgICAgICAgIC0tIFJlc3BvbnNlIHRpbWUgc3RvcmVkIGFzIG1pY3Jvc2Vjb25kcywgY29udmVydCB0byBzZWNvbmRzIChmbG9hdCkKICAgICAgICAgICAgbG9jYWwgcnRfdXMgPSBhbmFseXRpY3M6Z2V0KHAgLi4gIjp0Iikgb3IgMAogICAgICAgICAgICBidWNrZXRzWyNidWNrZXRzICsgMV0gPSB7CiAgICAgICAgICAgICAgICBtaW51dGUgICAgICAgICAgID0gbSwKICAgICAgICAgICAgICAgIHJlcXVlc3RzICAgICAgICAgPSByLAogICAgICAgICAgICAgICAgdW5pcXVlX3JlcXVlc3RzICA9IGFuYWx5dGljczpnZXQocCAuLiAiOnUiKSBvciAwLAogICAgICAgICAgICAgICAgYmFuZHdpZHRoX2luICAgICA9IGFuYWx5dGljczpnZXQocCAuLiAiOmkiKSBvciAwLAogICAgICAgICAgICAgICAgYmFuZHdpZHRoX291dCAgICA9IGFuYWx5dGljczpnZXQocCAuLiAiOm8iKSBvciAwLAogICAgICAgICAgICAgICAgcmVzcG9uc2VfdGltZSAgICA9IHJ0X3VzIC8gMTAwMDAwMCwKICAgICAgICAgICAgICAgIGNvdW50cmllcyAgICAgICAgPSByZWFkX21pbnV0ZV9jb3VudHJpZXMoY291bnRyeV9pbmRleFttXSwgZmFsc2UpLAogICAgICAgICAgICB9CiAgICAgICAgZW5kCiAgICBlbmQKCiAgICByZXR1cm4ganNvbih7IGRvbWFpbiA9IGRvbWFpbiwgYnVja2V0cyA9IGJ1Y2tldHMgfSkKZW5kCgotLSDilIDilIAgUE9TVCAvYW5hbHl0aWNzL2ZsdXNoIC0gcmVhZCArIGRlbGV0ZSBtaW51dGUgYnVja2V0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKLS0gU2FtZSBhcyBHRVQgL2FuYWx5dGljcyBidXQgZGVsZXRlcyB0aGUgcmV0dXJuZWQgYnVja2V0cyBmcm9tIHNoYXJlZCBtZW1vcnkuCi0tIFVzZWQgYnkgdGhlIHNjcmFwZXIgdG8gYXRvbWljYWxseSBtb3ZlIGRhdGEgZnJvbSBPcGVuUmVzdHkg4oaSIERCLgotLSA/ZG9tYWluPWV4YW1wbGUuY29tJmZyb209RVBPQ0hfTUlOJnRvPUVQT0NIX01JTgoKaWYgdXJpID09ICIvYW5hbHl0aWNzL2ZsdXNoIiBhbmQgbmd4LnJlcS5nZXRfbWV0aG9kKCkgPT0gIlBPU1QiIHRoZW4KICAgIGxvY2FsIGRvbWFpbiA9IG5neC52YXIuYXJnX2RvbWFpbgogICAgaWYgbm90IGRvbWFpbiBvciBkb21haW4gPT0gIiIgdGhlbiByZXR1cm4gYmFkKCJtaXNzaW5nID9kb21haW49IikgZW5kCiAgICBkb21haW4gPSBkb21haW46bG93ZXIoKQoKICAgIGxvY2FsIGZyb21fbSA9IHRvbnVtYmVyKG5neC52YXIuYXJnX2Zyb20pCiAgICBsb2NhbCB0b19tICAgPSB0b251bWJlcihuZ3gudmFyLmFyZ190bykKICAgIGlmIG5vdCBmcm9tX20gb3Igbm90IHRvX20gdGhlbgogICAgICAgIHJldHVybiBiYWQoIm1pc3NpbmcgP2Zyb209IGFuZCA/dG89IChlcG9jaCBtaW51dGVzKSIpCiAgICBlbmQKICAgIGlmIHRvX20gLSBmcm9tX20gPiAxNDQwIHRoZW4gdG9fbSA9IGZyb21fbSArIDE0NDAgZW5kCgogICAgLS0gT05FIHNjYW4gZm9yIHRoZSB3aG9sZSB3aW5kb3cgKHNlZSBzY2FuX2NvdW50cnlfaW5kZXgpLgogICAgbG9jYWwgY291bnRyeV9pbmRleCA9IHNjYW5fY291bnRyeV9pbmRleChkb21haW4sIGZyb21fbSwgdG9fbSkKCiAgICBsb2NhbCBidWNrZXRzID0ge30KICAgIGxvY2FsIGZsdXNoZWQgPSAwCiAgICBmb3IgbSA9IGZyb21fbSwgdG9fbSBkbwogICAgICAgIGxvY2FsIHAgPSAiczoiIC4uIGRvbWFpbiAuLiAiOiIgLi4gbQogICAgICAgIC0tIERyYWluLCBkb24ndCBkZWxldGUg4oCUIHNlZSBgZHJhaW5gLiBBIGNvdW50ZXIgYWxyZWFkeSBhdCAwIGlzIG5vdCBhIGJ1Y2tldC4KICAgICAgICBsb2NhbCByID0gZHJhaW4ocCAuLiAiOnIiKQogICAgICAgIGlmIHIgPiAwIHRoZW4KICAgICAgICAgICAgbG9jYWwgcnRfdXMgPSBkcmFpbihwIC4uICI6dCIpCiAgICAgICAgICAgIGJ1Y2tldHNbI2J1Y2tldHMgKyAxXSA9IHsKICAgICAgICAgICAgICAgIG1pbnV0ZSAgICAgICAgICAgPSBtLAogICAgICAgICAgICAgICAgcmVxdWVzdHMgICAgICAgICA9IHIsCiAgICAgICAgICAgICAgICB1bmlxdWVfcmVxdWVzdHMgID0gZHJhaW4ocCAuLiAiOnUiKSwKICAgICAgICAgICAgICAgIGJhbmR3aWR0aF9pbiAgICAgPSBkcmFpbihwIC4uICI6aSIpLAogICAgICAgICAgICAgICAgYmFuZHdpZHRoX291dCAgICA9IGRyYWluKHAgLi4gIjpvIiksCiAgICAgICAgICAgICAgICByZXNwb25zZV90aW1lICAgID0gcnRfdXMgLyAxMDAwMDAwLAogICAgICAgICAgICAgICAgLS0gRHJhaW5lZCB0b286IHRoaXMgZW5kcG9pbnQgaGFuZHMgdGhlIG1pbnV0ZSB0byB0aGUgREIsIHNvIHRoZSBjb3VudHJ5CiAgICAgICAgICAgICAgICAtLSBrZXlzIG11c3QgZ28gd2l0aCBpdCBvciB0aGV5IHdvdWxkIGJlIGNvdW50ZWQgdHdpY2UuCiAgICAgICAgICAgICAgICBjb3VudHJpZXMgICAgICAgID0gcmVhZF9taW51dGVfY291bnRyaWVzKGNvdW50cnlfaW5kZXhbbV0sIHRydWUpLAogICAgICAgICAgICB9CiAgICAgICAgICAgIGZsdXNoZWQgPSBmbHVzaGVkICsgMQogICAgICAgIGVuZAogICAgZW5kCgogICAgcmV0dXJuIGpzb24oeyBkb21haW4gPSBkb21haW4sIGJ1Y2tldHMgPSBidWNrZXRzLCBmbHVzaGVkID0gZmx1c2hlZCB9KQplbmQKCi0tIOKUgOKUgCBHRVQgL2FuYWx5dGljcy90b3RhbHMgLSBsaWZldGltZSBjb3VudGVycyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKLS0gP2RvbWFpbj1leGFtcGxlLmNvbSAgICAgIOKGkiBzaW5nbGUgZG9tYWluCi0tIChubyBkb21haW4pICAgICAgICAgICAgICDihpIgYWxsIGtub3duIGRvbWFpbnMKCmlmIHVyaSA9PSAiL2FuYWx5dGljcy90b3RhbHMiIHRoZW4KICAgIGxvY2FsIGRvbWFpbiA9IG5neC52YXIuYXJnX2RvbWFpbgoKICAgIGlmIG5vdCBkb21haW4gb3IgZG9tYWluID09ICIiIHRoZW4KICAgICAgICAtLSBUaGUgc2NyYXBlcidzIGRvbWFpbi1kaXNjb3ZlcnkgY2FsbC4gUmVhZCBmcm9tIHRoZSBgZG5gL2BkaTpgIGluZGV4IHRoYXQKICAgICAgICAtLSBzaXRlX2xvZ2dlciBhcHBlbmRzIHRvIHRoZSBmaXJzdCB0aW1lIGl0IGV2ZXIgc2VlcyBhIGhvc3QsIHNvIHRoaXMgbm8gbG9uZ2VyCiAgICAgICAgLS0gd2Fsa3MgdGhlIHpvbmUuIEl0IHdhcyB0aGUgd29yc3QgcGxhY2UgZm9yIGEgc2NhbjogYSBjYXAgaGVyZSBzaWxlbnRseSBkcm9wcGVkCiAgICAgICAgLS0gd2hvbGUgZG9tYWlucyBmcm9tIGV2ZXJ5IHN1YnNlcXVlbnQgZmx1c2guCiAgICAgICAgbG9jYWwgZG9tYWlucyA9IHt9CiAgICAgICAgZm9yIF8sIGQgaW4gaXBhaXJzKHJlYWRfaW5kZXgoImRuIiwgImRpOiIpKSBkbwogICAgICAgICAgICAtLSBBIGhvc3QgY2FuIGJlIGluZGV4ZWQgYnV0IGhhdmUgaGFkIGl0cyBsaWZldGltZSB0b3RhbHMgZXZpY3RlZDsgcmVwb3J0IGl0CiAgICAgICAgICAgIC0tIHdpdGggemVyb3MgcmF0aGVyIHRoYW4gb21pdHRpbmcgaXQsIHNvIHRoZSBzY3JhcGVyIHN0aWxsIGFza3MgZm9yIGl0cyBidWNrZXRzLgogICAgICAgICAgICBkb21haW5zWyNkb21haW5zICsgMV0gPSB7CiAgICAgICAgICAgICAgICBkb21haW4gICAgICAgID0gZCwKICAgICAgICAgICAgICAgIHJlcXVlc3RzICAgICAgPSBhbmFseXRpY3M6Z2V0KCJ0OiIgLi4gZCAuLiAiOnIiKSBvciAwLAogICAgICAgICAgICAgICAgYmFuZHdpZHRoX2luICA9IGFuYWx5dGljczpnZXQoInQ6IiAuLiBkIC4uICI6aSIpIG9yIDAsCiAgICAgICAgICAgICAgICBiYW5kd2lkdGhfb3V0ID0gYW5hbHl0aWNzOmdldCgidDoiIC4uIGQgLi4gIjpvIikgb3IgMCwKICAgICAgICAgICAgfQogICAgICAgIGVuZAogICAgICAgIHJldHVybiBqc29uKHsgZG9tYWlucyA9IGRvbWFpbnMgfSkKICAgIGVuZAoKICAgIGRvbWFpbiA9IGRvbWFpbjpsb3dlcigpCiAgICByZXR1cm4ganNvbih7CiAgICAgICAgZG9tYWluICAgICAgICA9IGRvbWFpbiwKICAgICAgICByZXF1ZXN0cyAgICAgID0gYW5hbHl0aWNzOmdldCgidDoiIC4uIGRvbWFpbiAuLiAiOnIiKSBvciAwLAogICAgICAgIGJhbmR3aWR0aF9pbiAgPSBhbmFseXRpY3M6Z2V0KCJ0OiIgLi4gZG9tYWluIC4uICI6aSIpIG9yIDAsCiAgICAgICAgYmFuZHdpZHRoX291dCA9IGFuYWx5dGljczpnZXQoInQ6IiAuLiBkb21haW4gLi4gIjpvIikgb3IgMCwKICAgIH0pCmVuZAoKLS0g4pSA4pSAIEdFVCAvYW5hbHl0aWNzL2dlbyAtIGRhaWx5IHJvbGx1cCBmb3IgYSBkYXkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tID9kb21haW49ZXhhbXBsZS5jb20mZGF5PVlZWVlNTURECi0tCi0tIE5hbWVkIC9nZW8gZm9yIGNvbXBhdGliaWxpdHk7IGl0IG5vdyByZXR1cm5zIHRoZSB3aG9sZSBkYWlseSByb2xsdXAg4oCUIGNvdW50cmllcywKLS0gZGlzdGluY3QgdmlzaXRvcnMsIHRvcCBwYXRocywgc3RhdHVzLWNvZGUgbWl4LiBPbmUgc2NhbiBzZXJ2ZXMgYWxsIGZvdXI6IHRoZXkKLS0gc2hhcmUgdGhlIGBnOntkb21haW59OntkYXl9OmAgcHJlZml4IHByZWNpc2VseSBzbyBhIHJlYWRlciBuZXZlciBuZWVkcyBhIHNlY29uZAotLSBwYXNzIG92ZXIgdGhlIHpvbmUuCi0tCi0tIEtleSBsYXlvdXQgdW5kZXIgdGhhdCBwcmVmaXggKHdyaXR0ZW4gYnkgc2l0ZV9sb2dnZXIubHVhKToKLS0gICA8Q0M+ICAgICAgICAgICAgRVhBQ1RMWSB0d28gdXBwZXJjYXNlIGxldHRlcnMg4oaSIGNvdW50cnkgaGl0IGNvdW50Ci0tICAgdiAgICAgICAgICAgICAgIGRpc3RpbmN0IHZpc2l0b3JzIHRvZGF5Ci0tICAgcDo8cGF0aD4gICAgICAgIHBhdGggY291bnRlcgotLSAgIHBuICAgICAgICAgICAgICBkaXN0aW5jdC1wYXRoIGNvdW50ZXIgKGNhcmRpbmFsaXR5IGNhcCBib29ra2VlcGluZykKLS0gICBzOjxzdGF0dXM+ICAgICAgc3RhdHVzLWNvZGUgY291bnRlcgotLQotLSBDb3VudHJ5IG1hdGNoaW5nIGlzIHN0cmljdCAoXiV1JXUkKSByYXRoZXIgdGhhbiAid2hhdGV2ZXIncyBsZWZ0IjogYSBib29ra2VlcGluZwotLSBrZXkgbGlrZSBgcG5gIHdvdWxkIG90aGVyd2lzZSBzdXJmYWNlIGFzIGEgY291bnRyeSBuYW1lZCAicG4iIGFuZCBnZXQgcGxvdHRlZC4KCmlmIHVyaSA9PSAiL2FuYWx5dGljcy9nZW8iIHRoZW4KICAgIGxvY2FsIGRvbWFpbiA9IG5neC52YXIuYXJnX2RvbWFpbgogICAgaWYgbm90IGRvbWFpbiBvciBkb21haW4gPT0gIiIgdGhlbiByZXR1cm4gYmFkKCJtaXNzaW5nID9kb21haW49IikgZW5kCiAgICBkb21haW4gPSBkb21haW46bG93ZXIoKQoKICAgIGxvY2FsIGRheSA9IG5neC52YXIuYXJnX2RheQogICAgaWYgbm90IGRheSBvciAjZGF5IH49IDggdGhlbgogICAgICAgIGRheSA9IG9zLmRhdGUoIiElWSVtJWQiKQogICAgZW5kCgogICAgLS0gUmVhZCB0aHJvdWdoIHRoZSB3cml0ZS10aW1lIGluZGV4ZXMg4oCUIHNhbWUgaGVscGVyIC9hbmFseXRpY3MvY29sbGVjdCB1c2VzLCBzbyB0aGUgdHdvCiAgICAtLSBlbmRwb2ludHMgY2Fubm90IGRpc2FncmVlIGFib3V0IHdoYXQgYSBkYXkgY29udGFpbnMuIFJlcGxhY2VzIGEgYGdldF9rZXlzKDApYCB0aGF0CiAgICAtLSB3YWxrZWQgdGhlIHdob2xlIHpvbmUgdG8gZmluZCBrZXlzIHVuZGVyIG9uZSBwcmVmaXguCiAgICBsb2NhbCByb2xsdXAgPSByZWFkX3JvbGx1cChkb21haW4sIGRheSkKICAgIGxvY2FsIGNvdW50cmllcywgcGF0aHMsIHN0YXR1c2VzID0ge30sIHt9LCB7fQogICAgbG9jYWwgdmlzaXRvcnMgPSB0b251bWJlcihyb2xsdXBbInYiXSkgb3IgMAogICAgZm9yIHN1ZmZpeCwgdiBpbiBwYWlycyhyb2xsdXApIGRvCiAgICAgICAgaWYgc3VmZml4ID09ICJ2IiBvciBzdWZmaXggPT0gInBuIiB0aGVuCiAgICAgICAgICAgIC0tIGJvb2trZWVwaW5nLCBub3QgZGF0YQogICAgICAgIGVsc2VpZiBzdWZmaXg6c3ViKDEsIDIpID09ICJwOiIgdGhlbgogICAgICAgICAgICBwYXRoc1tzdWZmaXg6c3ViKDMpXSA9IHYKICAgICAgICBlbHNlaWYgc3VmZml4OnN1YigxLCAyKSA9PSAiczoiIHRoZW4KICAgICAgICAgICAgc3RhdHVzZXNbc3VmZml4OnN1YigzKV0gPSB2CiAgICAgICAgZWxzZWlmIHN1ZmZpeDptYXRjaCgiXiV1JXUkIikgdGhlbgogICAgICAgICAgICAtLSBDb3VudHJ5IGNvZGVzIG9ubHkuIEFueXRoaW5nIGVsc2UgdW5kZXIgdGhpcyBwcmVmaXggaXMgYm9va2tlZXBpbmcsIGFuZAogICAgICAgICAgICAtLSBsZXR0aW5nIG9uZSB0aHJvdWdoIG1hZGUgYHBuYCBwbG90IGFzIGEgY291bnRyeSBhbmQgc2tldyBldmVyeSBwZXJjZW50YWdlLgogICAgICAgICAgICBjb3VudHJpZXNbc3VmZml4XSA9IHYKICAgICAgICBlbmQKICAgIGVuZAogICAgcmV0dXJuIGpzb24oewogICAgICAgIGRvbWFpbiAgICA9IGRvbWFpbiwKICAgICAgICBkYXkgICAgICAgPSBkYXksCiAgICAgICAgY291bnRyaWVzID0gY291bnRyaWVzLAogICAgICAgIHZpc2l0b3JzICA9IHZpc2l0b3JzLAogICAgICAgIHBhdGhzICAgICA9IHBhdGhzLAogICAgICAgIHN0YXR1c2VzICA9IHN0YXR1c2VzLAogICAgfSkKZW5kCgotLSDilIDilIAgR0VUIC9sb2dzL3JlY2VudCAtIHJhdyByZXF1ZXN0IHJpbmcgYnVmZmVyIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAotLSA/ZG9tYWluPWV4YW1wbGUuY29tJmxpbWl0PTUwCgppZiB1cmkgPT0gIi9sb2dzL3JlY2VudCIgdGhlbgogICAgaWYgbm90IHJlcXVlc3RfZGF0YSB0aGVuCiAgICAgICAgcmV0dXJuIGpzb24oeyBlcnJvciA9ICJyZXF1ZXN0X2RhdGEgZGljdCB1bmF2YWlsYWJsZSIgfSwgNTAzKQogICAgZW5kCgogICAgbG9jYWwgZG9tYWluID0gbmd4LnZhci5hcmdfZG9tYWluCiAgICBpZiBub3QgZG9tYWluIG9yIGRvbWFpbiA9PSAiIiB0aGVuIHJldHVybiBiYWQoIm1pc3NpbmcgP2RvbWFpbj0iKSBlbmQKICAgIGRvbWFpbiA9IGRvbWFpbjpsb3dlcigpCgogICAgbG9jYWwgbGltaXQgPSBtYXRoLm1pbih0b251bWJlcihuZ3gudmFyLmFyZ19saW1pdCkgb3IgNTAsIDEwMDApCiAgICBsb2NhbCBzZXEgICA9IHJlcXVlc3RfZGF0YTpnZXQoInJsb2c6IiAuLiBkb21haW4gLi4gIjpzZXEiKSBvciAwCiAgICBsb2NhbCBvdXQgICA9IHt9CgogICAgZm9yIGkgPSAwLCBsaW1pdCAtIDEgZG8KICAgICAgICBsb2NhbCBzbG90ID0gKHNlcSAtIGkpICUgMTAwMAogICAgICAgIGlmIHNsb3QgPCAwIHRoZW4gc2xvdCA9IHNsb3QgKyAxMDAwIGVuZAogICAgICAgIGxvY2FsIHJhdyA9IHJlcXVlc3RfZGF0YTpnZXQoInJsb2c6IiAuLiBkb21haW4gLi4gIjoiIC4uIHNsb3QpCiAgICAgICAgaWYgcmF3IHRoZW4gb3V0WyNvdXQgKyAxXSA9IHJhdyBlbmQKICAgIGVuZAoKICAgIC0tIFJldHVybiBwcmUtZW5jb2RlZCBKU09OIGVudHJpZXMgYXMgYSBKU09OIGFycmF5CiAgICBuZ3guaGVhZGVyWyJDb250ZW50LVR5cGUiXSA9ICJhcHBsaWNhdGlvbi9qc29uIgogICAgbmd4LnByaW50KCJbIikKICAgIGZvciBpZHgsIGVudHJ5IGluIGlwYWlycyhvdXQpIGRvCiAgICAgICAgaWYgaWR4ID4gMSB0aGVuIG5neC5wcmludCgiLCIpIGVuZAogICAgICAgIG5neC5wcmludChlbnRyeSkKICAgIGVuZAogICAgbmd4LnNheSgiXSIpCiAgICByZXR1cm4gbmd4LmV4aXQoMjAwKQplbmQKCi0tIOKUgOKUgCA0MDQg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACnJldHVybiBqc29uKHsgZXJyb3IgPSAibm90IGZvdW5kIiB9LCA0MDQpCg==",
|
|
37
|
+
"pipe_stream.lua": "LS0gcGlwZV9zdHJlYW0ubHVhCi0tIGNvbnRlbnRfYnlfbHVhOiBTU0UgZW5kcG9pbnQgZm9yIHJlYWwtdGltZSByZXF1ZXN0IGxvZyBzdHJlYW1pbmcuCi0tIEdFVCAvbG9ncy9zdHJlYW0/ZG9tYWluPWV4YW1wbGUuY29tCi0tIEludGVybmFsIG9ubHkgLSAxMjcuMC4wLjE6OTE0NQotLQotLSBSZWFkcyB0aGUgU0FNRSByaW5nIGJ1ZmZlciBzaXRlX2xvZ2dlci5sdWEgd3JpdGVzIChybG9nOntkb21haW59OnNlcSArCi0tIHJsb2c6e2RvbWFpbn06e3Nsb3R9KSwgYnkgYSBQRVItQ09OTkVDVElPTiBjdXJzb3IuIE5vdGhpbmcgaXMgY29uc3VtZWQ6IE4KLS0gY29uY3VycmVudCB3YXRjaGVycyBlYWNoIHdhbGsgdGhlIHJpbmcgaW5kZXBlbmRlbnRseSBhbmQgbm9uZSBzdGVhbHMgYW5vdGhlcidzCi0tIGZyYW1lcy4gVGhpcyBpcyB3aGF0IHJlcGxhY2VkIHRoZSBvbGQgc2luZ2xlLXN1YnNjcmliZXIgbG9nX3BpcGU6cSBxdWV1ZSDigJQKLS0gYSBjb250YWluZXJpemVkIGVkZ2UgdGFpbHMgdGhpcyBvdmVyIGBkb2NrZXIgZXhlYyBjdXJsYCwgYW5kIGEgY3VybCB0aGF0Ci0tIG91dGxpdmVzIGl0cyBjbGllbnQgKHRoZSBkYWVtb24gYnVmZmVycyBpdHMgc3Rkb3V0LCBzbyBubyBFUElQRSkgY2FuIG5vIGxvbmdlcgotLSBkcmFpbiB0aGUgcXVldWUgb3V0IGZyb20gdW5kZXIgdGhlIG5leHQgcmVhZGVyLgoKbG9jYWwgc2ggPSBuZ3guc2hhcmVkLnJlcXVlc3RfZGF0YQppZiBub3Qgc2ggdGhlbgogICAgbmd4LnN0YXR1cyA9IDUwMwogICAgbmd4LnNheSgic2hhcmVkIGRpY3QgdW5hdmFpbGFibGUiKQogICAgcmV0dXJuIG5neC5leGl0KDUwMykKZW5kCgpsb2NhbCBkb21haW4gPSBuZ3gudmFyLmFyZ19kb21haW4KaWYgbm90IGRvbWFpbiBvciBkb21haW4gPT0gIiIgdGhlbgogICAgbmd4LnN0YXR1cyA9IDQwMAogICAgbmd4LnNheSgibWlzc2luZyA/ZG9tYWluPSBwYXJhbWV0ZXIiKQogICAgcmV0dXJuIG5neC5leGl0KDQwMCkKZW5kCgpkb21haW4gPSBkb21haW46bG93ZXIoKQppZiBkb21haW46c3ViKDEsIDQpID09ICJ3d3cuIiB0aGVuIGRvbWFpbiA9IGRvbWFpbjpzdWIoNSkgZW5kCgotLSBNVVNUIG1hdGNoIHNpdGVfbG9nZ2VyLmx1YSdzIFJJTkcg4oCUIHNhbWUgc2xvdCBhcml0aG1ldGljIG9uIGJvdGggZW5kcy4KbG9jYWwgUklORyAgICA9IDEwMDAKbG9jYWwgU0VRX0tFWSA9ICJybG9nOiIgLi4gZG9tYWluIC4uICI6c2VxIgpsb2NhbCBzbG90X2tleSA9IGZ1bmN0aW9uKHNlcSkgcmV0dXJuICJybG9nOiIgLi4gZG9tYWluIC4uICI6IiAuLiAoc2VxICUgUklORykgZW5kCgpuZ3guaGVhZGVyWyJDb250ZW50LVR5cGUiXSAgICAgID0gInRleHQvZXZlbnQtc3RyZWFtIgpuZ3guaGVhZGVyWyJDYWNoZS1Db250cm9sIl0gICAgID0gIm5vLWNhY2hlLCBuby1zdG9yZSIKbmd4LmhlYWRlclsiQ29ubmVjdGlvbiJdICAgICAgICA9ICJrZWVwLWFsaXZlIgpuZ3guaGVhZGVyWyJYLUFjY2VsLUJ1ZmZlcmluZyJdID0gIm5vIgoKLS0gU2VuZCBpbml0aWFsIFNTRSBjb21tZW50IHNvIHRoZSBmaXJzdCBmbHVzaCBoYXMgZGF0YS4KLS0gV2l0aG91dCB0aGlzLCBuZ3guZmx1c2ggb24gYW4gZW1wdHkgYnVmZmVyIHNlbmRzIGNodW5rZWQtRU9GICgwXHJcblxyXG4pCi0tIGFuZCB0ZXJtaW5hdGVzIHRoZSByZXNwb25zZSBpbW1lZGlhdGVseS4Kbmd4LnByaW50KCI6IGNvbm5lY3RlZFxuXG4iKQppZiBub3Qgbmd4LmZsdXNoKHRydWUpIHRoZW4gcmV0dXJuIGVuZAoKLS0gU3RhcnQgYXQgdGhlIGN1cnJlbnQgaGVhZDogc3RyZWFtIG9ubHkgcmVxdWVzdHMgdGhhdCBhcnJpdmUgQUZURVIgY29ubmVjdC4KLS0gSGlzdG9yeSB1cCB0byB0aGlzIHBvaW50IGlzIHNlcnZlZCBzZXBhcmF0ZWx5IGJ5IC9sb2dzL3JlY2VudCwgYW5kIHRoZSBjbGllbnQKLS0gZGVkdXBzIHRoZSB0d28gYnkgdGhlIGRldGVybWluaXN0aWMgYHtob3N0fTp7c2VxfWAgaWQsIHNvIGEgcm93IHNlZW4gYnkgYm90aAotLSBjb2xsYXBzZXMgdG8gb25lLgpsb2NhbCBjdXJzb3IgID0gdG9udW1iZXIoc2g6Z2V0KFNFUV9LRVkpKSBvciAwCmxvY2FsIHN0YXJ0ZWQgPSBuZ3gubm93KCkKbG9jYWwgbGFzdF9oYiA9IHN0YXJ0ZWQKCndoaWxlIHRydWUgZG8KICAgIC0tIE1heCAxIGhvdXIgcGVyIGNvbm5lY3Rpb24uCiAgICBpZiBuZ3gubm93KCkgLSBzdGFydGVkID4gMzYwMCB0aGVuIHJldHVybiBlbmQKCiAgICBsb2NhbCBoZWFkID0gdG9udW1iZXIoc2g6Z2V0KFNFUV9LRVkpKSBvciAwCgogICAgLS0gSWYgd2UndmUgZmFsbGVuIG1vcmUgdGhhbiBhIGZ1bGwgcmluZyBiZWhpbmQsIHRoZSBvbGRlc3QgdW5yZWFkIHNsb3RzIGhhdmUKICAgIC0tIGFscmVhZHkgYmVlbiBvdmVyd3JpdHRlbi4gSnVtcCB0byB0aGUgb2xkZXN0IHNsb3Qgc3RpbGwgaG9sZGluZyBpdHMgb3duCiAgICAtLSBlbnRyeSAoaGVhZC1SSU5HIG1hcHMgdG8gaGVhZCdzIHNsb3QsIHNvIGhlYWQtUklORysxIGlzIHRoZSBvbGRlc3QgbGl2ZSBvbmUpCiAgICAtLSBhbmQgc2tpcCB0aGUgbG9zdCByYW5nZSDigJQgc2FtZSBib3VuZCB0aGUgb2xkIDIwMDAtZW50cnkgcXVldWUgaGFkLgogICAgaWYgY3Vyc29yIDwgaGVhZCAtIFJJTkcgdGhlbiBjdXJzb3IgPSBoZWFkIC0gUklORyBlbmQKCiAgICBsb2NhbCBzZW50ID0gMAogICAgd2hpbGUgY3Vyc29yIDwgaGVhZCBhbmQgc2VudCA8IDEwMCBkbwogICAgICAgIGxvY2FsIG5leHRfc2VxID0gY3Vyc29yICsgMQogICAgICAgIGxvY2FsIGVudHJ5ID0gc2g6Z2V0KHNsb3Rfa2V5KG5leHRfc2VxKSkKICAgICAgICBpZiBlbnRyeSB0aGVuCiAgICAgICAgICAgIG5neC5wcmludCgiZXZlbnQ6IHJlcXVlc3RcbmRhdGE6ICIsIGVudHJ5LCAiXG5cbiIpCiAgICAgICAgICAgIHNlbnQgPSBzZW50ICsgMQogICAgICAgICAgICBjdXJzb3IgPSBuZXh0X3NlcQogICAgICAgIGVsc2VpZiBuZXh0X3NlcSA8IGhlYWQgdGhlbgogICAgICAgICAgICAtLSBBIGxhdGVyIHNlcSBhbHJlYWR5IGV4aXN0cywgc28gdGhpcyBjYW4ndCBiZSB0aGUgaW5jcihzZXEp4oaSc2V0KHNsb3QpCiAgICAgICAgICAgIC0tIHdyaXRlIHdpbmRvdzogdGhlIHNsb3QgaXMgZ2VudWluZWx5IGxvc3QgKGV4cGlyZWQgb3Igd3JhcHBlZCkuIFNraXAgaXQuCiAgICAgICAgICAgIGN1cnNvciA9IG5leHRfc2VxCiAgICAgICAgZWxzZQogICAgICAgICAgICAtLSBuZXh0X3NlcSA9PSBoZWFkOiB0aGUgbmV3ZXN0IGVudHJ5J3Mgc2xvdCBtYXkgbm90IGJlIHdyaXR0ZW4geWV0CiAgICAgICAgICAgIC0tICh0aGUgbWljcm9zZWNvbmQgd2luZG93IGJldHdlZW4gaW5jcihzZXEpIGFuZCBzZXQoc2xvdCkpLiBSZXRyeSBpdAogICAgICAgICAgICAtLSBuZXh0IGN5Y2xlIHdpdGhvdXQgYWR2YW5jaW5nLgogICAgICAgICAgICBicmVhawogICAgICAgIGVuZAogICAgZW5kCgogICAgaWYgc2VudCA+IDAgdGhlbgogICAgICAgIGlmIG5vdCBuZ3guZmx1c2godHJ1ZSkgdGhlbiByZXR1cm4gZW5kCiAgICBlbmQKCiAgICBsb2NhbCBub3cgPSBuZ3gubm93KCkKCiAgICAtLSBIZWFydGJlYXQgZXZlcnkgMTVzLiBJdHMgZmx1c2ggaXMgYWxzbyBob3cgYSBkZWFkIGNsaWVudCBpcyBkZXRlY3RlZDogb25jZQogICAgLS0gdGhlIHJlYWRlciAoYSBgZG9ja2VyIGV4ZWMgY3VybGApIGdvZXMgYXdheSBhbmQgaXRzIHNvY2tldCBjbG9zZXMsIHRoaXMKICAgIC0tIGZsdXNoIGZhaWxzIGFuZCB0aGUgY29ubmVjdGlvbiB0ZWFycyBkb3duIGhlcmUuCiAgICBpZiBub3cgLSBsYXN0X2hiID4gMTUgdGhlbgogICAgICAgIG5neC5wcmludCgiOiBwaW5nXG5cbiIpCiAgICAgICAgaWYgbm90IG5neC5mbHVzaCh0cnVlKSB0aGVuIHJldHVybiBlbmQKICAgICAgICBsYXN0X2hiID0gbm93CiAgICBlbmQKCiAgICBuZ3guc2xlZXAoMC4wNSkKZW5kCg==",
|
|
38
|
+
"rules_guard.lua": "LS0gcnVsZXNfZ3VhcmQubHVhCi0tIGFjY2Vzc19ieV9sdWEgZHJpdmVyOiBlbmZvcmNlIHBlci1yb3V0ZSBydWxlcyAobWV0aG9kIMK3IElQL0NJRFIgYWxsb3ctZGVueSDCtwotLSBjb3VudHJ5IGFsbG93L2JhbiDCtyBiYWQgdXNlci1hZ2VudCDCtyBob3RsaW5rIMK3IHJhdGUtbGltaXQpIGZvciB0aGUgcmVxdWVzdCdzCi0tIGhvc3QuIFJ1bGVzIGFyZSBwdXNoZWQgcmVsb2FkLWZyZWUgYnkgbWdtdF9hcGkgYFBPU1QgL3J1bGVzYDsgdGhlIERCCi0tIGByb3V0ZV9ydWxlYCB0YWJsZSBpcyB0aGUgc291cmNlIG9mIHRydXRoLiBBbGwgcGFyc2luZy9jb21waWxpbmcvbWF0Y2hpbmcKLS0gbGl2ZXMgaW4ga3JhZnQucnVsZXNfbGliIChsb2FkZWQgT05DRSBwZXIgd29ya2VyKSDigJQgdGhpcyBmaWxlIGlzIHJlLXJ1bgotLSBldmVyeSByZXF1ZXN0IHNvIGl0IHN0YXlzIG1pbmltYWwuIFNlZSBydWxlc19saWIubHVhIGZvciB0aGUgY29tcGlsZWQgc2hhcGUuCi0tCi0tIEVuZm9yY2VtZW50IHVzZXMgdGhlIGNvbm5lY3RpbmcgcGVlciAobmd4LnZhci5yZW1vdGVfYWRkcik7IGZyb250IGEgcmVhbF9pcAotLSBjb25maWcgaWYgYmVoaW5kIGEgdHJ1c3RlZCBwcm94eS4gTm8gdXNlci1zdXBwbGllZCB2YWx1ZSBpcyBldmVyIHVzZWQgYXMgYQotLSBMdWEgcGF0dGVybiBvciB3cml0dGVuIGludG8gYSByZXNwb25zZSBoZWFkZXIuCgpsb2NhbCBydWxlcyA9IG5neC5zaGFyZWQucnVsZXMKaWYgbm90IHJ1bGVzIHRoZW4gcmV0dXJuIGVuZAoKLS0gUmF0ZS1saW1pdCBjb3VudGVycyBsaXZlIGluIHRoZWlyIE9XTiBkaWN0IHNvIGEgaGlnaC1jYXJkaW5hbGl0eSBmbG9vZCAoYSBuZXcKLS0gcmw6IGtleSBwZXIgc291cmNlIElQIHBlciBzZWNvbmQpIGNhbid0IExSVS1ldmljdCB0aGUgcnVsZXNldHMgYW5kIHNpbGVudGx5Ci0tIGRpc2FibGUgZW5mb3JjZW1lbnQuIEZhbGwgYmFjayB0byBgcnVsZXNgIG9uIGEgYm94IHdob3NlIGNvbmZpZyBwcmVkYXRlcyB0aGUKLS0gc2VwYXJhdGUgZGljdCAoc3RpbGwgd29ya3MsIGp1c3Qgc2hhcmVzIHRoZSB6b25lIHVudGlsIHRoZSBuZXh0IHJlbG9hZCkuCmxvY2FsIGNvdW50ZXJzID0gbmd4LnNoYXJlZC5ybF9jb3VudGVycyBvciBydWxlcwoKbG9jYWwgaG9zdCA9IG5neC52YXIuaG9zdAppZiBub3QgaG9zdCB0aGVuIHJldHVybiBlbmQKCmxvY2FsIHJhdyA9IHJ1bGVzOmdldChob3N0KQppZiBub3QgcmF3IHRoZW4gcmV0dXJuIGVuZCAgICAgICAgICAtLSBmYXN0IHBhdGg6IG5vdGhpbmcgY29uZmlndXJlZCBmb3IgdGhpcyBob3N0Cgpsb2NhbCBsaWIgPSByZXF1aXJlICJrcmFmdC5ydWxlc19saWIiCmxvY2FsIGVudHJpZXMgPSBsaWIuZ2V0KGhvc3QsIHJhdykKbG9jYWwgbiA9ICNlbnRyaWVzCmlmIG4gPT0gMCB0aGVuIHJldHVybiBlbmQKCi0tIOKUgOKUgCBMb25nZXN0IG1hdGNoaW5nIHBhdGhQcmVmaXggd2lucyDilIDilIAKbG9jYWwgdXJpID0gbmd4LnZhci51cmkgb3IgIi8iCmxvY2FsIGNob3NlbiwgY2hvc2VuX2xlbiA9IG5pbCwgLTEKZm9yIGkgPSAxLCBuIGRvCiAgICBsb2NhbCBlID0gZW50cmllc1tpXQogICAgbG9jYWwgcCA9IGUucGF0aFByZWZpeAogICAgaWYgcCA9PSBuaWwgb3IgcCA9PSAiIiBvciBwID09ICIvIiB0aGVuCiAgICAgICAgaWYgY2hvc2VuX2xlbiA8IDAgdGhlbiBjaG9zZW4sIGNob3Nlbl9sZW4gPSBlLCAwIGVuZAogICAgZWxzZWlmIHVyaSA9PSBwIG9yIHN0cmluZy5zdWIodXJpLCAxLCAjcCkgPT0gcCB0aGVuCiAgICAgICAgaWYgI3AgPiBjaG9zZW5fbGVuIHRoZW4gY2hvc2VuLCBjaG9zZW5fbGVuID0gZSwgI3AgZW5kCiAgICBlbmQKZW5kCmlmIG5vdCBjaG9zZW4gdGhlbiByZXR1cm4gZW5kCgpsb2NhbCBzcGVjID0gY2hvc2VuLnNwZWMKbG9jYWwgZGVueV9zdGF0dXMgPSBzcGVjLmJsb2NrU3RhdHVzIG9yIDQwMwoKbG9jYWwgaXBzID0gbmd4LnZhci5yZW1vdGVfYWRkciBvciAiMC4wLjAuMCIKbG9jYWwgaXBpID0gbGliLmlwdjRfdG9faW50KGlwcykKCi0tIENvdW50cnkgcmVzb2x2ZWQgYXQgbW9zdCBvbmNlIHBlciByZXF1ZXN0IChvbmx5IHdoZW4gYSBjb3VudHJ5IHJ1bGUgZXhpc3RzKS4KbG9jYWwgY291bnRyeV9jYWNoZQpsb2NhbCBmdW5jdGlvbiBjb3VudHJ5X29mKCkKICAgIGlmIGNvdW50cnlfY2FjaGUgPT0gbmlsIHRoZW4KICAgICAgICBsb2NhbCBvaywgZ2VvID0gcGNhbGwocmVxdWlyZSwgImtyYWZ0Lmdlb19jb3VudHJ5IikKICAgICAgICBjb3VudHJ5X2NhY2hlID0gKG9rIGFuZCBnZW8gYW5kIGdlby5nZXRfY291bnRyeV9jb2RlKGlwcykpIG9yIGZhbHNlCiAgICBlbmQKICAgIHJldHVybiBjb3VudHJ5X2NhY2hlIG9yIG5pbAplbmQKCi0tIOKUgOKUgCAxLiBBY2Nlc3M6IG1ldGhvZCBhbGxvdy1saXN0LCBJUCBhbGxvdy9kZW55LCBjb3VudHJ5IGFsbG93LWxpc3Qg4pSA4pSACmxvY2FsIGFjY2VzcyA9IHNwZWMuYWNjZXNzCmlmIGFjY2VzcyB0aGVuCiAgICBpZiBhY2Nlc3MubWV0aG9kcyBhbmQgbm90IGFjY2Vzcy5tZXRob2RzW25neC5yZXEuZ2V0X21ldGhvZCgpXSB0aGVuCiAgICAgICAgcmV0dXJuIG5neC5leGl0KGRlbnlfc3RhdHVzKQogICAgZW5kCiAgICBpZiBsaWIubWF0Y2hfY29tcGlsZWQoYWNjZXNzLmRlbnksIGlwaSwgaXBzKSB0aGVuIHJldHVybiBuZ3guZXhpdChkZW55X3N0YXR1cykgZW5kCiAgICBpZiBhY2Nlc3MuYWxsb3cgYW5kIG5vdCBsaWIubWF0Y2hfY29tcGlsZWQoYWNjZXNzLmFsbG93LCBpcGksIGlwcykgdGhlbgogICAgICAgIHJldHVybiBuZ3guZXhpdChkZW55X3N0YXR1cykKICAgIGVuZAogICAgLS0gQWxsb3ctbGlzdDogYW4gdW5yZXNvbHZlZCBjb3VudHJ5IGlzIG5vdCBvbiB0aGUgbGlzdCDihpIgYmxvY2tlZCAoZGVmYXVsdC1kZW55KS4KICAgIGlmIGFjY2Vzcy5hbGxvd0NvdW50cmllcyBhbmQgbm90IGFjY2Vzcy5hbGxvd0NvdW50cmllc1tjb3VudHJ5X29mKCkgb3IgIiJdIHRoZW4KICAgICAgICByZXR1cm4gbmd4LmV4aXQoZGVueV9zdGF0dXMpCiAgICBlbmQKZW5kCgotLSDilIDilIAgMi4gQmFuOiBJUC9DSURSLCBjb3VudHJ5LCB1c2VyLWFnZW50IOKUgOKUgApsb2NhbCBiYW4gPSBzcGVjLmJhbgppZiBiYW4gdGhlbgogICAgaWYgbGliLm1hdGNoX2NvbXBpbGVkKGJhbi5pcHMsIGlwaSwgaXBzKSBvciBsaWIubWF0Y2hfY29tcGlsZWQoYmFuLmNpZHJzLCBpcGksIGlwcykgdGhlbgogICAgICAgIHJldHVybiBuZ3guZXhpdChkZW55X3N0YXR1cykKICAgIGVuZAogICAgaWYgYmFuLmNvdW50cmllcyB0aGVuCiAgICAgICAgbG9jYWwgY2MgPSBjb3VudHJ5X29mKCkKICAgICAgICAtLSBGYWlsIENMT1NFRCAobWF0Y2hlcyB0aGUgYWxsb3ctbGlzdCBhYm92ZSk6IGlmIGdlbyBpcyB1bmF2YWlsYWJsZSB3ZQogICAgICAgIC0tIGNhbm5vdCBwcm92ZSB0aGUgY2xpZW50IGlzIE5PVCBmcm9tIGEgYmFubmVkIGNvdW50cnksIHNvIGJsb2NrIHJhdGhlcgogICAgICAgIC0tIHRoYW4gc2lsZW50bHkgbGV0dGluZyBiYW5uZWQgdHJhZmZpYyB0aHJvdWdoLiBBIGJsb2NrZWQgaG9zdCBpcyBhIGxvdWQKICAgICAgICAtLSBzaWduYWwgdG8gZml4IGdlbzsgZmFpbC1vcGVuIHdvdWxkIGJlIGEgc2lsZW50IHNlY3VyaXR5IGhvbGUuCiAgICAgICAgaWYgbm90IGNjIHRoZW4KICAgICAgICAgICAgbmd4LmxvZyhuZ3guV0FSTiwgInJ1bGVzX2d1YXJkOiBjb3VudHJ5IGJhbiBhY3RpdmUgYnV0IGdlbyB1bmF2YWlsYWJsZSDigJQgYmxvY2tpbmcgKGZhaWwtY2xvc2VkKSIpCiAgICAgICAgICAgIHJldHVybiBuZ3guZXhpdChkZW55X3N0YXR1cykKICAgICAgICBlbmQKICAgICAgICBpZiBiYW4uY291bnRyaWVzW2NjXSB0aGVuIHJldHVybiBuZ3guZXhpdChkZW55X3N0YXR1cykgZW5kCiAgICBlbmQKICAgIGlmIGJhbi5lbXB0eVVBIG9yIGJhbi51YXMgdGhlbgogICAgICAgIGxvY2FsIHVhID0gbmd4LnZhci5odHRwX3VzZXJfYWdlbnQKICAgICAgICBpZiBiYW4uZW1wdHlVQSBhbmQgKHVhID09IG5pbCBvciB1YSA9PSAiIikgdGhlbiByZXR1cm4gbmd4LmV4aXQoZGVueV9zdGF0dXMpIGVuZAogICAgICAgIGlmIGJhbi51YXMgYW5kIHVhIGFuZCB1YSB+PSAiIiB0aGVuCiAgICAgICAgICAgIGxvY2FsIHVhbCA9IHN0cmluZy5sb3dlcih1YSkKICAgICAgICAgICAgZm9yIGkgPSAxLCAjYmFuLnVhcyBkbwogICAgICAgICAgICAgICAgaWYgc3RyaW5nLmZpbmQodWFsLCBiYW4udWFzW2ldLCAxLCB0cnVlKSB0aGVuIHJldHVybiBuZ3guZXhpdChkZW55X3N0YXR1cykgZW5kCiAgICAgICAgICAgIGVuZAogICAgICAgIGVuZAogICAgZW5kCmVuZAoKLS0g4pSA4pSAIDMuIEhvdGxpbms6IG9ubHkgbGlzdGVkIHJlZmVyZXIgaG9zdHMgKGVtcHR5IHJlZmVyZXIgcGVyIGFsbG93RW1wdHkpIOKUgOKUgApsb2NhbCBob3QgPSBzcGVjLmhvdGxpbmsKaWYgaG90IHRoZW4KICAgIGxvY2FsIHJlZiA9IG5neC52YXIuaHR0cF9yZWZlcmVyCiAgICBpZiByZWYgPT0gbmlsIG9yIHJlZiA9PSAiIiB0aGVuCiAgICAgICAgaWYgbm90IGhvdC5hbGxvd0VtcHR5IHRoZW4gcmV0dXJuIG5neC5leGl0KGRlbnlfc3RhdHVzKSBlbmQKICAgIGVsc2UKICAgICAgICBsb2NhbCByaG9zdCA9IHN0cmluZy5tYXRjaChyZWYsICJeJXcrOi8vKFteL10rKSIpICAgICAgICAgIC0tIGF1dGhvcml0eQogICAgICAgIGlmIHJob3N0IHRoZW4gcmhvc3QgPSBzdHJpbmcubG93ZXIoc3RyaW5nLm1hdGNoKHJob3N0LCAiXihbXjpdKykiKSBvciByaG9zdCkgZW5kIC0tIHN0cmlwIDpwb3J0CiAgICAgICAgaWYgbm90IChyaG9zdCBhbmQgaG90LnJlZmVyZXJzW3Job3N0XSkgdGhlbiByZXR1cm4gbmd4LmV4aXQoZGVueV9zdGF0dXMpIGVuZAogICAgZW5kCmVuZAoKLS0g4pSA4pSAIDQuIFJhdGUgbGltaXQg4oCUIGZpeGVkIDFzIHdpbmRvdyBwZXIgKGhvc3QsIHBhdGgsIGlwKSDilIDilIAKbG9jYWwgcmwgPSBzcGVjLnJsCmlmIHJsIHRoZW4KICAgIGxvY2FsIGtleSA9ICJybDoiIC4uIGhvc3QgLi4gIjoiIC4uIChjaG9zZW4ucGF0aFByZWZpeCBvciAiLyIpIC4uICI6IiAuLiBpcHMKICAgICAgICAuLiAiOiIgLi4gbWF0aC5mbG9vcihuZ3gubm93KCkpCiAgICBsb2NhbCBjID0gY291bnRlcnM6aW5jcihrZXksIDEsIDAsIDIpICAtLSBpbml0IDAsIDJzIFRUTCDihpIgc2VsZi1leHBpcmluZyBidWNrZXRzCiAgICBpZiBjIGFuZCBjID4gcmwubGltaXQgdGhlbgogICAgICAgIG5neC5oZWFkZXJbIlJldHJ5LUFmdGVyIl0gPSAiMSIKICAgICAgICByZXR1cm4gbmd4LmV4aXQocmwuc3RhdHVzKQogICAgZW5kCmVuZAo=",
|
|
39
|
+
"rules_lib.lua": "LS0gcnVsZXNfbGliLmx1YQotLSBQZXItd29ya2VyIGhlbHBlcnMgKyBwYXJzZWQtcnVsZSBjYWNoZSBmb3IgcnVsZXNfZ3VhcmQubHVhIChhY2Nlc3MgcGhhc2UpLgotLSBMb2FkZWQgT05DRSBwZXIgd29ya2VyIHZpYSByZXF1aXJlKCJrcmFmdC5ydWxlc19saWIiKS4gVGhlIGFjY2VzcyBmaWxlIGlzCi0tIHJlLWV4ZWN1dGVkIG9uIGV2ZXJ5IHJlcXVlc3QsIHNvIGFsbCBwYXJzaW5nL2NvbXBpbGluZy9tYXRjaGluZyBsaXZlcyBoZXJlIHRvCi0tIGF2b2lkIHJlLWNyZWF0aW5nIGNsb3N1cmVzIGFuZCByZS1kZWNvZGluZyBKU09OIG9uIHRoZSBob3QgcGF0aC4KLS0KLS0gU2hhcmVkLWRpY3QgdmFsdWUgYHJ1bGVzW2hvc3RdYCA9IEpTT04gYXJyYXkgb2YgeyBwYXRoUHJlZml4LCBzcGVjIH0gd2hlcmUKLS0gc3BlYyBtYXRjaGVzIEByZXBvL2NvcmUgUm91dGVSdWxlU3BlYy4gcGFyc2UoKSBkZWNvZGVzICsgcHJlY29tcGlsZXMgQ0lEUnMgdG8KLS0gaW50ZWdlcnMsIGxvd2VyY2FzZXMgVUEvcmVmZXJlciBuZWVkbGVzLCBhbmQgYnVpbGRzIE8oMSkgc2V0cyBmb3IKLS0gY291bnRyaWVzL21ldGhvZHMgT05DRTsgdGhlIGNvbXBpbGVkIHJlc3VsdCBpcyBMUlUtY2FjaGVkIHBlciBob3N0IGFuZCByZXVzZWQKLS0gdW50aWwgdGhlIHJhdyBzdHJpbmcgY2hhbmdlcyAocnVsZSBlZGl0cyBhcmUgcmFyZSwgcmVxdWVzdHMgYXJlIGhvdCkuCi0tCi0tIFNFQ1VSSVRZOiBub3RoaW5nIGhlcmUgdHVybnMgYSBydWxlIHZhbHVlIGludG8gTHVhIGNvZGUgb3IgYSBMdWEgcGF0dGVybi4KLS0gU3RyaW5ncyBhcmUgY29tcGFyZWQgd2l0aCBgPT1gL3NldC1sb29rdXBzOyB1c2VyLWFnZW50IG1hdGNoaW5nIGlzCi0tIHN0cmluZy5maW5kKGhheSwgbmVlZGxlLCAxLCB0cnVlKSDigJQgUExBSU4sIG5ldmVyIGEgcmVnZXguCgpsb2NhbCBjanNvbiA9IHJlcXVpcmUgImNqc29uLnNhZmUiCmxvY2FsIGxydWNhY2hlID0gcmVxdWlyZSAicmVzdHkubHJ1Y2FjaGUiCgpsb2NhbCBNID0ge30KCmxvY2FsIGNhY2hlID0gbHJ1Y2FjaGUubmV3KDEwMjQpIC0tIGNvbXBpbGVkIHJ1bGVzLCBwZXIgd29ya2VyLCB+MTAyNCBob3N0cwoKLS0g4pSA4pSAIElQdjQgaGVscGVycyDilIDilIAKbG9jYWwgZnVuY3Rpb24gaXB2NF90b19pbnQocykKICAgIGxvY2FsIGEsIGIsIGMsIGQgPSBzdHJpbmcubWF0Y2gocywgIl4oJWQrKSUuKCVkKyklLiglZCspJS4oJWQrKSQiKQogICAgaWYgbm90IGEgdGhlbiByZXR1cm4gbmlsIGVuZAogICAgYSwgYiwgYywgZCA9IHRvbnVtYmVyKGEpLCB0b251bWJlcihiKSwgdG9udW1iZXIoYyksIHRvbnVtYmVyKGQpCiAgICBpZiBhID4gMjU1IG9yIGIgPiAyNTUgb3IgYyA+IDI1NSBvciBkID4gMjU1IHRoZW4gcmV0dXJuIG5pbCBlbmQKICAgIHJldHVybiBhICogMTY3NzcyMTYgKyBiICogNjU1MzYgKyBjICogMjU2ICsgZAplbmQKTS5pcHY0X3RvX2ludCA9IGlwdjRfdG9faW50CgotLSBQcmVjb21waWxlIGEgQ0lEUiAvIGJhcmUtSVAgc3RyaW5nIGludG8gYSBjaGVhcCBtYXRjaCBkZXNjcmlwdG9yLgpsb2NhbCBmdW5jdGlvbiBjb21waWxlX2NpZHIocykKICAgIGxvY2FsIGJhc2UsIGJpdHMgPSBzdHJpbmcubWF0Y2gocywgIl4oW14vXSspLyglZCspJCIpCiAgICBpZiBiYXNlIHRoZW4KICAgICAgICBiaXRzID0gdG9udW1iZXIoYml0cykKICAgICAgICBsb2NhbCBiYXNlaSA9IGlwdjRfdG9faW50KGJhc2UpCiAgICAgICAgaWYgbm90IGJhc2VpIG9yIGJpdHMgPCAwIG9yIGJpdHMgPiAzMiB0aGVuIHJldHVybiB7IGV4YWN0ID0gcyB9IGVuZAogICAgICAgIGlmIGJpdHMgPT0gMCB0aGVuIHJldHVybiB7IGFsbCA9IHRydWUgfSBlbmQKICAgICAgICBsb2NhbCBkaXYgPSAyIF4gKDMyIC0gYml0cykgLS0gY29tcGFyZSB0aGUgdG9wIGBiaXRzYCBiaXRzCiAgICAgICAgcmV0dXJuIHsgbmV0ID0gbWF0aC5mbG9vcihiYXNlaSAvIGRpdiksIGRpdiA9IGRpdiB9CiAgICBlbmQKICAgIGxvY2FsIGkgPSBpcHY0X3RvX2ludChzKQogICAgaWYgaSB0aGVuIHJldHVybiB7IGlwID0gaSB9IGVuZAogICAgcmV0dXJuIHsgZXhhY3QgPSBzIH0gLS0gSVB2NiAvIHVucGFyc2VhYmxlIOKGkiBsaXRlcmFsIHN0cmluZyBjb21wYXJlCmVuZAoKbG9jYWwgZnVuY3Rpb24gY29tcGlsZV9saXN0KGxpc3QpCiAgICBpZiB0eXBlKGxpc3QpIH49ICJ0YWJsZSIgdGhlbiByZXR1cm4gbmlsIGVuZAogICAgbG9jYWwgb3V0LCBuID0ge30sIDAKICAgIGZvciBfLCBzIGluIGlwYWlycyhsaXN0KSBkbwogICAgICAgIGlmIHR5cGUocykgPT0gInN0cmluZyIgYW5kIHMgfj0gIiIgdGhlbgogICAgICAgICAgICBuID0gbiArIDEKICAgICAgICAgICAgb3V0W25dID0gY29tcGlsZV9jaWRyKHMpCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJldHVybiBuID4gMCBhbmQgb3V0IG9yIG5pbAplbmQKCi0tIE1hdGNoIGEgY2xpZW50IChpbnQgZm9ybSBgaXBpYCwgbWF5IGJlIG5pbCBmb3Igbm9uLUlQdjQ7IHJhdyBgaXBzYCkgYWdhaW5zdCBhCi0tIGNvbXBpbGVkIENJRFIvSVAgbGlzdC4KbG9jYWwgZnVuY3Rpb24gbWF0Y2hfY29tcGlsZWQoY29tcGlsZWQsIGlwaSwgaXBzKQogICAgaWYgbm90IGNvbXBpbGVkIHRoZW4gcmV0dXJuIGZhbHNlIGVuZAogICAgZm9yIGkgPSAxLCAjY29tcGlsZWQgZG8KICAgICAgICBsb2NhbCBjID0gY29tcGlsZWRbaV0KICAgICAgICBpZiBjLmFsbCB0aGVuCiAgICAgICAgICAgIHJldHVybiB0cnVlCiAgICAgICAgZWxzZWlmIGMuaXAgdGhlbgogICAgICAgICAgICBpZiBpcGkgYW5kIGlwaSA9PSBjLmlwIHRoZW4gcmV0dXJuIHRydWUgZW5kCiAgICAgICAgZWxzZWlmIGMubmV0IHRoZW4KICAgICAgICAgICAgaWYgaXBpIGFuZCBtYXRoLmZsb29yKGlwaSAvIGMuZGl2KSA9PSBjLm5ldCB0aGVuIHJldHVybiB0cnVlIGVuZAogICAgICAgIGVsc2VpZiBjLmV4YWN0ID09IGlwcyB0aGVuCiAgICAgICAgICAgIHJldHVybiB0cnVlCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJldHVybiBmYWxzZQplbmQKTS5tYXRjaF9jb21waWxlZCA9IG1hdGNoX2NvbXBpbGVkCgpsb2NhbCBmdW5jdGlvbiBsb3dlcl9saXN0KGxpc3QpCiAgICBpZiB0eXBlKGxpc3QpIH49ICJ0YWJsZSIgdGhlbiByZXR1cm4gbmlsIGVuZAogICAgbG9jYWwgb3V0LCBuID0ge30sIDAKICAgIGZvciBfLCBzIGluIGlwYWlycyhsaXN0KSBkbwogICAgICAgIGlmIHR5cGUocykgPT0gInN0cmluZyIgYW5kIHMgfj0gIiIgdGhlbgogICAgICAgICAgICBuID0gbiArIDEKICAgICAgICAgICAgb3V0W25dID0gc3RyaW5nLmxvd2VyKHMpCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJldHVybiBuID4gMCBhbmQgb3V0IG9yIG5pbAplbmQKCi0tIEJ1aWxkIGFuIE8oMSkgbG9va3VwIHNldCBmcm9tIGEgc3RyaW5nIGxpc3QgKG9wdGlvbmFsbHkgbG93ZXJjYXNlZCkuCmxvY2FsIGZ1bmN0aW9uIHRvX3NldChsaXN0LCBsb3dlcikKICAgIGlmIHR5cGUobGlzdCkgfj0gInRhYmxlIiB0aGVuIHJldHVybiBuaWwgZW5kCiAgICBsb2NhbCBzZXQsIGFueSA9IHt9LCBmYWxzZQogICAgZm9yIF8sIHMgaW4gaXBhaXJzKGxpc3QpIGRvCiAgICAgICAgaWYgdHlwZShzKSA9PSAic3RyaW5nIiBhbmQgcyB+PSAiIiB0aGVuCiAgICAgICAgICAgIHNldFtsb3dlciBhbmQgc3RyaW5nLmxvd2VyKHMpIG9yIHNdID0gdHJ1ZQogICAgICAgICAgICBhbnkgPSB0cnVlCiAgICAgICAgZW5kCiAgICBlbmQKICAgIHJldHVybiBhbnkgYW5kIHNldCBvciBuaWwKZW5kCgotLSBDb21waWxlIG9uZSBSb3V0ZVJ1bGVTcGVjIGludG8gYSBmYXN0LW1hdGNoIHNoYXBlLgpsb2NhbCBmdW5jdGlvbiBjb21waWxlX3NwZWMoc3BlYykKICAgIGlmIHR5cGUoc3BlYykgfj0gInRhYmxlIiB0aGVuIHJldHVybiB7IGJsb2NrU3RhdHVzID0gNDAzIH0gZW5kCiAgICBsb2NhbCBvdXQgPSB7fQoKICAgIGxvY2FsIHJsID0gc3BlYy5yYXRlTGltaXQKICAgIGxvY2FsIHJwcyA9IHJsIGFuZCB0b251bWJlcihybC5ycHMpCiAgICBpZiBycHMgYW5kIHJwcyA+IDAgdGhlbgogICAgICAgIG91dC5ybCA9IHsKICAgICAgICAgICAgbGltaXQgPSBtYXRoLmZsb29yKHJwcykgKyBtYXRoLmZsb29yKHRvbnVtYmVyKHJsLmJ1cnN0KSBvciAwKSwKICAgICAgICAgICAgc3RhdHVzID0gdG9udW1iZXIocmwuc3RhdHVzKSBvciA0MjksCiAgICAgICAgfQogICAgZW5kCgogICAgbG9jYWwgYmFuID0gc3BlYy5iYW4KICAgIGlmIHR5cGUoYmFuKSA9PSAidGFibGUiIHRoZW4KICAgICAgICBvdXQuYmFuID0gewogICAgICAgICAgICBpcHMgPSBjb21waWxlX2xpc3QoYmFuLmlwcyksCiAgICAgICAgICAgIGNpZHJzID0gY29tcGlsZV9saXN0KGJhbi5jaWRycyksCiAgICAgICAgICAgIGNvdW50cmllcyA9IHRvX3NldChiYW4uY291bnRyaWVzKSwKICAgICAgICAgICAgdWFzID0gbG93ZXJfbGlzdChiYW4udXNlckFnZW50cyksCiAgICAgICAgICAgIGVtcHR5VUEgPSBiYW4uZW1wdHlVc2VyQWdlbnQgPT0gdHJ1ZSwKICAgICAgICB9CiAgICBlbmQKCiAgICBsb2NhbCBhY2MgPSBzcGVjLmFjY2VzcwogICAgaWYgdHlwZShhY2MpID09ICJ0YWJsZSIgdGhlbgogICAgICAgIG91dC5hY2Nlc3MgPSB7CiAgICAgICAgICAgIGFsbG93ID0gY29tcGlsZV9saXN0KGFjYy5hbGxvd0NpZHJzKSwKICAgICAgICAgICAgZGVueSA9IGNvbXBpbGVfbGlzdChhY2MuZGVueUNpZHJzKSwKICAgICAgICAgICAgYWxsb3dDb3VudHJpZXMgPSB0b19zZXQoYWNjLmFsbG93Q291bnRyaWVzKSwKICAgICAgICAgICAgbWV0aG9kcyA9IHRvX3NldChhY2MubWV0aG9kcyksCiAgICAgICAgfQogICAgZW5kCgogICAgbG9jYWwgaG90ID0gc3BlYy5ob3RsaW5rCiAgICBpZiB0eXBlKGhvdCkgPT0gInRhYmxlIiB0aGVuCiAgICAgICAgbG9jYWwgcmVmcyA9IHRvX3NldChob3QuYWxsb3dSZWZlcmVycywgdHJ1ZSkKICAgICAgICBpZiByZWZzIHRoZW4KICAgICAgICAgICAgb3V0LmhvdGxpbmsgPSB7IHJlZmVyZXJzID0gcmVmcywgYWxsb3dFbXB0eSA9IGhvdC5hbGxvd0VtcHR5IH49IGZhbHNlIH0KICAgICAgICBlbmQKICAgIGVuZAoKICAgIG91dC5ibG9ja1N0YXR1cyA9ICh0eXBlKHNwZWMuYmxvY2spID09ICJ0YWJsZSIgYW5kIHRvbnVtYmVyKHNwZWMuYmxvY2suc3RhdHVzKSkgb3IgNDAzCiAgICByZXR1cm4gb3V0CmVuZAoKbG9jYWwgZnVuY3Rpb24gcGFyc2UocmF3KQogICAgbG9jYWwgZW50cmllcyA9IGNqc29uLmRlY29kZShyYXcpCiAgICBpZiB0eXBlKGVudHJpZXMpIH49ICJ0YWJsZSIgdGhlbiByZXR1cm4ge30gZW5kCiAgICBsb2NhbCBvdXQsIG4gPSB7fSwgMAogICAgZm9yIF8sIGUgaW4gaXBhaXJzKGVudHJpZXMpIGRvCiAgICAgICAgaWYgdHlwZShlKSA9PSAidGFibGUiIHRoZW4KICAgICAgICAgICAgbiA9IG4gKyAxCiAgICAgICAgICAgIG91dFtuXSA9IHsgcGF0aFByZWZpeCA9IGUucGF0aFByZWZpeCwgc3BlYyA9IGNvbXBpbGVfc3BlYyhlLnNwZWMpIH0KICAgICAgICBlbmQKICAgIGVuZAogICAgcmV0dXJuIG91dAplbmQKCi0tIExSVS1jYWNoZWQgcGFyc2U6IHJldXNlIHRoZSBjb21waWxlZCBmb3JtIHVudGlsIHRoZSByYXcgZGljdCBzdHJpbmcgY2hhbmdlcy4KZnVuY3Rpb24gTS5nZXQoaG9zdCwgcmF3KQogICAgbG9jYWwgaGl0ID0gY2FjaGU6Z2V0KGhvc3QpCiAgICBpZiBoaXQgYW5kIGhpdC5yYXcgPT0gcmF3IHRoZW4gcmV0dXJuIGhpdC5wYXJzZWQgZW5kCiAgICBsb2NhbCBwYXJzZWQgPSBwYXJzZShyYXcpCiAgICBjYWNoZTpzZXQoaG9zdCwgeyByYXcgPSByYXcsIHBhcnNlZCA9IHBhcnNlZCB9KQogICAgcmV0dXJuIHBhcnNlZAplbmQKCnJldHVybiBNCg==",
|
|
40
|
+
"site_logger.lua": "LS0gc2l0ZV9sb2dnZXIubHVhCi0tIE9wZW5SZXN0eSBsb2dfYnlfbHVhIC0gcnVucyBBRlRFUiB0aGUgcmVzcG9uc2UgaXMgc2VudC4KLS0gUHVyZSBzaGFyZWQtZGljdCBhbmFseXRpY3MuICBObyBSZWRpcywgbm8gdGltZXJzIGZvciBjb3VudGVycywgbm8gYmF0Y2hpbmcuCi0tIEV2ZXJ5IGluY3IoKSBpcyBhdG9taWMgYWNyb3NzIHdvcmtlcnMuCi0tCi0tIFNoYXJlZCBkaWN0IGtleSBzY2hlbWEgKGFuYWx5dGljcyB6b25lKToKLS0gICBzOntkb21haW59OntlcG9jaF9taW59OnIgICAgICAgIHJlcXVlc3QgY291bnQgICAgICAgICAgICAgICAoVFRMIDI0aCkKLS0gICBzOntkb21haW59OntlcG9jaF9taW59OmkgICAgICAgIGJhbmR3aWR0aCBpbiAgYnl0ZXMgICAgICAgICAoVFRMIDI0aCkKLS0gICBzOntkb21haW59OntlcG9jaF9taW59Om8gICAgICAgIGJhbmR3aWR0aCBvdXQgYnl0ZXMgICAgICAgICAoVFRMIDI0aCkKLS0gICBzOntkb21haW59OntlcG9jaF9taW59OnQgICAgICAgIHJlc3BvbnNlIHRpbWUgc3VtIChzZWNvbmRzKSAoVFRMIDI0aCkKLS0gICBzOntkb21haW59OntlcG9jaF9taW59OnUgICAgICAgIHBhZ2UgKG5vbi1zdGF0aWMpIHJlcXVlc3RzICAoVFRMIDI0aCkKLS0gICBjOntkb21haW59OntlcG9jaF9taW59OntDQ30gICAgIGNvdW50cnkgcGVyIG1pbnV0ZSAgICAgICAgICAoVFRMIDI0aCkKLS0gICB0Ontkb21haW59OnIgLyA6aSAvIDpvICAgICAgICAgIGxpZmV0aW1lIHRvdGFscyAgICAgICAgICAgICAobm8gVFRMKQotLSAgIGQ6e2RvbWFpbn0gICAgICAgICAgICAgICAgICAgICAgZG9tYWluIGluZGV4IG1hcmtlciAgICAgICAgIChubyBUVEwpCi0tCi0tICAgRGFpbHkgcm9sbHVwLCBhbGwgdW5kZXIgb25lIGBnOntkb21haW59OntZWVlZTU1ERH06YCBwcmVmaXggc28gbWdtdF9hcGkncwotLSAgIC9hbmFseXRpY3MvZ2VvIHNlcnZlcyB0aGUgd2hvbGUgZGF5IGluIGEgU0lOR0xFIGRpY3Qgc2NhbjoKLS0gICBnOntkb21haW59OntZWVlZTU1ERH06e0NDfSAgICAgIGNvdW50cnkgaGl0IGNvdW50ICAgICAgICAgICAoVFRMIDQ4aCkKLS0gICBnOntkb21haW59OntZWVlZTU1ERH06diAgICAgICAgIGRpc3RpbmN0IHZpc2l0b3JzICAgICAgICAgICAoVFRMIDQ4aCkKLS0gICBnOntkb21haW59OntZWVlZTU1ERH06cDp7cGF0aH0gIHBhdGggaGl0IGNvdW50ICAgICAgICAgICAgICAoVFRMIDQ4aCkKLS0gICBnOntkb21haW59OntZWVlZTU1ERH06czp7Y29kZX0gIHN0YXR1cy1jb2RlIGNvdW50ICAgICAgICAgICAoVFRMIDQ4aCkKLS0KLS0gU2hhcmVkIGRpY3Qga2V5IHNjaGVtYSAodmlzaXRvcnMgem9uZSk6Ci0tICAgdnNhbHQ6e1lZWVlNTUREfSAgICAgICAgICAgICAgICBwZXItZGF5IGhhc2ggc2FsdCAgICAgICAgICAgKFRUTCA0OGgpCi0tICAgdmQ6e2RvbWFpbn06e1lZWVlNTUREfTp7aGFzaH0gICBkaXN0aW5jdC12aXNpdG9yIG1hcmtlciAgICAgKFRUTCA0OGgpCi0tCi0tIFNoYXJlZCBkaWN0IGtleSBzY2hlbWEgKHJlcXVlc3RfZGF0YSB6b25lKToKLS0gICBybG9nOntkb21haW59OnNlcSAgICAgICAgICAgICAgIG1vbm90b25pYyB3cml0ZSBwb2ludGVyCi0tICAgcmxvZzp7ZG9tYWlufTp7c2xvdH0gICAgICAgICAgICBKU09OIGVudHJ5IChyaW5nIGJ1ZikgICAgICAgKFRUTCAxaCkKLS0KLS0gVGhlIHJpbmcgaXMgQUxTTyB0aGUgbGl2ZSBzb3VyY2U6IHBpcGVfc3RyZWFtLmx1YSdzIFNTRSBlbmRwb2ludCByZWFkcyB0aGVzZQotLSBzbG90cyBieSBhIHBlci1jb25uZWN0aW9uIGN1cnNvciwgc28gdGhlcmUgaXMgbm8gc2VwYXJhdGUgbGl2ZSBxdWV1ZSBvcgotLSBzdWJzY3JpYmVyIGZsYWcg4oCUIGV2ZXJ5IHdhdGNoZXIgc2VlcyB0aGUgZnVsbCBzdHJlYW0gYW5kIHN0ZWFscyBmcm9tIG5vbmUuCi0tCi0tIE5PVEUgb24gYDp1YCDigJQgaXQgY291bnRzIG5vbi1zdGF0aWMgUkVRVUVTVFMsIG5vdCBwZW9wbGUuIEl0IHdhcyBzdXJmYWNlZCBhcwotLSAidW5pcXVlIElQcyIgYWxsIHRoZSB3YXkgdG8gdGhlIGRhc2hib2FyZCwgd2hpY2ggaXQgbmV2ZXIgd2FzLiBSZWFsIGRpc3RpbmN0Ci0tIHZpc2l0b3JzIGFyZSB0aGUgYHZkOmAvYDp2YCBwYWlyIGJlbG93LgoKbG9jYWwgY2pzb24gPSByZXF1aXJlICJjanNvbi5zYWZlIgoKLS0gU0FGRSBMT0FEOiBHZW9JUCBNb2R1bGUgKHBlci13b3JrZXIsIGNhY2hlZCBieSByZXF1aXJlKQpsb2NhbCBnZW9fb2ssIGdlbyA9IHBjYWxsKHJlcXVpcmUsICJrcmFmdC5nZW9fY291bnRyeSIpCmlmIG5vdCBnZW9fb2sgdGhlbgogICAgZ2VvID0gbmlsCiAgICBuZ3gubG9nKG5neC5XQVJOLCAiW3NpdGVfbG9nZ2VyXSBnZW9fY291bnRyeSBtb2R1bGUgbm90IGF2YWlsYWJsZS4gR2VvSVAgZGlzYWJsZWQuIikKZW5kCgpsb2NhbCBhbmFseXRpY3MgICAgPSBuZ3guc2hhcmVkLmFuYWx5dGljcwpsb2NhbCByZXF1ZXN0X2RhdGEgPSBuZ3guc2hhcmVkLnJlcXVlc3RfZGF0YQotLSBQZXItaG9zdCBlZGdlIGNvbmZpZywgcHVzaGVkIGJ5IHRoZSBBUEkgKHNlZSBtZ210X2FwaSdzIC9hbmFseXRpY3MvY29uZmlnKS4KLS0KLS0gVGhlIGBydWxlc2Agem9uZSwgTk9UIGBhbmFseXRpY3NgOiB0aGlzIGhvbGRzIGEgaGFuZGZ1bCBvZiBzbWFsbCBjb25maWcgdmFsdWVzIGFuZCBpcwotLSBuZXZlciB1bmRlciBldmljdGlvbiBwcmVzc3VyZSwgd2hlcmVhcyB0aGUgYW5hbHl0aWNzIHpvbmUgaXMgYSAyNTYgTUIgY2h1cm4gb2YgY291bnRlcnMuCi0tIEFuIGV2aWN0ZWQgZmxhZyB0aGVyZSB3b3VsZCBzaWxlbnRseSBzdG9wIHBhdGggY29sbGVjdGlvbiB3aXRoIG5vdGhpbmcgdG8gZXhwbGFpbiB3aHkuCmxvY2FsIHJ1bGVzX2RpY3QgICA9IG5neC5zaGFyZWQucnVsZXMKLS0gT3B0aW9uYWw6IGEgYm94IHdob3NlIG5naW54LmNvbmYgcHJlZGF0ZXMgdGhpcyB6b25lIGtlZXBzIHdvcmtpbmcsIGp1c3Qgd2l0aG91dAotLSBkaXN0aW5jdC12aXNpdG9yIGNvdW50cy4gTmV2ZXIgYXNzdW1lIGEgZGljdCBleGlzdHMuCmxvY2FsIHZpc2l0b3JzICAgICA9IG5neC5zaGFyZWQudmlzaXRvcnMKaWYgbm90IGFuYWx5dGljcyBvciBub3QgcmVxdWVzdF9kYXRhIHRoZW4gcmV0dXJuIGVuZAoKLS0g4pSA4pSAIEhlbHBlcnMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACgpsb2NhbCBmdW5jdGlvbiBub3JtYWxpemUoaG9zdCkKICAgIGlmIG5vdCBob3N0IHRoZW4gcmV0dXJuIG5pbCBlbmQKICAgIGxvY2FsIGggPSBob3N0Omxvd2VyKCkKICAgIGlmIGg6c3ViKDEsIDQpID09ICJ3d3cuIiB0aGVuIGggPSBoOnN1Yig1KSBlbmQKICAgIHJldHVybiBoCmVuZAoKbG9jYWwgX2RheSA9IHsgc3RyID0gIiIsIHRzID0gMCB9CmxvY2FsIGZ1bmN0aW9uIHRvZGF5KCkKICAgIGxvY2FsIG5vdyA9IG5neC5ub3coKQogICAgaWYgbm93IC0gX2RheS50cyA+IDYwIHRoZW4KICAgICAgICBfZGF5LnN0ciA9IG9zLmRhdGUoIiElWSVtJWQiLCBub3cpCiAgICAgICAgX2RheS50cyA9IG5vdwogICAgZW5kCiAgICByZXR1cm4gX2RheS5zdHIKZW5kCgotLSBGYXN0IGNoZWNrIGlmIFVSSSBpcyBhIHN0YXRpYyBhc3NldCAoZm9yIHVuaXF1ZV9yZXF1ZXN0cyBjb3VudGVyKQpsb2NhbCBmdW5jdGlvbiBpc19zdGF0aWNfYXNzZXQodSkKICAgIGxvY2FsIGxvd2VyID0gdTpsb3dlcigpCgogICAgLS0gU3RhdGljIGZpbGUgZXh0ZW5zaW9ucwogICAgaWYgbG93ZXI6bWF0Y2goIiUuanMkIikgb3IgbG93ZXI6bWF0Y2goIiUuY3NzJCIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiJS5qcGckIikgb3IgbG93ZXI6bWF0Y2goIiUuanBlZyQiKSBvcgogICAgICAgbG93ZXI6bWF0Y2goIiUucG5nJCIpIG9yIGxvd2VyOm1hdGNoKCIlLmdpZiQiKSBvcgogICAgICAgbG93ZXI6bWF0Y2goIiUuc3ZnJCIpIG9yIGxvd2VyOm1hdGNoKCIlLndlYnAkIikgb3IKICAgICAgIGxvd2VyOm1hdGNoKCIlLmljbyQiKSBvciBsb3dlcjptYXRjaCgiJS5ibXAkIikgb3IKICAgICAgIGxvd2VyOm1hdGNoKCIlLndvZmYyPyQiKSBvciBsb3dlcjptYXRjaCgiJS50dGYkIikgb3IKICAgICAgIGxvd2VyOm1hdGNoKCIlLmVvdCQiKSBvciBsb3dlcjptYXRjaCgiJS5vdGYkIikgb3IKICAgICAgIGxvd2VyOm1hdGNoKCIlLm1wNCQiKSBvciBsb3dlcjptYXRjaCgiJS53ZWJtJCIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiJS5tcDMkIikgb3IgbG93ZXI6bWF0Y2goIiUud2F2JCIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiJS5wZGYkIikgb3IgbG93ZXI6bWF0Y2goIiUuemlwJCIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiJS50YXIkIikgb3IgbG93ZXI6bWF0Y2goIiUuZ3okIikgb3IKICAgICAgIGxvd2VyOm1hdGNoKCIlLnhtbCQiKSBvciBsb3dlcjptYXRjaCgiJS5qc29uJCIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiJS50eHQkIikgb3IgbG93ZXI6bWF0Y2goIiUubWFwJCIpIHRoZW4KICAgICAgICByZXR1cm4gdHJ1ZQogICAgZW5kCgogICAgLS0gQ29tbW9uIHN0YXRpYyBwYXRocwogICAgaWYgbG93ZXI6bWF0Y2goIl4vX25leHQvc3RhdGljLyIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiXi9zdGF0aWMvIikgb3IKICAgICAgIGxvd2VyOm1hdGNoKCJeL2Fzc2V0cy8iKSBvcgogICAgICAgbG93ZXI6bWF0Y2goIl4vcHVibGljLyIpIG9yCiAgICAgICBsb3dlcjptYXRjaCgiL2Zhdmljb24lLmljbyIpIHRoZW4KICAgICAgICByZXR1cm4gdHJ1ZQogICAgZW5kCgogICAgcmV0dXJuIGZhbHNlCmVuZAoKLS0gQ29sbGFwc2UgYSByZXF1ZXN0IFVSSSBpbnRvIGEgbG93LWNhcmRpbmFsaXR5IGJ1Y2tldCBzdWl0YWJsZSBhcyBhIGRpY3Qga2V5LgotLSBXaXRob3V0IHRoaXMsICJ0b3AgcGF0aHMiIGlzIHVuYm91bmRlZDogZXZlcnkgP3Rva2VuPSwgZXZlcnkgL29yZGVycy80ODIxOSwgYW5kCi0tIGV2ZXJ5IDQwNCBhIHNjYW5uZXIgcHJvYmVzIG1pbnRzIGEgcGVybWFuZW50IGtleSwgYW5kIHRoZSBhbmFseXRpY3Mgem9uZQotLSBMUlUtZXZpY3RzIHJlYWwgY291bnRlcnMgdG8gc3RvcmUganVuay4KbG9jYWwgZnVuY3Rpb24gbm9ybWFsaXplX3BhdGgodSkKICAgIC0tIFF1ZXJ5IHN0cmluZyBjYXJyaWVzIGlkcy90b2tlbnMgYW5kIG5ldmVyIGlkZW50aWZpZXMgdGhlIHJvdXRlLgogICAgbG9jYWwgcGF0aCA9IHU6bWF0Y2goIl4oW14/I10qKSIpIG9yIHUKICAgIGlmIHBhdGggPT0gIiIgdGhlbiByZXR1cm4gIi8iIGVuZAogICAgLS0gTnVtZXJpYyBhbmQgVVVJRC9oZXggc2VnbWVudHMgYXJlIGlkcywgbm90IHJvdXRlczogL29yZGVycy80ODIxOSBhbmQKICAgIC0tIC9vcmRlcnMvNDgyMjAgYXJlIG9uZSBwYXRoLgogICAgcGF0aCA9IHBhdGg6Z3N1YigiLyVkKyIsICIvOmlkIikKICAgIHBhdGggPSBwYXRoOmdzdWIoIi8leCV4JXgleCV4JXgleCV4JS0/JXgqJS0/JXgqJS0/JXgqJS0/JXgqIiwgIi86aWQiKQogICAgLS0gQm91bmQgdGhlIGtleSBpdHNlbGYg4oCUIGEgbG9uZyBVUkkgbXVzdCBub3QgYmVjb21lIGEgbG9uZyBrZXkuCiAgICBpZiAjcGF0aCA+IDEyMCB0aGVuIHBhdGggPSBwYXRoOnN1YigxLCAxMjApIC4uICLigKYiIGVuZAogICAgcmV0dXJuIHBhdGgKZW5kCgotLSBSYXcgcmVxdWVzdCB0ZWxlbWV0cnkgbXVzdCBuZXZlciByZXRhaW4gY3JlZGVudGlhbHMgZnJvbSBhIFVSTC4gUXVlcnkKLS0gc3RyaW5ncyByb3V0aW5lbHkgY2FycnkgT0F1dGggY29kZXMsIHNpZ25lZCBVUkxzIGFuZCB0b2tlbnMsIHNvIGV4Y2x1ZGUgdGhlbQotLSBjb21wbGV0ZWx5LiBJbnZpdGF0aW9uIGNsYWltIGlkcyBhcmUgYmVhcmVyIGNyZWRlbnRpYWxzIGluIHRoZSBwYXRoIGl0c2VsZjsKLS0gY29sbGFwc2UgdGhvc2UgdHdvIGtub3duIHJvdXRlcyBiZWZvcmUgZWl0aGVyIHRvcC1wYXRoIGFnZ3JlZ2F0aW9uIG9yIHRoZQotLSBvbmUtaG91ciByZXF1ZXN0IHJpbmcgY2FuIG9ic2VydmUgdGhlbS4KbG9jYWwgZnVuY3Rpb24gdGVsZW1ldHJ5X3VyaSh1KQogICAgbG9jYWwgcGF0aCA9IHU6bWF0Y2goIl4oW14/I10qKSIpIG9yICIvIgogICAgaWYgcGF0aCA9PSAiIiB0aGVuIHJldHVybiAiLyIgZW5kCiAgICBpZiBwYXRoOm1hdGNoKCJeL2FjY2VwdCUtaW52aXRlL1teL10rIikgdGhlbgogICAgICAgIHJldHVybiAiL2FjY2VwdC1pbnZpdGUvOnRva2VuIgogICAgZW5kCiAgICBpZiBwYXRoOm1hdGNoKCJeL2FwaS9hdXRoL2ludml0YXRpb24lLXByZXZpZXcvW14vXSsiKSB0aGVuCiAgICAgICAgcmV0dXJuICIvYXBpL2F1dGgvaW52aXRhdGlvbi1wcmV2aWV3Lzp0b2tlbiIKICAgIGVuZAogICAgcmV0dXJuIHBhdGgKZW5kCgotLSDilIDilIAgRW51bWVyYWJsZSBzZXRzLCB3aXRob3V0IGEgem9uZSBzY2FuIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAotLQotLSBSZWFkaW5nIHRoZXNlIGNvdW50ZXJzIGJhY2sgdXNlZCB0byBuZWVkIGtleSBESVNDT1ZFUlksIGFuZCBhIHNoYXJlZCBkaWN0IG9mZmVycyBleGFjdGx5Ci0tIG9uZSBtZWNoYW5pc20gZm9yIHRoYXQ6IGBnZXRfa2V5c2AsIHdoaWNoIHdhbGtzIEVWRVJZIGtleSBpbiB0aGUgem9uZSBob2xkaW5nIGl0cyBsb2NrLgotLSBDb3N0IHNjYWxlZCB3aXRoIGhvdyBtdWNoIHdhcyBpbiB0aGUgMjU2IE1CIHpvbmUsIG5vdCB3aXRoIHdoYXQgd2FzIGJlaW5nIGFza2VkIGZvciwgYW5kCi0tIGl0IHJhbiBvbiB0aGUgbWdtdCBwYXRoIGZvdXIgZGlmZmVyZW50IHdheXMuCi0tCi0tIFNvIGV2ZXJ5IHVuYm91bmRlZCBzZXQgbm93IGNhcnJpZXMgaXRzIG93biBpbmRleDogYSBjb3VudGVyIHBsdXMgbnVtYmVyZWQgc2xvdHMuCi0tCi0tICAgICA8Y291bnRlcj4gICAgICAgIGhvdyBtYW55IGRpc3RpbmN0IG1lbWJlcnMKLS0gICAgIDxwcmVmaXg+PG4+ICAgICAgdGhlIG4tdGggbWVtYmVyCi0tCi0tIEEgcmVhZGVyIHJlYWRzIHRoZSBjb3VudGVyIGFuZCB0aGVuIHJlYWRzIHNsb3RzIDEuLm4uIEJvdW5kZWQgYnkgdGhlIGFuc3dlci4KLS0KLS0gVGhlIHdyaXRlIG9ubHkgaGFwcGVucyBvbiBhIG1lbWJlcidzIEZJUlNUIHNpZ2h0aW5nLCBzbyBzdGVhZHkgc3RhdGUgY29zdHMgbm90aGluZzogdGhlCi0tIG1pbGxpb250aCByZXF1ZXN0IGZyb20gR2VybWFueSB0b2RheSB0YWtlcyB0aGUgcGxhaW4gYGluY3JgIHBhdGggYW5kIHRvdWNoZXMgbm8gaW5kZXguCmxvY2FsIGZ1bmN0aW9uIGluZGV4X2FkZChjb3VudGVyX2tleSwgc2xvdF9wcmVmaXgsIG1lbWJlciwgdHRsKQogICAgbG9jYWwgbiA9IGFuYWx5dGljczppbmNyKGNvdW50ZXJfa2V5LCAxLCAwLCB0dGwpCiAgICBpZiBuIHRoZW4gYW5hbHl0aWNzOnNldChzbG90X3ByZWZpeCAuLiBuLCBtZW1iZXIsIHR0bCkgZW5kCmVuZAoKLS0tIEFkZCAxIHRvIGEgY291bnRlciwgY3JlYXRpbmcgaXQgKHdpdGggVFRMKSBhbmQgaW5kZXhpbmcgaXQgb24gZmlyc3Qgc2lnaHRpbmcuCi0tCi0tIGBpbmNyYCB3aXRoIG5vIGBpbml0YCByZXR1cm5zIG5pbCBmb3IgYW4gYWJzZW50IGtleSwgd2hpY2ggZG91YmxlcyBhcyB0aGUgZXhpc3RlbmNlCi0tIHByb2JlIOKAlCBzbyB0aGUgY29tbW9uIGNhc2UgaXMgT05FIGhhc2ggb3BlcmF0aW9uLiBUVEwgaXMgc2V0IGJ5IHRoZSBjcmVhdGluZyBgc2FmZV9hZGRgCi0tIHJhdGhlciB0aGFuIHBhc3NlZCB0byBgaW5jcmA6IHNoZGljdCByZWplY3RzIGBpbml0X3R0bGAgd2l0aG91dCBgaW5pdGAsIGFuZCB0aGF0IHJhaXNlcyBhCi0tIEx1YSBlcnJvciB3aGljaCBhYm9ydHMgdGhlIHdob2xlIGxvZyBoYW5kbGVyIChpdCBoYXMgc2lsZW50bHkgemVyb2VkIGV2ZXJ5IGNvdW50ZXIgYmVsb3cKLS0gaXQgYmVmb3JlKS4KbG9jYWwgZnVuY3Rpb24gYnVtcF9pbmRleGVkKGtleSwgdHRsLCBjb3VudGVyX2tleSwgc2xvdF9wcmVmaXgsIG1lbWJlcikKICAgIGlmIGFuYWx5dGljczppbmNyKGtleSwgMSkgdGhlbiByZXR1cm4gZW5kCiAgICBpZiBhbmFseXRpY3M6c2FmZV9hZGQoa2V5LCAxLCB0dGwpIHRoZW4KICAgICAgICBpbmRleF9hZGQoY291bnRlcl9rZXksIHNsb3RfcHJlZml4LCBtZW1iZXIsIHR0bCkKICAgIGVsc2UKICAgICAgICAtLSBBbm90aGVyIHdvcmtlciBjcmVhdGVkIGl0IGJldHdlZW4gb3VyIHByb2JlIGFuZCBvdXIgYWRkOyBvdXIgKzEgc3RpbGwgY291bnRzLgogICAgICAgIGFuYWx5dGljczppbmNyKGtleSwgMSkKICAgIGVuZAplbmQKCmxvY2FsIFJJTkcgICA9IDEwMDAKbG9jYWwgRDI0SCAgID0gODY0MDAKbG9jYWwgRDQ4SCAgID0gMTcyODAwCmxvY2FsIEQxSCAgICA9IDM2MDAKCi0tIERpc3RpbmN0IHBhdGhzIHRyYWNrZWQgcGVyIGRvbWFpbiBwZXIgZGF5LiBQYXN0IHRoaXMgdGhlIHRhaWwgZm9sZHMgaW50bwotLSAib3RoZXIiIHJhdGhlciB0aGFuIGdyb3dpbmcgdGhlIHpvbmUg4oCUIGEgVVJMLWZ1enppbmcgYm90IGlzIGNhcHBlZCBhdCBvbmUKLS0gZXh0cmEga2V5LCBub3QgdGhvdXNhbmRzLgpsb2NhbCBQQVRIX0NBUkRJTkFMSVRZX0NBUCA9IDIwMDAKCi0tIOKUgOKUgCBDYXB0dXJlIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAoKbG9jYWwgaG9zdCA9IG5vcm1hbGl6ZShuZ3gudmFyLmhvc3QpCmlmIG5vdCBob3N0IHRoZW4gcmV0dXJuIGVuZAoKbG9jYWwgaXAgICAgICA9IG5neC52YXIucmVtb3RlX2FkZHIgICAgb3IgIjAuMC4wLjAiCmxvY2FsIHRzICAgICAgPSBuZ3gubm93KCkKbG9jYWwgdWEgICAgICA9IG5neC52YXIuaHR0cF91c2VyX2FnZW50IG9yICIiCmxvY2FsIHVyaSAgICAgPSB0ZWxlbWV0cnlfdXJpKG5neC52YXIucmVxdWVzdF91cmkgb3IgIi8iKQpsb2NhbCByZXFfbGVuID0gdG9udW1iZXIobmd4LnZhci5yZXF1ZXN0X2xlbmd0aCkgb3IgMApsb2NhbCBieXRlcyAgID0gdG9udW1iZXIobmd4LnZhci5ieXRlc19zZW50KSAgICAgb3IgMApsb2NhbCBydCAgICAgID0gdG9udW1iZXIobmd4LnZhci5yZXF1ZXN0X3RpbWUpICAgb3IgMCAgLS0gc2Vjb25kcyAoZmxvYXQpCmxvY2FsIG1ldGhvZCAgPSBuZ3gudmFyLnJlcXVlc3RfbWV0aG9kIG9yICJHRVQiCmxvY2FsIHN0YXR1cyAgPSBuZ3gudmFyLnN0YXR1cyAgICAgICAgIG9yICIwIgoKLS0gQ2xpZW50IGNvdW50cnksIHJlc29sdmVkIE9OQ0UgcGVyIHJlcXVlc3QuCi0tCi0tIEhvaXN0ZWQgb3V0IG9mIHRoZSBnZW8gYmxvY2sgYmVjYXVzZSBib3RoIHRoZSBkYWlseS9wZXItbWludXRlIHJvbGx1cHMgYW5kIHRoZSByYXcKLS0gcmluZyBidWZmZXIgbmVlZCBpdC4gVGhlIHJpbmcgaXMgdGhlIHNpbmdsZSBzb3VyY2UgZm9yIHRoZSByZXF1ZXN0IGxvZyDigJQgL2xvZ3MvcmVjZW50Ci0tIHJlYWRzIGl0IGRpcmVjdGx5IGFuZCB0aGUgbGl2ZSBTU0Ugc3RyZWFtIChwaXBlX3N0cmVhbS5sdWEpIHJlYWRzIHRoZSBzYW1lIHNsb3RzIGJ5Ci0tIGN1cnNvciDigJQgc28gcmVzb2x2aW5nIHRoZSBjb3VudHJ5IGhlcmUgbWVhbnMgZXZlcnkgcm93IGNhcnJpZXMgaXRzIGZsYWcgbm8gbWF0dGVyCi0tIHdoaWNoIHBhdGggZGVsaXZlcmVkIGl0LiBBbiBlYXJsaWVyIHNwbGl0IChsb29rZWQgdXAgaW4gdGhlIHJvbGx1cCwgYWdhaW4gaW4gYQotLSBzZXBhcmF0ZSBsaXZlIHBpcGUpIGxlZnQgdGhlIHJpbmcgd2l0aCBubyBjb3VudHJ5IGF0IGFsbC4KLS0KLS0gcGNhbGwnZCBiZWNhdXNlIGEgY29ycnVwdCBvciBwYXJ0aWFsbHktd3JpdHRlbiBtbWRiIG1ha2VzIHRoZSBsb29rdXAgcmFpc2UsIGFuZCBhbgotLSBlcnJvciBoZXJlIHdvdWxkIGFib3J0IGV2ZXJ5IGNvdW50ZXIgYmVsb3cgaXQgKHNlZSB0aGUgc2VjdGlvbiBoZWFkZXIpLgpsb2NhbCBjYyA9IG5pbAppZiBnZW8gYW5kIGdlby5nZXRfY291bnRyeV9jb2RlIHRoZW4KICAgIGxvY2FsIG9rX2NjLCByZXMgPSBwY2FsbChnZW8uZ2V0X2NvdW50cnlfY29kZSwgaXApCiAgICBpZiBva19jYyBhbmQgdHlwZShyZXMpID09ICJzdHJpbmciIGFuZCByZXMgfj0gIiIgdGhlbiBjYyA9IHJlcyBlbmQKZW5kCgotLSDilIDilIAgMS4gTWludXRlLWJ1Y2tldCBjb3VudGVycyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKCmxvY2FsIG1pbnV0ZSA9IG1hdGguZmxvb3IodHMgLyA2MCkKbG9jYWwgcCA9ICJzOiIgLi4gaG9zdCAuLiAiOiIgLi4gbWludXRlCgphbmFseXRpY3M6aW5jcihwIC4uICI6ciIsIDEsICAgICAgMCwgRDI0SCkKYW5hbHl0aWNzOmluY3IocCAuLiAiOmkiLCByZXFfbGVuLCAwLCBEMjRIKQphbmFseXRpY3M6aW5jcihwIC4uICI6byIsIGJ5dGVzLCAgIDAsIEQyNEgpCgotLSBSZXNwb25zZSB0aW1lIGFzIGZsb2F0IHNlY29uZHMgKG1hdGNoZXMgb3JpZ2luYWwgcHJlY2lzaW9uKQppZiBydCA+IDAgdGhlbgogICAgLS0gc2FmZV9hZGQgaW5pdGlhbGl6ZXMsIGluY3IgYWRkcyAtIGVtdWxhdGUgSElOQ1JCWUZMT0FUIHdpdGggaW50ZWdlciBtaWNyb3MKICAgIGxvY2FsIHJ0X3VzID0gbWF0aC5mbG9vcihydCAqIDEwMDAwMDApCiAgICBhbmFseXRpY3M6aW5jcihwIC4uICI6dCIsIHJ0X3VzLCAwLCBEMjRIKQplbmQKCi0tIFVuaXF1ZSAobm9uLXN0YXRpYykgcmVxdWVzdCBjb3VudGVyCmlmIG5vdCBpc19zdGF0aWNfYXNzZXQodXJpKSB0aGVuCiAgICBhbmFseXRpY3M6aW5jcihwIC4uICI6dSIsIDEsIDAsIEQyNEgpCmVuZAoKLS0g4pSA4pSAIDIuIExpZmV0aW1lIHRvdGFscyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIAKCmFuYWx5dGljczppbmNyKCJ0OiIgLi4gaG9zdCAuLiAiOnIiLCAxLCAgICAgICAwKQphbmFseXRpY3M6aW5jcigidDoiIC4uIGhvc3QgLi4gIjppIiwgcmVxX2xlbiwgMCkKYW5hbHl0aWNzOmluY3IoInQ6IiAuLiBob3N0IC4uICI6byIsIGJ5dGVzLCAgIDApCgotLSBEb21haW4gaW5kZXguIGBzYWZlX2FkZGAgcmV0dXJuaW5nIHRydWUgbWVhbnMgdGhpcyBpcyB0aGUgZmlyc3QgcmVxdWVzdCB0aGlzIGJveCBoYXMKLS0gZXZlciBzZWVuIGZvciB0aGUgaG9zdCwgd2hpY2ggaXMgZXhhY3RseSB3aGVuIHRoZSBlbnVtZXJhYmxlIGluZGV4IG5lZWRzIGFwcGVuZGluZyDigJQKLS0gc28gZG9tYWluIGRpc2NvdmVyeSBubyBsb25nZXIgY29zdHMgYSB6b25lIHNjYW4gZWl0aGVyLgppZiBhbmFseXRpY3M6c2FmZV9hZGQoImQ6IiAuLiBob3N0LCAxKSB0aGVuCiAgICBpbmRleF9hZGQoImRuIiwgImRpOiIsIGhvc3QpCmVuZAoKLS0g4pSA4pSAIDMuIERhaWx5IHJvbGx1cDogZ2VvLCB2aXNpdG9ycywgcGF0aHMsIHN0YXR1c2VzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAotLQotLSBFYWNoIHN1Yi1ibG9jayBpcyBwY2FsbCdkIFNFUEFSQVRFTFksIGFuZCB0aGF0IGlzIGxvYWQtYmVhcmluZyByYXRoZXIgdGhhbgotLSBkZWZlbnNpdmUgaGFiaXQuIEEgcmFpc2VkIGVycm9yIGluIGxvZ19ieV9sdWEgYWJvcnRzIHRoZSByZW1haW5kZXIgb2YgdGhlCi0tIGhhbmRsZXIsIHNvIG9uZSBiYWQgc2hkaWN0IGNhbGwgc2lsZW50bHkgemVyb2VzIGV2ZXJ5IGNvdW50ZXIgd3JpdHRlbiBhZnRlciBpdCDigJQKLS0gd2hpY2ggaXMgZXhhY3RseSB3aGF0IGFuIGBpbmNyKC4uLiwgbmlsLCB0dGwpYCBoZXJlIGRpZDogcGF0aHMgQU5EIHN0YXR1c2VzIHJlYWQKLS0gYXMgIm5vIHRyYWZmaWMiIHdoaWxlIHJlcXVlc3RzIGFuZCBiYW5kd2lkdGggbG9va2VkIHBlcmZlY3QuIElzb2xhdGluZyB0aGVtCi0tIG1lYW5zIGEgZnV0dXJlIGVkaXQgY2FuIGxvc2UgYXQgbW9zdCBpdHMgb3duIG1ldHJpYy4KCmxvY2FsIGRheSAgPSB0b2RheSgpCmxvY2FsIGdwZnggPSAiZzoiIC4uIGhvc3QgLi4gIjoiIC4uIGRheSAuLiAiOiIKCi0tIDNhLiBHZW9JUC4gYGNjYCB3YXMgcmVzb2x2ZWQgb25jZSBhYm92ZSBhbmQgaXMgcmV1c2VkIGJ5IHRoZSByaW5nIGJ1ZmZlciBhbmQgdGhlCi0tIGxpdmUgcGlwZSwgc28gYSByZXF1ZXN0IGNvc3RzIGV4YWN0bHkgb25lIG1tZGIgbG9va3VwIG5vIG1hdHRlciBob3cgbWFueSBjb25zdW1lcnMKLS0gcmVwb3J0IGl0cyBjb3VudHJ5LgppZiBjYyB0aGVuCiAgICBwY2FsbChmdW5jdGlvbigpCiAgICAgICAgLS0gRGFpbHkgZ2VvIChmb3IgL2FuYWx5dGljcy9nZW8gZW5kcG9pbnQpCiAgICAgICAgYnVtcF9pbmRleGVkKGdwZnggLi4gY2MsIEQ0OEgsIGdwZnggLi4gImNuIiwgZ3BmeCAuLiAiY2k6IiwgY2MpCiAgICAgICAgLS0gUGVyLW1pbnV0ZSBnZW8gKGZvciB0aGUgdGltZS1zZXJpZXMgY291bnRyeSBicmVha2Rvd24pLiBJbmRleGVkIHBlciBNSU5VVEUsIHNvCiAgICAgICAgLS0gdGhlIHNjcmFwZXIgcmVhZHMgb25seSB0aGUgbWludXRlcyBpbiBpdHMgd2luZG93LgogICAgICAgIGxvY2FsIG1wZnggPSAiYzoiIC4uIGhvc3QgLi4gIjoiIC4uIG1pbnV0ZSAuLiAiOiIKICAgICAgICBidW1wX2luZGV4ZWQobXBmeCAuLiBjYywgRDI0SCwgbXBmeCAuLiAibiIsIG1wZnggLi4gImk6IiwgY2MpCiAgICBlbmQpCmVuZAoKLS0gM2IuIERpc3RpbmN0IHZpc2l0b3JzIOKAlCBhIENPVU5ULCBuZXZlciBhbiBpZGVudGl0eS4KLS0KLS0gVGhlIGFkZHJlc3MgaXMgaGFzaGVkIHdpdGggYSBzYWx0IHRoYXQgaXMgZ2VuZXJhdGVkIG9uIHRoaXMgYm94LCByb3RhdGVzIGRhaWx5LAotLSBhbmQgaXMgbmV2ZXIgd3JpdHRlbiBhbnl3aGVyZSBidXQgdGhpcyBzaGFyZWQgZGljdCwgc28gdGhlIG1hcmtlciBrZXlzIGFyZSBub3QKLS0gcmV2ZXJzaWJsZSB0byBhbiBJUCBhbmQgYXJlIHdvcnRobGVzcyB0aGUgbmV4dCBkYXkuIE9ubHkgdGhlIHJlc3VsdGluZyBjb3VudGVyCi0tIGlzIGV2ZXIgZmx1c2hlZCB0byBQb3N0Z3Jlczsgbm8gcGVyLXZpc2l0b3Igcm93IGV4aXN0cyBhdCBhbnkgbGF5ZXIuIFRoYXQgaXMKLS0gd2hhdCBsZXRzIHVzIHJlcG9ydCByZWFsIHZpc2l0b3IgbnVtYmVycyB3aGlsZSBzdGlsbCBub3QgY29sbGVjdGluZyBiZWhhdmlvdXJhbAotLSBhbmFseXRpY3Mgb24gYW55b25lJ3MgZW5kIHVzZXJzLgotLQotLSBQZXIgREFZLCBub3QgcGVyIG1pbnV0ZTogYSBwZXItbWludXRlIHNldCBpcyB+MTQ0MHggdGhlIGtleXMgZm9yIGEgbnVtYmVyCi0tIG5vYm9keSByZWFkcywgYW5kIHdvdWxkIGV2aWN0IHRoZSBjb3VudGVycyBpdCBleGlzdHMgdG8gYW5ub3RhdGUuCnBjYWxsKGZ1bmN0aW9uKCkKaWYgdmlzaXRvcnMgdGhlbgogICAgbG9jYWwgc2FsdF9rZXkgPSAidnNhbHQ6IiAuLiBkYXkKICAgIGxvY2FsIHNhbHQgPSB2aXNpdG9yczpnZXQoc2FsdF9rZXkpCiAgICBpZiBub3Qgc2FsdCB0aGVuCiAgICAgICAgLS0gRmlyc3Qgd3JpdGVyIHdpbnM7IGEgcmFjaW5nIHdvcmtlcidzIHNhZmVfYWRkIGZhaWxzIGFuZCBpdCByZS1yZWFkcy4gVGhlCiAgICAgICAgLS0gc2FsdCBvbmx5IGhhcyB0byBiZSB1bnByZWRpY3RhYmxlIGFuZCBzdGFibGUgZm9yIHRoZSBkYXkuCiAgICAgICAgc2FsdCA9IHRvc3RyaW5nKG5neC5ub3coKSkgLi4gdG9zdHJpbmcobWF0aC5yYW5kb20oMSwgMjE0NzQ4MzY0NykpCiAgICAgICAgbG9jYWwgb2sgPSB2aXNpdG9yczpzYWZlX2FkZChzYWx0X2tleSwgc2FsdCwgRDQ4SCkKICAgICAgICBpZiBub3Qgb2sgdGhlbiBzYWx0ID0gdmlzaXRvcnM6Z2V0KHNhbHRfa2V5KSBvciBzYWx0IGVuZAogICAgZW5kCiAgICAtLSBzYWZlX2FkZCBpcyB0aGUgZGVkdXA6IGl0IHN1Y2NlZWRzIE9OTFkgb24gdGhpcyB2aXNpdG9yJ3MgZmlyc3QgcmVxdWVzdAogICAgLS0gdG9kYXksIHNvIHRoZSBjb3VudGVyIGJlbG93IGluY3JlbWVudHMgZXhhY3RseSBvbmNlIHBlciBkaXN0aW5jdCB2aXNpdG9yLgogICAgbG9jYWwgbWFya2VyID0gInZkOiIgLi4gaG9zdCAuLiAiOiIgLi4gZGF5IC4uICI6IiAuLiBuZ3guY3JjMzJfbG9uZyhzYWx0IC4uIGlwKQogICAgaWYgdmlzaXRvcnM6c2FmZV9hZGQobWFya2VyLCAxLCBENDhIKSB0aGVuCiAgICAgICAgYW5hbHl0aWNzOmluY3IoZ3BmeCAuLiAidiIsIDEsIDAsIEQ0OEgpCiAgICBlbmQKZW5kCmVuZCkKCi0tIDNjLiBUb3AgcGF0aHMg4oCUIE9QVC1JTiwgbm9uLXN0YXRpYyBvbmx5LCBub3JtYWxpemVkIGFuZCBjYXJkaW5hbGl0eS1jYXBwZWQuCi0tCi0tIE9mZiB1bmxlc3MgdGhlIHByb2plY3QgdHVybmVkIGl0IG9uLCBiZWNhdXNlIHRoaXMgb25lIGJsb2NrIGlzIHRoZSBtb3N0IGV4cGVuc2l2ZSB0aGluZwotLSB0aGUgbG9nIGhhbmRsZXIgZG9lcy4gTWVhc3VyZWQgb24gdGhlIHNoaXBwZWQgZWRnZSBpbWFnZSwgcGVyIHJlcXVlc3Q6Ci0tCi0tICAgICBwYXRocyAod2hvbGUgYmxvY2spICAgICAgICAxLjcyIHVzICAgICAgPC0gNTclIG9mIHRoZSBjb3VudGVyIHBhdGgKLS0gICAgICAgb2Ygd2hpY2ggc3RyaW5nIHdvcmsgICAgIDEuMzggdXMgICAgICBub3JtYWxpemVfcGF0aCArIGlzX3N0YXRpY19hc3NldAotLSAgICAgbWludXRlIGJ1Y2tldHMgKDUgaW5jcikgICAgMC42MSB1cwotLSAgICAgY291bnRyeSAoMiBpbmNyKSAgICAgICAgICAgMC4yNCB1cwotLSAgICAgc3RhdHVzICgxIGluY3IpICAgICAgICAgICAgMC4xNCB1cwotLSAgICAgdGhpcyBmbGFnIHJlYWQgKDEgZ2V0KSAgICAgMC4wNyB1cwotLQotLSBTbyB0aGUgZ2F0ZSBjb3N0cyAwLjA3IHVzIGFuZCBzYXZlcyAxLjcyIHVzIOKAlCB0aGUgY291bnRlciBwYXRoIGRyb3BzIGZyb20gfjMuMCB1cyB0bwotLSB+MS4zNSB1cyB3aXRoIHBhdGhzIG9mZi4gSXQgaXMgYWxzbyB0aGUgaGlnaGVzdC1jYXJkaW5hbGl0eSBkaW1lbnNpb24gKHVwIHRvCi0tIFBBVEhfQ0FSRElOQUxJVFlfQ0FQIGtleXMgcGVyIGRvbWFpbiBwZXIgZGF5LCBhZ2FpbnN0IH4yMDAgY291bnRyaWVzIGFuZCBhIGZldyBkb3plbgotLSBzdGF0dXNlcykgYW5kIHRoZSBsYXJnZXN0IGNvbHVtbiBpbiB0aGUgZGFpbHkgcm9sbHVwLgotLQotLSBBYnNlbnQgZmxhZyA9IG9mZi4gQSBib3ggd2hvc2UgZGljdCB3YXMganVzdCByZXN0YXJ0ZWQgdGhlcmVmb3JlIGNvbGxlY3RzIG5vdGhpbmcgdW50aWwKLS0gdGhlIEFQSSByZS1wdXNoZXMsIHdoaWNoIGlzIHRoZSBzYWZlIGRpcmVjdGlvbjogbm8gZGF0YSBiZWF0cyBkYXRhIG5vYm9keSBhc2tlZCB0byBwYXkKLS0gZm9yLiBUaGUgREIgaXMgdGhlIHNvdXJjZSBvZiB0cnV0aCBhbmQgcmUtcHVzaGVzIG9uIGV2ZXJ5IHJvdXRlIGFwcGx5Lgpsb2NhbCBjb2xsZWN0X3BhdGhzID0gcnVsZXNfZGljdCBhbmQgcnVsZXNfZGljdDpnZXQoImNmZzoiIC4uIGhvc3QgLi4gIjpwYXRocyIpCgpwY2FsbChmdW5jdGlvbigpCmlmIGNvbGxlY3RfcGF0aHMgYW5kIG5vdCBpc19zdGF0aWNfYXNzZXQodXJpKSB0aGVuCiAgICAtLSBIb2lzdGVkOiBub3JtYWxpemVfcGF0aCBpcyB0aGUgc2luZ2xlIG1vc3QgZXhwZW5zaXZlIGNhbGwgaW4gdGhpcyBoYW5kbGVyICh+MS40IHVzCiAgICAtLSBvZiBzdHJpbmcgd29yayksIHNvIGl0IHJ1bnMgZXhhY3RseSBvbmNlIGV2ZW4gdGhvdWdoIGJvdGggdGhlIGNvdW50ZXIga2V5IGFuZCB0aGUKICAgIC0tIGluZGV4IHNsb3QgbmVlZCBpdHMgcmVzdWx0LgogICAgbG9jYWwgbm9ybSA9IG5vcm1hbGl6ZV9wYXRoKHVyaSkKICAgIGxvY2FsIHBhdGhfa2V5ID0gZ3BmeCAuLiAicDoiIC4uIG5vcm0KICAgIC0tIGluY3ItdGhlbi1hZGQ6IHRoZSBob3QgcGF0aCBpcyBPTkUgaGFzaCBoaXQgb24gYW4gZXhpc3Rpbmcga2V5LiBgaW5jcmAgd2l0aAogICAgLS0gbm8gaW5pdCByZXR1cm5zIG5pbCBmb3IgYW4gYWJzZW50IGtleSwgd2hpY2ggZG91YmxlcyBhcyB0aGUgZXhpc3RlbmNlIHByb2JlLAogICAgLS0gc28gb25seSBhIHBhdGggdW5zZWVuIHRvZGF5IHJlYWNoZXMgdGhlIGNhcCBjaGVjayBiZWxvdy4KICAgIC0tCiAgICAtLSBEZWxpYmVyYXRlbHkgbm8gaW5pdF90dGwgaGVyZTogc2hkaWN0IHJlamVjdHMgaW5pdF90dGwgdW5sZXNzIGluaXQgaXMgYWxzbwogICAgLS0gZ2l2ZW4gKCInaW5pdF90dGwnIG11c3QgYmUgdXNlZCB3aXRoICdpbml0JyIpLCBhbmQgdGhhdCByYWlzZXMgYSBMdWEgZXJyb3IKICAgIC0tIHdoaWNoIGFib3J0cyB0aGUgd2hvbGUgbG9nIGhhbmRsZXIg4oCUIHRha2luZyB0aGUgc3RhdHVzIGNvdW50ZXJzIGJlbG93IGRvd24KICAgIC0tIHdpdGggaXQuIFRoZSBUVEwgaXMgc2V0IGJ5IHRoZSBzYWZlX2FkZCBvbiB0aGUgY3JlYXRpbmcgcmVxdWVzdCBpbnN0ZWFkLgogICAgaWYgbm90IGFuYWx5dGljczppbmNyKHBhdGhfa2V5LCAxKSB0aGVuCiAgICAgICAgbG9jYWwgZGlzdGluY3QgPSBhbmFseXRpY3M6aW5jcihncGZ4IC4uICJwbiIsIDEsIDAsIEQ0OEgpIG9yIDAKICAgICAgICBpZiBkaXN0aW5jdCA+IFBBVEhfQ0FSRElOQUxJVFlfQ0FQIHRoZW4KICAgICAgICAgICAgYW5hbHl0aWNzOmluY3IoZ3BmeCAuLiAicDpvdGhlciIsIDEsIDAsIEQ0OEgpCiAgICAgICAgZWxzZQogICAgICAgICAgICAtLSBgcG5gIHdhcyBhbHJlYWR5IHRoZSBkaXN0aW5jdC1wYXRoIGNvdW50ZXIsIHNvIHRoZSBzbG90cyBqdXN0IGdpdmUgaXQgYW4KICAgICAgICAgICAgLS0gZW51bWVyYWJsZSBzaWRlLiBTdG9yZWQgV0lUSE9VVCB0aGUgInA6IiBwcmVmaXg7IHRoZSByZWFkZXIgYWRkcyBpdCBiYWNrLgogICAgICAgICAgICBpZiBhbmFseXRpY3M6c2FmZV9hZGQocGF0aF9rZXksIDEsIEQ0OEgpIHRoZW4KICAgICAgICAgICAgICAgIGFuYWx5dGljczpzZXQoZ3BmeCAuLiAicGk6IiAuLiBkaXN0aW5jdCwgbm9ybSwgRDQ4SCkKICAgICAgICAgICAgZW5kCiAgICAgICAgZW5kCiAgICBlbmQKZW5kCmVuZCkKCi0tIDNkLiBTdGF0dXMtY29kZSBtaXguIEJvdW5kZWQgYnkgY29uc3RydWN0aW9uIChhIGZldyBkb3plbiBjb2RlcykuCnBjYWxsKGZ1bmN0aW9uKCkKICAgIGJ1bXBfaW5kZXhlZChncGZ4IC4uICJzOiIgLi4gc3RhdHVzLCBENDhILCBncGZ4IC4uICJzbiIsIGdwZnggLi4gInNpOiIsIHN0YXR1cykKZW5kKQoKLS0g4pSA4pSAIDQuIFJhdyByZXF1ZXN0IHJpbmcgYnVmZmVyIChhbHNvIHRoZSBsaXZlIFNTRSBzb3VyY2UpIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAotLQotLSBgc2VxYCBpcyBjbGFpbWVkIEJFRk9SRSBlbmNvZGluZyBzbyB0aGUgc3RvcmVkIEpTT04gY2FuIGNhcnJ5IGEgZGV0ZXJtaW5pc3RpYwotLSBpZCAoYHtob3N0fTp7c2VxfWApLiBUaGF0IGlkIGlzIHRoZSBkZWR1cCBrZXkgZXZlcnl3aGVyZSBkb3duc3RyZWFtOiAvbG9ncy9yZWNlbnQKLS0gcmV0dXJucyB0aGVzZSBlbnRyaWVzIHZlcmJhdGltLCBhbmQgcGlwZV9zdHJlYW0ubHVhIHN0cmVhbXMgdGhlIHNhbWUgc2xvdHMgbGl2ZSwKLS0gc28gdGhlIHNhbWUgcmVxdWVzdCByZWFjaGVzIHRoZSBjbGllbnQgd2l0aCBvbmUgc3RhYmxlIGlkIGluc3RlYWQgb2YgYSBmcmVzaAotLSByYW5kb20gb25lIHBlciBzb3VyY2UuIGBpbmNyYCB3aXRoIGluaXQgMCBuZXZlciByZXR1cm5zIG5pbCBoZXJlOyBndWFyZCBhbnl3YXkKLS0gc28gYSBzaGRpY3QgaGljY3VwIGNhbid0IGluZGV4IGEgbmlsIGludG8gdGhlIHNsb3Qga2V5LgoKcGNhbGwoZnVuY3Rpb24oKQogICAgbG9jYWwgc2VxID0gcmVxdWVzdF9kYXRhOmluY3IoInJsb2c6IiAuLiBob3N0IC4uICI6c2VxIiwgMSwgMCkKICAgIGlmIG5vdCBzZXEgdGhlbiByZXR1cm4gZW5kCiAgICBsb2NhbCBva19qLCBqID0gcGNhbGwoY2pzb24uZW5jb2RlLCB7CiAgICAgICAgaWQgICAgID0gaG9zdCAuLiAiOiIgLi4gc2VxLAogICAgICAgIGlwICAgICA9IGlwLAogICAgICAgIC0tIG5pbCBpcyBzaW1wbHkgb21pdHRlZCBieSBjanNvbiwgc28gYSBib3ggd2l0aCBubyBHZW9JUCB3cml0ZXMgdGhlIHNhbWUgc2hhcGUKICAgICAgICAtLSBtaW51cyB0aGlzIGtleSByYXRoZXIgdGhhbiBhIG51bGwgdGhlIHJlYWRlciBoYXMgdG8gc3BlY2lhbC1jYXNlLgogICAgICAgIGNvdW50cnkgPSBjYywKICAgICAgICB0cyAgICAgPSB0cywKICAgICAgICBtZXRob2QgPSBtZXRob2QsCiAgICAgICAgc3RhdHVzID0gc3RhdHVzLAogICAgICAgIHVyaSAgICA9IHVyaSwKICAgICAgICB1YSAgICAgPSB1YSwKICAgICAgICBid19pbiAgPSByZXFfbGVuLAogICAgICAgIGJ3X291dCA9IGJ5dGVzLAogICAgICAgIHJ0ICAgICA9IHJ0LAogICAgfSkKICAgIGlmIG9rX2ogYW5kIGogdGhlbgogICAgICAgIHJlcXVlc3RfZGF0YTpzZXQoInJsb2c6IiAuLiBob3N0IC4uICI6IiAuLiAoc2VxICUgUklORyksIGosIEQxSCkKICAgIGVuZAplbmQpCg==",
|
|
41
|
+
"webhook_handler.lua": "LS0gd2ViaG9va19oYW5kbGVyLmx1YQotLSBIYW5kbGVzIGluY29taW5nIHdlYmhvb2sgZXZlbnRzIGZvcndhcmRlZCBmcm9tIHRoZSBTYWFTIGVkZ2UuCi0tIEludGVybmFsIG1hbmFnZW1lbnQgcG9ydCBvbmx5ICgxMjcuMC4wLjE6OTE0NSkuCi0tCi0tIFJvdXRlczoKLS0gICBQT1NUIC9faG9va3MvcHVzaCAgICAgICAgICAtIHJlY2VpdmUgYSBmb3J3YXJkZWQgR2l0SHViIHB1c2ggZXZlbnQKLS0gICBHRVQgIC9faG9va3MvcGVuZGluZyAgICAgICAtIGZldGNoIHN0b3JlZCBldmVudHMgKGZvciBsb2NhbCBhcHAgcG9sbGluZykKLS0gICBQT1NUIC9faG9va3MvYWNrICAgICAgICAgICAtIGFja25vd2xlZGdlIGNvbnN1bWVkIGV2ZW50cwotLQotLSBCZWhhdmlvciBvbiBQT1NUIC9faG9va3MvcHVzaDoKLS0gICAxLiBUcnkgdG8gcHJveHkgdG8gYSBsb2NhbCBLcmFmdCBBUEkgKGNvbmZpZ3VyYWJsZSB2aWEgWC1LcmFmdC1VcmwgaGVhZGVyKQotLSAgIDIuIElmIEtyYWZ0IGlzIG5vdCByZWFjaGFibGUsIHN0b3JlIHRoZSBldmVudCBpbiBzaGFyZWQgZGljdCBmb3IgbGF0ZXIgcG9sbGluZwoKbG9jYWwgY2pzb24gPSByZXF1aXJlICJjanNvbi5zYWZlIgoKbG9jYWwgd2ViaG9va19ldmVudHMgPSBuZ3guc2hhcmVkLndlYmhvb2tfZXZlbnRzCmxvY2FsIHVyaSAgICAgICAgICAgID0gbmd4LnZhci51cmkKbG9jYWwgbWV0aG9kICAgICAgICAgPSBuZ3gucmVxLmdldF9tZXRob2QoKQoKbG9jYWwgZnVuY3Rpb24ganNvbl9yZXNwb25zZShkYXRhLCBjb2RlKQogICAgbmd4LnN0YXR1cyA9IGNvZGUgb3IgMjAwCiAgICBuZ3guaGVhZGVyWyJDb250ZW50LVR5cGUiXSA9ICJhcHBsaWNhdGlvbi9qc29uIgogICAgbmd4LnNheShjanNvbi5lbmNvZGUoZGF0YSkpCiAgICByZXR1cm4gbmd4LmV4aXQobmd4LnN0YXR1cykKZW5kCgotLSDilIDilIAgUE9TVCAvX2hvb2tzL3B1c2gg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tIFJlY2VpdmVzIGZvcndhcmRlZCB3ZWJob29rIHBheWxvYWQgZnJvbSBTYWFTLgotLSBIZWFkZXJzOgotLSAgIFgtS3JhZnQtVXJsOiBodHRwOi8vMTI3LjAuMC4xOjM0NTYgKGlmIEtyYWZ0IHJ1bnMgb24gdGhpcyBzZXJ2ZXIpCi0tICAgWC1Ib29rLUlkOiB0aGUgc3Vic2NyaXB0aW9uIGhvb2tJZCAoZm9yIGNvcnJlbGF0aW9uKQoKaWYgdXJpID09ICIvX2hvb2tzL3B1c2giIGFuZCBtZXRob2QgPT0gIlBPU1QiIHRoZW4KICAgIG5neC5yZXEucmVhZF9ib2R5KCkKICAgIGxvY2FsIGJvZHkgPSBuZ3gucmVxLmdldF9ib2R5X2RhdGEoKQogICAgaWYgbm90IGJvZHkgdGhlbgogICAgICAgIHJldHVybiBqc29uX3Jlc3BvbnNlKHsgZXJyb3IgPSAiZW1wdHkgYm9keSIgfSwgNDAwKQogICAgZW5kCgogICAgbG9jYWwga3JhZnRfdXJsID0gbmd4LnJlcS5nZXRfaGVhZGVycygpWyJ4LWtyYWZ0LXVybCJdCgogICAgLS0gSWYgS3JhZnQgcnVucyBvbiB0aGlzIHNlcnZlciwgcHJveHkgZGlyZWN0bHkKICAgIGlmIGtyYWZ0X3VybCBhbmQga3JhZnRfdXJsIH49ICIiIHRoZW4KICAgICAgICBsb2NhbCBodHRwID0gcmVxdWlyZSAicmVzdHkuaHR0cCIKICAgICAgICBsb2NhbCBodHRwYyA9IGh0dHAubmV3KCkKICAgICAgICBodHRwYzpzZXRfdGltZW91dCg1MDAwKQoKICAgICAgICBsb2NhbCB0YXJnZXQgPSBrcmFmdF91cmwgLi4gIi9hcGkvd2ViaG9va3MvcHVzaCIKICAgICAgICBsb2NhbCByZXMsIGVyciA9IGh0dHBjOnJlcXVlc3RfdXJpKHRhcmdldCwgewogICAgICAgICAgICBtZXRob2QgID0gIlBPU1QiLAogICAgICAgICAgICBib2R5ICAgID0gYm9keSwKICAgICAgICAgICAgaGVhZGVycyA9IHsKICAgICAgICAgICAgICAgIFsiQ29udGVudC1UeXBlIl0gPSAiYXBwbGljYXRpb24vanNvbiIsCiAgICAgICAgICAgICAgICBbIlgtSG9vay1JZCJdICAgID0gbmd4LnJlcS5nZXRfaGVhZGVycygpWyJ4LWhvb2staWQiXSBvciAiIiwKICAgICAgICAgICAgfSwKICAgICAgICB9KQoKICAgICAgICBpZiByZXMgYW5kIHJlcy5zdGF0dXMgPCA1MDAgdGhlbgogICAgICAgICAgICAtLSBLcmFmdCBoYW5kbGVkIGl0ICgyeHggb3IgNHh4KQogICAgICAgICAgICByZXR1cm4ganNvbl9yZXNwb25zZSh7IG9rID0gdHJ1ZSwgcHJveGllZCA9IHRydWUsIHN0YXR1cyA9IHJlcy5zdGF0dXMgfSkKICAgICAgICBlbmQKCiAgICAgICAgLS0gS3JhZnQgdW5yZWFjaGFibGUgb3IgZXJyb3JlZCAtIGZhbGwgdGhyb3VnaCB0byBzdG9yZQogICAgZW5kCgogICAgLS0gU3RvcmUgZm9yIGxhdGVyIHBvbGxpbmcgYnkgbG9jYWwvZGVza3RvcCBhcHAKICAgIGxvY2FsIGV2ZW50X2lkID0gbmd4Lm5vdygpIC4uICI6IiAuLiBtYXRoLnJhbmRvbSgxMDAwMDAsIDk5OTk5OSkKICAgIGxvY2FsIGV2ZW50ID0gY2pzb24uZW5jb2RlKHsKICAgICAgICBpZCAgICAgICA9IGV2ZW50X2lkLAogICAgICAgIGhvb2tfaWQgID0gbmd4LnJlcS5nZXRfaGVhZGVycygpWyJ4LWhvb2staWQiXSBvciAiIiwKICAgICAgICBwYXlsb2FkICA9IGJvZHksCiAgICAgICAgcmVjZWl2ZWQgPSBuZ3gubm93KCksCiAgICB9KQoKICAgIC0tIFVzZSBhIHNsb3QtYmFzZWQgcmluZyBidWZmZXIgKG1heCAyMDAgZXZlbnRzKQogICAgbG9jYWwgbWF4X2V2ZW50cyA9IDIwMAogICAgbG9jYWwgaWR4ID0gd2ViaG9va19ldmVudHM6aW5jcigiX2lkeCIsIDEsIDApIG9yIDAKICAgIGxvY2FsIHNsb3QgPSAoaWR4ICUgbWF4X2V2ZW50cykKICAgIHdlYmhvb2tfZXZlbnRzOnNldCgiZXZ0OiIgLi4gc2xvdCwgZXZlbnQsIDM2MDApIC0tIDFoIFRUTAogICAgd2ViaG9va19ldmVudHM6c2V0KCJfY291bnQiLCBtYXRoLm1pbihpZHgsIG1heF9ldmVudHMpKQoKICAgIHJldHVybiBqc29uX3Jlc3BvbnNlKHsgb2sgPSB0cnVlLCBzdG9yZWQgPSB0cnVlLCBldmVudF9pZCA9IGV2ZW50X2lkIH0pCmVuZAoKLS0g4pSA4pSAIEdFVCAvX2hvb2tzL3BlbmRpbmcg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tIFJldHVybnMgc3RvcmVkIHdlYmhvb2sgZXZlbnRzIGZvciBsb2NhbCBhcHAgdG8gY29uc3VtZS4KCmlmIHVyaSA9PSAiL19ob29rcy9wZW5kaW5nIiBhbmQgbWV0aG9kID09ICJHRVQiIHRoZW4KICAgIGlmIG5vdCB3ZWJob29rX2V2ZW50cyB0aGVuCiAgICAgICAgcmV0dXJuIGpzb25fcmVzcG9uc2UoeyBldmVudHMgPSB7fSB9KQogICAgZW5kCgogICAgbG9jYWwgY291bnQgPSB3ZWJob29rX2V2ZW50czpnZXQoIl9jb3VudCIpIG9yIDAKICAgIGxvY2FsIGlkeCAgID0gd2ViaG9va19ldmVudHM6Z2V0KCJfaWR4Iikgb3IgMAogICAgbG9jYWwgZXZlbnRzID0ge30KCiAgICAtLSBSZWFkIGFsbCBzdG9yZWQgZXZlbnRzIChuZXdlc3QgZmlyc3QpCiAgICBsb2NhbCBtYXhfZXZlbnRzID0gMjAwCiAgICBsb2NhbCBzdGFydCA9IG1hdGgubWF4KDAsIGlkeCAtIGNvdW50KQogICAgZm9yIGkgPSBzdGFydCwgaWR4IC0gMSBkbwogICAgICAgIGxvY2FsIHNsb3QgPSBpICUgbWF4X2V2ZW50cwogICAgICAgIGxvY2FsIHJhdyA9IHdlYmhvb2tfZXZlbnRzOmdldCgiZXZ0OiIgLi4gc2xvdCkKICAgICAgICBpZiByYXcgdGhlbgogICAgICAgICAgICBsb2NhbCBwYXJzZWQgPSBjanNvbi5kZWNvZGUocmF3KQogICAgICAgICAgICBpZiBwYXJzZWQgdGhlbgogICAgICAgICAgICAgICAgZXZlbnRzWyNldmVudHMgKyAxXSA9IHBhcnNlZAogICAgICAgICAgICBlbmQKICAgICAgICBlbmQKICAgIGVuZAoKICAgIHJldHVybiBqc29uX3Jlc3BvbnNlKHsgZXZlbnRzID0gZXZlbnRzIH0pCmVuZAoKLS0g4pSA4pSAIFBPU1QgL19ob29rcy9hY2sg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSACi0tIEFja25vd2xlZGdlIGV2ZW50cyBoYXZlIGJlZW4gY29uc3VtZWQgLSBjbGVhcnMgdGhlIHN0b3JlLgoKaWYgdXJpID09ICIvX2hvb2tzL2FjayIgYW5kIG1ldGhvZCA9PSAiUE9TVCIgdGhlbgogICAgaWYgd2ViaG9va19ldmVudHMgdGhlbgogICAgICAgIHdlYmhvb2tfZXZlbnRzOmZsdXNoX2FsbCgpCiAgICAgICAgd2ViaG9va19ldmVudHM6Zmx1c2hfZXhwaXJlZCgpCiAgICBlbmQKICAgIHJldHVybiBqc29uX3Jlc3BvbnNlKHsgb2sgPSB0cnVlIH0pCmVuZAoKLS0g4pSA4pSAIEZhbGxiYWNrIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgApyZXR1cm4ganNvbl9yZXNwb25zZSh7IGVycm9yID0gIm5vdCBmb3VuZCIgfSwgNDA0KQo="
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// ../../packages/adapters/src/infra/cloudflare-ips.generated.ts
|
|
45
|
+
var CLOUDFLARE_IPV4 = [
|
|
46
|
+
"173.245.48.0/20",
|
|
47
|
+
"103.21.244.0/22",
|
|
48
|
+
"103.22.200.0/22",
|
|
49
|
+
"103.31.4.0/22",
|
|
50
|
+
"141.101.64.0/18",
|
|
51
|
+
"108.162.192.0/18",
|
|
52
|
+
"190.93.240.0/20",
|
|
53
|
+
"188.114.96.0/20",
|
|
54
|
+
"197.234.240.0/22",
|
|
55
|
+
"198.41.128.0/17",
|
|
56
|
+
"162.158.0.0/15",
|
|
57
|
+
"104.16.0.0/13",
|
|
58
|
+
"104.24.0.0/14",
|
|
59
|
+
"172.64.0.0/13",
|
|
60
|
+
"131.0.72.0/22"
|
|
61
|
+
];
|
|
62
|
+
var CLOUDFLARE_IPV6 = [
|
|
63
|
+
"2400:cb00::/32",
|
|
64
|
+
"2606:4700::/32",
|
|
65
|
+
"2803:f800::/32",
|
|
66
|
+
"2405:b500::/32",
|
|
67
|
+
"2405:8100::/32",
|
|
68
|
+
"2a06:98c0::/29",
|
|
69
|
+
"2c0f:f248::/32"
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
// ../../packages/adapters/src/infra/edge-real-ip.ts
|
|
73
|
+
var EDGE_REAL_IP_CONF_NAME = "kraft-real-ip.conf";
|
|
74
|
+
function edgeRealIpHeader() {
|
|
75
|
+
const raw = process.env.KRAFT_EDGE_REAL_IP_HEADER?.trim();
|
|
76
|
+
if (raw && /^[A-Za-z0-9-]{1,64}$/.test(raw)) return raw;
|
|
77
|
+
return "CF-Connecting-IP";
|
|
78
|
+
}
|
|
79
|
+
function edgeTrustedProxies() {
|
|
80
|
+
const raw = process.env.KRAFT_EDGE_TRUSTED_PROXIES?.trim();
|
|
81
|
+
if (!raw) return [];
|
|
82
|
+
const CIDR = /^(?:(?:\d{1,3}\.){3}\d{1,3}|[0-9a-fA-F:]+)(?:\/\d{1,3})?$/;
|
|
83
|
+
return raw.split(/[,\s]+/).map((s) => s.trim()).filter((s) => s.length > 0 && s.length <= 64 && CIDR.test(s));
|
|
84
|
+
}
|
|
85
|
+
function edgeRealIpConf() {
|
|
86
|
+
const header = edgeRealIpHeader();
|
|
87
|
+
const extra = edgeTrustedProxies();
|
|
88
|
+
const lines = [
|
|
89
|
+
"# Kraft \u2014 recover the real client address from a trusted front proxy.",
|
|
90
|
+
"#",
|
|
91
|
+
"# GENERATED. Source: packages/adapters/src/infra/edge-real-ip.ts",
|
|
92
|
+
"#",
|
|
93
|
+
"# Without this, remote_addr is the PROXY on any box behind Cloudflare or a load",
|
|
94
|
+
"# balancer, which silently breaks four things at once: visitor country resolves to",
|
|
95
|
+
"# the PoP, distinct-visitor counts collapse toward the number of PoPs, per-IP rate",
|
|
96
|
+
"# limits put the whole planet behind one PoP in a single bucket, and IP bans ban a",
|
|
97
|
+
"# PoP instead of a visitor.",
|
|
98
|
+
"#",
|
|
99
|
+
"# set_real_ip_from does NOT mean 'trust this header'. It means 'trust this header",
|
|
100
|
+
"# only when the TCP peer is one of these addresses'. Someone hitting the origin",
|
|
101
|
+
"# directly with a forged header is not connecting FROM Cloudflare, so the header is",
|
|
102
|
+
"# ignored and their real address stands. The trust is anchored to who opened the",
|
|
103
|
+
`# socket, which a client cannot forge.`,
|
|
104
|
+
"#",
|
|
105
|
+
`# The header is ${header}.`,
|
|
106
|
+
...header.toLowerCase() === "cf-connecting-ip" ? [
|
|
107
|
+
"# Cloudflare OVERWRITES CF-Connecting-IP, so its value holds nothing the client",
|
|
108
|
+
"# supplied. It deliberately is NOT X-Forwarded-For: Cloudflare APPENDS to that",
|
|
109
|
+
"# one, so XFF arrives as '<client-controlled>, <real client>' and reading it",
|
|
110
|
+
"# left-to-right would let a visitor choose their own apparent address \u2014 and",
|
|
111
|
+
"# with it their rate-limit bucket and which ban rules miss them."
|
|
112
|
+
] : [
|
|
113
|
+
"# NOT the default (CF-Connecting-IP) \u2014 set via KRAFT_EDGE_REAL_IP_HEADER.",
|
|
114
|
+
"# If this is X-Forwarded-For, note that proxies APPEND to it, so the header is",
|
|
115
|
+
"# partly client-controlled; real_ip_recursive below is what makes nginx walk it",
|
|
116
|
+
"# from the right and stop at the last untrusted hop, which is the real client."
|
|
117
|
+
],
|
|
118
|
+
"",
|
|
119
|
+
`real_ip_header ${header};`,
|
|
120
|
+
"",
|
|
121
|
+
"# Walk a multi-hop header from the RIGHT, skipping trusted addresses. Inert for a",
|
|
122
|
+
"# single-value header like CF-Connecting-IP; load-bearing for X-Forwarded-For, where",
|
|
123
|
+
"# the left-hand entries are whatever the client sent.",
|
|
124
|
+
"real_ip_recursive on;",
|
|
125
|
+
"",
|
|
126
|
+
`# Cloudflare's published edge ranges (${CLOUDFLARE_IPV4.length} v4 + ${CLOUDFLARE_IPV6.length} v6).`,
|
|
127
|
+
"# Trusted unconditionally, which is safe by construction: on a box that is not behind",
|
|
128
|
+
"# Cloudflare no peer ever matches, so every line here is inert. Refresh with",
|
|
129
|
+
"# `bun run update:cloudflare-ips`.",
|
|
130
|
+
...CLOUDFLARE_IPV4.map((c) => `set_real_ip_from ${c};`),
|
|
131
|
+
...CLOUDFLARE_IPV6.map((c) => `set_real_ip_from ${c};`)
|
|
132
|
+
];
|
|
133
|
+
if (extra.length > 0) {
|
|
134
|
+
lines.push(
|
|
135
|
+
"",
|
|
136
|
+
"# Operator-declared proxies (KRAFT_EDGE_TRUSTED_PROXIES). Each of these can set",
|
|
137
|
+
"# the header above and be believed, so keep the list to hosts you control.",
|
|
138
|
+
...extra.map((c) => `set_real_ip_from ${c};`)
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
return lines.join("\n") + "\n";
|
|
142
|
+
}
|
|
143
|
+
var CLOUD_EDGE_REAL_IP_HEADER = "X-Real-IP";
|
|
144
|
+
function isCloudFrontedHost(hostname) {
|
|
145
|
+
const host = hostname.trim().toLowerCase().replace(/\.+$/, "");
|
|
146
|
+
const suffix = `.${SYSTEM.DOMAINS.CLOUD_DOMAIN.toLowerCase()}`;
|
|
147
|
+
return host.length > suffix.length && host.endsWith(suffix);
|
|
148
|
+
}
|
|
149
|
+
function cloudEdgeRealIpConf(indent = " ") {
|
|
150
|
+
const lines = [
|
|
151
|
+
"# Kraft Cloud's edge fronts this free host, so the peer is the edge and the",
|
|
152
|
+
"# visitor is named in X-Real-IP (which that front OVERWRITES). The http-scope block",
|
|
153
|
+
"# reads CF-Connecting-IP for Cloudflare-fronted custom domains, and there is one",
|
|
154
|
+
"# real_ip_header per scope \u2014 hence this override.",
|
|
155
|
+
"#",
|
|
156
|
+
"# Trust is scoped to this VHOST instead of to a peer list, deliberately. The Cloud",
|
|
157
|
+
"# edge reaches origins from its own address, which this box has no way to know and",
|
|
158
|
+
"# which Cloudflare's ranges (the visitor\u2192edge leg) do not contain \u2014 so a peer list",
|
|
159
|
+
"# here silently ignores the header and every free-domain visitor stays the edge.",
|
|
160
|
+
"#",
|
|
161
|
+
"# What bounds it is the server_name: this block exists only inside a <slug>.kraft.io",
|
|
162
|
+
"# vhost, a hostname whose only legitimate path is that edge. Someone who reaches this",
|
|
163
|
+
"# box directly on :80 with a forged Host AND a forged X-Real-IP can choose their own",
|
|
164
|
+
"# apparent address for THIS vhost \u2014 accepted, because the alternative is the address",
|
|
165
|
+
"# being wrong for every visitor all the time. Custom domains keep the peer-anchored",
|
|
166
|
+
"# http-scope block; do not widen this to them.",
|
|
167
|
+
`real_ip_header ${CLOUD_EDGE_REAL_IP_HEADER};`,
|
|
168
|
+
// OFF, unlike the http-scope block: the Cloud edge OVERWRITES X-Real-IP with a single
|
|
169
|
+
// address, so there is no list to walk, and "skip trusted addresses from the right"
|
|
170
|
+
// has no meaning once every address is trusted.
|
|
171
|
+
"real_ip_recursive off;",
|
|
172
|
+
"set_real_ip_from 0.0.0.0/0;",
|
|
173
|
+
"set_real_ip_from ::/0;"
|
|
174
|
+
];
|
|
175
|
+
return lines.map((l) => `${indent}${l}`).join("\n") + "\n";
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ../../packages/adapters/src/infra/edge-not-found.ts
|
|
179
|
+
var EDGE_UNROUTED_SENTINEL = "kraft-edge-unrouted";
|
|
180
|
+
var HTML_FRAGMENTS = [
|
|
181
|
+
`<!doctype html>`,
|
|
182
|
+
`<!--${EDGE_UNROUTED_SENTINEL}-->`,
|
|
183
|
+
`<html lang="en">`,
|
|
184
|
+
`<head>`,
|
|
185
|
+
`<meta charset="utf-8">`,
|
|
186
|
+
`<meta name="viewport" content="width=device-width,initial-scale=1">`,
|
|
187
|
+
// An unrouted host must never enter a search index under our page.
|
|
188
|
+
`<meta name="robots" content="noindex,nofollow">`,
|
|
189
|
+
`<title>Service not found</title>`,
|
|
190
|
+
`<style>`,
|
|
191
|
+
// Matches the dashboard's theme: a neutral black-on-white scale, mirrored for
|
|
192
|
+
// dark. No webfont, no image, no external request — the page must render on a
|
|
193
|
+
// box whose only working listener is the one serving it. Colours are `rgb()`,
|
|
194
|
+
// never `#rrggbb`: see the no-`#` invariant in the header.
|
|
195
|
+
`:root{color-scheme:light dark}`,
|
|
196
|
+
`*{box-sizing:border-box}`,
|
|
197
|
+
`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}`,
|
|
198
|
+
`main{width:100%;max-width:32rem;padding:2.5rem 1.5rem;text-align:center}`,
|
|
199
|
+
// The muted scale is .56, not the .4–.52 it started at: black at .52 on white is
|
|
200
|
+
// 4.3:1 and at .4 is 2.9:1, both under WCAG AA's 4.5:1 for text this small, and
|
|
201
|
+
// this is the most-seen page the edge serves. .56 ≈ 4.75:1.
|
|
202
|
+
`.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)}`,
|
|
203
|
+
`.dot{width:6px;height:6px;border-radius:50%;background:rgb(224,169,10)}`,
|
|
204
|
+
`h1{margin:0 0 .5rem;font-size:1.375rem;font-weight:600;letter-spacing:-.01em;color:rgba(0,0,0,.92)}`,
|
|
205
|
+
`p{margin:0 auto 1.5rem;max-width:26rem}`,
|
|
206
|
+
`ul{display:inline-block;margin:0;padding:0;list-style:none;text-align:left;font-size:13.5px;color:rgba(0,0,0,.56)}`,
|
|
207
|
+
`li{position:relative;padding:.2rem 0 .2rem 1rem}`,
|
|
208
|
+
`li::before{content:"";position:absolute;left:0;top:.75em;width:4px;height:4px;border-radius:50%;background:rgba(0,0,0,.25)}`,
|
|
209
|
+
`footer{margin-top:2.25rem;font-size:12px;color:rgba(0,0,0,.56)}`,
|
|
210
|
+
`@media(prefers-color-scheme:dark){`,
|
|
211
|
+
`body{background:rgb(10,10,10);color:rgba(255,255,255,.66)}`,
|
|
212
|
+
`.tag{border-color:rgba(255,255,255,.12);color:rgba(255,255,255,.56)}`,
|
|
213
|
+
`h1{color:rgba(255,255,255,.95)}`,
|
|
214
|
+
`ul{color:rgba(255,255,255,.56)}`,
|
|
215
|
+
`li::before{background:rgba(255,255,255,.28)}`,
|
|
216
|
+
`footer{color:rgba(255,255,255,.56)}`,
|
|
217
|
+
`}`,
|
|
218
|
+
`</style>`,
|
|
219
|
+
`</head>`,
|
|
220
|
+
`<body>`,
|
|
221
|
+
`<main>`,
|
|
222
|
+
`<span class="tag"><span class="dot"></span>404 · no route</span>`,
|
|
223
|
+
`<h1>Service not found</h1>`,
|
|
224
|
+
// "reachable, but nothing is configured" is the whole message: it separates a
|
|
225
|
+
// down app from an address that was never wired up, which is the distinction a
|
|
226
|
+
// raw TLS error or a stock 404 destroys.
|
|
227
|
+
`<p>This server is reachable, but no application is configured for the address you requested.</p>`,
|
|
228
|
+
`<ul>`,
|
|
229
|
+
`<li>Check the address for a typo</li>`,
|
|
230
|
+
`<li>The deployment may have been removed or renamed</li>`,
|
|
231
|
+
`<li>A newly added domain can take a few minutes to start serving</li>`,
|
|
232
|
+
`</ul>`,
|
|
233
|
+
`<footer>Served by Kraft</footer>`,
|
|
234
|
+
`</main>`,
|
|
235
|
+
`</body>`,
|
|
236
|
+
`</html>`
|
|
237
|
+
];
|
|
238
|
+
var EDGE_NOT_FOUND_HTML = HTML_FRAGMENTS.join("");
|
|
239
|
+
var EDGE_NOT_FOUND_LOCATION = ` server_tokens off;
|
|
240
|
+
|
|
241
|
+
location / {
|
|
242
|
+
types { }
|
|
243
|
+
default_type text/html;
|
|
244
|
+
return 404 '${EDGE_NOT_FOUND_HTML}';
|
|
245
|
+
}`;
|
|
246
|
+
|
|
247
|
+
// ../../packages/adapters/src/infra/openresty-reload.ts
|
|
248
|
+
var NGINX_MASTER_RE = /\b(?:nginx|openresty)\s*:\s*master process/i;
|
|
249
|
+
var NGINX_WORKER_RE = /\b(?:nginx|openresty)\s*:\s*worker process/i;
|
|
250
|
+
var NGINX_PROCESS_RE = /\b(?:nginx|openresty)\b/i;
|
|
251
|
+
async function canonicalRemotePath(executor, path) {
|
|
252
|
+
const resolved = await executor.exec(`readlink -f ${sq(path)} 2>/dev/null || true`, { timeout: 5e3 }).catch(() => "");
|
|
253
|
+
return resolved.trim() || null;
|
|
254
|
+
}
|
|
255
|
+
function explicitNginxConfig(rawCommand) {
|
|
256
|
+
const match = rawCommand.match(
|
|
257
|
+
/(?:^|\s)-c(?:(?:\s+|=)(?:"([^"]+)"|'([^']+)'|(\S+))|(\S+))/
|
|
258
|
+
);
|
|
259
|
+
if (!match) return void 0;
|
|
260
|
+
const value = match[1] ?? match[2] ?? match[3] ?? match[4] ?? "";
|
|
261
|
+
return value.startsWith("/") ? value : null;
|
|
262
|
+
}
|
|
263
|
+
function hasExplicitNginxPrefix(rawCommand) {
|
|
264
|
+
return /(?:^|\s)-p(?:\s+|=|\S)/.test(rawCommand);
|
|
265
|
+
}
|
|
266
|
+
async function processStartTime(executor, pid) {
|
|
267
|
+
const value = await executor.exec(
|
|
268
|
+
`awk '{ line=$0; sub(/^.*\\) /, "", line); split(line, fields, " "); print fields[20] }' /proc/${pid}/stat 2>/dev/null || true`,
|
|
269
|
+
{ timeout: 5e3 }
|
|
270
|
+
).catch(() => "");
|
|
271
|
+
return /^\d+$/.test(value.trim()) ? value.trim() : null;
|
|
272
|
+
}
|
|
273
|
+
async function verifyNginxProcessIdentity(executor, occupant, paths) {
|
|
274
|
+
if (!occupant.pid) return "unknown";
|
|
275
|
+
const rawCommand = occupant.rawCommand?.trim();
|
|
276
|
+
if (!rawCommand || !NGINX_MASTER_RE.test(rawCommand)) return "unknown";
|
|
277
|
+
const [actualExe, expectedExe] = await Promise.all([
|
|
278
|
+
canonicalRemotePath(executor, `/proc/${occupant.pid}/exe`),
|
|
279
|
+
canonicalRemotePath(executor, paths.bin)
|
|
280
|
+
]);
|
|
281
|
+
if (!actualExe || !expectedExe) return "unknown";
|
|
282
|
+
if (actualExe !== expectedExe) return "foreign";
|
|
283
|
+
if (hasExplicitNginxPrefix(rawCommand)) return "unknown";
|
|
284
|
+
const explicitConfig = explicitNginxConfig(rawCommand);
|
|
285
|
+
if (explicitConfig === null) return "unknown";
|
|
286
|
+
const effectiveConfig = explicitConfig ?? paths.compiledConfPath;
|
|
287
|
+
const [actualConfig, expectedConfig] = await Promise.all([
|
|
288
|
+
canonicalRemotePath(executor, effectiveConfig),
|
|
289
|
+
canonicalRemotePath(executor, paths.confPath)
|
|
290
|
+
]);
|
|
291
|
+
if (!actualConfig || !expectedConfig || actualConfig !== expectedConfig)
|
|
292
|
+
return "unknown";
|
|
293
|
+
return "match";
|
|
294
|
+
}
|
|
295
|
+
async function resolveListeningNginxMaster(executor, occupant) {
|
|
296
|
+
const description = `${occupant.rawCommand ?? ""} ${occupant.command}`;
|
|
297
|
+
if (!occupant.pid || !NGINX_WORKER_RE.test(description)) return occupant;
|
|
298
|
+
const rawParent = await executor.exec(
|
|
299
|
+
`awk '/^PPid:/{print $2}' /proc/${occupant.pid}/status 2>/dev/null || true`
|
|
300
|
+
).catch(() => "");
|
|
301
|
+
const parentPid = Number.parseInt(rawParent.trim(), 10);
|
|
302
|
+
if (!Number.isInteger(parentPid) || parentPid <= 1) return occupant;
|
|
303
|
+
const parent = await describeProcess(executor, parentPid).catch(() => null);
|
|
304
|
+
if (!parent) return occupant;
|
|
305
|
+
const parentDescription = `${parent.rawCommand ?? ""} ${parent.command}`;
|
|
306
|
+
return NGINX_MASTER_RE.test(parentDescription) ? parent : occupant;
|
|
307
|
+
}
|
|
308
|
+
async function reloadBareOpenResty(executor, paths, opts = {}) {
|
|
309
|
+
await executor.exec(`${sq(paths.bin)} -t -c ${sq(paths.confPath)} 2>&1`, {
|
|
310
|
+
timeout: 15e3
|
|
311
|
+
});
|
|
312
|
+
const listenerStates = await Promise.all([
|
|
313
|
+
probeListeningPortOwners(executor, 80),
|
|
314
|
+
probeListeningPortOwners(executor, 443)
|
|
315
|
+
]);
|
|
316
|
+
if (listenerStates.some((state) => !state.checked)) {
|
|
317
|
+
throw new Error(
|
|
318
|
+
"OpenResty config is valid, but the port 80/443 listener probe was inconclusive; refusing to assume the managed daemon is stopped."
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
if (listenerStates.some((state) => !state.ownershipComplete)) {
|
|
322
|
+
throw new Error(
|
|
323
|
+
"OpenResty config is valid, but every listener on port 80/443 could not be identified; refusing to signal an unknown or mixed owner."
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
const occupants = listenerStates.flatMap((state) => state.occupants);
|
|
327
|
+
const verifiedMasters = /* @__PURE__ */ new Map();
|
|
328
|
+
let foreignListenerOwner = false;
|
|
329
|
+
let ambiguousNginxOwner = false;
|
|
330
|
+
let containerBackedNginxOwner = false;
|
|
331
|
+
for (const occupant of occupants) {
|
|
332
|
+
if (!occupant.rawCommand?.trim()) {
|
|
333
|
+
ambiguousNginxOwner = true;
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
const description = [
|
|
337
|
+
occupant.rawCommand,
|
|
338
|
+
occupant.command,
|
|
339
|
+
occupant.systemdUnit,
|
|
340
|
+
occupant.systemdDescription
|
|
341
|
+
].filter(Boolean).join(" ");
|
|
342
|
+
if (!NGINX_PROCESS_RE.test(description)) {
|
|
343
|
+
foreignListenerOwner = true;
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
if (occupant.containerId) {
|
|
347
|
+
containerBackedNginxOwner = true;
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
const master = await resolveListeningNginxMaster(executor, occupant);
|
|
351
|
+
if (master.containerId) {
|
|
352
|
+
containerBackedNginxOwner = true;
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
const initialIdentity = await verifyNginxProcessIdentity(
|
|
356
|
+
executor,
|
|
357
|
+
master,
|
|
358
|
+
paths
|
|
359
|
+
);
|
|
360
|
+
if (initialIdentity === "foreign") {
|
|
361
|
+
foreignListenerOwner = true;
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
if (initialIdentity === "unknown" || !master.pid) {
|
|
365
|
+
ambiguousNginxOwner = true;
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
if (master.cgroupVerified !== true || !master.processCgroup) {
|
|
369
|
+
ambiguousNginxOwner = true;
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
const startTime = await processStartTime(executor, master.pid);
|
|
373
|
+
if (!startTime) {
|
|
374
|
+
ambiguousNginxOwner = true;
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
const refreshedMaster = await describeProcess(executor, master.pid).catch(
|
|
378
|
+
() => null
|
|
379
|
+
);
|
|
380
|
+
const confirmedStartTime = await processStartTime(executor, master.pid);
|
|
381
|
+
if (!refreshedMaster || confirmedStartTime !== startTime || refreshedMaster.cgroupVerified !== true || !refreshedMaster.processCgroup) {
|
|
382
|
+
ambiguousNginxOwner = true;
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
if (refreshedMaster.containerId) {
|
|
386
|
+
containerBackedNginxOwner = true;
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
const identity = await verifyNginxProcessIdentity(
|
|
390
|
+
executor,
|
|
391
|
+
refreshedMaster,
|
|
392
|
+
paths
|
|
393
|
+
);
|
|
394
|
+
if (identity !== "match") {
|
|
395
|
+
ambiguousNginxOwner = true;
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
verifiedMasters.set(master.pid, {
|
|
399
|
+
pid: master.pid,
|
|
400
|
+
startTime,
|
|
401
|
+
processCgroup: refreshedMaster.processCgroup
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
if (containerBackedNginxOwner) {
|
|
405
|
+
throw new Error(
|
|
406
|
+
"A container-backed nginx/OpenResty listener owns port 80/443; refusing to signal it from bare-host reload."
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
if (ambiguousNginxOwner) {
|
|
410
|
+
throw new Error(
|
|
411
|
+
"A live nginx/OpenResty listener was found, but its executable and configuration could not be verified, or its host ownership could not be proven; refusing to signal an ambiguous process."
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
if (foreignListenerOwner) {
|
|
415
|
+
throw new Error(
|
|
416
|
+
verifiedMasters.size > 0 ? "The managed OpenResty master shares ports 80/443 with a foreign listener; refusing a reload that cannot apply the validated configuration safely." : "A foreign listener owns port 80/443; refusing to treat a live daemon as stopped or report the managed route reload as complete."
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
if (verifiedMasters.size === 0) {
|
|
420
|
+
if (opts.allowStopped && occupants.length === 0) return;
|
|
421
|
+
const owners = occupants.map((occupant) => occupant.command).filter(Boolean);
|
|
422
|
+
throw new Error(
|
|
423
|
+
"OpenResty config is valid, but no verified bare-host master is listening on port 80/443" + (owners.length > 0 ? ` (found: ${owners.join(", ")})` : "") + "; refusing to start a second daemon."
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
if (verifiedMasters.size !== 1) {
|
|
427
|
+
throw new Error(
|
|
428
|
+
`Found ${verifiedMasters.size} verified nginx/OpenResty masters on ports 80/443; refusing an ambiguous reload.`
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
const target = [...verifiedMasters.values()][0];
|
|
432
|
+
await executor.exec(
|
|
433
|
+
`current_exe=$(readlink -f /proc/${target.pid}/exe 2>/dev/null || true); expected_exe=$(readlink -f ${sq(paths.bin)} 2>/dev/null || true); current_start=$(awk '{ line=$0; sub(/^.*\\) /, "", line); split(line, fields, " "); print fields[20] }' /proc/${target.pid}/stat 2>/dev/null || true); current_cgroup=$(cat /proc/${target.pid}/cgroup 2>/dev/null) || { echo "nginx master cgroup became unreadable; refusing reload" >&2; exit 1; }; [ -n "$current_exe" ] && [ "$current_exe" = "$expected_exe" ] && [ "$current_start" = ${sq(target.startTime)} ] && [ -n "$current_cgroup" ] && [ "$current_cgroup" = ${sq(target.processCgroup)} ] || { echo "nginx master identity changed; refusing reload" >&2; exit 1; }; kill -HUP ${target.pid}`,
|
|
434
|
+
{ timeout: 5e3 }
|
|
435
|
+
).catch((err) => {
|
|
436
|
+
throw new Error(
|
|
437
|
+
`Safe bare-host OpenResty reload failed: ${safeErrorMessage(err)}`
|
|
438
|
+
);
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// ../../packages/adapters/src/infra/openresty-lua.ts
|
|
443
|
+
var OPENRESTY_LUA_DIR = "/usr/local/openresty/site/lualib/kraft";
|
|
444
|
+
var LUA_LOGGER_PATH = `${OPENRESTY_LUA_DIR}/site_logger.lua`;
|
|
445
|
+
var RULES_GUARD_PATH = `${OPENRESTY_LUA_DIR}/rules_guard.lua`;
|
|
446
|
+
var OPENRESTY_MGMT_PORT = 9145;
|
|
447
|
+
var OPENRESTY_SITE_LUALIB = OPENRESTY_LUA_DIR.replace(/\/[^/]+$/, "");
|
|
448
|
+
var EDGE_LUA_PACKAGE_PATH = `${OPENRESTY_SITE_LUALIB}/?.lua;;`;
|
|
449
|
+
var EDGE_SERVER_NAMES_HASH_BUCKET_SIZE = 128;
|
|
450
|
+
var EDGE_CLIENT_MAX_BODY_SIZE = "50m";
|
|
451
|
+
var EDGE_SHARED_DICTS = [
|
|
452
|
+
/** Analytics counters. */
|
|
453
|
+
{ name: "analytics", size: "256m" },
|
|
454
|
+
/** Raw-log ring buffers + the live-log pipe. */
|
|
455
|
+
{ name: "request_data", size: "128m" },
|
|
456
|
+
/** Per-route rules cache: written reload-free by mgmt_api `POST /rules`, read
|
|
457
|
+
* by rules_guard.lua in the access phase. The DB (route_rule) is the source
|
|
458
|
+
* of truth, so losing this dict costs a re-push, not a ruleset. */
|
|
459
|
+
{ name: "rules", size: "32m" },
|
|
460
|
+
/** Rate-limit COUNTERS, kept apart from `rules` so a high-cardinality flood (a
|
|
461
|
+
* fresh key per source IP per second) can't LRU-evict the rulesets and
|
|
462
|
+
* silently disable enforcement mid-attack.
|
|
463
|
+
*
|
|
464
|
+
* 32m, matching openresty module migration 1.1.0, which raises it from the
|
|
465
|
+
* original 16m on boxes already installed. Both must state the same target: a
|
|
466
|
+
* fresh install writes THIS value, so leaving it at 16m meant a new box got the
|
|
467
|
+
* size the migration exists to correct — and only bare boxes that consented to
|
|
468
|
+
* the migration would ever reach 32m. The migration stays because the
|
|
469
|
+
* `grep || sed` convergence below is append-only and cannot resize an existing
|
|
470
|
+
* directive; `edge-shared-dicts.test.ts` pins the two together. */
|
|
471
|
+
{ name: "rl_counters", size: "32m" },
|
|
472
|
+
/**
|
|
473
|
+
* Distinct-visitor sets. One key per (domain, day, salted-IP hash) — high
|
|
474
|
+
* cardinality and short-lived, so it gets its own zone for the same reason
|
|
475
|
+
* `rl_counters` does: a busy day's visitor set must not LRU-evict the analytics
|
|
476
|
+
* counters or the rulesets.
|
|
477
|
+
*
|
|
478
|
+
* Privacy: keys hold a per-day-salted hash, never an address, and only the
|
|
479
|
+
* resulting COUNT is ever flushed to Postgres. Nothing that identifies a visitor
|
|
480
|
+
* leaves the box — see the visitor block in site_logger.lua.
|
|
481
|
+
*
|
|
482
|
+
* 64m ≈ 1M distinct visitors/day. Past that the zone LRU-evicts and the count
|
|
483
|
+
* UNDERSTATES; `GET /status` reports free_space so a reader can mark it
|
|
484
|
+
* approximate rather than present an eviction artifact as a measurement.
|
|
485
|
+
*/
|
|
486
|
+
{ name: "visitors", size: "64m" }
|
|
487
|
+
];
|
|
488
|
+
function parseNginxVersion(raw) {
|
|
489
|
+
const m = raw.match(/nginx version:\s*\S*?\/(\d+)\.(\d+)\.(\d+)/i);
|
|
490
|
+
if (!m) return void 0;
|
|
491
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
492
|
+
}
|
|
493
|
+
var OPENRESTY_DEFAULT_PATHS = {
|
|
494
|
+
bin: "/usr/local/openresty/bin/openresty",
|
|
495
|
+
compiledConfPath: "/usr/local/openresty/nginx/conf/nginx.conf",
|
|
496
|
+
confPath: "/usr/local/openresty/nginx/conf/nginx.conf",
|
|
497
|
+
confDir: "/usr/local/openresty/nginx/conf",
|
|
498
|
+
sitesDir: "/usr/local/openresty/nginx/conf/sites-enabled",
|
|
499
|
+
pidPath: "/usr/local/openresty/nginx/logs/nginx.pid"
|
|
500
|
+
};
|
|
501
|
+
var EDGE_DEFAULT_CERT_DIRNAME = "kraft-default-cert";
|
|
502
|
+
function edgeDefaultCertPaths(confDir) {
|
|
503
|
+
const dir = `${confDir}/${EDGE_DEFAULT_CERT_DIRNAME}`;
|
|
504
|
+
return {
|
|
505
|
+
dir,
|
|
506
|
+
certPath: `${dir}/fullchain.pem`,
|
|
507
|
+
keyPath: `${dir}/privkey.pem`
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
var EDGE_DEFAULT_CERT_CN = "kraft-edge-default";
|
|
511
|
+
var EDGE_HOST_STATE_DIR = "/var/lib/kraft/edge";
|
|
512
|
+
var EDGE_CONTAINER_MOUNTS = [
|
|
513
|
+
{
|
|
514
|
+
host: `${EDGE_HOST_STATE_DIR}/sites-enabled`,
|
|
515
|
+
container: OPENRESTY_DEFAULT_PATHS.sitesDir
|
|
516
|
+
},
|
|
517
|
+
{ host: "/etc/letsencrypt", container: "/etc/letsencrypt" },
|
|
518
|
+
{ host: `${EDGE_HOST_STATE_DIR}/acme`, container: "/var/www/acme" },
|
|
519
|
+
{ host: "/opt/kraft/static", container: "/opt/kraft/static" }
|
|
520
|
+
];
|
|
521
|
+
var EDGE_SAME_PATH_MOUNTS = EDGE_CONTAINER_MOUNTS.filter((m) => m.host === m.container).map(
|
|
522
|
+
(m) => m.host.replace(/\/+$/, "")
|
|
523
|
+
);
|
|
524
|
+
var EDGE_HOST_PATHS = {
|
|
525
|
+
bin: OPENRESTY_DEFAULT_PATHS.bin,
|
|
526
|
+
compiledConfPath: OPENRESTY_DEFAULT_PATHS.compiledConfPath,
|
|
527
|
+
confPath: OPENRESTY_DEFAULT_PATHS.confPath,
|
|
528
|
+
confDir: OPENRESTY_DEFAULT_PATHS.confDir,
|
|
529
|
+
sitesDir: `${EDGE_HOST_STATE_DIR}/sites-enabled`,
|
|
530
|
+
pidPath: OPENRESTY_DEFAULT_PATHS.pidPath
|
|
531
|
+
};
|
|
532
|
+
var KNOWN_CONF_PATHS = [
|
|
533
|
+
"/usr/local/openresty/nginx/conf/nginx.conf",
|
|
534
|
+
"/etc/openresty/nginx.conf",
|
|
535
|
+
"/etc/nginx/nginx.conf"
|
|
536
|
+
];
|
|
537
|
+
async function detectOpenRestyPaths(executor) {
|
|
538
|
+
const raw = await executor.exec("openresty -V 2>&1 || true");
|
|
539
|
+
const parseFlag = (flag) => {
|
|
540
|
+
const m = raw.match(new RegExp(`--${flag}=([^\\s]+)`));
|
|
541
|
+
return m ? m[1] : null;
|
|
542
|
+
};
|
|
543
|
+
const bin = parseFlag("sbin-path") ?? OPENRESTY_DEFAULT_PATHS.bin;
|
|
544
|
+
const compiledConfPath = parseFlag("conf-path") ?? OPENRESTY_DEFAULT_PATHS.compiledConfPath;
|
|
545
|
+
let confPath = compiledConfPath;
|
|
546
|
+
const pidPath = parseFlag("pid-path") ?? OPENRESTY_DEFAULT_PATHS.pidPath;
|
|
547
|
+
if (!await executor.exists(confPath)) {
|
|
548
|
+
let found = false;
|
|
549
|
+
for (const candidate of KNOWN_CONF_PATHS) {
|
|
550
|
+
if (candidate !== confPath && await executor.exists(candidate)) {
|
|
551
|
+
confPath = candidate;
|
|
552
|
+
found = true;
|
|
553
|
+
break;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
if (!found) {
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
const confDir = confPath.replace(/\/[^/]+$/, "");
|
|
560
|
+
const nginxVersion = parseNginxVersion(raw);
|
|
561
|
+
return {
|
|
562
|
+
bin,
|
|
563
|
+
compiledConfPath,
|
|
564
|
+
confPath,
|
|
565
|
+
confDir,
|
|
566
|
+
sitesDir: `${confDir}/sites-enabled`,
|
|
567
|
+
pidPath,
|
|
568
|
+
...nginxVersion ? { nginxVersion } : {}
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
function buildReloadCommand(paths) {
|
|
572
|
+
const bin = sq(paths?.bin || "openresty");
|
|
573
|
+
const config = sq(paths?.confPath || "/etc/openresty/nginx.conf");
|
|
574
|
+
return `${bin} -t -c ${config} 2>&1 || exit 1
|
|
575
|
+
${bin} -s reload -c ${config} 2>&1 || exit 1`;
|
|
576
|
+
}
|
|
577
|
+
async function ensureEdgeDefaultCert(executor, confDir) {
|
|
578
|
+
const { dir, certPath, keyPath } = edgeDefaultCertPaths(confDir);
|
|
579
|
+
try {
|
|
580
|
+
if (await executor.exists(certPath) && await executor.exists(keyPath)) {
|
|
581
|
+
return { certPath, keyPath };
|
|
582
|
+
}
|
|
583
|
+
} catch {
|
|
584
|
+
return null;
|
|
585
|
+
}
|
|
586
|
+
const staging = `${dir}.staging-${process.pid}-${randomBytes(4).toString("hex")}`;
|
|
587
|
+
try {
|
|
588
|
+
await executor.mkdir(staging);
|
|
589
|
+
await executor.exec(
|
|
590
|
+
`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`
|
|
591
|
+
);
|
|
592
|
+
await executor.exec(`chmod 600 ${sq(`${staging}/privkey.pem`)}`);
|
|
593
|
+
await executor.mkdir(dir);
|
|
594
|
+
await executor.exec(
|
|
595
|
+
`mv -f ${sq(`${staging}/fullchain.pem`)} ${sq(`${staging}/privkey.pem`)} ${sq(dir)}/`
|
|
596
|
+
);
|
|
597
|
+
if (!await executor.exists(certPath) || !await executor.exists(keyPath))
|
|
598
|
+
return null;
|
|
599
|
+
return { certPath, keyPath };
|
|
600
|
+
} catch (err) {
|
|
601
|
+
console.warn(
|
|
602
|
+
`[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)}`
|
|
603
|
+
);
|
|
604
|
+
return null;
|
|
605
|
+
} finally {
|
|
606
|
+
await executor.rm(staging).catch(() => void 0);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
async function ensureOpenRestyConfig(executor, paths) {
|
|
610
|
+
await executor.mkdir(paths.sitesDir);
|
|
611
|
+
await executor.mkdir("/var/www/acme");
|
|
612
|
+
const pidDir = paths.pidPath.replace(/\/[^/]+$/, "");
|
|
613
|
+
await executor.mkdir(pidDir);
|
|
614
|
+
const defaultCert = await ensureEdgeDefaultCert(executor, paths.confDir);
|
|
615
|
+
await executor.writeFile(
|
|
616
|
+
`${paths.sitesDir}/_management.conf`,
|
|
617
|
+
MANAGEMENT_BLOCK
|
|
618
|
+
);
|
|
619
|
+
await executor.writeFile(
|
|
620
|
+
`${paths.sitesDir}/_default.conf`,
|
|
621
|
+
edgeDefaultCatchAllConf(defaultCert)
|
|
622
|
+
);
|
|
623
|
+
if (!await executor.exists(paths.confPath)) {
|
|
624
|
+
await executor.mkdir(paths.confDir);
|
|
625
|
+
await executor.writeFile(
|
|
626
|
+
paths.confPath,
|
|
627
|
+
MINIMAL_NGINX_CONF(paths.confDir, paths.sitesDir)
|
|
628
|
+
);
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
const hasCorrectInclude = await executor.exec(`grep -qF 'include ${paths.sitesDir}/' ${paths.confPath}`).then(() => true).catch(() => false);
|
|
632
|
+
if (!hasCorrectInclude) {
|
|
633
|
+
const hasWrongInclude = await executor.exec(`grep -q 'include.*sites-enabled' ${paths.confPath}`).then(() => true).catch(() => false);
|
|
634
|
+
if (hasWrongInclude) {
|
|
635
|
+
await executor.exec(
|
|
636
|
+
`sed -i 's|include.*/sites-enabled/\\*\\.conf;|include ${paths.sitesDir}/*.conf;|' ${paths.confPath}`
|
|
637
|
+
);
|
|
638
|
+
} else {
|
|
639
|
+
await executor.exec(
|
|
640
|
+
`sed -i '/http *{/a \\ include ${paths.sitesDir}/*.conf;' ${paths.confPath}`
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
const hasBodySize = await executor.exec(`grep -qE '^[[:space:]]*client_max_body_size' ${paths.confPath}`).then(() => true).catch(() => false);
|
|
645
|
+
if (!hasBodySize) {
|
|
646
|
+
await executor.exec(
|
|
647
|
+
`sed -i '/http *{/a \\ client_max_body_size ${EDGE_CLIENT_MAX_BODY_SIZE};' ${paths.confPath}`
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
function MINIMAL_NGINX_CONF(confDir, sitesDir) {
|
|
652
|
+
return `# Auto-generated by Kraft - safe to extend
|
|
653
|
+
worker_processes auto;
|
|
654
|
+
events {
|
|
655
|
+
worker_connections 1024;
|
|
656
|
+
}
|
|
657
|
+
http {
|
|
658
|
+
include ${confDir}/mime.types;
|
|
659
|
+
default_type application/octet-stream;
|
|
660
|
+
sendfile on;
|
|
661
|
+
keepalive_timeout 65;
|
|
662
|
+
# See EDGE_SERVER_NAMES_HASH_BUCKET_SIZE \u2014 the 64-byte default fails
|
|
663
|
+
# \`nginx -t\` outright for any server_name past ~63 chars, refusing the reload
|
|
664
|
+
# and wedging every route on the box, not just the long one.
|
|
665
|
+
server_names_hash_bucket_size ${EDGE_SERVER_NAMES_HASH_BUCKET_SIZE};
|
|
666
|
+
# See EDGE_CLIENT_MAX_BODY_SIZE \u2014 nginx's 1 MB default 413s an upload before the app
|
|
667
|
+
# ever sees it. A project's own value overrides this (server beats http).
|
|
668
|
+
client_max_body_size ${EDGE_CLIENT_MAX_BODY_SIZE};
|
|
669
|
+
include ${sitesDir}/*.conf;
|
|
670
|
+
}
|
|
671
|
+
`;
|
|
672
|
+
}
|
|
673
|
+
var GEOIP_DIR = "/usr/share/GeoIP";
|
|
674
|
+
var GEOIP_DB_PATH = `${GEOIP_DIR}/GeoLite2-Country.mmdb`;
|
|
675
|
+
var GEOIP_DB_URL = process.env.KRAFT_GEOIP_URL?.trim() || "https://raw.githubusercontent.com/rakay-technology/kraft/main/apps/api/assets/geoip/GeoLite2-Country.mmdb";
|
|
676
|
+
var LUA_SRC_DIR = process.env.KRAFT_LUA_DIR?.trim() || join(dirname(fileURLToPath(import.meta.url)), "lua");
|
|
677
|
+
var VHOST_REFERENCED_LUA = [
|
|
678
|
+
"rules_guard.lua",
|
|
679
|
+
"rules_lib.lua",
|
|
680
|
+
"site_logger.lua"
|
|
681
|
+
];
|
|
682
|
+
function luaSourceAvailable() {
|
|
683
|
+
return VHOST_REFERENCED_LUA.every(
|
|
684
|
+
(f) => EMBEDDED_LUA[f] !== void 0 || existsSync(join(LUA_SRC_DIR, f))
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
function readLua(filename) {
|
|
688
|
+
const onDisk = join(LUA_SRC_DIR, filename);
|
|
689
|
+
if (existsSync(onDisk)) return readFileSync(onDisk, "utf-8");
|
|
690
|
+
const embedded = EMBEDDED_LUA[filename];
|
|
691
|
+
if (embedded !== void 0)
|
|
692
|
+
return Buffer.from(embedded, "base64").toString("utf-8");
|
|
693
|
+
throw new Error(
|
|
694
|
+
`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\`.`
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
var EDGE_MGMT_SERVER_BLOCK = `server {
|
|
698
|
+
listen 127.0.0.1:${OPENRESTY_MGMT_PORT};
|
|
699
|
+
|
|
700
|
+
# Long-running Lua content handlers need generous timeouts
|
|
701
|
+
send_timeout 3600s;
|
|
702
|
+
keepalive_timeout 3600s;
|
|
703
|
+
lua_check_client_abort on;
|
|
704
|
+
|
|
705
|
+
# SSE live-log stream (long-lived connection)
|
|
706
|
+
location = /logs/stream {
|
|
707
|
+
content_by_lua_file ${OPENRESTY_LUA_DIR}/pipe_stream.lua;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
# REST analytics + health (short-lived)
|
|
711
|
+
location / {
|
|
712
|
+
content_by_lua_file ${OPENRESTY_LUA_DIR}/mgmt_api.lua;
|
|
713
|
+
}
|
|
714
|
+
}`;
|
|
715
|
+
var MANAGEMENT_BLOCK = `# Kraft internal management - analytics & live-log streaming
|
|
716
|
+
# Auto-generated - do not edit manually
|
|
717
|
+
${EDGE_MGMT_SERVER_BLOCK}
|
|
718
|
+
`;
|
|
719
|
+
var ACME_HTTP01_PORT = 49180;
|
|
720
|
+
var ACME_CHALLENGE_LOCATION = ` location ^~ /.well-known/acme-challenge/ {
|
|
721
|
+
proxy_pass http://127.0.0.1:${ACME_HTTP01_PORT};
|
|
722
|
+
proxy_set_header Host $host;
|
|
723
|
+
}`;
|
|
724
|
+
var EDGE_CHALLENGE_URL_PREFIX = "/.well-known/oblien-proxy-challenge/";
|
|
725
|
+
var EDGE_CHALLENGE_ROOT = "/var/www/acme/oblien";
|
|
726
|
+
var EDGE_CHALLENGE_DIR = `${EDGE_CHALLENGE_ROOT}${EDGE_CHALLENGE_URL_PREFIX}`.replace(/\/$/, "");
|
|
727
|
+
var EDGE_CHALLENGE_HOST_DIR = `${EDGE_HOST_STATE_DIR}/acme/oblien${EDGE_CHALLENGE_URL_PREFIX}`.replace(
|
|
728
|
+
/\/$/,
|
|
729
|
+
""
|
|
730
|
+
);
|
|
731
|
+
var EDGE_CHALLENGE_LOCATION = ` location ^~ ${EDGE_CHALLENGE_URL_PREFIX} {
|
|
732
|
+
root ${EDGE_CHALLENGE_ROOT};
|
|
733
|
+
default_type text/plain;
|
|
734
|
+
try_files $uri =404;
|
|
735
|
+
}`;
|
|
736
|
+
function edgeChallengeVhostConf(host) {
|
|
737
|
+
return `# Auto-generated by Kraft - do not edit manually
|
|
738
|
+
# kraft-oblien-challenge: answers ${EDGE_CHALLENGE_URL_PREFIX}<token> for
|
|
739
|
+
# Host: ${host}, so Kraft Cloud's shared edge can prove this box controls that
|
|
740
|
+
# routing target. Everything else gets the shared not-found page - this is
|
|
741
|
+
# scaffolding, not a site.
|
|
742
|
+
server {
|
|
743
|
+
listen 80;
|
|
744
|
+
server_name ${host};
|
|
745
|
+
|
|
746
|
+
${EDGE_CHALLENGE_LOCATION}
|
|
747
|
+
|
|
748
|
+
${EDGE_NOT_FOUND_LOCATION}
|
|
749
|
+
}
|
|
750
|
+
`;
|
|
751
|
+
}
|
|
752
|
+
var EDGE_HTTPS_REJECT_BLOCK = `# HTTPS catch-all. WITHOUT a 443 default_server, nginx serves the first-loaded
|
|
753
|
+
# 443 vhost to any request whose SNI matches no server_name - so a domain we do
|
|
754
|
+
# NOT route (removed / never-added / just pointed at this IP) silently gets some
|
|
755
|
+
# other app's cert + backend. That is cross-serving, a security hole. Owning the
|
|
756
|
+
# 443 default closes it: an unrouted host is answered HERE, never by a fallthrough.
|
|
757
|
+
#
|
|
758
|
+
# This is the no-certificate variant, used only when the placeholder cert could not
|
|
759
|
+
# be created. It refuses the handshake, so the visitor gets a raw TLS error and a
|
|
760
|
+
# Cloudflare-proxied host gets error 525 - correct, but unfriendly. See
|
|
761
|
+
# edgeHttpsDefaultBlock. ssl_reject_handshake (OpenResty/nginx >= 1.19.4; our
|
|
762
|
+
# installer pulls the newest LTS) needs no certificate.
|
|
763
|
+
server {
|
|
764
|
+
listen 443 ssl default_server;
|
|
765
|
+
ssl_reject_handshake on;
|
|
766
|
+
}`;
|
|
767
|
+
function edgeHttpsDefaultBlock(cert) {
|
|
768
|
+
if (!cert) return EDGE_HTTPS_REJECT_BLOCK;
|
|
769
|
+
return `# HTTPS catch-all. WITHOUT a 443 default_server, nginx serves the first-loaded
|
|
770
|
+
# 443 vhost to any request whose SNI matches no server_name - so a domain we do
|
|
771
|
+
# NOT route (removed / never-added / just pointed at this IP) silently gets some
|
|
772
|
+
# other app's cert + backend. That is cross-serving, a security hole. Owning the
|
|
773
|
+
# 443 default closes it: an unrouted host is answered HERE, never by a fallthrough.
|
|
774
|
+
#
|
|
775
|
+
# The cert below belongs to no domain and is trusted by nothing - it exists so the
|
|
776
|
+
# handshake COMPLETES and the request can be answered with a page instead of
|
|
777
|
+
# ERR_SSL_UNRECOGNIZED_NAME_ALERT (Cloudflare "Full" reports the refusal as error
|
|
778
|
+
# 525; "Full (Strict)" validates the cert and will still show 526). Keep this block a
|
|
779
|
+
# dead end: no proxy_pass, no root, no HSTS, no reuse of a real certificate - that is
|
|
780
|
+
# what stops it from becoming the cross-serving it prevents. And never set
|
|
781
|
+
# ssl_certificate at http scope: this block would inherit a real domain's cert.
|
|
782
|
+
server {
|
|
783
|
+
listen 443 ssl default_server;
|
|
784
|
+
server_name _;
|
|
785
|
+
|
|
786
|
+
ssl_certificate ${cert.certPath};
|
|
787
|
+
ssl_certificate_key ${cert.keyPath};
|
|
788
|
+
|
|
789
|
+
${EDGE_NOT_FOUND_LOCATION}
|
|
790
|
+
}`;
|
|
791
|
+
}
|
|
792
|
+
function edgeDefaultCatchAllConf(cert) {
|
|
793
|
+
return `# Kraft default catch-all - prevents the stock OpenResty welcome page AND
|
|
794
|
+
# stops an unmatched Host/SNI from being served the first real vhost by default.
|
|
795
|
+
# Auto-generated - do not edit manually
|
|
796
|
+
server {
|
|
797
|
+
listen 80 default_server;
|
|
798
|
+
server_name _;
|
|
799
|
+
|
|
800
|
+
${ACME_CHALLENGE_LOCATION}
|
|
801
|
+
|
|
802
|
+
${EDGE_NOT_FOUND_LOCATION}
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
${edgeHttpsDefaultBlock(cert)}
|
|
806
|
+
`;
|
|
807
|
+
}
|
|
808
|
+
var LUA_SCRIPTS = [
|
|
809
|
+
"site_logger.lua",
|
|
810
|
+
"pipe_stream.lua",
|
|
811
|
+
"mgmt_api.lua",
|
|
812
|
+
"geo_country.lua",
|
|
813
|
+
// Vendored FFI binding geo_country requires as `kraft.maxminddb`. Ships with
|
|
814
|
+
// the rest so a bare box needs no `opm get` (which needs perl) — see the file
|
|
815
|
+
// header. Flat, like every other script: ensureLuaScripts writes this list into
|
|
816
|
+
// one directory and its presence scan is a plain `ls -1`.
|
|
817
|
+
"maxminddb.lua",
|
|
818
|
+
"rules_lib.lua",
|
|
819
|
+
"rules_guard.lua"
|
|
820
|
+
];
|
|
821
|
+
var LUA_VERSION_MARKER = `${OPENRESTY_LUA_DIR}/.kraft-lua-version`;
|
|
822
|
+
function luaBundleHash() {
|
|
823
|
+
const h = createHash("sha256");
|
|
824
|
+
for (const name of LUA_SCRIPTS) {
|
|
825
|
+
h.update(name);
|
|
826
|
+
h.update("\0");
|
|
827
|
+
h.update(readLua(name));
|
|
828
|
+
h.update("\0");
|
|
829
|
+
}
|
|
830
|
+
return h.digest("hex");
|
|
831
|
+
}
|
|
832
|
+
async function ensureLuaScripts(executor, paths) {
|
|
833
|
+
try {
|
|
834
|
+
if (!luaSourceAvailable()) {
|
|
835
|
+
console.error(
|
|
836
|
+
"[openresty] Lua unavailable in this build (not on disk or embedded) \u2014 edge rules/logging disabled. Run `bun run embed:lua` in packages/adapters."
|
|
837
|
+
);
|
|
838
|
+
return { repaired: [], available: false };
|
|
839
|
+
}
|
|
840
|
+
const expected = luaBundleHash();
|
|
841
|
+
await executor.mkdir(OPENRESTY_LUA_DIR);
|
|
842
|
+
const listing = await executor.exec(`ls -1 '${OPENRESTY_LUA_DIR}' 2>/dev/null || true`).catch(() => "");
|
|
843
|
+
const present = new Set(
|
|
844
|
+
listing.split("\n").map((s) => s.trim()).filter(Boolean)
|
|
845
|
+
);
|
|
846
|
+
const missing = LUA_SCRIPTS.filter((name) => !present.has(name));
|
|
847
|
+
const onBoxVersion = (await executor.readFile(LUA_VERSION_MARKER).catch(() => "")).trim();
|
|
848
|
+
if (missing.length === 0 && onBoxVersion === expected) {
|
|
849
|
+
return { repaired: [], available: true };
|
|
850
|
+
}
|
|
851
|
+
for (const name of LUA_SCRIPTS) {
|
|
852
|
+
await executor.writeFile(`${OPENRESTY_LUA_DIR}/${name}`, readLua(name));
|
|
853
|
+
}
|
|
854
|
+
await executor.writeFile(LUA_VERSION_MARKER, expected);
|
|
855
|
+
const reason = missing.length ? `missing: ${missing.join(", ")}` : "version changed";
|
|
856
|
+
console.warn(`[openresty] (re)installed Lua (${reason}) \u2014 reloading edge.`);
|
|
857
|
+
await reloadBareOpenResty(executor, paths).catch((err) => {
|
|
858
|
+
console.error(
|
|
859
|
+
`[openresty] reload after Lua (re)install failed: ${safeErrorMessage(err)}`
|
|
860
|
+
);
|
|
861
|
+
});
|
|
862
|
+
return {
|
|
863
|
+
repaired: missing.length ? missing : [...LUA_SCRIPTS],
|
|
864
|
+
available: true
|
|
865
|
+
};
|
|
866
|
+
} catch (err) {
|
|
867
|
+
console.error(
|
|
868
|
+
`[openresty] ensureLuaScripts failed (deploy continues): ${safeErrorMessage(err)}`
|
|
869
|
+
);
|
|
870
|
+
return { repaired: [], available: false };
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
async function installGeoDeps(executor) {
|
|
874
|
+
const profile = await resolveEnvironment(executor).catch(
|
|
875
|
+
(err) => safeErrorMessage(err)
|
|
876
|
+
);
|
|
877
|
+
const install = typeof profile === "string" ? refused(`the host profile could not be read: ${profile}`) : envOps(profile).pkgInstallVariants({
|
|
878
|
+
apt: answered(["libmaxminddb0", "libmaxminddb-dev"]),
|
|
879
|
+
dnf: answered(["libmaxminddb", "libmaxminddb-devel"]),
|
|
880
|
+
yum: answered(["libmaxminddb", "libmaxminddb-devel"]),
|
|
881
|
+
apk: answered(["libmaxminddb"]),
|
|
882
|
+
brew: refused(
|
|
883
|
+
"the bare edge is Linux-only, so Kraft has no macOS package for it."
|
|
884
|
+
)
|
|
885
|
+
});
|
|
886
|
+
if (install.supported) {
|
|
887
|
+
await executor.exec(opScript(install.value)).catch((err) => {
|
|
888
|
+
console.warn(
|
|
889
|
+
`[openresty] libmaxminddb install failed \u2014 geo lookups return nil: ${safeErrorMessage(err)}`
|
|
890
|
+
);
|
|
891
|
+
});
|
|
892
|
+
} else {
|
|
893
|
+
console.warn(
|
|
894
|
+
`[openresty] libmaxminddb not installed \u2014 geo lookups return nil: ${install.reason}`
|
|
895
|
+
);
|
|
896
|
+
}
|
|
897
|
+
try {
|
|
898
|
+
const exists = await executor.exists(GEOIP_DB_PATH);
|
|
899
|
+
if (!exists) {
|
|
900
|
+
await executor.mkdir(GEOIP_DIR);
|
|
901
|
+
await executor.exec(`curl -fsSL -o ${GEOIP_DB_PATH} "${GEOIP_DB_URL}"`);
|
|
902
|
+
}
|
|
903
|
+
} catch {
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
async function deployLuaScripts(executor, paths) {
|
|
907
|
+
await installGeoDeps(executor);
|
|
908
|
+
if (!luaSourceAvailable()) {
|
|
909
|
+
throw new Error(
|
|
910
|
+
`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.`
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
await executor.mkdir(OPENRESTY_LUA_DIR);
|
|
914
|
+
for (const name of LUA_SCRIPTS) {
|
|
915
|
+
await executor.writeFile(`${OPENRESTY_LUA_DIR}/${name}`, readLua(name));
|
|
916
|
+
}
|
|
917
|
+
await ensureOpenRestyConfig(executor, paths);
|
|
918
|
+
for (const dict of EDGE_SHARED_DICTS) {
|
|
919
|
+
await executor.exec(
|
|
920
|
+
`grep -q 'lua_shared_dict ${dict.name} ' ${paths.confPath} || sed -i '/http *{/a \\ lua_shared_dict ${dict.name} ${dict.size};' ${paths.confPath}`
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
await executor.exec(
|
|
924
|
+
`grep -q 'lua_package_path' ${paths.confPath} || sed -i '/http *{/a \\ lua_package_path "${EDGE_LUA_PACKAGE_PATH}";' ${paths.confPath}`
|
|
925
|
+
);
|
|
926
|
+
const realIpPath = `${paths.confDir}/${EDGE_REAL_IP_CONF_NAME}`;
|
|
927
|
+
await executor.writeFile(realIpPath, edgeRealIpConf());
|
|
928
|
+
await executor.exec(
|
|
929
|
+
`grep -q '${EDGE_REAL_IP_CONF_NAME}' '${paths.confPath}' || sed -i '/http *{/a \\ include ${realIpPath};' '${paths.confPath}'`
|
|
930
|
+
);
|
|
931
|
+
await reloadBareOpenResty(executor, paths);
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
export {
|
|
935
|
+
isCloudFrontedHost,
|
|
936
|
+
cloudEdgeRealIpConf,
|
|
937
|
+
reloadBareOpenResty,
|
|
938
|
+
OPENRESTY_LUA_DIR,
|
|
939
|
+
LUA_LOGGER_PATH,
|
|
940
|
+
RULES_GUARD_PATH,
|
|
941
|
+
OPENRESTY_MGMT_PORT,
|
|
942
|
+
EDGE_LUA_PACKAGE_PATH,
|
|
943
|
+
EDGE_SERVER_NAMES_HASH_BUCKET_SIZE,
|
|
944
|
+
EDGE_CLIENT_MAX_BODY_SIZE,
|
|
945
|
+
EDGE_SHARED_DICTS,
|
|
946
|
+
parseNginxVersion,
|
|
947
|
+
OPENRESTY_DEFAULT_PATHS,
|
|
948
|
+
EDGE_DEFAULT_CERT_DIRNAME,
|
|
949
|
+
edgeDefaultCertPaths,
|
|
950
|
+
EDGE_DEFAULT_CERT_CN,
|
|
951
|
+
EDGE_HOST_STATE_DIR,
|
|
952
|
+
EDGE_CONTAINER_MOUNTS,
|
|
953
|
+
EDGE_SAME_PATH_MOUNTS,
|
|
954
|
+
EDGE_HOST_PATHS,
|
|
955
|
+
detectOpenRestyPaths,
|
|
956
|
+
buildReloadCommand,
|
|
957
|
+
ensureOpenRestyConfig,
|
|
958
|
+
GEOIP_DIR,
|
|
959
|
+
GEOIP_DB_PATH,
|
|
960
|
+
luaSourceAvailable,
|
|
961
|
+
EDGE_MGMT_SERVER_BLOCK,
|
|
962
|
+
ACME_HTTP01_PORT,
|
|
963
|
+
ACME_CHALLENGE_LOCATION,
|
|
964
|
+
EDGE_CHALLENGE_URL_PREFIX,
|
|
965
|
+
EDGE_CHALLENGE_ROOT,
|
|
966
|
+
EDGE_CHALLENGE_DIR,
|
|
967
|
+
EDGE_CHALLENGE_HOST_DIR,
|
|
968
|
+
EDGE_CHALLENGE_LOCATION,
|
|
969
|
+
edgeChallengeVhostConf,
|
|
970
|
+
EDGE_HTTPS_REJECT_BLOCK,
|
|
971
|
+
edgeHttpsDefaultBlock,
|
|
972
|
+
edgeDefaultCatchAllConf,
|
|
973
|
+
ensureLuaScripts,
|
|
974
|
+
deployLuaScripts
|
|
975
|
+
};
|