media-player/target/main.js
2025-07-08 16:52:31 +02:00

556 lines
38 KiB
JavaScript

/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./src/css/main.css":
/*!**************************!*\
!*** ./src/css/main.css ***!
\**************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
// extracted by mini-css-extract-plugin
/***/ }),
/***/ "./src/js/descriptor/FileDescriptor.js":
/*!*********************************************!*\
!*** ./src/js/descriptor/FileDescriptor.js ***!
\*********************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (/* binding */ FileDescriptor)
/* harmony export */ });
class FileDescriptor {
/**
* @type {string}
*/
path = "";
/**
* @type {FileSystemFileHandle}
*/
handle = "";
/**
* @param {string} path
* @param {FileSystemFileHandle} handle
*/
constructor(path, handle){
this.path = path;
this.handle = handle;
}
}
/***/ }),
/***/ "./src/js/profile/MediaProfile.js":
/*!****************************************!*\
!*** ./src/js/profile/MediaProfile.js ***!
\****************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (/* binding */ MediaProfile)
/* harmony export */ });
/* harmony import */ var _MediaProfileRole_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./MediaProfileRole.js */ "./src/js/profile/MediaProfileRole.js");
/* harmony import */ var _MediaProfileSettings_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./MediaProfileSettings.js */ "./src/js/profile/MediaProfileSettings.js");
/* harmony import */ var _MediaProfileViewSettings_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./MediaProfileViewSettings.js */ "./src/js/profile/MediaProfileViewSettings.js");
class MediaProfile{
/**
* @type {string}
*/
name = "";
/**
* @type {string}
*/
role = _MediaProfileRole_js__WEBPACK_IMPORTED_MODULE_0__["default"].ADMIN;
/**
* @type {MediaProfileSettings}
*/
settings = new _MediaProfileSettings_js__WEBPACK_IMPORTED_MODULE_1__["default"]();
/**
* @type {MediaProfileViewSettings}
*/
playSettings = new _MediaProfileViewSettings_js__WEBPACK_IMPORTED_MODULE_2__["default"]();
/**
* @param {object} jsonObj
* @returns {MediaProfile}
*/
static fromJson(jsonObj) {
const profile = new MediaProfile();
if (jsonObj == null) {
return profile;
}
if (jsonObj.name != null) {
profile.name = jsonObj.name;
}
if (jsonObj.role != null) {
profile.role = jsonObj.role;
}
if (jsonObj.settings != null && typeof jsonObj.settings === "object") {
profile.settings = _MediaProfileSettings_js__WEBPACK_IMPORTED_MODULE_1__["default"].fromSettingsJson(jsonObj.settings);
}
if (jsonObj.playSettings != null && typeof jsonObj.playSettings === "object") {
profile.playSettings = _MediaProfileViewSettings_js__WEBPACK_IMPORTED_MODULE_2__["default"].fromSettingsJson(jsonObj.playSettings);
}
return profile;
}
}
/***/ }),
/***/ "./src/js/profile/MediaProfileRole.js":
/*!********************************************!*\
!*** ./src/js/profile/MediaProfileRole.js ***!
\********************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (/* binding */ MediaProfileRole)
/* harmony export */ });
class MediaProfileRole {
/**
* @type {string}
*/
static ADMIN = "ADMIN";
/**
* @type {string}
*/
static USER = "USER";
}
/***/ }),
/***/ "./src/js/profile/MediaProfileSettings.js":
/*!************************************************!*\
!*** ./src/js/profile/MediaProfileSettings.js ***!
\************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (/* binding */ MediaProfileSettings)
/* harmony export */ });
class MediaProfileSettings {
/**
* @type {boolean}
*/
skipIntro = true;
/**
* @type {boolean}
*/
skipOutro = true;
/**
* @type {boolean}
*/
skipRecall = true;
/**
* @type {boolean}
*/
skipPreview = true;
/**
* @param {object} jsonObj
* @returns {MediaProfileSettings}
*/
static fromSettingsJson(jsonObj) {
const settings = new MediaProfileSettings();
if (jsonObj == null) {
return settings;
}
if (jsonObj.skipIntro != null) {
settings.skipIntro = jsonObj.skipIntro;
}
if (jsonObj.skipOutro != null) {
settings.skipOutro = jsonObj.skipOutro;
}
if (jsonObj.skipRecall != null) {
settings.skipRecall = jsonObj.skipRecall;
}
if (jsonObj.skipPreview != null) {
settings.skipPreview = jsonObj.skipPreview;
}
return settings;
}
}
/***/ }),
/***/ "./src/js/profile/MediaProfileViewSettings.js":
/*!****************************************************!*\
!*** ./src/js/profile/MediaProfileViewSettings.js ***!
\****************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (/* binding */ MediaProfileViewSettings)
/* harmony export */ });
class MediaProfileViewSettings {
/**
* @type {boolean}
*/
hasOpenPlaylist = false;
/**
* @type {string}
*/
playlistPath = null;
/**
* @type {number}
*/
playlistTrackNumber = 0;
/**
* @type {number}
*/
trackPosition = 0;
/**
* @param {object} jsonObj
* @returns {MediaProfileViewSettings}
*/
static fromSettingsJson(jsonObj) {
const settings = new MediaProfileViewSettings();
if (jsonObj == null) {
return settings;
}
if (jsonObj.hasOpenPlaylist != null) {
settings.hasOpenPlaylist = jsonObj.hasOpenPlaylist;
}
if (jsonObj.playlistPath != null) {
settings.playlistPath = jsonObj.playlistPath;
}
if (jsonObj.playlistTrackNumber != null) {
settings.playlistTrackNumber = jsonObj.playlistTrackNumber;
}
if (jsonObj.trackPosition != null) {
settings.trackPosition = jsonObj.trackPosition;
}
return settings;
}
}
/***/ }),
/***/ "./src/js/util/FSUtil.js":
/*!*******************************!*\
!*** ./src/js/util/FSUtil.js ***!
\*******************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (/* binding */ FSUtil)
/* harmony export */ });
/* harmony import */ var _descriptor_FileDescriptor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../descriptor/FileDescriptor.js */ "./src/js/descriptor/FileDescriptor.js");
class FSUtil {
/**
* @param {FileSystemDirectoryHandle} rootDir
* @param {string} path
* @returns {Promise<string | null>}
*/
static async getFileContent(rootDir, path) {
const fileHandle = await FSUtil.getFileHandle(rootDir, FSUtil.fixPath(path));
return await FSUtil.getFileHandleFileContent(fileHandle);
}
/**
* @param {FileSystemFileHandle} handle
* @returns {Promise<string>}
*/
static async getFileHandleFileContent(handle) {
if (handle == null) {
return null;
}
const file = await handle.getFile();
return await file.text();
}
/**
* @param {FileSystemDirectoryHandle} rootDir
* @param {string} path
* @returns {Promise<FileSystemFileHandle | null>}
*/
static async getFileHandle(rootDir, path) {
let resultDir = rootDir;
let outputFile = null;
const pathes = FSUtil.fixPath(path).split("/");
let nextDirName = null;
while (nextDirName = pathes.shift()) {
let nextDir = null;
for await (const value of resultDir.values()) {
if (value.kind == 'directory' && value.name == nextDirName) {
nextDir = value;
} else if (value.kind == 'file' && value.name == nextDirName) {
outputFile = value;
}
}
if (nextDir != null) {
resultDir = nextDir;
}
}
return outputFile;
}
/**
* @param {FileSystemDirectoryHandle} rootDir
* @param {string} path
* @returns {Promise<FileSystemDirectoryHandle | null>}
*/
static async getDirectoryHandle(curDir, path) {
let resultDir = curDir;
const pathes = FSUtil.fixPath(path).split("/");
let nextDirName = null;
while (nextDirName = pathes.shift()) {
let nextDir = null;
for await (const value of resultDir.values()) {
if (value.kind == 'directory' && value.name == nextDirName) {
nextDir = value;
}
}
if (nextDir != null) {
resultDir = nextDir;
}
}
return resultDir;
}
/**
* @param {string} path
* @returns {string}
*/
static fixPath(path) {
let fixedPath = path.replaceAll("/./", "/"); //remove same folder subpathes
fixedPath = fixedPath.replaceAll("//", "/"); //remove double slashes
if (fixedPath.startsWith("/")) {
fixedPath = fixedPath.substring(1);
}
const pathParts = fixedPath.split("/");
for (let i = pathParts.length - 1; i > 0; i--) {
if (pathParts[i] == "..") {
pathParts.splice(i - 1, 2);
i--;
}
}
return pathParts.join("/");
}
/**
* @param {FileSystemDirectoryHandle} dir
* @param {string} fileName
* @param {boolean} includeSubDirs
* @returns {Promise<FileDescriptor>}
*/
static async findFile(dir, fileName, includeSubDirs = true) {
const files = await FSUtil.#findFilesInTree(dir, fileName, includeSubDirs, true);
return files.length > 0 ? files[0] : null;
}
/**
* @param {FileSystemDirectoryHandle} dir
* @param {string} fileName
* @param {boolean} includeSubDirs
* @returns {Promise<FileDescriptor[]>}
*/
static async findFiles(dir, fileName, includeSubDirs = true) {
return FSUtil.#findFilesInTree(dir, fileName, includeSubDirs, false);;
}
/**
* @param {FileSystemDirectoryHandle} dir
* @param {string} fileName
* @param {boolean} includeSubDirs
* @param {boolean} stopOnFirst
* @returns {Promise<FileDescriptor[]>}
*/
static async #findFilesInTree(dir, fileName, includeSubDirs = true, stopOnFirst = false, path = "") {
const files = [];
const subdirs = [];
for await (const child of dir.values()) {
if (child.kind == 'directory' && includeSubDirs) {
subdirs.push(child);
} else if (child.kind == 'file' && child.name == fileName) {
files.push(new _descriptor_FileDescriptor_js__WEBPACK_IMPORTED_MODULE_0__["default"](path, child));
if(stopOnFirst){
return files;
}
}
}
for (let i = 0; i < subdirs.length; i++) {
files.push(...(await FSUtil.#findFilesInTree(subdirs[i], fileName, includeSubDirs, stopOnFirst, path + "/" + subdirs[i].name)));
if(stopOnFirst && files.length > 0){
break;
}
}
return files;
}
}
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
(() => {
/*!*************************!*\
!*** ./src/js/index.js ***!
\*************************/
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _css_main_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../css/main.css */ "./src/css/main.css");
/* harmony import */ var _profile_MediaProfile_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./profile/MediaProfile.js */ "./src/js/profile/MediaProfile.js");
/* harmony import */ var _util_FSUtil_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util/FSUtil.js */ "./src/js/util/FSUtil.js");
async function load(){
const dir = await showDirectoryPicker({"id": "mediaplayer_amin", "mode": "readwrite"});
const files = await _util_FSUtil_js__WEBPACK_IMPORTED_MODULE_2__["default"].findFiles(dir, "S01-E0001.mp4");
files.forEach(f => {console.log(f.path + "/" + f.handle.name);});
//await walkFileTree(dir);
}
async function walkFileTree(currentDir){
for await (const value of currentDir.values()) {
if(value.kind == 'directory'){
await walkFileTree(value);
} else if(value.kind == 'file' && value.name == 'playlist.json'){
await getVideo(currentDir, value);
}
}
}
async function getVideo(dir, playlistFile){
const file = await playlistFile.getFile();
console.log("Playlist file:", file);
const content = await file.text();
const playlist = JSON.parse(content);
console.log(playlist);
const videoPath = playlist.tracks[0].relativePath;
console.log(videoPath);
const videoHandle = await _util_FSUtil_js__WEBPACK_IMPORTED_MODULE_2__["default"].getFileHandle(dir, videoPath);
console.log(videoHandle);
playVideo(await videoHandle.getFile());
}
function playVideo(file){
document.getElementById("video").src = URL.createObjectURL(file);
}
document.getElementById("startAppButton").addEventListener("click", load);
})();
/******/ })()
;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQUFBOzs7Ozs7Ozs7Ozs7Ozs7QUNBZTtBQUNmO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCLGVBQWUsc0JBQXNCO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNuQnFEO0FBQ1E7QUFDUTtBQUNyRTtBQUNlO0FBQ2Y7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQSxXQUFXLDREQUFnQjtBQUMzQjtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0EsbUJBQW1CLGdFQUFvQjtBQUN2QztBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0EsdUJBQXVCLG9FQUF3QjtBQUMvQztBQUNBO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLGdFQUFvQjtBQUNuRDtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsb0VBQXdCO0FBQzNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FDdERlO0FBQ2Y7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7OztBQ1ZlO0FBQ2Y7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLFFBQVE7QUFDdkIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7QUNsRGU7QUFDZjtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsUUFBUTtBQUN2QixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7QUNsRDZEO0FBQzdEO0FBQ2U7QUFDZjtBQUNBLGVBQWUsMkJBQTJCO0FBQzFDLGVBQWUsUUFBUTtBQUN2QixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLHNCQUFzQjtBQUNyQyxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsMkJBQTJCO0FBQzFDLGVBQWUsUUFBUTtBQUN2QixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLDJCQUEyQjtBQUMxQyxlQUFlLFFBQVE7QUFDdkIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsUUFBUTtBQUN2QixpQkFBaUI7QUFDakI7QUFDQTtBQUNBLHFEQUFxRDtBQUNyRCxxREFBcUQ7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkNBQTJDLE9BQU87QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLDJCQUEyQjtBQUMxQyxlQUFlLFFBQVE7QUFDdkIsZUFBZSxTQUFTO0FBQ3hCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsMkJBQTJCO0FBQzFDLGVBQWUsUUFBUTtBQUN2QixlQUFlLFNBQVM7QUFDeEIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsMkJBQTJCO0FBQzFDLGVBQWUsUUFBUTtBQUN2QixlQUFlLFNBQVM7QUFDeEIsZUFBZSxTQUFTO0FBQ3hCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkLCtCQUErQixxRUFBYztBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0Isb0JBQW9CO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O1VDOUpBO1VBQ0E7O1VBRUE7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7O1VBRUE7VUFDQTs7VUFFQTtVQUNBO1VBQ0E7Ozs7O1dDdEJBO1dBQ0E7V0FDQTtXQUNBO1dBQ0EseUNBQXlDLHdDQUF3QztXQUNqRjtXQUNBO1dBQ0E7Ozs7O1dDUEE7Ozs7O1dDQUE7V0FDQTtXQUNBO1dBQ0EsdURBQXVELGlCQUFpQjtXQUN4RTtXQUNBLGdEQUFnRCxhQUFhO1dBQzdEOzs7Ozs7Ozs7Ozs7OztBQ05rQztBQUNtQjtBQUNmO0FBQ3RDO0FBQ0E7QUFDQSwyQ0FBMkMsOENBQThDO0FBQ3pGLHdCQUF3Qix1REFBTTtBQUM5Qix3QkFBd0IsMkNBQTJDO0FBQ25FO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEIsdURBQU07QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBFIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vZGFzaGJvYXJkLy4vc3JjL2Nzcy9tYWluLmNzcz9jNDhmIiwid2VicGFjazovL2Rhc2hib2FyZC8uL3NyYy9qcy9kZXNjcmlwdG9yL0ZpbGVEZXNjcmlwdG9yLmpzIiwid2VicGFjazovL2Rhc2hib2FyZC8uL3NyYy9qcy9wcm9maWxlL01lZGlhUHJvZmlsZS5qcyIsIndlYnBhY2s6Ly9kYXNoYm9hcmQvLi9zcmMvanMvcHJvZmlsZS9NZWRpYVByb2ZpbGVSb2xlLmpzIiwid2VicGFjazovL2Rhc2hib2FyZC8uL3NyYy9qcy9wcm9maWxlL01lZGlhUHJvZmlsZVNldHRpbmdzLmpzIiwid2VicGFjazovL2Rhc2hib2FyZC8uL3NyYy9qcy9wcm9maWxlL01lZGlhUHJvZmlsZVZpZXdTZXR0aW5ncy5qcyIsIndlYnBhY2s6Ly9kYXNoYm9hcmQvLi9zcmMvanMvdXRpbC9GU1V0aWwuanMiLCJ3ZWJwYWNrOi8vZGFzaGJvYXJkL3dlYnBhY2svYm9vdHN0cmFwIiwid2VicGFjazovL2Rhc2hib2FyZC93ZWJwYWNrL3J1bnRpbWUvZGVmaW5lIHByb3BlcnR5IGdldHRlcnMiLCJ3ZWJwYWNrOi8vZGFzaGJvYXJkL3dlYnBhY2svcnVudGltZS9oYXNPd25Qcm9wZXJ0eSBzaG9ydGhhbmQiLCJ3ZWJwYWNrOi8vZGFzaGJvYXJkL3dlYnBhY2svcnVudGltZS9tYWtlIG5hbWVzcGFjZSBvYmplY3QiLCJ3ZWJwYWNrOi8vZGFzaGJvYXJkLy4vc3JjL2pzL2luZGV4LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIGV4dHJhY3RlZCBieSBtaW5pLWNzcy1leHRyYWN0LXBsdWdpblxuZXhwb3J0IHt9OyIsImV4cG9ydCBkZWZhdWx0IGNsYXNzIEZpbGVEZXNjcmlwdG9yIHtcclxuICAgIC8qKlxyXG4gICAgICogQHR5cGUge3N0cmluZ31cclxuICAgICAqL1xyXG4gICAgcGF0aCA9IFwiXCI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAdHlwZSB7RmlsZVN5c3RlbUZpbGVIYW5kbGV9XHJcbiAgICAgKi9cclxuICAgIGhhbmRsZSA9IFwiXCI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBcclxuICAgICAqIEBwYXJhbSB7RmlsZVN5c3RlbUZpbGVIYW5kbGV9IGhhbmRsZSBcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IocGF0aCwgaGFuZGxlKXtcclxuICAgICAgICB0aGlzLnBhdGggPSBwYXRoO1xyXG4gICAgICAgIHRoaXMuaGFuZGxlID0gaGFuZGxlO1xyXG4gICAgfVxyXG59IiwiaW1wb3J0IE1lZGlhUHJvZmlsZVJvbGUgZnJvbSBcIi4vTWVkaWFQcm9maWxlUm9sZS5qc1wiO1xyXG5pbXBvcnQgTWVkaWFQcm9maWxlU2V0dGluZ3MgZnJvbSBcIi4vTWVkaWFQcm9maWxlU2V0dGluZ3MuanNcIjtcclxuaW1wb3J0IE1lZGlhUHJvZmlsZVZpZXdTZXR0aW5ncyBmcm9tIFwiLi9NZWRpYVByb2ZpbGVWaWV3U2V0dGluZ3MuanNcIjtcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE1lZGlhUHJvZmlsZXtcclxuICAgIC8qKlxyXG4gICAgICogQHR5cGUge3N0cmluZ31cclxuICAgICAqL1xyXG4gICAgbmFtZSA9IFwiXCI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxyXG4gICAgICovXHJcbiAgICByb2xlID0gTWVkaWFQcm9maWxlUm9sZS5BRE1JTjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEB0eXBlIHtNZWRpYVByb2ZpbGVTZXR0aW5nc31cclxuICAgICAqL1xyXG4gICAgc2V0dGluZ3MgPSBuZXcgTWVkaWFQcm9maWxlU2V0dGluZ3MoKTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEB0eXBlIHtNZWRpYVByb2ZpbGVWaWV3U2V0dGluZ3N9XHJcbiAgICAgKi9cclxuICAgIHBsYXlTZXR0aW5ncyA9IG5ldyBNZWRpYVByb2ZpbGVWaWV3U2V0dGluZ3MoKTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBqc29uT2JqIFxyXG4gICAgICogQHJldHVybnMge01lZGlhUHJvZmlsZX1cclxuICAgICAqL1xyXG4gICAgc3RhdGljIGZyb21Kc29uKGpzb25PYmopIHtcclxuICAgICAgICBjb25zdCBwcm9maWxlID0gbmV3IE1lZGlhUHJvZmlsZSgpO1xyXG5cclxuICAgICAgICBpZiAoanNvbk9iaiA9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBwcm9maWxlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGpzb25PYmoubmFtZSAhPSBudWxsKSB7XHJcbiAgICAgICAgICAgIHByb2ZpbGUubmFtZSA9IGpzb25PYmoubmFtZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChqc29uT2JqLnJvbGUgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICBwcm9maWxlLnJvbGUgPSBqc29uT2JqLnJvbGU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoanNvbk9iai5zZXR0aW5ncyAhPSBudWxsICYmIHR5cGVvZiBqc29uT2JqLnNldHRpbmdzID09PSBcIm9iamVjdFwiKSB7XHJcbiAgICAgICAgICAgIHByb2ZpbGUuc2V0dGluZ3MgPSBNZWRpYVByb2ZpbGVTZXR0aW5ncy5mcm9tU2V0dGluZ3NKc29uKGpzb25PYmouc2V0dGluZ3MpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGpzb25PYmoucGxheVNldHRpbmdzICE9IG51bGwgJiYgdHlwZW9mIGpzb25PYmoucGxheVNldHRpbmdzID09PSBcIm9iamVjdFwiKSB7XHJcbiAgICAgICAgICAgIHByb2ZpbGUucGxheVNldHRpbmdzID0gTWVkaWFQcm9maWxlVmlld1NldHRpbmdzLmZyb21TZXR0aW5nc0pzb24oanNvbk9iai5wbGF5U2V0dGluZ3MpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHByb2ZpbGU7XHJcbiAgICB9XHJcbn0iLCJleHBvcnQgZGVmYXVsdCBjbGFzcyBNZWRpYVByb2ZpbGVSb2xlIHtcclxuICAgIC8qKlxyXG4gICAgICogQHR5cGUge3N0cmluZ31cclxuICAgICAqL1xyXG4gICAgc3RhdGljIEFETUlOID0gXCJBRE1JTlwiO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHR5cGUge3N0cmluZ31cclxuICAgICAqL1xyXG4gICAgc3RhdGljIFVTRVIgPSBcIlVTRVJcIjtcclxufSIsImV4cG9ydCBkZWZhdWx0IGNsYXNzIE1lZGlhUHJvZmlsZVNldHRpbmdzIHtcclxuICAgIC8qKlxyXG4gICAgICogQHR5cGUge2Jvb2xlYW59XHJcbiAgICAgKi9cclxuICAgIHNraXBJbnRybyA9IHRydWU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cclxuICAgICAqL1xyXG4gICAgc2tpcE91dHJvID0gdHJ1ZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEB0eXBlIHtib29sZWFufVxyXG4gICAgICovXHJcbiAgICBza2lwUmVjYWxsID0gdHJ1ZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEB0eXBlIHtib29sZWFufVxyXG4gICAgICovXHJcbiAgICBza2lwUHJldmlldyA9IHRydWU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0ge29iamVjdH0ganNvbk9iaiBcclxuICAgICAqIEByZXR1cm5zIHtNZWRpYVByb2ZpbGVTZXR0aW5nc31cclxuICAgICAqL1xyXG4gICAgc3RhdGljIGZyb21TZXR0aW5nc0pzb24oanNvbk9iaikge1xyXG4gICAgICAgIGNvbnN0IHNldHRpbmdzID0gbmV3IE1lZGlhUHJvZmlsZVNldHRpbmdzKCk7XHJcblxyXG4gICAgICAgIGlmIChqc29uT2JqID09IG51bGwpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHNldHRpbmdzO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGpzb25PYmouc2tpcEludHJvICE9IG51bGwpIHtcclxuICAgICAgICAgICAgc2V0dGluZ3Muc2tpcEludHJvID0ganNvbk9iai5za2lwSW50cm87XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoanNvbk9iai5za2lwT3V0cm8gIT0gbnVsbCkge1xyXG4gICAgICAgICAgICBzZXR0aW5ncy5za2lwT3V0cm8gPSBqc29uT2JqLnNraXBPdXRybztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChqc29uT2JqLnNraXBSZWNhbGwgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICBzZXR0aW5ncy5za2lwUmVjYWxsID0ganNvbk9iai5za2lwUmVjYWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGpzb25PYmouc2tpcFByZXZpZXcgIT0gbnVsbCkge1xyXG4gICAgICAgICAgICBzZXR0aW5ncy5za2lwUHJldmlldyA9IGpzb25PYmouc2tpcFByZXZpZXc7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gc2V0dGluZ3M7XHJcbiAgICB9XHJcbn0iLCJleHBvcnQgZGVmYXVsdCBjbGFzcyBNZWRpYVByb2ZpbGVWaWV3U2V0dGluZ3Mge1xyXG4gICAgLyoqXHJcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cclxuICAgICAqL1xyXG4gICAgaGFzT3BlblBsYXlsaXN0ID0gZmFsc2U7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxyXG4gICAgICovXHJcbiAgICBwbGF5bGlzdFBhdGggPSBudWxsO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHR5cGUge251bWJlcn1cclxuICAgICAqL1xyXG4gICAgcGxheWxpc3RUcmFja051bWJlciA9IDA7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxyXG4gICAgICovXHJcbiAgICB0cmFja1Bvc2l0aW9uID0gMDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBqc29uT2JqIFxyXG4gICAgICogQHJldHVybnMge01lZGlhUHJvZmlsZVZpZXdTZXR0aW5nc31cclxuICAgICAqL1xyXG4gICAgc3RhdGljIGZyb21TZXR0aW5nc0pzb24oanNvbk9iaikge1xyXG4gICAgICAgIGNvbnN0IHNldHRpbmdzID0gbmV3IE1lZGlhUHJvZmlsZVZpZXdTZXR0aW5ncygpO1xyXG5cclxuICAgICAgICBpZiAoanNvbk9iaiA9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBzZXR0aW5ncztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChqc29uT2JqLmhhc09wZW5QbGF5bGlzdCAhPSBudWxsKSB7XHJcbiAgICAgICAgICAgIHNldHRpbmdzLmhhc09wZW5QbGF5bGlzdCA9IGpzb25PYmouaGFzT3BlblBsYXlsaXN0O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGpzb25PYmoucGxheWxpc3RQYXRoICE9IG51bGwpIHtcclxuICAgICAgICAgICAgc2V0dGluZ3MucGxheWxpc3RQYXRoID0ganNvbk9iai5wbGF5bGlzdFBhdGg7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoanNvbk9iai5wbGF5bGlzdFRyYWNrTnVtYmVyICE9IG51bGwpIHtcclxuICAgICAgICAgICAgc2V0dGluZ3MucGxheWxpc3RUcmFja051bWJlciA9IGpzb25PYmoucGxheWxpc3RUcmFja051bWJlcjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChqc29uT2JqLnRyYWNrUG9zaXRpb24gIT0gbnVsbCkge1xyXG4gICAgICAgICAgICBzZXR0aW5ncy50cmFja1Bvc2l0aW9uID0ganNvbk9iai50cmFja1Bvc2l0aW9uO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHNldHRpbmdzO1xyXG4gICAgfVxyXG59IiwiaW1wb3J0IEZpbGVEZXNjcmlwdG9yIGZyb20gXCIuLi9kZXNjcmlwdG9yL0ZpbGVEZXNjcmlwdG9yLmpzXCI7XHJcblxyXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBGU1V0aWwge1xyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0ge0ZpbGVTeXN0ZW1EaXJlY3RvcnlIYW5kbGV9IHJvb3REaXIgXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBcclxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZyB8IG51bGw+fVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgYXN5bmMgZ2V0RmlsZUNvbnRlbnQocm9vdERpciwgcGF0aCkge1xyXG4gICAgICAgIGNvbnN0IGZpbGVIYW5kbGUgPSBhd2FpdCBGU1V0aWwuZ2V0RmlsZUhhbmRsZShyb290RGlyLCBGU1V0aWwuZml4UGF0aChwYXRoKSk7XHJcbiAgICAgICAgcmV0dXJuIGF3YWl0IEZTVXRpbC5nZXRGaWxlSGFuZGxlRmlsZUNvbnRlbnQoZmlsZUhhbmRsZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0ge0ZpbGVTeXN0ZW1GaWxlSGFuZGxlfSBoYW5kbGUgXHJcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgYXN5bmMgZ2V0RmlsZUhhbmRsZUZpbGVDb250ZW50KGhhbmRsZSkge1xyXG4gICAgICAgIGlmIChoYW5kbGUgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGZpbGUgPSBhd2FpdCBoYW5kbGUuZ2V0RmlsZSgpO1xyXG4gICAgICAgIHJldHVybiBhd2FpdCBmaWxlLnRleHQoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBwYXJhbSB7RmlsZVN5c3RlbURpcmVjdG9yeUhhbmRsZX0gcm9vdERpciBcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXRoIFxyXG4gICAgICogQHJldHVybnMge1Byb21pc2U8RmlsZVN5c3RlbUZpbGVIYW5kbGUgfCBudWxsPn1cclxuICAgICAqL1xyXG4gICAgc3RhdGljIGFzeW5jIGdldEZpbGVIYW5kbGUocm9vdERpciwgcGF0aCkge1xyXG4gICAgICAgIGxldCByZXN1bHREaXIgPSByb290RGlyO1xyXG4gICAgICAgIGxldCBvdXRwdXRGaWxlID0gbnVsbDtcclxuICAgICAgICBjb25zdCBwYXRoZXMgPSBGU1V0aWwuZml4UGF0aChwYXRoKS5zcGxpdChcIi9cIik7XHJcbiAgICAgICAgbGV0IG5leHREaXJOYW1lID0gbnVsbDtcclxuXHJcbiAgICAgICAgd2hpbGUgKG5leHREaXJOYW1lID0gcGF0aGVzLnNoaWZ0KCkpIHtcclxuICAgICAgICAgICAgbGV0IG5leHREaXIgPSBudWxsO1xyXG5cclxuICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCB2YWx1ZSBvZiByZXN1bHREaXIudmFsdWVzKCkpIHtcclxuICAgICAgICAgICAgICAgIGlmICh2YWx1ZS5raW5kID09ICdkaXJlY3RvcnknICYmIHZhbHVlLm5hbWUgPT0gbmV4dERpck5hbWUpIHtcclxuICAgICAgICAgICAgICAgICAgICBuZXh0RGlyID0gdmFsdWU7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmtpbmQgPT0gJ2ZpbGUnICYmIHZhbHVlLm5hbWUgPT0gbmV4dERpck5hbWUpIHtcclxuICAgICAgICAgICAgICAgICAgICBvdXRwdXRGaWxlID0gdmFsdWU7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmIChuZXh0RGlyICE9IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdERpciA9IG5leHREaXI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBvdXRwdXRGaWxlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHBhcmFtIHtGaWxlU3lzdGVtRGlyZWN0b3J5SGFuZGxlfSByb290RGlyIFxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBhdGggXHJcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxGaWxlU3lzdGVtRGlyZWN0b3J5SGFuZGxlIHwgbnVsbD59XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBhc3luYyBnZXREaXJlY3RvcnlIYW5kbGUoY3VyRGlyLCBwYXRoKSB7XHJcbiAgICAgICAgbGV0IHJlc3VsdERpciA9IGN1ckRpcjtcclxuICAgICAgICBjb25zdCBwYXRoZXMgPSBGU1V0aWwuZml4UGF0aChwYXRoKS5zcGxpdChcIi9cIik7XHJcbiAgICAgICAgbGV0IG5leHREaXJOYW1lID0gbnVsbDtcclxuXHJcbiAgICAgICAgd2hpbGUgKG5leHREaXJOYW1lID0gcGF0aGVzLnNoaWZ0KCkpIHtcclxuICAgICAgICAgICAgbGV0IG5leHREaXIgPSBudWxsO1xyXG5cclxuICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCB2YWx1ZSBvZiByZXN1bHREaXIudmFsdWVzKCkpIHtcclxuICAgICAgICAgICAgICAgIGlmICh2YWx1ZS5raW5kID09ICdkaXJlY3RvcnknICYmIHZhbHVlLm5hbWUgPT0gbmV4dERpck5hbWUpIHtcclxuICAgICAgICAgICAgICAgICAgICBuZXh0RGlyID0gdmFsdWU7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmIChuZXh0RGlyICE9IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHJlc3VsdERpciA9IG5leHREaXI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiByZXN1bHREaXI7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGF0aCBcclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBmaXhQYXRoKHBhdGgpIHtcclxuICAgICAgICBsZXQgZml4ZWRQYXRoID0gcGF0aC5yZXBsYWNlQWxsKFwiLy4vXCIsIFwiL1wiKTsgLy9yZW1vdmUgc2FtZSBmb2xkZXIgc3VicGF0aGVzXHJcbiAgICAgICAgZml4ZWRQYXRoID0gZml4ZWRQYXRoLnJlcGxhY2VBbGwoXCIvL1wiLCBcIi9cIik7IC8vcmVtb3ZlIGRvdWJsZSBzbGFzaGVzXHJcblxyXG4gICAgICAgIGlmIChmaXhlZFBhdGguc3RhcnRzV2l0aChcIi9cIikpIHtcclxuICAgICAgICAgICAgZml4ZWRQYXRoID0gZml4ZWRQYXRoLnN1YnN0cmluZygxKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHBhdGhQYXJ0cyA9IGZpeGVkUGF0aC5zcGxpdChcIi9cIik7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IHBhdGhQYXJ0cy5sZW5ndGggLSAxOyBpID4gMDsgaS0tKSB7XHJcbiAgICAgICAgICAgIGlmIChwYXRoUGFydHNbaV0gPT0gXCIuLlwiKSB7XHJcbiAgICAgICAgICAgICAgICBwYXRoUGFydHMuc3BsaWNlKGkgLSAxLCAyKTtcclxuICAgICAgICAgICAgICAgIGktLTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHBhdGhQYXJ0cy5qb2luKFwiL1wiKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBwYXJhbSB7RmlsZVN5c3RlbURpcmVjdG9yeUhhbmRsZX0gZGlyIFxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGZpbGVOYW1lIFxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBpbmNsdWRlU3ViRGlyc1xyXG4gICAgICogQHJldHVybnMge1Byb21pc2U8RmlsZURlc2NyaXB0b3I+fVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgYXN5bmMgZmluZEZpbGUoZGlyLCBmaWxlTmFtZSwgaW5jbHVkZVN1YkRpcnMgPSB0cnVlKSB7XHJcbiAgICAgICAgY29uc3QgZmlsZXMgPSBhd2FpdCBGU1V0aWwuI2ZpbmRGaWxlc0luVHJlZShkaXIsIGZpbGVOYW1lLCBpbmNsdWRlU3ViRGlycywgdHJ1ZSk7XHJcbiAgICAgICAgcmV0dXJuIGZpbGVzLmxlbmd0aCA+IDAgPyBmaWxlc1swXSA6IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAcGFyYW0ge0ZpbGVTeXN0ZW1EaXJlY3RvcnlIYW5kbGV9IGRpciBcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlTmFtZSBcclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaW5jbHVkZVN1YkRpcnNcclxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPEZpbGVEZXNjcmlwdG9yW10+fVxyXG4gICAgICovXHJcbiAgICBzdGF0aWMgYXN5bmMgZmluZEZpbGVzKGRpciwgZmlsZU5hbWUsIGluY2x1ZGVTdWJEaXJzID0gdHJ1ZSkge1xyXG4gICAgICAgIHJldHVybiBGU1V0aWwuI2ZpbmRGaWxlc0luVHJlZShkaXIsIGZpbGVOYW1lLCBpbmNsdWRlU3ViRGlycywgZmFsc2UpOztcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBwYXJhbSB7RmlsZVN5c3RlbURpcmVjdG9yeUhhbmRsZX0gZGlyIFxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGZpbGVOYW1lIFxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBpbmNsdWRlU3ViRGlyc1xyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBzdG9wT25GaXJzdFxyXG4gICAgICogQHJldHVybnMge1Byb21pc2U8RmlsZURlc2NyaXB0b3JbXT59XHJcbiAgICAgKi9cclxuICAgIHN0YXRpYyBhc3luYyAjZmluZEZpbGVzSW5UcmVlKGRpciwgZmlsZU5hbWUsIGluY2x1ZGVTdWJEaXJzID0gdHJ1ZSwgc3RvcE9uRmlyc3QgPSBmYWxzZSwgcGF0aCA9IFwiXCIpIHtcclxuICAgICAgICBjb25zdCBmaWxlcyA9IFtdO1xyXG4gICAgICAgIGNvbnN0IHN1YmRpcnMgPSBbXTtcclxuXHJcbiAgICAgICAgZm9yIGF3YWl0IChjb25zdCBjaGlsZCBvZiBkaXIudmFsdWVzKCkpIHtcclxuICAgICAgICAgICAgaWYgKGNoaWxkLmtpbmQgPT0gJ2RpcmVjdG9yeScgJiYgaW5jbHVkZVN1YkRpcnMpIHtcclxuICAgICAgICAgICAgICAgIHN1YmRpcnMucHVzaChjaGlsZCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2hpbGQua2luZCA9PSAnZmlsZScgJiYgY2hpbGQubmFtZSA9PSBmaWxlTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgZmlsZXMucHVzaChuZXcgRmlsZURlc2NyaXB0b3IocGF0aCwgY2hpbGQpKTtcclxuICAgICAgICAgICAgICAgIGlmKHN0b3BPbkZpcnN0KXtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmlsZXM7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3ViZGlycy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBmaWxlcy5wdXNoKC4uLihhd2FpdCBGU1V0aWwuI2ZpbmRGaWxlc0luVHJlZShzdWJkaXJzW2ldLCBmaWxlTmFtZSwgaW5jbHVkZVN1YkRpcnMsIHN0b3BPbkZpcnN0LCBwYXRoICsgXCIvXCIgKyBzdWJkaXJzW2ldLm5hbWUpKSk7XHJcbiAgICAgICAgICAgIGlmKHN0b3BPbkZpcnN0ICYmIGZpbGVzLmxlbmd0aCA+IDApe1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBmaWxlcztcclxuICAgIH1cclxufSIsIi8vIFRoZSBtb2R1bGUgY2FjaGVcbnZhciBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX18gPSB7fTtcblxuLy8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbmZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG5cdHZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdO1xuXHRpZiAoY2FjaGVkTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcblx0XHRyZXR1cm4gY2FjaGVkTW9kdWxlLmV4cG9ydHM7XG5cdH1cblx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcblx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XG5cdFx0Ly8gbm8gbW9kdWxlLmlkIG5lZWRlZFxuXHRcdC8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkXG5cdFx0ZXhwb3J0czoge31cblx0fTtcblxuXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cblx0X193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0obW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cblx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcblx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xufVxuXG4iLCIvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9ucyBmb3IgaGFybW9ueSBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSAoZXhwb3J0cywgZGVmaW5pdGlvbikgPT4ge1xuXHRmb3IodmFyIGtleSBpbiBkZWZpbml0aW9uKSB7XG5cdFx0aWYoX193ZWJwYWNrX3JlcXVpcmVfXy5vKGRlZmluaXRpb24sIGtleSkgJiYgIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBrZXkpKSB7XG5cdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywga2V5LCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZGVmaW5pdGlvbltrZXldIH0pO1xuXHRcdH1cblx0fVxufTsiLCJfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSAob2JqLCBwcm9wKSA9PiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCkpIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IGNzcyBmcm9tIFwiLi4vY3NzL21haW4uY3NzXCI7XHJcbmltcG9ydCBNZWRpYVByb2ZpbGUgZnJvbSBcIi4vcHJvZmlsZS9NZWRpYVByb2ZpbGUuanNcIjtcclxuaW1wb3J0IEZTVXRpbCBmcm9tIFwiLi91dGlsL0ZTVXRpbC5qc1wiO1xyXG5cclxuYXN5bmMgZnVuY3Rpb24gbG9hZCgpe1xyXG4gICAgY29uc3QgZGlyID0gYXdhaXQgc2hvd0RpcmVjdG9yeVBpY2tlcih7XCJpZFwiOiBcIm1lZGlhcGxheWVyX2FtaW5cIiwgXCJtb2RlXCI6IFwicmVhZHdyaXRlXCJ9KTtcclxuICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgRlNVdGlsLmZpbmRGaWxlcyhkaXIsIFwiUzAxLUUwMDAxLm1wNFwiKTtcclxuICAgIGZpbGVzLmZvckVhY2goZiA9PiB7Y29uc29sZS5sb2coZi5wYXRoICsgXCIvXCIgKyBmLmhhbmRsZS5uYW1lKTt9KTtcclxuICAgIC8vYXdhaXQgd2Fsa0ZpbGVUcmVlKGRpcik7XHJcbn1cclxuXHJcbmFzeW5jIGZ1bmN0aW9uIHdhbGtGaWxlVHJlZShjdXJyZW50RGlyKXtcclxuICAgIGZvciBhd2FpdCAoY29uc3QgdmFsdWUgb2YgY3VycmVudERpci52YWx1ZXMoKSkge1xyXG4gICAgICAgIGlmKHZhbHVlLmtpbmQgPT0gJ2RpcmVjdG9yeScpe1xyXG4gICAgICAgICAgICBhd2FpdCB3YWxrRmlsZVRyZWUodmFsdWUpO1xyXG4gICAgICAgIH0gZWxzZSBpZih2YWx1ZS5raW5kID09ICdmaWxlJyAmJiB2YWx1ZS5uYW1lID09ICdwbGF5bGlzdC5qc29uJyl7XHJcbiAgICAgICAgICAgIGF3YWl0IGdldFZpZGVvKGN1cnJlbnREaXIsIHZhbHVlKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbmFzeW5jIGZ1bmN0aW9uIGdldFZpZGVvKGRpciwgcGxheWxpc3RGaWxlKXtcclxuICAgIGNvbnN0IGZpbGUgPSBhd2FpdCBwbGF5bGlzdEZpbGUuZ2V0RmlsZSgpO1xyXG4gICAgY29uc29sZS5sb2coXCJQbGF5bGlzdCBmaWxlOlwiLCBmaWxlKTtcclxuICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBmaWxlLnRleHQoKTtcclxuICAgIGNvbnN0IHBsYXlsaXN0ID0gSlNPTi5wYXJzZShjb250ZW50KTtcclxuICAgIGNvbnNvbGUubG9nKHBsYXlsaXN0KTtcclxuICAgIGNvbnN0IHZpZGVvUGF0aCA9IHBsYXlsaXN0LnRyYWNrc1swXS5yZWxhdGl2ZVBhdGg7XHJcbiAgICBjb25zb2xlLmxvZyh2aWRlb1BhdGgpO1xyXG5cclxuICAgIGNvbnN0IHZpZGVvSGFuZGxlID0gYXdhaXQgRlNVdGlsLmdldEZpbGVIYW5kbGUoZGlyLCB2aWRlb1BhdGgpO1xyXG4gICAgY29uc29sZS5sb2codmlkZW9IYW5kbGUpO1xyXG4gICAgcGxheVZpZGVvKGF3YWl0IHZpZGVvSGFuZGxlLmdldEZpbGUoKSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHBsYXlWaWRlbyhmaWxlKXtcclxuICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwidmlkZW9cIikuc3JjID0gVVJMLmNyZWF0ZU9iamVjdFVSTChmaWxlKTtcclxufVxyXG5cclxuZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJzdGFydEFwcEJ1dHRvblwiKS5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgbG9hZCk7Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9