556 lines
38 KiB
JavaScript
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
|