rubyfox-server 2.17.3.2 → 2.19.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rubyfox/server/data/config/admin/descriptors/config_room.txt +10 -1
  3. data/lib/rubyfox/server/data/config/admin/descriptors/config_server.txt +90 -20
  4. data/lib/rubyfox/server/data/config/admin/descriptors/config_zone.txt +9 -0
  5. data/lib/rubyfox/server/data/config/admin/descriptors/runtime_room.txt +11 -0
  6. data/lib/rubyfox/server/data/config/admin/descriptors/runtime_user.txt +3 -3
  7. data/lib/rubyfox/server/data/config/core.xml +4 -4
  8. data/lib/rubyfox/server/data/config/default.words.txt +11 -0
  9. data/lib/rubyfox/server/data/config/log4j.properties +1 -2
  10. data/lib/rubyfox/server/data/config/server.xml +1 -1
  11. data/lib/rubyfox/server/data/data/GeoLite2-Country.mmdb +0 -0
  12. data/lib/rubyfox/server/data/data/bannedusers/users.bin +0 -0
  13. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/bootstrap.jar +0 -0
  14. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/catalina-tasks.xml +39 -39
  15. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/catalina.sh +0 -0
  16. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/ciphers.sh +0 -0
  17. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/commons-daemon-native.tar.gz +0 -0
  18. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/commons-daemon.jar +0 -0
  19. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/configtest.sh +0 -0
  20. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/daemon.sh +0 -0
  21. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/digest.sh +0 -0
  22. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/makebase.sh +0 -0
  23. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/setclasspath.sh +0 -0
  24. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/shutdown.sh +0 -0
  25. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/startup.sh +0 -0
  26. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tomcat-juli.jar +0 -0
  27. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tomcat-native.tar.gz +0 -0
  28. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tool-wrapper.sh +0 -0
  29. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/version.sh +0 -0
  30. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/Catalina/localhost/rewrite.config +1 -1
  31. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/catalina.policy +263 -263
  32. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/catalina.properties +209 -207
  33. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/context.xml +31 -31
  34. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/jaspic-providers.xml +23 -23
  35. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/jaspic-providers.xsd +52 -52
  36. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/keystore.jks +0 -0
  37. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/server.xml +177 -161
  38. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/tomcat-users.xml +18 -7
  39. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/tomcat-users.xsd +59 -59
  40. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/web.xml +4740 -4737
  41. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/annotations-api.jar +0 -0
  42. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ant.jar +0 -0
  43. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ha.jar +0 -0
  44. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ssi.jar +0 -0
  45. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-storeconfig.jar +0 -0
  46. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-tribes.jar +0 -0
  47. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina.jar +0 -0
  48. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/el-api.jar +0 -0
  49. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jasper-el.jar +0 -0
  50. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jasper.jar +0 -0
  51. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jaspic-api.jar +0 -0
  52. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jsp-api.jar +0 -0
  53. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/servlet-api.jar +0 -0
  54. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/sfs2x-ws-helper.jar +0 -0
  55. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-api.jar +0 -0
  56. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-coyote.jar +0 -0
  57. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-dbcp.jar +0 -0
  58. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-cs.jar +0 -0
  59. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-de.jar +0 -0
  60. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-es.jar +0 -0
  61. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-fr.jar +0 -0
  62. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ja.jar +0 -0
  63. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ko.jar +0 -0
  64. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-pt-BR.jar +0 -0
  65. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ru.jar +0 -0
  66. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-zh-CN.jar +0 -0
  67. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-jdbc.jar +0 -0
  68. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-jni.jar +0 -0
  69. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-util-scan.jar +0 -0
  70. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-util.jar +0 -0
  71. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-websocket.jar +0 -0
  72. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/websocket-api.jar +0 -0
  73. data/lib/rubyfox/server/data/lib/javax.activation-1.2.0.jar +0 -0
  74. data/lib/rubyfox/server/data/lib/javax.mail.jar +0 -0
  75. data/lib/rubyfox/server/data/lib/js/JSApi.js +2 -1
  76. data/lib/rubyfox/server/data/lib/js/LibApi.js +181 -48
  77. data/lib/rubyfox/server/data/lib/sfs2x-admin.jar +0 -0
  78. data/lib/rubyfox/server/data/lib/sfs2x-cluster.jar +0 -0
  79. data/lib/rubyfox/server/data/lib/sfs2x-core.jar +0 -0
  80. data/lib/rubyfox/server/data/lib/sfs2x.jar +0 -0
  81. data/lib/rubyfox/server/data/sfs2x-service +26 -30
  82. data/lib/rubyfox/server/data/www/BlueBox.war +0 -0
  83. data/lib/rubyfox/server/data/www/HelloServlet/WEB-INF/web.xml +1 -3
  84. data/lib/rubyfox/server/data/www/ROOT/_css_/default.css +14 -6
  85. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/style.css +44 -2
  86. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/application.bundle.js +98 -61
  87. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/endors~mod-0~mod-1~mod-11~mod-12~mod-17~mod-6~mod-7~mod-8~mod-9.bundle.js +17357 -0
  88. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-0.bundle.js +4 -4
  89. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-1.bundle.js +3 -3
  90. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-10.bundle.js +101 -66
  91. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-11.bundle.js +544 -8
  92. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12.bundle.js +915 -1480
  93. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12~module-15~module-16~module-4.bundle.js +2665 -0
  94. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-13.bundle.js +606 -3093
  95. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-13~module-16~module-17~module-4.bundle.js +2665 -0
  96. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-14.bundle.js +764 -0
  97. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-15.bundle.js +71 -0
  98. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-16.bundle.js +1787 -0
  99. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-17.bundle.js +3383 -0
  100. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-4.bundle.js +121 -1009
  101. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-5.bundle.js +1214 -1744
  102. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-6.bundle.js +398 -666
  103. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-7.bundle.js +717 -192
  104. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-8.bundle.js +2117 -665
  105. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-9.bundle.js +613 -690
  106. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~mod-0~mod-1~mod-10~mod-11~mod-16~mod-5~mod-6~mod-7~mod-8.bundle.js +17357 -0
  107. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~mod-0~mod-1~mod-11~mod-12~mod-17~mod-5~mod-6~mod-7~mod-8~mod-9.bundle.js +17357 -0
  108. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/{vendors~module-0~module-1~module-13~module-4~module-5~module-7~module-8.bundle.js → vendors~mod-0~mod-1~mod-11~mod-12~mod-17~mod-5~mod-7~mod-8~mod-9.bundle.js} +2 -2
  109. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-12.bundle.js +807 -0
  110. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-13.bundle.js +807 -0
  111. data/lib/rubyfox/server/data/www/ROOT/admin/modules/cluster-configurator.html +32 -0
  112. data/lib/rubyfox/server/data/www/ROOT/admin/modules/cluster-monitor.html +185 -0
  113. data/lib/rubyfox/server/data/www/ROOT/admin/modules/cluster-updater.html +47 -0
  114. data/lib/rubyfox/server/data/www/ROOT/admin/modules/extension-deployer.html +84 -0
  115. data/lib/rubyfox/server/data/www/ROOT/admin/modules/zone-monitor.html +15 -8
  116. data/lib/rubyfox/server/data/www/ROOT/index.html +13 -23
  117. data/lib/rubyfox/server/data/www/host-manager/META-INF/context.xml +2 -2
  118. data/lib/rubyfox/server/data/www/host-manager/WEB-INF/jsp/404.jsp +2 -2
  119. data/lib/rubyfox/server/data/www/host-manager/{manager.xml → WEB-INF/manager.xml} +5 -1
  120. data/lib/rubyfox/server/data/www/host-manager/WEB-INF/web.xml +17 -0
  121. data/lib/rubyfox/server/data/www/host-manager/css/manager.css +141 -0
  122. data/lib/rubyfox/server/data/www/host-manager/images/tomcat.svg +967 -0
  123. data/lib/rubyfox/server/data/www/manager/META-INF/context.xml +2 -0
  124. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorCerts.jsp +1 -1
  125. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorCiphers.jsp +1 -1
  126. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorTrustedCerts.jsp +1 -1
  127. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/sessionDetail.jsp +3 -3
  128. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/sessionsList.jsp +1 -1
  129. data/lib/rubyfox/server/data/www/manager/WEB-INF/web.xml +17 -0
  130. data/lib/rubyfox/server/data/www/manager/css/manager.css +141 -0
  131. data/lib/rubyfox/server/data/www/manager/images/tomcat.svg +967 -0
  132. data/lib/rubyfox/server/data/www/manager/xform.xsl +74 -59
  133. data/lib/rubyfox/server/version.rb +1 -1
  134. metadata +30 -31
  135. data/lib/rubyfox/server/data/config/admin/icons/Analytics.png +0 -0
  136. data/lib/rubyfox/server/data/config/admin/icons/BanManager.png +0 -0
  137. data/lib/rubyfox/server/data/config/admin/icons/BlueBoxMonitor.png +0 -0
  138. data/lib/rubyfox/server/data/config/admin/icons/Console.png +0 -0
  139. data/lib/rubyfox/server/data/config/admin/icons/Dashboard.png +0 -0
  140. data/lib/rubyfox/server/data/config/admin/icons/ExtensionManager.png +0 -0
  141. data/lib/rubyfox/server/data/config/admin/icons/LicenseManager.png +0 -0
  142. data/lib/rubyfox/server/data/config/admin/icons/LogViewer.png +0 -0
  143. data/lib/rubyfox/server/data/config/admin/icons/ServerConfigurator.png +0 -0
  144. data/lib/rubyfox/server/data/config/admin/icons/ServletManager.png +0 -0
  145. data/lib/rubyfox/server/data/config/admin/icons/ZoneConfigurator.png +0 -0
  146. data/lib/rubyfox/server/data/config/admin/icons/ZoneMonitor.png +0 -0
  147. data/lib/rubyfox/server/data/lib/BlueBox.war +0 -0
  148. data/lib/rubyfox/server/data/lib/apache-tomcat/LICENSE +0 -1061
  149. data/lib/rubyfox/server/data/lib/apache-tomcat/NOTICE +0 -68
  150. data/lib/rubyfox/server/data/lib/apache-tomcat/README.md +0 -81
  151. data/lib/rubyfox/server/data/lib/apache-tomcat/RELEASE-NOTES +0 -174
  152. data/lib/rubyfox/server/data/lib/imap.jar +0 -0
  153. data/lib/rubyfox/server/data/lib/mailapi.jar +0 -0
  154. data/lib/rubyfox/server/data/lib/pop3.jar +0 -0
  155. data/lib/rubyfox/server/data/lib/smtp.jar +0 -0
  156. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12~module-13~module-9.bundle.js +0 -2634
  157. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-9.bundle.js +0 -807
  158. data/lib/rubyfox/server/data/www/host-manager/images/tomcat.gif +0 -0
  159. data/lib/rubyfox/server/data/www/manager/images/tomcat.gif +0 -0
  160. /data/lib/rubyfox/server/data/data/buddylists/{BasicExamples/.keep → .keep} +0 -0
@@ -1,536 +1,333 @@
1
1
  /*! (c) gotoAndPlay | All rights reserved */
2
2
  (window["webpackJsonpapplication"] = window["webpackJsonpapplication"] || []).push([["module-9"],{
3
3
 
4
- /***/ "./src/components/module-specific/ssl-certificate-manager.js":
5
- /*!*******************************************************************!*\
6
- !*** ./src/components/module-specific/ssl-certificate-manager.js ***!
7
- \*******************************************************************/
8
- /*! exports provided: SslCertificateManager */
9
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
10
-
11
- "use strict";
12
- __webpack_require__.r(__webpack_exports__);
13
- /* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SslCertificateManager", function() { return SslCertificateManager; });
14
- /* harmony import */ var _utils_utilities__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/utilities */ "./src/utils/utilities.js");
15
- /* harmony import */ var aes_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! aes-js */ "./node_modules/aes-js/index.js");
16
- /* harmony import */ var aes_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(aes_js__WEBPACK_IMPORTED_MODULE_1__);
17
-
18
-
19
-
20
- class SslCertificateManager extends HTMLElement
21
- {
22
- constructor()
23
- {
24
- super();
25
-
26
- this._modalHtml = `
27
- <div class="modal" id="uploadModal" tabindex="-1" role="dialog" aria-labelledby="uploadModalTitle" aria-hidden="true">
28
- <div class="modal-dialog modal-dialog-centered" role="document">
29
- <div class="modal-content">
30
- <div class="modal-header">
31
- <h5 class="modal-title text-primary" id="uploadModalTitle">SSL Certificate Manager</h5>
32
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
33
- <span aria-hidden="true">&times;</span>
34
- </button>
35
- </div>
36
- <div class="modal-body in-flow-invalid-msg">
37
- <fieldset id="uploadFieldset">
38
- <div id="uploaderSubform">
39
- <div class="form-group">
40
- <div class="col-form-label form-label-container">
41
- <label for="uploader" class="form-label">Certificate keystore (jks) <i class="fas fa-question-circle text-muted help" title="SSL certificate's protected keystore file to be uploaded to the server, in jks format"></i></label>
42
- </div>
43
- <div class="inner-widget">
44
- <input type="file" id="uploader" name="uploader" accept=".jks" data-upload-msg="Select a file">
45
- <span class="k-invalid-msg position-static" data-for="uploader"></span>
46
- </div>
47
- </div>
48
- </div>
49
- <div id="passwordsSubform">
50
- <div class="form-row">
51
- <div class="form-group col">
52
- <div class="col-form-label form-label-container">
53
- <label for="ksPassword" class="form-label">Keystore password <i class="fas fa-question-circle text-muted help" title="Password used to protect the certificate keystore"></i></label>
54
- </div>
55
- <div class="inner-widget">
56
- <input type="password" id="ksPassword" name="ksPassword" class="form-control k-textbox" autocomplete="off" required data-required-msg="Required" />
57
- <span class="k-invalid-msg position-static" data-for="ksPassword"></span>
58
- </div>
59
- </div>
60
-
61
- <div class="form-group col">
62
- <div class="col-form-label form-label-container">
63
- <label for="confirmKsPassword" class="form-label">Confirm password <i class="fas fa-question-circle text-muted help" title="Keystore password confirmation"></i></label>
64
- </div>
65
- <div class="inner-widget">
66
- <input type="password" id="confirmKsPassword" name="confirmKsPassword" class="form-control k-textbox" autocomplete="off" required data-required-msg="Required" />
67
- <span class="k-invalid-msg position-static" data-for="confirmKsPassword"></span>
68
- </div>
69
- </div>
70
- </div>
71
-
72
- <p><em>For additional security, enter again and confirm your SFS2X administration password.</em></p>
73
-
74
- <div class="form-row">
75
- <div class="form-group col">
76
- <div class="col-form-label form-label-container">
77
- <label for="adminPassword" class="form-label">Admin password <i class="fas fa-question-circle text-muted help" title="SmartFoxServer 2X remote administration password"></i></label>
78
- </div>
79
- <div class="inner-widget">
80
- <input type="password" id="adminPassword" name="adminPassword" class="form-control k-textbox" autocomplete="off" required data-required-msg="Required" />
81
- <span class="k-invalid-msg position-static" data-for="adminPassword"></span>
82
- </div>
83
- </div>
84
-
85
- <div class="form-group col">
86
- <div class="col-form-label form-label-container">
87
- <label for="confirmAdminPassword" class="form-label">Confirm password <i class="fas fa-question-circle text-muted help" title="SmartFoxServer 2X remote administration password confirmation"></i></label>
88
- </div>
89
- <div class="inner-widget">
90
- <input type="password" id="confirmAdminPassword" name="confirmAdminPassword" class="form-control k-textbox" autocomplete="off" required data-required-msg="Required" />
91
- <span class="k-invalid-msg position-static" data-for="confirmAdminPassword"></span>
92
- </div>
93
- </div>
94
- </div>
95
- </div>
96
- </fieldset>
97
- </div>
98
- <div class="modal-footer flex-column">
99
- <div class="d-flex w-100">
100
- <div class="flex-grow-1 text-left">
101
- <button id="uploadSslButton" type="button" class="k-button k-primary"><i class="fas fa-upload mr-1"></i>Upload certificate</button>
102
- <i id="uploadSpinner" class="fas fa-circle-notch fa-spin text-primary align-middle ml-1"></i>
103
- </div>
104
- <div class="flex-grow-1 text-right">
105
- <button type="button" class="k-button k-secondary" data-dismiss="modal">Cancel</button>
106
- </div>
107
- </div>
108
- <div id="uploadErrorMsg" class="text-danger mt-3"></div>
109
- </div>
110
- </div>
111
- </div>
112
- </div>
113
- `;
114
-
115
- //-------------------------------------------
116
-
117
- $(this).append(`
118
- <div class="col-sm-5 col-lg-4 col-form-label form-label-container">
119
- <label class="form-label">Upload certificate <i class="fas fa-question-circle text-muted help" title="Upload an SSL certificate's protected keystore to the server"></i></label>
120
- </div>
121
- <div class="inner-widget align-self-center align-self-sm-start col-auto">
122
- <button id="manageSslButton" type="button" class="k-button k-primary" disabled><i class="fas fa-cog mr-1"></i>Manage</button>
123
- </div>
124
- `);
125
-
126
- // Add listeners to Manage button click
127
- $('#manageSslButton', $(this)).on('click', $.proxy(this._onManageSslClick, this));
128
- }
129
-
130
- destroy()
131
- {
132
- // Remove event listener
133
- $('#manageSslButton', $(this)).off('click');
134
-
135
- // Hide modal (which in turn destroys it)
136
- let modalElement = $('#uploadModal', $(this));
137
-
138
- if (modalElement)
139
- modalElement.modal('hide');
140
- }
141
-
142
- get enabled()
143
- {
144
- return this._isEnabled;
145
- }
146
-
147
- set enabled(value)
148
- {
149
- this._isEnabled = value;
150
-
151
- // Enable/disable Manage button
152
- $('#manageSslButton', $(this)).attr('disabled', !value);
153
-
154
- // Enable/disable modal
155
- let modalElement = $('#uploadModal', $(this));
156
-
157
- if (modalElement)
158
- {
159
- // Disable modal close buttons
160
- $('button[data-dismiss="modal"]', modalElement).attr('disabled', !value);
161
-
162
- // Disable upload button
163
- $('#uploadSslButton', modalElement).attr('disabled', !value);
164
-
165
- // Disable fieldset
166
- $('#uploadFieldset', modalElement).attr('disabled', !value);
167
- }
168
- }
169
-
170
- get uploadTargetConfig()
171
- {
172
- return this._uploadTargetConfig;
173
- }
174
-
175
- set uploadTargetConfig(data)
176
- {
177
- this._uploadTargetConfig = data;
178
- }
179
-
180
- _onManageSslClick()
181
- {
182
- // Initialize and show modal
183
- this._showModal();
184
- }
185
-
186
- _onUploadSslClick()
187
- {
188
- if (this._validate())
189
- this._startSslCertUpload();
190
- }
191
-
192
- _showModal()
193
- {
194
- // Append modal html
195
- $(this).append(this._modalHtml);
196
-
197
- let modalElement = $('#uploadModal', $(this));
198
-
199
- // Hide SSL certificate upload spinner and error message container
200
- $('#uploadSpinner', modalElement).hide();
201
- $('#uploadErrorMsg', modalElement).hide();
202
- $('#uploadErrorMsg', modalElement).text('');
203
-
204
- // Add listener to Upload button click
205
- $('#uploadSslButton', modalElement).on('click', $.proxy(this._onUploadSslClick, this));
206
-
207
- // Add listener to modal hide event
208
- modalElement.on('hidden.bs.modal', $.proxy(this._destroyModal, this));
209
-
210
- // Initialize kendo uploader
211
- this._uploadWidget = modalElement.find('#uploader').kendoUpload({
212
- allowedExtensions: ['.jks'],
213
- multiple: false,
214
- template: function(dataItem) {
215
- dataItem.bytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_0__["bytesToSize"]; // Pass bytesToSize utility function to template
216
- return kendo.template(`
217
- <span class='k-progress w-100'></span>
218
- <span class="">
219
- <span class="k-file-name" title="#=name#">#=name#</span>
220
- <span class="k-file-size">Size: #=bytesToSize(size, 1, 'Bytes')#</span>
221
- </span>
222
- `)(dataItem);
223
- },
224
- localization: {
225
- select: 'Select file...'
226
- }
227
- }).data('kendoUpload');
228
-
229
- // Initialize kendo validation on uploader subform
230
- // NOTE: we use separate validators to be able to disable 'validateOnBlur' on the uploader,
231
- // because it causes the error message to appear as soon as the "Select file" button is clicked
232
- this._validator1 = modalElement.find('#uploaderSubform').kendoValidator({
233
- validateOnBlur: false,
234
- rules: {
235
- upload: function(input) {
236
- let valid = false;
237
- if (input.is('[type=file]'))
238
- valid = input.closest('.k-upload').find('.k-file').length > 0;
239
-
240
- return valid;
241
- }
242
- }
243
- }).data('kendoValidator');
244
-
245
- // Initialize kendo validation on passwords subform
246
- this._validator2 = modalElement.find('#passwordsSubform').kendoValidator({
247
- validateOnBlur: true,
248
- rules: {
249
- verifyKsPassword: $.proxy(function(input) {
250
- let valid = true;
251
- if (input.is('[name=confirmKsPassword]'))
252
- valid = input.val() === $(this).find('#ksPassword').val();
253
- return valid;
254
- }, this),
255
- verifyAdmPassword: $.proxy(function(input) {
256
- let valid = true;
257
- if (input.is('[name=confirmAdminPassword]'))
258
- valid = input.val() === $(this).find('#adminPassword').val();
259
- return valid;
260
- }, this)
261
- },
262
- messages: {
263
- verifyKsPassword: 'Password not matching',
264
- verifyAdmPassword: 'Password not matching',
265
- }
266
- }).data('kendoValidator');
267
-
268
- // Initialize bootstrap modal
269
- modalElement.modal({
270
- backdrop: 'static',
271
- keyboard: false,
272
- });
273
- }
274
-
275
- _destroyModal()
276
- {
277
- let modalElement = $('#uploadModal', $(this));
278
-
279
- if (modalElement)
280
- {
281
- // Remove listeners
282
- $('#uploadSslButton', modalElement).off('click');
283
- modalElement.off('hidden.bs.modal');
284
-
285
- // Destroy everything Kendo
286
- kendo.destroy(modalElement);
287
-
288
- // Dispose modal
289
- modalElement.modal('dispose');
290
-
291
- // Remove html
292
- modalElement.remove();
293
- modalElement = null;
294
- }
295
- }
296
-
297
- _validate()
298
- {
299
- let val1 = this._validator1.validate();
300
- let val2 = this._validator2.validate();
301
-
302
- return val1 && val2;
303
- }
304
-
305
- _startSslCertUpload()
306
- {
307
- if (!this._uploadTargetConfig)
308
- throw new Error('Upload target configuration not set');
309
-
310
- let modalElement = $('#uploadModal', $(this));
311
-
312
- if (modalElement)
313
- {
314
- let certData = {};
315
- certData.file = this._uploadWidget.getFiles()[0];
316
- certData.ksPassword = $('#ksPassword', modalElement).val();
317
- certData.adminPassword = $('#adminPassword', modalElement).val();
318
-
319
- // Disable modal
320
- this.enabled = false;
321
-
322
- // Hide previous error and show spinner
323
- $('#uploadSpinner', modalElement).show();
324
- $('#uploadErrorMsg', modalElement).hide();
325
- $('#uploadErrorMsg', modalElement).text('');
326
-
327
- //=================================================================
328
-
329
- // Generate Init Vector
330
- let rngValues = [];
331
- for (let i = 0; i < 16; i++)
332
- rngValues.push(Math.floor(Math.random() * 256));
333
-
334
- let iv = new Uint8Array(rngValues);
335
-
336
- // Generate secret key by MD5-encoding admin password + session token
337
- let md5Pass = this._binaryMD5(certData.adminPassword + this._uploadTargetConfig.sessionToken);
338
-
339
- // Encrypt keystore password via AES (128bit)
340
- let encryptedPwd = this._aesEncrypt(certData.ksPassword, md5Pass, iv);
341
-
342
- // Encode IV using Base64
343
- let encodedIv = this._b64Encode(iv);
344
-
345
- // Encode encrypted password using Base64
346
- let encodedPwd = this._b64Encode(encryptedPwd);
347
-
348
- //=================================================================
349
-
350
- // Set parameters to be sent with the certificate keystore file
351
- const params = new FormData();
352
- params.append('files[]', certData.file.rawFile);
353
- params.append('__iv', encodedIv);
354
- params.append('__password', encodedPwd);
355
- params.append('__module', this._uploadTargetConfig.moduleId);
356
-
357
- // Set destination url
358
- const url = this._uploadTargetConfig.protocol + '://' + this._uploadTargetConfig.host + ':' + this._uploadTargetConfig.port + '/BlueBox/SFS2XFileUpload?sessHashId=' + this._uploadTargetConfig.sessionToken;
359
-
360
- // Start upload
361
- fetch(url, {
362
- method: 'POST',
363
- body: params,
364
- mode: 'no-cors'
365
- }).then($.proxy(this._onSslCertUploadEnd, this));
366
- }
367
- }
368
-
369
- _onSslCertUploadEnd(response)
370
- {
371
- // Nothing to do: we have to wait the upload process completion to be signaled by the server through the dedicated Extension response
372
-
373
- //=================================================================
374
-
375
- // TODO Should we handle this response in some way? For some unknown reason we always get ok=false and status=0
376
- //console.log(response)
377
- //console.log(response.ok)
378
- //console.log(response.status)
379
- }
380
-
381
- /**
382
- * Method called by parent when upload failed.
383
- */
384
- onSslCertUploadError(error)
385
- {
386
- let modalElement = $('#uploadModal', $(this));
387
-
388
- if (modalElement)
389
- {
390
- // Enable modal
391
- this.enabled = true;
392
-
393
- // Show upload error
394
- $('#uploadErrorMsg', modalElement).show();
395
- $('#uploadErrorMsg', modalElement).text(error + '.');
396
-
397
- // Hide spinner
398
- $('#uploadSpinner', modalElement).hide();
399
- }
400
- }
401
-
402
- /**
403
- * Method called by parent when upload is completed successfully.
404
- */
405
- onSslCertUploadSuccess()
406
- {
407
- let modalElement = $('#uploadModal', $(this));
408
-
409
- if (modalElement)
410
- {
411
- // Enable modal
412
- this.enabled = true;
413
-
414
- // Hide spinner
415
- $('#uploadSpinner', modalElement).hide();
416
-
417
- // Hide modal
418
- modalElement.modal('hide');
419
- }
420
- }
421
-
422
- // *****************************************************************
423
-
424
- /*
425
- * Takes a string and returns the MD5 as Uint8Array
426
- */
427
- _binaryMD5(str)
428
- {
429
- let MD5 = new SFS2X.MD5();
430
- let hexStr = MD5.hex_md5(str);
431
-
432
- return this._hexByteStringToByteArray(hexStr);
433
- }
434
-
435
- /*
436
- * Hex bytes ---> Actual byte[] as Uint8Array
437
- */
438
- _hexByteStringToByteArray(hexByteString)
439
- {
440
- let bytes = new Uint8Array(16); // MD5 fixed output size
441
-
442
- for (let i = 0; i < hexByteString.length;)
443
- {
444
- let hexByte = hexByteString[i++] + hexByteString[i++];
445
- let byte = parseInt(hexByte, 16);
446
-
447
- bytes[i / 2 - 1] = byte;
448
- }
449
-
450
- return bytes;
451
- }
452
-
453
- /*
454
- * Encrypt using AES, mode CBC, PKCS#7 padding
455
- *
456
- * text -> the text we want to encode
457
- * key -> the AES key
458
- * iv -> the AES/CBC init vector
459
- *
460
- * Returns -> Uint8Array
461
- */
462
- _aesEncrypt(text, key, iv)
463
- {
464
- let textBytes = aes_js__WEBPACK_IMPORTED_MODULE_1___default.a.utils.utf8.toBytes(text); // Get UTF-8 bytes
465
- let aesCBC = new aes_js__WEBPACK_IMPORTED_MODULE_1___default.a.ModeOfOperation.cbc(key, iv); // Init CBC mode
466
- textBytes = aes_js__WEBPACK_IMPORTED_MODULE_1___default.a.padding.pkcs7.pad(textBytes); // PKCS#7 padding
467
-
468
- // Encrypt
469
- return aesCBC.encrypt(textBytes);
470
- }
471
-
472
- /*
473
- * Encode passed byte array --> Base64 representation
474
- * Returns --> string
475
- */
476
- _b64Encode(barray)
477
- {
478
- return btoa(String.fromCharCode.apply(null, barray));
4
+ /***/ "./node_modules/moment/locale sync recursive ^\\.\\/.*$":
5
+ /*!**************************************************!*\
6
+ !*** ./node_modules/moment/locale sync ^\.\/.*$ ***!
7
+ \**************************************************/
8
+ /*! no static exports found */
9
+ /***/ (function(module, exports, __webpack_require__) {
10
+
11
+ var map = {
12
+ "./af": "./node_modules/moment/locale/af.js",
13
+ "./af.js": "./node_modules/moment/locale/af.js",
14
+ "./ar": "./node_modules/moment/locale/ar.js",
15
+ "./ar-dz": "./node_modules/moment/locale/ar-dz.js",
16
+ "./ar-dz.js": "./node_modules/moment/locale/ar-dz.js",
17
+ "./ar-kw": "./node_modules/moment/locale/ar-kw.js",
18
+ "./ar-kw.js": "./node_modules/moment/locale/ar-kw.js",
19
+ "./ar-ly": "./node_modules/moment/locale/ar-ly.js",
20
+ "./ar-ly.js": "./node_modules/moment/locale/ar-ly.js",
21
+ "./ar-ma": "./node_modules/moment/locale/ar-ma.js",
22
+ "./ar-ma.js": "./node_modules/moment/locale/ar-ma.js",
23
+ "./ar-sa": "./node_modules/moment/locale/ar-sa.js",
24
+ "./ar-sa.js": "./node_modules/moment/locale/ar-sa.js",
25
+ "./ar-tn": "./node_modules/moment/locale/ar-tn.js",
26
+ "./ar-tn.js": "./node_modules/moment/locale/ar-tn.js",
27
+ "./ar.js": "./node_modules/moment/locale/ar.js",
28
+ "./az": "./node_modules/moment/locale/az.js",
29
+ "./az.js": "./node_modules/moment/locale/az.js",
30
+ "./be": "./node_modules/moment/locale/be.js",
31
+ "./be.js": "./node_modules/moment/locale/be.js",
32
+ "./bg": "./node_modules/moment/locale/bg.js",
33
+ "./bg.js": "./node_modules/moment/locale/bg.js",
34
+ "./bm": "./node_modules/moment/locale/bm.js",
35
+ "./bm.js": "./node_modules/moment/locale/bm.js",
36
+ "./bn": "./node_modules/moment/locale/bn.js",
37
+ "./bn.js": "./node_modules/moment/locale/bn.js",
38
+ "./bo": "./node_modules/moment/locale/bo.js",
39
+ "./bo.js": "./node_modules/moment/locale/bo.js",
40
+ "./br": "./node_modules/moment/locale/br.js",
41
+ "./br.js": "./node_modules/moment/locale/br.js",
42
+ "./bs": "./node_modules/moment/locale/bs.js",
43
+ "./bs.js": "./node_modules/moment/locale/bs.js",
44
+ "./ca": "./node_modules/moment/locale/ca.js",
45
+ "./ca.js": "./node_modules/moment/locale/ca.js",
46
+ "./cs": "./node_modules/moment/locale/cs.js",
47
+ "./cs.js": "./node_modules/moment/locale/cs.js",
48
+ "./cv": "./node_modules/moment/locale/cv.js",
49
+ "./cv.js": "./node_modules/moment/locale/cv.js",
50
+ "./cy": "./node_modules/moment/locale/cy.js",
51
+ "./cy.js": "./node_modules/moment/locale/cy.js",
52
+ "./da": "./node_modules/moment/locale/da.js",
53
+ "./da.js": "./node_modules/moment/locale/da.js",
54
+ "./de": "./node_modules/moment/locale/de.js",
55
+ "./de-at": "./node_modules/moment/locale/de-at.js",
56
+ "./de-at.js": "./node_modules/moment/locale/de-at.js",
57
+ "./de-ch": "./node_modules/moment/locale/de-ch.js",
58
+ "./de-ch.js": "./node_modules/moment/locale/de-ch.js",
59
+ "./de.js": "./node_modules/moment/locale/de.js",
60
+ "./dv": "./node_modules/moment/locale/dv.js",
61
+ "./dv.js": "./node_modules/moment/locale/dv.js",
62
+ "./el": "./node_modules/moment/locale/el.js",
63
+ "./el.js": "./node_modules/moment/locale/el.js",
64
+ "./en-SG": "./node_modules/moment/locale/en-SG.js",
65
+ "./en-SG.js": "./node_modules/moment/locale/en-SG.js",
66
+ "./en-au": "./node_modules/moment/locale/en-au.js",
67
+ "./en-au.js": "./node_modules/moment/locale/en-au.js",
68
+ "./en-ca": "./node_modules/moment/locale/en-ca.js",
69
+ "./en-ca.js": "./node_modules/moment/locale/en-ca.js",
70
+ "./en-gb": "./node_modules/moment/locale/en-gb.js",
71
+ "./en-gb.js": "./node_modules/moment/locale/en-gb.js",
72
+ "./en-ie": "./node_modules/moment/locale/en-ie.js",
73
+ "./en-ie.js": "./node_modules/moment/locale/en-ie.js",
74
+ "./en-il": "./node_modules/moment/locale/en-il.js",
75
+ "./en-il.js": "./node_modules/moment/locale/en-il.js",
76
+ "./en-nz": "./node_modules/moment/locale/en-nz.js",
77
+ "./en-nz.js": "./node_modules/moment/locale/en-nz.js",
78
+ "./eo": "./node_modules/moment/locale/eo.js",
79
+ "./eo.js": "./node_modules/moment/locale/eo.js",
80
+ "./es": "./node_modules/moment/locale/es.js",
81
+ "./es-do": "./node_modules/moment/locale/es-do.js",
82
+ "./es-do.js": "./node_modules/moment/locale/es-do.js",
83
+ "./es-us": "./node_modules/moment/locale/es-us.js",
84
+ "./es-us.js": "./node_modules/moment/locale/es-us.js",
85
+ "./es.js": "./node_modules/moment/locale/es.js",
86
+ "./et": "./node_modules/moment/locale/et.js",
87
+ "./et.js": "./node_modules/moment/locale/et.js",
88
+ "./eu": "./node_modules/moment/locale/eu.js",
89
+ "./eu.js": "./node_modules/moment/locale/eu.js",
90
+ "./fa": "./node_modules/moment/locale/fa.js",
91
+ "./fa.js": "./node_modules/moment/locale/fa.js",
92
+ "./fi": "./node_modules/moment/locale/fi.js",
93
+ "./fi.js": "./node_modules/moment/locale/fi.js",
94
+ "./fo": "./node_modules/moment/locale/fo.js",
95
+ "./fo.js": "./node_modules/moment/locale/fo.js",
96
+ "./fr": "./node_modules/moment/locale/fr.js",
97
+ "./fr-ca": "./node_modules/moment/locale/fr-ca.js",
98
+ "./fr-ca.js": "./node_modules/moment/locale/fr-ca.js",
99
+ "./fr-ch": "./node_modules/moment/locale/fr-ch.js",
100
+ "./fr-ch.js": "./node_modules/moment/locale/fr-ch.js",
101
+ "./fr.js": "./node_modules/moment/locale/fr.js",
102
+ "./fy": "./node_modules/moment/locale/fy.js",
103
+ "./fy.js": "./node_modules/moment/locale/fy.js",
104
+ "./ga": "./node_modules/moment/locale/ga.js",
105
+ "./ga.js": "./node_modules/moment/locale/ga.js",
106
+ "./gd": "./node_modules/moment/locale/gd.js",
107
+ "./gd.js": "./node_modules/moment/locale/gd.js",
108
+ "./gl": "./node_modules/moment/locale/gl.js",
109
+ "./gl.js": "./node_modules/moment/locale/gl.js",
110
+ "./gom-latn": "./node_modules/moment/locale/gom-latn.js",
111
+ "./gom-latn.js": "./node_modules/moment/locale/gom-latn.js",
112
+ "./gu": "./node_modules/moment/locale/gu.js",
113
+ "./gu.js": "./node_modules/moment/locale/gu.js",
114
+ "./he": "./node_modules/moment/locale/he.js",
115
+ "./he.js": "./node_modules/moment/locale/he.js",
116
+ "./hi": "./node_modules/moment/locale/hi.js",
117
+ "./hi.js": "./node_modules/moment/locale/hi.js",
118
+ "./hr": "./node_modules/moment/locale/hr.js",
119
+ "./hr.js": "./node_modules/moment/locale/hr.js",
120
+ "./hu": "./node_modules/moment/locale/hu.js",
121
+ "./hu.js": "./node_modules/moment/locale/hu.js",
122
+ "./hy-am": "./node_modules/moment/locale/hy-am.js",
123
+ "./hy-am.js": "./node_modules/moment/locale/hy-am.js",
124
+ "./id": "./node_modules/moment/locale/id.js",
125
+ "./id.js": "./node_modules/moment/locale/id.js",
126
+ "./is": "./node_modules/moment/locale/is.js",
127
+ "./is.js": "./node_modules/moment/locale/is.js",
128
+ "./it": "./node_modules/moment/locale/it.js",
129
+ "./it-ch": "./node_modules/moment/locale/it-ch.js",
130
+ "./it-ch.js": "./node_modules/moment/locale/it-ch.js",
131
+ "./it.js": "./node_modules/moment/locale/it.js",
132
+ "./ja": "./node_modules/moment/locale/ja.js",
133
+ "./ja.js": "./node_modules/moment/locale/ja.js",
134
+ "./jv": "./node_modules/moment/locale/jv.js",
135
+ "./jv.js": "./node_modules/moment/locale/jv.js",
136
+ "./ka": "./node_modules/moment/locale/ka.js",
137
+ "./ka.js": "./node_modules/moment/locale/ka.js",
138
+ "./kk": "./node_modules/moment/locale/kk.js",
139
+ "./kk.js": "./node_modules/moment/locale/kk.js",
140
+ "./km": "./node_modules/moment/locale/km.js",
141
+ "./km.js": "./node_modules/moment/locale/km.js",
142
+ "./kn": "./node_modules/moment/locale/kn.js",
143
+ "./kn.js": "./node_modules/moment/locale/kn.js",
144
+ "./ko": "./node_modules/moment/locale/ko.js",
145
+ "./ko.js": "./node_modules/moment/locale/ko.js",
146
+ "./ku": "./node_modules/moment/locale/ku.js",
147
+ "./ku.js": "./node_modules/moment/locale/ku.js",
148
+ "./ky": "./node_modules/moment/locale/ky.js",
149
+ "./ky.js": "./node_modules/moment/locale/ky.js",
150
+ "./lb": "./node_modules/moment/locale/lb.js",
151
+ "./lb.js": "./node_modules/moment/locale/lb.js",
152
+ "./lo": "./node_modules/moment/locale/lo.js",
153
+ "./lo.js": "./node_modules/moment/locale/lo.js",
154
+ "./lt": "./node_modules/moment/locale/lt.js",
155
+ "./lt.js": "./node_modules/moment/locale/lt.js",
156
+ "./lv": "./node_modules/moment/locale/lv.js",
157
+ "./lv.js": "./node_modules/moment/locale/lv.js",
158
+ "./me": "./node_modules/moment/locale/me.js",
159
+ "./me.js": "./node_modules/moment/locale/me.js",
160
+ "./mi": "./node_modules/moment/locale/mi.js",
161
+ "./mi.js": "./node_modules/moment/locale/mi.js",
162
+ "./mk": "./node_modules/moment/locale/mk.js",
163
+ "./mk.js": "./node_modules/moment/locale/mk.js",
164
+ "./ml": "./node_modules/moment/locale/ml.js",
165
+ "./ml.js": "./node_modules/moment/locale/ml.js",
166
+ "./mn": "./node_modules/moment/locale/mn.js",
167
+ "./mn.js": "./node_modules/moment/locale/mn.js",
168
+ "./mr": "./node_modules/moment/locale/mr.js",
169
+ "./mr.js": "./node_modules/moment/locale/mr.js",
170
+ "./ms": "./node_modules/moment/locale/ms.js",
171
+ "./ms-my": "./node_modules/moment/locale/ms-my.js",
172
+ "./ms-my.js": "./node_modules/moment/locale/ms-my.js",
173
+ "./ms.js": "./node_modules/moment/locale/ms.js",
174
+ "./mt": "./node_modules/moment/locale/mt.js",
175
+ "./mt.js": "./node_modules/moment/locale/mt.js",
176
+ "./my": "./node_modules/moment/locale/my.js",
177
+ "./my.js": "./node_modules/moment/locale/my.js",
178
+ "./nb": "./node_modules/moment/locale/nb.js",
179
+ "./nb.js": "./node_modules/moment/locale/nb.js",
180
+ "./ne": "./node_modules/moment/locale/ne.js",
181
+ "./ne.js": "./node_modules/moment/locale/ne.js",
182
+ "./nl": "./node_modules/moment/locale/nl.js",
183
+ "./nl-be": "./node_modules/moment/locale/nl-be.js",
184
+ "./nl-be.js": "./node_modules/moment/locale/nl-be.js",
185
+ "./nl.js": "./node_modules/moment/locale/nl.js",
186
+ "./nn": "./node_modules/moment/locale/nn.js",
187
+ "./nn.js": "./node_modules/moment/locale/nn.js",
188
+ "./pa-in": "./node_modules/moment/locale/pa-in.js",
189
+ "./pa-in.js": "./node_modules/moment/locale/pa-in.js",
190
+ "./pl": "./node_modules/moment/locale/pl.js",
191
+ "./pl.js": "./node_modules/moment/locale/pl.js",
192
+ "./pt": "./node_modules/moment/locale/pt.js",
193
+ "./pt-br": "./node_modules/moment/locale/pt-br.js",
194
+ "./pt-br.js": "./node_modules/moment/locale/pt-br.js",
195
+ "./pt.js": "./node_modules/moment/locale/pt.js",
196
+ "./ro": "./node_modules/moment/locale/ro.js",
197
+ "./ro.js": "./node_modules/moment/locale/ro.js",
198
+ "./ru": "./node_modules/moment/locale/ru.js",
199
+ "./ru.js": "./node_modules/moment/locale/ru.js",
200
+ "./sd": "./node_modules/moment/locale/sd.js",
201
+ "./sd.js": "./node_modules/moment/locale/sd.js",
202
+ "./se": "./node_modules/moment/locale/se.js",
203
+ "./se.js": "./node_modules/moment/locale/se.js",
204
+ "./si": "./node_modules/moment/locale/si.js",
205
+ "./si.js": "./node_modules/moment/locale/si.js",
206
+ "./sk": "./node_modules/moment/locale/sk.js",
207
+ "./sk.js": "./node_modules/moment/locale/sk.js",
208
+ "./sl": "./node_modules/moment/locale/sl.js",
209
+ "./sl.js": "./node_modules/moment/locale/sl.js",
210
+ "./sq": "./node_modules/moment/locale/sq.js",
211
+ "./sq.js": "./node_modules/moment/locale/sq.js",
212
+ "./sr": "./node_modules/moment/locale/sr.js",
213
+ "./sr-cyrl": "./node_modules/moment/locale/sr-cyrl.js",
214
+ "./sr-cyrl.js": "./node_modules/moment/locale/sr-cyrl.js",
215
+ "./sr.js": "./node_modules/moment/locale/sr.js",
216
+ "./ss": "./node_modules/moment/locale/ss.js",
217
+ "./ss.js": "./node_modules/moment/locale/ss.js",
218
+ "./sv": "./node_modules/moment/locale/sv.js",
219
+ "./sv.js": "./node_modules/moment/locale/sv.js",
220
+ "./sw": "./node_modules/moment/locale/sw.js",
221
+ "./sw.js": "./node_modules/moment/locale/sw.js",
222
+ "./ta": "./node_modules/moment/locale/ta.js",
223
+ "./ta.js": "./node_modules/moment/locale/ta.js",
224
+ "./te": "./node_modules/moment/locale/te.js",
225
+ "./te.js": "./node_modules/moment/locale/te.js",
226
+ "./tet": "./node_modules/moment/locale/tet.js",
227
+ "./tet.js": "./node_modules/moment/locale/tet.js",
228
+ "./tg": "./node_modules/moment/locale/tg.js",
229
+ "./tg.js": "./node_modules/moment/locale/tg.js",
230
+ "./th": "./node_modules/moment/locale/th.js",
231
+ "./th.js": "./node_modules/moment/locale/th.js",
232
+ "./tl-ph": "./node_modules/moment/locale/tl-ph.js",
233
+ "./tl-ph.js": "./node_modules/moment/locale/tl-ph.js",
234
+ "./tlh": "./node_modules/moment/locale/tlh.js",
235
+ "./tlh.js": "./node_modules/moment/locale/tlh.js",
236
+ "./tr": "./node_modules/moment/locale/tr.js",
237
+ "./tr.js": "./node_modules/moment/locale/tr.js",
238
+ "./tzl": "./node_modules/moment/locale/tzl.js",
239
+ "./tzl.js": "./node_modules/moment/locale/tzl.js",
240
+ "./tzm": "./node_modules/moment/locale/tzm.js",
241
+ "./tzm-latn": "./node_modules/moment/locale/tzm-latn.js",
242
+ "./tzm-latn.js": "./node_modules/moment/locale/tzm-latn.js",
243
+ "./tzm.js": "./node_modules/moment/locale/tzm.js",
244
+ "./ug-cn": "./node_modules/moment/locale/ug-cn.js",
245
+ "./ug-cn.js": "./node_modules/moment/locale/ug-cn.js",
246
+ "./uk": "./node_modules/moment/locale/uk.js",
247
+ "./uk.js": "./node_modules/moment/locale/uk.js",
248
+ "./ur": "./node_modules/moment/locale/ur.js",
249
+ "./ur.js": "./node_modules/moment/locale/ur.js",
250
+ "./uz": "./node_modules/moment/locale/uz.js",
251
+ "./uz-latn": "./node_modules/moment/locale/uz-latn.js",
252
+ "./uz-latn.js": "./node_modules/moment/locale/uz-latn.js",
253
+ "./uz.js": "./node_modules/moment/locale/uz.js",
254
+ "./vi": "./node_modules/moment/locale/vi.js",
255
+ "./vi.js": "./node_modules/moment/locale/vi.js",
256
+ "./x-pseudo": "./node_modules/moment/locale/x-pseudo.js",
257
+ "./x-pseudo.js": "./node_modules/moment/locale/x-pseudo.js",
258
+ "./yo": "./node_modules/moment/locale/yo.js",
259
+ "./yo.js": "./node_modules/moment/locale/yo.js",
260
+ "./zh-cn": "./node_modules/moment/locale/zh-cn.js",
261
+ "./zh-cn.js": "./node_modules/moment/locale/zh-cn.js",
262
+ "./zh-hk": "./node_modules/moment/locale/zh-hk.js",
263
+ "./zh-hk.js": "./node_modules/moment/locale/zh-hk.js",
264
+ "./zh-tw": "./node_modules/moment/locale/zh-tw.js",
265
+ "./zh-tw.js": "./node_modules/moment/locale/zh-tw.js"
266
+ };
267
+
268
+
269
+ function webpackContext(req) {
270
+ var id = webpackContextResolve(req);
271
+ return __webpack_require__(id);
272
+ }
273
+ function webpackContextResolve(req) {
274
+ if(!__webpack_require__.o(map, req)) {
275
+ var e = new Error("Cannot find module '" + req + "'");
276
+ e.code = 'MODULE_NOT_FOUND';
277
+ throw e;
479
278
  }
279
+ return map[req];
480
280
  }
481
-
482
- // DEFINE COMPONENT
483
- if (!window.customElements.get('ssl-certificate-manager'))
484
- window.customElements.define('ssl-certificate-manager', SslCertificateManager);
485
-
486
- /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! jquery */ "jquery")))
281
+ webpackContext.keys = function webpackContextKeys() {
282
+ return Object.keys(map);
283
+ };
284
+ webpackContext.resolve = webpackContextResolve;
285
+ module.exports = webpackContext;
286
+ webpackContext.id = "./node_modules/moment/locale sync recursive ^\\.\\/.*$";
487
287
 
488
288
  /***/ }),
489
289
 
490
- /***/ "./src/modules/server-configurator.js":
491
- /*!********************************************!*\
492
- !*** ./src/modules/server-configurator.js ***!
493
- \********************************************/
290
+ /***/ "./src/modules/extension-deployer.js":
291
+ /*!*******************************************!*\
292
+ !*** ./src/modules/extension-deployer.js ***!
293
+ \*******************************************/
494
294
  /*! exports provided: default */
495
295
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
496
296
 
497
297
  "use strict";
498
298
  __webpack_require__.r(__webpack_exports__);
499
- /* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return ServerConfigurator; });
299
+ /* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return ExtensionDeployer; });
500
300
  /* harmony import */ var _base_module__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-module */ "./src/modules/base-module.js");
501
- /* harmony import */ var _utils_uibuilder_config_interface_builder__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/uibuilder/config-interface-builder */ "./src/utils/uibuilder/config-interface-builder.js");
502
- /* harmony import */ var _components_module_specific_ssl_certificate_manager__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../components/module-specific/ssl-certificate-manager */ "./src/components/module-specific/ssl-certificate-manager.js");
503
-
301
+ /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! moment */ "./node_modules/moment/moment.js");
302
+ /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_1__);
504
303
 
505
304
 
506
305
 
507
- class ServerConfigurator extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseModule"]
306
+ class ExtensionDeployer extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseModule"]
508
307
  {
509
308
  constructor()
510
309
  {
511
- super('serverConfig');
310
+ super('extDeployer');
512
311
 
513
312
  // Outgoing requests
514
313
  this.REQ_INIT = 'init';
515
- this.REQ_GET_CONFIG = 'getConfig';
516
- this.REQ_UPDATE_CONFIG = 'updConfig';
517
- this.REQ_UPDATE_GEO_DB = 'updGeoDb';
314
+ this.REQ_GET_NODES = 'getNodes';
518
315
 
519
316
  // Incoming responses
317
+ this.RESP_LOCKED = 'lock';
520
318
  this.RESP_INIT = 'init';
521
- this.RESP_CONFIG = 'config';
522
- this.RESP_CONFIG_UPDATE_CONFIRM = 'configUpdate';
523
- this.RESP_CONFIG_CHANGED_ALERT = 'configAlert';
524
- this.RESP_SSL_UPLOAD_ERROR = 'sslUploadError';
525
- this.RESP_SSL_UPLOAD_CONFIRM = 'sslUpload';
526
- this.RESP_UPDATE_GEO_DB = 'geoDbUpdate';
319
+ this.RESP_NODES = 'nodes';
320
+ this.RESP_SUCCESS = 'success';
321
+ this.RESP_WARN = 'warn';
322
+ this.RESP_ERROR = 'error';
323
+
324
+ this._selectedNodes = [];
527
325
  }
528
326
 
529
327
  //------------------------------------
530
328
  // COMMON MODULE INTERFACE METHODS
531
329
  // This members are used by the main controller
532
330
  // to communicate with the module's controller.
533
- // This methods override those in BaseModule class.
534
331
  //------------------------------------
535
332
 
536
333
  initialize(idData, shellController)
@@ -538,8 +335,8 @@ class ServerConfigurator extends _base_module__WEBPACK_IMPORTED_MODULE_0__["Base
538
335
  // Call super method
539
336
  super.initialize(idData, shellController);
540
337
 
541
- // Initialize progress bar
542
- $('#src-progressBar').kendoProgressBar({
338
+ // Initialize progress bars
339
+ $('.exd-progressBar').kendoProgressBar({
543
340
  min: 0,
544
341
  max: 100,
545
342
  value: false,
@@ -549,20 +346,103 @@ class ServerConfigurator extends _base_module__WEBPACK_IMPORTED_MODULE_0__["Base
549
346
  }
550
347
  });
551
348
 
552
- // Create interface builder instance
553
- this._interfaceBuilder = new _utils_uibuilder_config_interface_builder__WEBPACK_IMPORTED_MODULE_1__["ConfigInterfaceBuilder"]();
349
+ // Add listeners to buttons
350
+ $('#exd-retryBt').on('click', $.proxy(this._onRetryClick, this));
351
+ $('#exd-refreshBt').on('click', $.proxy(this._requestNodesList, this));
352
+ $('#exd-deployBt').on('click', $.proxy(this._onDeployClick, this));
353
+ $('.exd-statusCloseBt').on('click', $.proxy(this._onCloseStatusClick, this));
354
+
355
+ // Initialize kendo switch
356
+ this._modeSwitch = $('#exd-modeCb').kendoSwitch().data('kendoSwitch');
357
+
358
+ // Initialize grid
359
+ this._grid = $('#exd-nodesList').kendoGrid({
360
+ scrollable: true,
361
+ sortable: true,
362
+ //resizable: true,
363
+ selectable: false,
364
+ columns: [
365
+ {
366
+ selectable: true,
367
+ width: 41
368
+ },
369
+ {
370
+ field: 'name',
371
+ width: 500,
372
+ title: 'Node',
373
+ template: function(dataItem) {
374
+ if (dataItem['alias'])
375
+ return '<div class="name-cell"><span>' + dataItem['alias'] + '</span><br><small class="text-muted">' + dataItem['name'] + '<small></div>';
376
+ else
377
+ return '<div class="name-cell"><span>' + dataItem['name'] + '</span></div>';
378
+ }
379
+ },
380
+ {
381
+ field: 'health',
382
+ width: 75,
383
+ title: 'Health',
384
+ sortable: false,
385
+ template: $.proxy(this._getHealthTemplate, this)
386
+ },
387
+ ],
388
+ noRecords: {
389
+ template: 'No game nodes in the cluster.'
390
+ },
391
+ dataSource: {
392
+ schema: {
393
+ model: {
394
+ id: 'id',
395
+ // fields: {
396
+ // id: { type: 'string' },
397
+ // active: { type: 'boolean' }
398
+ // }
399
+ }
400
+ },
401
+ group: {
402
+ field: 'active',
403
+ dir: 'desc',
404
+ }
405
+ },
406
+ change: $.proxy(this._onNodesGridChange, this),
407
+ dataBound: $.proxy(this._onNodesGridDataBound, this),
408
+ }).data('kendoGrid');
409
+
410
+ // Initialize kendo uploader
411
+ this._uploader = $('#exd-uploader').kendoUpload({
412
+ multiple: false,
413
+ async: {
414
+ saveUrl: 'http://localhost', // This will be changed later in _onUploadStart method
415
+ autoUpload: false,
416
+ },
417
+ directoryDrop: true,
418
+ upload: $.proxy(this._onUploadStart, this),
419
+ complete: $.proxy(this._onUploadEnd, this),
420
+ localization: {
421
+ select: 'Select zip file...'
422
+ }
423
+ }).data('kendoUpload');
554
424
 
555
- // Add listener to GeoLite2 database update button
556
- $('#src-updateGeolocDbButton').on('click', $.proxy(this._onUpdateGeolocDbClick, this));
425
+ // Initialize "deployment status" modal
426
+ this._deployStatusModal = $('#exd-deployStatusModal');
427
+ this._deployStatusModal.modal({
428
+ backdrop: 'static',
429
+ keyboard: false,
430
+ show: false
431
+ });
557
432
 
558
- // Add listener to interface buttons
559
- $('#src-reloadButton').on('click', $.proxy(this._onReloadClick, this));
560
- $('#src-submitButton').on('click', $.proxy(this._onSubmitClick, this));
433
+ // Initialize help tooltips
434
+ $(this).kendoTooltip({
435
+ filter: 'i[title].help',
436
+ position: 'right',
437
+ content: function(e) {
438
+ return `<div class="help-tooltip">${e.target.data('title')}</div>`;
439
+ }
440
+ });
561
441
 
562
- // Save ref to SSL Manager
563
- this._sslCertManager = document.getElementById('src-sslCertManager');
442
+ // Set upload form disabled
443
+ this._enableDeployForm(false);
564
444
 
565
- //-----------------------------------*/
445
+ //-------------------------------------------
566
446
 
567
447
  // Send initialization request
568
448
  this.sendExtensionRequest(this.REQ_INIT);
@@ -573,28 +453,38 @@ class ServerConfigurator extends _base_module__WEBPACK_IMPORTED_MODULE_0__["Base
573
453
  // Call super method
574
454
  super.destroy();
575
455
 
576
- // Destroy SSL Certificate Manager
577
- this._sslCertManager.destroy();
456
+ // Remove click listeners
457
+ $('#exd-retryBt').off('click');
458
+ $('#exd-refreshBt').off('click');
459
+ $('#exd-deployBt').off('click');
460
+ $('.exd-statusCloseBt').off('click');
578
461
 
579
- // Remove interface buttons click listeners
580
- $('#src-updateGeolocDbButton').off('click');
581
- $('#src-reloadButton').off('click');
582
- $('#src-submitButton').off('click');
583
-
584
- // Clear tabs container
585
- this._clearTabs();
462
+ // Clear nodes request scheduling
463
+ clearTimeout(this._requestNodesTimer);
586
464
  }
587
465
 
588
466
  onExtensionCommand(command, data)
589
467
  {
590
- // Initialization data received
591
- if (command == this.RESP_INIT)
468
+ /*
469
+ * This response is returned if the file UploadsLock.txt exists in the /config folder of the server.
470
+ * This is an additional security measure to avoid unwanted files to be uploaded by malicius users accessing the server
471
+ * with the default credentials, in case they have not been changed by the administrator after the installation.
472
+ * The file must be removed manually before accessing the Extension Deployer module for the first time
473
+ */
474
+ if (command == this.RESP_LOCKED)
475
+ {
476
+ // Show warning
477
+ this._switchMainView('exd-locked');
478
+ }
479
+
480
+ // Module can be enabled (no locking file exists)
481
+ else if (command == this.RESP_INIT)
592
482
  {
593
483
  // Retrieve module id sent by the server (required because multiple modules use file uploading service)
594
484
  const uploadModuleId = data.getUtfString('modId');
595
485
 
596
- // Set SSL upload manager target configuration
597
- this._sslCertManager.uploadTargetConfig = {
486
+ // Set file uploading target configuration
487
+ this._uploadTargetConfig = {
598
488
  sessionToken: this.smartFox.sessionToken,
599
489
  host: this.smartFox.config.host,
600
490
  port: this.smartFox.config.port,
@@ -602,239 +492,272 @@ class ServerConfigurator extends _base_module__WEBPACK_IMPORTED_MODULE_0__["Base
602
492
  protocol: this.smartFox.config.useSSL ? 'https' : 'http'
603
493
  };
604
494
 
605
- // Server sends a flag indicating if file uploads are locked
606
- // We use it to enable the "Manage SSL certificate" button
607
- this._sslLocked = data.getBool('lock');
608
-
609
- if (!this._sslLocked)
610
- $('#src-manageSslWarn').hide();
495
+ // Show module's main view
496
+ this._switchMainView('exd-main');
611
497
 
612
- // Request configuration data to server instance
613
- this.sendExtensionRequest(this.REQ_GET_CONFIG);
498
+ // Request nodes list to server
499
+ this._requestNodesList();
614
500
  }
615
501
 
616
- // Server configuration data received
617
- else if (command == this.RESP_CONFIG)
502
+ else if (command == this.RESP_NODES)
618
503
  {
619
- // Build user interface based on received data
620
- this._interfaceBuilder.buildInterface(data.getSFSArray('settings'), 'src-tabNavigator', false);
504
+ let nodesObj = data.getSFSArray('nodes');
621
505
 
622
- // Enable buttons
623
- this._enableButtons(true);
506
+ let nodes = [];
507
+ let nodesIds = [];
624
508
 
625
- // Initialize TabNavigator-ralated widgets
626
- if (!this._tabNavInitialized)
509
+ for (let i = 0; i < nodesObj.size(); i++)
627
510
  {
628
- // Enable scrolling tabs
629
- $('#src-tabNavigator > #tabs').scrollingTabs({
630
- bootstrapVersion: 4,
631
- scrollToTabEdge: true,
632
- enableSwiping: true,
633
- disableScrollArrowsOnFullyScrolled: true,
634
- cssClassLeftArrow: 'fa fa-chevron-left',
635
- cssClassRightArrow: 'fa fa-chevron-right'
636
- });
511
+ let node = nodesObj.getSFSArray(i);
512
+
513
+ nodesIds.push(node.getUtfString(0));
637
514
 
638
- this._tabNavInitialized = true;
515
+ nodes.push({
516
+ 'id': node.getUtfString(0),
517
+ 'alias': node.getUtfString(1),
518
+ 'name': node.getUtfString(2),
519
+ 'health': node.getBool(3),
520
+ 'active': node.getBool(4), // Used for grouping
521
+ });
639
522
  }
640
523
 
641
- // Run validation (to remove validation messages if data was reloaded)
642
- this._interfaceBuilder.checkIsValid();
524
+ // Get nodes grid datasource
525
+ let ds = this._grid.dataSource;
643
526
 
644
- this._switchView('src-main');
645
- }
527
+ // --- REMOVE NODES ---
646
528
 
647
- // Server configuration update confirmation
648
- else if (command == this.RESP_CONFIG_UPDATE_CONFIRM)
649
- {
650
- // Enable buttons
651
- this._enableButtons(true);
529
+ let self = this;
530
+ $.map(ds.data(), function (dataItem, index) {
531
+ if (dataItem && !nodesIds.includes(dataItem['id']))
532
+ {
533
+ // Remove node from datastore
534
+ ds.remove(dataItem);
652
535
 
653
- // Enable form items
654
- this._interfaceBuilder.disableInterface(false);
536
+ // Remove node from list of selected nodes (if selected)
537
+ self._selectedNodes = self._selectedNodes.filter(x => x !== dataItem['id']);
538
+ }
539
+ });
655
540
 
656
- // If the current user is the updater, show a notification
657
- // Otherwise, show a dialog box suggesting to reload
658
- let updater = data.getUtfString('user');
541
+ // --- ADD/UPDATE NODES ---
659
542
 
660
- if (updater == this.smartFox.mySelf.name)
543
+ for (let node of nodes)
661
544
  {
662
- // Reset the 'modified' flag
663
- this._interfaceBuilder.resetIsModified();
545
+ var dataItem = ds.get(node.id);
664
546
 
665
- // Display notification
666
- this.shellCtrl.showNotification('Server settings updated', 'Changes will be applied on next server restart');
667
- }
668
- else
669
- {
670
- // Show alert
671
- this.shellCtrl.showSimpleAlert(`Administrator ${updater} has modified the server settings; please reload to update your view.`);
547
+ // Update node
548
+ if (dataItem)
549
+ {
550
+ dataItem.set('health', node.health);
551
+ dataItem.set('active', node.active);
552
+
553
+ dataItem.dirty = false; // Hides "dirty" indicator in grid
554
+ }
672
555
 
673
- // Disable submit button
674
- $('#src-submitButton').attr('disabled', true);
556
+ // Add node
557
+ else
558
+ ds.add(node);
675
559
  }
560
+
561
+ // Refresh grid
562
+ this._grid.refresh();
676
563
  }
677
564
 
678
- // Server configuration xml saved by an external process
679
- else if (command == this.RESP_CONFIG_CHANGED_ALERT)
565
+ else if (command == this.RESP_ERROR)
680
566
  {
681
- // Show alert
682
- this.shellCtrl.showSimpleAlert(`The system has modified the server settings automatically; please reload to update your view.`);
567
+ // Display error message
568
+ $('#exd-statusErrorText').html(data.getUtfString('msg'));
683
569
 
684
- // Disable submit button
685
- $('#src-submitButton').attr('disabled', true);
570
+ // Switch to view
571
+ this._switchStatusView('exd-statusError');
686
572
  }
687
573
 
688
- // SSL certificate upload error
689
- else if (command == this.RESP_SSL_UPLOAD_ERROR)
574
+ else if (command == this.RESP_WARN)
690
575
  {
691
- const error = data.getUtfString('error');
692
-
693
- // Log warning
694
- this.shellCtrl.logMessage(error, 'error');
576
+ // Display error message
577
+ $('#exd-statusWarningText').html(data.getUtfString('msg').replace(/(?:\r\n|\r|\n)/g, '<br>'));
695
578
 
696
- // Show error in manager window
697
- this._sslCertManager.onSslCertUploadError(error);
579
+ // Switch to view
580
+ this._switchStatusView('exd-statusWarning');
698
581
  }
699
582
 
700
- // SSL certificate upload confirmed
701
- else if (command == this.RESP_SSL_UPLOAD_CONFIRM)
583
+ else if (command == this.RESP_SUCCESS)
702
584
  {
703
- // Closw manager window
704
- this._sslCertManager.onSslCertUploadSuccess();
705
-
706
- let updater = data.getUtfString('user');
707
-
708
- // Display notification
709
- if (updater == this.smartFox.mySelf.name)
710
- this.shellCtrl.showNotification('SSL certificate', 'SSL certificate keystore was uploaded successfully');
711
- else
712
- this.shellCtrl.showNotification('SSL certificate', `Administrator ${updater} has uploaded a new SSL certificate keystore`);
713
-
714
- // When a certificate is uploaded, HTTPS is also enabled automatically:
715
- // we have to update the interface accordingly
716
- this._updateConfigFormItemDisplayedValue('webServer.enableHttps', true);
585
+ this._switchStatusView('exd-statusSuccess');
717
586
  }
587
+ }
718
588
 
719
- // Geolocation database update confirmation
720
- else if (command == this.RESP_UPDATE_GEO_DB)
721
- {
722
- // Enable button
723
- $('#src-updateGeolocDbButton').attr('disabled', false);
589
+ //---------------------------------
590
+ // UI EVENT LISTENERS
591
+ //---------------------------------
724
592
 
725
- // Check success
726
- if (data.getBool('success'))
727
- {
728
- // Update displayed date
729
- this._updateConfigFormItemDisplayedValue('adminHelper.geoDbReleaseDate', data.getUtfString('newRelDate'));
593
+ _enableDeployForm(enabled)
594
+ {
595
+ $('#exd-uploadFileForm').prop('disabled', !enabled);
596
+ this._modeSwitch.enable(enabled);
597
+ }
730
598
 
731
- // If the current user is the updater, also show a notification
732
- let updater = data.getUtfString('user');
599
+ _onRetryClick()
600
+ {
601
+ this._switchMainView('exd-init');
733
602
 
734
- if (updater == this.smartFox.mySelf.name)
735
- this.shellCtrl.showNotification('Geolocation database updated', 'Latest release of the GeoLite2 Country database has been installed successfully');
736
- }
737
- else
738
- {
739
- // Show alert
740
- this.shellCtrl.showSimpleAlert(data.getUtfString('error'));
741
- }
742
- }
603
+ // Re-send initialization request
604
+ this.sendExtensionRequest(this.REQ_INIT);
743
605
  }
744
606
 
745
- //------------------------------------
746
- // PRIVATE METHODS
747
- //------------------------------------
607
+ _onCloseStatusClick()
608
+ {
609
+ this._deployStatusModal.hide();
610
+
611
+ // Clear uploader
612
+ this._uploader.clearAllFiles();
613
+ }
748
614
 
749
- _enableButtons(enabled)
615
+ _onNodesGridChange(e, args)
750
616
  {
751
- $('#src-reloadButton').attr('disabled', !enabled);
752
- $('#src-submitButton').attr('disabled', !enabled);
753
- $('#src-backupCheck').attr('disabled', !enabled);
617
+ let grid = e.sender;
618
+ let items = grid.items();
754
619
 
755
- $('#src-updateGeolocDbButton').attr('disabled', !enabled);
620
+ this._selectedNodes = [];
621
+
622
+ for (let i of grid.select())
623
+ {
624
+ let dataItem = grid.dataItem(i);
625
+ this._selectedNodes.push(dataItem['id']);
626
+ }
756
627
 
757
- if (!this._sslLocked)
758
- this._sslCertManager.enabled = enabled;
628
+ // Enable upload button
629
+ this._enableDeployForm(this._selectedNodes.length > 0);
759
630
  }
760
631
 
761
- _switchView(viewId)
632
+ _onNodesGridDataBound(e)
762
633
  {
763
- document.getElementById('src-viewstack').selectedElement = document.getElementById(viewId);
634
+ let grid = e.sender;
635
+ let items = grid.items();
636
+ let itemsToSelect = [];
637
+ let self = this;
638
+
639
+ items.each(function (idx, row) {
640
+ let dataItem = grid.dataItem(row);
641
+ if (self._selectedNodes.includes(dataItem['id'])) {
642
+ itemsToSelect.push(row);
643
+ }
644
+ });
645
+
646
+ // Re-select previously selected nodes
647
+ grid.select(itemsToSelect);
648
+
649
+ // Disable upload button
650
+ if (itemsToSelect.length == 0)
651
+ this._enableDeployForm(false);
652
+
653
+ //==================================================
654
+
655
+ // Hide group column and collapse icon
656
+ $('#exd-nodesList .k-group-col, #exd-nodesList .k-group-cell').remove();
657
+ let spanCells = $('#exd-nodesList .k-grouping-row').children('td');
658
+ spanCells.attr('colspan', spanCells.attr('colspan') - 1);
659
+ $('#exd-nodesList .k-icon.k-i-collapse').hide();
660
+
661
+ // Modify group label
662
+ $('#exd-nodesList .k-grouping-row td p.k-reset').each(function( index ) {
663
+ if ($(this).text() == 'active: true')
664
+ $(this).text('Active nodes');
665
+ else
666
+ $(this).text('Inactive nodes');
667
+ });
764
668
  }
765
669
 
766
- _clearTabs()
670
+ _requestNodesList()
767
671
  {
768
- // Destroy scrolling tabs
769
- $('#src-tabNavigator #tabs').scrollingTabs('destroy');
672
+ // Clear previous request scheduling
673
+ clearTimeout(this._requestNodesTimer);
674
+
675
+ // Check if connection is still available
676
+ if (this.smartFox.isConnected)
677
+ {
678
+ // Send request to extension
679
+ this.sendExtensionRequest(this.REQ_GET_NODES);
770
680
 
771
- // Remove all tab navigator content
772
- this._interfaceBuilder.destroyInterface();
681
+ // Schedule next request
682
+ this._requestNodesTimer = setTimeout($.proxy(this._requestNodesList, this), 5000); // Every 5 seconds
683
+ }
773
684
  }
774
685
 
775
- _onUpdateGeolocDbClick()
686
+ _onDeployClick()
776
687
  {
777
- // Disable button
778
- $('#src-updateGeolocDbButton').attr('disabled', true);
779
-
780
- // Send request to server
781
- this.sendExtensionRequest(this.REQ_UPDATE_GEO_DB);
688
+ // Trigger click on Upload widget
689
+ $('button.k-upload-selected').click();
782
690
  }
783
691
 
784
- _onReloadClick()
692
+ _onUploadStart(e)
785
693
  {
786
- // Disable buttons
787
- this._enableButtons(false);
694
+ // Display status modal
695
+ this._switchStatusView('exd-statusProgress');
696
+ this._deployStatusModal.show();
697
+
698
+ // Set destination url
699
+ const url = this._uploadTargetConfig.protocol + '://' + this._uploadTargetConfig.host + ':' + this._uploadTargetConfig.port + '/BlueBox/SFS2XFileUpload?sessHashId=' + this._uploadTargetConfig.sessionToken;
700
+
701
+ e.sender.options.async.saveUrl = url;
788
702
 
789
- // Switch to loading view
790
- this._switchView('src-loading');
703
+ // Set payload
704
+ const params = new FormData();
705
+ params.append('__module', this._uploadTargetConfig.moduleId);
706
+ params.append('__nodes', JSON.stringify(this._selectedNodes));
707
+ params.append('__noDestroy', this._modeSwitch.check());
791
708
 
792
- // Hide validation messages
793
- this._interfaceBuilder.resetValidation();
709
+ for (let f = 0; f < e.files.length; f++)
710
+ params.append('files[]', e.files[f].rawFile);
794
711
 
795
- // Request configuration data to server instance
796
- this.sendExtensionRequest(this.REQ_GET_CONFIG);
712
+ e.formData = params;
797
713
  }
798
714
 
799
- _onSubmitClick()
715
+ _onUploadEnd(e)
800
716
  {
801
- // Check validity
802
- if (this._interfaceBuilder.checkIsValid())
803
- {
804
- let changes = this._interfaceBuilder.getChangedData();
717
+ // Nothign to do
718
+ }
805
719
 
806
- if (changes.size() > 0)
807
- {
808
- // Disable buttons
809
- this._enableButtons(false);
720
+ _onFilesUploadEnd(response)
721
+ {
722
+ // Nothing to do: we have to wait the upload process completion to be signaled by the server through the dedicated Extension response
810
723
 
811
- // Disable form items
812
- this._interfaceBuilder.disableInterface(true);
724
+ //=================================================================
813
725
 
814
- // Send updated settings to server instance
815
- let params = new SFS2X.SFSObject();
816
- params.putSFSArray('settings', changes);
817
- params.putBool('backup', $('#src-backupCheck').prop('checked'));
726
+ // TODO Should we handle this response in some way? For some unknown reason we always get ok=false and status=0
727
+ // console.log(response)
728
+ // console.log(response.ok)
729
+ // console.log(response.status)
730
+ }
818
731
 
819
- this.sendExtensionRequest(this.REQ_UPDATE_CONFIG, params);
820
- }
821
- }
822
- else
823
- this.shellCtrl.showSimpleAlert('Unable to submit configuration changes due to an invalid value; please verify the highlighted form fields in all tabs.', true);
732
+ //------------------------------------
733
+ // PRIVATE METHODS
734
+ //------------------------------------
735
+
736
+ _switchMainView(viewId)
737
+ {
738
+ document.getElementById('exd-viewstack').selectedElement = document.getElementById(viewId);
739
+ }
740
+
741
+ _switchStatusView(viewId)
742
+ {
743
+ document.getElementById('exd-deployStatus').selectedElement = document.getElementById(viewId);
824
744
  }
825
745
 
826
- _updateConfigFormItemDisplayedValue(configParamName, newValue)
746
+ _getHealthTemplate(dataItem)
827
747
  {
828
- // Get the relevant Configuration Form Item
829
- const configFormItem = this._interfaceBuilder.getConfigFormItem(configParamName);
748
+ let style = 'text-success';
830
749
 
831
- // Update Configuration Parameter associated with the Configuration Form Item
832
- configFormItem.data.value = newValue;
833
- configFormItem.data.resetIsModified(); // This is needed to avoid the Configuration Parameter to flagged as 'changed'
750
+ if (!dataItem['health'])
751
+ style = 'text-danger';
834
752
 
835
- // Display the new value of the Configuration Form Item
836
- configFormItem._setWidgetValue(); // Display the new value in the config form item
753
+ return `<span class="${style}"><i class="fas fa-circle"></i></span>`;
837
754
  }
755
+
756
+ //---------------------------------
757
+ // PRIVATE GETTERS
758
+ //---------------------------------
759
+
760
+
838
761
  }
839
762
 
840
763
  /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! jquery */ "jquery")))
@@ -842,4 +765,4 @@ class ServerConfigurator extends _base_module__WEBPACK_IMPORTED_MODULE_0__["Base
842
765
  /***/ })
843
766
 
844
767
  }]);
845
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXRzL2pzL2NvcmUvbW9kdWxlcy9tb2R1bGUtOS5idW5kbGUuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9jb21wb25lbnRzL21vZHVsZS1zcGVjaWZpYy9zc2wtY2VydGlmaWNhdGUtbWFuYWdlci5qcyIsIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9tb2R1bGVzL3NlcnZlci1jb25maWd1cmF0b3IuanMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtieXRlc1RvU2l6ZX0gZnJvbSAnLi4vLi4vdXRpbHMvdXRpbGl0aWVzJztcbmltcG9ydCBhZXNqcyBmcm9tICdhZXMtanMnO1xuXG5leHBvcnQgY2xhc3MgU3NsQ2VydGlmaWNhdGVNYW5hZ2VyIGV4dGVuZHMgSFRNTEVsZW1lbnRcbntcblx0Y29uc3RydWN0b3IoKVxuXHR7XG5cdCAgICBzdXBlcigpO1xuXG5cdFx0dGhpcy5fbW9kYWxIdG1sID0gYFxuXHRcdFx0PGRpdiBjbGFzcz1cIm1vZGFsXCIgaWQ9XCJ1cGxvYWRNb2RhbFwiIHRhYmluZGV4PVwiLTFcIiByb2xlPVwiZGlhbG9nXCIgYXJpYS1sYWJlbGxlZGJ5PVwidXBsb2FkTW9kYWxUaXRsZVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxuXHRcdFx0XHQ8ZGl2IGNsYXNzPVwibW9kYWwtZGlhbG9nIG1vZGFsLWRpYWxvZy1jZW50ZXJlZFwiIHJvbGU9XCJkb2N1bWVudFwiPlxuXHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJtb2RhbC1jb250ZW50XCI+XG5cdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwibW9kYWwtaGVhZGVyXCI+XG5cdFx0XHRcdFx0XHRcdDxoNSBjbGFzcz1cIm1vZGFsLXRpdGxlIHRleHQtcHJpbWFyeVwiIGlkPVwidXBsb2FkTW9kYWxUaXRsZVwiPlNTTCBDZXJ0aWZpY2F0ZSBNYW5hZ2VyPC9oNT5cblx0XHRcdFx0XHRcdFx0PGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJjbG9zZVwiIGRhdGEtZGlzbWlzcz1cIm1vZGFsXCIgYXJpYS1sYWJlbD1cIkNsb3NlXCI+XG5cdFx0XHRcdFx0XHRcdFx0PHNwYW4gYXJpYS1oaWRkZW49XCJ0cnVlXCI+JnRpbWVzOzwvc3Bhbj5cblx0XHRcdFx0XHRcdFx0PC9idXR0b24+XG5cdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJtb2RhbC1ib2R5IGluLWZsb3ctaW52YWxpZC1tc2dcIj5cblx0XHRcdFx0XHRcdFx0PGZpZWxkc2V0IGlkPVwidXBsb2FkRmllbGRzZXRcIj5cblx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGlkPVwidXBsb2FkZXJTdWJmb3JtXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuXHRcdFx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiY29sLWZvcm0tbGFiZWwgZm9ybS1sYWJlbC1jb250YWluZXJcIj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ8bGFiZWwgZm9yPVwidXBsb2FkZXJcIiBjbGFzcz1cImZvcm0tbGFiZWxcIj5DZXJ0aWZpY2F0ZSBrZXlzdG9yZSAoamtzKSA8aSBjbGFzcz1cImZhcyBmYS1xdWVzdGlvbi1jaXJjbGUgdGV4dC1tdXRlZCBoZWxwXCIgdGl0bGU9XCJTU0wgY2VydGlmaWNhdGUncyBwcm90ZWN0ZWQga2V5c3RvcmUgZmlsZSB0byBiZSB1cGxvYWRlZCB0byB0aGUgc2VydmVyLCBpbiBqa3MgZm9ybWF0XCI+PC9pPjwvbGFiZWw+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiaW5uZXItd2lkZ2V0XCI+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0PGlucHV0IHR5cGU9XCJmaWxlXCIgaWQ9XCJ1cGxvYWRlclwiIG5hbWU9XCJ1cGxvYWRlclwiIGFjY2VwdD1cIi5qa3NcIiBkYXRhLXVwbG9hZC1tc2c9XCJTZWxlY3QgYSBmaWxlXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJrLWludmFsaWQtbXNnIHBvc2l0aW9uLXN0YXRpY1wiIGRhdGEtZm9yPVwidXBsb2FkZXJcIj48L3NwYW4+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHRcdFx0PGRpdiBpZD1cInBhc3N3b3Jkc1N1YmZvcm1cIj5cblx0XHRcdFx0XHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJmb3JtLXJvd1wiPlxuXHRcdFx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cCBjb2xcIj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiY29sLWZvcm0tbGFiZWwgZm9ybS1sYWJlbC1jb250YWluZXJcIj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdDxsYWJlbCBmb3I9XCJrc1Bhc3N3b3JkXCIgY2xhc3M9XCJmb3JtLWxhYmVsXCI+S2V5c3RvcmUgcGFzc3dvcmQgPGkgY2xhc3M9XCJmYXMgZmEtcXVlc3Rpb24tY2lyY2xlIHRleHQtbXV0ZWQgaGVscFwiIHRpdGxlPVwiUGFzc3dvcmQgdXNlZCB0byBwcm90ZWN0IHRoZSBjZXJ0aWZpY2F0ZSBrZXlzdG9yZVwiPjwvaT48L2xhYmVsPlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJpbm5lci13aWRnZXRcIj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdDxpbnB1dCB0eXBlPVwicGFzc3dvcmRcIiBpZD1cImtzUGFzc3dvcmRcIiBuYW1lPVwia3NQYXNzd29yZFwiIGNsYXNzPVwiZm9ybS1jb250cm9sIGstdGV4dGJveFwiIGF1dG9jb21wbGV0ZT1cIm9mZlwiIHJlcXVpcmVkIGRhdGEtcmVxdWlyZWQtbXNnPVwiUmVxdWlyZWRcIiAvPlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJrLWludmFsaWQtbXNnIHBvc2l0aW9uLXN0YXRpY1wiIGRhdGEtZm9yPVwia3NQYXNzd29yZFwiPjwvc3Bhbj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0PGRpdiBjbGFzcz1cImZvcm0tZ3JvdXAgY29sXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0PGRpdiBjbGFzcz1cImNvbC1mb3JtLWxhYmVsIGZvcm0tbGFiZWwtY29udGFpbmVyXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ8bGFiZWwgZm9yPVwiY29uZmlybUtzUGFzc3dvcmRcIiBjbGFzcz1cImZvcm0tbGFiZWxcIj5Db25maXJtIHBhc3N3b3JkIDxpIGNsYXNzPVwiZmFzIGZhLXF1ZXN0aW9uLWNpcmNsZSB0ZXh0LW11dGVkIGhlbHBcIiB0aXRsZT1cIktleXN0b3JlIHBhc3N3b3JkIGNvbmZpcm1hdGlvblwiPjwvaT48L2xhYmVsPlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJpbm5lci13aWRnZXRcIj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdDxpbnB1dCB0eXBlPVwicGFzc3dvcmRcIiBpZD1cImNvbmZpcm1Lc1Bhc3N3b3JkXCIgbmFtZT1cImNvbmZpcm1Lc1Bhc3N3b3JkXCIgY2xhc3M9XCJmb3JtLWNvbnRyb2wgay10ZXh0Ym94XCIgYXV0b2NvbXBsZXRlPVwib2ZmXCIgcmVxdWlyZWQgZGF0YS1yZXF1aXJlZC1tc2c9XCJSZXF1aXJlZFwiIC8+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ8c3BhbiBjbGFzcz1cImstaW52YWxpZC1tc2cgcG9zaXRpb24tc3RhdGljXCIgZGF0YS1mb3I9XCJjb25maXJtS3NQYXNzd29yZFwiPjwvc3Bhbj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHRcdFx0XHQ8L2Rpdj5cblxuXHRcdFx0XHRcdFx0XHRcdFx0PHA+PGVtPkZvciBhZGRpdGlvbmFsIHNlY3VyaXR5LCBlbnRlciBhZ2FpbiBhbmQgY29uZmlybSB5b3VyIFNGUzJYIGFkbWluaXN0cmF0aW9uIHBhc3N3b3JkLjwvZW0+PC9wPlxuXG5cdFx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiZm9ybS1yb3dcIj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0PGRpdiBjbGFzcz1cImZvcm0tZ3JvdXAgY29sXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0PGRpdiBjbGFzcz1cImNvbC1mb3JtLWxhYmVsIGZvcm0tbGFiZWwtY29udGFpbmVyXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ8bGFiZWwgZm9yPVwiYWRtaW5QYXNzd29yZFwiIGNsYXNzPVwiZm9ybS1sYWJlbFwiPkFkbWluIHBhc3N3b3JkIDxpIGNsYXNzPVwiZmFzIGZhLXF1ZXN0aW9uLWNpcmNsZSB0ZXh0LW11dGVkIGhlbHBcIiB0aXRsZT1cIlNtYXJ0Rm94U2VydmVyIDJYIHJlbW90ZSBhZG1pbmlzdHJhdGlvbiBwYXNzd29yZFwiPjwvaT48L2xhYmVsPlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJpbm5lci13aWRnZXRcIj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdDxpbnB1dCB0eXBlPVwicGFzc3dvcmRcIiBpZD1cImFkbWluUGFzc3dvcmRcIiBuYW1lPVwiYWRtaW5QYXNzd29yZFwiIGNsYXNzPVwiZm9ybS1jb250cm9sIGstdGV4dGJveFwiIGF1dG9jb21wbGV0ZT1cIm9mZlwiIHJlcXVpcmVkIGRhdGEtcmVxdWlyZWQtbXNnPVwiUmVxdWlyZWRcIiAvPlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJrLWludmFsaWQtbXNnIHBvc2l0aW9uLXN0YXRpY1wiIGRhdGEtZm9yPVwiYWRtaW5QYXNzd29yZFwiPjwvc3Bhbj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0PGRpdiBjbGFzcz1cImZvcm0tZ3JvdXAgY29sXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0PGRpdiBjbGFzcz1cImNvbC1mb3JtLWxhYmVsIGZvcm0tbGFiZWwtY29udGFpbmVyXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ8bGFiZWwgZm9yPVwiY29uZmlybUFkbWluUGFzc3dvcmRcIiBjbGFzcz1cImZvcm0tbGFiZWxcIj5Db25maXJtIHBhc3N3b3JkIDxpIGNsYXNzPVwiZmFzIGZhLXF1ZXN0aW9uLWNpcmNsZSB0ZXh0LW11dGVkIGhlbHBcIiB0aXRsZT1cIlNtYXJ0Rm94U2VydmVyIDJYIHJlbW90ZSBhZG1pbmlzdHJhdGlvbiBwYXNzd29yZCBjb25maXJtYXRpb25cIj48L2k+PC9sYWJlbD5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiaW5uZXItd2lkZ2V0XCI+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ8aW5wdXQgdHlwZT1cInBhc3N3b3JkXCIgaWQ9XCJjb25maXJtQWRtaW5QYXNzd29yZFwiIG5hbWU9XCJjb25maXJtQWRtaW5QYXNzd29yZFwiIGNsYXNzPVwiZm9ybS1jb250cm9sIGstdGV4dGJveFwiIGF1dG9jb21wbGV0ZT1cIm9mZlwiIHJlcXVpcmVkIGRhdGEtcmVxdWlyZWQtbXNnPVwiUmVxdWlyZWRcIiAvPlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0PHNwYW4gY2xhc3M9XCJrLWludmFsaWQtbXNnIHBvc2l0aW9uLXN0YXRpY1wiIGRhdGEtZm9yPVwiY29uZmlybUFkbWluUGFzc3dvcmRcIj48L3NwYW4+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHRcdDwvZmllbGRzZXQ+XG5cdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJtb2RhbC1mb290ZXIgZmxleC1jb2x1bW5cIj5cblx0XHRcdFx0XHRcdFx0PGRpdiBjbGFzcz1cImQtZmxleCB3LTEwMFwiPlxuXHRcdFx0XHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJmbGV4LWdyb3ctMSB0ZXh0LWxlZnRcIj5cblx0XHRcdFx0XHRcdFx0XHRcdDxidXR0b24gaWQ9XCJ1cGxvYWRTc2xCdXR0b25cIiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJrLWJ1dHRvbiBrLXByaW1hcnlcIj48aSBjbGFzcz1cImZhcyBmYS11cGxvYWQgbXItMVwiPjwvaT5VcGxvYWQgY2VydGlmaWNhdGU8L2J1dHRvbj5cblx0XHRcdFx0XHRcdFx0XHRcdDxpIGlkPVwidXBsb2FkU3Bpbm5lclwiIGNsYXNzPVwiZmFzIGZhLWNpcmNsZS1ub3RjaCBmYS1zcGluIHRleHQtcHJpbWFyeSBhbGlnbi1taWRkbGUgbWwtMVwiPjwvaT5cblx0XHRcdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiZmxleC1ncm93LTEgdGV4dC1yaWdodFwiPlxuXHRcdFx0XHRcdFx0XHRcdFx0PGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJrLWJ1dHRvbiBrLXNlY29uZGFyeVwiIGRhdGEtZGlzbWlzcz1cIm1vZGFsXCI+Q2FuY2VsPC9idXR0b24+XG5cdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdFx0XHQ8ZGl2IGlkPVwidXBsb2FkRXJyb3JNc2dcIiBjbGFzcz1cInRleHQtZGFuZ2VyIG10LTNcIj48L2Rpdj5cblx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdDwvZGl2PlxuXHRcdGA7XG5cblx0XHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRcdCQodGhpcykuYXBwZW5kKGBcblx0XHRcdDxkaXYgY2xhc3M9XCJjb2wtc20tNSBjb2wtbGctNCBjb2wtZm9ybS1sYWJlbCBmb3JtLWxhYmVsLWNvbnRhaW5lclwiPlxuXHRcdFx0XHQ8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsXCI+VXBsb2FkIGNlcnRpZmljYXRlIDxpIGNsYXNzPVwiZmFzIGZhLXF1ZXN0aW9uLWNpcmNsZSB0ZXh0LW11dGVkIGhlbHBcIiB0aXRsZT1cIlVwbG9hZCBhbiBTU0wgY2VydGlmaWNhdGUncyBwcm90ZWN0ZWQga2V5c3RvcmUgdG8gdGhlIHNlcnZlclwiPjwvaT48L2xhYmVsPlxuXHRcdFx0PC9kaXY+XG5cdFx0XHQ8ZGl2IGNsYXNzPVwiaW5uZXItd2lkZ2V0IGFsaWduLXNlbGYtY2VudGVyIGFsaWduLXNlbGYtc20tc3RhcnQgY29sLWF1dG9cIj5cblx0XHRcdFx0PGJ1dHRvbiBpZD1cIm1hbmFnZVNzbEJ1dHRvblwiIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImstYnV0dG9uIGstcHJpbWFyeVwiIGRpc2FibGVkPjxpIGNsYXNzPVwiZmFzIGZhLWNvZyBtci0xXCI+PC9pPk1hbmFnZTwvYnV0dG9uPlxuXHRcdFx0PC9kaXY+XG5cdFx0YCk7XG5cblx0XHQvLyBBZGQgbGlzdGVuZXJzIHRvIE1hbmFnZSBidXR0b24gY2xpY2tcblx0XHQkKCcjbWFuYWdlU3NsQnV0dG9uJywgJCh0aGlzKSkub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vbk1hbmFnZVNzbENsaWNrLCB0aGlzKSk7XG5cdH1cblxuXHRkZXN0cm95KClcblx0e1xuXHRcdC8vIFJlbW92ZSBldmVudCBsaXN0ZW5lclxuXHRcdCQoJyNtYW5hZ2VTc2xCdXR0b24nLCAkKHRoaXMpKS5vZmYoJ2NsaWNrJyk7XG5cblx0XHQvLyBIaWRlIG1vZGFsICh3aGljaCBpbiB0dXJuIGRlc3Ryb3lzIGl0KVxuXHRcdGxldCBtb2RhbEVsZW1lbnQgPSAkKCcjdXBsb2FkTW9kYWwnLCAkKHRoaXMpKTtcblxuXHRcdGlmIChtb2RhbEVsZW1lbnQpXG5cdFx0XHRtb2RhbEVsZW1lbnQubW9kYWwoJ2hpZGUnKTtcblx0fVxuXG5cdGdldCBlbmFibGVkKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9pc0VuYWJsZWQ7XG5cdH1cblxuXHRzZXQgZW5hYmxlZCh2YWx1ZSlcblx0e1xuXHRcdHRoaXMuX2lzRW5hYmxlZCA9IHZhbHVlO1xuXG5cdFx0Ly8gRW5hYmxlL2Rpc2FibGUgTWFuYWdlIGJ1dHRvblxuXHRcdCQoJyNtYW5hZ2VTc2xCdXR0b24nLCAkKHRoaXMpKS5hdHRyKCdkaXNhYmxlZCcsICF2YWx1ZSk7XG5cblx0XHQvLyBFbmFibGUvZGlzYWJsZSBtb2RhbFxuXHRcdGxldCBtb2RhbEVsZW1lbnQgPSAkKCcjdXBsb2FkTW9kYWwnLCAkKHRoaXMpKTtcblxuXHRcdGlmIChtb2RhbEVsZW1lbnQpXG5cdFx0e1xuXHRcdFx0Ly8gRGlzYWJsZSBtb2RhbCBjbG9zZSBidXR0b25zXG5cdFx0XHQkKCdidXR0b25bZGF0YS1kaXNtaXNzPVwibW9kYWxcIl0nLCBtb2RhbEVsZW1lbnQpLmF0dHIoJ2Rpc2FibGVkJywgIXZhbHVlKTtcblxuXHRcdFx0Ly8gRGlzYWJsZSB1cGxvYWQgYnV0dG9uXG5cdFx0XHQkKCcjdXBsb2FkU3NsQnV0dG9uJywgbW9kYWxFbGVtZW50KS5hdHRyKCdkaXNhYmxlZCcsICF2YWx1ZSk7XG5cblx0XHRcdC8vIERpc2FibGUgZmllbGRzZXRcblx0XHRcdCQoJyN1cGxvYWRGaWVsZHNldCcsIG1vZGFsRWxlbWVudCkuYXR0cignZGlzYWJsZWQnLCAhdmFsdWUpO1xuXHRcdH1cblx0fVxuXG5cdGdldCB1cGxvYWRUYXJnZXRDb25maWcoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3VwbG9hZFRhcmdldENvbmZpZztcblx0fVxuXG5cdHNldCB1cGxvYWRUYXJnZXRDb25maWcoZGF0YSlcblx0e1xuXHRcdHRoaXMuX3VwbG9hZFRhcmdldENvbmZpZyA9IGRhdGE7XG5cdH1cblxuXHRfb25NYW5hZ2VTc2xDbGljaygpXG5cdHtcblx0XHQvLyBJbml0aWFsaXplIGFuZCBzaG93IG1vZGFsXG5cdFx0dGhpcy5fc2hvd01vZGFsKCk7XG5cdH1cblxuXHRfb25VcGxvYWRTc2xDbGljaygpXG5cdHtcblx0XHRpZiAodGhpcy5fdmFsaWRhdGUoKSlcblx0XHRcdHRoaXMuX3N0YXJ0U3NsQ2VydFVwbG9hZCgpO1xuXHR9XG5cblx0X3Nob3dNb2RhbCgpXG5cdHtcblx0XHQvLyBBcHBlbmQgbW9kYWwgaHRtbFxuXHRcdCQodGhpcykuYXBwZW5kKHRoaXMuX21vZGFsSHRtbCk7XG5cblx0XHRsZXQgbW9kYWxFbGVtZW50ID0gJCgnI3VwbG9hZE1vZGFsJywgJCh0aGlzKSk7XG5cblx0XHQvLyBIaWRlIFNTTCBjZXJ0aWZpY2F0ZSB1cGxvYWQgc3Bpbm5lciBhbmQgZXJyb3IgbWVzc2FnZSBjb250YWluZXJcblx0XHQkKCcjdXBsb2FkU3Bpbm5lcicsIG1vZGFsRWxlbWVudCkuaGlkZSgpO1xuXHRcdCQoJyN1cGxvYWRFcnJvck1zZycsIG1vZGFsRWxlbWVudCkuaGlkZSgpO1xuXHRcdCQoJyN1cGxvYWRFcnJvck1zZycsIG1vZGFsRWxlbWVudCkudGV4dCgnJyk7XG5cblx0XHQvLyBBZGQgbGlzdGVuZXIgdG8gVXBsb2FkIGJ1dHRvbiBjbGlja1xuXHRcdCQoJyN1cGxvYWRTc2xCdXR0b24nLCBtb2RhbEVsZW1lbnQpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25VcGxvYWRTc2xDbGljaywgdGhpcykpO1xuXG5cdFx0Ly8gQWRkIGxpc3RlbmVyIHRvIG1vZGFsIGhpZGUgZXZlbnRcblx0XHRtb2RhbEVsZW1lbnQub24oJ2hpZGRlbi5icy5tb2RhbCcsICQucHJveHkodGhpcy5fZGVzdHJveU1vZGFsLCB0aGlzKSk7XG5cblx0XHQvLyBJbml0aWFsaXplIGtlbmRvIHVwbG9hZGVyXG5cdFx0dGhpcy5fdXBsb2FkV2lkZ2V0ID0gbW9kYWxFbGVtZW50LmZpbmQoJyN1cGxvYWRlcicpLmtlbmRvVXBsb2FkKHtcblx0XHRcdGFsbG93ZWRFeHRlbnNpb25zOiBbJy5qa3MnXSxcblx0XHRcdG11bHRpcGxlOiBmYWxzZSxcblx0XHRcdHRlbXBsYXRlOiBmdW5jdGlvbihkYXRhSXRlbSkge1xuXHRcdFx0XHRkYXRhSXRlbS5ieXRlc1RvU2l6ZSA9IGJ5dGVzVG9TaXplOyAvLyBQYXNzIGJ5dGVzVG9TaXplIHV0aWxpdHkgZnVuY3Rpb24gdG8gdGVtcGxhdGVcblx0XHRcdFx0cmV0dXJuIGtlbmRvLnRlbXBsYXRlKGBcblx0XHRcdFx0XHQ8c3BhbiBjbGFzcz0nay1wcm9ncmVzcyB3LTEwMCc+PC9zcGFuPlxuXHRcdFx0XHRcdDxzcGFuIGNsYXNzPVwiXCI+XG5cdFx0XHRcdFx0XHQ8c3BhbiBjbGFzcz1cImstZmlsZS1uYW1lXCIgdGl0bGU9XCIjPW5hbWUjXCI+Iz1uYW1lIzwvc3Bhbj5cblx0XHRcdFx0XHRcdDxzcGFuIGNsYXNzPVwiay1maWxlLXNpemVcIj5TaXplOiAjPWJ5dGVzVG9TaXplKHNpemUsIDEsICdCeXRlcycpIzwvc3Bhbj5cblx0XHRcdFx0XHQ8L3NwYW4+XG5cdFx0XHRcdGApKGRhdGFJdGVtKTtcblx0XHRcdH0sXG5cdCAgICAgICAgbG9jYWxpemF0aW9uOiB7XG5cdCAgICAgICAgICAgIHNlbGVjdDogJ1NlbGVjdCBmaWxlLi4uJ1xuXHQgICAgICAgIH1cbiAgICAgICAgfSkuZGF0YSgna2VuZG9VcGxvYWQnKTtcblxuXHRcdC8vIEluaXRpYWxpemUga2VuZG8gdmFsaWRhdGlvbiBvbiB1cGxvYWRlciBzdWJmb3JtXG5cdFx0Ly8gTk9URTogd2UgdXNlIHNlcGFyYXRlIHZhbGlkYXRvcnMgdG8gYmUgYWJsZSB0byBkaXNhYmxlICd2YWxpZGF0ZU9uQmx1cicgb24gdGhlIHVwbG9hZGVyLFxuXHRcdC8vIGJlY2F1c2UgaXQgY2F1c2VzIHRoZSBlcnJvciBtZXNzYWdlIHRvIGFwcGVhciBhcyBzb29uIGFzIHRoZSBcIlNlbGVjdCBmaWxlXCIgYnV0dG9uIGlzIGNsaWNrZWRcblx0XHR0aGlzLl92YWxpZGF0b3IxID0gbW9kYWxFbGVtZW50LmZpbmQoJyN1cGxvYWRlclN1YmZvcm0nKS5rZW5kb1ZhbGlkYXRvcih7XG5cdFx0XHR2YWxpZGF0ZU9uQmx1cjogZmFsc2UsXG5cdFx0XHRydWxlczoge1xuXHRcdFx0XHR1cGxvYWQ6IGZ1bmN0aW9uKGlucHV0KSB7XG5cdFx0XHRcdFx0bGV0IHZhbGlkID0gZmFsc2U7XG5cdFx0XHRcdFx0aWYgKGlucHV0LmlzKCdbdHlwZT1maWxlXScpKVxuXHRcdFx0XHRcdFx0dmFsaWQgPSBpbnB1dC5jbG9zZXN0KCcuay11cGxvYWQnKS5maW5kKCcuay1maWxlJykubGVuZ3RoID4gMDtcblxuXHRcdFx0XHRcdHJldHVybiB2YWxpZDtcblx0ICAgICAgICAgICAgfVxuXHRcdFx0fVxuXHRcdH0pLmRhdGEoJ2tlbmRvVmFsaWRhdG9yJyk7XG5cblx0XHQvLyBJbml0aWFsaXplIGtlbmRvIHZhbGlkYXRpb24gb24gcGFzc3dvcmRzIHN1YmZvcm1cblx0XHR0aGlzLl92YWxpZGF0b3IyID0gbW9kYWxFbGVtZW50LmZpbmQoJyNwYXNzd29yZHNTdWJmb3JtJykua2VuZG9WYWxpZGF0b3Ioe1xuXHRcdFx0dmFsaWRhdGVPbkJsdXI6IHRydWUsXG5cdFx0XHRydWxlczoge1xuXHRcdFx0XHR2ZXJpZnlLc1Bhc3N3b3JkOiAkLnByb3h5KGZ1bmN0aW9uKGlucHV0KSB7XG5cdFx0XHRcdFx0bGV0IHZhbGlkID0gdHJ1ZTtcblx0XHRcdFx0XHRpZiAoaW5wdXQuaXMoJ1tuYW1lPWNvbmZpcm1Lc1Bhc3N3b3JkXScpKVxuXHRcdFx0XHRcdFx0dmFsaWQgPSBpbnB1dC52YWwoKSA9PT0gJCh0aGlzKS5maW5kKCcja3NQYXNzd29yZCcpLnZhbCgpO1xuXHRcdFx0XHRcdHJldHVybiB2YWxpZDtcblx0XHRcdFx0fSwgdGhpcyksXG5cdFx0XHRcdHZlcmlmeUFkbVBhc3N3b3JkOiAkLnByb3h5KGZ1bmN0aW9uKGlucHV0KSB7XG5cdFx0XHRcdFx0bGV0IHZhbGlkID0gdHJ1ZTtcblx0XHRcdFx0XHRpZiAoaW5wdXQuaXMoJ1tuYW1lPWNvbmZpcm1BZG1pblBhc3N3b3JkXScpKVxuXHRcdFx0XHRcdFx0dmFsaWQgPSBpbnB1dC52YWwoKSA9PT0gJCh0aGlzKS5maW5kKCcjYWRtaW5QYXNzd29yZCcpLnZhbCgpO1xuXHRcdFx0XHRcdHJldHVybiB2YWxpZDtcblx0XHRcdFx0fSwgdGhpcylcblx0XHRcdH0sXG5cdFx0XHRtZXNzYWdlczoge1xuXHRcdFx0XHR2ZXJpZnlLc1Bhc3N3b3JkOiAnUGFzc3dvcmQgbm90IG1hdGNoaW5nJyxcblx0XHRcdFx0dmVyaWZ5QWRtUGFzc3dvcmQ6ICdQYXNzd29yZCBub3QgbWF0Y2hpbmcnLFxuXHRcdFx0fVxuXHRcdH0pLmRhdGEoJ2tlbmRvVmFsaWRhdG9yJyk7XG5cblx0XHQvLyBJbml0aWFsaXplIGJvb3RzdHJhcCBtb2RhbFxuXHRcdG1vZGFsRWxlbWVudC5tb2RhbCh7XG5cdFx0XHRiYWNrZHJvcDogJ3N0YXRpYycsXG5cdFx0XHRrZXlib2FyZDogZmFsc2UsXG5cdFx0fSk7XG5cdH1cblxuXHRfZGVzdHJveU1vZGFsKClcblx0e1xuXHRcdGxldCBtb2RhbEVsZW1lbnQgPSAkKCcjdXBsb2FkTW9kYWwnLCAkKHRoaXMpKTtcblxuXHRcdGlmIChtb2RhbEVsZW1lbnQpXG5cdFx0e1xuXHRcdFx0Ly8gUmVtb3ZlIGxpc3RlbmVyc1xuXHRcdFx0JCgnI3VwbG9hZFNzbEJ1dHRvbicsIG1vZGFsRWxlbWVudCkub2ZmKCdjbGljaycpO1xuXHRcdFx0bW9kYWxFbGVtZW50Lm9mZignaGlkZGVuLmJzLm1vZGFsJyk7XG5cblx0XHRcdC8vIERlc3Ryb3kgZXZlcnl0aGluZyBLZW5kb1xuXHRcdFx0a2VuZG8uZGVzdHJveShtb2RhbEVsZW1lbnQpO1xuXG5cdFx0XHQvLyBEaXNwb3NlIG1vZGFsXG5cdFx0XHRtb2RhbEVsZW1lbnQubW9kYWwoJ2Rpc3Bvc2UnKTtcblxuXHRcdFx0Ly8gUmVtb3ZlIGh0bWxcblx0XHRcdG1vZGFsRWxlbWVudC5yZW1vdmUoKTtcblx0XHRcdG1vZGFsRWxlbWVudCA9IG51bGw7XG5cdFx0fVxuXHR9XG5cblx0X3ZhbGlkYXRlKClcblx0e1xuXHRcdGxldCB2YWwxID0gdGhpcy5fdmFsaWRhdG9yMS52YWxpZGF0ZSgpO1xuXHRcdGxldCB2YWwyID0gdGhpcy5fdmFsaWRhdG9yMi52YWxpZGF0ZSgpO1xuXG5cdFx0cmV0dXJuIHZhbDEgJiYgdmFsMjtcblx0fVxuXG5cdF9zdGFydFNzbENlcnRVcGxvYWQoKVxuXHR7XG5cdFx0aWYgKCF0aGlzLl91cGxvYWRUYXJnZXRDb25maWcpXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1VwbG9hZCB0YXJnZXQgY29uZmlndXJhdGlvbiBub3Qgc2V0Jyk7XG5cblx0XHRsZXQgbW9kYWxFbGVtZW50ID0gJCgnI3VwbG9hZE1vZGFsJywgJCh0aGlzKSk7XG5cblx0XHRpZiAobW9kYWxFbGVtZW50KVxuXHRcdHtcblx0XHRcdGxldCBjZXJ0RGF0YSA9IHt9O1xuXHRcdFx0Y2VydERhdGEuZmlsZSA9IHRoaXMuX3VwbG9hZFdpZGdldC5nZXRGaWxlcygpWzBdO1xuXHRcdFx0Y2VydERhdGEua3NQYXNzd29yZCA9ICQoJyNrc1Bhc3N3b3JkJywgbW9kYWxFbGVtZW50KS52YWwoKTtcblx0XHRcdGNlcnREYXRhLmFkbWluUGFzc3dvcmQgPSAkKCcjYWRtaW5QYXNzd29yZCcsIG1vZGFsRWxlbWVudCkudmFsKCk7XG5cblx0XHRcdC8vIERpc2FibGUgbW9kYWxcblx0XHRcdHRoaXMuZW5hYmxlZCA9IGZhbHNlO1xuXG5cdFx0XHQvLyBIaWRlIHByZXZpb3VzIGVycm9yIGFuZCBzaG93IHNwaW5uZXJcblx0XHRcdCQoJyN1cGxvYWRTcGlubmVyJywgbW9kYWxFbGVtZW50KS5zaG93KCk7XG5cdFx0XHQkKCcjdXBsb2FkRXJyb3JNc2cnLCBtb2RhbEVsZW1lbnQpLmhpZGUoKTtcblx0XHRcdCQoJyN1cGxvYWRFcnJvck1zZycsIG1vZGFsRWxlbWVudCkudGV4dCgnJyk7XG5cblx0XHRcdC8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuXHRcdFx0Ly8gR2VuZXJhdGUgSW5pdCBWZWN0b3Jcblx0XHRcdGxldCBybmdWYWx1ZXMgPSBbXTtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgMTY7IGkrKylcblx0XHRcdFx0cm5nVmFsdWVzLnB1c2goTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMjU2KSk7XG5cblx0XHRcdGxldCBpdiA9IG5ldyBVaW50OEFycmF5KHJuZ1ZhbHVlcyk7XG5cblx0XHRcdC8vIEdlbmVyYXRlIHNlY3JldCBrZXkgYnkgTUQ1LWVuY29kaW5nIGFkbWluIHBhc3N3b3JkICsgc2Vzc2lvbiB0b2tlblxuXHRcdFx0bGV0IG1kNVBhc3MgPSB0aGlzLl9iaW5hcnlNRDUoY2VydERhdGEuYWRtaW5QYXNzd29yZCArIHRoaXMuX3VwbG9hZFRhcmdldENvbmZpZy5zZXNzaW9uVG9rZW4pO1xuXG5cdFx0XHQvLyBFbmNyeXB0IGtleXN0b3JlIHBhc3N3b3JkIHZpYSBBRVMgKDEyOGJpdClcblx0XHRcdGxldCBlbmNyeXB0ZWRQd2QgPSB0aGlzLl9hZXNFbmNyeXB0KGNlcnREYXRhLmtzUGFzc3dvcmQsIG1kNVBhc3MsIGl2KTtcblxuXHRcdFx0Ly8gRW5jb2RlIElWIHVzaW5nIEJhc2U2NFxuXHRcdFx0bGV0IGVuY29kZWRJdiA9IHRoaXMuX2I2NEVuY29kZShpdik7XG5cblx0XHRcdC8vIEVuY29kZSBlbmNyeXB0ZWQgcGFzc3dvcmQgdXNpbmcgQmFzZTY0XG5cdFx0XHRsZXQgZW5jb2RlZFB3ZCA9IHRoaXMuX2I2NEVuY29kZShlbmNyeXB0ZWRQd2QpO1xuXG5cdFx0XHQvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cblx0XHRcdC8vIFNldCBwYXJhbWV0ZXJzIHRvIGJlIHNlbnQgd2l0aCB0aGUgY2VydGlmaWNhdGUga2V5c3RvcmUgZmlsZVxuXHRcdFx0Y29uc3QgcGFyYW1zID0gbmV3IEZvcm1EYXRhKCk7XG5cdFx0XHRwYXJhbXMuYXBwZW5kKCdmaWxlc1tdJywgY2VydERhdGEuZmlsZS5yYXdGaWxlKTtcblx0XHRcdHBhcmFtcy5hcHBlbmQoJ19faXYnLCBlbmNvZGVkSXYpO1xuXHRcdFx0cGFyYW1zLmFwcGVuZCgnX19wYXNzd29yZCcsIGVuY29kZWRQd2QpO1xuXHRcdFx0cGFyYW1zLmFwcGVuZCgnX19tb2R1bGUnLCB0aGlzLl91cGxvYWRUYXJnZXRDb25maWcubW9kdWxlSWQpO1xuXG5cdFx0XHQvLyBTZXQgZGVzdGluYXRpb24gdXJsXG5cdFx0XHRjb25zdCB1cmwgPSB0aGlzLl91cGxvYWRUYXJnZXRDb25maWcucHJvdG9jb2wgKyAnOi8vJyArIHRoaXMuX3VwbG9hZFRhcmdldENvbmZpZy5ob3N0ICsgJzonICsgdGhpcy5fdXBsb2FkVGFyZ2V0Q29uZmlnLnBvcnQgKyAnL0JsdWVCb3gvU0ZTMlhGaWxlVXBsb2FkP3Nlc3NIYXNoSWQ9JyArIHRoaXMuX3VwbG9hZFRhcmdldENvbmZpZy5zZXNzaW9uVG9rZW47XG5cblx0XHRcdC8vIFN0YXJ0IHVwbG9hZFxuXHRcdFx0ZmV0Y2godXJsLCB7XG5cdFx0XHRcdG1ldGhvZDogJ1BPU1QnLFxuXHRcdFx0XHRib2R5OiBwYXJhbXMsXG5cdFx0XHRcdG1vZGU6ICduby1jb3JzJ1xuXHRcdFx0fSkudGhlbigkLnByb3h5KHRoaXMuX29uU3NsQ2VydFVwbG9hZEVuZCwgdGhpcykpO1xuXHRcdH1cblx0fVxuXG5cdF9vblNzbENlcnRVcGxvYWRFbmQocmVzcG9uc2UpXG5cdHtcblx0XHQvLyBOb3RoaW5nIHRvIGRvOiB3ZSBoYXZlIHRvIHdhaXQgdGhlIHVwbG9hZCBwcm9jZXNzIGNvbXBsZXRpb24gdG8gYmUgc2lnbmFsZWQgYnkgdGhlIHNlcnZlciB0aHJvdWdoIHRoZSBkZWRpY2F0ZWQgRXh0ZW5zaW9uIHJlc3BvbnNlXG5cblx0XHQvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cblx0XHQvLyBUT0RPIFNob3VsZCB3ZSBoYW5kbGUgdGhpcyByZXNwb25zZSBpbiBzb21lIHdheT8gRm9yIHNvbWUgdW5rbm93biByZWFzb24gd2UgYWx3YXlzIGdldCBvaz1mYWxzZSBhbmQgc3RhdHVzPTBcblx0XHQvL2NvbnNvbGUubG9nKHJlc3BvbnNlKVxuXHRcdC8vY29uc29sZS5sb2cocmVzcG9uc2Uub2spXG5cdFx0Ly9jb25zb2xlLmxvZyhyZXNwb25zZS5zdGF0dXMpXG5cdH1cblxuXHQvKipcblx0ICogTWV0aG9kIGNhbGxlZCBieSBwYXJlbnQgd2hlbiB1cGxvYWQgZmFpbGVkLlxuXHQgKi9cblx0b25Tc2xDZXJ0VXBsb2FkRXJyb3IoZXJyb3IpXG5cdHtcblx0XHRsZXQgbW9kYWxFbGVtZW50ID0gJCgnI3VwbG9hZE1vZGFsJywgJCh0aGlzKSk7XG5cblx0XHRpZiAobW9kYWxFbGVtZW50KVxuXHRcdHtcblx0XHRcdC8vIEVuYWJsZSBtb2RhbFxuXHRcdFx0dGhpcy5lbmFibGVkID0gdHJ1ZTtcblxuXHRcdFx0Ly8gU2hvdyB1cGxvYWQgZXJyb3Jcblx0XHRcdCQoJyN1cGxvYWRFcnJvck1zZycsIG1vZGFsRWxlbWVudCkuc2hvdygpO1xuXHRcdFx0JCgnI3VwbG9hZEVycm9yTXNnJywgbW9kYWxFbGVtZW50KS50ZXh0KGVycm9yICsgJy4nKTtcblxuXHRcdFx0Ly8gSGlkZSBzcGlubmVyXG5cdFx0XHQkKCcjdXBsb2FkU3Bpbm5lcicsIG1vZGFsRWxlbWVudCkuaGlkZSgpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBNZXRob2QgY2FsbGVkIGJ5IHBhcmVudCB3aGVuIHVwbG9hZCBpcyBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5LlxuXHQgKi9cblx0b25Tc2xDZXJ0VXBsb2FkU3VjY2VzcygpXG5cdHtcblx0XHRsZXQgbW9kYWxFbGVtZW50ID0gJCgnI3VwbG9hZE1vZGFsJywgJCh0aGlzKSk7XG5cblx0XHRpZiAobW9kYWxFbGVtZW50KVxuXHRcdHtcblx0XHRcdC8vIEVuYWJsZSBtb2RhbFxuXHRcdFx0dGhpcy5lbmFibGVkID0gdHJ1ZTtcblxuXHRcdFx0Ly8gSGlkZSBzcGlubmVyXG5cdFx0XHQkKCcjdXBsb2FkU3Bpbm5lcicsIG1vZGFsRWxlbWVudCkuaGlkZSgpO1xuXG5cdFx0XHQvLyBIaWRlIG1vZGFsXG5cdFx0XHRtb2RhbEVsZW1lbnQubW9kYWwoJ2hpZGUnKTtcblx0XHR9XG5cdH1cblxuXHQvLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuXG5cdC8qXG5cdCAqIFRha2VzIGEgc3RyaW5nIGFuZCByZXR1cm5zIHRoZSBNRDUgYXMgVWludDhBcnJheVxuXHQgKi9cblx0X2JpbmFyeU1ENShzdHIpXG5cdHtcblx0XHRsZXQgTUQ1ID0gbmV3IFNGUzJYLk1ENSgpO1xuXHRcdGxldCBoZXhTdHIgPSBNRDUuaGV4X21kNShzdHIpO1xuXG5cdFx0cmV0dXJuIHRoaXMuX2hleEJ5dGVTdHJpbmdUb0J5dGVBcnJheShoZXhTdHIpO1xuXHR9XG5cblx0Lypcblx0ICogSGV4IGJ5dGVzIC0tLT4gQWN0dWFsIGJ5dGVbXSBhcyBVaW50OEFycmF5XG5cdCAqL1xuXHRfaGV4Qnl0ZVN0cmluZ1RvQnl0ZUFycmF5KGhleEJ5dGVTdHJpbmcpXG5cdHtcblx0ICAgIGxldCBieXRlcyA9IG5ldyBVaW50OEFycmF5KDE2KTsgLy8gTUQ1IGZpeGVkIG91dHB1dCBzaXplXG5cblx0ICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaGV4Qnl0ZVN0cmluZy5sZW5ndGg7KVxuXHQgICAge1xuXHQgICAgICAgIGxldCBoZXhCeXRlID0gaGV4Qnl0ZVN0cmluZ1tpKytdICsgaGV4Qnl0ZVN0cmluZ1tpKytdO1xuXHQgICAgICAgIGxldCBieXRlID0gcGFyc2VJbnQoaGV4Qnl0ZSwgMTYpO1xuXG5cdCAgICAgICAgYnl0ZXNbaSAvIDIgLSAxXSA9IGJ5dGU7XG5cdCAgICB9XG5cblx0ICAgIHJldHVybiBieXRlcztcblx0fVxuXG5cdC8qXG5cdCAqIEVuY3J5cHQgdXNpbmcgQUVTLCBtb2RlIENCQywgUEtDUyM3IHBhZGRpbmdcblx0ICpcblx0ICogdGV4dCBcdFx0LT4gdGhlIHRleHQgd2Ugd2FudCB0byBlbmNvZGVcblx0ICoga2V5IFx0XHQtPiB0aGUgQUVTIGtleVxuXHQgKiBpdiAgXHRcdC0+IHRoZSBBRVMvQ0JDIGluaXQgdmVjdG9yXG5cdCAqXG5cdCAqIFJldHVybnMgXHQtPiBVaW50OEFycmF5XG5cdCAqL1xuXHRfYWVzRW5jcnlwdCh0ZXh0LCBrZXksIGl2KVxuXHR7XG5cdFx0bGV0IHRleHRCeXRlcyA9IGFlc2pzLnV0aWxzLnV0ZjgudG9CeXRlcyh0ZXh0KTsgXHRcdC8vIEdldCBVVEYtOCBieXRlc1xuXHRcdGxldCBhZXNDQkMgPSBuZXcgYWVzanMuTW9kZU9mT3BlcmF0aW9uLmNiYyhrZXksIGl2KTtcdC8vIEluaXQgQ0JDIG1vZGVcblx0XHR0ZXh0Qnl0ZXMgPSBhZXNqcy5wYWRkaW5nLnBrY3M3LnBhZCh0ZXh0Qnl0ZXMpOyBcdFx0Ly8gUEtDUyM3IHBhZGRpbmdcblxuXHRcdC8vIEVuY3J5cHRcblx0XHRyZXR1cm4gYWVzQ0JDLmVuY3J5cHQodGV4dEJ5dGVzKTtcblx0fVxuXG5cdC8qXG5cdCAqIEVuY29kZSBwYXNzZWQgYnl0ZSBhcnJheSAtLT4gQmFzZTY0IHJlcHJlc2VudGF0aW9uXG5cdCAqIFJldHVybnMgLS0+IHN0cmluZ1xuXHQgKi9cblx0X2I2NEVuY29kZShiYXJyYXkpXG5cdHtcblx0XHRyZXR1cm4gYnRvYShTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIGJhcnJheSkpO1xuXHR9XG59XG5cbi8vIERFRklORSBDT01QT05FTlRcbmlmICghd2luZG93LmN1c3RvbUVsZW1lbnRzLmdldCgnc3NsLWNlcnRpZmljYXRlLW1hbmFnZXInKSlcblx0d2luZG93LmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnc3NsLWNlcnRpZmljYXRlLW1hbmFnZXInLCBTc2xDZXJ0aWZpY2F0ZU1hbmFnZXIpO1xuIiwiaW1wb3J0IHtCYXNlTW9kdWxlfSBmcm9tICcuL2Jhc2UtbW9kdWxlJztcbmltcG9ydCB7Q29uZmlnSW50ZXJmYWNlQnVpbGRlcn0gZnJvbSAnLi4vdXRpbHMvdWlidWlsZGVyL2NvbmZpZy1pbnRlcmZhY2UtYnVpbGRlcic7XG5pbXBvcnQge1NzbENlcnRpZmljYXRlTWFuYWdlcn0gZnJvbSAnLi4vY29tcG9uZW50cy9tb2R1bGUtc3BlY2lmaWMvc3NsLWNlcnRpZmljYXRlLW1hbmFnZXInO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTZXJ2ZXJDb25maWd1cmF0b3IgZXh0ZW5kcyBCYXNlTW9kdWxlXG57XG5cdGNvbnN0cnVjdG9yKClcblx0e1xuXHQgICAgc3VwZXIoJ3NlcnZlckNvbmZpZycpO1xuXG5cdFx0Ly8gT3V0Z29pbmcgcmVxdWVzdHNcblx0XHR0aGlzLlJFUV9JTklUID0gJ2luaXQnO1xuXHRcdHRoaXMuUkVRX0dFVF9DT05GSUcgPSAnZ2V0Q29uZmlnJztcblx0XHR0aGlzLlJFUV9VUERBVEVfQ09ORklHID0gJ3VwZENvbmZpZyc7XG5cdFx0dGhpcy5SRVFfVVBEQVRFX0dFT19EQiA9ICd1cGRHZW9EYic7XG5cblx0XHQvLyBJbmNvbWluZyByZXNwb25zZXNcblx0XHR0aGlzLlJFU1BfSU5JVCA9ICdpbml0Jztcblx0XHR0aGlzLlJFU1BfQ09ORklHID0gJ2NvbmZpZyc7XG5cdFx0dGhpcy5SRVNQX0NPTkZJR19VUERBVEVfQ09ORklSTSA9ICdjb25maWdVcGRhdGUnO1xuXHRcdHRoaXMuUkVTUF9DT05GSUdfQ0hBTkdFRF9BTEVSVCA9ICdjb25maWdBbGVydCc7XG5cdFx0dGhpcy5SRVNQX1NTTF9VUExPQURfRVJST1IgPSAnc3NsVXBsb2FkRXJyb3InO1xuXHRcdHRoaXMuUkVTUF9TU0xfVVBMT0FEX0NPTkZJUk0gPSAnc3NsVXBsb2FkJztcblx0XHR0aGlzLlJFU1BfVVBEQVRFX0dFT19EQiA9ICdnZW9EYlVwZGF0ZSc7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLyBDT01NT04gTU9EVUxFIElOVEVSRkFDRSBNRVRIT0RTXG5cdC8vIFRoaXMgbWVtYmVycyBhcmUgdXNlZCBieSB0aGUgbWFpbiBjb250cm9sbGVyXG5cdC8vIHRvIGNvbW11bmljYXRlIHdpdGggdGhlIG1vZHVsZSdzIGNvbnRyb2xsZXIuXG5cdC8vIFRoaXMgbWV0aG9kcyBvdmVycmlkZSB0aG9zZSBpbiBCYXNlTW9kdWxlIGNsYXNzLlxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdGluaXRpYWxpemUoaWREYXRhLCBzaGVsbENvbnRyb2xsZXIpXG5cdHtcblx0XHQvLyBDYWxsIHN1cGVyIG1ldGhvZFxuXHRcdHN1cGVyLmluaXRpYWxpemUoaWREYXRhLCBzaGVsbENvbnRyb2xsZXIpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBwcm9ncmVzcyBiYXJcblx0XHQkKCcjc3JjLXByb2dyZXNzQmFyJykua2VuZG9Qcm9ncmVzc0Jhcih7XG5cdFx0XHRtaW46IDAsXG4gICAgICAgICAgICBtYXg6IDEwMCxcblx0XHRcdHZhbHVlOiBmYWxzZSxcbiAgICAgICAgICAgIHR5cGU6ICd2YWx1ZScsXG4gICAgICAgICAgICBhbmltYXRpb246IHtcbiAgICAgICAgICAgICAgICBkdXJhdGlvbjogNDAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG5cdFx0Ly8gQ3JlYXRlIGludGVyZmFjZSBidWlsZGVyIGluc3RhbmNlXG5cdFx0dGhpcy5faW50ZXJmYWNlQnVpbGRlciA9IG5ldyBDb25maWdJbnRlcmZhY2VCdWlsZGVyKCk7XG5cblx0XHQvLyBBZGQgbGlzdGVuZXIgdG8gR2VvTGl0ZTIgZGF0YWJhc2UgdXBkYXRlIGJ1dHRvblxuXHRcdCQoJyNzcmMtdXBkYXRlR2VvbG9jRGJCdXR0b24nKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uVXBkYXRlR2VvbG9jRGJDbGljaywgdGhpcykpO1xuXG5cdFx0Ly8gQWRkIGxpc3RlbmVyIHRvIGludGVyZmFjZSBidXR0b25zXG5cdFx0JCgnI3NyYy1yZWxvYWRCdXR0b24nKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uUmVsb2FkQ2xpY2ssIHRoaXMpKTtcblx0XHQkKCcjc3JjLXN1Ym1pdEJ1dHRvbicpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25TdWJtaXRDbGljaywgdGhpcykpO1xuXG5cdFx0Ly8gU2F2ZSByZWYgdG8gU1NMIE1hbmFnZXJcblx0XHR0aGlzLl9zc2xDZXJ0TWFuYWdlciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzcmMtc3NsQ2VydE1hbmFnZXInKTtcblxuXHRcdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG5cdFx0Ly8gU2VuZCBpbml0aWFsaXphdGlvbiByZXF1ZXN0XG5cdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9JTklUKTtcblx0fVxuXG5cdGRlc3Ryb3koKVxuXHR7XG5cdFx0Ly8gQ2FsbCBzdXBlciBtZXRob2Rcblx0XHRzdXBlci5kZXN0cm95KCk7XG5cblx0XHQvLyBEZXN0cm95IFNTTCBDZXJ0aWZpY2F0ZSBNYW5hZ2VyXG5cdFx0dGhpcy5fc3NsQ2VydE1hbmFnZXIuZGVzdHJveSgpO1xuXG5cdFx0Ly8gUmVtb3ZlIGludGVyZmFjZSBidXR0b25zIGNsaWNrIGxpc3RlbmVyc1xuXHRcdCQoJyNzcmMtdXBkYXRlR2VvbG9jRGJCdXR0b24nKS5vZmYoJ2NsaWNrJyk7XG5cdFx0JCgnI3NyYy1yZWxvYWRCdXR0b24nKS5vZmYoJ2NsaWNrJyk7XG5cdFx0JCgnI3NyYy1zdWJtaXRCdXR0b24nKS5vZmYoJ2NsaWNrJyk7XG5cblx0XHQvLyBDbGVhciB0YWJzIGNvbnRhaW5lclxuXHRcdHRoaXMuX2NsZWFyVGFicygpO1xuXHR9XG5cblx0b25FeHRlbnNpb25Db21tYW5kKGNvbW1hbmQsIGRhdGEpXG5cdHtcblx0XHQvLyBJbml0aWFsaXphdGlvbiBkYXRhIHJlY2VpdmVkXG5cdFx0aWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0lOSVQpXG5cdFx0e1xuXHRcdFx0Ly8gUmV0cmlldmUgbW9kdWxlIGlkIHNlbnQgYnkgdGhlIHNlcnZlciAocmVxdWlyZWQgYmVjYXVzZSBtdWx0aXBsZSBtb2R1bGVzIHVzZSBmaWxlIHVwbG9hZGluZyBzZXJ2aWNlKVxuXHRcdFx0Y29uc3QgdXBsb2FkTW9kdWxlSWQgPSBkYXRhLmdldFV0ZlN0cmluZygnbW9kSWQnKTtcblxuXHRcdFx0Ly8gU2V0IFNTTCB1cGxvYWQgbWFuYWdlciB0YXJnZXQgY29uZmlndXJhdGlvblxuXHRcdFx0dGhpcy5fc3NsQ2VydE1hbmFnZXIudXBsb2FkVGFyZ2V0Q29uZmlnID0ge1xuXHRcdFx0XHRzZXNzaW9uVG9rZW46IHRoaXMuc21hcnRGb3guc2Vzc2lvblRva2VuLFxuXHRcdFx0XHRob3N0OiB0aGlzLnNtYXJ0Rm94LmNvbmZpZy5ob3N0LFxuXHRcdFx0XHRwb3J0OiB0aGlzLnNtYXJ0Rm94LmNvbmZpZy5wb3J0LFxuXHRcdFx0XHRtb2R1bGVJZDogdXBsb2FkTW9kdWxlSWQsXG5cdFx0XHRcdHByb3RvY29sOiB0aGlzLnNtYXJ0Rm94LmNvbmZpZy51c2VTU0wgPyAnaHR0cHMnIDogJ2h0dHAnXG5cdFx0XHR9O1xuXG5cdFx0XHQvLyBTZXJ2ZXIgc2VuZHMgYSBmbGFnIGluZGljYXRpbmcgaWYgZmlsZSB1cGxvYWRzIGFyZSBsb2NrZWRcblx0XHRcdC8vIFdlIHVzZSBpdCB0byBlbmFibGUgdGhlIFwiTWFuYWdlIFNTTCBjZXJ0aWZpY2F0ZVwiIGJ1dHRvblxuXHRcdFx0dGhpcy5fc3NsTG9ja2VkID0gZGF0YS5nZXRCb29sKCdsb2NrJyk7XG5cblx0XHRcdGlmICghdGhpcy5fc3NsTG9ja2VkKVxuXHRcdFx0XHQkKCcjc3JjLW1hbmFnZVNzbFdhcm4nKS5oaWRlKCk7XG5cblx0XHRcdC8vIFJlcXVlc3QgY29uZmlndXJhdGlvbiBkYXRhIHRvIHNlcnZlciBpbnN0YW5jZVxuXHRcdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9HRVRfQ09ORklHKTtcblx0XHR9XG5cblx0XHQvLyBTZXJ2ZXIgY29uZmlndXJhdGlvbiBkYXRhIHJlY2VpdmVkXG5cdFx0ZWxzZSBpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfQ09ORklHKVxuXHRcdHtcblx0XHRcdC8vIEJ1aWxkIHVzZXIgaW50ZXJmYWNlIGJhc2VkIG9uIHJlY2VpdmVkIGRhdGFcblx0XHRcdHRoaXMuX2ludGVyZmFjZUJ1aWxkZXIuYnVpbGRJbnRlcmZhY2UoZGF0YS5nZXRTRlNBcnJheSgnc2V0dGluZ3MnKSwgJ3NyYy10YWJOYXZpZ2F0b3InLCBmYWxzZSk7XG5cblx0XHRcdC8vIEVuYWJsZSBidXR0b25zXG5cdFx0XHR0aGlzLl9lbmFibGVCdXR0b25zKHRydWUpO1xuXG5cdFx0XHQvLyBJbml0aWFsaXplIFRhYk5hdmlnYXRvci1yYWxhdGVkIHdpZGdldHNcblx0XHRcdGlmICghdGhpcy5fdGFiTmF2SW5pdGlhbGl6ZWQpXG5cdFx0XHR7XG5cdFx0XHRcdC8vIEVuYWJsZSBzY3JvbGxpbmcgdGFic1xuXHRcdFx0XHQkKCcjc3JjLXRhYk5hdmlnYXRvciA+ICN0YWJzJykuc2Nyb2xsaW5nVGFicyh7XG5cdFx0XHRcdFx0Ym9vdHN0cmFwVmVyc2lvbjogNCxcblx0XHRcdFx0XHRzY3JvbGxUb1RhYkVkZ2U6IHRydWUsXG5cdFx0XHRcdFx0ZW5hYmxlU3dpcGluZzogdHJ1ZSxcblx0XHRcdFx0XHRkaXNhYmxlU2Nyb2xsQXJyb3dzT25GdWxseVNjcm9sbGVkOiB0cnVlLFxuXHRcdFx0XHRcdGNzc0NsYXNzTGVmdEFycm93OiAnZmEgZmEtY2hldnJvbi1sZWZ0Jyxcblx0XHRcdFx0XHRjc3NDbGFzc1JpZ2h0QXJyb3c6ICdmYSBmYS1jaGV2cm9uLXJpZ2h0J1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHR0aGlzLl90YWJOYXZJbml0aWFsaXplZCA9IHRydWU7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJ1biB2YWxpZGF0aW9uICh0byByZW1vdmUgdmFsaWRhdGlvbiBtZXNzYWdlcyBpZiBkYXRhIHdhcyByZWxvYWRlZClcblx0XHRcdHRoaXMuX2ludGVyZmFjZUJ1aWxkZXIuY2hlY2tJc1ZhbGlkKCk7XG5cblx0XHRcdHRoaXMuX3N3aXRjaFZpZXcoJ3NyYy1tYWluJyk7XG5cdFx0fVxuXG5cdFx0Ly8gU2VydmVyIGNvbmZpZ3VyYXRpb24gdXBkYXRlIGNvbmZpcm1hdGlvblxuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0NPTkZJR19VUERBVEVfQ09ORklSTSlcblx0XHR7XG5cdFx0XHQvLyBFbmFibGUgYnV0dG9uc1xuXHRcdFx0dGhpcy5fZW5hYmxlQnV0dG9ucyh0cnVlKTtcblxuXHRcdFx0Ly8gRW5hYmxlIGZvcm0gaXRlbXNcblx0XHRcdHRoaXMuX2ludGVyZmFjZUJ1aWxkZXIuZGlzYWJsZUludGVyZmFjZShmYWxzZSk7XG5cblx0XHRcdC8vIElmIHRoZSBjdXJyZW50IHVzZXIgaXMgdGhlIHVwZGF0ZXIsIHNob3cgYSBub3RpZmljYXRpb25cblx0XHRcdC8vIE90aGVyd2lzZSwgc2hvdyBhIGRpYWxvZyBib3ggc3VnZ2VzdGluZyB0byByZWxvYWRcblx0XHRcdGxldCB1cGRhdGVyID0gZGF0YS5nZXRVdGZTdHJpbmcoJ3VzZXInKTtcblxuXHRcdFx0aWYgKHVwZGF0ZXIgPT0gdGhpcy5zbWFydEZveC5teVNlbGYubmFtZSlcblx0XHRcdHtcblx0XHRcdFx0Ly8gUmVzZXQgdGhlICdtb2RpZmllZCcgZmxhZ1xuXHRcdFx0XHR0aGlzLl9pbnRlcmZhY2VCdWlsZGVyLnJlc2V0SXNNb2RpZmllZCgpO1xuXG5cdFx0XHRcdC8vIERpc3BsYXkgbm90aWZpY2F0aW9uXG5cdFx0XHRcdHRoaXMuc2hlbGxDdHJsLnNob3dOb3RpZmljYXRpb24oJ1NlcnZlciBzZXR0aW5ncyB1cGRhdGVkJywgJ0NoYW5nZXMgd2lsbCBiZSBhcHBsaWVkIG9uIG5leHQgc2VydmVyIHJlc3RhcnQnKTtcblx0XHRcdH1cblx0XHRcdGVsc2Vcblx0XHRcdHtcblx0XHRcdFx0Ly8gU2hvdyBhbGVydFxuXHRcdFx0XHR0aGlzLnNoZWxsQ3RybC5zaG93U2ltcGxlQWxlcnQoYEFkbWluaXN0cmF0b3IgJHt1cGRhdGVyfSBoYXMgbW9kaWZpZWQgdGhlIHNlcnZlciBzZXR0aW5nczsgcGxlYXNlIHJlbG9hZCB0byB1cGRhdGUgeW91ciB2aWV3LmApO1xuXG5cdFx0XHRcdC8vIERpc2FibGUgc3VibWl0IGJ1dHRvblxuXHRcdFx0XHQkKCcjc3JjLXN1Ym1pdEJ1dHRvbicpLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gU2VydmVyIGNvbmZpZ3VyYXRpb24geG1sIHNhdmVkIGJ5IGFuIGV4dGVybmFsIHByb2Nlc3Ncblx0XHRlbHNlIGlmIChjb21tYW5kID09IHRoaXMuUkVTUF9DT05GSUdfQ0hBTkdFRF9BTEVSVClcblx0XHR7XG5cdFx0XHQvLyBTaG93IGFsZXJ0XG5cdFx0XHR0aGlzLnNoZWxsQ3RybC5zaG93U2ltcGxlQWxlcnQoYFRoZSBzeXN0ZW0gaGFzIG1vZGlmaWVkIHRoZSBzZXJ2ZXIgc2V0dGluZ3MgYXV0b21hdGljYWxseTsgcGxlYXNlIHJlbG9hZCB0byB1cGRhdGUgeW91ciB2aWV3LmApO1xuXG5cdFx0XHQvLyBEaXNhYmxlIHN1Ym1pdCBidXR0b25cblx0XHRcdCQoJyNzcmMtc3VibWl0QnV0dG9uJykuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcblx0XHR9XG5cblx0XHQvLyBTU0wgY2VydGlmaWNhdGUgdXBsb2FkIGVycm9yXG5cdFx0ZWxzZSBpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfU1NMX1VQTE9BRF9FUlJPUilcblx0XHR7XG5cdFx0XHRjb25zdCBlcnJvciA9IGRhdGEuZ2V0VXRmU3RyaW5nKCdlcnJvcicpO1xuXG5cdFx0XHQvLyBMb2cgd2FybmluZ1xuXHRcdFx0dGhpcy5zaGVsbEN0cmwubG9nTWVzc2FnZShlcnJvciwgJ2Vycm9yJyk7XG5cblx0XHRcdC8vIFNob3cgZXJyb3IgaW4gbWFuYWdlciB3aW5kb3dcblx0XHRcdHRoaXMuX3NzbENlcnRNYW5hZ2VyLm9uU3NsQ2VydFVwbG9hZEVycm9yKGVycm9yKTtcblx0XHR9XG5cblx0XHQvLyBTU0wgY2VydGlmaWNhdGUgdXBsb2FkIGNvbmZpcm1lZFxuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX1NTTF9VUExPQURfQ09ORklSTSlcblx0XHR7XG5cdFx0XHQvLyBDbG9zdyBtYW5hZ2VyIHdpbmRvd1xuXHRcdFx0dGhpcy5fc3NsQ2VydE1hbmFnZXIub25Tc2xDZXJ0VXBsb2FkU3VjY2VzcygpO1xuXG5cdFx0XHRsZXQgdXBkYXRlciA9IGRhdGEuZ2V0VXRmU3RyaW5nKCd1c2VyJyk7XG5cblx0XHRcdC8vIERpc3BsYXkgbm90aWZpY2F0aW9uXG5cdFx0XHRpZiAodXBkYXRlciA9PSB0aGlzLnNtYXJ0Rm94Lm15U2VsZi5uYW1lKVxuXHRcdFx0XHR0aGlzLnNoZWxsQ3RybC5zaG93Tm90aWZpY2F0aW9uKCdTU0wgY2VydGlmaWNhdGUnLCAnU1NMIGNlcnRpZmljYXRlIGtleXN0b3JlIHdhcyB1cGxvYWRlZCBzdWNjZXNzZnVsbHknKTtcblx0XHRcdGVsc2Vcblx0XHRcdFx0dGhpcy5zaGVsbEN0cmwuc2hvd05vdGlmaWNhdGlvbignU1NMIGNlcnRpZmljYXRlJywgYEFkbWluaXN0cmF0b3IgJHt1cGRhdGVyfSBoYXMgdXBsb2FkZWQgYSBuZXcgU1NMIGNlcnRpZmljYXRlIGtleXN0b3JlYCk7XG5cblx0XHRcdC8vIFdoZW4gYSBjZXJ0aWZpY2F0ZSBpcyB1cGxvYWRlZCwgSFRUUFMgaXMgYWxzbyBlbmFibGVkIGF1dG9tYXRpY2FsbHk6XG5cdFx0XHQvLyB3ZSBoYXZlIHRvIHVwZGF0ZSB0aGUgaW50ZXJmYWNlIGFjY29yZGluZ2x5XG5cdFx0XHR0aGlzLl91cGRhdGVDb25maWdGb3JtSXRlbURpc3BsYXllZFZhbHVlKCd3ZWJTZXJ2ZXIuZW5hYmxlSHR0cHMnLCB0cnVlKTtcblx0XHR9XG5cblx0XHQvLyBHZW9sb2NhdGlvbiBkYXRhYmFzZSB1cGRhdGUgY29uZmlybWF0aW9uXG5cdFx0ZWxzZSBpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfVVBEQVRFX0dFT19EQilcblx0XHR7XG5cdFx0XHQvLyBFbmFibGUgYnV0dG9uXG5cdFx0XHQkKCcjc3JjLXVwZGF0ZUdlb2xvY0RiQnV0dG9uJykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cblx0XHRcdC8vIENoZWNrIHN1Y2Nlc3Ncblx0XHRcdGlmIChkYXRhLmdldEJvb2woJ3N1Y2Nlc3MnKSlcblx0XHRcdHtcblx0XHRcdFx0Ly8gVXBkYXRlIGRpc3BsYXllZCBkYXRlXG5cdFx0XHRcdHRoaXMuX3VwZGF0ZUNvbmZpZ0Zvcm1JdGVtRGlzcGxheWVkVmFsdWUoJ2FkbWluSGVscGVyLmdlb0RiUmVsZWFzZURhdGUnLCBkYXRhLmdldFV0ZlN0cmluZygnbmV3UmVsRGF0ZScpKTtcblxuXHRcdFx0XHQvLyBJZiB0aGUgY3VycmVudCB1c2VyIGlzIHRoZSB1cGRhdGVyLCBhbHNvIHNob3cgYSBub3RpZmljYXRpb25cblx0XHRcdFx0bGV0IHVwZGF0ZXIgPSBkYXRhLmdldFV0ZlN0cmluZygndXNlcicpO1xuXG5cdFx0XHRcdGlmICh1cGRhdGVyID09IHRoaXMuc21hcnRGb3gubXlTZWxmLm5hbWUpXG5cdFx0XHRcdFx0dGhpcy5zaGVsbEN0cmwuc2hvd05vdGlmaWNhdGlvbignR2VvbG9jYXRpb24gZGF0YWJhc2UgdXBkYXRlZCcsICdMYXRlc3QgcmVsZWFzZSBvZiB0aGUgR2VvTGl0ZTIgQ291bnRyeSBkYXRhYmFzZSBoYXMgYmVlbiBpbnN0YWxsZWQgc3VjY2Vzc2Z1bGx5Jyk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlXG5cdFx0XHR7XG5cdFx0XHRcdC8vIFNob3cgYWxlcnRcblx0XHRcdFx0dGhpcy5zaGVsbEN0cmwuc2hvd1NpbXBsZUFsZXJ0KGRhdGEuZ2V0VXRmU3RyaW5nKCdlcnJvcicpKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLyBQUklWQVRFIE1FVEhPRFNcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRfZW5hYmxlQnV0dG9ucyhlbmFibGVkKVxuXHR7XG5cdFx0JCgnI3NyYy1yZWxvYWRCdXR0b24nKS5hdHRyKCdkaXNhYmxlZCcsICFlbmFibGVkKTtcblx0XHQkKCcjc3JjLXN1Ym1pdEJ1dHRvbicpLmF0dHIoJ2Rpc2FibGVkJywgIWVuYWJsZWQpO1xuXHRcdCQoJyNzcmMtYmFja3VwQ2hlY2snKS5hdHRyKCdkaXNhYmxlZCcsICFlbmFibGVkKTtcblxuXHRcdCQoJyNzcmMtdXBkYXRlR2VvbG9jRGJCdXR0b24nKS5hdHRyKCdkaXNhYmxlZCcsICFlbmFibGVkKTtcblxuXHRcdGlmICghdGhpcy5fc3NsTG9ja2VkKVxuXHRcdFx0dGhpcy5fc3NsQ2VydE1hbmFnZXIuZW5hYmxlZCA9IGVuYWJsZWQ7XG5cdH1cblxuXHRfc3dpdGNoVmlldyh2aWV3SWQpXG5cdHtcblx0XHRkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc3JjLXZpZXdzdGFjaycpLnNlbGVjdGVkRWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHZpZXdJZCk7XG5cdH1cblxuXHRfY2xlYXJUYWJzKClcblx0e1xuXHRcdC8vIERlc3Ryb3kgc2Nyb2xsaW5nIHRhYnNcblx0XHQkKCcjc3JjLXRhYk5hdmlnYXRvciAjdGFicycpLnNjcm9sbGluZ1RhYnMoJ2Rlc3Ryb3knKTtcblxuXHRcdC8vIFJlbW92ZSBhbGwgdGFiIG5hdmlnYXRvciBjb250ZW50XG5cdFx0dGhpcy5faW50ZXJmYWNlQnVpbGRlci5kZXN0cm95SW50ZXJmYWNlKCk7XG5cdH1cblxuXHRfb25VcGRhdGVHZW9sb2NEYkNsaWNrKClcblx0e1xuXHRcdC8vIERpc2FibGUgYnV0dG9uXG5cdFx0JCgnI3NyYy11cGRhdGVHZW9sb2NEYkJ1dHRvbicpLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cblx0XHQvLyBTZW5kIHJlcXVlc3QgdG8gc2VydmVyXG5cdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9VUERBVEVfR0VPX0RCKTtcblx0fVxuXG5cdF9vblJlbG9hZENsaWNrKClcblx0e1xuXHRcdC8vIERpc2FibGUgYnV0dG9uc1xuXHRcdHRoaXMuX2VuYWJsZUJ1dHRvbnMoZmFsc2UpO1xuXG5cdFx0Ly8gU3dpdGNoIHRvIGxvYWRpbmcgdmlld1xuXHRcdHRoaXMuX3N3aXRjaFZpZXcoJ3NyYy1sb2FkaW5nJyk7XG5cblx0XHQvLyBIaWRlIHZhbGlkYXRpb24gbWVzc2FnZXNcblx0XHR0aGlzLl9pbnRlcmZhY2VCdWlsZGVyLnJlc2V0VmFsaWRhdGlvbigpO1xuXG5cdFx0Ly8gUmVxdWVzdCBjb25maWd1cmF0aW9uIGRhdGEgdG8gc2VydmVyIGluc3RhbmNlXG5cdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9HRVRfQ09ORklHKTtcblx0fVxuXG5cdF9vblN1Ym1pdENsaWNrKClcblx0e1xuXHRcdC8vIENoZWNrIHZhbGlkaXR5XG5cdFx0aWYgKHRoaXMuX2ludGVyZmFjZUJ1aWxkZXIuY2hlY2tJc1ZhbGlkKCkpXG5cdFx0e1xuXHRcdFx0bGV0IGNoYW5nZXMgPSB0aGlzLl9pbnRlcmZhY2VCdWlsZGVyLmdldENoYW5nZWREYXRhKCk7XG5cblx0XHRcdGlmIChjaGFuZ2VzLnNpemUoKSA+IDApXG5cdFx0XHR7XG5cdFx0XHRcdC8vIERpc2FibGUgYnV0dG9uc1xuXHRcdFx0XHR0aGlzLl9lbmFibGVCdXR0b25zKGZhbHNlKTtcblxuXHRcdFx0XHQvLyBEaXNhYmxlIGZvcm0gaXRlbXNcblx0XHRcdFx0dGhpcy5faW50ZXJmYWNlQnVpbGRlci5kaXNhYmxlSW50ZXJmYWNlKHRydWUpO1xuXG5cdFx0XHRcdC8vIFNlbmQgdXBkYXRlZCBzZXR0aW5ncyB0byBzZXJ2ZXIgaW5zdGFuY2Vcblx0XHRcdFx0bGV0IHBhcmFtcyA9IG5ldyBTRlMyWC5TRlNPYmplY3QoKTtcblx0XHRcdFx0cGFyYW1zLnB1dFNGU0FycmF5KCdzZXR0aW5ncycsIGNoYW5nZXMpO1xuXHRcdFx0XHRwYXJhbXMucHV0Qm9vbCgnYmFja3VwJywgJCgnI3NyYy1iYWNrdXBDaGVjaycpLnByb3AoJ2NoZWNrZWQnKSk7XG5cblx0XHRcdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9VUERBVEVfQ09ORklHLCBwYXJhbXMpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlXG5cdFx0XHR0aGlzLnNoZWxsQ3RybC5zaG93U2ltcGxlQWxlcnQoJ1VuYWJsZSB0byBzdWJtaXQgY29uZmlndXJhdGlvbiBjaGFuZ2VzIGR1ZSB0byBhbiBpbnZhbGlkIHZhbHVlOyBwbGVhc2UgdmVyaWZ5IHRoZSBoaWdobGlnaHRlZCBmb3JtIGZpZWxkcyBpbiBhbGwgdGFicy4nLCB0cnVlKTtcblx0fVxuXG5cdF91cGRhdGVDb25maWdGb3JtSXRlbURpc3BsYXllZFZhbHVlKGNvbmZpZ1BhcmFtTmFtZSwgbmV3VmFsdWUpXG5cdHtcblx0XHQvLyBHZXQgdGhlIHJlbGV2YW50IENvbmZpZ3VyYXRpb24gRm9ybSBJdGVtXG5cdFx0Y29uc3QgY29uZmlnRm9ybUl0ZW0gPSB0aGlzLl9pbnRlcmZhY2VCdWlsZGVyLmdldENvbmZpZ0Zvcm1JdGVtKGNvbmZpZ1BhcmFtTmFtZSk7XG5cblx0XHQvLyBVcGRhdGUgQ29uZmlndXJhdGlvbiBQYXJhbWV0ZXIgYXNzb2NpYXRlZCB3aXRoIHRoZSBDb25maWd1cmF0aW9uIEZvcm0gSXRlbVxuXHRcdGNvbmZpZ0Zvcm1JdGVtLmRhdGEudmFsdWUgPSBuZXdWYWx1ZTtcblx0XHRjb25maWdGb3JtSXRlbS5kYXRhLnJlc2V0SXNNb2RpZmllZCgpOyAvLyBUaGlzIGlzIG5lZWRlZCB0byBhdm9pZCB0aGUgQ29uZmlndXJhdGlvbiBQYXJhbWV0ZXIgdG8gZmxhZ2dlZCBhcyAnY2hhbmdlZCdcblxuXHRcdC8vIERpc3BsYXkgdGhlIG5ldyB2YWx1ZSBvZiB0aGUgQ29uZmlndXJhdGlvbiBGb3JtIEl0ZW1cblx0XHRjb25maWdGb3JtSXRlbS5fc2V0V2lkZ2V0VmFsdWUoKTsgLy8gRGlzcGxheSB0aGUgbmV3IHZhbHVlIGluIHRoZSBjb25maWcgZm9ybSBpdGVtXG5cdH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7OztBQ25kQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QSIsInNvdXJjZVJvb3QiOiIifQ==
768
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXRzL2pzL2NvcmUvbW9kdWxlcy9tb2R1bGUtOS5idW5kbGUuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9tb2R1bGVzL2V4dGVuc2lvbi1kZXBsb3llci5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0Jhc2VNb2R1bGV9IGZyb20gJy4vYmFzZS1tb2R1bGUnO1xuaW1wb3J0ICogYXMgbW9tZW50IGZyb20gJ21vbWVudCc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEV4dGVuc2lvbkRlcGxveWVyIGV4dGVuZHMgQmFzZU1vZHVsZVxue1xuXHRjb25zdHJ1Y3RvcigpXG5cdHtcblx0ICAgIHN1cGVyKCdleHREZXBsb3llcicpO1xuXG5cdFx0Ly8gT3V0Z29pbmcgcmVxdWVzdHNcblx0XHR0aGlzLlJFUV9JTklUID0gJ2luaXQnO1xuXHRcdHRoaXMuUkVRX0dFVF9OT0RFUyA9ICdnZXROb2Rlcyc7XG5cblx0XHQvLyBJbmNvbWluZyByZXNwb25zZXNcblx0XHR0aGlzLlJFU1BfTE9DS0VEID0gJ2xvY2snO1xuXHRcdHRoaXMuUkVTUF9JTklUID0gJ2luaXQnO1xuXHRcdHRoaXMuUkVTUF9OT0RFUyA9ICdub2Rlcyc7XG5cdFx0dGhpcy5SRVNQX1NVQ0NFU1MgPSAnc3VjY2Vzcyc7XG5cdFx0dGhpcy5SRVNQX1dBUk4gPSAnd2Fybic7XG5cdFx0dGhpcy5SRVNQX0VSUk9SID0gJ2Vycm9yJztcblxuXHRcdHRoaXMuX3NlbGVjdGVkTm9kZXMgPSBbXTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIENPTU1PTiBNT0RVTEUgSU5URVJGQUNFIE1FVEhPRFNcblx0Ly8gVGhpcyBtZW1iZXJzIGFyZSB1c2VkIGJ5IHRoZSBtYWluIGNvbnRyb2xsZXJcblx0Ly8gdG8gY29tbXVuaWNhdGUgd2l0aCB0aGUgbW9kdWxlJ3MgY29udHJvbGxlci5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRpbml0aWFsaXplKGlkRGF0YSwgc2hlbGxDb250cm9sbGVyKVxuXHR7XG5cdFx0Ly8gQ2FsbCBzdXBlciBtZXRob2Rcblx0XHRzdXBlci5pbml0aWFsaXplKGlkRGF0YSwgc2hlbGxDb250cm9sbGVyKTtcblxuXHRcdC8vIEluaXRpYWxpemUgcHJvZ3Jlc3MgYmFyc1xuXHRcdCQoJy5leGQtcHJvZ3Jlc3NCYXInKS5rZW5kb1Byb2dyZXNzQmFyKHtcblx0XHRcdG1pbjogMCxcbiAgICAgICAgICAgIG1heDogMTAwLFxuXHRcdFx0dmFsdWU6IGZhbHNlLFxuICAgICAgICAgICAgdHlwZTogJ3ZhbHVlJyxcbiAgICAgICAgICAgIGFuaW1hdGlvbjoge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiA0MDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cblx0XHQvLyBBZGQgbGlzdGVuZXJzIHRvIGJ1dHRvbnNcblx0XHQkKCcjZXhkLXJldHJ5QnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uUmV0cnlDbGljaywgdGhpcykpO1xuXHRcdCQoJyNleGQtcmVmcmVzaEJ0Jykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9yZXF1ZXN0Tm9kZXNMaXN0LCB0aGlzKSk7XG5cdFx0JCgnI2V4ZC1kZXBsb3lCdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25EZXBsb3lDbGljaywgdGhpcykpO1xuXHRcdCQoJy5leGQtc3RhdHVzQ2xvc2VCdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25DbG9zZVN0YXR1c0NsaWNrLCB0aGlzKSk7XG5cblx0XHQvLyBJbml0aWFsaXplIGtlbmRvIHN3aXRjaFxuXHRcdHRoaXMuX21vZGVTd2l0Y2ggPSAkKCcjZXhkLW1vZGVDYicpLmtlbmRvU3dpdGNoKCkuZGF0YSgna2VuZG9Td2l0Y2gnKTtcblxuXHRcdC8vIEluaXRpYWxpemUgZ3JpZFxuXHRcdHRoaXMuX2dyaWQgPSAkKCcjZXhkLW5vZGVzTGlzdCcpLmtlbmRvR3JpZCh7XG5cdFx0XHRzY3JvbGxhYmxlOiB0cnVlLFxuICAgICAgICAgICAgc29ydGFibGU6IHRydWUsXG5cdFx0XHQvL3Jlc2l6YWJsZTogdHJ1ZSxcblx0XHRcdHNlbGVjdGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgY29sdW1uczogW1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0c2VsZWN0YWJsZTogdHJ1ZSxcblx0XHRcdFx0XHR3aWR0aDogNDFcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHQgICAgICAgICAgICAgICAgZmllbGQ6ICduYW1lJyxcblx0ICAgICAgICAgICAgICAgIHdpZHRoOiA1MDAsXG5cdFx0XHRcdFx0dGl0bGU6ICdOb2RlJyxcblx0XHRcdFx0XHR0ZW1wbGF0ZTogZnVuY3Rpb24oZGF0YUl0ZW0pIHtcblx0XHRcdFx0XHRcdGlmIChkYXRhSXRlbVsnYWxpYXMnXSlcblx0XHRcdFx0XHRcdFx0cmV0dXJuICc8ZGl2IGNsYXNzPVwibmFtZS1jZWxsXCI+PHNwYW4+JyArIGRhdGFJdGVtWydhbGlhcyddICsgJzwvc3Bhbj48YnI+PHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZFwiPicgKyBkYXRhSXRlbVsnbmFtZSddICsgJzxzbWFsbD48L2Rpdj4nO1xuXHRcdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gJzxkaXYgY2xhc3M9XCJuYW1lLWNlbGxcIj48c3Bhbj4nICsgZGF0YUl0ZW1bJ25hbWUnXSArICc8L3NwYW4+PC9kaXY+Jztcblx0XHRcdFx0XHR9XG5cdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdHtcblx0ICAgICAgICAgICAgICAgIGZpZWxkOiAnaGVhbHRoJyxcblx0ICAgICAgICAgICAgICAgIHdpZHRoOiA3NSxcblx0XHRcdFx0XHR0aXRsZTogJ0hlYWx0aCcsXG5cdFx0XHRcdFx0c29ydGFibGU6IGZhbHNlLFxuXHRcdFx0XHRcdHRlbXBsYXRlOiAkLnByb3h5KHRoaXMuX2dldEhlYWx0aFRlbXBsYXRlLCB0aGlzKVxuXHQgICAgICAgICAgICB9LFxuXHRcdFx0XSxcblx0XHRcdG5vUmVjb3Jkczoge1xuXHRcdFx0XHR0ZW1wbGF0ZTogJ05vIGdhbWUgbm9kZXMgaW4gdGhlIGNsdXN0ZXIuJ1xuXHRcdFx0fSxcblx0XHRcdGRhdGFTb3VyY2U6IHtcblx0XHRcdFx0c2NoZW1hOiB7XG5cdFx0XHRcdFx0bW9kZWw6IHtcblx0XHRcdFx0XHRcdGlkOiAnaWQnLFxuXHRcdFx0XHRcdFx0Ly8gZmllbGRzOiB7XG5cdFx0XHRcdFx0XHQvLyBcdGlkOiB7IHR5cGU6ICdzdHJpbmcnIH0sXG5cdFx0XHRcdFx0XHQvLyBcdGFjdGl2ZTogeyB0eXBlOiAnYm9vbGVhbicgfVxuXHRcdFx0XHRcdFx0Ly8gfVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0Z3JvdXA6IHtcblx0XHRcdFx0XHRmaWVsZDogJ2FjdGl2ZScsXG5cdFx0XHRcdFx0ZGlyOiAnZGVzYycsXG5cdFx0XHRcdH1cbiAgICAgICAgICAgIH0sXG5cdFx0XHRjaGFuZ2U6ICQucHJveHkodGhpcy5fb25Ob2Rlc0dyaWRDaGFuZ2UsIHRoaXMpLFxuXHRcdFx0ZGF0YUJvdW5kOiAkLnByb3h5KHRoaXMuX29uTm9kZXNHcmlkRGF0YUJvdW5kLCB0aGlzKSxcbiAgICAgICAgfSkuZGF0YSgna2VuZG9HcmlkJyk7XG5cblx0XHQvLyBJbml0aWFsaXplIGtlbmRvIHVwbG9hZGVyXG5cdFx0dGhpcy5fdXBsb2FkZXIgPSAkKCcjZXhkLXVwbG9hZGVyJykua2VuZG9VcGxvYWQoe1xuXHRcdFx0bXVsdGlwbGU6IGZhbHNlLFxuXHRcdFx0YXN5bmM6IHtcblx0XHRcdFx0c2F2ZVVybDogJ2h0dHA6Ly9sb2NhbGhvc3QnLCAvLyBUaGlzIHdpbGwgYmUgY2hhbmdlZCBsYXRlciBpbiBfb25VcGxvYWRTdGFydCBtZXRob2Rcblx0XHRcdFx0YXV0b1VwbG9hZDogZmFsc2UsXG5cdFx0XHR9LFxuXHRcdFx0ZGlyZWN0b3J5RHJvcDogdHJ1ZSxcblx0XHRcdHVwbG9hZDogJC5wcm94eSh0aGlzLl9vblVwbG9hZFN0YXJ0LCB0aGlzKSxcblx0XHRcdGNvbXBsZXRlOiAkLnByb3h5KHRoaXMuX29uVXBsb2FkRW5kLCB0aGlzKSxcblx0XHRcdGxvY2FsaXphdGlvbjoge1xuXHRcdFx0XHRzZWxlY3Q6ICdTZWxlY3QgemlwIGZpbGUuLi4nXG5cdFx0XHR9XG5cdFx0fSkuZGF0YSgna2VuZG9VcGxvYWQnKTtcblxuXHRcdC8vIEluaXRpYWxpemUgXCJkZXBsb3ltZW50IHN0YXR1c1wiIG1vZGFsXG5cdFx0dGhpcy5fZGVwbG95U3RhdHVzTW9kYWwgPSAkKCcjZXhkLWRlcGxveVN0YXR1c01vZGFsJyk7XG5cdFx0dGhpcy5fZGVwbG95U3RhdHVzTW9kYWwubW9kYWwoe1xuXHRcdFx0YmFja2Ryb3A6ICdzdGF0aWMnLFxuXHRcdFx0a2V5Ym9hcmQ6IGZhbHNlLFxuXHRcdFx0c2hvdzogZmFsc2Vcblx0XHR9KTtcblxuXHRcdC8vIEluaXRpYWxpemUgaGVscCB0b29sdGlwc1xuXHRcdCQodGhpcykua2VuZG9Ub29sdGlwKHtcblx0XHRcdGZpbHRlcjogJ2lbdGl0bGVdLmhlbHAnLFxuXHRcdFx0cG9zaXRpb246ICdyaWdodCcsXG5cdFx0XHRjb250ZW50OiBmdW5jdGlvbihlKSB7XG5cdFx0XHRcdHJldHVybiBgPGRpdiBjbGFzcz1cImhlbHAtdG9vbHRpcFwiPiR7ZS50YXJnZXQuZGF0YSgndGl0bGUnKX08L2Rpdj5gO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0Ly8gU2V0IHVwbG9hZCBmb3JtIGRpc2FibGVkXG5cdFx0dGhpcy5fZW5hYmxlRGVwbG95Rm9ybShmYWxzZSk7XG5cblx0XHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRcdC8vIFNlbmQgaW5pdGlhbGl6YXRpb24gcmVxdWVzdFxuXHRcdHRoaXMuc2VuZEV4dGVuc2lvblJlcXVlc3QodGhpcy5SRVFfSU5JVCk7XG5cdH1cblxuXHRkZXN0cm95KClcblx0e1xuXHRcdC8vIENhbGwgc3VwZXIgbWV0aG9kXG5cdFx0c3VwZXIuZGVzdHJveSgpO1xuXG5cdFx0Ly8gUmVtb3ZlIGNsaWNrIGxpc3RlbmVyc1xuXHRcdCQoJyNleGQtcmV0cnlCdCcpLm9mZignY2xpY2snKTtcblx0XHQkKCcjZXhkLXJlZnJlc2hCdCcpLm9mZignY2xpY2snKTtcblx0XHQkKCcjZXhkLWRlcGxveUJ0Jykub2ZmKCdjbGljaycpO1xuXHRcdCQoJy5leGQtc3RhdHVzQ2xvc2VCdCcpLm9mZignY2xpY2snKTtcblxuXHRcdC8vIENsZWFyIG5vZGVzIHJlcXVlc3Qgc2NoZWR1bGluZ1xuXHRcdGNsZWFyVGltZW91dCh0aGlzLl9yZXF1ZXN0Tm9kZXNUaW1lcik7XG5cdH1cblxuXHRvbkV4dGVuc2lvbkNvbW1hbmQoY29tbWFuZCwgZGF0YSlcblx0e1xuXHRcdC8qXG5cdFx0ICogVGhpcyByZXNwb25zZSBpcyByZXR1cm5lZCBpZiB0aGUgZmlsZSBVcGxvYWRzTG9jay50eHQgZXhpc3RzIGluIHRoZSAvY29uZmlnIGZvbGRlciBvZiB0aGUgc2VydmVyLlxuXHRcdCAqIFRoaXMgaXMgYW4gYWRkaXRpb25hbCBzZWN1cml0eSBtZWFzdXJlIHRvIGF2b2lkIHVud2FudGVkIGZpbGVzIHRvIGJlIHVwbG9hZGVkIGJ5IG1hbGljaXVzIHVzZXJzIGFjY2Vzc2luZyB0aGUgc2VydmVyXG5cdFx0ICogd2l0aCB0aGUgZGVmYXVsdCBjcmVkZW50aWFscywgaW4gY2FzZSB0aGV5IGhhdmUgbm90IGJlZW4gY2hhbmdlZCBieSB0aGUgYWRtaW5pc3RyYXRvciBhZnRlciB0aGUgaW5zdGFsbGF0aW9uLlxuXHRcdCAqIFRoZSBmaWxlIG11c3QgYmUgcmVtb3ZlZCBtYW51YWxseSBiZWZvcmUgYWNjZXNzaW5nIHRoZSBFeHRlbnNpb24gRGVwbG95ZXIgbW9kdWxlIGZvciB0aGUgZmlyc3QgdGltZVxuXHRcdCAqL1xuXHRcdGlmIChjb21tYW5kID09IHRoaXMuUkVTUF9MT0NLRUQpXG5cdFx0e1xuXHRcdFx0Ly8gU2hvdyB3YXJuaW5nXG5cdFx0XHR0aGlzLl9zd2l0Y2hNYWluVmlldygnZXhkLWxvY2tlZCcpO1xuXHRcdH1cblxuXHRcdC8vIE1vZHVsZSBjYW4gYmUgZW5hYmxlZCAobm8gbG9ja2luZyBmaWxlIGV4aXN0cylcblx0XHRlbHNlIGlmIChjb21tYW5kID09IHRoaXMuUkVTUF9JTklUKVxuXHRcdHtcblx0XHRcdC8vIFJldHJpZXZlIG1vZHVsZSBpZCBzZW50IGJ5IHRoZSBzZXJ2ZXIgKHJlcXVpcmVkIGJlY2F1c2UgbXVsdGlwbGUgbW9kdWxlcyB1c2UgZmlsZSB1cGxvYWRpbmcgc2VydmljZSlcblx0XHRcdGNvbnN0IHVwbG9hZE1vZHVsZUlkID0gZGF0YS5nZXRVdGZTdHJpbmcoJ21vZElkJyk7XG5cblx0XHRcdC8vIFNldCBmaWxlIHVwbG9hZGluZyB0YXJnZXQgY29uZmlndXJhdGlvblxuXHRcdFx0dGhpcy5fdXBsb2FkVGFyZ2V0Q29uZmlnID0ge1xuXHRcdFx0XHRzZXNzaW9uVG9rZW46IHRoaXMuc21hcnRGb3guc2Vzc2lvblRva2VuLFxuXHRcdFx0XHRob3N0OiB0aGlzLnNtYXJ0Rm94LmNvbmZpZy5ob3N0LFxuXHRcdFx0XHRwb3J0OiB0aGlzLnNtYXJ0Rm94LmNvbmZpZy5wb3J0LFxuXHRcdFx0XHRtb2R1bGVJZDogdXBsb2FkTW9kdWxlSWQsXG5cdFx0XHRcdHByb3RvY29sOiB0aGlzLnNtYXJ0Rm94LmNvbmZpZy51c2VTU0wgPyAnaHR0cHMnIDogJ2h0dHAnXG5cdFx0XHR9O1xuXG5cdFx0XHQvLyBTaG93IG1vZHVsZSdzIG1haW4gdmlld1xuXHRcdFx0dGhpcy5fc3dpdGNoTWFpblZpZXcoJ2V4ZC1tYWluJyk7XG5cblx0XHRcdC8vIFJlcXVlc3Qgbm9kZXMgbGlzdCB0byBzZXJ2ZXJcblx0XHRcdHRoaXMuX3JlcXVlc3ROb2Rlc0xpc3QoKTtcblx0XHR9XG5cblx0XHRlbHNlIGlmIChjb21tYW5kID09IHRoaXMuUkVTUF9OT0RFUylcblx0XHR7XG5cdFx0XHRsZXQgbm9kZXNPYmogPSBkYXRhLmdldFNGU0FycmF5KCdub2RlcycpO1xuXG5cdFx0XHRsZXQgbm9kZXMgPSBbXTtcblx0XHRcdGxldCBub2Rlc0lkcyA9IFtdO1xuXG5cdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IG5vZGVzT2JqLnNpemUoKTsgaSsrKVxuXHRcdFx0e1xuXHRcdFx0XHRsZXQgbm9kZSA9IG5vZGVzT2JqLmdldFNGU0FycmF5KGkpO1xuXG5cdFx0XHRcdG5vZGVzSWRzLnB1c2gobm9kZS5nZXRVdGZTdHJpbmcoMCkpO1xuXG5cdFx0XHRcdG5vZGVzLnB1c2goe1xuXHRcdFx0XHRcdCdpZCc6IG5vZGUuZ2V0VXRmU3RyaW5nKDApLFxuXHRcdFx0XHRcdCdhbGlhcyc6IG5vZGUuZ2V0VXRmU3RyaW5nKDEpLFxuXHRcdFx0XHRcdCduYW1lJzogbm9kZS5nZXRVdGZTdHJpbmcoMiksXG5cdFx0XHRcdFx0J2hlYWx0aCc6IG5vZGUuZ2V0Qm9vbCgzKSxcblx0XHRcdFx0XHQnYWN0aXZlJzogbm9kZS5nZXRCb29sKDQpLCAvLyBVc2VkIGZvciBncm91cGluZ1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gR2V0IG5vZGVzIGdyaWQgZGF0YXNvdXJjZVxuXHRcdFx0bGV0IGRzID0gdGhpcy5fZ3JpZC5kYXRhU291cmNlO1xuXG5cdFx0XHQvLyAtLS0gUkVNT1ZFIE5PREVTIC0tLVxuXG5cdFx0XHRsZXQgc2VsZiA9IHRoaXM7XG5cdFx0XHQkLm1hcChkcy5kYXRhKCksIGZ1bmN0aW9uIChkYXRhSXRlbSwgaW5kZXgpIHtcblx0XHRcdFx0aWYgKGRhdGFJdGVtICYmICFub2Rlc0lkcy5pbmNsdWRlcyhkYXRhSXRlbVsnaWQnXSkpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHQvLyBSZW1vdmUgbm9kZSBmcm9tIGRhdGFzdG9yZVxuXHRcdFx0XHRcdGRzLnJlbW92ZShkYXRhSXRlbSk7XG5cblx0XHRcdFx0XHQvLyBSZW1vdmUgbm9kZSBmcm9tIGxpc3Qgb2Ygc2VsZWN0ZWQgbm9kZXMgKGlmIHNlbGVjdGVkKVxuXHRcdFx0XHRcdHNlbGYuX3NlbGVjdGVkTm9kZXMgPSBzZWxmLl9zZWxlY3RlZE5vZGVzLmZpbHRlcih4ID0+IHggIT09IGRhdGFJdGVtWydpZCddKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cblx0XHRcdC8vIC0tLSBBREQvVVBEQVRFIE5PREVTIC0tLVxuXG5cdFx0XHRmb3IgKGxldCBub2RlIG9mIG5vZGVzKVxuXHRcdFx0e1xuXHRcdFx0XHR2YXIgZGF0YUl0ZW0gPSBkcy5nZXQobm9kZS5pZCk7XG5cblx0XHRcdFx0Ly8gVXBkYXRlIG5vZGVcblx0XHRcdFx0aWYgKGRhdGFJdGVtKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0ZGF0YUl0ZW0uc2V0KCdoZWFsdGgnLCBub2RlLmhlYWx0aCk7XG5cdFx0XHRcdFx0ZGF0YUl0ZW0uc2V0KCdhY3RpdmUnLCBub2RlLmFjdGl2ZSk7XG5cblx0XHRcdFx0XHRkYXRhSXRlbS5kaXJ0eSA9IGZhbHNlOyAvLyBIaWRlcyBcImRpcnR5XCIgaW5kaWNhdG9yIGluIGdyaWRcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEFkZCBub2RlXG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0IFx0ZHMuYWRkKG5vZGUpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBSZWZyZXNoIGdyaWRcblx0XHRcdHRoaXMuX2dyaWQucmVmcmVzaCgpO1xuXHRcdH1cblxuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0VSUk9SKVxuXHRcdHtcblx0XHRcdC8vIERpc3BsYXkgZXJyb3IgbWVzc2FnZVxuXHRcdFx0JCgnI2V4ZC1zdGF0dXNFcnJvclRleHQnKS5odG1sKGRhdGEuZ2V0VXRmU3RyaW5nKCdtc2cnKSk7XG5cblx0XHRcdC8vIFN3aXRjaCB0byB2aWV3XG5cdFx0XHR0aGlzLl9zd2l0Y2hTdGF0dXNWaWV3KCdleGQtc3RhdHVzRXJyb3InKTtcblx0XHR9XG5cblx0XHRlbHNlIGlmIChjb21tYW5kID09IHRoaXMuUkVTUF9XQVJOKVxuXHRcdHtcblx0XHRcdC8vIERpc3BsYXkgZXJyb3IgbWVzc2FnZVxuXHRcdFx0JCgnI2V4ZC1zdGF0dXNXYXJuaW5nVGV4dCcpLmh0bWwoZGF0YS5nZXRVdGZTdHJpbmcoJ21zZycpLnJlcGxhY2UoLyg/OlxcclxcbnxcXHJ8XFxuKS9nLCAnPGJyPicpKTtcblxuXHRcdFx0Ly8gU3dpdGNoIHRvIHZpZXdcblx0XHRcdHRoaXMuX3N3aXRjaFN0YXR1c1ZpZXcoJ2V4ZC1zdGF0dXNXYXJuaW5nJyk7XG5cdFx0fVxuXG5cdFx0ZWxzZSBpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfU1VDQ0VTUylcblx0XHR7XG5cdFx0XHR0aGlzLl9zd2l0Y2hTdGF0dXNWaWV3KCdleGQtc3RhdHVzU3VjY2VzcycpO1xuXHRcdH1cblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIFVJIEVWRU5UIExJU1RFTkVSU1xuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdF9lbmFibGVEZXBsb3lGb3JtKGVuYWJsZWQpXG5cdHtcblx0XHQkKCcjZXhkLXVwbG9hZEZpbGVGb3JtJykucHJvcCgnZGlzYWJsZWQnLCAhZW5hYmxlZCk7XG5cdFx0dGhpcy5fbW9kZVN3aXRjaC5lbmFibGUoZW5hYmxlZCk7XG5cdH1cblxuXHRfb25SZXRyeUNsaWNrKClcblx0e1xuXHRcdHRoaXMuX3N3aXRjaE1haW5WaWV3KCdleGQtaW5pdCcpO1xuXG5cdFx0Ly8gUmUtc2VuZCBpbml0aWFsaXphdGlvbiByZXF1ZXN0XG5cdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9JTklUKTtcblx0fVxuXG5cdF9vbkNsb3NlU3RhdHVzQ2xpY2soKVxuXHR7XG5cdFx0dGhpcy5fZGVwbG95U3RhdHVzTW9kYWwuaGlkZSgpO1xuXG5cdFx0Ly8gQ2xlYXIgdXBsb2FkZXJcblx0XHR0aGlzLl91cGxvYWRlci5jbGVhckFsbEZpbGVzKCk7XG5cdH1cblxuXHRfb25Ob2Rlc0dyaWRDaGFuZ2UoZSwgYXJncylcblx0e1xuXHRcdGxldCBncmlkID0gZS5zZW5kZXI7XG5cdFx0bGV0IGl0ZW1zID0gZ3JpZC5pdGVtcygpO1xuXG5cdFx0dGhpcy5fc2VsZWN0ZWROb2RlcyA9IFtdO1xuXG5cdFx0Zm9yIChsZXQgaSBvZiBncmlkLnNlbGVjdCgpKVxuXHRcdHtcblx0XHRcdGxldCBkYXRhSXRlbSA9IGdyaWQuZGF0YUl0ZW0oaSk7XG5cdFx0XHR0aGlzLl9zZWxlY3RlZE5vZGVzLnB1c2goZGF0YUl0ZW1bJ2lkJ10pO1xuXHRcdH1cblxuXHRcdC8vIEVuYWJsZSB1cGxvYWQgYnV0dG9uXG5cdFx0dGhpcy5fZW5hYmxlRGVwbG95Rm9ybSh0aGlzLl9zZWxlY3RlZE5vZGVzLmxlbmd0aCA+IDApO1xuXHR9XG5cblx0X29uTm9kZXNHcmlkRGF0YUJvdW5kKGUpXG5cdHtcblx0XHRsZXQgZ3JpZCA9IGUuc2VuZGVyO1xuXHRcdGxldCBpdGVtcyA9IGdyaWQuaXRlbXMoKTtcblx0XHRsZXQgaXRlbXNUb1NlbGVjdCA9IFtdO1xuXHRcdGxldCBzZWxmID0gdGhpcztcblxuXHRcdGl0ZW1zLmVhY2goZnVuY3Rpb24gKGlkeCwgcm93KSB7XG5cdFx0XHRsZXQgZGF0YUl0ZW0gPSBncmlkLmRhdGFJdGVtKHJvdyk7XG5cdFx0XHRpZiAoc2VsZi5fc2VsZWN0ZWROb2Rlcy5pbmNsdWRlcyhkYXRhSXRlbVsnaWQnXSkpIHtcblx0XHRcdCBcdGl0ZW1zVG9TZWxlY3QucHVzaChyb3cpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0Ly8gUmUtc2VsZWN0IHByZXZpb3VzbHkgc2VsZWN0ZWQgbm9kZXNcblx0XHRncmlkLnNlbGVjdChpdGVtc1RvU2VsZWN0KTtcblxuXHRcdC8vIERpc2FibGUgdXBsb2FkIGJ1dHRvblxuXHRcdGlmIChpdGVtc1RvU2VsZWN0Lmxlbmd0aCA9PSAwKVxuXHRcdFx0dGhpcy5fZW5hYmxlRGVwbG95Rm9ybShmYWxzZSk7XG5cblx0XHQvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cblx0XHQvLyBIaWRlIGdyb3VwIGNvbHVtbiBhbmQgY29sbGFwc2UgaWNvblxuXHRcdCQoJyNleGQtbm9kZXNMaXN0IC5rLWdyb3VwLWNvbCwgI2V4ZC1ub2Rlc0xpc3QgLmstZ3JvdXAtY2VsbCcpLnJlbW92ZSgpO1xuXHRcdGxldCBzcGFuQ2VsbHMgPSAkKCcjZXhkLW5vZGVzTGlzdCAuay1ncm91cGluZy1yb3cnKS5jaGlsZHJlbigndGQnKTtcblx0XHRzcGFuQ2VsbHMuYXR0cignY29sc3BhbicsIHNwYW5DZWxscy5hdHRyKCdjb2xzcGFuJykgLSAxKTtcblx0XHQkKCcjZXhkLW5vZGVzTGlzdCAuay1pY29uLmstaS1jb2xsYXBzZScpLmhpZGUoKTtcblxuXHRcdC8vIE1vZGlmeSBncm91cCBsYWJlbFxuXHRcdCQoJyNleGQtbm9kZXNMaXN0IC5rLWdyb3VwaW5nLXJvdyB0ZCBwLmstcmVzZXQnKS5lYWNoKGZ1bmN0aW9uKCBpbmRleCApIHtcblx0XHRcdGlmICgkKHRoaXMpLnRleHQoKSA9PSAnYWN0aXZlOiB0cnVlJylcblx0XHRcdFx0JCh0aGlzKS50ZXh0KCdBY3RpdmUgbm9kZXMnKTtcblx0XHRcdGVsc2Vcblx0XHRcdFx0JCh0aGlzKS50ZXh0KCdJbmFjdGl2ZSBub2RlcycpO1xuXHRcdH0pO1xuXHR9XG5cblx0X3JlcXVlc3ROb2Rlc0xpc3QoKVxuXHR7XG5cdFx0Ly8gQ2xlYXIgcHJldmlvdXMgcmVxdWVzdCBzY2hlZHVsaW5nXG5cdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3JlcXVlc3ROb2Rlc1RpbWVyKTtcblxuXHRcdC8vIENoZWNrIGlmIGNvbm5lY3Rpb24gaXMgc3RpbGwgYXZhaWxhYmxlXG5cdFx0aWYgKHRoaXMuc21hcnRGb3guaXNDb25uZWN0ZWQpXG5cdFx0e1xuXHRcdFx0Ly8gU2VuZCByZXF1ZXN0IHRvIGV4dGVuc2lvblxuXHRcdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9HRVRfTk9ERVMpO1xuXG5cdFx0XHQvLyBTY2hlZHVsZSBuZXh0IHJlcXVlc3Rcblx0XHRcdHRoaXMuX3JlcXVlc3ROb2Rlc1RpbWVyID0gc2V0VGltZW91dCgkLnByb3h5KHRoaXMuX3JlcXVlc3ROb2Rlc0xpc3QsIHRoaXMpLCA1MDAwKTsgLy8gRXZlcnkgNSBzZWNvbmRzXG5cdFx0fVxuXHR9XG5cblx0X29uRGVwbG95Q2xpY2soKVxuXHR7XG5cdFx0Ly8gVHJpZ2dlciBjbGljayBvbiBVcGxvYWQgd2lkZ2V0XG5cdFx0JCgnYnV0dG9uLmstdXBsb2FkLXNlbGVjdGVkJykuY2xpY2soKTtcblx0fVxuXG5cdF9vblVwbG9hZFN0YXJ0KGUpXG5cdHtcblx0XHQvLyBEaXNwbGF5IHN0YXR1cyBtb2RhbFxuXHRcdHRoaXMuX3N3aXRjaFN0YXR1c1ZpZXcoJ2V4ZC1zdGF0dXNQcm9ncmVzcycpO1xuXHRcdHRoaXMuX2RlcGxveVN0YXR1c01vZGFsLnNob3coKTtcblxuXHRcdC8vIFNldCBkZXN0aW5hdGlvbiB1cmxcblx0XHRjb25zdCB1cmwgPSB0aGlzLl91cGxvYWRUYXJnZXRDb25maWcucHJvdG9jb2wgKyAnOi8vJyArIHRoaXMuX3VwbG9hZFRhcmdldENvbmZpZy5ob3N0ICsgJzonICsgdGhpcy5fdXBsb2FkVGFyZ2V0Q29uZmlnLnBvcnQgKyAnL0JsdWVCb3gvU0ZTMlhGaWxlVXBsb2FkP3Nlc3NIYXNoSWQ9JyArIHRoaXMuX3VwbG9hZFRhcmdldENvbmZpZy5zZXNzaW9uVG9rZW47XG5cblx0XHRlLnNlbmRlci5vcHRpb25zLmFzeW5jLnNhdmVVcmwgPSB1cmw7XG5cblx0XHQvLyBTZXQgcGF5bG9hZFxuXHRcdGNvbnN0IHBhcmFtcyA9IG5ldyBGb3JtRGF0YSgpO1xuXHRcdHBhcmFtcy5hcHBlbmQoJ19fbW9kdWxlJywgdGhpcy5fdXBsb2FkVGFyZ2V0Q29uZmlnLm1vZHVsZUlkKTtcblx0XHRwYXJhbXMuYXBwZW5kKCdfX25vZGVzJywgSlNPTi5zdHJpbmdpZnkodGhpcy5fc2VsZWN0ZWROb2RlcykpO1xuXHRcdHBhcmFtcy5hcHBlbmQoJ19fbm9EZXN0cm95JywgdGhpcy5fbW9kZVN3aXRjaC5jaGVjaygpKTtcblxuXHRcdGZvciAobGV0IGYgPSAwOyBmIDwgZS5maWxlcy5sZW5ndGg7IGYrKylcblx0XHRcdHBhcmFtcy5hcHBlbmQoJ2ZpbGVzW10nLCBlLmZpbGVzW2ZdLnJhd0ZpbGUpO1xuXG5cdFx0ZS5mb3JtRGF0YSA9IHBhcmFtcztcblx0fVxuXG5cdF9vblVwbG9hZEVuZChlKVxuXHR7XG5cdFx0Ly8gTm90aGlnbiB0byBkb1xuXHR9XG5cblx0X29uRmlsZXNVcGxvYWRFbmQocmVzcG9uc2UpXG5cdHtcblx0XHQvLyBOb3RoaW5nIHRvIGRvOiB3ZSBoYXZlIHRvIHdhaXQgdGhlIHVwbG9hZCBwcm9jZXNzIGNvbXBsZXRpb24gdG8gYmUgc2lnbmFsZWQgYnkgdGhlIHNlcnZlciB0aHJvdWdoIHRoZSBkZWRpY2F0ZWQgRXh0ZW5zaW9uIHJlc3BvbnNlXG5cblx0XHQvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cblx0XHQvLyBUT0RPIFNob3VsZCB3ZSBoYW5kbGUgdGhpcyByZXNwb25zZSBpbiBzb21lIHdheT8gRm9yIHNvbWUgdW5rbm93biByZWFzb24gd2UgYWx3YXlzIGdldCBvaz1mYWxzZSBhbmQgc3RhdHVzPTBcblx0XHQvLyBjb25zb2xlLmxvZyhyZXNwb25zZSlcblx0XHQvLyBjb25zb2xlLmxvZyhyZXNwb25zZS5vaylcblx0XHQvLyBjb25zb2xlLmxvZyhyZXNwb25zZS5zdGF0dXMpXG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLyBQUklWQVRFIE1FVEhPRFNcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRfc3dpdGNoTWFpblZpZXcodmlld0lkKVxuXHR7XG5cdFx0ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2V4ZC12aWV3c3RhY2snKS5zZWxlY3RlZEVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh2aWV3SWQpO1xuXHR9XG5cblx0X3N3aXRjaFN0YXR1c1ZpZXcodmlld0lkKVxuXHR7XG5cdFx0ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2V4ZC1kZXBsb3lTdGF0dXMnKS5zZWxlY3RlZEVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh2aWV3SWQpO1xuXHR9XG5cblx0X2dldEhlYWx0aFRlbXBsYXRlKGRhdGFJdGVtKVxuXHR7XG5cdFx0bGV0IHN0eWxlID0gJ3RleHQtc3VjY2Vzcyc7XG5cblx0XHRpZiAoIWRhdGFJdGVtWydoZWFsdGgnXSlcblx0XHRcdHN0eWxlID0gJ3RleHQtZGFuZ2VyJztcblxuXHRcdHJldHVybiBgPHNwYW4gY2xhc3M9XCIke3N0eWxlfVwiPjxpIGNsYXNzPVwiZmFzIGZhLWNpcmNsZVwiPjwvaT48L3NwYW4+YDtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIFBSSVZBVEUgR0VUVEVSU1xuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0EiLCJzb3VyY2VSb290IjoiIn0=