rubyfox-server 2.17.3.1 → 2.19.2.0

Sign up to get free protection for your applications and to get access to all the features.
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 -264
  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,202 +1,322 @@
1
1
  /*! (c) gotoAndPlay | All rights reserved */
2
2
  (window["webpackJsonpapplication"] = window["webpackJsonpapplication"] || []).push([["module-6"],{
3
3
 
4
- /***/ "./src/managers/file-datasource-manager.js":
5
- /*!*************************************************!*\
6
- !*** ./src/managers/file-datasource-manager.js ***!
7
- \*************************************************/
8
- /*! exports provided: FileDataSourceManager */
9
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
10
-
11
- "use strict";
12
- __webpack_require__.r(__webpack_exports__);
13
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FileDataSourceManager", function() { return FileDataSourceManager; });
14
- class FileDataSourceManager
15
- {
16
- constructor(libFolder, protectedFolders, fileSeparator)
17
- {
18
- this._protectedFolders = protectedFolders; // Folders which can't be deleted (but their content can)
19
- this._libFolder = libFolder;
20
- this._fileSeparator = fileSeparator;
21
- }
22
-
23
- get dataSource()
24
- {
25
- return this._dataSource;
26
- }
27
-
28
- init()
29
- {
30
- this._dataSource = new kendo.data.TreeListDataSource({
31
- data: [],
32
- schema: {
33
- model: {
34
- id: 'id',
35
- parentId: 'parentId',
36
- expanded: false
37
- }
38
- },
39
- sort: { field: 'name', dir: 'asc' }
40
- });
41
- }
42
-
43
- addFile(fileObj, parentLevel = null)
44
- {
45
- let file = {};
46
-
47
- file.name = fileObj.getUtfString('name');
48
- file.isDir = fileObj.getBool('isDir');
49
- file.lastMod = fileObj.getLong('lastMod');
50
- file.isLib = (file.isDir && file.name == this._libFolder);
51
- file.isProtected = (file.isDir && this._protectedFolders.indexOf(file.name) > -1);
52
- file.size = 0;
53
-
54
- if (parentLevel == null)
55
- file.level = 0;
56
- else
57
- file.level = parentLevel + 1;
58
-
59
- if (fileObj.containsKey('parent'))
60
- {
61
- file.parentId = fileObj.getUtfString('parent');
62
- file.id = file.parentId + this._fileSeparator + file.name;
63
- }
64
- else
65
- {
66
- file.parentId = null;
67
- file.id = file.name;
68
- }
69
-
70
- // Add child files
71
- if (file.isDir)
72
- {
73
- let filesArr = fileObj.getSFSArray('files');
74
-
75
- for (let i = 0; i < filesArr.size(); i++)
76
- file.size += this.addFile(filesArr.getSFSObject(i), file.level);
77
- }
78
- else
79
- file.size = fileObj.getLong('size');
80
-
81
- // Add file to data source
82
- this._dataSource.add(file);
83
-
84
- // Return file size
85
- return file.size;
86
- }
87
-
88
- removeFile(id)
89
- {
90
- let fileItem = this._dataSource.get(id);
91
-
92
- if (fileItem)
93
- {
94
- if (fileItem.parentId)
95
- {
96
- // Subtract old size from parent size
97
- let parentItem = this._dataSource.get(fileItem.parentId);
98
- this._updateParentSize(parentItem, -fileItem.size);
99
- }
100
-
101
- this._dataSource.remove(fileItem);
102
-
103
- // Return parent item
104
- if (fileItem.parentId)
105
- return this._dataSource.get(fileItem.parentId);
106
- }
107
- }
108
-
109
- getFileById(id)
110
- {
111
- return this._dataSource.get(id);
112
- }
113
-
114
- addFileToParent(fileObj, parentId)
115
- {
116
- let parentItem = this._dataSource.get(parentId);
117
-
118
- if (parentItem != null && parentItem.isDir)
119
- {
120
- const fileId = parentId + this._fileSeparator + fileObj.getUtfString('name');
121
- let fileItem = this._dataSource.get(fileId);
122
-
123
- if (fileItem != null)
124
- {
125
- // Subtract old size from parent size
126
- this._updateParentSize(parentItem, -fileItem.size);
127
-
128
- // Update existing item
129
- fileItem.name = fileObj.getUtfString('name');
130
- fileItem.lastMod = fileObj.getLong('lastMod');
131
- fileItem.size = fileObj.getLong('size');
132
- }
133
- else
134
- {
135
- // Add new item
136
- this.addFile(fileObj, parentItem.level);
137
- }
138
-
139
- // Update parent item size
140
- this._updateParentSize(parentItem, fileObj.getLong('size'));
141
-
142
- return fileId;
143
- }
144
- else
145
- throw new Error(`An unexpected error occurred while adding file '${fileObj.getUtfString('name')}' (target: ${parentId}).`);
146
- }
147
-
148
- _updateParentSize(parentItem, value)
149
- {
150
- parentItem.size += value;
151
-
152
- if (parentItem.parentId)
153
- {
154
- let grandParent = this._dataSource.get(parentItem.parentId);
155
- this._updateParentSize(grandParent, value);
156
- }
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;
157
278
  }
279
+ return map[req];
158
280
  }
159
-
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 ^\\.\\/.*$";
160
287
 
161
288
  /***/ }),
162
289
 
163
- /***/ "./src/modules/extension-manager.js":
164
- /*!******************************************!*\
165
- !*** ./src/modules/extension-manager.js ***!
166
- \******************************************/
290
+ /***/ "./src/modules/cluster-updater.js":
291
+ /*!****************************************!*\
292
+ !*** ./src/modules/cluster-updater.js ***!
293
+ \****************************************/
167
294
  /*! exports provided: default */
168
295
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
169
296
 
170
297
  "use strict";
171
298
  __webpack_require__.r(__webpack_exports__);
172
- /* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return ExtensionManager; });
299
+ /* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return ClusterUpdater; });
173
300
  /* harmony import */ var _base_module__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-module */ "./src/modules/base-module.js");
174
- /* harmony import */ var _managers_file_datasource_manager__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../managers/file-datasource-manager */ "./src/managers/file-datasource-manager.js");
175
- /* harmony import */ var _utils_utilities__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/utilities */ "./src/utils/utilities.js");
176
-
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__);
177
303
 
178
304
 
179
305
 
180
- class ExtensionManager extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseModule"]
306
+ class ClusterUpdater extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseModule"]
181
307
  {
182
308
  constructor()
183
309
  {
184
- super('extensionMan');
310
+ super('clusterUpd');
185
311
 
186
312
  // Outgoing requests
187
- this.REQ_INIT = 'init';
188
- this.REQ_GET_EXTENSIONS = 'getExtensions';
189
- this.REQ_CREATE_FOLDER = 'createFolder';
190
- this.REQ_DELETE_FILES = 'deleteExtFiles';
191
- this.REQ_RELOAD_EXTENSIONS = 'reloadExt';
313
+ this.REQ_GET_NEW_VERSION = 'getNewVer';
314
+ this.REQ_UPDATE_NODE = 'updNode';
192
315
 
193
316
  // Incoming responses
194
- this.RESP_LOCKED = 'lock';
195
- this.RESP_INIT = 'init';
196
- this.RESP_EXTENSIONS = 'extensions';
197
- this.RESP_FILE_ADDED = 'fileAdded';
198
- this.RESP_FILES_DELETED = 'filesDeleted';
199
- this.RESP_ERROR = 'error';
317
+ this.RESP_NEW_VERSION = 'newVer';
318
+ this.RESP_GET_ERROR = 'error1';
319
+ this.RESP_UPD_ERROR = 'error2';
200
320
  }
201
321
 
202
322
  //------------------------------------
@@ -211,7 +331,7 @@ class ExtensionManager extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseMo
211
331
  super.initialize(idData, shellController);
212
332
 
213
333
  // Initialize progress bar
214
- $('#exm-progressBar').kendoProgressBar({
334
+ $('#cup-progressBar').kendoProgressBar({
215
335
  min: 0,
216
336
  max: 100,
217
337
  value: false,
@@ -221,343 +341,118 @@ class ExtensionManager extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseMo
221
341
  }
222
342
  });
223
343
 
224
- // Add listeners to buttons
225
- $('#exm-retryBt').on('click', $.proxy(this._onRetryClick, this));
226
- $('#exm-refreshBt').on('click', $.proxy(this._onRefreshClick, this));
227
-
228
- // Initialize files list
229
- this._filesList = $('#exm-fileList').kendoTreeList({
230
- dataSource: [],
231
- resizable: true,
232
- selectable: true,
233
- columns: [
234
- {
235
- field: 'name',
236
- title: 'Name',
237
- template: kendo.template(`
238
- <div >
239
- # if (isDir) { #
240
- # if (expanded) { #
241
- <i class="fas fa-folder-open"></i>
242
- # } else { #
243
- <i class="fas fa-folder"></i>
244
- # } #
245
- # } else { #
246
- <i class="far fa-file"></i>
247
- # } #
248
-
249
- #: name #
250
-
251
- </div>
252
- <div class="file-controls flex-grow-1 text-right" data-item-id="#:id#">
253
- # if (isDir) { #
254
- <button type="button" class="k-button k-primary my-1 create-folder-bt"><i class="fas fa-folder-plus"></i></button>
255
- # if (level > 0) { #
256
- <button type="button" class="k-button k-primary my-1 upload-files-bt"><i class="fas fa-file-upload"></i></button>
257
- # } #
258
- # } #
259
-
260
- # if (level > 0 && !isProtected) { #
261
- <button type="button" class="k-button k-primary my-1 remove-file-bt"><i class="fas fa-minus-circle"></i></button>
262
- # } #
263
-
264
- # if (level == 1 && !isLib) { #
265
- <button type="button" class="k-button k-primary my-1 reload-ext-bt"><i class="fas fa-redo-alt"></i></button>
266
- # } #
267
- </div>
268
- `),
269
- },
270
- {
271
- field: 'size',
272
- title: 'Size',
273
- template: function(dataItem) {
274
- dataItem.bytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_2__["bytesToSize"]; // Pass bytesToSize utility function to template
275
- return kendo.template(`
276
- #: bytesToSize(size, 2, 'KB') #
277
- `)(dataItem);
278
- },
279
- width: 120,
280
- minScreenWidth: 576
281
- },
282
- {
283
- field: 'lastMod',
284
- title: 'Last Modified',
285
- template: kendo.template(`
286
- #: kendo.toString(new Date(lastMod), 'dd MMM yyyy HH:mm:ss') #
287
- `),
288
- width: 200,
289
- minScreenWidth: 768
290
- },
291
- ],
292
- change: $.proxy(this._onFileSelectedChange, this)
293
- }).data('kendoTreeList');
294
-
295
- //-------------------------------------------
296
-
297
- // Add listeners to catch control button clicks on rows
298
- $('#exm-fileList').on('click', '.create-folder-bt', $.proxy(this._showAddFolderModalClick, this));
299
- $('#exm-fileList').on('click', '.upload-files-bt', $.proxy(this._showUploadFilesModalClick, this));
300
- $('#exm-fileList').on('click', '.remove-file-bt', $.proxy(this._onRemoveFileClick, this));
301
- $('#exm-fileList').on('click', '.reload-ext-bt', $.proxy(this._onReloadExtClick, this));
302
-
303
- //-------------------------------------------
304
-
305
- // Initialize "add folder" modal
306
- this._addFolderModal = $('#exm-addFolderModal');
307
- this._addFolderModal.modal({
308
- backdrop: 'static',
309
- keyboard: false,
310
- show: false
311
- });
312
-
313
- // Add listener to modal hide event
314
- this._addFolderModal.on('hidden.bs.modal', $.proxy(this._onAddFolderModalHidden, this));
315
-
316
- // Add listener to Add button click
317
- $('#exm-addFolderBt').on('click', $.proxy(this._onAddFolderClick, this));
318
-
319
- // Initialize kendo validation on folder name form
320
- this._addFolderValidator = $('#exm-addFolderForm').kendoValidator({}).data('kendoValidator');
321
-
322
- //-------------------------------------------
323
-
324
- // Initialize "upload files" modal
325
- this._uploadFilesModal = $('#exm-uploadModal');
326
- this._uploadFilesModal.modal({
327
- backdrop: 'static',
328
- keyboard: false,
329
- show: false
330
- });
331
-
332
- // Initialize kendo uploader
333
- this._uploader = $('#exm-uploader').kendoUpload({
334
- multiple: true,
335
- async: {
336
- saveUrl: 'http://localhost', // This will be changed later in _onUploadStart method
337
- autoUpload: true,
338
- },
339
- directoryDrop: true,
340
- upload: $.proxy(this._onUploadStart, this),
341
- complete: $.proxy(this._onUploadEnd, this),
342
- localization: {
343
- select: 'Select files...'
344
- }
345
- }).data('kendoUpload');
346
-
347
- // Add listener to Upload button click
348
- $('#exm-clearFilesBt').on('click', $.proxy(this._onClearFilesClick, this));
349
-
350
- //-------------------------------------------
344
+ // Add listener to interface buttons
345
+ $('#cup-retryBt').on('click', $.proxy(this._onRetryClick, this));
346
+ $('#cup-refreshBt').on('click', $.proxy(this._onRefreshClick, this));
347
+ $('#cup-updateBt').on('click', $.proxy(this._onUpdateClick, this));
351
348
 
352
- // Send initialization request
353
- this.sendExtensionRequest(this.REQ_INIT);
349
+ // Request new SmartFoxServer version availability and release notes
350
+ this._requestNewVersion();
354
351
  }
355
352
 
356
353
  destroy()
357
354
  {
358
355
  // Call super method
359
356
  super.destroy();
360
-
361
- $('#exm-retryBt').off('click');
362
- $('#exm-refreshBt').off('click');
363
-
364
- $('#exm-fileList').off('click');
365
-
366
- this._addFolderModal.off('hidden.bs.modal');
367
- this._addFolderModal.modal('dispose');
368
- $('#exm-addFolderBt').off('click');
369
-
370
- this._uploadFilesModal.modal('dispose');
371
- $('#exm-clearFilesBt').off('click');
372
357
  }
373
358
 
374
359
  onExtensionCommand(command, data)
375
360
  {
376
- // Module can be enabled (no locking file exists)
377
- if (command == this.RESP_INIT)
378
- {
379
- // Retrieve file separator
380
- this._fileSeparator = data.getUtfString('sep');
381
-
382
- // Retrieve Extensions' __lib__ folder name
383
- const libFolder = data.getUtfString('lib');
384
-
385
- // Create file data source manager
386
- this._fileManager = new _managers_file_datasource_manager__WEBPACK_IMPORTED_MODULE_1__["FileDataSourceManager"](libFolder, [libFolder], this._fileSeparator);
387
-
388
- // Retrieve module id sent by the server (required because multiple modules use file uploading service)
389
- const uploadModuleId = data.getUtfString('modId');
390
-
391
- // Set file uploading target configuration
392
- this._uploadTargetConfig = {
393
- sessionToken: this.smartFox.sessionToken,
394
- host: this.smartFox.config.host,
395
- port: this.smartFox.config.port,
396
- moduleId: uploadModuleId,
397
- protocol: this.smartFox.config.useSSL ? 'https' : 'http'
398
- };
399
-
400
- // Request Extension files data to server instance
401
- this._refreshDataList();
402
- }
403
-
404
- /*
405
- * This response is returned if the file UploadsLock.txt exists in the /config folder of the server.
406
- * This is an additional security measure to avoid unwanted files to be uploaded by malicius users accessing the server
407
- * with the default credentials, in case they have not been changed by the administrator after the installation.
408
- * The file must be removed manually before accessing the Extension Manager module for the first time
409
- */
410
- else if (command == this.RESP_LOCKED)
361
+ // New SmartFoxServer version number and release notes received
362
+ if (command == this.RESP_NEW_VERSION)
411
363
  {
412
- // Show warning
413
- this._switchView('exm-locked');
414
- }
415
-
416
- // Extensions folders and files
417
- else if (command == this.RESP_EXTENSIONS)
418
- {
419
- // Retrieve Extension file list
420
- let extensionsObj = data.getSFSObject('extensions');
421
-
422
- // Initialize manager
423
- this._fileManager.init();
424
-
425
- // Add list to manager
426
- this._fileManager.addFile(extensionsObj);
427
-
428
- // Set TreeList data source
429
- this._filesList.setDataSource(this._fileManager.dataSource);
430
-
431
- // Expand first level
432
- this._filesList.expand($('#exm-fileList tbody>tr:eq(0)'));
364
+ const update = data.getUtfString('update');
433
365
 
434
- // Enable interface
435
- this._enableInterface(true);
436
-
437
- // Show module's main view
438
- this._switchView('exm-main');
439
- }
366
+ // "update" parameter is empty if node is already running the latest version of SmartFoxServer
367
+ if (update == '')
368
+ {
369
+ // Switch view
370
+ this._switchView('cup-none');
371
+ }
372
+ else
373
+ {
374
+ let updateVersion = data.getUtfString('update');
440
375
 
441
- // An error occurred while managing extension files
442
- else if (command == this.RESP_ERROR)
443
- {
444
- // Hide add folder modal
445
- this._addFolderModal.modal('hide');
376
+ // Update view
377
+ $('#cup-releaseNotes').empty();
446
378
 
447
- // Re-enable interface
448
- this._enableInterface(true);
379
+ $('#cup-currentVer').text(this.shellCtrl.getSfsVersion());
380
+ $('#cup-updateVer').text(updateVersion);
449
381
 
450
- // Show an alert
451
- this.shellCtrl.showSimpleAlert(data.getUtfString('error'));
452
- }
382
+ if (data.getBool('critical'))
383
+ $('#cup-criticalUpd').show();
384
+ else
385
+ $('#cup-criticalUpd').hide();
453
386
 
454
- // Extension folder or file added
455
- else if (command == this.RESP_FILE_ADDED)
456
- {
457
- // Get name of the user who added the file/folder
458
- const requester = data.getUtfString('user');
387
+ let includes = '';
388
+ let relNotesArr = data.getSFSArray('notes');
459
389
 
460
- // Get the object representing the file/folder being added
461
- const fileObj = data.getSFSObject('file');
390
+ for (let i = 0; i < relNotesArr.size(); i++)
391
+ {
392
+ let relNote = relNotesArr.getSFSObject(i);
393
+ let versionNum = relNote.getUtfString('update_version');
462
394
 
463
- // Get the target folder where the new file/folder should be added
464
- const parentPath = data.getUtfString('parent');
395
+ let version = $('<h4>', {class: 'mb-0'}).append($('<span>', {class: 'badge badge-secondary'}).text(versionNum));
396
+ let critical = relNote.getUtfString('is_critical') == '1' ? $('<div>', {class: 'ml-3'}).append($('<span>', {class: 'badge badge-danger'}).text("CRITICAL")) : '';
397
+ let date = $('<strong>', {class: 'ml-auto'}).text(moment__WEBPACK_IMPORTED_MODULE_1__(relNote.getUtfString('release_date')).format('DD MMM YYYY'));
465
398
 
466
- // Get the flag notifying this was a file upload
467
- const isUpload = data.getBool('isUpload');
399
+ let header = $('<div>', {class: 'd-flex align-items-center'});
400
+ header.append(version, critical, date);
468
401
 
469
- try
470
- {
471
- // Add/update item on data source
472
- const filePath = this._fileManager.addFileToParent(fileObj, parentPath);
402
+ let note = $('<pre>', {class: 'mt-3 rel-notes'}).text(relNote.getUtfString('release_notes'));
473
403
 
474
- // Refresh view
475
- this._filesList.refresh();
404
+ $('#cup-releaseNotes').append(header, note, $('<hr>'));
476
405
 
477
- if (requester == this.smartFox.mySelf.name)
478
- {
479
- // Expand parent
480
- this._filesList.expand($(`#exm-fileList .file-controls[data-item-id="${$.escapeSelector(parentPath)}"]`).closest('tr'));
481
-
482
- if (!isUpload)
406
+ if (versionNum != updateVersion)
483
407
  {
484
- // Hide modal
485
- this._addFolderModal.modal('hide');
408
+ if (includes != '')
409
+ includes += (i < relNotesArr.size() - 1) ? ', ' : ' and ';
486
410
 
487
- // Select upload file
488
- this._filesList.select($(`#exm-fileList .file-controls[data-item-id="${$.escapeSelector(filePath)}"]`).closest('tr'));
411
+ includes += 'v' + versionNum;
489
412
  }
490
-
491
- // Update selection
492
- this._onFileSelectedChange();
493
413
  }
494
- else
414
+
415
+ if (includes != '')
495
416
  {
496
- // Display notification
497
- if (!isUpload)
498
- this.shellCtrl.showNotification(`Folder created`, `Administrator ${requester} created folder: <strong>${filePath}</strong>`);
499
- else
500
- this.shellCtrl.showNotification(`File uploaded`, `Administrator ${requester} uploaded file: <strong>${filePath}</strong>`);
417
+ $('#cup-includedVer').text('Update also includes ' + includes);
418
+ $('#cup-includedVer').show();
501
419
  }
502
- }
503
- catch (e)
504
- {
505
- // This should not happen... data source is corrupted?
506
- if (requester == this.smartFox.mySelf.name)
507
- this.shellCtrl.showSimpleAlert(e.message, true);
508
- }
509
-
510
- // Enable interface
511
- this._enableInterface(true);
512
- }
513
-
514
- // Extension files deleted
515
- else if (command == this.RESP_FILES_DELETED)
516
- {
517
- // Get name of the user who deleted the file/s
518
- const requester = data.getUtfString('user');
519
-
520
- // Get the list of deleted files
521
- let files = data.getSFSArray('files');
522
-
523
- let filesArr = [];
524
-
525
- // Update data source
526
- for (let j = 0; j < files.size(); j++)
527
- {
528
- let path = files.getUtfString(j);
529
- filesArr.push(path);
420
+ else
421
+ $('#cup-includedVer').hide();
530
422
 
531
- //------------------------
423
+ // Add installed version
424
+ let version = $('<h4>', {class: 'mb-0'}).append($('<span>', {class: 'badge badge-secondary'}).text(this.shellCtrl.getSfsVersion()));
425
+ let installed = $('<strong>', {class: 'ml-3'}).text("(installed)");
532
426
 
533
- // Remove item from data source; parent item is returned
534
- let parentItem = this._fileManager.removeFile(path);
427
+ let header = $('<div>', {class: 'd-flex align-items-center'});
428
+ header.append(version, installed);
429
+ $('#cup-releaseNotes').append(header);
535
430
 
536
- // Collapse parent if the last of its children was deleted
537
- if (parentItem && !parentItem.hasChildren)
538
- this._filesList.collapse($(`#exm-fileList .file-controls[data-item-id="${$.escapeSelector(parentItem.id)}"]`).closest('tr'));
431
+ // Switch view
432
+ this._switchView('cup-main');
539
433
  }
434
+ }
540
435
 
541
- if (requester == this.smartFox.mySelf.name)
542
- {
543
- // Display notification
544
- this.shellCtrl.showNotification(`${this._selectedItem.isDir ? 'Folder' : 'File'} deleted`, `${this._selectedItem.isDir ? 'Folder' : 'File'} '${this._selectedItem.name}' deleted successfully`);
436
+ // Error retrieving available update
437
+ else if (command == this.RESP_GET_ERROR)
438
+ {
439
+ // Display error message
440
+ $('#cup-error1Msg').text(data.getUtfString('error'));
545
441
 
546
- this._selectedItem = null;
442
+ // Switch view
443
+ this._switchView('cup-error');
444
+ }
547
445
 
548
- this._enableInterface(true);
549
- }
550
- else
551
- {
552
- // Display notification
553
- this.shellCtrl.showNotification(`File deleted`, `Administrator ${requester} deleted the following file${filesArr.length > 1 ? 's' : ''}: <strong>${filesArr.join('<br> ')}</strong>`);
554
- }
446
+ // Error launching update process
447
+ else if (command == this.RESP_UPD_ERROR)
448
+ {
449
+ // Enable buttons
450
+ $('#cup-refreshBt').attr('disabled', false);
451
+ $('#cup-updateBt').attr('disabled', false);
555
452
 
556
- // Reset selection
557
- this._onFileSelectedChange();
453
+ // Display error message
454
+ $('#cup-error2Msg').text('The following error occurred when launching the server update process: ' + data.getUtfString('error'));
558
455
  }
559
-
560
- // else if ()
561
456
  }
562
457
 
563
458
  //---------------------------------
@@ -566,176 +461,44 @@ class ExtensionManager extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseMo
566
461
 
567
462
  _onRetryClick()
568
463
  {
569
- this._switchView('exm-init');
464
+ // Switch view
465
+ this._switchView('cup-loading');
570
466
 
571
- // Re-send initialization request
572
- this.sendExtensionRequest(this.REQ_INIT);
467
+ // Try again requesting new version
468
+ this._requestNewVersion();
573
469
  }
574
470
 
575
471
  _onRefreshClick()
576
472
  {
577
- this._filesList.clearSelection();
578
- this._refreshDataList();
579
- }
473
+ // Hide previous error
474
+ $('#cup-error2Msg').text('');
580
475
 
581
- _onFileSelectedChange()
582
- {
583
- // Hide control buttons on currently selected item
584
- if (this._selectedItem)
585
- $(`#exm-fileList .file-controls[data-item-id="${$.escapeSelector(this._selectedItem.id)}"]`).hide();
586
-
587
- // Get selected item
588
- let selectedRows = this._filesList.select();
589
-
590
- if (selectedRows.length > 0)
591
- {
592
- // Save ref. to selected item
593
- this._selectedItem = this._filesList.dataItem(selectedRows[0]);
476
+ // Switch view
477
+ this._switchView('cup-loading');
594
478
 
595
- // Show control buttons on new selected item
596
- $(`#exm-fileList .file-controls[data-item-id="${$.escapeSelector(this._selectedItem.id)}"]`).show();
597
- }
598
- else
599
- this._selectedItem = null;
479
+ // Request new version again
480
+ this._requestNewVersion();
600
481
  }
601
482
 
602
- _showAddFolderModalClick()
483
+ _onUpdateClick()
603
484
  {
604
- if (this._selectedItem && this._selectedItem.isDir)
605
- {
606
- this._addFolderModal.modal('show');
607
- $('#exm-folderNameIn').focus();
608
- }
485
+ // Show confirmation dialog
486
+ let message = 'Are you sure you want to proceed?<br>The server will be restarted when the update process is complete.';
487
+ this.shellCtrl.showConfirmWarning(message, $.proxy(this._onUpdateConfirmDialogConfirm, this));
609
488
  }
610
489
 
611
- _onAddFolderClick()
490
+ _onUpdateConfirmDialogConfirm()
612
491
  {
613
- // The parent folder could have been deleted while user is still typing the name of the new child folder
614
- if (!this._selectedItem)
615
- {
616
- this._addFolderModal.modal('hide');
617
- this.shellCtrl.showSimpleAlert('Unable to create folder; the parent folder doesn\'t exist.');
618
- return;
619
- }
492
+ // Disable buttons
493
+ $('#cup-refreshBt').attr('disabled', true);
494
+ $('#cup-updateBt').attr('disabled', true);
620
495
 
621
- if (this._addFolderValidator.validate())
622
- {
623
- // Disable modal interface
624
- this._enableAddFolderModal(false);
496
+ // Hide previous error
497
+ $('#cup-error2Msg').text('');
625
498
 
626
- let data = new SFS2X.SFSObject();
627
- data.putUtfString('folder', this._selectedItem.id + this._fileSeparator + $('#exm-folderNameIn').val());
628
-
629
- // Send request to server
630
- this.sendExtensionRequest(this.REQ_CREATE_FOLDER, data);
631
- }
632
- }
633
-
634
- _onAddFolderModalHidden()
635
- {
636
- $('#exm-folderNameIn').val('');
637
- this._resetAddFolderValidation();
638
-
639
- // Enable modal interface
640
- this._enableAddFolderModal(true);
641
- }
642
-
643
- _showUploadFilesModalClick()
644
- {
645
- if (this._selectedItem)
646
- this._uploadFilesModal.modal('show');
647
- }
648
-
649
- _onClearFilesClick()
650
- {
651
- this._uploader.clearAllFiles();
652
- }
653
-
654
- _onUploadStart(e)
655
- {
656
- // Disable clear button
657
- $('#exm-clearFilesBt').attr('disabled', true);
658
-
659
- // Set destination url
660
- const url = this._uploadTargetConfig.protocol + '://' + this._uploadTargetConfig.host + ':' + this._uploadTargetConfig.port + '/BlueBox/SFS2XFileUpload?sessHashId=' + this._uploadTargetConfig.sessionToken;
661
-
662
- e.sender.options.async.saveUrl = url;
663
-
664
- // Set payload
665
- const params = new FormData();
666
- params.append('__module', this._uploadTargetConfig.moduleId);
667
- params.append('__target', this._selectedItem.id);
668
-
669
- for (let f = 0; f < e.files.length; f++)
670
- params.append('files[]', e.files[f].rawFile);
671
-
672
- e.formData = params;
673
- }
674
-
675
- _onUploadEnd(e)
676
- {
677
- // Enable clear button
678
- $('#exm-clearFilesBt').attr('disabled', false);
679
- }
680
-
681
- _onFilesUploadEnd(response)
682
- {
683
- // Nothing to do: we have to wait the upload process completion to be signaled by the server through the dedicated Extension response
684
-
685
- //=================================================================
686
-
687
- // TODO Should we handle this response in some way? For some unknown reason we always get ok=false and status=0
688
- // console.log(response)
689
- // console.log(response.ok)
690
- // console.log(response.status)
691
- }
692
-
693
- _onRemoveFileClick()
694
- {
695
- if (this._selectedItem)
696
- this.shellCtrl.showConfirmWarning(`Are you sure you want to delete the selected ${this._selectedItem.isDir ? 'folder' : 'file'}?<br><br>Path: <strong>${this._selectedItem.id}</strong>`, $.proxy(this._onRemoveFileConfirm, this));
697
- }
698
-
699
- _onRemoveFileConfirm()
700
- {
701
- // Disable interface
702
- this._enableInterface(false);
703
-
704
- // Request Extension files removal
705
- // NOTE: for compatibility with older AdminTool, the file to be deleted is sent
706
- // in an array of strings, even if we can't delete more than 1 file at once in this AdminTool
707
-
708
- let files = new SFS2X.SFSArray();
709
- files.addUtfString(this._selectedItem.id);
710
-
711
- let params = new SFS2X.SFSObject();
712
- params.putSFSArray('files', files);
713
-
714
- this.sendExtensionRequest(this.REQ_DELETE_FILES, params);
715
- }
716
-
717
- _onReloadExtClick()
718
- {
719
- if (this._selectedItem)
720
- {
721
- let pathArr = this._selectedItem.id.split(this._fileSeparator);
722
-
723
- if (pathArr.length > 1)
724
- {
725
- // Request Extension reload
726
- // NOTE: for compatibility with older AdminTool, the Extension to be reloaded is sent
727
- // in an array of strings, even if we can't reload more than 1 Extension at once in this AdminTool
728
-
729
- let extToReload = [];
730
- extToReload.push(pathArr[1]);
731
-
732
- let params = new SFS2X.SFSObject();
733
- params.putUtfStringArray('extensions', extToReload);
734
-
735
- // Send request to server
736
- this.sendExtensionRequest(this.REQ_RELOAD_EXTENSIONS, params);
737
- }
738
- }
499
+ // Send request to extension
500
+ // No parameters are passed because the extension already know which version to install
501
+ this.sendExtensionRequest(this.REQ_UPDATE_NODE);
739
502
  }
740
503
 
741
504
  //------------------------------------
@@ -744,44 +507,13 @@ class ExtensionManager extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseMo
744
507
 
745
508
  _switchView(viewId)
746
509
  {
747
- document.getElementById('exm-viewstack').selectedElement = document.getElementById(viewId);
748
- }
749
-
750
- _enableInterface(enable)
751
- {
752
- $('#exm-fileList').attr('disabled', !enable);
753
- $('#exm-refreshBt').attr('disabled', !enable);
754
- }
755
-
756
- _refreshDataList()
757
- {
758
- // Disable interface
759
- this._enableInterface(false);
760
-
761
- // Send request to server
762
- this.sendExtensionRequest(this.REQ_GET_EXTENSIONS)
763
- }
764
-
765
- _resetAddFolderValidation()
766
- {
767
- this._addFolderValidator.hideMessages();
768
-
769
- // The method above doesn't remove the k-invalid classes and aria-invalid="true" attributes from inputs
770
- // Let's do it manually
771
- $('#exm-addFolderForm .k-invalid').removeClass('k-invalid');
772
- $('#exm-addFolderForm [aria-invalid="true"]').removeAttr('aria-invalid');
510
+ document.getElementById('cup-viewstack').selectedElement = document.getElementById(viewId);
773
511
  }
774
512
 
775
- _enableAddFolderModal(enable)
513
+ _requestNewVersion()
776
514
  {
777
- // Disable modal close buttons
778
- $('#exm-addFolderModal button[data-dismiss="modal"]').attr('disabled', !enable);
779
-
780
- // Disable add button
781
- $('#exm-addFolderBt').attr('disabled', !enable);
782
-
783
- // Disable fieldset
784
- $('#exm-addFolderForm').attr('disabled', !enable);
515
+ // Send request to extension
516
+ this.sendExtensionRequest(this.REQ_GET_NEW_VERSION);
785
517
  }
786
518
 
787
519
  //---------------------------------
@@ -796,4 +528,4 @@ class ExtensionManager extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseMo
796
528
  /***/ })
797
529
 
798
530
  }]);
799
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXRzL2pzL2NvcmUvbW9kdWxlcy9tb2R1bGUtNi5idW5kbGUuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9tYW5hZ2Vycy9maWxlLWRhdGFzb3VyY2UtbWFuYWdlci5qcyIsIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9tb2R1bGVzL2V4dGVuc2lvbi1tYW5hZ2VyLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjbGFzcyBGaWxlRGF0YVNvdXJjZU1hbmFnZXJcbntcblx0Y29uc3RydWN0b3IobGliRm9sZGVyLCBwcm90ZWN0ZWRGb2xkZXJzLCBmaWxlU2VwYXJhdG9yKVxuXHR7XG5cdFx0dGhpcy5fcHJvdGVjdGVkRm9sZGVycyA9IHByb3RlY3RlZEZvbGRlcnM7IC8vIEZvbGRlcnMgd2hpY2ggY2FuJ3QgYmUgZGVsZXRlZCAoYnV0IHRoZWlyIGNvbnRlbnQgY2FuKVxuXHRcdHRoaXMuX2xpYkZvbGRlciA9IGxpYkZvbGRlcjtcblx0XHR0aGlzLl9maWxlU2VwYXJhdG9yID0gZmlsZVNlcGFyYXRvcjtcblx0fVxuXG5cdGdldCBkYXRhU291cmNlKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9kYXRhU291cmNlO1xuXHR9XG5cblx0aW5pdCgpXG5cdHtcblx0XHR0aGlzLl9kYXRhU291cmNlID0gbmV3IGtlbmRvLmRhdGEuVHJlZUxpc3REYXRhU291cmNlKHtcblx0XHRcdGRhdGE6IFtdLFxuXHRcdFx0c2NoZW1hOiB7XG5cdFx0XHRcdG1vZGVsOiB7XG5cdFx0XHRcdFx0aWQ6ICdpZCcsXG5cdFx0XHRcdFx0cGFyZW50SWQ6ICdwYXJlbnRJZCcsXG5cdFx0XHRcdFx0ZXhwYW5kZWQ6IGZhbHNlXG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRzb3J0OiB7IGZpZWxkOiAnbmFtZScsIGRpcjogJ2FzYycgfVxuXHRcdH0pO1xuXHR9XG5cblx0YWRkRmlsZShmaWxlT2JqLCBwYXJlbnRMZXZlbCA9IG51bGwpXG5cdHtcblx0XHRsZXQgZmlsZSA9IHt9O1xuXG5cdFx0ZmlsZS5uYW1lID0gZmlsZU9iai5nZXRVdGZTdHJpbmcoJ25hbWUnKTtcblx0XHRmaWxlLmlzRGlyID0gZmlsZU9iai5nZXRCb29sKCdpc0RpcicpO1xuXHRcdGZpbGUubGFzdE1vZCA9IGZpbGVPYmouZ2V0TG9uZygnbGFzdE1vZCcpO1xuXHRcdGZpbGUuaXNMaWIgPSAoZmlsZS5pc0RpciAmJiBmaWxlLm5hbWUgPT0gdGhpcy5fbGliRm9sZGVyKTtcblx0XHRmaWxlLmlzUHJvdGVjdGVkID0gKGZpbGUuaXNEaXIgJiYgdGhpcy5fcHJvdGVjdGVkRm9sZGVycy5pbmRleE9mKGZpbGUubmFtZSkgPiAtMSk7XG5cdFx0ZmlsZS5zaXplID0gMDtcblxuXHRcdGlmIChwYXJlbnRMZXZlbCA9PSBudWxsKVxuXHRcdFx0ZmlsZS5sZXZlbCA9IDA7XG5cdFx0ZWxzZVxuXHRcdFx0ZmlsZS5sZXZlbCA9IHBhcmVudExldmVsICsgMTtcblxuXHRcdGlmIChmaWxlT2JqLmNvbnRhaW5zS2V5KCdwYXJlbnQnKSlcblx0XHR7XG5cdFx0XHRmaWxlLnBhcmVudElkID0gZmlsZU9iai5nZXRVdGZTdHJpbmcoJ3BhcmVudCcpO1xuXHRcdFx0ZmlsZS5pZCA9IGZpbGUucGFyZW50SWQgKyB0aGlzLl9maWxlU2VwYXJhdG9yICsgZmlsZS5uYW1lO1xuXHRcdH1cblx0XHRlbHNlXG5cdFx0e1xuXHRcdFx0ZmlsZS5wYXJlbnRJZCA9IG51bGw7XG5cdFx0XHRmaWxlLmlkID0gZmlsZS5uYW1lO1xuXHRcdH1cblxuXHRcdC8vIEFkZCBjaGlsZCBmaWxlc1xuXHRcdGlmIChmaWxlLmlzRGlyKVxuXHRcdHtcblx0XHRcdGxldCBmaWxlc0FyciA9IGZpbGVPYmouZ2V0U0ZTQXJyYXkoJ2ZpbGVzJyk7XG5cblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZmlsZXNBcnIuc2l6ZSgpOyBpKyspXG5cdFx0XHRcdGZpbGUuc2l6ZSArPSB0aGlzLmFkZEZpbGUoZmlsZXNBcnIuZ2V0U0ZTT2JqZWN0KGkpLCBmaWxlLmxldmVsKTtcblx0XHR9XG5cdFx0ZWxzZVxuXHRcdFx0ZmlsZS5zaXplID0gZmlsZU9iai5nZXRMb25nKCdzaXplJyk7XG5cblx0XHQvLyBBZGQgZmlsZSB0byBkYXRhIHNvdXJjZVxuXHRcdHRoaXMuX2RhdGFTb3VyY2UuYWRkKGZpbGUpO1xuXG5cdFx0Ly8gUmV0dXJuIGZpbGUgc2l6ZVxuXHRcdHJldHVybiBmaWxlLnNpemU7XG5cdH1cblxuXHRyZW1vdmVGaWxlKGlkKVxuXHR7XG5cdFx0bGV0IGZpbGVJdGVtID0gdGhpcy5fZGF0YVNvdXJjZS5nZXQoaWQpO1xuXG5cdFx0aWYgKGZpbGVJdGVtKVxuXHRcdHtcblx0XHRcdGlmIChmaWxlSXRlbS5wYXJlbnRJZClcblx0XHRcdHtcblx0XHRcdFx0Ly8gU3VidHJhY3Qgb2xkIHNpemUgZnJvbSBwYXJlbnQgc2l6ZVxuXHRcdFx0XHRsZXQgcGFyZW50SXRlbSA9IHRoaXMuX2RhdGFTb3VyY2UuZ2V0KGZpbGVJdGVtLnBhcmVudElkKTtcblx0XHRcdFx0dGhpcy5fdXBkYXRlUGFyZW50U2l6ZShwYXJlbnRJdGVtLCAtZmlsZUl0ZW0uc2l6ZSk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuX2RhdGFTb3VyY2UucmVtb3ZlKGZpbGVJdGVtKTtcblxuXHRcdFx0Ly8gUmV0dXJuIHBhcmVudCBpdGVtXG5cdFx0XHRpZiAoZmlsZUl0ZW0ucGFyZW50SWQpXG5cdFx0XHRcdHJldHVybiB0aGlzLl9kYXRhU291cmNlLmdldChmaWxlSXRlbS5wYXJlbnRJZCk7XG5cdFx0fVxuXHR9XG5cblx0Z2V0RmlsZUJ5SWQoaWQpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fZGF0YVNvdXJjZS5nZXQoaWQpO1xuXHR9XG5cblx0YWRkRmlsZVRvUGFyZW50KGZpbGVPYmosIHBhcmVudElkKVxuXHR7XG5cdFx0bGV0IHBhcmVudEl0ZW0gPSB0aGlzLl9kYXRhU291cmNlLmdldChwYXJlbnRJZCk7XG5cblx0XHRpZiAocGFyZW50SXRlbSAhPSBudWxsICYmIHBhcmVudEl0ZW0uaXNEaXIpXG5cdFx0e1xuXHRcdFx0Y29uc3QgZmlsZUlkID0gcGFyZW50SWQgKyB0aGlzLl9maWxlU2VwYXJhdG9yICsgZmlsZU9iai5nZXRVdGZTdHJpbmcoJ25hbWUnKTtcblx0XHRcdGxldCBmaWxlSXRlbSA9IHRoaXMuX2RhdGFTb3VyY2UuZ2V0KGZpbGVJZCk7XG5cblx0XHRcdGlmIChmaWxlSXRlbSAhPSBudWxsKVxuXHRcdFx0e1xuXHRcdFx0XHQvLyBTdWJ0cmFjdCBvbGQgc2l6ZSBmcm9tIHBhcmVudCBzaXplXG5cdFx0XHRcdHRoaXMuX3VwZGF0ZVBhcmVudFNpemUocGFyZW50SXRlbSwgLWZpbGVJdGVtLnNpemUpO1xuXG5cdFx0XHRcdC8vIFVwZGF0ZSBleGlzdGluZyBpdGVtXG5cdFx0XHRcdGZpbGVJdGVtLm5hbWUgPSBmaWxlT2JqLmdldFV0ZlN0cmluZygnbmFtZScpO1xuXHRcdFx0XHRmaWxlSXRlbS5sYXN0TW9kID0gZmlsZU9iai5nZXRMb25nKCdsYXN0TW9kJyk7XG5cdFx0XHRcdGZpbGVJdGVtLnNpemUgPSBmaWxlT2JqLmdldExvbmcoJ3NpemUnKTtcblx0XHRcdH1cblx0XHRcdGVsc2Vcblx0XHRcdHtcblx0XHRcdFx0Ly8gQWRkIG5ldyBpdGVtXG5cdFx0XHRcdHRoaXMuYWRkRmlsZShmaWxlT2JqLCBwYXJlbnRJdGVtLmxldmVsKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gVXBkYXRlIHBhcmVudCBpdGVtIHNpemVcblx0XHRcdHRoaXMuX3VwZGF0ZVBhcmVudFNpemUocGFyZW50SXRlbSwgZmlsZU9iai5nZXRMb25nKCdzaXplJykpO1xuXG5cdFx0XHRyZXR1cm4gZmlsZUlkO1xuXHRcdH1cblx0XHRlbHNlXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEFuIHVuZXhwZWN0ZWQgZXJyb3Igb2NjdXJyZWQgd2hpbGUgYWRkaW5nIGZpbGUgJyR7ZmlsZU9iai5nZXRVdGZTdHJpbmcoJ25hbWUnKX0nICh0YXJnZXQ6ICR7cGFyZW50SWR9KS5gKTtcblx0fVxuXG5cdF91cGRhdGVQYXJlbnRTaXplKHBhcmVudEl0ZW0sIHZhbHVlKVxuXHR7XG5cdFx0cGFyZW50SXRlbS5zaXplICs9IHZhbHVlO1xuXG5cdFx0aWYgKHBhcmVudEl0ZW0ucGFyZW50SWQpXG5cdFx0e1xuXHRcdFx0bGV0IGdyYW5kUGFyZW50ID0gdGhpcy5fZGF0YVNvdXJjZS5nZXQocGFyZW50SXRlbS5wYXJlbnRJZCk7XG5cdFx0XHR0aGlzLl91cGRhdGVQYXJlbnRTaXplKGdyYW5kUGFyZW50LCB2YWx1ZSk7XG5cdFx0fVxuXHR9XG59XG4iLCJpbXBvcnQge0Jhc2VNb2R1bGV9IGZyb20gJy4vYmFzZS1tb2R1bGUnO1xuaW1wb3J0IHtGaWxlRGF0YVNvdXJjZU1hbmFnZXJ9IGZyb20gJy4uL21hbmFnZXJzL2ZpbGUtZGF0YXNvdXJjZS1tYW5hZ2VyJztcbmltcG9ydCB7Ynl0ZXNUb1NpemV9IGZyb20gJy4uL3V0aWxzL3V0aWxpdGllcyc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEV4dGVuc2lvbk1hbmFnZXIgZXh0ZW5kcyBCYXNlTW9kdWxlXG57XG5cdGNvbnN0cnVjdG9yKClcblx0e1xuXHQgICAgc3VwZXIoJ2V4dGVuc2lvbk1hbicpO1xuXG5cdFx0Ly8gT3V0Z29pbmcgcmVxdWVzdHNcblx0XHR0aGlzLlJFUV9JTklUID0gJ2luaXQnO1xuXHRcdHRoaXMuUkVRX0dFVF9FWFRFTlNJT05TID0gJ2dldEV4dGVuc2lvbnMnO1xuXHRcdHRoaXMuUkVRX0NSRUFURV9GT0xERVIgPSAnY3JlYXRlRm9sZGVyJztcblx0XHR0aGlzLlJFUV9ERUxFVEVfRklMRVMgPSAnZGVsZXRlRXh0RmlsZXMnO1xuXHRcdHRoaXMuUkVRX1JFTE9BRF9FWFRFTlNJT05TID0gJ3JlbG9hZEV4dCc7XG5cblx0XHQvLyBJbmNvbWluZyByZXNwb25zZXNcblx0XHR0aGlzLlJFU1BfTE9DS0VEID0gJ2xvY2snO1xuXHRcdHRoaXMuUkVTUF9JTklUID0gJ2luaXQnO1xuXHRcdHRoaXMuUkVTUF9FWFRFTlNJT05TID0gJ2V4dGVuc2lvbnMnO1xuXHRcdHRoaXMuUkVTUF9GSUxFX0FEREVEID0gJ2ZpbGVBZGRlZCc7XG5cdFx0dGhpcy5SRVNQX0ZJTEVTX0RFTEVURUQgPSAnZmlsZXNEZWxldGVkJztcblx0XHR0aGlzLlJFU1BfRVJST1IgPSAnZXJyb3InO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8gQ09NTU9OIE1PRFVMRSBJTlRFUkZBQ0UgTUVUSE9EU1xuXHQvLyBUaGlzIG1lbWJlcnMgYXJlIHVzZWQgYnkgdGhlIG1haW4gY29udHJvbGxlclxuXHQvLyB0byBjb21tdW5pY2F0ZSB3aXRoIHRoZSBtb2R1bGUncyBjb250cm9sbGVyLlxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdGluaXRpYWxpemUoaWREYXRhLCBzaGVsbENvbnRyb2xsZXIpXG5cdHtcblx0XHQvLyBDYWxsIHN1cGVyIG1ldGhvZFxuXHRcdHN1cGVyLmluaXRpYWxpemUoaWREYXRhLCBzaGVsbENvbnRyb2xsZXIpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBwcm9ncmVzcyBiYXJcblx0XHQkKCcjZXhtLXByb2dyZXNzQmFyJykua2VuZG9Qcm9ncmVzc0Jhcih7XG5cdFx0XHRtaW46IDAsXG4gICAgICAgICAgICBtYXg6IDEwMCxcblx0XHRcdHZhbHVlOiBmYWxzZSxcbiAgICAgICAgICAgIHR5cGU6ICd2YWx1ZScsXG4gICAgICAgICAgICBhbmltYXRpb246IHtcbiAgICAgICAgICAgICAgICBkdXJhdGlvbjogNDAwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG5cdFx0Ly8gQWRkIGxpc3RlbmVycyB0byBidXR0b25zXG5cdFx0JCgnI2V4bS1yZXRyeUJ0Jykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vblJldHJ5Q2xpY2ssIHRoaXMpKTtcblx0XHQkKCcjZXhtLXJlZnJlc2hCdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25SZWZyZXNoQ2xpY2ssIHRoaXMpKTtcblxuXHRcdC8vIEluaXRpYWxpemUgZmlsZXMgbGlzdFxuXHRcdHRoaXMuX2ZpbGVzTGlzdCA9ICQoJyNleG0tZmlsZUxpc3QnKS5rZW5kb1RyZWVMaXN0KHtcbiAgICAgICAgICAgIGRhdGFTb3VyY2U6IFtdLFxuXHRcdFx0cmVzaXphYmxlOiB0cnVlLFxuXHRcdFx0c2VsZWN0YWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbHVtbnM6IFtcbiAgICAgICAgICAgICAgICB7XG5cdFx0XHRcdFx0ZmllbGQ6ICduYW1lJyxcblx0XHRcdFx0XHR0aXRsZTogJ05hbWUnLFxuXHRcdFx0XHRcdHRlbXBsYXRlOiBrZW5kby50ZW1wbGF0ZShgXG5cdFx0XHRcdFx0XHQ8ZGl2ID5cblx0XHRcdFx0XHRcdFx0IyBpZiAoaXNEaXIpIHsgI1xuXHRcdFx0XHRcdFx0XHRcdCMgaWYgKGV4cGFuZGVkKSB7ICNcblx0XHRcdFx0XHRcdFx0XHRcdDxpIGNsYXNzPVwiZmFzIGZhLWZvbGRlci1vcGVuXCI+PC9pPlxuXHRcdFx0XHRcdFx0XHRcdCMgfSBlbHNlIHsgI1xuXHRcdFx0XHRcdFx0XHRcdFx0PGkgY2xhc3M9XCJmYXMgZmEtZm9sZGVyXCI+PC9pPlxuXHRcdFx0XHRcdFx0XHRcdCMgfSAjXG5cdFx0XHRcdFx0XHRcdCMgfSBlbHNlIHsgI1xuXHRcdFx0XHRcdFx0XHRcdDxpIGNsYXNzPVwiZmFyIGZhLWZpbGVcIj48L2k+XG5cdFx0XHRcdFx0XHRcdCMgfSAjXG5cblx0XHRcdFx0XHRcdFx0IzogbmFtZSAjXG5cblx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdFx0PGRpdiBjbGFzcz1cImZpbGUtY29udHJvbHMgZmxleC1ncm93LTEgdGV4dC1yaWdodFwiIGRhdGEtaXRlbS1pZD1cIiM6aWQjXCI+XG5cdFx0XHRcdFx0XHRcdCMgaWYgKGlzRGlyKSB7ICNcblx0XHRcdFx0XHRcdFx0XHQ8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImstYnV0dG9uIGstcHJpbWFyeSBteS0xIGNyZWF0ZS1mb2xkZXItYnRcIj48aSBjbGFzcz1cImZhcyBmYS1mb2xkZXItcGx1c1wiPjwvaT48L2J1dHRvbj5cblx0XHRcdFx0XHRcdFx0XHQjIGlmIChsZXZlbCA+IDApIHsgI1xuXHRcdFx0XHRcdFx0XHRcdFx0PGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJrLWJ1dHRvbiBrLXByaW1hcnkgbXktMSB1cGxvYWQtZmlsZXMtYnRcIj48aSBjbGFzcz1cImZhcyBmYS1maWxlLXVwbG9hZFwiPjwvaT48L2J1dHRvbj5cblx0XHRcdFx0XHRcdFx0XHQjIH0gI1xuXHRcdFx0XHRcdFx0XHQjIH0gI1xuXG5cdFx0XHRcdFx0XHRcdCMgaWYgKGxldmVsID4gMCAmJiAhaXNQcm90ZWN0ZWQpIHsgI1xuXHRcdFx0XHRcdFx0XHRcdDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiay1idXR0b24gay1wcmltYXJ5IG15LTEgcmVtb3ZlLWZpbGUtYnRcIj48aSBjbGFzcz1cImZhcyBmYS1taW51cy1jaXJjbGVcIj48L2k+PC9idXR0b24+XG5cdFx0XHRcdFx0XHRcdCMgfSAjXG5cblx0XHRcdFx0XHRcdFx0IyBpZiAobGV2ZWwgPT0gMSAmJiAhaXNMaWIpIHsgI1xuXHRcdFx0XHRcdFx0XHRcdDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiay1idXR0b24gay1wcmltYXJ5IG15LTEgcmVsb2FkLWV4dC1idFwiPjxpIGNsYXNzPVwiZmFzIGZhLXJlZG8tYWx0XCI+PC9pPjwvYnV0dG9uPlxuXHRcdFx0XHRcdFx0XHQjIH0gI1xuXHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0YCksXG5cdFx0XHRcdH0sXG4gICAgICAgICAgICAgICAge1xuXHRcdFx0XHRcdGZpZWxkOiAnc2l6ZScsXG5cdFx0XHRcdFx0dGl0bGU6ICdTaXplJyxcblx0XHRcdFx0XHR0ZW1wbGF0ZTogZnVuY3Rpb24oZGF0YUl0ZW0pIHtcblx0XHRcdFx0XHRcdGRhdGFJdGVtLmJ5dGVzVG9TaXplID0gYnl0ZXNUb1NpemU7IC8vIFBhc3MgYnl0ZXNUb1NpemUgdXRpbGl0eSBmdW5jdGlvbiB0byB0ZW1wbGF0ZVxuXHRcdFx0XHRcdFx0cmV0dXJuIGtlbmRvLnRlbXBsYXRlKGBcblx0XHRcdFx0XHRcdFx0IzogYnl0ZXNUb1NpemUoc2l6ZSwgMiwgJ0tCJykgI1xuXHRcdFx0XHRcdFx0YCkoZGF0YUl0ZW0pO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0d2lkdGg6IDEyMCxcblx0XHRcdFx0XHRtaW5TY3JlZW5XaWR0aDogNTc2XG5cdFx0XHRcdH0sXG4gICAgICAgICAgICAgICAge1xuXHRcdFx0XHRcdGZpZWxkOiAnbGFzdE1vZCcsXG5cdFx0XHRcdFx0dGl0bGU6ICdMYXN0IE1vZGlmaWVkJyxcblx0XHRcdFx0XHR0ZW1wbGF0ZToga2VuZG8udGVtcGxhdGUoYFxuXHRcdFx0XHRcdFx0Izoga2VuZG8udG9TdHJpbmcobmV3IERhdGUobGFzdE1vZCksICdkZCBNTU0geXl5eSBISDptbTpzcycpICNcblx0XHRcdFx0XHRgKSxcblx0XHRcdFx0XHR3aWR0aDogMjAwLFxuXHRcdFx0XHRcdG1pblNjcmVlbldpZHRoOiA3Njhcblx0XHRcdFx0fSxcbiAgICAgICAgICAgIF0sXG5cdFx0XHRjaGFuZ2U6ICQucHJveHkodGhpcy5fb25GaWxlU2VsZWN0ZWRDaGFuZ2UsIHRoaXMpXG4gICAgICAgIH0pLmRhdGEoJ2tlbmRvVHJlZUxpc3QnKTtcblxuXHRcdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdFx0Ly8gQWRkIGxpc3RlbmVycyB0byBjYXRjaCBjb250cm9sIGJ1dHRvbiBjbGlja3Mgb24gcm93c1xuXHRcdCQoJyNleG0tZmlsZUxpc3QnKS5vbignY2xpY2snLCAnLmNyZWF0ZS1mb2xkZXItYnQnLCAkLnByb3h5KHRoaXMuX3Nob3dBZGRGb2xkZXJNb2RhbENsaWNrLCB0aGlzKSk7XG5cdFx0JCgnI2V4bS1maWxlTGlzdCcpLm9uKCdjbGljaycsICcudXBsb2FkLWZpbGVzLWJ0JywgJC5wcm94eSh0aGlzLl9zaG93VXBsb2FkRmlsZXNNb2RhbENsaWNrLCB0aGlzKSk7XG5cdFx0JCgnI2V4bS1maWxlTGlzdCcpLm9uKCdjbGljaycsICcucmVtb3ZlLWZpbGUtYnQnLCAkLnByb3h5KHRoaXMuX29uUmVtb3ZlRmlsZUNsaWNrLCB0aGlzKSk7XG5cdFx0JCgnI2V4bS1maWxlTGlzdCcpLm9uKCdjbGljaycsICcucmVsb2FkLWV4dC1idCcsICQucHJveHkodGhpcy5fb25SZWxvYWRFeHRDbGljaywgdGhpcykpO1xuXG5cdFx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0XHQvLyBJbml0aWFsaXplIFwiYWRkIGZvbGRlclwiIG1vZGFsXG5cdFx0dGhpcy5fYWRkRm9sZGVyTW9kYWwgPSAkKCcjZXhtLWFkZEZvbGRlck1vZGFsJyk7XG5cdFx0dGhpcy5fYWRkRm9sZGVyTW9kYWwubW9kYWwoe1xuXHRcdFx0YmFja2Ryb3A6ICdzdGF0aWMnLFxuXHRcdFx0a2V5Ym9hcmQ6IGZhbHNlLFxuXHRcdFx0c2hvdzogZmFsc2Vcblx0XHR9KTtcblxuXHRcdC8vIEFkZCBsaXN0ZW5lciB0byBtb2RhbCBoaWRlIGV2ZW50XG5cdFx0dGhpcy5fYWRkRm9sZGVyTW9kYWwub24oJ2hpZGRlbi5icy5tb2RhbCcsICQucHJveHkodGhpcy5fb25BZGRGb2xkZXJNb2RhbEhpZGRlbiwgdGhpcykpO1xuXG5cdFx0Ly8gQWRkIGxpc3RlbmVyIHRvIEFkZCBidXR0b24gY2xpY2tcblx0XHQkKCcjZXhtLWFkZEZvbGRlckJ0Jykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vbkFkZEZvbGRlckNsaWNrLCB0aGlzKSk7XG5cblx0XHQvLyBJbml0aWFsaXplIGtlbmRvIHZhbGlkYXRpb24gb24gZm9sZGVyIG5hbWUgZm9ybVxuXHRcdHRoaXMuX2FkZEZvbGRlclZhbGlkYXRvciA9ICQoJyNleG0tYWRkRm9sZGVyRm9ybScpLmtlbmRvVmFsaWRhdG9yKHt9KS5kYXRhKCdrZW5kb1ZhbGlkYXRvcicpO1xuXG5cdFx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0XHQvLyBJbml0aWFsaXplIFwidXBsb2FkIGZpbGVzXCIgbW9kYWxcblx0XHR0aGlzLl91cGxvYWRGaWxlc01vZGFsID0gJCgnI2V4bS11cGxvYWRNb2RhbCcpO1xuXHRcdHRoaXMuX3VwbG9hZEZpbGVzTW9kYWwubW9kYWwoe1xuXHRcdFx0YmFja2Ryb3A6ICdzdGF0aWMnLFxuXHRcdFx0a2V5Ym9hcmQ6IGZhbHNlLFxuXHRcdFx0c2hvdzogZmFsc2Vcblx0XHR9KTtcblxuXHRcdC8vIEluaXRpYWxpemUga2VuZG8gdXBsb2FkZXJcblx0XHR0aGlzLl91cGxvYWRlciA9ICQoJyNleG0tdXBsb2FkZXInKS5rZW5kb1VwbG9hZCh7XG5cdFx0XHRtdWx0aXBsZTogdHJ1ZSxcblx0XHRcdGFzeW5jOiB7XG5cdFx0XHRcdHNhdmVVcmw6ICdodHRwOi8vbG9jYWxob3N0JywgLy8gVGhpcyB3aWxsIGJlIGNoYW5nZWQgbGF0ZXIgaW4gX29uVXBsb2FkU3RhcnQgbWV0aG9kXG5cdFx0XHRcdGF1dG9VcGxvYWQ6IHRydWUsXG5cdFx0XHR9LFxuXHRcdFx0ZGlyZWN0b3J5RHJvcDogdHJ1ZSxcblx0XHRcdHVwbG9hZDogJC5wcm94eSh0aGlzLl9vblVwbG9hZFN0YXJ0LCB0aGlzKSxcblx0XHRcdGNvbXBsZXRlOiAkLnByb3h5KHRoaXMuX29uVXBsb2FkRW5kLCB0aGlzKSxcblx0XHRcdGxvY2FsaXphdGlvbjoge1xuXHRcdFx0XHRzZWxlY3Q6ICdTZWxlY3QgZmlsZXMuLi4nXG5cdFx0XHR9XG5cdFx0fSkuZGF0YSgna2VuZG9VcGxvYWQnKTtcblxuXHRcdC8vIEFkZCBsaXN0ZW5lciB0byBVcGxvYWQgYnV0dG9uIGNsaWNrXG5cdFx0JCgnI2V4bS1jbGVhckZpbGVzQnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uQ2xlYXJGaWxlc0NsaWNrLCB0aGlzKSk7XG5cblx0XHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRcdC8vIFNlbmQgaW5pdGlhbGl6YXRpb24gcmVxdWVzdFxuXHRcdHRoaXMuc2VuZEV4dGVuc2lvblJlcXVlc3QodGhpcy5SRVFfSU5JVCk7XG5cdH1cblxuXHRkZXN0cm95KClcblx0e1xuXHRcdC8vIENhbGwgc3VwZXIgbWV0aG9kXG5cdFx0c3VwZXIuZGVzdHJveSgpO1xuXG5cdFx0JCgnI2V4bS1yZXRyeUJ0Jykub2ZmKCdjbGljaycpO1xuXHRcdCQoJyNleG0tcmVmcmVzaEJ0Jykub2ZmKCdjbGljaycpO1xuXG5cdFx0JCgnI2V4bS1maWxlTGlzdCcpLm9mZignY2xpY2snKTtcblxuXHRcdHRoaXMuX2FkZEZvbGRlck1vZGFsLm9mZignaGlkZGVuLmJzLm1vZGFsJyk7XG5cdFx0dGhpcy5fYWRkRm9sZGVyTW9kYWwubW9kYWwoJ2Rpc3Bvc2UnKTtcblx0XHQkKCcjZXhtLWFkZEZvbGRlckJ0Jykub2ZmKCdjbGljaycpO1xuXG5cdFx0dGhpcy5fdXBsb2FkRmlsZXNNb2RhbC5tb2RhbCgnZGlzcG9zZScpO1xuXHRcdCQoJyNleG0tY2xlYXJGaWxlc0J0Jykub2ZmKCdjbGljaycpO1xuXHR9XG5cblx0b25FeHRlbnNpb25Db21tYW5kKGNvbW1hbmQsIGRhdGEpXG5cdHtcblx0XHQvLyBNb2R1bGUgY2FuIGJlIGVuYWJsZWQgKG5vIGxvY2tpbmcgZmlsZSBleGlzdHMpXG5cdFx0aWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0lOSVQpXG5cdFx0e1xuXHRcdFx0Ly8gUmV0cmlldmUgZmlsZSBzZXBhcmF0b3Jcblx0XHRcdHRoaXMuX2ZpbGVTZXBhcmF0b3IgPSBkYXRhLmdldFV0ZlN0cmluZygnc2VwJyk7XG5cblx0XHRcdC8vIFJldHJpZXZlIEV4dGVuc2lvbnMnIF9fbGliX18gZm9sZGVyIG5hbWVcblx0XHRcdGNvbnN0IGxpYkZvbGRlciA9IGRhdGEuZ2V0VXRmU3RyaW5nKCdsaWInKTtcblxuXHRcdFx0Ly8gQ3JlYXRlIGZpbGUgZGF0YSBzb3VyY2UgbWFuYWdlclxuXHRcdFx0dGhpcy5fZmlsZU1hbmFnZXIgPSBuZXcgRmlsZURhdGFTb3VyY2VNYW5hZ2VyKGxpYkZvbGRlciwgW2xpYkZvbGRlcl0sIHRoaXMuX2ZpbGVTZXBhcmF0b3IpO1xuXG5cdFx0XHQvLyBSZXRyaWV2ZSBtb2R1bGUgaWQgc2VudCBieSB0aGUgc2VydmVyIChyZXF1aXJlZCBiZWNhdXNlIG11bHRpcGxlIG1vZHVsZXMgdXNlIGZpbGUgdXBsb2FkaW5nIHNlcnZpY2UpXG5cdFx0XHRjb25zdCB1cGxvYWRNb2R1bGVJZCA9IGRhdGEuZ2V0VXRmU3RyaW5nKCdtb2RJZCcpO1xuXG5cdFx0XHQvLyBTZXQgZmlsZSB1cGxvYWRpbmcgdGFyZ2V0IGNvbmZpZ3VyYXRpb25cblx0XHRcdHRoaXMuX3VwbG9hZFRhcmdldENvbmZpZyA9IHtcblx0XHRcdFx0c2Vzc2lvblRva2VuOiB0aGlzLnNtYXJ0Rm94LnNlc3Npb25Ub2tlbixcblx0XHRcdFx0aG9zdDogdGhpcy5zbWFydEZveC5jb25maWcuaG9zdCxcblx0XHRcdFx0cG9ydDogdGhpcy5zbWFydEZveC5jb25maWcucG9ydCxcblx0XHRcdFx0bW9kdWxlSWQ6IHVwbG9hZE1vZHVsZUlkLFxuXHRcdFx0XHRwcm90b2NvbDogdGhpcy5zbWFydEZveC5jb25maWcudXNlU1NMID8gJ2h0dHBzJyA6ICdodHRwJ1xuXHRcdFx0fTtcblxuXHRcdFx0Ly8gUmVxdWVzdCBFeHRlbnNpb24gZmlsZXMgZGF0YSB0byBzZXJ2ZXIgaW5zdGFuY2Vcblx0XHRcdHRoaXMuX3JlZnJlc2hEYXRhTGlzdCgpO1xuXHRcdH1cblxuXHRcdC8qXG5cdFx0ICogVGhpcyByZXNwb25zZSBpcyByZXR1cm5lZCBpZiB0aGUgZmlsZSBVcGxvYWRzTG9jay50eHQgZXhpc3RzIGluIHRoZSAvY29uZmlnIGZvbGRlciBvZiB0aGUgc2VydmVyLlxuXHRcdCAqIFRoaXMgaXMgYW4gYWRkaXRpb25hbCBzZWN1cml0eSBtZWFzdXJlIHRvIGF2b2lkIHVud2FudGVkIGZpbGVzIHRvIGJlIHVwbG9hZGVkIGJ5IG1hbGljaXVzIHVzZXJzIGFjY2Vzc2luZyB0aGUgc2VydmVyXG5cdFx0ICogd2l0aCB0aGUgZGVmYXVsdCBjcmVkZW50aWFscywgaW4gY2FzZSB0aGV5IGhhdmUgbm90IGJlZW4gY2hhbmdlZCBieSB0aGUgYWRtaW5pc3RyYXRvciBhZnRlciB0aGUgaW5zdGFsbGF0aW9uLlxuXHRcdCAqIFRoZSBmaWxlIG11c3QgYmUgcmVtb3ZlZCBtYW51YWxseSBiZWZvcmUgYWNjZXNzaW5nIHRoZSBFeHRlbnNpb24gTWFuYWdlciBtb2R1bGUgZm9yIHRoZSBmaXJzdCB0aW1lXG5cdFx0ICovXG5cdFx0ZWxzZSBpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfTE9DS0VEKVxuXHRcdHtcblx0XHRcdC8vIFNob3cgd2FybmluZ1xuXHRcdFx0dGhpcy5fc3dpdGNoVmlldygnZXhtLWxvY2tlZCcpO1xuXHRcdH1cblxuXHRcdC8vIEV4dGVuc2lvbnMgZm9sZGVycyBhbmQgZmlsZXNcblx0XHRlbHNlIGlmIChjb21tYW5kID09IHRoaXMuUkVTUF9FWFRFTlNJT05TKVxuXHRcdHtcblx0XHRcdC8vIFJldHJpZXZlIEV4dGVuc2lvbiBmaWxlIGxpc3Rcblx0XHRcdGxldCBleHRlbnNpb25zT2JqID0gZGF0YS5nZXRTRlNPYmplY3QoJ2V4dGVuc2lvbnMnKTtcblxuXHRcdFx0Ly8gSW5pdGlhbGl6ZSBtYW5hZ2VyXG5cdFx0XHR0aGlzLl9maWxlTWFuYWdlci5pbml0KCk7XG5cblx0XHRcdC8vIEFkZCBsaXN0IHRvIG1hbmFnZXJcblx0XHRcdHRoaXMuX2ZpbGVNYW5hZ2VyLmFkZEZpbGUoZXh0ZW5zaW9uc09iaik7XG5cblx0XHRcdC8vIFNldCBUcmVlTGlzdCBkYXRhIHNvdXJjZVxuXHRcdFx0dGhpcy5fZmlsZXNMaXN0LnNldERhdGFTb3VyY2UodGhpcy5fZmlsZU1hbmFnZXIuZGF0YVNvdXJjZSk7XG5cblx0XHRcdC8vIEV4cGFuZCBmaXJzdCBsZXZlbFxuXHRcdFx0dGhpcy5fZmlsZXNMaXN0LmV4cGFuZCgkKCcjZXhtLWZpbGVMaXN0IHRib2R5PnRyOmVxKDApJykpO1xuXG5cdFx0XHQvLyBFbmFibGUgaW50ZXJmYWNlXG5cdFx0XHR0aGlzLl9lbmFibGVJbnRlcmZhY2UodHJ1ZSk7XG5cblx0XHRcdC8vIFNob3cgbW9kdWxlJ3MgbWFpbiB2aWV3XG5cdFx0XHR0aGlzLl9zd2l0Y2hWaWV3KCdleG0tbWFpbicpO1xuXHRcdH1cblxuXHRcdC8vIEFuIGVycm9yIG9jY3VycmVkIHdoaWxlIG1hbmFnaW5nIGV4dGVuc2lvbiBmaWxlc1xuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0VSUk9SKVxuXHRcdHtcblx0XHRcdC8vIEhpZGUgYWRkIGZvbGRlciBtb2RhbFxuXHRcdFx0dGhpcy5fYWRkRm9sZGVyTW9kYWwubW9kYWwoJ2hpZGUnKTtcblxuXHRcdFx0Ly8gUmUtZW5hYmxlIGludGVyZmFjZVxuXHRcdFx0dGhpcy5fZW5hYmxlSW50ZXJmYWNlKHRydWUpO1xuXG5cdFx0XHQvLyBTaG93IGFuIGFsZXJ0XG5cdFx0XHR0aGlzLnNoZWxsQ3RybC5zaG93U2ltcGxlQWxlcnQoZGF0YS5nZXRVdGZTdHJpbmcoJ2Vycm9yJykpO1xuXHRcdH1cblxuXHRcdC8vIEV4dGVuc2lvbiBmb2xkZXIgb3IgZmlsZSBhZGRlZFxuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0ZJTEVfQURERUQpXG5cdFx0e1xuXHRcdFx0Ly8gR2V0IG5hbWUgb2YgdGhlIHVzZXIgd2hvIGFkZGVkIHRoZSBmaWxlL2ZvbGRlclxuXHRcdFx0Y29uc3QgcmVxdWVzdGVyID0gZGF0YS5nZXRVdGZTdHJpbmcoJ3VzZXInKTtcblxuXHRcdFx0Ly8gR2V0IHRoZSBvYmplY3QgcmVwcmVzZW50aW5nIHRoZSBmaWxlL2ZvbGRlciBiZWluZyBhZGRlZFxuXHRcdFx0Y29uc3QgZmlsZU9iaiA9IGRhdGEuZ2V0U0ZTT2JqZWN0KCdmaWxlJyk7XG5cblx0XHRcdC8vIEdldCB0aGUgdGFyZ2V0IGZvbGRlciB3aGVyZSB0aGUgbmV3IGZpbGUvZm9sZGVyIHNob3VsZCBiZSBhZGRlZFxuXHRcdFx0Y29uc3QgcGFyZW50UGF0aCA9IGRhdGEuZ2V0VXRmU3RyaW5nKCdwYXJlbnQnKTtcblxuXHRcdFx0Ly8gR2V0IHRoZSBmbGFnIG5vdGlmeWluZyB0aGlzIHdhcyBhIGZpbGUgdXBsb2FkXG5cdFx0XHRjb25zdCBpc1VwbG9hZCA9IGRhdGEuZ2V0Qm9vbCgnaXNVcGxvYWQnKTtcblxuXHRcdFx0dHJ5XG5cdFx0XHR7XG5cdFx0XHRcdC8vIEFkZC91cGRhdGUgaXRlbSBvbiBkYXRhIHNvdXJjZVxuXHRcdFx0XHRjb25zdCBmaWxlUGF0aCA9IHRoaXMuX2ZpbGVNYW5hZ2VyLmFkZEZpbGVUb1BhcmVudChmaWxlT2JqLCBwYXJlbnRQYXRoKTtcblxuXHRcdFx0XHQvLyBSZWZyZXNoIHZpZXdcblx0XHRcdFx0dGhpcy5fZmlsZXNMaXN0LnJlZnJlc2goKTtcblxuXHRcdFx0XHRpZiAocmVxdWVzdGVyID09IHRoaXMuc21hcnRGb3gubXlTZWxmLm5hbWUpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHQvLyBFeHBhbmQgcGFyZW50XG5cdFx0XHRcdFx0dGhpcy5fZmlsZXNMaXN0LmV4cGFuZCgkKGAjZXhtLWZpbGVMaXN0IC5maWxlLWNvbnRyb2xzW2RhdGEtaXRlbS1pZD1cIiR7JC5lc2NhcGVTZWxlY3RvcihwYXJlbnRQYXRoKX1cIl1gKS5jbG9zZXN0KCd0cicpKTtcblxuXHRcdFx0XHRcdGlmICghaXNVcGxvYWQpXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0Ly8gSGlkZSBtb2RhbFxuXHRcdFx0XHRcdFx0dGhpcy5fYWRkRm9sZGVyTW9kYWwubW9kYWwoJ2hpZGUnKTtcblxuXHRcdFx0XHRcdFx0Ly8gU2VsZWN0IHVwbG9hZCBmaWxlXG5cdFx0XHRcdFx0XHR0aGlzLl9maWxlc0xpc3Quc2VsZWN0KCQoYCNleG0tZmlsZUxpc3QgLmZpbGUtY29udHJvbHNbZGF0YS1pdGVtLWlkPVwiJHskLmVzY2FwZVNlbGVjdG9yKGZpbGVQYXRoKX1cIl1gKS5jbG9zZXN0KCd0cicpKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBVcGRhdGUgc2VsZWN0aW9uXG5cdFx0XHRcdFx0dGhpcy5fb25GaWxlU2VsZWN0ZWRDaGFuZ2UoKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdHtcblx0XHRcdFx0XHQvLyBEaXNwbGF5IG5vdGlmaWNhdGlvblxuXHRcdFx0XHRcdGlmICghaXNVcGxvYWQpXG5cdFx0XHRcdFx0XHR0aGlzLnNoZWxsQ3RybC5zaG93Tm90aWZpY2F0aW9uKGBGb2xkZXIgY3JlYXRlZGAsIGBBZG1pbmlzdHJhdG9yICR7cmVxdWVzdGVyfSBjcmVhdGVkIGZvbGRlcjogPHN0cm9uZz4ke2ZpbGVQYXRofTwvc3Ryb25nPmApO1xuXHRcdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRcdHRoaXMuc2hlbGxDdHJsLnNob3dOb3RpZmljYXRpb24oYEZpbGUgdXBsb2FkZWRgLCBgQWRtaW5pc3RyYXRvciAke3JlcXVlc3Rlcn0gdXBsb2FkZWQgZmlsZTogPHN0cm9uZz4ke2ZpbGVQYXRofTwvc3Ryb25nPmApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRjYXRjaCAoZSlcblx0XHRcdHtcblx0XHRcdFx0Ly8gVGhpcyBzaG91bGQgbm90IGhhcHBlbi4uLiBkYXRhIHNvdXJjZSBpcyBjb3JydXB0ZWQ/XG5cdFx0XHRcdGlmIChyZXF1ZXN0ZXIgPT0gdGhpcy5zbWFydEZveC5teVNlbGYubmFtZSlcblx0XHRcdFx0XHR0aGlzLnNoZWxsQ3RybC5zaG93U2ltcGxlQWxlcnQoZS5tZXNzYWdlLCB0cnVlKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gRW5hYmxlIGludGVyZmFjZVxuXHRcdFx0dGhpcy5fZW5hYmxlSW50ZXJmYWNlKHRydWUpO1xuXHRcdH1cblxuXHRcdC8vIEV4dGVuc2lvbiBmaWxlcyBkZWxldGVkXG5cdFx0ZWxzZSBpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfRklMRVNfREVMRVRFRClcblx0XHR7XG5cdFx0XHQvLyBHZXQgbmFtZSBvZiB0aGUgdXNlciB3aG8gZGVsZXRlZCB0aGUgZmlsZS9zXG5cdFx0XHRjb25zdCByZXF1ZXN0ZXIgPSBkYXRhLmdldFV0ZlN0cmluZygndXNlcicpO1xuXG5cdFx0XHQvLyBHZXQgdGhlIGxpc3Qgb2YgZGVsZXRlZCBmaWxlc1xuXHRcdFx0bGV0IGZpbGVzID0gZGF0YS5nZXRTRlNBcnJheSgnZmlsZXMnKTtcblxuXHRcdFx0bGV0IGZpbGVzQXJyID0gW107XG5cblx0XHRcdC8vIFVwZGF0ZSBkYXRhIHNvdXJjZVxuXHRcdFx0Zm9yIChsZXQgaiA9IDA7IGogPCBmaWxlcy5zaXplKCk7IGorKylcblx0XHRcdHtcblx0XHRcdFx0bGV0IHBhdGggPSBmaWxlcy5nZXRVdGZTdHJpbmcoaik7XG5cdFx0XHRcdGZpbGVzQXJyLnB1c2gocGF0aCk7XG5cblx0XHRcdFx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRcdFx0XHQvLyBSZW1vdmUgaXRlbSBmcm9tIGRhdGEgc291cmNlOyBwYXJlbnQgaXRlbSBpcyByZXR1cm5lZFxuXHRcdFx0XHRsZXQgcGFyZW50SXRlbSA9IHRoaXMuX2ZpbGVNYW5hZ2VyLnJlbW92ZUZpbGUocGF0aCk7XG5cblx0XHRcdFx0Ly8gQ29sbGFwc2UgcGFyZW50IGlmIHRoZSBsYXN0IG9mIGl0cyBjaGlsZHJlbiB3YXMgZGVsZXRlZFxuXHRcdFx0XHRpZiAocGFyZW50SXRlbSAmJiAhcGFyZW50SXRlbS5oYXNDaGlsZHJlbilcblx0XHRcdFx0XHR0aGlzLl9maWxlc0xpc3QuY29sbGFwc2UoJChgI2V4bS1maWxlTGlzdCAuZmlsZS1jb250cm9sc1tkYXRhLWl0ZW0taWQ9XCIkeyQuZXNjYXBlU2VsZWN0b3IocGFyZW50SXRlbS5pZCl9XCJdYCkuY2xvc2VzdCgndHInKSk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChyZXF1ZXN0ZXIgPT0gdGhpcy5zbWFydEZveC5teVNlbGYubmFtZSlcblx0XHRcdHtcblx0XHRcdFx0Ly8gRGlzcGxheSBub3RpZmljYXRpb25cblx0XHRcdFx0dGhpcy5zaGVsbEN0cmwuc2hvd05vdGlmaWNhdGlvbihgJHt0aGlzLl9zZWxlY3RlZEl0ZW0uaXNEaXIgPyAnRm9sZGVyJyA6ICdGaWxlJ30gZGVsZXRlZGAsIGAke3RoaXMuX3NlbGVjdGVkSXRlbS5pc0RpciA/ICdGb2xkZXInIDogJ0ZpbGUnfSAnJHt0aGlzLl9zZWxlY3RlZEl0ZW0ubmFtZX0nIGRlbGV0ZWQgc3VjY2Vzc2Z1bGx5YCk7XG5cblx0XHRcdFx0dGhpcy5fc2VsZWN0ZWRJdGVtID0gbnVsbDtcblxuXHRcdFx0XHR0aGlzLl9lbmFibGVJbnRlcmZhY2UodHJ1ZSk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlXG5cdFx0XHR7XG5cdFx0XHRcdC8vIERpc3BsYXkgbm90aWZpY2F0aW9uXG5cdFx0XHRcdHRoaXMuc2hlbGxDdHJsLnNob3dOb3RpZmljYXRpb24oYEZpbGUgZGVsZXRlZGAsIGBBZG1pbmlzdHJhdG9yICR7cmVxdWVzdGVyfSBkZWxldGVkIHRoZSBmb2xsb3dpbmcgZmlsZSR7ZmlsZXNBcnIubGVuZ3RoID4gMSA/ICdzJyA6ICcnfTogPHN0cm9uZz4ke2ZpbGVzQXJyLmpvaW4oJzxicj4gJyl9PC9zdHJvbmc+YCk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJlc2V0IHNlbGVjdGlvblxuXHRcdFx0dGhpcy5fb25GaWxlU2VsZWN0ZWRDaGFuZ2UoKTtcblx0XHR9XG5cblx0XHQvLyBlbHNlIGlmICgpXG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLyBVSSBFVkVOVCBMSVNURU5FUlNcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRfb25SZXRyeUNsaWNrKClcblx0e1xuXHRcdHRoaXMuX3N3aXRjaFZpZXcoJ2V4bS1pbml0Jyk7XG5cblx0XHQvLyBSZS1zZW5kIGluaXRpYWxpemF0aW9uIHJlcXVlc3Rcblx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX0lOSVQpO1xuXHR9XG5cblx0X29uUmVmcmVzaENsaWNrKClcblx0e1xuXHRcdHRoaXMuX2ZpbGVzTGlzdC5jbGVhclNlbGVjdGlvbigpO1xuXHRcdHRoaXMuX3JlZnJlc2hEYXRhTGlzdCgpO1xuXHR9XG5cblx0X29uRmlsZVNlbGVjdGVkQ2hhbmdlKClcblx0e1xuXHRcdC8vIEhpZGUgY29udHJvbCBidXR0b25zIG9uIGN1cnJlbnRseSBzZWxlY3RlZCBpdGVtXG5cdFx0aWYgKHRoaXMuX3NlbGVjdGVkSXRlbSlcblx0XHRcdCQoYCNleG0tZmlsZUxpc3QgLmZpbGUtY29udHJvbHNbZGF0YS1pdGVtLWlkPVwiJHskLmVzY2FwZVNlbGVjdG9yKHRoaXMuX3NlbGVjdGVkSXRlbS5pZCl9XCJdYCkuaGlkZSgpO1xuXG5cdFx0Ly8gR2V0IHNlbGVjdGVkIGl0ZW1cblx0XHRsZXQgc2VsZWN0ZWRSb3dzID0gdGhpcy5fZmlsZXNMaXN0LnNlbGVjdCgpO1xuXG5cdFx0aWYgKHNlbGVjdGVkUm93cy5sZW5ndGggPiAwKVxuXHRcdHtcblx0XHRcdC8vIFNhdmUgcmVmLiB0byBzZWxlY3RlZCBpdGVtXG5cdFx0XHR0aGlzLl9zZWxlY3RlZEl0ZW0gPSB0aGlzLl9maWxlc0xpc3QuZGF0YUl0ZW0oc2VsZWN0ZWRSb3dzWzBdKTtcblxuXHRcdFx0Ly8gU2hvdyBjb250cm9sIGJ1dHRvbnMgb24gbmV3IHNlbGVjdGVkIGl0ZW1cblx0XHRcdCQoYCNleG0tZmlsZUxpc3QgLmZpbGUtY29udHJvbHNbZGF0YS1pdGVtLWlkPVwiJHskLmVzY2FwZVNlbGVjdG9yKHRoaXMuX3NlbGVjdGVkSXRlbS5pZCl9XCJdYCkuc2hvdygpO1xuXHRcdH1cblx0XHRlbHNlXG5cdFx0XHR0aGlzLl9zZWxlY3RlZEl0ZW0gPSBudWxsO1xuXHR9XG5cblx0X3Nob3dBZGRGb2xkZXJNb2RhbENsaWNrKClcblx0e1xuXHRcdGlmICh0aGlzLl9zZWxlY3RlZEl0ZW0gJiYgdGhpcy5fc2VsZWN0ZWRJdGVtLmlzRGlyKVxuXHRcdHtcblx0XHRcdHRoaXMuX2FkZEZvbGRlck1vZGFsLm1vZGFsKCdzaG93Jyk7XG5cdFx0XHQkKCcjZXhtLWZvbGRlck5hbWVJbicpLmZvY3VzKCk7XG5cdFx0fVxuXHR9XG5cblx0X29uQWRkRm9sZGVyQ2xpY2soKVxuXHR7XG5cdFx0Ly8gVGhlIHBhcmVudCBmb2xkZXIgY291bGQgaGF2ZSBiZWVuIGRlbGV0ZWQgd2hpbGUgdXNlciBpcyBzdGlsbCB0eXBpbmcgdGhlIG5hbWUgb2YgdGhlIG5ldyBjaGlsZCBmb2xkZXJcblx0XHRpZiAoIXRoaXMuX3NlbGVjdGVkSXRlbSlcblx0XHR7XG5cdFx0XHR0aGlzLl9hZGRGb2xkZXJNb2RhbC5tb2RhbCgnaGlkZScpO1xuXHRcdFx0dGhpcy5zaGVsbEN0cmwuc2hvd1NpbXBsZUFsZXJ0KCdVbmFibGUgdG8gY3JlYXRlIGZvbGRlcjsgdGhlIHBhcmVudCBmb2xkZXIgZG9lc25cXCd0IGV4aXN0LicpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLl9hZGRGb2xkZXJWYWxpZGF0b3IudmFsaWRhdGUoKSlcblx0XHR7XG5cdFx0XHQvLyBEaXNhYmxlIG1vZGFsIGludGVyZmFjZVxuXHRcdFx0dGhpcy5fZW5hYmxlQWRkRm9sZGVyTW9kYWwoZmFsc2UpO1xuXG5cdFx0XHRsZXQgZGF0YSA9IG5ldyBTRlMyWC5TRlNPYmplY3QoKTtcblx0XHRcdGRhdGEucHV0VXRmU3RyaW5nKCdmb2xkZXInLCB0aGlzLl9zZWxlY3RlZEl0ZW0uaWQgKyB0aGlzLl9maWxlU2VwYXJhdG9yICsgJCgnI2V4bS1mb2xkZXJOYW1lSW4nKS52YWwoKSk7XG5cblx0XHRcdC8vIFNlbmQgcmVxdWVzdCB0byBzZXJ2ZXJcblx0XHRcdHRoaXMuc2VuZEV4dGVuc2lvblJlcXVlc3QodGhpcy5SRVFfQ1JFQVRFX0ZPTERFUiwgZGF0YSk7XG5cdFx0fVxuXHR9XG5cblx0X29uQWRkRm9sZGVyTW9kYWxIaWRkZW4oKVxuXHR7XG5cdFx0JCgnI2V4bS1mb2xkZXJOYW1lSW4nKS52YWwoJycpO1xuXHRcdHRoaXMuX3Jlc2V0QWRkRm9sZGVyVmFsaWRhdGlvbigpO1xuXG5cdFx0Ly8gRW5hYmxlIG1vZGFsIGludGVyZmFjZVxuXHRcdHRoaXMuX2VuYWJsZUFkZEZvbGRlck1vZGFsKHRydWUpO1xuXHR9XG5cblx0X3Nob3dVcGxvYWRGaWxlc01vZGFsQ2xpY2soKVxuXHR7XG5cdFx0aWYgKHRoaXMuX3NlbGVjdGVkSXRlbSlcblx0XHRcdHRoaXMuX3VwbG9hZEZpbGVzTW9kYWwubW9kYWwoJ3Nob3cnKTtcblx0fVxuXG5cdF9vbkNsZWFyRmlsZXNDbGljaygpXG5cdHtcblx0XHR0aGlzLl91cGxvYWRlci5jbGVhckFsbEZpbGVzKCk7XG5cdH1cblxuXHRfb25VcGxvYWRTdGFydChlKVxuXHR7XG5cdFx0Ly8gRGlzYWJsZSBjbGVhciBidXR0b25cblx0XHQkKCcjZXhtLWNsZWFyRmlsZXNCdCcpLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cblx0XHQvLyBTZXQgZGVzdGluYXRpb24gdXJsXG5cdFx0Y29uc3QgdXJsID0gdGhpcy5fdXBsb2FkVGFyZ2V0Q29uZmlnLnByb3RvY29sICsgJzovLycgKyB0aGlzLl91cGxvYWRUYXJnZXRDb25maWcuaG9zdCArICc6JyArIHRoaXMuX3VwbG9hZFRhcmdldENvbmZpZy5wb3J0ICsgJy9CbHVlQm94L1NGUzJYRmlsZVVwbG9hZD9zZXNzSGFzaElkPScgKyB0aGlzLl91cGxvYWRUYXJnZXRDb25maWcuc2Vzc2lvblRva2VuO1xuXHRcdFxuXHRcdGUuc2VuZGVyLm9wdGlvbnMuYXN5bmMuc2F2ZVVybCA9IHVybDtcblxuXHRcdC8vIFNldCBwYXlsb2FkXG5cdFx0Y29uc3QgcGFyYW1zID0gbmV3IEZvcm1EYXRhKCk7XG5cdFx0cGFyYW1zLmFwcGVuZCgnX19tb2R1bGUnLCB0aGlzLl91cGxvYWRUYXJnZXRDb25maWcubW9kdWxlSWQpO1xuXHRcdHBhcmFtcy5hcHBlbmQoJ19fdGFyZ2V0JywgdGhpcy5fc2VsZWN0ZWRJdGVtLmlkKTtcblxuXHRcdGZvciAobGV0IGYgPSAwOyBmIDwgZS5maWxlcy5sZW5ndGg7IGYrKylcblx0XHRcdHBhcmFtcy5hcHBlbmQoJ2ZpbGVzW10nLCBlLmZpbGVzW2ZdLnJhd0ZpbGUpO1xuXG5cdFx0ZS5mb3JtRGF0YSA9IHBhcmFtcztcblx0fVxuXG5cdF9vblVwbG9hZEVuZChlKVxuXHR7XG5cdFx0Ly8gRW5hYmxlIGNsZWFyIGJ1dHRvblxuXHRcdCQoJyNleG0tY2xlYXJGaWxlc0J0JykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cdH1cblxuXHRfb25GaWxlc1VwbG9hZEVuZChyZXNwb25zZSlcblx0e1xuXHRcdC8vIE5vdGhpbmcgdG8gZG86IHdlIGhhdmUgdG8gd2FpdCB0aGUgdXBsb2FkIHByb2Nlc3MgY29tcGxldGlvbiB0byBiZSBzaWduYWxlZCBieSB0aGUgc2VydmVyIHRocm91Z2ggdGhlIGRlZGljYXRlZCBFeHRlbnNpb24gcmVzcG9uc2VcblxuXHRcdC8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuXHRcdC8vIFRPRE8gU2hvdWxkIHdlIGhhbmRsZSB0aGlzIHJlc3BvbnNlIGluIHNvbWUgd2F5PyBGb3Igc29tZSB1bmtub3duIHJlYXNvbiB3ZSBhbHdheXMgZ2V0IG9rPWZhbHNlIGFuZCBzdGF0dXM9MFxuXHRcdC8vIGNvbnNvbGUubG9nKHJlc3BvbnNlKVxuXHRcdC8vIGNvbnNvbGUubG9nKHJlc3BvbnNlLm9rKVxuXHRcdC8vIGNvbnNvbGUubG9nKHJlc3BvbnNlLnN0YXR1cylcblx0fVxuXG5cdF9vblJlbW92ZUZpbGVDbGljaygpXG5cdHtcblx0XHRpZiAodGhpcy5fc2VsZWN0ZWRJdGVtKVxuXHRcdFx0dGhpcy5zaGVsbEN0cmwuc2hvd0NvbmZpcm1XYXJuaW5nKGBBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gZGVsZXRlIHRoZSBzZWxlY3RlZCAke3RoaXMuX3NlbGVjdGVkSXRlbS5pc0RpciA/ICdmb2xkZXInIDogJ2ZpbGUnfT88YnI+PGJyPlBhdGg6IDxzdHJvbmc+JHt0aGlzLl9zZWxlY3RlZEl0ZW0uaWR9PC9zdHJvbmc+YCwgJC5wcm94eSh0aGlzLl9vblJlbW92ZUZpbGVDb25maXJtLCB0aGlzKSk7XG5cdH1cblxuXHRfb25SZW1vdmVGaWxlQ29uZmlybSgpXG5cdHtcblx0XHQvLyBEaXNhYmxlIGludGVyZmFjZVxuXHRcdHRoaXMuX2VuYWJsZUludGVyZmFjZShmYWxzZSk7XG5cblx0XHQvLyBSZXF1ZXN0IEV4dGVuc2lvbiBmaWxlcyByZW1vdmFsXG5cdFx0Ly8gTk9URTogZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBvbGRlciBBZG1pblRvb2wsIHRoZSBmaWxlIHRvIGJlIGRlbGV0ZWQgaXMgc2VudFxuXHRcdC8vIGluIGFuIGFycmF5IG9mIHN0cmluZ3MsIGV2ZW4gaWYgd2UgY2FuJ3QgZGVsZXRlIG1vcmUgdGhhbiAxIGZpbGUgYXQgb25jZSBpbiB0aGlzIEFkbWluVG9vbFxuXG5cdFx0bGV0IGZpbGVzID0gbmV3IFNGUzJYLlNGU0FycmF5KCk7XG5cdFx0ZmlsZXMuYWRkVXRmU3RyaW5nKHRoaXMuX3NlbGVjdGVkSXRlbS5pZCk7XG5cblx0XHRsZXQgcGFyYW1zID0gbmV3IFNGUzJYLlNGU09iamVjdCgpO1xuXHRcdHBhcmFtcy5wdXRTRlNBcnJheSgnZmlsZXMnLCBmaWxlcyk7XG5cblx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX0RFTEVURV9GSUxFUywgcGFyYW1zKTtcblx0fVxuXG5cdF9vblJlbG9hZEV4dENsaWNrKClcblx0e1xuXHRcdGlmICh0aGlzLl9zZWxlY3RlZEl0ZW0pXG5cdFx0e1xuXHRcdFx0bGV0IHBhdGhBcnIgPSB0aGlzLl9zZWxlY3RlZEl0ZW0uaWQuc3BsaXQodGhpcy5fZmlsZVNlcGFyYXRvcik7XG5cblx0XHRcdGlmIChwYXRoQXJyLmxlbmd0aCA+IDEpXG5cdFx0XHR7XG5cdFx0XHRcdC8vIFJlcXVlc3QgRXh0ZW5zaW9uIHJlbG9hZFxuXHRcdFx0XHQvLyBOT1RFOiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG9sZGVyIEFkbWluVG9vbCwgdGhlIEV4dGVuc2lvbiB0byBiZSByZWxvYWRlZCBpcyBzZW50XG5cdFx0XHRcdC8vIGluIGFuIGFycmF5IG9mIHN0cmluZ3MsIGV2ZW4gaWYgd2UgY2FuJ3QgcmVsb2FkIG1vcmUgdGhhbiAxIEV4dGVuc2lvbiBhdCBvbmNlIGluIHRoaXMgQWRtaW5Ub29sXG5cblx0XHRcdFx0bGV0IGV4dFRvUmVsb2FkID0gW107XG5cdFx0XHRcdGV4dFRvUmVsb2FkLnB1c2gocGF0aEFyclsxXSk7XG5cblx0XHRcdFx0bGV0IHBhcmFtcyA9IG5ldyBTRlMyWC5TRlNPYmplY3QoKTtcblx0XHRcdFx0cGFyYW1zLnB1dFV0ZlN0cmluZ0FycmF5KCdleHRlbnNpb25zJywgZXh0VG9SZWxvYWQpO1xuXG5cdFx0XHRcdC8vIFNlbmQgcmVxdWVzdCB0byBzZXJ2ZXJcblx0XHRcdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9SRUxPQURfRVhURU5TSU9OUywgcGFyYW1zKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLyBQUklWQVRFIE1FVEhPRFNcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRfc3dpdGNoVmlldyh2aWV3SWQpXG5cdHtcblx0XHRkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZXhtLXZpZXdzdGFjaycpLnNlbGVjdGVkRWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHZpZXdJZCk7XG5cdH1cblxuXHRfZW5hYmxlSW50ZXJmYWNlKGVuYWJsZSlcblx0e1xuXHRcdCQoJyNleG0tZmlsZUxpc3QnKS5hdHRyKCdkaXNhYmxlZCcsICFlbmFibGUpO1xuXHRcdCQoJyNleG0tcmVmcmVzaEJ0JykuYXR0cignZGlzYWJsZWQnLCAhZW5hYmxlKTtcblx0fVxuXG5cdF9yZWZyZXNoRGF0YUxpc3QoKVxuXHR7XG5cdFx0Ly8gRGlzYWJsZSBpbnRlcmZhY2Vcblx0XHR0aGlzLl9lbmFibGVJbnRlcmZhY2UoZmFsc2UpO1xuXG5cdFx0Ly8gU2VuZCByZXF1ZXN0IHRvIHNlcnZlclxuXHRcdHRoaXMuc2VuZEV4dGVuc2lvblJlcXVlc3QodGhpcy5SRVFfR0VUX0VYVEVOU0lPTlMpXG5cdH1cblxuXHRfcmVzZXRBZGRGb2xkZXJWYWxpZGF0aW9uKClcblx0e1xuXHRcdHRoaXMuX2FkZEZvbGRlclZhbGlkYXRvci5oaWRlTWVzc2FnZXMoKTtcblxuXHRcdC8vIFRoZSBtZXRob2QgYWJvdmUgZG9lc24ndCByZW1vdmUgdGhlIGstaW52YWxpZCBjbGFzc2VzIGFuZCBhcmlhLWludmFsaWQ9XCJ0cnVlXCIgYXR0cmlidXRlcyBmcm9tIGlucHV0c1xuXHRcdC8vIExldCdzIGRvIGl0IG1hbnVhbGx5XG5cdFx0JCgnI2V4bS1hZGRGb2xkZXJGb3JtIC5rLWludmFsaWQnKS5yZW1vdmVDbGFzcygnay1pbnZhbGlkJyk7XG5cdFx0JCgnI2V4bS1hZGRGb2xkZXJGb3JtIFthcmlhLWludmFsaWQ9XCJ0cnVlXCJdJykucmVtb3ZlQXR0cignYXJpYS1pbnZhbGlkJyk7XG5cdH1cblxuXHRfZW5hYmxlQWRkRm9sZGVyTW9kYWwoZW5hYmxlKVxuXHR7XG5cdFx0Ly8gRGlzYWJsZSBtb2RhbCBjbG9zZSBidXR0b25zXG5cdFx0JCgnI2V4bS1hZGRGb2xkZXJNb2RhbCBidXR0b25bZGF0YS1kaXNtaXNzPVwibW9kYWxcIl0nKS5hdHRyKCdkaXNhYmxlZCcsICFlbmFibGUpO1xuXG5cdFx0Ly8gRGlzYWJsZSBhZGQgYnV0dG9uXG5cdFx0JCgnI2V4bS1hZGRGb2xkZXJCdCcpLmF0dHIoJ2Rpc2FibGVkJywgIWVuYWJsZSk7XG5cblx0XHQvLyBEaXNhYmxlIGZpZWxkc2V0XG5cdFx0JCgnI2V4bS1hZGRGb2xkZXJGb3JtJykuYXR0cignZGlzYWJsZWQnLCAhZW5hYmxlKTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIFBSSVZBVEUgR0VUVEVSU1xuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUNoSkE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBIiwic291cmNlUm9vdCI6IiJ9
531
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXRzL2pzL2NvcmUvbW9kdWxlcy9tb2R1bGUtNi5idW5kbGUuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9tb2R1bGVzL2NsdXN0ZXItdXBkYXRlci5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0Jhc2VNb2R1bGV9IGZyb20gJy4vYmFzZS1tb2R1bGUnO1xuaW1wb3J0ICogYXMgbW9tZW50IGZyb20gJ21vbWVudCc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENsdXN0ZXJVcGRhdGVyIGV4dGVuZHMgQmFzZU1vZHVsZVxue1xuXHRjb25zdHJ1Y3RvcigpXG5cdHtcblx0ICAgIHN1cGVyKCdjbHVzdGVyVXBkJyk7XG5cblx0XHQvLyBPdXRnb2luZyByZXF1ZXN0c1xuXHRcdHRoaXMuUkVRX0dFVF9ORVdfVkVSU0lPTiA9ICdnZXROZXdWZXInO1xuXHRcdHRoaXMuUkVRX1VQREFURV9OT0RFID0gJ3VwZE5vZGUnO1xuXG5cdFx0Ly8gSW5jb21pbmcgcmVzcG9uc2VzXG5cdFx0dGhpcy5SRVNQX05FV19WRVJTSU9OID0gJ25ld1Zlcic7XG5cdFx0dGhpcy5SRVNQX0dFVF9FUlJPUiA9ICdlcnJvcjEnO1xuXHRcdHRoaXMuUkVTUF9VUERfRVJST1IgPSAnZXJyb3IyJztcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIENPTU1PTiBNT0RVTEUgSU5URVJGQUNFIE1FVEhPRFNcblx0Ly8gVGhpcyBtZW1iZXJzIGFyZSB1c2VkIGJ5IHRoZSBtYWluIGNvbnRyb2xsZXJcblx0Ly8gdG8gY29tbXVuaWNhdGUgd2l0aCB0aGUgbW9kdWxlJ3MgY29udHJvbGxlci5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRpbml0aWFsaXplKGlkRGF0YSwgc2hlbGxDb250cm9sbGVyKVxuXHR7XG5cdFx0Ly8gQ2FsbCBzdXBlciBtZXRob2Rcblx0XHRzdXBlci5pbml0aWFsaXplKGlkRGF0YSwgc2hlbGxDb250cm9sbGVyKTtcblxuXHRcdC8vIEluaXRpYWxpemUgcHJvZ3Jlc3MgYmFyXG5cdFx0JCgnI2N1cC1wcm9ncmVzc0JhcicpLmtlbmRvUHJvZ3Jlc3NCYXIoe1xuXHRcdFx0bWluOiAwLFxuICAgICAgICAgICAgbWF4OiAxMDAsXG5cdFx0XHR2YWx1ZTogZmFsc2UsXG4gICAgICAgICAgICB0eXBlOiAndmFsdWUnLFxuICAgICAgICAgICAgYW5pbWF0aW9uOiB7XG4gICAgICAgICAgICAgICAgZHVyYXRpb246IDQwMFxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuXHRcdC8vIEFkZCBsaXN0ZW5lciB0byBpbnRlcmZhY2UgYnV0dG9uc1xuXHRcdCQoJyNjdXAtcmV0cnlCdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25SZXRyeUNsaWNrLCB0aGlzKSk7XG5cdFx0JCgnI2N1cC1yZWZyZXNoQnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uUmVmcmVzaENsaWNrLCB0aGlzKSk7XG5cdFx0JCgnI2N1cC11cGRhdGVCdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25VcGRhdGVDbGljaywgdGhpcykpO1xuXG5cdFx0Ly8gUmVxdWVzdCBuZXcgU21hcnRGb3hTZXJ2ZXIgdmVyc2lvbiBhdmFpbGFiaWxpdHkgYW5kIHJlbGVhc2Ugbm90ZXNcblx0XHR0aGlzLl9yZXF1ZXN0TmV3VmVyc2lvbigpO1xuXHR9XG5cblx0ZGVzdHJveSgpXG5cdHtcblx0XHQvLyBDYWxsIHN1cGVyIG1ldGhvZFxuXHRcdHN1cGVyLmRlc3Ryb3koKTtcblx0fVxuXG5cdG9uRXh0ZW5zaW9uQ29tbWFuZChjb21tYW5kLCBkYXRhKVxuXHR7XG5cdFx0Ly8gTmV3IFNtYXJ0Rm94U2VydmVyIHZlcnNpb24gbnVtYmVyIGFuZCByZWxlYXNlIG5vdGVzIHJlY2VpdmVkXG5cdFx0aWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX05FV19WRVJTSU9OKVxuXHRcdHtcblx0XHRcdGNvbnN0IHVwZGF0ZSA9IGRhdGEuZ2V0VXRmU3RyaW5nKCd1cGRhdGUnKTtcblxuXHRcdFx0Ly8gXCJ1cGRhdGVcIiBwYXJhbWV0ZXIgaXMgZW1wdHkgaWYgbm9kZSBpcyBhbHJlYWR5IHJ1bm5pbmcgdGhlIGxhdGVzdCB2ZXJzaW9uIG9mIFNtYXJ0Rm94U2VydmVyXG5cdFx0XHRpZiAodXBkYXRlID09ICcnKVxuXHRcdFx0e1xuXHRcdFx0XHQvLyBTd2l0Y2ggdmlld1xuXHRcdFx0XHR0aGlzLl9zd2l0Y2hWaWV3KCdjdXAtbm9uZScpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZVxuXHRcdFx0e1xuXHRcdFx0XHRsZXQgdXBkYXRlVmVyc2lvbiA9IGRhdGEuZ2V0VXRmU3RyaW5nKCd1cGRhdGUnKTtcblxuXHRcdFx0XHQvLyBVcGRhdGUgdmlld1xuXHRcdFx0XHQkKCcjY3VwLXJlbGVhc2VOb3RlcycpLmVtcHR5KCk7XG5cblx0XHRcdFx0JCgnI2N1cC1jdXJyZW50VmVyJykudGV4dCh0aGlzLnNoZWxsQ3RybC5nZXRTZnNWZXJzaW9uKCkpO1xuXHRcdFx0XHQkKCcjY3VwLXVwZGF0ZVZlcicpLnRleHQodXBkYXRlVmVyc2lvbik7XG5cblx0XHRcdFx0aWYgKGRhdGEuZ2V0Qm9vbCgnY3JpdGljYWwnKSlcblx0XHRcdFx0XHQkKCcjY3VwLWNyaXRpY2FsVXBkJykuc2hvdygpO1xuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0JCgnI2N1cC1jcml0aWNhbFVwZCcpLmhpZGUoKTtcblxuXHRcdFx0XHRsZXQgaW5jbHVkZXMgPSAnJztcblx0XHRcdFx0bGV0IHJlbE5vdGVzQXJyID0gZGF0YS5nZXRTRlNBcnJheSgnbm90ZXMnKTtcblxuXHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHJlbE5vdGVzQXJyLnNpemUoKTsgaSsrKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGV0IHJlbE5vdGUgPSByZWxOb3Rlc0Fyci5nZXRTRlNPYmplY3QoaSk7XG5cdFx0XHRcdFx0bGV0IHZlcnNpb25OdW0gPSByZWxOb3RlLmdldFV0ZlN0cmluZygndXBkYXRlX3ZlcnNpb24nKTtcblxuXHRcdFx0XHRcdGxldCB2ZXJzaW9uID0gJCgnPGg0PicsIHtjbGFzczogJ21iLTAnfSkuYXBwZW5kKCQoJzxzcGFuPicsIHtjbGFzczogJ2JhZGdlIGJhZGdlLXNlY29uZGFyeSd9KS50ZXh0KHZlcnNpb25OdW0pKTtcblx0XHRcdFx0XHRsZXQgY3JpdGljYWwgPSByZWxOb3RlLmdldFV0ZlN0cmluZygnaXNfY3JpdGljYWwnKSA9PSAnMScgPyAkKCc8ZGl2PicsIHtjbGFzczogJ21sLTMnfSkuYXBwZW5kKCQoJzxzcGFuPicsIHtjbGFzczogJ2JhZGdlIGJhZGdlLWRhbmdlcid9KS50ZXh0KFwiQ1JJVElDQUxcIikpIDogJyc7XG5cdFx0XHRcdFx0bGV0IGRhdGUgPSAkKCc8c3Ryb25nPicsIHtjbGFzczogJ21sLWF1dG8nfSkudGV4dChtb21lbnQocmVsTm90ZS5nZXRVdGZTdHJpbmcoJ3JlbGVhc2VfZGF0ZScpKS5mb3JtYXQoJ0REIE1NTSBZWVlZJykpO1xuXG5cdFx0XHRcdFx0bGV0IGhlYWRlciA9ICQoJzxkaXY+Jywge2NsYXNzOiAnZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlcid9KTtcblx0XHRcdFx0XHRoZWFkZXIuYXBwZW5kKHZlcnNpb24sIGNyaXRpY2FsLCBkYXRlKTtcblxuXHRcdFx0XHRcdGxldCBub3RlID0gJCgnPHByZT4nLCB7Y2xhc3M6ICdtdC0zIHJlbC1ub3Rlcyd9KS50ZXh0KHJlbE5vdGUuZ2V0VXRmU3RyaW5nKCdyZWxlYXNlX25vdGVzJykpO1xuXG5cdFx0XHRcdFx0JCgnI2N1cC1yZWxlYXNlTm90ZXMnKS5hcHBlbmQoaGVhZGVyLCBub3RlLCAkKCc8aHI+JykpO1xuXG5cdFx0XHRcdFx0aWYgKHZlcnNpb25OdW0gIT0gdXBkYXRlVmVyc2lvbilcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRpZiAoaW5jbHVkZXMgIT0gJycpXG5cdFx0XHRcdFx0XHRcdGluY2x1ZGVzICs9IChpIDwgcmVsTm90ZXNBcnIuc2l6ZSgpIC0gMSkgPyAnLCAnIDogJyBhbmQgJztcblxuXHRcdFx0XHRcdFx0aW5jbHVkZXMgKz0gJ3YnICsgdmVyc2lvbk51bTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoaW5jbHVkZXMgIT0gJycpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHQkKCcjY3VwLWluY2x1ZGVkVmVyJykudGV4dCgnVXBkYXRlIGFsc28gaW5jbHVkZXMgJyArIGluY2x1ZGVzKTtcblx0XHRcdFx0XHQkKCcjY3VwLWluY2x1ZGVkVmVyJykuc2hvdygpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHQkKCcjY3VwLWluY2x1ZGVkVmVyJykuaGlkZSgpO1xuXG5cdFx0XHRcdC8vIEFkZCBpbnN0YWxsZWQgdmVyc2lvblxuXHRcdFx0XHRsZXQgdmVyc2lvbiA9ICQoJzxoND4nLCB7Y2xhc3M6ICdtYi0wJ30pLmFwcGVuZCgkKCc8c3Bhbj4nLCB7Y2xhc3M6ICdiYWRnZSBiYWRnZS1zZWNvbmRhcnknfSkudGV4dCh0aGlzLnNoZWxsQ3RybC5nZXRTZnNWZXJzaW9uKCkpKTtcblx0XHRcdFx0bGV0IGluc3RhbGxlZCA9ICQoJzxzdHJvbmc+Jywge2NsYXNzOiAnbWwtMyd9KS50ZXh0KFwiKGluc3RhbGxlZClcIik7XG5cblx0XHRcdFx0bGV0IGhlYWRlciA9ICQoJzxkaXY+Jywge2NsYXNzOiAnZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlcid9KTtcblx0XHRcdFx0aGVhZGVyLmFwcGVuZCh2ZXJzaW9uLCBpbnN0YWxsZWQpO1xuXHRcdFx0XHQkKCcjY3VwLXJlbGVhc2VOb3RlcycpLmFwcGVuZChoZWFkZXIpO1xuXG5cdFx0XHRcdC8vIFN3aXRjaCB2aWV3XG5cdFx0XHRcdHRoaXMuX3N3aXRjaFZpZXcoJ2N1cC1tYWluJyk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gRXJyb3IgcmV0cmlldmluZyBhdmFpbGFibGUgdXBkYXRlXG5cdFx0ZWxzZSBpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfR0VUX0VSUk9SKVxuXHRcdHtcblx0XHRcdC8vIERpc3BsYXkgZXJyb3IgbWVzc2FnZVxuXHRcdFx0JCgnI2N1cC1lcnJvcjFNc2cnKS50ZXh0KGRhdGEuZ2V0VXRmU3RyaW5nKCdlcnJvcicpKTtcblxuXHRcdFx0Ly8gU3dpdGNoIHZpZXdcblx0XHRcdHRoaXMuX3N3aXRjaFZpZXcoJ2N1cC1lcnJvcicpO1xuXHRcdH1cblxuXHRcdC8vIEVycm9yIGxhdW5jaGluZyB1cGRhdGUgcHJvY2Vzc1xuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX1VQRF9FUlJPUilcblx0XHR7XG5cdFx0XHQvLyBFbmFibGUgYnV0dG9uc1xuXHRcdFx0JCgnI2N1cC1yZWZyZXNoQnQnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblx0XHRcdCQoJyNjdXAtdXBkYXRlQnQnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblxuXHRcdFx0Ly8gRGlzcGxheSBlcnJvciBtZXNzYWdlXG5cdFx0XHQkKCcjY3VwLWVycm9yMk1zZycpLnRleHQoJ1RoZSBmb2xsb3dpbmcgZXJyb3Igb2NjdXJyZWQgd2hlbiBsYXVuY2hpbmcgdGhlIHNlcnZlciB1cGRhdGUgcHJvY2VzczogJyArIGRhdGEuZ2V0VXRmU3RyaW5nKCdlcnJvcicpKTtcblx0XHR9XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLyBVSSBFVkVOVCBMSVNURU5FUlNcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRfb25SZXRyeUNsaWNrKClcblx0e1xuXHRcdC8vIFN3aXRjaCB2aWV3XG5cdFx0dGhpcy5fc3dpdGNoVmlldygnY3VwLWxvYWRpbmcnKTtcblxuXHRcdC8vIFRyeSBhZ2FpbiByZXF1ZXN0aW5nIG5ldyB2ZXJzaW9uXG5cdFx0dGhpcy5fcmVxdWVzdE5ld1ZlcnNpb24oKTtcblx0fVxuXG5cdF9vblJlZnJlc2hDbGljaygpXG5cdHtcblx0XHQvLyBIaWRlIHByZXZpb3VzIGVycm9yXG5cdFx0JCgnI2N1cC1lcnJvcjJNc2cnKS50ZXh0KCcnKTtcblxuXHRcdC8vIFN3aXRjaCB2aWV3XG5cdFx0dGhpcy5fc3dpdGNoVmlldygnY3VwLWxvYWRpbmcnKTtcblxuXHRcdC8vIFJlcXVlc3QgbmV3IHZlcnNpb24gYWdhaW5cblx0XHR0aGlzLl9yZXF1ZXN0TmV3VmVyc2lvbigpO1xuXHR9XG5cblx0X29uVXBkYXRlQ2xpY2soKVxuXHR7XG5cdFx0Ly8gU2hvdyBjb25maXJtYXRpb24gZGlhbG9nXG5cdFx0bGV0IG1lc3NhZ2UgPSAnQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIHByb2NlZWQ/PGJyPlRoZSBzZXJ2ZXIgd2lsbCBiZSByZXN0YXJ0ZWQgd2hlbiB0aGUgdXBkYXRlIHByb2Nlc3MgaXMgY29tcGxldGUuJztcblx0XHR0aGlzLnNoZWxsQ3RybC5zaG93Q29uZmlybVdhcm5pbmcobWVzc2FnZSwgJC5wcm94eSh0aGlzLl9vblVwZGF0ZUNvbmZpcm1EaWFsb2dDb25maXJtLCB0aGlzKSk7XG5cdH1cblxuXHRfb25VcGRhdGVDb25maXJtRGlhbG9nQ29uZmlybSgpXG5cdHtcblx0XHQvLyBEaXNhYmxlIGJ1dHRvbnNcblx0XHQkKCcjY3VwLXJlZnJlc2hCdCcpLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cdFx0JCgnI2N1cC11cGRhdGVCdCcpLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cblx0XHQvLyBIaWRlIHByZXZpb3VzIGVycm9yXG5cdFx0JCgnI2N1cC1lcnJvcjJNc2cnKS50ZXh0KCcnKTtcblxuXHRcdC8vIFNlbmQgcmVxdWVzdCB0byBleHRlbnNpb25cblx0XHQvLyBObyBwYXJhbWV0ZXJzIGFyZSBwYXNzZWQgYmVjYXVzZSB0aGUgZXh0ZW5zaW9uIGFscmVhZHkga25vdyB3aGljaCB2ZXJzaW9uIHRvIGluc3RhbGxcblx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX1VQREFURV9OT0RFKTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIFBSSVZBVEUgTUVUSE9EU1xuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdF9zd2l0Y2hWaWV3KHZpZXdJZClcblx0e1xuXHRcdGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjdXAtdmlld3N0YWNrJykuc2VsZWN0ZWRFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodmlld0lkKTtcblx0fVxuXG5cdF9yZXF1ZXN0TmV3VmVyc2lvbigpXG5cdHtcblx0XHQvLyBTZW5kIHJlcXVlc3QgdG8gZXh0ZW5zaW9uXG5cdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9HRVRfTkVXX1ZFUlNJT04pO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8gUFJJVkFURSBHRVRURVJTXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QSIsInNvdXJjZVJvb3QiOiIifQ==