map.
- this.prevOpen = this.open;
- this.selectWidth = 0;
- if (lit__WEBPACK_IMPORTED_MODULE_1__.isServer) {
- return;
- }
- this.addEventListener('focus', this.handleFocus.bind(this));
- this.addEventListener('blur', this.handleBlur.bind(this));
- }
- /**
- * Selects an option given the value of the option, and updates MdSelect's
- * value.
- */
- select(value) {
- const optionToSelect = this.options.find((option) => option.value === value);
- if (optionToSelect) {
- this.selectItem(optionToSelect);
- }
- }
- /**
- * Selects an option given the index of the option, and updates MdSelect's
- * value.
- */
- selectIndex(index) {
- const optionToSelect = this.options[index];
- if (optionToSelect) {
- this.selectItem(optionToSelect);
- }
- }
- /**
- * Reset the select to its default value.
- */
- reset() {
- for (const option of this.options) {
- option.selected = option.hasAttribute('selected');
- }
- this.updateValueAndDisplayText();
- this.nativeError = false;
- this.nativeErrorText = '';
- }
- [(_a = VALUE, _labs_behaviors_on_report_validity_js__WEBPACK_IMPORTED_MODULE_11__.onReportValidity)](invalidEvent) {
- // Prevent default pop-up behavior.
- invalidEvent?.preventDefault();
- const prevMessage = this.getErrorText();
- this.nativeError = !!invalidEvent;
- this.nativeErrorText = this.validationMessage;
- if (prevMessage === this.getErrorText()) {
- this.field?.reannounceError();
- }
- }
- update(changed) {
- // In SSR the options will be ready to query, so try to figure out what
- // the value and display text should be.
- if (!this.hasUpdated) {
- this.initUserSelection();
- }
- // We have just opened the menu.
- // We are only able to check for the select's rect in `update()` instead of
- // having to wait for `updated()` because the menu can never be open on
- // first render since it is not settable and Lit SSR does not support click
- // events which would open the menu.
- if (this.prevOpen !== this.open && this.open) {
- const selectRect = this.getBoundingClientRect();
- this.selectWidth = selectRect.width;
- }
- this.prevOpen = this.open;
- super.update(changed);
- }
- render() {
- return (0,lit__WEBPACK_IMPORTED_MODULE_1__.html) `
-
- ${this.renderField()} ${this.renderMenu()}
-
- `;
- }
- async firstUpdated(changed) {
- await this.menu?.updateComplete;
- // If this has been handled on update already due to SSR, try again.
- if (!this.lastSelectedOptionRecords.length) {
- this.initUserSelection();
- }
- // Case for when the DOM is streaming, there are no children, and a child
- // has [selected] set on it, we need to wait for DOM to render something.
- if (!this.lastSelectedOptionRecords.length &&
- !lit__WEBPACK_IMPORTED_MODULE_1__.isServer &&
- !this.options.length) {
- setTimeout(() => {
- this.updateValueAndDisplayText();
- });
- }
- super.firstUpdated(changed);
- }
- getRenderClasses() {
- return {
- 'disabled': this.disabled,
- 'error': this.error,
- 'open': this.open,
- };
- }
- renderField() {
- const ariaLabel = this.ariaLabel || this.label;
- return (0,lit_static_html_js__WEBPACK_IMPORTED_MODULE_5__.html) `
- <${this.fieldTag}
- aria-haspopup="listbox"
- role="combobox"
- part="field"
- id="field"
- tabindex=${this.disabled ? '-1' : '0'}
- aria-label=${ariaLabel || lit__WEBPACK_IMPORTED_MODULE_1__.nothing}
- aria-describedby="description"
- aria-expanded=${this.open ? 'true' : 'false'}
- aria-controls="listbox"
- class="field"
- label=${this.label}
- ?no-asterisk=${this.noAsterisk}
- .focused=${this.focused || this.open}
- .populated=${!!this.displayText}
- .disabled=${this.disabled}
- .required=${this.required}
- .error=${this.hasError}
- ?has-start=${this.hasLeadingIcon}
- has-end
- supporting-text=${this.supportingText}
- error-text=${this.getErrorText()}
- @keydown=${this.handleKeydown}
- @click=${this.handleClick}>
- ${this.renderFieldContent()}
-
- ${this.fieldTag}>`;
- }
- renderFieldContent() {
- return [
- this.renderLeadingIcon(),
- this.renderLabel(),
- this.renderTrailingIcon(),
- ];
- }
- renderLeadingIcon() {
- return (0,lit__WEBPACK_IMPORTED_MODULE_1__.html) `
-
-
-
- `;
- }
- renderTrailingIcon() {
- return (0,lit__WEBPACK_IMPORTED_MODULE_1__.html) `
-
-
-
-
-
-
-
-
- `;
- }
- renderLabel() {
- // need to render so that line-height can apply and give it a
- // non-zero height
- return (0,lit__WEBPACK_IMPORTED_MODULE_1__.html) `${this.displayText || (0,lit__WEBPACK_IMPORTED_MODULE_1__.html) ` `}
`;
- }
- renderMenu() {
- const ariaLabel = this.label || this.ariaLabel;
- return (0,lit__WEBPACK_IMPORTED_MODULE_1__.html) ``;
- }
- renderMenuContent() {
- return (0,lit__WEBPACK_IMPORTED_MODULE_1__.html) ` `;
- }
- /**
- * Handles opening the select on keydown and typahead selection when the menu
- * is closed.
- */
- handleKeydown(event) {
- if (this.open || this.disabled || !this.menu) {
- return;
- }
- const typeaheadController = this.menu.typeaheadController;
- const isOpenKey = event.code === 'Space' ||
- event.code === 'ArrowDown' ||
- event.code === 'ArrowUp' ||
- event.code === 'End' ||
- event.code === 'Home' ||
- event.code === 'Enter';
- // Do not open if currently typing ahead because the user may be typing the
- // spacebar to match a word with a space
- if (!typeaheadController.isTypingAhead && isOpenKey) {
- event.preventDefault();
- this.open = true;
- // https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/#kbd_label
- switch (event.code) {
- case 'Space':
- case 'ArrowDown':
- case 'Enter':
- // We will handle focusing last selected item in this.handleOpening()
- this.defaultFocus = _menu_internal_controllers_shared_js__WEBPACK_IMPORTED_MODULE_14__.FocusState.NONE;
- break;
- case 'End':
- this.defaultFocus = _menu_internal_controllers_shared_js__WEBPACK_IMPORTED_MODULE_14__.FocusState.LAST_ITEM;
- break;
- case 'ArrowUp':
- case 'Home':
- this.defaultFocus = _menu_internal_controllers_shared_js__WEBPACK_IMPORTED_MODULE_14__.FocusState.FIRST_ITEM;
- break;
- default:
- break;
- }
- return;
- }
- const isPrintableKey = event.key.length === 1;
- // Handles typing ahead when the menu is closed by delegating the event to
- // the underlying menu's typeaheadController
- if (isPrintableKey) {
- typeaheadController.onKeydown(event);
- event.preventDefault();
- const { lastActiveRecord } = typeaheadController;
- if (!lastActiveRecord) {
- return;
- }
- this.labelEl?.setAttribute?.('aria-live', 'polite');
- const hasChanged = this.selectItem(lastActiveRecord[_menu_internal_controllers_typeaheadController_js__WEBPACK_IMPORTED_MODULE_15__.TYPEAHEAD_RECORD.ITEM]);
- if (hasChanged) {
- this.dispatchInteractionEvents();
- }
- }
- }
- handleClick() {
- this.open = !this.open;
- }
- handleFocus() {
- this.focused = true;
- }
- handleBlur() {
- this.focused = false;
- }
- /**
- * Handles closing the menu when the focus leaves the select's subtree.
- */
- handleFocusout(event) {
- // Don't close the menu if we are switching focus between menu,
- // select-option, and field
- if (event.relatedTarget && (0,_menu_internal_controllers_shared_js__WEBPACK_IMPORTED_MODULE_14__.isElementInSubtree)(event.relatedTarget, this)) {
- return;
- }
- this.open = false;
- }
- /**
- * Gets a list of all selected select options as a list item record array.
- *
- * @return An array of selected list option records.
- */
- getSelectedOptions() {
- if (!this.menu) {
- this.lastSelectedOptionRecords = [];
- return null;
- }
- const items = this.menu.items;
- this.lastSelectedOptionRecords = (0,_shared_js__WEBPACK_IMPORTED_MODULE_17__.getSelectedItems)(items);
- return this.lastSelectedOptionRecords;
- }
- async getUpdateComplete() {
- await this.menu?.updateComplete;
- return super.getUpdateComplete();
- }
- /**
- * Gets the selected options from the DOM, and updates the value and display
- * text to the first selected option's value and headline respectively.
- *
- * @return Whether or not the selected option has changed since last update.
- */
- updateValueAndDisplayText() {
- const selectedOptions = this.getSelectedOptions() ?? [];
- // Used to determine whether or not we need to fire an input / change event
- // which fire whenever the option element changes (value or selectedIndex)
- // on user interaction.
- let hasSelectedOptionChanged = false;
- if (selectedOptions.length) {
- const [firstSelectedOption] = selectedOptions[0];
- hasSelectedOptionChanged =
- this.lastSelectedOption !== firstSelectedOption;
- this.lastSelectedOption = firstSelectedOption;
- this[VALUE] = firstSelectedOption.value;
- this.displayText = firstSelectedOption.displayText;
- }
- else {
- hasSelectedOptionChanged = this.lastSelectedOption !== null;
- this.lastSelectedOption = null;
- this[VALUE] = '';
- this.displayText = '';
- }
- return hasSelectedOptionChanged;
- }
- /**
- * Focuses and activates the last selected item upon opening, and resets other
- * active items.
- */
- async handleOpening(e) {
- this.labelEl?.removeAttribute?.('aria-live');
- this.redispatchEvent(e);
- // FocusState.NONE means we want to handle focus ourselves and focus the
- // last selected item.
- if (this.defaultFocus !== _menu_internal_controllers_shared_js__WEBPACK_IMPORTED_MODULE_14__.FocusState.NONE) {
- return;
- }
- const items = this.menu.items;
- const activeItem = (0,_list_internal_list_navigation_helpers_js__WEBPACK_IMPORTED_MODULE_13__.getActiveItem)(items)?.item;
- let [selectedItem] = this.lastSelectedOptionRecords[0] ?? [null];
- // This is true if the user keys through the list but clicks out of the menu
- // thus no close-menu event is fired by an item and we can't clean up in
- // handleCloseMenu.
- if (activeItem && activeItem !== selectedItem) {
- activeItem.tabIndex = -1;
- }
- // in the case that nothing is selected, focus the first item
- selectedItem = selectedItem ?? items[0];
- if (selectedItem) {
- selectedItem.tabIndex = 0;
- selectedItem.focus();
- }
- }
- redispatchEvent(e) {
- (0,_internal_events_redispatch_event_js__WEBPACK_IMPORTED_MODULE_7__.redispatchEvent)(this, e);
- }
- handleClosed(e) {
- this.open = false;
- this.redispatchEvent(e);
- }
- /**
- * Determines the reason for closing, and updates the UI accordingly.
- */
- handleCloseMenu(event) {
- const reason = event.detail.reason;
- const item = event.detail.itemPath[0];
- this.open = false;
- let hasChanged = false;
- if (reason.kind === 'click-selection') {
- hasChanged = this.selectItem(item);
- }
- else if (reason.kind === 'keydown' && (0,_menu_internal_controllers_shared_js__WEBPACK_IMPORTED_MODULE_14__.isSelectableKey)(reason.key)) {
- hasChanged = this.selectItem(item);
- }
- else {
- // This can happen on ESC being pressed
- item.tabIndex = -1;
- item.blur();
- }
- // Dispatch interaction events since selection has been made via keyboard
- // or mouse.
- if (hasChanged) {
- this.dispatchInteractionEvents();
- }
- }
- /**
- * Selects a given option, deselects other options, and updates the UI.
- *
- * @return Whether the last selected option has changed.
- */
- selectItem(item) {
- const selectedOptions = this.getSelectedOptions() ?? [];
- selectedOptions.forEach(([option]) => {
- if (item !== option) {
- option.selected = false;
- }
- });
- item.selected = true;
- return this.updateValueAndDisplayText();
- }
- /**
- * Handles updating selection when an option element requests selection via
- * property / attribute change.
- */
- handleRequestSelection(event) {
- const requestingOptionEl = event.target;
- // No-op if this item is already selected.
- if (this.lastSelectedOptionRecords.some(([option]) => option === requestingOptionEl)) {
- return;
- }
- this.selectItem(requestingOptionEl);
- }
- /**
- * Handles updating selection when an option element requests deselection via
- * property / attribute change.
- */
- handleRequestDeselection(event) {
- const requestingOptionEl = event.target;
- // No-op if this item is not even in the list of tracked selected items.
- if (!this.lastSelectedOptionRecords.some(([option]) => option === requestingOptionEl)) {
- return;
- }
- this.updateValueAndDisplayText();
- }
- /**
- * Attempts to initialize the selected option from user-settable values like
- * SSR, setting `value`, or `selectedIndex` at startup.
- */
- initUserSelection() {
- // User has set `.value` directly, but internals have not yet booted up.
- if (this.lastUserSetValue && !this.lastSelectedOptionRecords.length) {
- this.select(this.lastUserSetValue);
- // User has set `.selectedIndex` directly, but internals have not yet
- // booted up.
- }
- else if (this.lastUserSetSelectedIndex !== null &&
- !this.lastSelectedOptionRecords.length) {
- this.selectIndex(this.lastUserSetSelectedIndex);
- // Regular boot up!
- }
- else {
- this.updateValueAndDisplayText();
- }
- }
- handleIconChange() {
- this.hasLeadingIcon = this.leadingIcons.length > 0;
- }
- /**
- * Dispatches the `input` and `change` events.
- */
- dispatchInteractionEvents() {
- this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
- this.dispatchEvent(new Event('change', { bubbles: true }));
- }
- getErrorText() {
- return this.error ? this.errorText : this.nativeErrorText;
- }
- [_labs_behaviors_form_associated_js__WEBPACK_IMPORTED_MODULE_10__.getFormValue]() {
- return this.value;
- }
- formResetCallback() {
- this.reset();
- }
- formStateRestoreCallback(state) {
- this.value = state;
- }
- click() {
- this.field?.click();
- }
- [_labs_behaviors_constraint_validation_js__WEBPACK_IMPORTED_MODULE_8__.createValidator]() {
- return new _labs_behaviors_validators_select_validator_js__WEBPACK_IMPORTED_MODULE_12__.SelectValidator(() => this);
- }
- [_labs_behaviors_constraint_validation_js__WEBPACK_IMPORTED_MODULE_8__.getValidityAnchor]() {
- return this.field;
- }
-}
-/** @nocollapse */
-Select.shadowRootOptions = {
- ...lit__WEBPACK_IMPORTED_MODULE_1__.LitElement.shadowRootOptions,
- delegatesFocus: true,
-};
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ type: Boolean })
-], Select.prototype, "quick", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ type: Boolean })
-], Select.prototype, "required", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ type: String, attribute: 'error-text' })
-], Select.prototype, "errorText", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)()
-], Select.prototype, "label", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ type: Boolean, attribute: 'no-asterisk' })
-], Select.prototype, "noAsterisk", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ type: String, attribute: 'supporting-text' })
-], Select.prototype, "supportingText", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ type: Boolean, reflect: true })
-], Select.prototype, "error", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ attribute: 'menu-positioning' })
-], Select.prototype, "menuPositioning", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ type: Boolean, attribute: 'clamp-menu-width' })
-], Select.prototype, "clampMenuWidth", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ type: Number, attribute: 'typeahead-delay' })
-], Select.prototype, "typeaheadDelay", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ type: Boolean, attribute: 'has-leading-icon' })
-], Select.prototype, "hasLeadingIcon", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ attribute: 'display-text' })
-], Select.prototype, "displayText", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ attribute: 'menu-align' })
-], Select.prototype, "menuAlign", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)()
-], Select.prototype, "value", null);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.property)({ type: Number, attribute: 'selected-index' })
-], Select.prototype, "selectedIndex", null);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.state)()
-], Select.prototype, "nativeError", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.state)()
-], Select.prototype, "nativeErrorText", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.state)()
-], Select.prototype, "focused", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.state)()
-], Select.prototype, "open", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.state)()
-], Select.prototype, "defaultFocus", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.query)('.field')
-], Select.prototype, "field", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.query)('md-menu')
-], Select.prototype, "menu", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.query)('#label')
-], Select.prototype, "labelEl", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_18__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_2__.queryAssignedElements)({ slot: 'leading-icon', flatten: true })
-], Select.prototype, "leadingIcons", void 0);
-//# sourceMappingURL=select.js.map
-
-/***/ }),
-
-/***/ "./node_modules/@material/web/select/internal/selectoption/select-option.js":
-/*!**********************************************************************************!*\
- !*** ./node_modules/@material/web/select/internal/selectoption/select-option.js ***!
- \**********************************************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ SelectOptionEl: () => (/* binding */ SelectOptionEl)
-/* harmony export */ });
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
-/* harmony import */ var _focus_md_focus_ring_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../focus/md-focus-ring.js */ "./node_modules/@material/web/focus/md-focus-ring.js");
-/* harmony import */ var _labs_item_item_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../labs/item/item.js */ "./node_modules/@material/web/labs/item/item.js");
-/* harmony import */ var _ripple_ripple_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../ripple/ripple.js */ "./node_modules/@material/web/ripple/ripple.js");
-/* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! lit */ "./node_modules/lit/index.js");
-/* harmony import */ var lit_decorators_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! lit/decorators.js */ "./node_modules/lit/decorators.js");
-/* harmony import */ var lit_directives_class_map_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! lit/directives/class-map.js */ "./node_modules/lit/directives/class-map.js");
-/* harmony import */ var _internal_aria_delegate_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../internal/aria/delegate.js */ "./node_modules/@material/web/internal/aria/delegate.js");
-/* harmony import */ var _selectOptionController_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./selectOptionController.js */ "./node_modules/@material/web/select/internal/selectoption/selectOptionController.js");
-/**
- * @license
- * Copyright 2023 Google LLC
- * SPDX-License-Identifier: Apache-2.0
- */
-
-
-
-
-
-
-
-
-
-// Separate variable needed for closure.
-const selectOptionBaseClass = (0,_internal_aria_delegate_js__WEBPACK_IMPORTED_MODULE_6__.mixinDelegatesAria)(lit__WEBPACK_IMPORTED_MODULE_3__.LitElement);
-/**
- * @fires close-menu {CustomEvent<{initiator: SelectOption, reason: Reason, itemPath: SelectOption[]}>}
- * Closes the encapsulating menu on closable interaction. --bubbles --composed
- * @fires request-selection {Event} Requests the parent md-select to select this
- * element (and deselect others if single-selection) when `selected` changed to
- * `true`. --bubbles --composed
- * @fires request-deselection {Event} Requests the parent md-select to deselect
- * this element when `selected` changed to `false`. --bubbles --composed
- */
-class SelectOptionEl extends selectOptionBaseClass {
- constructor() {
- super(...arguments);
- /**
- * Disables the item and makes it non-selectable and non-interactive.
- */
- this.disabled = false;
- /**
- * READONLY: self-identifies as a menu item and sets its identifying attribute
- */
- this.isMenuItem = true;
- /**
- * Sets the item in the selected visual state when a submenu is opened.
- */
- this.selected = false;
- /**
- * Form value of the option.
- */
- this.value = '';
- this.type = 'option';
- this.selectOptionController = new _selectOptionController_js__WEBPACK_IMPORTED_MODULE_7__.SelectOptionController(this, {
- getHeadlineElements: () => {
- return this.headlineElements;
- },
- getSupportingTextElements: () => {
- return this.supportingTextElements;
- },
- getDefaultElements: () => {
- return this.defaultElements;
- },
- getInteractiveElement: () => this.listItemRoot,
- });
- }
- /**
- * The text that is selectable via typeahead. If not set, defaults to the
- * innerText of the item slotted into the `"headline"` slot.
- */
- get typeaheadText() {
- return this.selectOptionController.typeaheadText;
- }
- set typeaheadText(text) {
- this.selectOptionController.setTypeaheadText(text);
- }
- /**
- * The text that is displayed in the select field when selected. If not set,
- * defaults to the textContent of the item slotted into the `"headline"` slot.
- */
- get displayText() {
- return this.selectOptionController.displayText;
- }
- set displayText(text) {
- this.selectOptionController.setDisplayText(text);
- }
- render() {
- return this.renderListItem((0,lit__WEBPACK_IMPORTED_MODULE_3__.html) `
-
-
- ${this.renderRipple()} ${this.renderFocusRing()}
-
-
-
- ${this.renderBody()}
-
- `);
- }
- /**
- * Renders the root list item.
- *
- * @param content the child content of the list item.
- */
- renderListItem(content) {
- return (0,lit__WEBPACK_IMPORTED_MODULE_3__.html) `
- ${content}
- `;
- }
- /**
- * Handles rendering of the ripple element.
- */
- renderRipple() {
- return (0,lit__WEBPACK_IMPORTED_MODULE_3__.html) ` `;
- }
- /**
- * Handles rendering of the focus ring.
- */
- renderFocusRing() {
- return (0,lit__WEBPACK_IMPORTED_MODULE_3__.html) ` `;
- }
- /**
- * Classes applied to the list item root.
- */
- getRenderClasses() {
- return {
- 'disabled': this.disabled,
- 'selected': this.selected,
- };
- }
- /**
- * Handles rendering the headline and supporting text.
- */
- renderBody() {
- return (0,lit__WEBPACK_IMPORTED_MODULE_3__.html) `
-
-
-
-
-
- `;
- }
- focus() {
- // TODO(b/300334509): needed for some cases where delegatesFocus doesn't
- // work programmatically like in FF and select-option
- this.listItemRoot?.focus();
- }
-}
-/** @nocollapse */
-SelectOptionEl.shadowRootOptions = {
- ...lit__WEBPACK_IMPORTED_MODULE_3__.LitElement.shadowRootOptions,
- delegatesFocus: true,
-};
-(0,tslib__WEBPACK_IMPORTED_MODULE_8__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_4__.property)({ type: Boolean, reflect: true })
-], SelectOptionEl.prototype, "disabled", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_8__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_4__.property)({ type: Boolean, attribute: 'md-menu-item', reflect: true })
-], SelectOptionEl.prototype, "isMenuItem", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_8__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_4__.property)({ type: Boolean })
-], SelectOptionEl.prototype, "selected", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_8__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_4__.property)()
-], SelectOptionEl.prototype, "value", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_8__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_4__.query)('.list-item')
-], SelectOptionEl.prototype, "listItemRoot", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_8__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_4__.queryAssignedElements)({ slot: 'headline' })
-], SelectOptionEl.prototype, "headlineElements", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_8__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_4__.queryAssignedElements)({ slot: 'supporting-text' })
-], SelectOptionEl.prototype, "supportingTextElements", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_8__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_4__.queryAssignedNodes)({ slot: '' })
-], SelectOptionEl.prototype, "defaultElements", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_8__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_4__.property)({ attribute: 'typeahead-text' })
-], SelectOptionEl.prototype, "typeaheadText", null);
-(0,tslib__WEBPACK_IMPORTED_MODULE_8__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_4__.property)({ attribute: 'display-text' })
-], SelectOptionEl.prototype, "displayText", null);
-//# sourceMappingURL=select-option.js.map
-
-/***/ }),
-
-/***/ "./node_modules/@material/web/select/internal/selectoption/selectOptionController.js":
-/*!*******************************************************************************************!*\
- !*** ./node_modules/@material/web/select/internal/selectoption/selectOptionController.js ***!
- \*******************************************************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ SelectOptionController: () => (/* binding */ SelectOptionController),
-/* harmony export */ createRequestDeselectionEvent: () => (/* binding */ createRequestDeselectionEvent),
-/* harmony export */ createRequestSelectionEvent: () => (/* binding */ createRequestSelectionEvent)
-/* harmony export */ });
-/* harmony import */ var _menu_internal_controllers_menuItemController_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../menu/internal/controllers/menuItemController.js */ "./node_modules/@material/web/menu/internal/controllers/menuItemController.js");
-/**
- * @license
- * Copyright 2023 Google LLC
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/**
- * Creates an event fired by a SelectOption to request selection from md-select.
- * Typically fired after `selected` changes from `false` to `true`.
- */
-function createRequestSelectionEvent() {
- return new Event('request-selection', {
- bubbles: true,
- composed: true,
- });
-}
-/**
- * Creates an event fired by a SelectOption to request deselection from
- * md-select. Typically fired after `selected` changes from `true` to `false`.
- */
-function createRequestDeselectionEvent() {
- return new Event('request-deselection', {
- bubbles: true,
- composed: true,
- });
-}
-/**
- * A controller that provides most functionality and md-select compatibility for
- * an element that implements the SelectOption interface.
- */
-class SelectOptionController {
- /**
- * The recommended role of the select option.
- */
- get role() {
- return this.menuItemController.role;
- }
- /**
- * The text that is selectable via typeahead. If not set, defaults to the
- * innerText of the item slotted into the `"headline"` slot, and if there are
- * no slotted elements into headline, then it checks the _default_ slot, and
- * then the `"supporting-text"` slot if nothing is in _default_.
- */
- get typeaheadText() {
- return this.menuItemController.typeaheadText;
- }
- setTypeaheadText(text) {
- this.menuItemController.setTypeaheadText(text);
- }
- /**
- * The text that is displayed in the select field when selected. If not set,
- * defaults to the textContent of the item slotted into the `"headline"` slot,
- * and if there are no slotted elements into headline, then it checks the
- * _default_ slot, and then the `"supporting-text"` slot if nothing is in
- * _default_.
- */
- get displayText() {
- if (this.internalDisplayText !== null) {
- return this.internalDisplayText;
- }
- return this.menuItemController.typeaheadText;
- }
- setDisplayText(text) {
- this.internalDisplayText = text;
- }
- /**
- * @param host The SelectOption in which to attach this controller to.
- * @param config The object that configures this controller's behavior.
- */
- constructor(host, config) {
- this.host = host;
- this.internalDisplayText = null;
- this.firstUpdate = true;
- /**
- * Bind this click listener to the interactive element. Handles closing the
- * menu.
- */
- this.onClick = () => {
- this.menuItemController.onClick();
- };
- /**
- * Bind this click listener to the interactive element. Handles closing the
- * menu.
- */
- this.onKeydown = (e) => {
- this.menuItemController.onKeydown(e);
- };
- this.lastSelected = this.host.selected;
- this.menuItemController = new _menu_internal_controllers_menuItemController_js__WEBPACK_IMPORTED_MODULE_0__.MenuItemController(host, config);
- host.addController(this);
- }
- hostUpdate() {
- if (this.lastSelected !== this.host.selected) {
- this.host.ariaSelected = this.host.selected ? 'true' : 'false';
- }
- }
- hostUpdated() {
- // Do not dispatch event on first update / boot-up.
- if (this.lastSelected !== this.host.selected && !this.firstUpdate) {
- // This section is really useful for when the user sets selected on the
- // option programmatically. Most other cases (click and keyboard) are
- // handled by md-select because it needs to coordinate the
- // single-selection behavior.
- if (this.host.selected) {
- this.host.dispatchEvent(createRequestSelectionEvent());
- }
- else {
- this.host.dispatchEvent(createRequestDeselectionEvent());
- }
- }
- this.lastSelected = this.host.selected;
- this.firstUpdate = false;
- }
-}
-//# sourceMappingURL=selectOptionController.js.map
-
-/***/ }),
-
-/***/ "./node_modules/@material/web/select/internal/shared-styles.js":
-/*!*********************************************************************!*\
- !*** ./node_modules/@material/web/select/internal/shared-styles.js ***!
- \*********************************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ styles: () => (/* binding */ styles)
-/* harmony export */ });
-/* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lit */ "./node_modules/lit/index.js");
-/**
- * @license
- * Copyright 2024 Google LLC
- * SPDX-License-Identifier: Apache-2.0
- */
-// Generated stylesheet for ./select/internal/shared-styles.css.
-
-const styles = (0,lit__WEBPACK_IMPORTED_MODULE_0__.css) `:host{color:unset;min-width:210px;display:flex}.field{cursor:default;outline:none}.select{position:relative;flex-direction:column}.icon.trailing svg,.icon ::slotted(*){fill:currentColor}.icon ::slotted(*){width:inherit;height:inherit;font-size:inherit}.icon slot{display:flex;height:100%;width:100%;align-items:center;justify-content:center}.icon.trailing :is(.up,.down){opacity:0;transition:opacity 75ms linear 75ms}.select:not(.open) .down,.select.open .up{opacity:1}.field,.select,md-menu{min-width:inherit;width:inherit;max-width:inherit;display:flex}md-menu{min-width:var(--__menu-min-width);max-width:var(--__menu-max-width, inherit)}.menu-wrapper{width:0px;height:0px;max-width:inherit}md-menu ::slotted(:not[disabled]){cursor:pointer}.field,.select{width:100%}:host{display:inline-flex}:host([disabled]){pointer-events:none}
-`;
-//# sourceMappingURL=shared-styles.js.map
-
-/***/ }),
-
-/***/ "./node_modules/@material/web/select/internal/shared.js":
-/*!**************************************************************!*\
- !*** ./node_modules/@material/web/select/internal/shared.js ***!
- \**************************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ getSelectedItems: () => (/* binding */ getSelectedItems)
-/* harmony export */ });
-/**
- * @license
- * Copyright 2023 Google LLC
- * SPDX-License-Identifier: Apache-2.0
- */
-/**
- * Given a list of select options, this function will return an array of
- * SelectOptionRecords that are selected.
- *
- * @return An array of SelectOptionRecords describing the options that are
- * selected.
- */
-function getSelectedItems(items) {
- const selectedItemRecords = [];
- for (let i = 0; i < items.length; i++) {
- const item = items[i];
- if (item.selected) {
- selectedItemRecords.push([item, i]);
- }
- }
- return selectedItemRecords;
-}
-//# sourceMappingURL=shared.js.map
-
-/***/ }),
-
-/***/ "./node_modules/@material/web/textfield/internal/filled-styles.js":
-/*!************************************************************************!*\
- !*** ./node_modules/@material/web/textfield/internal/filled-styles.js ***!
- \************************************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ styles: () => (/* binding */ styles)
-/* harmony export */ });
-/* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lit */ "./node_modules/lit/index.js");
-/**
- * @license
- * Copyright 2024 Google LLC
- * SPDX-License-Identifier: Apache-2.0
- */
-// Generated stylesheet for ./textfield/internal/filled-styles.css.
-
-const styles = (0,lit__WEBPACK_IMPORTED_MODULE_0__.css) `:host{--_active-indicator-color: var(--md-filled-text-field-active-indicator-color, var(--md-sys-color-on-surface-variant, #49454f));--_active-indicator-height: var(--md-filled-text-field-active-indicator-height, 1px);--_caret-color: var(--md-filled-text-field-caret-color, var(--md-sys-color-primary, #6750a4));--_container-color: var(--md-filled-text-field-container-color, var(--md-sys-color-surface-container-highest, #e6e0e9));--_disabled-active-indicator-color: var(--md-filled-text-field-disabled-active-indicator-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-active-indicator-height: var(--md-filled-text-field-disabled-active-indicator-height, 1px);--_disabled-active-indicator-opacity: var(--md-filled-text-field-disabled-active-indicator-opacity, 0.38);--_disabled-container-color: var(--md-filled-text-field-disabled-container-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-container-opacity: var(--md-filled-text-field-disabled-container-opacity, 0.04);--_disabled-input-text-color: var(--md-filled-text-field-disabled-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-input-text-opacity: var(--md-filled-text-field-disabled-input-text-opacity, 0.38);--_disabled-label-text-color: var(--md-filled-text-field-disabled-label-text-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-label-text-opacity: var(--md-filled-text-field-disabled-label-text-opacity, 0.38);--_disabled-leading-icon-color: var(--md-filled-text-field-disabled-leading-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-leading-icon-opacity: var(--md-filled-text-field-disabled-leading-icon-opacity, 0.38);--_disabled-supporting-text-color: var(--md-filled-text-field-disabled-supporting-text-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-supporting-text-opacity: var(--md-filled-text-field-disabled-supporting-text-opacity, 0.38);--_disabled-trailing-icon-color: var(--md-filled-text-field-disabled-trailing-icon-color, var(--md-sys-color-on-surface, #1d1b20));--_disabled-trailing-icon-opacity: var(--md-filled-text-field-disabled-trailing-icon-opacity, 0.38);--_error-active-indicator-color: var(--md-filled-text-field-error-active-indicator-color, var(--md-sys-color-error, #b3261e));--_error-focus-active-indicator-color: var(--md-filled-text-field-error-focus-active-indicator-color, var(--md-sys-color-error, #b3261e));--_error-focus-caret-color: var(--md-filled-text-field-error-focus-caret-color, var(--md-sys-color-error, #b3261e));--_error-focus-input-text-color: var(--md-filled-text-field-error-focus-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_error-focus-label-text-color: var(--md-filled-text-field-error-focus-label-text-color, var(--md-sys-color-error, #b3261e));--_error-focus-leading-icon-color: var(--md-filled-text-field-error-focus-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_error-focus-supporting-text-color: var(--md-filled-text-field-error-focus-supporting-text-color, var(--md-sys-color-error, #b3261e));--_error-focus-trailing-icon-color: var(--md-filled-text-field-error-focus-trailing-icon-color, var(--md-sys-color-error, #b3261e));--_error-hover-active-indicator-color: var(--md-filled-text-field-error-hover-active-indicator-color, var(--md-sys-color-on-error-container, #410e0b));--_error-hover-input-text-color: var(--md-filled-text-field-error-hover-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_error-hover-label-text-color: var(--md-filled-text-field-error-hover-label-text-color, var(--md-sys-color-on-error-container, #410e0b));--_error-hover-leading-icon-color: var(--md-filled-text-field-error-hover-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_error-hover-state-layer-color: var(--md-filled-text-field-error-hover-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--_error-hover-state-layer-opacity: var(--md-filled-text-field-error-hover-state-layer-opacity, 0.08);--_error-hover-supporting-text-color: var(--md-filled-text-field-error-hover-supporting-text-color, var(--md-sys-color-error, #b3261e));--_error-hover-trailing-icon-color: var(--md-filled-text-field-error-hover-trailing-icon-color, var(--md-sys-color-on-error-container, #410e0b));--_error-input-text-color: var(--md-filled-text-field-error-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_error-label-text-color: var(--md-filled-text-field-error-label-text-color, var(--md-sys-color-error, #b3261e));--_error-leading-icon-color: var(--md-filled-text-field-error-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_error-supporting-text-color: var(--md-filled-text-field-error-supporting-text-color, var(--md-sys-color-error, #b3261e));--_error-trailing-icon-color: var(--md-filled-text-field-error-trailing-icon-color, var(--md-sys-color-error, #b3261e));--_focus-active-indicator-color: var(--md-filled-text-field-focus-active-indicator-color, var(--md-sys-color-primary, #6750a4));--_focus-active-indicator-height: var(--md-filled-text-field-focus-active-indicator-height, 3px);--_focus-input-text-color: var(--md-filled-text-field-focus-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_focus-label-text-color: var(--md-filled-text-field-focus-label-text-color, var(--md-sys-color-primary, #6750a4));--_focus-leading-icon-color: var(--md-filled-text-field-focus-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_focus-supporting-text-color: var(--md-filled-text-field-focus-supporting-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_focus-trailing-icon-color: var(--md-filled-text-field-focus-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-active-indicator-color: var(--md-filled-text-field-hover-active-indicator-color, var(--md-sys-color-on-surface, #1d1b20));--_hover-active-indicator-height: var(--md-filled-text-field-hover-active-indicator-height, 1px);--_hover-input-text-color: var(--md-filled-text-field-hover-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_hover-label-text-color: var(--md-filled-text-field-hover-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-leading-icon-color: var(--md-filled-text-field-hover-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-state-layer-color: var(--md-filled-text-field-hover-state-layer-color, var(--md-sys-color-on-surface, #1d1b20));--_hover-state-layer-opacity: var(--md-filled-text-field-hover-state-layer-opacity, 0.08);--_hover-supporting-text-color: var(--md-filled-text-field-hover-supporting-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_hover-trailing-icon-color: var(--md-filled-text-field-hover-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_input-text-color: var(--md-filled-text-field-input-text-color, var(--md-sys-color-on-surface, #1d1b20));--_input-text-font: var(--md-filled-text-field-input-text-font, var(--md-sys-typescale-body-large-font, var(--md-ref-typeface-plain, Roboto)));--_input-text-line-height: var(--md-filled-text-field-input-text-line-height, var(--md-sys-typescale-body-large-line-height, 1.5rem));--_input-text-placeholder-color: var(--md-filled-text-field-input-text-placeholder-color, var(--md-sys-color-on-surface-variant, #49454f));--_input-text-prefix-color: var(--md-filled-text-field-input-text-prefix-color, var(--md-sys-color-on-surface-variant, #49454f));--_input-text-size: var(--md-filled-text-field-input-text-size, var(--md-sys-typescale-body-large-size, 1rem));--_input-text-suffix-color: var(--md-filled-text-field-input-text-suffix-color, var(--md-sys-color-on-surface-variant, #49454f));--_input-text-weight: var(--md-filled-text-field-input-text-weight, var(--md-sys-typescale-body-large-weight, var(--md-ref-typeface-weight-regular, 400)));--_label-text-color: var(--md-filled-text-field-label-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_label-text-font: var(--md-filled-text-field-label-text-font, var(--md-sys-typescale-body-large-font, var(--md-ref-typeface-plain, Roboto)));--_label-text-line-height: var(--md-filled-text-field-label-text-line-height, var(--md-sys-typescale-body-large-line-height, 1.5rem));--_label-text-populated-line-height: var(--md-filled-text-field-label-text-populated-line-height, var(--md-sys-typescale-body-small-line-height, 1rem));--_label-text-populated-size: var(--md-filled-text-field-label-text-populated-size, var(--md-sys-typescale-body-small-size, 0.75rem));--_label-text-size: var(--md-filled-text-field-label-text-size, var(--md-sys-typescale-body-large-size, 1rem));--_label-text-weight: var(--md-filled-text-field-label-text-weight, var(--md-sys-typescale-body-large-weight, var(--md-ref-typeface-weight-regular, 400)));--_leading-icon-color: var(--md-filled-text-field-leading-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_leading-icon-size: var(--md-filled-text-field-leading-icon-size, 24px);--_supporting-text-color: var(--md-filled-text-field-supporting-text-color, var(--md-sys-color-on-surface-variant, #49454f));--_supporting-text-font: var(--md-filled-text-field-supporting-text-font, var(--md-sys-typescale-body-small-font, var(--md-ref-typeface-plain, Roboto)));--_supporting-text-line-height: var(--md-filled-text-field-supporting-text-line-height, var(--md-sys-typescale-body-small-line-height, 1rem));--_supporting-text-size: var(--md-filled-text-field-supporting-text-size, var(--md-sys-typescale-body-small-size, 0.75rem));--_supporting-text-weight: var(--md-filled-text-field-supporting-text-weight, var(--md-sys-typescale-body-small-weight, var(--md-ref-typeface-weight-regular, 400)));--_trailing-icon-color: var(--md-filled-text-field-trailing-icon-color, var(--md-sys-color-on-surface-variant, #49454f));--_trailing-icon-size: var(--md-filled-text-field-trailing-icon-size, 24px);--_container-shape-start-start: var(--md-filled-text-field-container-shape-start-start, var(--md-filled-text-field-container-shape, var(--md-sys-shape-corner-extra-small, 4px)));--_container-shape-start-end: var(--md-filled-text-field-container-shape-start-end, var(--md-filled-text-field-container-shape, var(--md-sys-shape-corner-extra-small, 4px)));--_container-shape-end-end: var(--md-filled-text-field-container-shape-end-end, var(--md-filled-text-field-container-shape, var(--md-sys-shape-corner-none, 0px)));--_container-shape-end-start: var(--md-filled-text-field-container-shape-end-start, var(--md-filled-text-field-container-shape, var(--md-sys-shape-corner-none, 0px)));--_icon-input-space: var(--md-filled-text-field-icon-input-space, 16px);--_leading-space: var(--md-filled-text-field-leading-space, 16px);--_trailing-space: var(--md-filled-text-field-trailing-space, 16px);--_top-space: var(--md-filled-text-field-top-space, 16px);--_bottom-space: var(--md-filled-text-field-bottom-space, 16px);--_input-text-prefix-trailing-space: var(--md-filled-text-field-input-text-prefix-trailing-space, 2px);--_input-text-suffix-leading-space: var(--md-filled-text-field-input-text-suffix-leading-space, 2px);--_with-label-top-space: var(--md-filled-text-field-with-label-top-space, 8px);--_with-label-bottom-space: var(--md-filled-text-field-with-label-bottom-space, 8px);--_focus-caret-color: var(--md-filled-text-field-focus-caret-color, var(--md-sys-color-primary, #6750a4));--_with-leading-icon-leading-space: var(--md-filled-text-field-with-leading-icon-leading-space, 12px);--_with-trailing-icon-trailing-space: var(--md-filled-text-field-with-trailing-icon-trailing-space, 12px);--md-filled-field-active-indicator-color: var(--_active-indicator-color);--md-filled-field-active-indicator-height: var(--_active-indicator-height);--md-filled-field-bottom-space: var(--_bottom-space);--md-filled-field-container-color: var(--_container-color);--md-filled-field-container-shape-end-end: var(--_container-shape-end-end);--md-filled-field-container-shape-end-start: var(--_container-shape-end-start);--md-filled-field-container-shape-start-end: var(--_container-shape-start-end);--md-filled-field-container-shape-start-start: var(--_container-shape-start-start);--md-filled-field-content-color: var(--_input-text-color);--md-filled-field-content-font: var(--_input-text-font);--md-filled-field-content-line-height: var(--_input-text-line-height);--md-filled-field-content-size: var(--_input-text-size);--md-filled-field-content-space: var(--_icon-input-space);--md-filled-field-content-weight: var(--_input-text-weight);--md-filled-field-disabled-active-indicator-color: var(--_disabled-active-indicator-color);--md-filled-field-disabled-active-indicator-height: var(--_disabled-active-indicator-height);--md-filled-field-disabled-active-indicator-opacity: var(--_disabled-active-indicator-opacity);--md-filled-field-disabled-container-color: var(--_disabled-container-color);--md-filled-field-disabled-container-opacity: var(--_disabled-container-opacity);--md-filled-field-disabled-content-color: var(--_disabled-input-text-color);--md-filled-field-disabled-content-opacity: var(--_disabled-input-text-opacity);--md-filled-field-disabled-label-text-color: var(--_disabled-label-text-color);--md-filled-field-disabled-label-text-opacity: var(--_disabled-label-text-opacity);--md-filled-field-disabled-leading-content-color: var(--_disabled-leading-icon-color);--md-filled-field-disabled-leading-content-opacity: var(--_disabled-leading-icon-opacity);--md-filled-field-disabled-supporting-text-color: var(--_disabled-supporting-text-color);--md-filled-field-disabled-supporting-text-opacity: var(--_disabled-supporting-text-opacity);--md-filled-field-disabled-trailing-content-color: var(--_disabled-trailing-icon-color);--md-filled-field-disabled-trailing-content-opacity: var(--_disabled-trailing-icon-opacity);--md-filled-field-error-active-indicator-color: var(--_error-active-indicator-color);--md-filled-field-error-content-color: var(--_error-input-text-color);--md-filled-field-error-focus-active-indicator-color: var(--_error-focus-active-indicator-color);--md-filled-field-error-focus-content-color: var(--_error-focus-input-text-color);--md-filled-field-error-focus-label-text-color: var(--_error-focus-label-text-color);--md-filled-field-error-focus-leading-content-color: var(--_error-focus-leading-icon-color);--md-filled-field-error-focus-supporting-text-color: var(--_error-focus-supporting-text-color);--md-filled-field-error-focus-trailing-content-color: var(--_error-focus-trailing-icon-color);--md-filled-field-error-hover-active-indicator-color: var(--_error-hover-active-indicator-color);--md-filled-field-error-hover-content-color: var(--_error-hover-input-text-color);--md-filled-field-error-hover-label-text-color: var(--_error-hover-label-text-color);--md-filled-field-error-hover-leading-content-color: var(--_error-hover-leading-icon-color);--md-filled-field-error-hover-state-layer-color: var(--_error-hover-state-layer-color);--md-filled-field-error-hover-state-layer-opacity: var(--_error-hover-state-layer-opacity);--md-filled-field-error-hover-supporting-text-color: var(--_error-hover-supporting-text-color);--md-filled-field-error-hover-trailing-content-color: var(--_error-hover-trailing-icon-color);--md-filled-field-error-label-text-color: var(--_error-label-text-color);--md-filled-field-error-leading-content-color: var(--_error-leading-icon-color);--md-filled-field-error-supporting-text-color: var(--_error-supporting-text-color);--md-filled-field-error-trailing-content-color: var(--_error-trailing-icon-color);--md-filled-field-focus-active-indicator-color: var(--_focus-active-indicator-color);--md-filled-field-focus-active-indicator-height: var(--_focus-active-indicator-height);--md-filled-field-focus-content-color: var(--_focus-input-text-color);--md-filled-field-focus-label-text-color: var(--_focus-label-text-color);--md-filled-field-focus-leading-content-color: var(--_focus-leading-icon-color);--md-filled-field-focus-supporting-text-color: var(--_focus-supporting-text-color);--md-filled-field-focus-trailing-content-color: var(--_focus-trailing-icon-color);--md-filled-field-hover-active-indicator-color: var(--_hover-active-indicator-color);--md-filled-field-hover-active-indicator-height: var(--_hover-active-indicator-height);--md-filled-field-hover-content-color: var(--_hover-input-text-color);--md-filled-field-hover-label-text-color: var(--_hover-label-text-color);--md-filled-field-hover-leading-content-color: var(--_hover-leading-icon-color);--md-filled-field-hover-state-layer-color: var(--_hover-state-layer-color);--md-filled-field-hover-state-layer-opacity: var(--_hover-state-layer-opacity);--md-filled-field-hover-supporting-text-color: var(--_hover-supporting-text-color);--md-filled-field-hover-trailing-content-color: var(--_hover-trailing-icon-color);--md-filled-field-label-text-color: var(--_label-text-color);--md-filled-field-label-text-font: var(--_label-text-font);--md-filled-field-label-text-line-height: var(--_label-text-line-height);--md-filled-field-label-text-populated-line-height: var(--_label-text-populated-line-height);--md-filled-field-label-text-populated-size: var(--_label-text-populated-size);--md-filled-field-label-text-size: var(--_label-text-size);--md-filled-field-label-text-weight: var(--_label-text-weight);--md-filled-field-leading-content-color: var(--_leading-icon-color);--md-filled-field-leading-space: var(--_leading-space);--md-filled-field-supporting-text-color: var(--_supporting-text-color);--md-filled-field-supporting-text-font: var(--_supporting-text-font);--md-filled-field-supporting-text-line-height: var(--_supporting-text-line-height);--md-filled-field-supporting-text-size: var(--_supporting-text-size);--md-filled-field-supporting-text-weight: var(--_supporting-text-weight);--md-filled-field-top-space: var(--_top-space);--md-filled-field-trailing-content-color: var(--_trailing-icon-color);--md-filled-field-trailing-space: var(--_trailing-space);--md-filled-field-with-label-bottom-space: var(--_with-label-bottom-space);--md-filled-field-with-label-top-space: var(--_with-label-top-space);--md-filled-field-with-leading-content-leading-space: var(--_with-leading-icon-leading-space);--md-filled-field-with-trailing-content-trailing-space: var(--_with-trailing-icon-trailing-space)}
-`;
-//# sourceMappingURL=filled-styles.js.map
-
-/***/ }),
-
-/***/ "./node_modules/@material/web/textfield/internal/filled-text-field.js":
-/*!****************************************************************************!*\
- !*** ./node_modules/@material/web/textfield/internal/filled-text-field.js ***!
- \****************************************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ FilledTextField: () => (/* binding */ FilledTextField)
-/* harmony export */ });
-/* harmony import */ var _field_filled_field_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../field/filled-field.js */ "./node_modules/@material/web/field/filled-field.js");
-/* harmony import */ var lit_static_html_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! lit/static-html.js */ "./node_modules/lit/static-html.js");
-/* harmony import */ var _text_field_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./text-field.js */ "./node_modules/@material/web/textfield/internal/text-field.js");
-/**
- * @license
- * Copyright 2021 Google LLC
- * SPDX-License-Identifier: Apache-2.0
- */
-
-
-
-/**
- * A filled text field component.
- */
-class FilledTextField extends _text_field_js__WEBPACK_IMPORTED_MODULE_2__.TextField {
- constructor() {
- super(...arguments);
- this.fieldTag = (0,lit_static_html_js__WEBPACK_IMPORTED_MODULE_1__.literal) `md-filled-field`;
- }
-}
-//# sourceMappingURL=filled-text-field.js.map
-
-/***/ }),
-
-/***/ "./node_modules/@material/web/textfield/internal/shared-styles.js":
-/*!************************************************************************!*\
- !*** ./node_modules/@material/web/textfield/internal/shared-styles.js ***!
- \************************************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ styles: () => (/* binding */ styles)
-/* harmony export */ });
-/* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lit */ "./node_modules/lit/index.js");
-/**
- * @license
- * Copyright 2024 Google LLC
- * SPDX-License-Identifier: Apache-2.0
- */
-// Generated stylesheet for ./textfield/internal/shared-styles.css.
-
-const styles = (0,lit__WEBPACK_IMPORTED_MODULE_0__.css) `:host{display:inline-flex;outline:none;resize:both;text-align:start;-webkit-tap-highlight-color:rgba(0,0,0,0)}.text-field,.field{width:100%}.text-field{display:inline-flex}.field{cursor:text}.disabled .field{cursor:default}.text-field,.textarea .field{resize:inherit}slot[name=container]{border-radius:inherit}.icon{color:currentColor;display:flex;align-items:center;justify-content:center;fill:currentColor;position:relative}.icon ::slotted(*){display:flex;position:absolute}[has-start] .icon.leading{font-size:var(--_leading-icon-size);height:var(--_leading-icon-size);width:var(--_leading-icon-size)}[has-end] .icon.trailing{font-size:var(--_trailing-icon-size);height:var(--_trailing-icon-size);width:var(--_trailing-icon-size)}.input-wrapper{display:flex}.input-wrapper>*{all:inherit;padding:0}.input{caret-color:var(--_caret-color);overflow-x:hidden;text-align:inherit}.input::placeholder{color:currentColor;opacity:1}.input::-webkit-calendar-picker-indicator{display:none}.input::-webkit-search-decoration,.input::-webkit-search-cancel-button{display:none}@media(forced-colors: active){.input{background:none}}.no-spinner .input::-webkit-inner-spin-button,.no-spinner .input::-webkit-outer-spin-button{display:none}.no-spinner .input[type=number]{-moz-appearance:textfield}:focus-within .input{caret-color:var(--_focus-caret-color)}.error:focus-within .input{caret-color:var(--_error-focus-caret-color)}.text-field:not(.disabled) .prefix{color:var(--_input-text-prefix-color)}.text-field:not(.disabled) .suffix{color:var(--_input-text-suffix-color)}.text-field:not(.disabled) .input::placeholder{color:var(--_input-text-placeholder-color)}.prefix,.suffix{text-wrap:nowrap;width:min-content}.prefix{padding-inline-end:var(--_input-text-prefix-trailing-space)}.suffix{padding-inline-start:var(--_input-text-suffix-leading-space)}
-`;
-//# sourceMappingURL=shared-styles.js.map
-
-/***/ }),
-
-/***/ "./node_modules/@material/web/textfield/internal/text-field.js":
-/*!*********************************************************************!*\
- !*** ./node_modules/@material/web/textfield/internal/text-field.js ***!
- \*********************************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ TextField: () => (/* binding */ TextField)
-/* harmony export */ });
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
-/* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lit */ "./node_modules/lit/index.js");
-/* harmony import */ var lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! lit/decorators.js */ "./node_modules/lit/decorators.js");
-/* harmony import */ var lit_directives_class_map_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! lit/directives/class-map.js */ "./node_modules/lit/directives/class-map.js");
-/* harmony import */ var lit_directives_live_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! lit/directives/live.js */ "./node_modules/lit/directives/live.js");
-/* harmony import */ var lit_directives_style_map_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! lit/directives/style-map.js */ "./node_modules/lit/directives/style-map.js");
-/* harmony import */ var lit_static_html_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! lit/static-html.js */ "./node_modules/lit/static-html.js");
-/* harmony import */ var _internal_aria_delegate_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../internal/aria/delegate.js */ "./node_modules/@material/web/internal/aria/delegate.js");
-/* harmony import */ var _internal_controller_string_converter_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../internal/controller/string-converter.js */ "./node_modules/@material/web/internal/controller/string-converter.js");
-/* harmony import */ var _internal_events_redispatch_event_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../internal/events/redispatch-event.js */ "./node_modules/@material/web/internal/events/redispatch-event.js");
-/* harmony import */ var _labs_behaviors_constraint_validation_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../labs/behaviors/constraint-validation.js */ "./node_modules/@material/web/labs/behaviors/constraint-validation.js");
-/* harmony import */ var _labs_behaviors_element_internals_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../labs/behaviors/element-internals.js */ "./node_modules/@material/web/labs/behaviors/element-internals.js");
-/* harmony import */ var _labs_behaviors_form_associated_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../labs/behaviors/form-associated.js */ "./node_modules/@material/web/labs/behaviors/form-associated.js");
-/* harmony import */ var _labs_behaviors_on_report_validity_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../labs/behaviors/on-report-validity.js */ "./node_modules/@material/web/labs/behaviors/on-report-validity.js");
-/* harmony import */ var _labs_behaviors_validators_text_field_validator_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../labs/behaviors/validators/text-field-validator.js */ "./node_modules/@material/web/labs/behaviors/validators/text-field-validator.js");
-/**
- * @license
- * Copyright 2021 Google LLC
- * SPDX-License-Identifier: Apache-2.0
- */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// Separate variable needed for closure.
-const textFieldBaseClass = (0,_internal_aria_delegate_js__WEBPACK_IMPORTED_MODULE_6__.mixinDelegatesAria)((0,_labs_behaviors_on_report_validity_js__WEBPACK_IMPORTED_MODULE_12__.mixinOnReportValidity)((0,_labs_behaviors_constraint_validation_js__WEBPACK_IMPORTED_MODULE_9__.mixinConstraintValidation)((0,_labs_behaviors_form_associated_js__WEBPACK_IMPORTED_MODULE_11__.mixinFormAssociated)((0,_labs_behaviors_element_internals_js__WEBPACK_IMPORTED_MODULE_10__.mixinElementInternals)(lit__WEBPACK_IMPORTED_MODULE_0__.LitElement)))));
-/**
- * A text field component.
- *
- * @fires select {Event} The native `select` event on
- * [` `](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/select_event)
- * --bubbles
- * @fires change {Event} The native `change` event on
- * [` `](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event)
- * --bubbles
- * @fires input {InputEvent} The native `input` event on
- * [` `](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event)
- * --bubbles --composed
- */
-class TextField extends textFieldBaseClass {
- constructor() {
- super(...arguments);
- /**
- * Gets or sets whether or not the text field is in a visually invalid state.
- *
- * This error state overrides the error state controlled by
- * `reportValidity()`.
- */
- this.error = false;
- /**
- * The error message that replaces supporting text when `error` is true. If
- * `errorText` is an empty string, then the supporting text will continue to
- * show.
- *
- * This error message overrides the error message displayed by
- * `reportValidity()`.
- */
- this.errorText = '';
- /**
- * The floating Material label of the textfield component. It informs the user
- * about what information is requested for a text field. It is aligned with
- * the input text, is always visible, and it floats when focused or when text
- * is entered into the textfield. This label also sets accessibilty labels,
- * but the accessible label is overriden by `aria-label`.
- *
- * Learn more about floating labels from the Material Design guidelines:
- * https://m3.material.io/components/text-fields/guidelines
- */
- this.label = '';
- /**
- * Disables the asterisk on the floating label, when the text field is
- * required.
- */
- this.noAsterisk = false;
- /**
- * Indicates that the user must specify a value for the input before the
- * owning form can be submitted and will render an error state when
- * `reportValidity()` is invoked when value is empty. Additionally the
- * floating label will render an asterisk `"*"` when true.
- *
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required
- */
- this.required = false;
- /**
- * The current value of the text field. It is always a string.
- */
- this.value = '';
- /**
- * An optional prefix to display before the input value.
- */
- this.prefixText = '';
- /**
- * An optional suffix to display after the input value.
- */
- this.suffixText = '';
- /**
- * Whether or not the text field has a leading icon. Used for SSR.
- */
- this.hasLeadingIcon = false;
- /**
- * Whether or not the text field has a trailing icon. Used for SSR.
- */
- this.hasTrailingIcon = false;
- /**
- * Conveys additional information below the text field, such as how it should
- * be used.
- */
- this.supportingText = '';
- /**
- * Override the input text CSS `direction`. Useful for RTL languages that use
- * LTR notation for fractions.
- */
- this.textDirection = '';
- /**
- * The number of rows to display for a `type="textarea"` text field.
- * Defaults to 2.
- */
- this.rows = 2;
- /**
- * The number of cols to display for a `type="textarea"` text field.
- * Defaults to 20.
- */
- this.cols = 20;
- // properties
- this.inputMode = '';
- /**
- * Defines the greatest value in the range of permitted values.
- *
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#max
- */
- this.max = '';
- /**
- * The maximum number of characters a user can enter into the text field. Set
- * to -1 for none.
- *
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#maxlength
- */
- this.maxLength = -1;
- /**
- * Defines the most negative value in the range of permitted values.
- *
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#min
- */
- this.min = '';
- /**
- * The minimum number of characters a user can enter into the text field. Set
- * to -1 for none.
- *
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#minlength
- */
- this.minLength = -1;
- /**
- * When true, hide the spinner for `type="number"` text fields.
- */
- this.noSpinner = false;
- /**
- * A regular expression that the text field's value must match to pass
- * constraint validation.
- *
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#pattern
- */
- this.pattern = '';
- /**
- * Defines the text displayed in the textfield when it has no value. Provides
- * a brief hint to the user as to the expected type of data that should be
- * entered into the control. Unlike `label`, the placeholder is not visible
- * and does not float when the textfield has a value.
- *
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/placeholder
- */
- this.placeholder = '';
- /**
- * Indicates whether or not a user should be able to edit the text field's
- * value.
- *
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#readonly
- */
- this.readOnly = false;
- /**
- * Indicates that input accepts multiple email addresses.
- *
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#multiple
- */
- this.multiple = false;
- /**
- * Returns or sets the element's step attribute, which works with min and max
- * to limit the increments at which a numeric or date-time value can be set.
- *
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#step
- */
- this.step = '';
- /**
- * The ` ` type to use, defaults to "text". The type greatly changes how
- * the text field behaves.
- *
- * Text fields support a limited number of ` ` types:
- *
- * - text
- * - textarea
- * - email
- * - number
- * - password
- * - search
- * - tel
- * - url
- *
- * See
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types
- * for more details on each input type.
- */
- this.type = 'text';
- /**
- * Describes what, if any, type of autocomplete functionality the input
- * should provide.
- *
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete
- */
- this.autocomplete = '';
- /**
- * Returns true when the text field has been interacted with. Native
- * validation errors only display in response to user interactions.
- */
- this.dirty = false;
- this.focused = false;
- /**
- * Whether or not a native error has been reported via `reportValidity()`.
- */
- this.nativeError = false;
- /**
- * The validation message displayed from a native error via
- * `reportValidity()`.
- */
- this.nativeErrorText = '';
- }
- /**
- * Gets or sets the direction in which selection occurred.
- */
- get selectionDirection() {
- return this.getInputOrTextarea().selectionDirection;
- }
- set selectionDirection(value) {
- this.getInputOrTextarea().selectionDirection = value;
- }
- /**
- * Gets or sets the end position or offset of a text selection.
- */
- get selectionEnd() {
- return this.getInputOrTextarea().selectionEnd;
- }
- set selectionEnd(value) {
- this.getInputOrTextarea().selectionEnd = value;
- }
- /**
- * Gets or sets the starting position or offset of a text selection.
- */
- get selectionStart() {
- return this.getInputOrTextarea().selectionStart;
- }
- set selectionStart(value) {
- this.getInputOrTextarea().selectionStart = value;
- }
- /**
- * The text field's value as a number.
- */
- get valueAsNumber() {
- const input = this.getInput();
- if (!input) {
- return NaN;
- }
- return input.valueAsNumber;
- }
- set valueAsNumber(value) {
- const input = this.getInput();
- if (!input) {
- return;
- }
- input.valueAsNumber = value;
- this.value = input.value;
- }
- /**
- * The text field's value as a Date.
- */
- get valueAsDate() {
- const input = this.getInput();
- if (!input) {
- return null;
- }
- return input.valueAsDate;
- }
- set valueAsDate(value) {
- const input = this.getInput();
- if (!input) {
- return;
- }
- input.valueAsDate = value;
- this.value = input.value;
- }
- get hasError() {
- return this.error || this.nativeError;
- }
- /**
- * Selects all the text in the text field.
- *
- * https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/select
- */
- select() {
- this.getInputOrTextarea().select();
- }
- setRangeText(...args) {
- // Calling setRangeText with 1 vs 3-4 arguments has different behavior.
- // Use spread syntax and type casting to ensure correct usage.
- this.getInputOrTextarea().setRangeText(...args);
- this.value = this.getInputOrTextarea().value;
- }
- /**
- * Sets the start and end positions of a selection in the text field.
- *
- * https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange
- *
- * @param start The offset into the text field for the start of the selection.
- * @param end The offset into the text field for the end of the selection.
- * @param direction The direction in which the selection is performed.
- */
- setSelectionRange(start, end, direction) {
- this.getInputOrTextarea().setSelectionRange(start, end, direction);
- }
- /**
- * Shows the browser picker for an input element of type "date", "time", etc.
- *
- * For a full list of supported types, see:
- * https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/showPicker#browser_compatibility
- *
- * https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/showPicker
- */
- showPicker() {
- const input = this.getInput();
- if (!input) {
- return;
- }
- input.showPicker();
- }
- /**
- * Decrements the value of a numeric type text field by `step` or `n` `step`
- * number of times.
- *
- * https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/stepDown
- *
- * @param stepDecrement The number of steps to decrement, defaults to 1.
- */
- stepDown(stepDecrement) {
- const input = this.getInput();
- if (!input) {
- return;
- }
- input.stepDown(stepDecrement);
- this.value = input.value;
- }
- /**
- * Increments the value of a numeric type text field by `step` or `n` `step`
- * number of times.
- *
- * https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/stepUp
- *
- * @param stepIncrement The number of steps to increment, defaults to 1.
- */
- stepUp(stepIncrement) {
- const input = this.getInput();
- if (!input) {
- return;
- }
- input.stepUp(stepIncrement);
- this.value = input.value;
- }
- /**
- * Reset the text field to its default value.
- */
- reset() {
- this.dirty = false;
- this.value = this.getAttribute('value') ?? '';
- this.nativeError = false;
- this.nativeErrorText = '';
- }
- attributeChangedCallback(attribute, newValue, oldValue) {
- if (attribute === 'value' && this.dirty) {
- // After user input, changing the value attribute no longer updates the
- // text field's value (until reset). This matches native behavior.
- return;
- }
- super.attributeChangedCallback(attribute, newValue, oldValue);
- }
- render() {
- const classes = {
- 'disabled': this.disabled,
- 'error': !this.disabled && this.hasError,
- 'textarea': this.type === 'textarea',
- 'no-spinner': this.noSpinner,
- };
- return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- ${this.renderField()}
-
- `;
- }
- updated(changedProperties) {
- // Keep changedProperties arg so that subclasses may call it
- // If a property such as `type` changes and causes the internal
- // value to change without dispatching an event, re-sync it.
- const value = this.getInputOrTextarea().value;
- if (this.value !== value) {
- // Note this is typically inefficient in updated() since it schedules
- // another update. However, it is needed for the to fully render
- // before checking its value.
- this.value = value;
- }
- }
- renderField() {
- return (0,lit_static_html_js__WEBPACK_IMPORTED_MODULE_5__.html) `<${this.fieldTag}
- class="field"
- count=${this.value.length}
- ?disabled=${this.disabled}
- ?error=${this.hasError}
- error-text=${this.getErrorText()}
- ?focused=${this.focused}
- ?has-end=${this.hasTrailingIcon}
- ?has-start=${this.hasLeadingIcon}
- label=${this.label}
- ?no-asterisk=${this.noAsterisk}
- max=${this.maxLength}
- ?populated=${!!this.value}
- ?required=${this.required}
- ?resizable=${this.type === 'textarea'}
- supporting-text=${this.supportingText}
- >
- ${this.renderLeadingIcon()}
- ${this.renderInputOrTextarea()}
- ${this.renderTrailingIcon()}
-
-
- ${this.fieldTag}>`;
- }
- renderLeadingIcon() {
- return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
-
-
- `;
- }
- renderTrailingIcon() {
- return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
-
-
- `;
- }
- renderInputOrTextarea() {
- const style = { 'direction': this.textDirection };
- const ariaLabel = this.ariaLabel || this.label || lit__WEBPACK_IMPORTED_MODULE_0__.nothing;
- // lit-anaylzer `autocomplete` types are too strict
- // tslint:disable-next-line:no-any
- const autocomplete = this.autocomplete;
- // These properties may be set to null if the attribute is removed, and
- // `null > -1` is incorrectly `true`.
- const hasMaxLength = (this.maxLength ?? -1) > -1;
- const hasMinLength = (this.minLength ?? -1) > -1;
- if (this.type === 'textarea') {
- return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- `;
- }
- const prefix = this.renderPrefix();
- const suffix = this.renderSuffix();
- // TODO(b/243805848): remove `as unknown as number` and `as any` once lit
- // analyzer is fixed
- // tslint:disable-next-line:no-any
- const inputMode = this.inputMode;
- return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- ${prefix}
-
- ${suffix}
-
- `;
- }
- renderPrefix() {
- return this.renderAffix(this.prefixText, /* isSuffix */ false);
- }
- renderSuffix() {
- return this.renderAffix(this.suffixText, /* isSuffix */ true);
- }
- renderAffix(text, isSuffix) {
- if (!text) {
- return lit__WEBPACK_IMPORTED_MODULE_0__.nothing;
- }
- const classes = {
- 'suffix': isSuffix,
- 'prefix': !isSuffix,
- };
- return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `${text} `;
- }
- getErrorText() {
- return this.error ? this.errorText : this.nativeErrorText;
- }
- handleFocusChange() {
- // When calling focus() or reportValidity() during change, it's possible
- // for blur to be called after the new focus event. Rather than set
- // `this.focused` to true/false on focus/blur, we always set it to whether
- // or not the input itself is focused.
- this.focused = this.inputOrTextarea?.matches(':focus') ?? false;
- }
- handleInput(event) {
- this.dirty = true;
- this.value = event.target.value;
- }
- redispatchEvent(event) {
- (0,_internal_events_redispatch_event_js__WEBPACK_IMPORTED_MODULE_8__.redispatchEvent)(this, event);
- }
- getInputOrTextarea() {
- if (!this.inputOrTextarea) {
- // If the input is not yet defined, synchronously render.
- // e.g.
- // const textField = document.createElement('md-outlined-text-field');
- // document.body.appendChild(textField);
- // textField.focus(); // synchronously render
- this.connectedCallback();
- this.scheduleUpdate();
- }
- if (this.isUpdatePending) {
- // If there are pending updates, synchronously perform them. This ensures
- // that constraint validation properties (like `required`) are synced
- // before interacting with input APIs that depend on them.
- this.scheduleUpdate();
- }
- return this.inputOrTextarea;
- }
- getInput() {
- if (this.type === 'textarea') {
- return null;
- }
- return this.getInputOrTextarea();
- }
- handleIconChange() {
- this.hasLeadingIcon = this.leadingIcons.length > 0;
- this.hasTrailingIcon = this.trailingIcons.length > 0;
- }
- [_labs_behaviors_form_associated_js__WEBPACK_IMPORTED_MODULE_11__.getFormValue]() {
- return this.value;
- }
- formResetCallback() {
- this.reset();
- }
- formStateRestoreCallback(state) {
- this.value = state;
- }
- focus() {
- // Required for the case that the user slots a focusable element into the
- // leading icon slot such as an iconbutton due to how delegatesFocus works.
- this.getInputOrTextarea().focus();
- }
- [_labs_behaviors_constraint_validation_js__WEBPACK_IMPORTED_MODULE_9__.createValidator]() {
- return new _labs_behaviors_validators_text_field_validator_js__WEBPACK_IMPORTED_MODULE_13__.TextFieldValidator(() => ({
- state: this,
- renderedControl: this.inputOrTextarea,
- }));
- }
- [_labs_behaviors_constraint_validation_js__WEBPACK_IMPORTED_MODULE_9__.getValidityAnchor]() {
- return this.inputOrTextarea;
- }
- [_labs_behaviors_on_report_validity_js__WEBPACK_IMPORTED_MODULE_12__.onReportValidity](invalidEvent) {
- // Prevent default pop-up behavior.
- invalidEvent?.preventDefault();
- const prevMessage = this.getErrorText();
- this.nativeError = !!invalidEvent;
- this.nativeErrorText = this.validationMessage;
- if (prevMessage === this.getErrorText()) {
- this.field?.reannounceError();
- }
- }
-}
-/** @nocollapse */
-TextField.shadowRootOptions = {
- ...lit__WEBPACK_IMPORTED_MODULE_0__.LitElement.shadowRootOptions,
- delegatesFocus: true,
-};
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ type: Boolean, reflect: true })
-], TextField.prototype, "error", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ attribute: 'error-text' })
-], TextField.prototype, "errorText", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)()
-], TextField.prototype, "label", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ type: Boolean, attribute: 'no-asterisk' })
-], TextField.prototype, "noAsterisk", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ type: Boolean, reflect: true })
-], TextField.prototype, "required", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)()
-], TextField.prototype, "value", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ attribute: 'prefix-text' })
-], TextField.prototype, "prefixText", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ attribute: 'suffix-text' })
-], TextField.prototype, "suffixText", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ type: Boolean, attribute: 'has-leading-icon' })
-], TextField.prototype, "hasLeadingIcon", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ type: Boolean, attribute: 'has-trailing-icon' })
-], TextField.prototype, "hasTrailingIcon", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ attribute: 'supporting-text' })
-], TextField.prototype, "supportingText", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ attribute: 'text-direction' })
-], TextField.prototype, "textDirection", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ type: Number })
-], TextField.prototype, "rows", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ type: Number })
-], TextField.prototype, "cols", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ reflect: true })
-], TextField.prototype, "inputMode", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)()
-], TextField.prototype, "max", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ type: Number })
-], TextField.prototype, "maxLength", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)()
-], TextField.prototype, "min", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ type: Number })
-], TextField.prototype, "minLength", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ type: Boolean, attribute: 'no-spinner' })
-], TextField.prototype, "noSpinner", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)()
-], TextField.prototype, "pattern", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ reflect: true, converter: _internal_controller_string_converter_js__WEBPACK_IMPORTED_MODULE_7__.stringConverter })
-], TextField.prototype, "placeholder", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ type: Boolean, reflect: true })
-], TextField.prototype, "readOnly", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ type: Boolean, reflect: true })
-], TextField.prototype, "multiple", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)()
-], TextField.prototype, "step", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ reflect: true })
-], TextField.prototype, "type", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)({ reflect: true })
-], TextField.prototype, "autocomplete", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], TextField.prototype, "dirty", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], TextField.prototype, "focused", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], TextField.prototype, "nativeError", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], TextField.prototype, "nativeErrorText", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.query)('.input')
-], TextField.prototype, "inputOrTextarea", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.query)('.field')
-], TextField.prototype, "field", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.queryAssignedElements)({ slot: 'leading-icon' })
-], TextField.prototype, "leadingIcons", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_14__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.queryAssignedElements)({ slot: 'trailing-icon' })
-], TextField.prototype, "trailingIcons", void 0);
-//# sourceMappingURL=text-field.js.map
-
-/***/ }),
-
-/***/ "./node_modules/atob-lite/atob-browser.js":
-/*!************************************************!*\
- !*** ./node_modules/atob-lite/atob-browser.js ***!
- \************************************************/
-/***/ ((module) => {
-
-module.exports = function _atob(str) {
- return atob(str)
-}
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/components/ew-checkbox.js":
-/*!*******************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/components/ew-checkbox.js ***!
- \*******************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ EwCheckbox: () => (/* binding */ EwCheckbox)
-/* harmony export */ });
-/* harmony import */ var _material_web_checkbox_internal_checkbox_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @material/web/checkbox/internal/checkbox.js */ "./node_modules/@material/web/checkbox/internal/checkbox.js");
-/* harmony import */ var _material_web_checkbox_internal_checkbox_styles_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @material/web/checkbox/internal/checkbox-styles.js */ "./node_modules/@material/web/checkbox/internal/checkbox-styles.js");
-
-
-class EwCheckbox extends _material_web_checkbox_internal_checkbox_js__WEBPACK_IMPORTED_MODULE_0__.Checkbox {
-}
-EwCheckbox.styles = [_material_web_checkbox_internal_checkbox_styles_js__WEBPACK_IMPORTED_MODULE_1__.styles];
-customElements.define("ew-checkbox", EwCheckbox);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/components/ew-circular-progress.js":
-/*!****************************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/components/ew-circular-progress.js ***!
- \****************************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ EwCircularProgress: () => (/* binding */ EwCircularProgress)
-/* harmony export */ });
-/* harmony import */ var _material_web_progress_internal_circular_progress_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @material/web/progress/internal/circular-progress.js */ "./node_modules/@material/web/progress/internal/circular-progress.js");
-/* harmony import */ var _material_web_progress_internal_circular_progress_styles_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @material/web/progress/internal/circular-progress-styles.js */ "./node_modules/@material/web/progress/internal/circular-progress-styles.js");
-
-
-class EwCircularProgress extends _material_web_progress_internal_circular_progress_js__WEBPACK_IMPORTED_MODULE_0__.CircularProgress {
-}
-EwCircularProgress.styles = [_material_web_progress_internal_circular_progress_styles_js__WEBPACK_IMPORTED_MODULE_1__.styles];
-customElements.define("ew-circular-progress", EwCircularProgress);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/components/ew-divider.js":
-/*!******************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/components/ew-divider.js ***!
- \******************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ EwDivider: () => (/* binding */ EwDivider)
-/* harmony export */ });
-/* harmony import */ var _material_web_divider_internal_divider_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @material/web/divider/internal/divider.js */ "./node_modules/@material/web/divider/internal/divider.js");
-/* harmony import */ var _material_web_divider_internal_divider_styles_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @material/web/divider/internal/divider-styles.js */ "./node_modules/@material/web/divider/internal/divider-styles.js");
-
-
-class EwDivider extends _material_web_divider_internal_divider_js__WEBPACK_IMPORTED_MODULE_0__.Divider {
-}
-EwDivider.styles = [_material_web_divider_internal_divider_styles_js__WEBPACK_IMPORTED_MODULE_1__.styles];
-customElements.define("ew-divider", EwDivider);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/components/ew-filled-select.js":
-/*!************************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/components/ew-filled-select.js ***!
- \************************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ EwFilledSelect: () => (/* binding */ EwFilledSelect)
-/* harmony export */ });
-/* harmony import */ var _material_web_select_internal_filled_select_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @material/web/select/internal/filled-select.js */ "./node_modules/@material/web/select/internal/filled-select.js");
-/* harmony import */ var _material_web_select_internal_filled_select_styles_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @material/web/select/internal/filled-select-styles.js */ "./node_modules/@material/web/select/internal/filled-select-styles.js");
-/* harmony import */ var _material_web_select_internal_shared_styles_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @material/web/select/internal/shared-styles.js */ "./node_modules/@material/web/select/internal/shared-styles.js");
-
-
-
-class EwFilledSelect extends _material_web_select_internal_filled_select_js__WEBPACK_IMPORTED_MODULE_0__.FilledSelect {
-}
-EwFilledSelect.styles = [_material_web_select_internal_shared_styles_js__WEBPACK_IMPORTED_MODULE_2__.styles, _material_web_select_internal_filled_select_styles_js__WEBPACK_IMPORTED_MODULE_1__.styles];
-customElements.define("ew-filled-select", EwFilledSelect);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/components/ew-filled-text-field.js":
-/*!****************************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/components/ew-filled-text-field.js ***!
- \****************************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ EwFilledTextField: () => (/* binding */ EwFilledTextField)
-/* harmony export */ });
-/* harmony import */ var _material_web_textfield_internal_filled_styles_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @material/web/textfield/internal/filled-styles.js */ "./node_modules/@material/web/textfield/internal/filled-styles.js");
-/* harmony import */ var _material_web_textfield_internal_filled_text_field_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @material/web/textfield/internal/filled-text-field.js */ "./node_modules/@material/web/textfield/internal/filled-text-field.js");
-/* harmony import */ var _material_web_textfield_internal_shared_styles_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @material/web/textfield/internal/shared-styles.js */ "./node_modules/@material/web/textfield/internal/shared-styles.js");
-/* harmony import */ var lit_static_html_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! lit/static-html.js */ "./node_modules/lit/static-html.js");
-
-
-
-
-class EwFilledTextField extends _material_web_textfield_internal_filled_text_field_js__WEBPACK_IMPORTED_MODULE_1__.FilledTextField {
- constructor() {
- super(...arguments);
- this.fieldTag = (0,lit_static_html_js__WEBPACK_IMPORTED_MODULE_3__.literal) `md-filled-field`;
- }
-}
-EwFilledTextField.styles = [_material_web_textfield_internal_shared_styles_js__WEBPACK_IMPORTED_MODULE_2__.styles, _material_web_textfield_internal_filled_styles_js__WEBPACK_IMPORTED_MODULE_0__.styles];
-customElements.define("ew-filled-text-field", EwFilledTextField);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/components/ew-icon-button.js":
-/*!**********************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/components/ew-icon-button.js ***!
- \**********************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ EwIconButton: () => (/* binding */ EwIconButton)
-/* harmony export */ });
-/* harmony import */ var _material_web_iconbutton_internal_icon_button_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @material/web/iconbutton/internal/icon-button.js */ "./node_modules/@material/web/iconbutton/internal/icon-button.js");
-/* harmony import */ var _material_web_iconbutton_internal_shared_styles_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @material/web/iconbutton/internal/shared-styles.js */ "./node_modules/@material/web/iconbutton/internal/shared-styles.js");
-/* harmony import */ var _material_web_iconbutton_internal_standard_styles_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @material/web/iconbutton/internal/standard-styles.js */ "./node_modules/@material/web/iconbutton/internal/standard-styles.js");
-
-
-
-class EwIconButton extends _material_web_iconbutton_internal_icon_button_js__WEBPACK_IMPORTED_MODULE_0__.IconButton {
-}
-EwIconButton.styles = [_material_web_iconbutton_internal_shared_styles_js__WEBPACK_IMPORTED_MODULE_1__.styles, _material_web_iconbutton_internal_standard_styles_js__WEBPACK_IMPORTED_MODULE_2__.styles];
-customElements.define("ew-icon-button", EwIconButton);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/components/ew-list-item.js":
-/*!********************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/components/ew-list-item.js ***!
- \********************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ EwListItem: () => (/* binding */ EwListItem)
-/* harmony export */ });
-/* harmony import */ var _material_web_list_internal_listitem_list_item_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @material/web/list/internal/listitem/list-item.js */ "./node_modules/@material/web/list/internal/listitem/list-item.js");
-/* harmony import */ var _material_web_list_internal_listitem_list_item_styles_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @material/web/list/internal/listitem/list-item-styles.js */ "./node_modules/@material/web/list/internal/listitem/list-item-styles.js");
-
-
-class EwListItem extends _material_web_list_internal_listitem_list_item_js__WEBPACK_IMPORTED_MODULE_0__.ListItemEl {
-}
-EwListItem.styles = [_material_web_list_internal_listitem_list_item_styles_js__WEBPACK_IMPORTED_MODULE_1__.styles];
-customElements.define("ew-list-item", EwListItem);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/components/ew-list.js":
-/*!***************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/components/ew-list.js ***!
- \***************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ EwList: () => (/* binding */ EwList)
-/* harmony export */ });
-/* harmony import */ var _material_web_list_internal_list_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @material/web/list/internal/list.js */ "./node_modules/@material/web/list/internal/list.js");
-/* harmony import */ var _material_web_list_internal_list_styles_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @material/web/list/internal/list-styles.js */ "./node_modules/@material/web/list/internal/list-styles.js");
-
-
-class EwList extends _material_web_list_internal_list_js__WEBPACK_IMPORTED_MODULE_0__.List {
-}
-EwList.styles = [_material_web_list_internal_list_styles_js__WEBPACK_IMPORTED_MODULE_1__.styles];
-customElements.define("ew-list", EwList);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/components/ew-select-option.js":
-/*!************************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/components/ew-select-option.js ***!
- \************************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ EwSelectOption: () => (/* binding */ EwSelectOption)
-/* harmony export */ });
-/* harmony import */ var _material_web_menu_internal_menuitem_menu_item_styles_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @material/web/menu/internal/menuitem/menu-item-styles.js */ "./node_modules/@material/web/menu/internal/menuitem/menu-item-styles.js");
-/* harmony import */ var _material_web_select_internal_selectoption_select_option_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @material/web/select/internal/selectoption/select-option.js */ "./node_modules/@material/web/select/internal/selectoption/select-option.js");
-
-
-class EwSelectOption extends _material_web_select_internal_selectoption_select_option_js__WEBPACK_IMPORTED_MODULE_1__.SelectOptionEl {
-}
-EwSelectOption.styles = [_material_web_menu_internal_menuitem_menu_item_styles_js__WEBPACK_IMPORTED_MODULE_0__.styles];
-customElements.define("ew-select-option", EwSelectOption);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/components/ewt-console.js":
-/*!*******************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/components/ewt-console.js ***!
- \*******************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ EwtConsole: () => (/* binding */ EwtConsole)
-/* harmony export */ });
-/* harmony import */ var _util_console_color__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../util/console-color */ "./node_modules/esp-web-tools/dist/util/console-color.js");
-/* harmony import */ var _util_sleep__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util/sleep */ "./node_modules/esp-web-tools/dist/util/sleep.js");
-/* harmony import */ var _util_line_break_transformer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../util/line-break-transformer */ "./node_modules/esp-web-tools/dist/util/line-break-transformer.js");
-/* harmony import */ var _util_timestamp_transformer__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../util/timestamp-transformer */ "./node_modules/esp-web-tools/dist/util/timestamp-transformer.js");
-
-
-
-
-class EwtConsole extends HTMLElement {
- constructor() {
- super(...arguments);
- this.allowInput = true;
- }
- logs() {
- var _a;
- return ((_a = this._console) === null || _a === void 0 ? void 0 : _a.logs()) || "";
- }
- connectedCallback() {
- if (this._console) {
- return;
- }
- const shadowRoot = this.attachShadow({ mode: "open" });
- shadowRoot.innerHTML = `
-
-
- ${this.allowInput
- ? `
- `
- : ""}
- `;
- this._console = new _util_console_color__WEBPACK_IMPORTED_MODULE_0__.ColoredConsole(this.shadowRoot.querySelector("div"));
- if (this.allowInput) {
- const input = this.shadowRoot.querySelector("input");
- this.addEventListener("click", () => {
- var _a;
- // Only focus input if user didn't select some text
- if (((_a = getSelection()) === null || _a === void 0 ? void 0 : _a.toString()) === "") {
- input.focus();
- }
- });
- input.addEventListener("keydown", (ev) => {
- if (ev.key === "Enter") {
- ev.preventDefault();
- ev.stopPropagation();
- this._sendCommand();
- }
- });
- }
- const abortController = new AbortController();
- const connection = this._connect(abortController.signal);
- this._cancelConnection = () => {
- abortController.abort();
- return connection;
- };
- }
- async _connect(abortSignal) {
- this.logger.debug("Starting console read loop");
- try {
- await this.port
- .readable.pipeThrough(new TextDecoderStream(), {
- signal: abortSignal,
- })
- .pipeThrough(new TransformStream(new _util_line_break_transformer__WEBPACK_IMPORTED_MODULE_2__.LineBreakTransformer()))
- .pipeThrough(new TransformStream(new _util_timestamp_transformer__WEBPACK_IMPORTED_MODULE_3__.TimestampTransformer()))
- .pipeTo(new WritableStream({
- write: (chunk) => {
- this._console.addLine(chunk.replace("\r", ""));
- },
- }));
- if (!abortSignal.aborted) {
- this._console.addLine("");
- this._console.addLine("");
- this._console.addLine("Terminal disconnected");
- }
- }
- catch (e) {
- this._console.addLine("");
- this._console.addLine("");
- this._console.addLine(`Terminal disconnected: ${e}`);
- }
- finally {
- await (0,_util_sleep__WEBPACK_IMPORTED_MODULE_1__.sleep)(100);
- this.logger.debug("Finished console read loop");
- }
- }
- async _sendCommand() {
- const input = this.shadowRoot.querySelector("input");
- const command = input.value;
- const encoder = new TextEncoder();
- const writer = this.port.writable.getWriter();
- await writer.write(encoder.encode(command + "\r\n"));
- this._console.addLine(`> ${command}\r\n`);
- input.value = "";
- input.focus();
- try {
- writer.releaseLock();
- }
- catch (err) {
- console.error("Ignoring release lock error", err);
- }
- }
- async disconnect() {
- if (this._cancelConnection) {
- await this._cancelConnection();
- this._cancelConnection = undefined;
- }
- }
- async reset() {
- this.logger.debug("Triggering reset");
- await this.port.setSignals({
- dataTerminalReady: false,
- requestToSend: true,
- });
- await (0,_util_sleep__WEBPACK_IMPORTED_MODULE_1__.sleep)(250);
- await this.port.setSignals({
- dataTerminalReady: false,
- requestToSend: false,
- });
- await (0,_util_sleep__WEBPACK_IMPORTED_MODULE_1__.sleep)(250);
- await new Promise((resolve) => setTimeout(resolve, 1000));
- }
-}
-customElements.define("ewt-console", EwtConsole);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/components/svg.js":
-/*!***********************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/components/svg.js ***!
- \***********************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ closeIcon: () => (/* binding */ closeIcon),
-/* harmony export */ listItemConsole: () => (/* binding */ listItemConsole),
-/* harmony export */ listItemEraseUserData: () => (/* binding */ listItemEraseUserData),
-/* harmony export */ listItemFundDevelopment: () => (/* binding */ listItemFundDevelopment),
-/* harmony export */ listItemHomeAssistant: () => (/* binding */ listItemHomeAssistant),
-/* harmony export */ listItemInstallIcon: () => (/* binding */ listItemInstallIcon),
-/* harmony export */ listItemVisitDevice: () => (/* binding */ listItemVisitDevice),
-/* harmony export */ listItemWifi: () => (/* binding */ listItemWifi),
-/* harmony export */ refreshIcon: () => (/* binding */ refreshIcon)
-/* harmony export */ });
-/* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lit */ "./node_modules/lit/index.js");
-
-const closeIcon = (0,lit__WEBPACK_IMPORTED_MODULE_0__.svg) `
-
-
-
-`;
-const refreshIcon = (0,lit__WEBPACK_IMPORTED_MODULE_0__.svg) `
-
-
-
-`;
-const listItemInstallIcon = (0,lit__WEBPACK_IMPORTED_MODULE_0__.svg) `
-
-
-
-`;
-const listItemWifi = (0,lit__WEBPACK_IMPORTED_MODULE_0__.svg) `
-
-
-
-`;
-const listItemConsole = (0,lit__WEBPACK_IMPORTED_MODULE_0__.svg) `
-
-
-
-`;
-const listItemVisitDevice = (0,lit__WEBPACK_IMPORTED_MODULE_0__.svg) `
-
-
-
-`;
-const listItemHomeAssistant = (0,lit__WEBPACK_IMPORTED_MODULE_0__.svg) `
-
-
-
-`;
-const listItemEraseUserData = (0,lit__WEBPACK_IMPORTED_MODULE_0__.svg) `
-
-
-
-`;
-const listItemFundDevelopment = (0,lit__WEBPACK_IMPORTED_MODULE_0__.svg) `
-
-
-
-`;
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/flash.js":
-/*!**************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/flash.js ***!
- \**************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ flash: () => (/* binding */ flash)
-/* harmony export */ });
-/* harmony import */ var esptool_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! esptool-js */ "./node_modules/esptool-js/lib/index.js");
-/* harmony import */ var _util_reset__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util/reset */ "./node_modules/esp-web-tools/dist/util/reset.js");
-
-
-const flash = async (onEvent, port, manifestPath, manifest, eraseFirst) => {
- let build;
- let chipFamily;
- const fireStateEvent = (stateUpdate) => onEvent({
- ...stateUpdate,
- manifest,
- build,
- chipFamily,
- });
- const transport = new esptool_js__WEBPACK_IMPORTED_MODULE_0__.Transport(port);
- const esploader = new esptool_js__WEBPACK_IMPORTED_MODULE_0__.ESPLoader({
- transport,
- baudrate: 115200,
- romBaudrate: 115200,
- enableTracing: false,
- });
- // For debugging
- window.esploader = esploader;
- fireStateEvent({
- state: "initializing" /* FlashStateType.INITIALIZING */,
- message: "Initializing...",
- details: { done: false },
- });
- try {
- await esploader.main();
- await esploader.flashId();
- }
- catch (err) {
- console.error(err);
- fireStateEvent({
- state: "error" /* FlashStateType.ERROR */,
- message: "Failed to initialize. Try resetting your device or holding the BOOT button while clicking INSTALL.",
- details: { error: "failed_initialize" /* FlashError.FAILED_INITIALIZING */, details: err },
- });
- await (0,_util_reset__WEBPACK_IMPORTED_MODULE_1__.hardReset)(transport);
- await transport.disconnect();
- return;
- }
- chipFamily = esploader.chip.CHIP_NAME;
- fireStateEvent({
- state: "initializing" /* FlashStateType.INITIALIZING */,
- message: `Initialized. Found ${chipFamily}`,
- details: { done: true },
- });
- build = manifest.builds.find((b) => b.chipFamily === chipFamily);
- if (!build) {
- fireStateEvent({
- state: "error" /* FlashStateType.ERROR */,
- message: `Your ${chipFamily} board is not supported.`,
- details: { error: "not_supported" /* FlashError.NOT_SUPPORTED */, details: chipFamily },
- });
- await (0,_util_reset__WEBPACK_IMPORTED_MODULE_1__.hardReset)(transport);
- await transport.disconnect();
- return;
- }
- fireStateEvent({
- state: "preparing" /* FlashStateType.PREPARING */,
- message: "Preparing installation...",
- details: { done: false },
- });
- const manifestURL = new URL(manifestPath, location.toString()).toString();
- const filePromises = build.parts.map(async (part) => {
- const url = new URL(part.path, manifestURL).toString();
- const resp = await fetch(url);
- if (!resp.ok) {
- throw new Error(`Downlading firmware ${part.path} failed: ${resp.status}`);
- }
- const reader = new FileReader();
- const blob = await resp.blob();
- return new Promise((resolve) => {
- reader.addEventListener("load", () => resolve(reader.result));
- reader.readAsBinaryString(blob);
- });
- });
- const fileArray = [];
- let totalSize = 0;
- for (let part = 0; part < filePromises.length; part++) {
- try {
- const data = await filePromises[part];
- fileArray.push({ data, address: build.parts[part].offset });
- totalSize += data.length;
- }
- catch (err) {
- fireStateEvent({
- state: "error" /* FlashStateType.ERROR */,
- message: err.message,
- details: {
- error: "failed_firmware_download" /* FlashError.FAILED_FIRMWARE_DOWNLOAD */,
- details: err.message,
- },
- });
- await (0,_util_reset__WEBPACK_IMPORTED_MODULE_1__.hardReset)(transport);
- await transport.disconnect();
- return;
- }
- }
- fireStateEvent({
- state: "preparing" /* FlashStateType.PREPARING */,
- message: "Installation prepared",
- details: { done: true },
- });
- if (eraseFirst) {
- fireStateEvent({
- state: "erasing" /* FlashStateType.ERASING */,
- message: "Erasing device...",
- details: { done: false },
- });
- await esploader.eraseFlash();
- fireStateEvent({
- state: "erasing" /* FlashStateType.ERASING */,
- message: "Device erased",
- details: { done: true },
- });
- }
- fireStateEvent({
- state: "writing" /* FlashStateType.WRITING */,
- message: `Writing progress: 0%`,
- details: {
- bytesTotal: totalSize,
- bytesWritten: 0,
- percentage: 0,
- },
- });
- let totalWritten = 0;
- try {
- await esploader.writeFlash({
- fileArray,
- flashSize: "keep",
- flashMode: "keep",
- flashFreq: "keep",
- eraseAll: false,
- compress: true,
- // report progress
- reportProgress: (fileIndex, written, total) => {
- const uncompressedWritten = (written / total) * fileArray[fileIndex].data.length;
- const newPct = Math.floor(((totalWritten + uncompressedWritten) / totalSize) * 100);
- // we're done with this file
- if (written === total) {
- totalWritten += uncompressedWritten;
- return;
- }
- fireStateEvent({
- state: "writing" /* FlashStateType.WRITING */,
- message: `Writing progress: ${newPct}%`,
- details: {
- bytesTotal: totalSize,
- bytesWritten: totalWritten + written,
- percentage: newPct,
- },
- });
- },
- });
- }
- catch (err) {
- fireStateEvent({
- state: "error" /* FlashStateType.ERROR */,
- message: err.message,
- details: { error: "write_failed" /* FlashError.WRITE_FAILED */, details: err },
- });
- await (0,_util_reset__WEBPACK_IMPORTED_MODULE_1__.hardReset)(transport);
- await transport.disconnect();
- return;
- }
- fireStateEvent({
- state: "writing" /* FlashStateType.WRITING */,
- message: "Writing complete",
- details: {
- bytesTotal: totalSize,
- bytesWritten: totalWritten,
- percentage: 100,
- },
- });
- await (0,_util_reset__WEBPACK_IMPORTED_MODULE_1__.hardReset)(transport);
- console.log("DISCONNECT");
- await transport.disconnect();
- fireStateEvent({
- state: "finished" /* FlashStateType.FINISHED */,
- message: "All done!",
- });
-};
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/install-dialog.js":
-/*!***********************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/install-dialog.js ***!
- \***********************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ EwtInstallDialog: () => (/* binding */ EwtInstallDialog)
-/* harmony export */ });
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
-/* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lit */ "./node_modules/lit/index.js");
-/* harmony import */ var lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! lit/decorators.js */ "./node_modules/lit/decorators.js");
-/* harmony import */ var _components_ew_text_button__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./components/ew-text-button */ "./node_modules/esp-web-tools/dist/components/ew-text-button.js");
-/* harmony import */ var _components_ew_list__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./components/ew-list */ "./node_modules/esp-web-tools/dist/components/ew-list.js");
-/* harmony import */ var _components_ew_list_item__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./components/ew-list-item */ "./node_modules/esp-web-tools/dist/components/ew-list-item.js");
-/* harmony import */ var _components_ew_divider__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./components/ew-divider */ "./node_modules/esp-web-tools/dist/components/ew-divider.js");
-/* harmony import */ var _components_ew_checkbox__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./components/ew-checkbox */ "./node_modules/esp-web-tools/dist/components/ew-checkbox.js");
-/* harmony import */ var _components_ewt_console__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./components/ewt-console */ "./node_modules/esp-web-tools/dist/components/ewt-console.js");
-/* harmony import */ var _components_ew_dialog__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./components/ew-dialog */ "./node_modules/esp-web-tools/dist/components/ew-dialog.js");
-/* harmony import */ var _components_ew_icon_button__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./components/ew-icon-button */ "./node_modules/esp-web-tools/dist/components/ew-icon-button.js");
-/* harmony import */ var _components_ew_filled_text_field__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./components/ew-filled-text-field */ "./node_modules/esp-web-tools/dist/components/ew-filled-text-field.js");
-/* harmony import */ var _components_ew_filled_select__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./components/ew-filled-select */ "./node_modules/esp-web-tools/dist/components/ew-filled-select.js");
-/* harmony import */ var _components_ew_select_option__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./components/ew-select-option */ "./node_modules/esp-web-tools/dist/components/ew-select-option.js");
-/* harmony import */ var _pages_ewt_page_progress__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./pages/ewt-page-progress */ "./node_modules/esp-web-tools/dist/pages/ewt-page-progress.js");
-/* harmony import */ var _pages_ewt_page_message__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./pages/ewt-page-message */ "./node_modules/esp-web-tools/dist/pages/ewt-page-message.js");
-/* harmony import */ var _components_svg__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./components/svg */ "./node_modules/esp-web-tools/dist/components/svg.js");
-/* harmony import */ var improv_wifi_serial_sdk_dist_serial__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! improv-wifi-serial-sdk/dist/serial */ "./node_modules/improv-wifi-serial-sdk/dist/serial.js");
-/* harmony import */ var improv_wifi_serial_sdk_dist_const__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! improv-wifi-serial-sdk/dist/const */ "./node_modules/improv-wifi-serial-sdk/dist/const.js");
-/* harmony import */ var _flash__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./flash */ "./node_modules/esp-web-tools/dist/flash.js");
-/* harmony import */ var _util_file_download__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./util/file-download */ "./node_modules/esp-web-tools/dist/util/file-download.js");
-/* harmony import */ var _util_fire_event__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./util/fire-event */ "./node_modules/esp-web-tools/dist/util/fire-event.js");
-/* harmony import */ var _util_sleep__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./util/sleep */ "./node_modules/esp-web-tools/dist/util/sleep.js");
-/* harmony import */ var _util_manifest__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./util/manifest */ "./node_modules/esp-web-tools/dist/util/manifest.js");
-/* harmony import */ var _styles__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./styles */ "./node_modules/esp-web-tools/dist/styles.js");
-/* harmony import */ var _version__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./version */ "./node_modules/esp-web-tools/dist/version.js");
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-console.log(`ESP Web Tools ${_version__WEBPACK_IMPORTED_MODULE_24__.version} by Open Home Foundation; https://esphome.github.io/esp-web-tools/`);
-const ERROR_ICON = "⚠️";
-const OK_ICON = "🎉";
-class EwtInstallDialog extends lit__WEBPACK_IMPORTED_MODULE_0__.LitElement {
- constructor() {
- super(...arguments);
- this.logger = console;
- this._state = "DASHBOARD";
- this._installErase = false;
- this._installConfirmed = false;
- this._provisionForce = false;
- this._wasProvisioned = false;
- this._busy = false;
- // Name of Ssid. Null = other
- this._selectedSsid = null;
- this._bodyOverflow = null;
- this._handleDisconnect = () => {
- this._state = "ERROR";
- this._error = "Disconnected";
- };
- }
- render() {
- if (!this.port) {
- return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) ``;
- }
- let heading;
- let content;
- let allowClosing = false;
- // During installation phase we temporarily remove the client
- if (this._client === undefined &&
- this._state !== "INSTALL" &&
- this._state !== "LOGS") {
- if (this._error) {
- [heading, content] = this._renderError(this._error);
- }
- else {
- content = this._renderProgress("Connecting");
- }
- }
- else if (this._state === "INSTALL") {
- [heading, content, allowClosing] = this._renderInstall();
- }
- else if (this._state === "ASK_ERASE") {
- [heading, content] = this._renderAskErase();
- }
- else if (this._state === "ERROR") {
- [heading, content] = this._renderError(this._error);
- }
- else if (this._state === "DASHBOARD") {
- [heading, content, allowClosing] = this._client
- ? this._renderDashboard()
- : this._renderDashboardNoImprov();
- }
- else if (this._state === "PROVISION") {
- [heading, content] = this._renderProvision();
- }
- else if (this._state === "LOGS") {
- [heading, content] = this._renderLogs();
- }
- return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- ${heading ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `${heading}
` : ""}
- ${allowClosing
- ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.closeIcon}
-
- `
- : ""}
- ${content}
-
- `;
- }
- _renderProgress(label, progress) {
- return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- `;
- }
- _renderError(label) {
- const heading = "Error";
- const content = (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
-
- Close
-
- `;
- return [heading, content];
- }
- _renderDashboard() {
- const heading = this._manifest.name;
- let content;
- let allowClosing = true;
- content = (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
-
-
- Connected to ${this._info.name}
-
- ${this._info.firmware} ${this._info.version}
- (${this._info.chipFamily})
-
-
- ${!this._isSameVersion
- ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
- {
- if (this._isSameFirmware) {
- this._startInstall(false);
- }
- else if (this._manifest.new_install_prompt_erase) {
- this._state = "ASK_ERASE";
- }
- else {
- this._startInstall(true);
- }
- }}
- >
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.listItemInstallIcon}
-
- ${!this._isSameFirmware
- ? `Install ${this._manifest.name}`
- : `Update ${this._manifest.name}`}
-
-
- `
- : ""}
- ${this._client.nextUrl === undefined
- ? ""
- : (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.listItemVisitDevice}
- Visit Device
-
- `}
- ${!this._manifest.home_assistant_domain ||
- this._client.state !== improv_wifi_serial_sdk_dist_const__WEBPACK_IMPORTED_MODULE_17__.ImprovSerialCurrentState.PROVISIONED
- ? ""
- : (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.listItemHomeAssistant}
- Add to Home Assistant
-
- `}
- {
- this._state = "PROVISION";
- if (this._client.state === improv_wifi_serial_sdk_dist_const__WEBPACK_IMPORTED_MODULE_17__.ImprovSerialCurrentState.PROVISIONED) {
- this._provisionForce = true;
- }
- }}
- >
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.listItemWifi}
-
- ${this._client.state === improv_wifi_serial_sdk_dist_const__WEBPACK_IMPORTED_MODULE_17__.ImprovSerialCurrentState.READY
- ? "Connect to Wi-Fi"
- : "Change Wi-Fi"}
-
-
- {
- const client = this._client;
- if (client) {
- await this._closeClientWithoutEvents(client);
- await (0,_util_sleep__WEBPACK_IMPORTED_MODULE_21__.sleep)(100);
- }
- // Also set `null` back to undefined.
- this._client = undefined;
- this._state = "LOGS";
- }}
- >
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.listItemConsole}
- Logs & Console
-
- ${this._isSameFirmware && this._manifest.funding_url
- ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.listItemFundDevelopment}
- Fund Development
-
- `
- : ""}
- ${this._isSameVersion
- ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
- this._startInstall(true)}
- >
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.listItemEraseUserData}
- Erase User Data
-
- `
- : ""}
-
-
- `;
- return [heading, content, allowClosing];
- }
- _renderDashboardNoImprov() {
- const heading = this._manifest.name;
- let content;
- let allowClosing = true;
- content = (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
-
- {
- if (this._manifest.new_install_prompt_erase) {
- this._state = "ASK_ERASE";
- }
- else {
- // Default is to erase a device that does not support Improv Serial
- this._startInstall(true);
- }
- }}
- >
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.listItemInstallIcon}
- ${`Install ${this._manifest.name}`}
-
- {
- // Also set `null` back to undefined.
- this._client = undefined;
- this._state = "LOGS";
- }}
- >
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.listItemConsole}
- Logs & Console
-
-
-
- `;
- return [heading, content, allowClosing];
- }
- _renderProvision() {
- var _a;
- let heading = "Configure Wi-Fi";
- let content;
- if (this._busy) {
- return [
- heading,
- this._renderProgress(this._ssids === undefined
- ? "Scanning for networks"
- : "Trying to connect"),
- ];
- }
- if (!this._provisionForce &&
- this._client.state === improv_wifi_serial_sdk_dist_const__WEBPACK_IMPORTED_MODULE_17__.ImprovSerialCurrentState.PROVISIONED) {
- heading = undefined;
- const showSetupLinks = !this._wasProvisioned &&
- (this._client.nextUrl !== undefined ||
- "home_assistant_domain" in this._manifest);
- content = (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
-
- ${showSetupLinks
- ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- ${this._client.nextUrl === undefined
- ? ""
- : (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
- {
- this._state = "DASHBOARD";
- }}
- >
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.listItemVisitDevice}
- Visit Device
-
- `}
- ${!this._manifest.home_assistant_domain
- ? ""
- : (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
- {
- this._state = "DASHBOARD";
- }}
- >
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.listItemHomeAssistant}
- Add to Home Assistant
-
- `}
- {
- this._state = "DASHBOARD";
- }}
- >
-
- Skip
-
-
- `
- : ""}
-
-
- ${!showSetupLinks
- ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- {
- this._state = "DASHBOARD";
- }}
- >
- Continue
-
-
- `
- : ""}
- `;
- }
- else {
- let error;
- switch (this._client.error) {
- case 3 /* ImprovSerialErrorState.UNABLE_TO_CONNECT */:
- error = "Unable to connect";
- break;
- case 254 /* ImprovSerialErrorState.TIMEOUT */:
- error = "Timeout";
- break;
- case 0 /* ImprovSerialErrorState.NO_ERROR */:
- // Happens when list SSIDs not supported.
- case 2 /* ImprovSerialErrorState.UNKNOWN_RPC_COMMAND */:
- break;
- default:
- error = `Unknown error (${this._client.error})`;
- }
- const selectedSsid = (_a = this._ssids) === null || _a === void 0 ? void 0 : _a.find((info) => info.name === this._selectedSsid);
- content = (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- ${_components_svg__WEBPACK_IMPORTED_MODULE_15__.refreshIcon}
-
-
-
Connect your device to the network to start using it.
- ${error ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
${error}
` : ""}
- ${this._ssids !== null
- ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
{
- const index = ev.target.selectedIndex;
- // The "Join Other" item is always the last item.
- this._selectedSsid =
- index === this._ssids.length
- ? null
- : this._ssids[index].name;
- }}
- >
- ${this._ssids.map((info) => (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- ${info.name}
-
- `)}
-
-
- Join other…
-
-
- `
- : ""}
- ${
- // Show input box if command not supported or "Join Other" selected
- !selectedSsid
- ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- `
- : ""}
- ${!selectedSsid || selectedSsid.secured
- ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- `
- : ""}
-
-
- {
- this._state = "DASHBOARD";
- }}
- >
- ${this._installState && this._installErase ? "Skip" : "Back"}
-
- Connect
-
- `;
- }
- return [heading, content];
- }
- _renderAskErase() {
- const heading = "Erase device";
- const content = (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
-
- Do you want to erase the device before installing
- ${this._manifest.name}? All data on the device will be lost.
-
-
-
- Erase device
-
-
-
- {
- this._state = "DASHBOARD";
- }}
- >
- Back
-
- {
- const checkbox = this.shadowRoot.querySelector("ew-checkbox");
- this._startInstall(checkbox.checked);
- }}
- >
- Next
-
-
- `;
- return [heading, content];
- }
- _renderInstall() {
- let heading;
- let content;
- const allowClosing = false;
- const isUpdate = !this._installErase && this._isSameFirmware;
- if (!this._installConfirmed && this._isSameVersion) {
- heading = "Erase User Data";
- content = (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- Do you want to reset your device and erase all user data from your
- device?
-
-
-
- Erase User Data
-
-
- `;
- }
- else if (!this._installConfirmed) {
- heading = "Confirm Installation";
- const action = isUpdate ? "update to" : "install";
- content = (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
- ${isUpdate
- ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `Your device is running
- ${this._info.firmware} ${this._info.version}. `
- : ""}
- Do you want to ${action}
- ${this._manifest.name} ${this._manifest.version}?
- ${this._installErase
- ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) ` All data on the device will be erased.`
- : ""}
-
-
- {
- this._state = "DASHBOARD";
- }}
- >
- Back
-
-
- Install
-
-
- `;
- }
- else if (!this._installState ||
- this._installState.state === "initializing" /* FlashStateType.INITIALIZING */ ||
- this._installState.state === "preparing" /* FlashStateType.PREPARING */) {
- heading = "Installing";
- content = this._renderProgress("Preparing installation");
- }
- else if (this._installState.state === "erasing" /* FlashStateType.ERASING */) {
- heading = "Installing";
- content = this._renderProgress("Erasing");
- }
- else if (this._installState.state === "writing" /* FlashStateType.WRITING */ ||
- // When we're finished, keep showing this screen with 100% written
- // until Improv is initialized / not detected.
- (this._installState.state === "finished" /* FlashStateType.FINISHED */ &&
- this._client === undefined)) {
- heading = "Installing";
- let percentage;
- let undeterminateLabel;
- if (this._installState.state === "finished" /* FlashStateType.FINISHED */) {
- // We're done writing and detecting improv, show spinner
- undeterminateLabel = "Wrapping up";
- }
- else if (this._installState.details.percentage < 4) {
- // We're writing the firmware under 4%, show spinner or else we don't show any pixels
- undeterminateLabel = "Installing";
- }
- else {
- // We're writing the firmware over 4%, show progress bar
- percentage = this._installState.details.percentage;
- }
- content = this._renderProgress((0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
- ${undeterminateLabel ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `${undeterminateLabel} ` : ""}
-
- This will take
- ${this._installState.chipFamily === "ESP8266"
- ? "a minute"
- : "2 minutes"}.
- Keep this page visible to prevent slow down
- `, percentage);
- }
- else if (this._installState.state === "finished" /* FlashStateType.FINISHED */) {
- heading = undefined;
- const supportsImprov = this._client !== null;
- content = (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
-
-
- {
- this._state =
- supportsImprov && this._installErase
- ? "PROVISION"
- : "DASHBOARD";
- }}
- >
- Next
-
-
- `;
- }
- else if (this._installState.state === "error" /* FlashStateType.ERROR */) {
- heading = "Installation failed";
- content = (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
-
- {
- this._initialize();
- this._state = "DASHBOARD";
- }}
- >
- Back
-
-
- `;
- }
- return [heading, content, allowClosing];
- }
- _renderLogs() {
- let heading = `Logs`;
- let content;
- content = (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
-
-
-
- {
- await this.shadowRoot.querySelector("ewt-console").reset();
- }}
- >
- Reset Device
-
- {
- (0,_util_file_download__WEBPACK_IMPORTED_MODULE_19__.textDownload)(this.shadowRoot.querySelector("ewt-console").logs(), `esp-web-tools-logs.txt`);
- this.shadowRoot.querySelector("ewt-console").reset();
- }}
- >
- Download Logs
-
- {
- await this.shadowRoot.querySelector("ewt-console").disconnect();
- this._state = "DASHBOARD";
- this._initialize();
- }}
- >
- Back
-
-
- `;
- return [heading, content];
- }
- willUpdate(changedProps) {
- if (!changedProps.has("_state")) {
- return;
- }
- // Clear errors when changing between pages unless we change
- // to the error page.
- if (this._state !== "ERROR") {
- this._error = undefined;
- }
- // Scan for SSIDs on provision
- if (this._state === "PROVISION") {
- this._updateSsids();
- }
- else {
- // Reset this value if we leave provisioning.
- this._provisionForce = false;
- }
- if (this._state === "INSTALL") {
- this._installConfirmed = false;
- this._installState = undefined;
- }
- }
- async _updateSsids(tries = 0) {
- const oldSsids = this._ssids;
- this._ssids = undefined;
- this._busy = true;
- let ssids;
- try {
- ssids = await this._client.scan();
- }
- catch (err) {
- // When we fail while loading, pick "Join other"
- if (this._ssids === undefined) {
- this._ssids = null;
- this._selectedSsid = null;
- }
- this._busy = false;
- return;
- }
- // We will retry a few times if we don't get any results
- if (ssids.length === 0 && tries < 3) {
- console.log("SCHEDULE RETRY", tries);
- setTimeout(() => this._updateSsids(tries + 1), 1000);
- return;
- }
- if (oldSsids) {
- // If we had a previous list, ensure the selection is still valid
- if (this._selectedSsid &&
- !ssids.find((s) => s.name === this._selectedSsid)) {
- this._selectedSsid = ssids[0].name;
- }
- }
- else {
- this._selectedSsid = ssids.length ? ssids[0].name : null;
- }
- this._ssids = ssids;
- this._busy = false;
- }
- firstUpdated(changedProps) {
- super.firstUpdated(changedProps);
- this._bodyOverflow = document.body.style.overflow;
- document.body.style.overflow = "hidden";
- this._initialize();
- }
- updated(changedProps) {
- super.updated(changedProps);
- if (changedProps.has("_state")) {
- this.setAttribute("state", this._state);
- }
- if (this._state !== "PROVISION") {
- return;
- }
- if (changedProps.has("_selectedSsid") && this._selectedSsid === null) {
- // If we pick "Join other", select SSID input.
- this._focusFormElement("ew-filled-text-field[name=ssid]");
- }
- else if (changedProps.has("_ssids")) {
- // Form is shown when SSIDs are loaded/marked not supported
- this._focusFormElement();
- }
- }
- _focusFormElement(selector = "ew-filled-text-field, ew-filled-select") {
- const formEl = this.shadowRoot.querySelector(selector);
- if (formEl) {
- formEl.updateComplete.then(() => setTimeout(() => formEl.focus(), 100));
- }
- }
- async _initialize(justInstalled = false) {
- if (this.port.readable === null || this.port.writable === null) {
- this._state = "ERROR";
- this._error =
- "Serial port is not readable/writable. Close any other application using it and try again.";
- return;
- }
- try {
- this._manifest = await (0,_util_manifest__WEBPACK_IMPORTED_MODULE_22__.downloadManifest)(this.manifestPath);
- }
- catch (err) {
- this._state = "ERROR";
- this._error = "Failed to download manifest";
- return;
- }
- if (this._manifest.new_install_improv_wait_time === 0) {
- this._client = null;
- return;
- }
- const client = new improv_wifi_serial_sdk_dist_serial__WEBPACK_IMPORTED_MODULE_16__.ImprovSerial(this.port, this.logger);
- client.addEventListener("state-changed", () => {
- this.requestUpdate();
- });
- client.addEventListener("error-changed", () => this.requestUpdate());
- try {
- // If a device was just installed, give new firmware 10 seconds (overridable) to
- // format the rest of the flash and do other stuff.
- const timeout = !justInstalled
- ? 1000
- : this._manifest.new_install_improv_wait_time !== undefined
- ? this._manifest.new_install_improv_wait_time * 1000
- : 10000;
- this._info = await client.initialize(timeout);
- this._client = client;
- client.addEventListener("disconnect", this._handleDisconnect);
- }
- catch (err) {
- // Clear old value
- this._info = undefined;
- if (err instanceof improv_wifi_serial_sdk_dist_const__WEBPACK_IMPORTED_MODULE_17__.PortNotReady) {
- this._state = "ERROR";
- this._error =
- "Serial port is not ready. Close any other application using it and try again.";
- }
- else {
- this._client = null; // not supported
- this.logger.error("Improv initialization failed.", err);
- }
- }
- }
- _startInstall(erase) {
- this._state = "INSTALL";
- this._installErase = erase;
- this._installConfirmed = false;
- }
- async _confirmInstall() {
- this._installConfirmed = true;
- this._installState = undefined;
- if (this._client) {
- await this._closeClientWithoutEvents(this._client);
- }
- this._client = undefined;
- // Close port. ESPLoader likes opening it.
- await this.port.close();
- (0,_flash__WEBPACK_IMPORTED_MODULE_18__.flash)((state) => {
- this._installState = state;
- if (state.state === "finished" /* FlashStateType.FINISHED */) {
- (0,_util_sleep__WEBPACK_IMPORTED_MODULE_21__.sleep)(100)
- // Flashing closes the port
- .then(() => this.port.open({ baudRate: 115200, bufferSize: 8192 }))
- .then(() => this._initialize(true))
- .then(() => this.requestUpdate());
- }
- else if (state.state === "error" /* FlashStateType.ERROR */) {
- (0,_util_sleep__WEBPACK_IMPORTED_MODULE_21__.sleep)(100)
- // Flashing closes the port
- .then(() => this.port.open({ baudRate: 115200, bufferSize: 8192 }));
- }
- }, this.port, this.manifestPath, this._manifest, this._installErase);
- }
- async _doProvision() {
- var _a;
- this._busy = true;
- this._wasProvisioned =
- this._client.state === improv_wifi_serial_sdk_dist_const__WEBPACK_IMPORTED_MODULE_17__.ImprovSerialCurrentState.PROVISIONED;
- const ssid = this._selectedSsid === null
- ? this.shadowRoot.querySelector("ew-filled-text-field[name=ssid]").value
- : this._selectedSsid;
- const password = ((_a = this.shadowRoot.querySelector("ew-filled-text-field[name=password]")) === null || _a === void 0 ? void 0 : _a.value) || "";
- try {
- await this._client.provision(ssid, password, 30000);
- }
- catch (err) {
- return;
- }
- finally {
- this._busy = false;
- this._provisionForce = false;
- }
- }
- _closeDialog() {
- this.shadowRoot.querySelector("ew-dialog").close();
- }
- async _handleClose() {
- if (this._client) {
- await this._closeClientWithoutEvents(this._client);
- }
- (0,_util_fire_event__WEBPACK_IMPORTED_MODULE_20__.fireEvent)(this, "closed");
- document.body.style.overflow = this._bodyOverflow;
- this.parentNode.removeChild(this);
- }
- /**
- * Return if the device runs same firmware as manifest.
- */
- get _isSameFirmware() {
- var _a;
- return !this._info
- ? false
- : ((_a = this.overrides) === null || _a === void 0 ? void 0 : _a.checkSameFirmware)
- ? this.overrides.checkSameFirmware(this._manifest, this._info)
- : this._info.firmware === this._manifest.name;
- }
- /**
- * Return if the device runs same firmware and version as manifest.
- */
- get _isSameVersion() {
- return (this._isSameFirmware && this._info.version === this._manifest.version);
- }
- async _closeClientWithoutEvents(client) {
- client.removeEventListener("disconnect", this._handleDisconnect);
- await client.close();
- }
- _preventDefault(ev) {
- ev.preventDefault();
- }
-}
-EwtInstallDialog.styles = [
- _styles__WEBPACK_IMPORTED_MODULE_23__.dialogStyles,
- (0,lit__WEBPACK_IMPORTED_MODULE_0__.css) `
- :host {
- --mdc-dialog-max-width: 390px;
- }
- div[slot="headline"] {
- padding-right: 48px;
- }
- ew-icon-button[slot="headline"] {
- position: absolute;
- right: 4px;
- top: 8px;
- }
- ew-icon-button[slot="headline"] svg {
- padding: 8px;
- color: var(--text-color);
- }
- .dialog-nav svg {
- color: var(--text-color);
- }
- .table-row {
- display: flex;
- }
- .table-row.last {
- margin-bottom: 16px;
- }
- .table-row svg {
- width: 20px;
- margin-right: 8px;
- }
- ew-filled-text-field,
- ew-filled-select {
- display: block;
- margin-top: 16px;
- }
- label.formfield {
- display: inline-flex;
- align-items: center;
- padding-right: 8px;
- }
- ew-list {
- margin: 0 -24px;
- padding: 0;
- }
- ew-list-item svg {
- height: 24px;
- }
- ewt-page-message + ew-list {
- padding-top: 16px;
- }
- .fake-icon {
- width: 24px;
- }
- .error {
- color: var(--danger-color);
- }
- .danger {
- --mdc-theme-primary: var(--danger-color);
- --mdc-theme-secondary: var(--danger-color);
- --md-sys-color-primary: var(--danger-color);
- --md-sys-color-on-surface: var(--danger-color);
- }
- button.link {
- background: none;
- color: inherit;
- border: none;
- padding: 0;
- font: inherit;
- text-align: left;
- text-decoration: underline;
- cursor: pointer;
- }
- :host([state="LOGS"]) ew-dialog {
- max-width: 90vw;
- max-height: 90vh;
- }
- ewt-console {
- width: calc(80vw - 48px);
- height: calc(90vh - 168px);
- }
- `,
-];
-(0,tslib__WEBPACK_IMPORTED_MODULE_25__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], EwtInstallDialog.prototype, "_client", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_25__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], EwtInstallDialog.prototype, "_state", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_25__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], EwtInstallDialog.prototype, "_installErase", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_25__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], EwtInstallDialog.prototype, "_installConfirmed", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_25__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], EwtInstallDialog.prototype, "_installState", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_25__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], EwtInstallDialog.prototype, "_provisionForce", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_25__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], EwtInstallDialog.prototype, "_error", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_25__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], EwtInstallDialog.prototype, "_busy", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_25__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], EwtInstallDialog.prototype, "_ssids", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_25__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.state)()
-], EwtInstallDialog.prototype, "_selectedSsid", void 0);
-customElements.define("ewt-install-dialog", EwtInstallDialog);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/pages/ewt-page-message.js":
-/*!*******************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/pages/ewt-page-message.js ***!
- \*******************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
-/* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lit */ "./node_modules/lit/index.js");
-/* harmony import */ var lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! lit/decorators.js */ "./node_modules/lit/decorators.js");
-
-
-
-class EwtPageMessage extends lit__WEBPACK_IMPORTED_MODULE_0__.LitElement {
- render() {
- return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
- ${this.icon}
- ${this.label}
- `;
- }
-}
-EwtPageMessage.styles = (0,lit__WEBPACK_IMPORTED_MODULE_0__.css) `
- :host {
- display: flex;
- flex-direction: column;
- text-align: center;
- }
- .icon {
- font-size: 50px;
- line-height: 80px;
- color: black;
- }
- `;
-(0,tslib__WEBPACK_IMPORTED_MODULE_2__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)()
-], EwtPageMessage.prototype, "icon", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_2__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)()
-], EwtPageMessage.prototype, "label", void 0);
-customElements.define("ewt-page-message", EwtPageMessage);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/pages/ewt-page-progress.js":
-/*!********************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/pages/ewt-page-progress.js ***!
- \********************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
-/* harmony import */ var lit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lit */ "./node_modules/lit/index.js");
-/* harmony import */ var lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! lit/decorators.js */ "./node_modules/lit/decorators.js");
-/* harmony import */ var _components_ew_circular_progress__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../components/ew-circular-progress */ "./node_modules/esp-web-tools/dist/components/ew-circular-progress.js");
-
-
-
-
-class EwtPageProgress extends lit__WEBPACK_IMPORTED_MODULE_0__.LitElement {
- render() {
- return (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
-
-
- ${this.progress !== undefined ? (0,lit__WEBPACK_IMPORTED_MODULE_0__.html) `
${this.progress}%
` : ""}
-
- ${this.label}
- `;
- }
-}
-EwtPageProgress.styles = (0,lit__WEBPACK_IMPORTED_MODULE_0__.css) `
- :host {
- display: flex;
- flex-direction: column;
- text-align: center;
- }
- ew-circular-progress {
- margin-bottom: 16px;
- }
- `;
-(0,tslib__WEBPACK_IMPORTED_MODULE_3__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)()
-], EwtPageProgress.prototype, "label", void 0);
-(0,tslib__WEBPACK_IMPORTED_MODULE_3__.__decorate)([
- (0,lit_decorators_js__WEBPACK_IMPORTED_MODULE_1__.property)()
-], EwtPageProgress.prototype, "progress", void 0);
-customElements.define("ewt-page-progress", EwtPageProgress);
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/util/console-color.js":
-/*!***************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/util/console-color.js ***!
- \***************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ ColoredConsole: () => (/* binding */ ColoredConsole),
-/* harmony export */ coloredConsoleStyles: () => (/* binding */ coloredConsoleStyles)
-/* harmony export */ });
-class ColoredConsole {
- constructor(targetElement) {
- this.targetElement = targetElement;
- this.state = {
- bold: false,
- italic: false,
- underline: false,
- strikethrough: false,
- foregroundColor: null,
- backgroundColor: null,
- carriageReturn: false,
- lines: [],
- secret: false,
- };
- }
- logs() {
- return this.targetElement.innerText;
- }
- processLine(line) {
- // @ts-expect-error
- const re = /(?:\033|\\033)(?:\[(.*?)[@-~]|\].*?(?:\007|\033\\))/g;
- let i = 0;
- const lineSpan = document.createElement("span");
- lineSpan.classList.add("line");
- const addSpan = (content) => {
- if (content === "")
- return;
- const span = document.createElement("span");
- if (this.state.bold)
- span.classList.add("log-bold");
- if (this.state.italic)
- span.classList.add("log-italic");
- if (this.state.underline)
- span.classList.add("log-underline");
- if (this.state.strikethrough)
- span.classList.add("log-strikethrough");
- if (this.state.secret)
- span.classList.add("log-secret");
- if (this.state.foregroundColor !== null)
- span.classList.add(`log-fg-${this.state.foregroundColor}`);
- if (this.state.backgroundColor !== null)
- span.classList.add(`log-bg-${this.state.backgroundColor}`);
- span.appendChild(document.createTextNode(content));
- lineSpan.appendChild(span);
- if (this.state.secret) {
- const redacted = document.createElement("span");
- redacted.classList.add("log-secret-redacted");
- redacted.appendChild(document.createTextNode("[redacted]"));
- lineSpan.appendChild(redacted);
- }
- };
- while (true) {
- const match = re.exec(line);
- if (match === null)
- break;
- const j = match.index;
- addSpan(line.substring(i, j));
- i = j + match[0].length;
- if (match[1] === undefined)
- continue;
- for (const colorCode of match[1].split(";")) {
- switch (parseInt(colorCode)) {
- case 0:
- // reset
- this.state.bold = false;
- this.state.italic = false;
- this.state.underline = false;
- this.state.strikethrough = false;
- this.state.foregroundColor = null;
- this.state.backgroundColor = null;
- this.state.secret = false;
- break;
- case 1:
- this.state.bold = true;
- break;
- case 3:
- this.state.italic = true;
- break;
- case 4:
- this.state.underline = true;
- break;
- case 5:
- this.state.secret = true;
- break;
- case 6:
- this.state.secret = false;
- break;
- case 9:
- this.state.strikethrough = true;
- break;
- case 22:
- this.state.bold = false;
- break;
- case 23:
- this.state.italic = false;
- break;
- case 24:
- this.state.underline = false;
- break;
- case 29:
- this.state.strikethrough = false;
- break;
- case 30:
- this.state.foregroundColor = "black";
- break;
- case 31:
- this.state.foregroundColor = "red";
- break;
- case 32:
- this.state.foregroundColor = "green";
- break;
- case 33:
- this.state.foregroundColor = "yellow";
- break;
- case 34:
- this.state.foregroundColor = "blue";
- break;
- case 35:
- this.state.foregroundColor = "magenta";
- break;
- case 36:
- this.state.foregroundColor = "cyan";
- break;
- case 37:
- this.state.foregroundColor = "white";
- break;
- case 39:
- this.state.foregroundColor = null;
- break;
- case 41:
- this.state.backgroundColor = "red";
- break;
- case 42:
- this.state.backgroundColor = "green";
- break;
- case 43:
- this.state.backgroundColor = "yellow";
- break;
- case 44:
- this.state.backgroundColor = "blue";
- break;
- case 45:
- this.state.backgroundColor = "magenta";
- break;
- case 46:
- this.state.backgroundColor = "cyan";
- break;
- case 47:
- this.state.backgroundColor = "white";
- break;
- case 40:
- case 49:
- this.state.backgroundColor = null;
- break;
- }
- }
- }
- addSpan(line.substring(i));
- return lineSpan;
- }
- processLines() {
- const atBottom = this.targetElement.scrollTop >
- this.targetElement.scrollHeight - this.targetElement.offsetHeight - 50;
- const prevCarriageReturn = this.state.carriageReturn;
- const fragment = document.createDocumentFragment();
- if (this.state.lines.length == 0) {
- return;
- }
- for (const line of this.state.lines) {
- if (this.state.carriageReturn && line !== "\n") {
- if (fragment.childElementCount) {
- fragment.removeChild(fragment.lastChild);
- }
- }
- fragment.appendChild(this.processLine(line));
- this.state.carriageReturn = line.includes("\r");
- }
- if (prevCarriageReturn && this.state.lines[0] !== "\n") {
- this.targetElement.replaceChild(fragment, this.targetElement.lastChild);
- }
- else {
- this.targetElement.appendChild(fragment);
- }
- this.state.lines = [];
- // Keep scroll at bottom
- if (atBottom) {
- this.targetElement.scrollTop = this.targetElement.scrollHeight;
- }
- }
- addLine(line) {
- // Processing of lines is deferred for performance reasons
- if (this.state.lines.length == 0) {
- setTimeout(() => this.processLines(), 0);
- }
- this.state.lines.push(line);
- }
-}
-const coloredConsoleStyles = `
- .log {
- flex: 1;
- background-color: #1c1c1c;
- font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
- monospace;
- font-size: 12px;
- padding: 16px;
- overflow: auto;
- line-height: 1.45;
- border-radius: 3px;
- white-space: pre-wrap;
- overflow-wrap: break-word;
- color: #ddd;
- }
-
- .log-bold {
- font-weight: bold;
- }
- .log-italic {
- font-style: italic;
- }
- .log-underline {
- text-decoration: underline;
- }
- .log-strikethrough {
- text-decoration: line-through;
- }
- .log-underline.log-strikethrough {
- text-decoration: underline line-through;
- }
- .log-secret {
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- }
- .log-secret-redacted {
- opacity: 0;
- width: 1px;
- font-size: 1px;
- }
- .log-fg-black {
- color: rgb(128, 128, 128);
- }
- .log-fg-red {
- color: rgb(255, 0, 0);
- }
- .log-fg-green {
- color: rgb(0, 255, 0);
- }
- .log-fg-yellow {
- color: rgb(255, 255, 0);
- }
- .log-fg-blue {
- color: rgb(0, 0, 255);
- }
- .log-fg-magenta {
- color: rgb(255, 0, 255);
- }
- .log-fg-cyan {
- color: rgb(0, 255, 255);
- }
- .log-fg-white {
- color: rgb(187, 187, 187);
- }
- .log-bg-black {
- background-color: rgb(0, 0, 0);
- }
- .log-bg-red {
- background-color: rgb(255, 0, 0);
- }
- .log-bg-green {
- background-color: rgb(0, 255, 0);
- }
- .log-bg-yellow {
- background-color: rgb(255, 255, 0);
- }
- .log-bg-blue {
- background-color: rgb(0, 0, 255);
- }
- .log-bg-magenta {
- background-color: rgb(255, 0, 255);
- }
- .log-bg-cyan {
- background-color: rgb(0, 255, 255);
- }
- .log-bg-white {
- background-color: rgb(255, 255, 255);
- }
-`;
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/util/file-download.js":
-/*!***************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/util/file-download.js ***!
- \***************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ fileDownload: () => (/* binding */ fileDownload),
-/* harmony export */ textDownload: () => (/* binding */ textDownload)
-/* harmony export */ });
-const fileDownload = (href, filename = "") => {
- const a = document.createElement("a");
- a.target = "_blank";
- a.href = href;
- a.download = filename;
- document.body.appendChild(a);
- a.dispatchEvent(new MouseEvent("click"));
- document.body.removeChild(a);
-};
-const textDownload = (text, filename = "") => {
- const blob = new Blob([text], { type: "text/plain" });
- const url = URL.createObjectURL(blob);
- fileDownload(url, filename);
- setTimeout(() => URL.revokeObjectURL(url), 0);
-};
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/util/fire-event.js":
-/*!************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/util/fire-event.js ***!
- \************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ fireEvent: () => (/* binding */ fireEvent)
-/* harmony export */ });
-const fireEvent = (eventTarget, type,
-// @ts-ignore
-detail, options) => {
- options = options || {};
- const event = new CustomEvent(type, {
- bubbles: options.bubbles === undefined ? true : options.bubbles,
- cancelable: Boolean(options.cancelable),
- composed: options.composed === undefined ? true : options.composed,
- detail,
- });
- eventTarget.dispatchEvent(event);
-};
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/util/line-break-transformer.js":
-/*!************************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/util/line-break-transformer.js ***!
- \************************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ LineBreakTransformer: () => (/* binding */ LineBreakTransformer)
-/* harmony export */ });
-class LineBreakTransformer {
- constructor() {
- this.chunks = "";
- }
- transform(chunk, controller) {
- // Append new chunks to existing chunks.
- this.chunks += chunk;
- // For each line breaks in chunks, send the parsed lines out.
- const lines = this.chunks.split(/\r?\n/);
- this.chunks = lines.pop();
- lines.forEach((line) => controller.enqueue(line + "\r\n"));
- }
- flush(controller) {
- // When the stream is closed, flush any remaining chunks out.
- controller.enqueue(this.chunks);
- }
-}
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/util/manifest.js":
-/*!**********************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/util/manifest.js ***!
- \**********************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ downloadManifest: () => (/* binding */ downloadManifest)
-/* harmony export */ });
-const downloadManifest = async (manifestPath) => {
- const manifestURL = new URL(manifestPath, location.toString()).toString();
- const resp = await fetch(manifestURL);
- const manifest = await resp.json();
- if ("new_install_skip_erase" in manifest) {
- console.warn('Manifest option "new_install_skip_erase" is deprecated. Use "new_install_prompt_erase" instead.');
- if (manifest.new_install_skip_erase) {
- manifest.new_install_prompt_erase = true;
- }
- }
- return manifest;
-};
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/util/reset.js":
-/*!*******************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/util/reset.js ***!
- \*******************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ hardReset: () => (/* binding */ hardReset)
-/* harmony export */ });
-/* harmony import */ var _sleep__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./sleep */ "./node_modules/esp-web-tools/dist/util/sleep.js");
-
-const hardReset = async (transport) => {
- console.log("Triggering reset");
- await transport.device.setSignals({
- dataTerminalReady: false,
- requestToSend: true,
- });
- await (0,_sleep__WEBPACK_IMPORTED_MODULE_0__.sleep)(250);
- await transport.device.setSignals({
- dataTerminalReady: false,
- requestToSend: false,
- });
- await (0,_sleep__WEBPACK_IMPORTED_MODULE_0__.sleep)(250);
- await new Promise((resolve) => setTimeout(resolve, 1000));
-};
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/util/sleep.js":
-/*!*******************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/util/sleep.js ***!
- \*******************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ sleep: () => (/* binding */ sleep)
-/* harmony export */ });
-const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/util/timestamp-transformer.js":
-/*!***********************************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/util/timestamp-transformer.js ***!
- \***********************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ TimestampTransformer: () => (/* binding */ TimestampTransformer)
-/* harmony export */ });
-class TimestampTransformer {
- transform(chunk, controller) {
- const date = new Date();
- const h = date.getHours().toString().padStart(2, "0");
- const m = date.getMinutes().toString().padStart(2, "0");
- const s = date.getSeconds().toString().padStart(2, "0");
- controller.enqueue(`[${h}:${m}:${s}]${chunk}`);
- }
-}
-
-
-/***/ }),
-
-/***/ "./node_modules/esp-web-tools/dist/version.js":
-/*!****************************************************!*\
- !*** ./node_modules/esp-web-tools/dist/version.js ***!
- \****************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ version: () => (/* binding */ version)
-/* harmony export */ });
-const version = "10.1.1";
-
-
-/***/ }),
-
-/***/ "./node_modules/esptool-js/lib/esploader.js":
-/*!**************************************************!*\
- !*** ./node_modules/esptool-js/lib/esploader.js ***!
- \**************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ ESPLoader: () => (/* binding */ ESPLoader)
-/* harmony export */ });
-/* harmony import */ var _types_error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./types/error.js */ "./node_modules/esptool-js/lib/types/error.js");
-/* harmony import */ var pako__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! pako */ "./node_modules/pako/dist/pako.esm.mjs");
-/* harmony import */ var _webserial_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./webserial.js */ "./node_modules/esptool-js/lib/webserial.js");
-/* harmony import */ var _reset_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./reset.js */ "./node_modules/esptool-js/lib/reset.js");
-/* harmony import */ var _stubFlasher_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./stubFlasher.js */ "./node_modules/esptool-js/lib/stubFlasher.js");
-/* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./util.js */ "./node_modules/esptool-js/lib/util.js");
-
-
-
-
-
-
-/**
- * Return the chip ROM based on the given magic number
- * @param {number} magic - magic hex number to select ROM.
- * @returns {ROM} The chip ROM class related to given magic hex number.
- */
-async function magic2Chip(magic) {
- switch (magic) {
- case 0x00f01d83: {
- const { ESP32ROM } = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_esp32_js").then(__webpack_require__.bind(__webpack_require__, /*! ./targets/esp32.js */ "./node_modules/esptool-js/lib/targets/esp32.js"));
- return new ESP32ROM();
- }
- case 0xc21e06f:
- case 0x6f51306f:
- case 0x7c41a06f: {
- const { ESP32C2ROM } = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_esp32c2_js").then(__webpack_require__.bind(__webpack_require__, /*! ./targets/esp32c2.js */ "./node_modules/esptool-js/lib/targets/esp32c2.js"));
- return new ESP32C2ROM();
- }
- case 0x6921506f:
- case 0x1b31506f:
- case 0x4881606f:
- case 0x4361606f: {
- const { ESP32C3ROM } = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_esp32c3_js").then(__webpack_require__.bind(__webpack_require__, /*! ./targets/esp32c3.js */ "./node_modules/esptool-js/lib/targets/esp32c3.js"));
- return new ESP32C3ROM();
- }
- case 0x2ce0806f: {
- const { ESP32C6ROM } = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_esp32c6_js").then(__webpack_require__.bind(__webpack_require__, /*! ./targets/esp32c6.js */ "./node_modules/esptool-js/lib/targets/esp32c6.js"));
- return new ESP32C6ROM();
- }
- case 0x2421606f:
- case 0x33f0206f:
- case 0x4f81606f: {
- const { ESP32C61ROM } = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_esp32c61_js").then(__webpack_require__.bind(__webpack_require__, /*! ./targets/esp32c61.js */ "./node_modules/esptool-js/lib/targets/esp32c61.js"));
- return new ESP32C61ROM();
- }
- case 0x1101406f:
- case 0x63e1406f:
- case 0x5fd1406f: {
- const { ESP32C5ROM } = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_esp32c5_js").then(__webpack_require__.bind(__webpack_require__, /*! ./targets/esp32c5.js */ "./node_modules/esptool-js/lib/targets/esp32c5.js"));
- return new ESP32C5ROM();
- }
- case 0xd7b73e80: {
- const { ESP32H2ROM } = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_esp32h2_js").then(__webpack_require__.bind(__webpack_require__, /*! ./targets/esp32h2.js */ "./node_modules/esptool-js/lib/targets/esp32h2.js"));
- return new ESP32H2ROM();
- }
- case 0x09: {
- const { ESP32S3ROM } = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_esp32s3_js").then(__webpack_require__.bind(__webpack_require__, /*! ./targets/esp32s3.js */ "./node_modules/esptool-js/lib/targets/esp32s3.js"));
- return new ESP32S3ROM();
- }
- case 0x000007c6: {
- const { ESP32S2ROM } = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_esp32s2_js").then(__webpack_require__.bind(__webpack_require__, /*! ./targets/esp32s2.js */ "./node_modules/esptool-js/lib/targets/esp32s2.js"));
- return new ESP32S2ROM();
- }
- case 0xfff0c101: {
- const { ESP8266ROM } = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_esp8266_js").then(__webpack_require__.bind(__webpack_require__, /*! ./targets/esp8266.js */ "./node_modules/esptool-js/lib/targets/esp8266.js"));
- return new ESP8266ROM();
- }
- case 0x0:
- case 0x0addbad0:
- case 0x7039ad9: {
- const { ESP32P4ROM } = await __webpack_require__.e(/*! import() */ "vendors-node_modules_esptool-js_lib_targets_esp32p4_js").then(__webpack_require__.bind(__webpack_require__, /*! ./targets/esp32p4.js */ "./node_modules/esptool-js/lib/targets/esp32p4.js"));
- return new ESP32P4ROM();
- }
- default:
- return null;
- }
-}
-class ESPLoader {
- /**
- * Create a new ESPLoader to perform serial communication
- * such as read/write flash memory and registers using a LoaderOptions object.
- * @param {LoaderOptions} options - LoaderOptions object argument for ESPLoader.
- * ```
- * const myLoader = new ESPLoader({ transport: Transport, baudrate: number, terminal?: IEspLoaderTerminal });
- * ```
- */
- constructor(options) {
- var _a, _b, _c, _d, _e, _f, _g, _h;
- this.ESP_RAM_BLOCK = 0x1800;
- this.ESP_FLASH_BEGIN = 0x02;
- this.ESP_FLASH_DATA = 0x03;
- this.ESP_FLASH_END = 0x04;
- this.ESP_MEM_BEGIN = 0x05;
- this.ESP_MEM_END = 0x06;
- this.ESP_MEM_DATA = 0x07;
- this.ESP_WRITE_REG = 0x09;
- this.ESP_READ_REG = 0x0a;
- this.ESP_SPI_ATTACH = 0x0d;
- this.ESP_CHANGE_BAUDRATE = 0x0f;
- this.ESP_FLASH_DEFL_BEGIN = 0x10;
- this.ESP_FLASH_DEFL_DATA = 0x11;
- this.ESP_FLASH_DEFL_END = 0x12;
- this.ESP_SPI_FLASH_MD5 = 0x13;
- // Only Stub supported commands
- this.ESP_ERASE_FLASH = 0xd0;
- this.ESP_ERASE_REGION = 0xd1;
- this.ESP_READ_FLASH = 0xd2;
- this.ESP_RUN_USER_CODE = 0xd3;
- this.ESP_IMAGE_MAGIC = 0xe9;
- this.ESP_CHECKSUM_MAGIC = 0xef;
- // Response code(s) sent by ROM
- this.ROM_INVALID_RECV_MSG = 0x05; // response if an invalid message is received
- this.DEFAULT_TIMEOUT = 3000;
- this.ERASE_REGION_TIMEOUT_PER_MB = 30000;
- this.ERASE_WRITE_TIMEOUT_PER_MB = 40000;
- this.MD5_TIMEOUT_PER_MB = 8000;
- this.CHIP_ERASE_TIMEOUT = 120000;
- this.FLASH_READ_TIMEOUT = 100000;
- this.MAX_TIMEOUT = this.CHIP_ERASE_TIMEOUT * 2;
- this.CHIP_DETECT_MAGIC_REG_ADDR = 0x40001000;
- this.DETECTED_FLASH_SIZES = {
- 0x12: "256KB",
- 0x13: "512KB",
- 0x14: "1MB",
- 0x15: "2MB",
- 0x16: "4MB",
- 0x17: "8MB",
- 0x18: "16MB",
- };
- this.DETECTED_FLASH_SIZES_NUM = {
- 0x12: 256,
- 0x13: 512,
- 0x14: 1024,
- 0x15: 2048,
- 0x16: 4096,
- 0x17: 8192,
- 0x18: 16384,
- };
- this.USB_JTAG_SERIAL_PID = 0x1001;
- this.romBaudrate = 115200;
- this.debugLogging = false;
- this.syncStubDetected = false;
- /**
- * Get flash size bytes from flash size string.
- * @param {string} flashSize Flash Size string
- * @returns {number} Flash size bytes
- */
- this.flashSizeBytes = function (flashSize) {
- let flashSizeB = -1;
- if (flashSize.indexOf("KB") !== -1) {
- flashSizeB = parseInt(flashSize.slice(0, flashSize.indexOf("KB"))) * 1024;
- }
- else if (flashSize.indexOf("MB") !== -1) {
- flashSizeB = parseInt(flashSize.slice(0, flashSize.indexOf("MB"))) * 1024 * 1024;
- }
- return flashSizeB;
- };
- this.IS_STUB = false;
- this.FLASH_WRITE_SIZE = 0x4000;
- this.transport = options.transport;
- this.baudrate = options.baudrate;
- this.resetConstructors = {
- classicReset: (transport, resetDelay) => new _reset_js__WEBPACK_IMPORTED_MODULE_3__.ClassicReset(transport, resetDelay),
- customReset: (transport, sequenceString) => new _reset_js__WEBPACK_IMPORTED_MODULE_3__.CustomReset(transport, sequenceString),
- hardReset: (transport, usingUsbOtg) => new _reset_js__WEBPACK_IMPORTED_MODULE_3__.HardReset(transport, usingUsbOtg),
- usbJTAGSerialReset: (transport) => new _reset_js__WEBPACK_IMPORTED_MODULE_3__.UsbJtagSerialReset(transport),
- };
- if (options.serialOptions) {
- this.serialOptions = options.serialOptions;
- }
- if (options.romBaudrate) {
- this.romBaudrate = options.romBaudrate;
- }
- if (options.terminal) {
- this.terminal = options.terminal;
- this.terminal.clean();
- }
- if (typeof options.debugLogging !== "undefined") {
- this.debugLogging = options.debugLogging;
- }
- if (options.port) {
- this.transport = new _webserial_js__WEBPACK_IMPORTED_MODULE_2__.Transport(options.port);
- }
- if (typeof options.enableTracing !== "undefined") {
- this.transport.tracing = options.enableTracing;
- }
- if ((_a = options.resetConstructors) === null || _a === void 0 ? void 0 : _a.classicReset) {
- this.resetConstructors.classicReset = (_b = options.resetConstructors) === null || _b === void 0 ? void 0 : _b.classicReset;
- }
- if ((_c = options.resetConstructors) === null || _c === void 0 ? void 0 : _c.customReset) {
- this.resetConstructors.customReset = (_d = options.resetConstructors) === null || _d === void 0 ? void 0 : _d.customReset;
- }
- if ((_e = options.resetConstructors) === null || _e === void 0 ? void 0 : _e.hardReset) {
- this.resetConstructors.hardReset = (_f = options.resetConstructors) === null || _f === void 0 ? void 0 : _f.hardReset;
- }
- if ((_g = options.resetConstructors) === null || _g === void 0 ? void 0 : _g.usbJTAGSerialReset) {
- this.resetConstructors.usbJTAGSerialReset = (_h = options.resetConstructors) === null || _h === void 0 ? void 0 : _h.usbJTAGSerialReset;
- }
- this.info("esptool.js");
- this.info("Serial port " + this.transport.getInfo());
- }
- _sleep(ms) {
- return new Promise((resolve) => setTimeout(resolve, ms));
- }
- /**
- * Write to ESP Loader constructor's terminal with or without new line.
- * @param {string} str - String to write.
- * @param {boolean} withNewline - Add new line at the end ?
- */
- write(str, withNewline = true) {
- if (this.terminal) {
- if (withNewline) {
- this.terminal.writeLine(str);
- }
- else {
- this.terminal.write(str);
- }
- }
- else {
- // eslint-disable-next-line no-console
- console.log(str);
- }
- }
- /**
- * Write error message to ESP Loader constructor's terminal with or without new line.
- * @param {string} str - String to write.
- * @param {boolean} withNewline - Add new line at the end ?
- */
- error(str, withNewline = true) {
- this.write(`Error: ${str}`, withNewline);
- }
- /**
- * Write information message to ESP Loader constructor's terminal with or without new line.
- * @param {string} str - String to write.
- * @param {boolean} withNewline - Add new line at the end ?
- */
- info(str, withNewline = true) {
- this.write(str, withNewline);
- }
- /**
- * Write debug message to ESP Loader constructor's terminal with or without new line.
- * @param {string} str - String to write.
- * @param {boolean} withNewline - Add new line at the end ?
- */
- debug(str, withNewline = true) {
- if (this.debugLogging) {
- this.write(`Debug: ${str}`, withNewline);
- }
- }
- /**
- * Convert short integer to byte array
- * @param {number} i - Number to convert.
- * @returns {Uint8Array} Byte array.
- */
- _shortToBytearray(i) {
- return new Uint8Array([i & 0xff, (i >> 8) & 0xff]);
- }
- /**
- * Convert an integer to byte array
- * @param {number} i - Number to convert.
- * @returns {ROM} The chip ROM class related to given magic hex number.
- */
- _intToByteArray(i) {
- return new Uint8Array([i & 0xff, (i >> 8) & 0xff, (i >> 16) & 0xff, (i >> 24) & 0xff]);
- }
- /**
- * Convert a byte array to short integer.
- * @param {number} i - Number to convert.
- * @param {number} j - Number to convert.
- * @returns {number} Return a short integer number.
- */
- _byteArrayToShort(i, j) {
- return i | (j >> 8);
- }
- /**
- * Convert a byte array to integer.
- * @param {number} i - Number to convert.
- * @param {number} j - Number to convert.
- * @param {number} k - Number to convert.
- * @param {number} l - Number to convert.
- * @returns {number} Return a integer number.
- */
- _byteArrayToInt(i, j, k, l) {
- return i | (j << 8) | (k << 16) | (l << 24);
- }
- /**
- * Append a buffer array after another buffer array
- * @param {ArrayBuffer} buffer1 - First array buffer.
- * @param {ArrayBuffer} buffer2 - magic hex number to select ROM.
- * @returns {ArrayBufferLike} Return an array buffer.
- */
- _appendBuffer(buffer1, buffer2) {
- const tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
- tmp.set(new Uint8Array(buffer1), 0);
- tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
- return tmp.buffer;
- }
- /**
- * Append a buffer array after another buffer array
- * @param {Uint8Array} arr1 - First array buffer.
- * @param {Uint8Array} arr2 - magic hex number to select ROM.
- * @returns {Uint8Array} Return a 8 bit unsigned array.
- */
- _appendArray(arr1, arr2) {
- const c = new Uint8Array(arr1.length + arr2.length);
- c.set(arr1, 0);
- c.set(arr2, arr1.length);
- return c;
- }
- /**
- * Convert a unsigned 8 bit integer array to byte string.
- * @param {Uint8Array} u8Array - magic hex number to select ROM.
- * @returns {string} Return the equivalent string.
- */
- ui8ToBstr(u8Array) {
- let bStr = "";
- for (let i = 0; i < u8Array.length; i++) {
- bStr += String.fromCharCode(u8Array[i]);
- }
- return bStr;
- }
- /**
- * Convert a byte string to unsigned 8 bit integer array.
- * @param {string} bStr - binary string input
- * @returns {Uint8Array} Return a 8 bit unsigned integer array.
- */
- bstrToUi8(bStr) {
- const u8Array = new Uint8Array(bStr.length);
- for (let i = 0; i < bStr.length; i++) {
- u8Array[i] = bStr.charCodeAt(i);
- }
- return u8Array;
- }
- /**
- * Flush the serial input by raw read with 200 ms timeout.
- */
- async flushInput() {
- try {
- await this.transport.flushInput();
- }
- catch (e) {
- this.error(e.message);
- }
- }
- /**
- * Use the device serial port read function with given timeout to create a valid packet.
- * @param {number} op Operation number
- * @param {number} timeout timeout number in milliseconds
- * @returns {[number, Uint8Array]} valid response packet.
- */
- async readPacket(op = null, timeout = this.DEFAULT_TIMEOUT) {
- // Check up-to next 100 packets for valid response packet
- for (let i = 0; i < 100; i++) {
- const { value: p } = await this.transport.read(timeout).next();
- if (!p || p.length < 8) {
- continue;
- }
- const resp = p[0];
- if (resp !== 1) {
- continue;
- }
- const opRet = p[1];
- const val = this._byteArrayToInt(p[4], p[5], p[6], p[7]);
- const data = p.slice(8);
- if (resp == 1) {
- if (op == null || opRet == op) {
- return [val, data];
- }
- else if (data[0] != 0 && data[1] == this.ROM_INVALID_RECV_MSG) {
- await this.flushInput();
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError("unsupported command error");
- }
- }
- }
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError("invalid response");
- }
- /**
- * Write a serial command to the chip
- * @param {number} op - Operation number
- * @param {Uint8Array} data - Unsigned 8 bit array
- * @param {number} chk - channel number
- * @param {boolean} waitResponse - wait for response ?
- * @param {number} timeout - timeout number in milliseconds
- * @returns {Promise<[number, Uint8Array]>} Return a number and a 8 bit unsigned integer array.
- */
- async command(op = null, data = new Uint8Array(0), chk = 0, waitResponse = true, timeout = this.DEFAULT_TIMEOUT) {
- if (op != null) {
- if (this.transport.tracing) {
- this.transport.trace(`command op:0x${op.toString(16).padStart(2, "0")} data len=${data.length} wait_response=${waitResponse ? 1 : 0} timeout=${(timeout / 1000).toFixed(3)} data=${this.transport.hexConvert(data)}`);
- }
- const pkt = new Uint8Array(8 + data.length);
- pkt[0] = 0x00;
- pkt[1] = op;
- pkt[2] = this._shortToBytearray(data.length)[0];
- pkt[3] = this._shortToBytearray(data.length)[1];
- pkt[4] = this._intToByteArray(chk)[0];
- pkt[5] = this._intToByteArray(chk)[1];
- pkt[6] = this._intToByteArray(chk)[2];
- pkt[7] = this._intToByteArray(chk)[3];
- let i;
- for (i = 0; i < data.length; i++) {
- pkt[8 + i] = data[i];
- }
- await this.transport.write(pkt);
- }
- if (!waitResponse) {
- return [0, new Uint8Array(0)];
- }
- return this.readPacket(op, timeout);
- }
- /**
- * Read a register from chip.
- * @param {number} addr - Register address number
- * @param {number} timeout - Timeout in milliseconds (Default: 3000ms)
- * @returns {number} - Command number value
- */
- async readReg(addr, timeout = this.DEFAULT_TIMEOUT) {
- const pkt = this._intToByteArray(addr);
- const val = await this.command(this.ESP_READ_REG, pkt, undefined, undefined, timeout);
- return val[0];
- }
- /**
- * Write a number value to register address in chip.
- * @param {number} addr - Register address number
- * @param {number} value - Number value to write in register
- * @param {number} mask - Hex number for mask
- * @param {number} delayUs Delay number
- * @param {number} delayAfterUs Delay after previous delay
- */
- async writeReg(addr, value, mask = 0xffffffff, delayUs = 0, delayAfterUs = 0) {
- let pkt = this._appendArray(this._intToByteArray(addr), this._intToByteArray(value));
- pkt = this._appendArray(pkt, this._intToByteArray(mask));
- pkt = this._appendArray(pkt, this._intToByteArray(delayUs));
- if (delayAfterUs > 0) {
- pkt = this._appendArray(pkt, this._intToByteArray(this.chip.UART_DATE_REG_ADDR));
- pkt = this._appendArray(pkt, this._intToByteArray(0));
- pkt = this._appendArray(pkt, this._intToByteArray(0));
- pkt = this._appendArray(pkt, this._intToByteArray(delayAfterUs));
- }
- await this.checkCommand("write target memory", this.ESP_WRITE_REG, pkt);
- }
- /**
- * Sync chip by sending sync command.
- * @returns {[number, Uint8Array]} Command result
- */
- async sync() {
- this.debug("Sync");
- const cmd = new Uint8Array(36);
- let i;
- cmd[0] = 0x07;
- cmd[1] = 0x07;
- cmd[2] = 0x12;
- cmd[3] = 0x20;
- for (i = 0; i < 32; i++) {
- cmd[4 + i] = 0x55;
- }
- try {
- let resp = await this.command(0x08, cmd, undefined, undefined, 100);
- // ROM bootloaders send some non-zero "val" response. The flasher stub sends 0.
- // If we receive 0 then it probably indicates that the chip wasn't or couldn't be
- // reset properly and esptool is talking to the flasher stub.
- this.syncStubDetected = resp[0] === 0;
- for (let i = 0; i < 7; i++) {
- resp = await this.command();
- this.syncStubDetected = this.syncStubDetected && resp[0] === 0;
- }
- return resp;
- }
- catch (e) {
- this.debug("Sync err " + e);
- throw e;
- }
- }
- /**
- * Attempt to connect to the chip by sending a reset sequence and later a sync command.
- * @param {string} mode - Reset mode to use
- * @param {ResetStrategy} resetStrategy - Reset strategy class to use for connect
- * @returns {string} - Returns 'success' or 'error' message.
- */
- async _connectAttempt(mode = "default_reset", resetStrategy) {
- this.debug("_connect_attempt " + mode);
- if (resetStrategy) {
- await resetStrategy.reset();
- }
- const waitingBytes = this.transport.inWaiting();
- const readBytes = await this.transport.newRead(waitingBytes > 0 ? waitingBytes : 1, this.DEFAULT_TIMEOUT);
- const binaryString = Array.from(readBytes, (byte) => String.fromCharCode(byte)).join("");
- const regex = /boot:(0x[0-9a-fA-F]+)(.*waiting for download)?/;
- const match = binaryString.match(regex);
- let bootLogDetected = false, bootMode = "", downloadMode = false;
- if (match) {
- bootLogDetected = true;
- bootMode = match[1];
- downloadMode = !!match[2];
- }
- let lastError = "";
- for (let i = 0; i < 5; i++) {
- try {
- this.debug(`Sync connect attempt ${i}`);
- const resp = await this.sync();
- this.debug(resp[0].toString());
- return "success";
- }
- catch (error) {
- this.debug(`Error at sync ${error}`);
- if (error instanceof Error) {
- lastError = error.message;
- }
- else if (typeof error === "string") {
- lastError = error;
- }
- else {
- lastError = JSON.stringify(error);
- }
- }
- }
- if (bootLogDetected) {
- lastError = `Wrong boot mode detected (${bootMode}).
- This chip needs to be in download mode.`;
- if (downloadMode) {
- lastError = `Download mode successfully detected, but getting no sync reply:
- The serial TX path seems to be down.`;
- }
- }
- return lastError;
- }
- /**
- * Constructs a sequence of reset strategies based on the OS,
- * used ESP chip, external settings, and environment variables.
- * Returns a tuple of one or more reset strategies to be tried sequentially.
- * @param {string} mode - Reset mode to use
- * @returns {ResetStrategy[]} - Array of reset strategies
- */
- constructResetSequence(mode) {
- if (mode !== "no_reset") {
- if (mode === "usb_reset" || this.transport.getPid() === this.USB_JTAG_SERIAL_PID) {
- // Custom reset sequence, which is required when the device
- // is connecting via its USB-JTAG-Serial peripheral
- if (this.resetConstructors.usbJTAGSerialReset) {
- this.debug("using USB JTAG Serial Reset");
- return [this.resetConstructors.usbJTAGSerialReset(this.transport)];
- }
- }
- else {
- const DEFAULT_RESET_DELAY = 50;
- const EXTRA_DELAY = DEFAULT_RESET_DELAY + 500;
- if (this.resetConstructors.classicReset) {
- this.debug("using Classic Serial Reset");
- return [
- this.resetConstructors.classicReset(this.transport, DEFAULT_RESET_DELAY),
- this.resetConstructors.classicReset(this.transport, EXTRA_DELAY),
- ];
- }
- }
- }
- return [];
- }
- /**
- * Perform a connection to chip.
- * @param {string} mode - Reset mode to use. Example: 'default_reset' | 'no_reset'
- * @param {number} attempts - Number of connection attempts
- * @param {boolean} detecting - Detect the connected chip
- */
- async connect(mode = "default_reset", attempts = 7, detecting = true) {
- let resp;
- this.info("Connecting...", false);
- await this.transport.connect(this.romBaudrate, this.serialOptions);
- const resetSequences = this.constructResetSequence(mode);
- for (let i = 0; i < attempts; i++) {
- const resetSequence = resetSequences.length > 0 ? resetSequences[i % resetSequences.length] : null;
- resp = await this._connectAttempt(mode, resetSequence);
- if (resp === "success") {
- break;
- }
- }
- if (resp !== "success") {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError("Failed to connect with the device");
- }
- this.debug("Connect attempt successful.");
- this.info("\n\r", false);
- if (detecting) {
- const chipMagicValue = (await this.readReg(this.CHIP_DETECT_MAGIC_REG_ADDR)) >>> 0;
- this.debug("Chip Magic " + chipMagicValue.toString(16));
- const chip = await magic2Chip(chipMagicValue);
- if (this.chip === null) {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError(`Unexpected CHIP magic value ${chipMagicValue}. Failed to autodetect chip type.`);
- }
- else {
- this.chip = chip;
- }
- }
- }
- /**
- * Connect and detect the existing chip.
- * @param {string} mode Reset mode to use for connection.
- */
- async detectChip(mode = "default_reset") {
- await this.connect(mode);
- this.info("Detecting chip type... ", false);
- if (this.chip != null) {
- this.info(this.chip.CHIP_NAME);
- }
- else {
- this.info("unknown!");
- }
- }
- /**
- * Execute the command and check the command response.
- * @param {string} opDescription Command operation description.
- * @param {number} op Command operation number
- * @param {Uint8Array} data Command value
- * @param {number} chk Checksum to use
- * @param {number} timeout TImeout number in milliseconds (ms)
- * @returns {number} Command result
- */
- async checkCommand(opDescription = "", op = null, data = new Uint8Array(0), chk = 0, timeout = this.DEFAULT_TIMEOUT) {
- this.debug("check_command " + opDescription);
- const resp = await this.command(op, data, chk, undefined, timeout);
- if (resp[1].length > 4) {
- return resp[1];
- }
- else {
- return resp[0];
- }
- }
- /**
- * Start downloading an application image to RAM
- * @param {number} size Image size number
- * @param {number} blocks Number of data blocks
- * @param {number} blocksize Size of each data block
- * @param {number} offset Image offset number
- */
- async memBegin(size, blocks, blocksize, offset) {
- /* XXX: Add check to ensure that STUB is not getting overwritten */
- if (this.IS_STUB) {
- const loadStart = offset;
- const loadEnd = offset + size;
- const stub = await (0,_stubFlasher_js__WEBPACK_IMPORTED_MODULE_4__.getStubJsonByChipName)(this.chip.CHIP_NAME);
- if (stub) {
- const areasToCheck = [
- [stub.bss_start || stub.data_start, stub.data_start + stub.decodedData.length],
- [stub.text_start, stub.text_start + stub.decodedText.length],
- ];
- for (const [stubStart, stubEnd] of areasToCheck) {
- if (loadStart < stubEnd && loadEnd > stubStart) {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError(`Software loader is resident at 0x${stubStart.toString(16).padStart(8, "0")}-0x${stubEnd
- .toString(16)
- .padStart(8, "0")}.
- Can't load binary at overlapping address range 0x${loadStart.toString(16).padStart(8, "0")}-0x${loadEnd
- .toString(16)
- .padStart(8, "0")}.
- Either change binary loading address, or use the no-stub option to disable the software loader.`);
- }
- }
- }
- }
- this.debug("mem_begin " + size + " " + blocks + " " + blocksize + " " + offset.toString(16));
- let pkt = this._appendArray(this._intToByteArray(size), this._intToByteArray(blocks));
- pkt = this._appendArray(pkt, this._intToByteArray(blocksize));
- pkt = this._appendArray(pkt, this._intToByteArray(offset));
- await this.checkCommand("enter RAM download mode", this.ESP_MEM_BEGIN, pkt);
- }
- /**
- * Get the checksum for given unsigned 8-bit array
- * @param {Uint8Array} data Unsigned 8-bit integer array
- * @param {number} state Initial checksum
- * @returns {number} - Array checksum
- */
- checksum(data, state = this.ESP_CHECKSUM_MAGIC) {
- for (let i = 0; i < data.length; i++) {
- state ^= data[i];
- }
- return state;
- }
- /**
- * Send a block of image to RAM
- * @param {Uint8Array} buffer Unsigned 8-bit array
- * @param {number} seq Sequence number
- */
- async memBlock(buffer, seq) {
- let pkt = this._appendArray(this._intToByteArray(buffer.length), this._intToByteArray(seq));
- pkt = this._appendArray(pkt, this._intToByteArray(0));
- pkt = this._appendArray(pkt, this._intToByteArray(0));
- pkt = this._appendArray(pkt, buffer);
- const checksum = this.checksum(buffer);
- await this.checkCommand("write to target RAM", this.ESP_MEM_DATA, pkt, checksum);
- }
- /**
- * Leave RAM download mode and run application
- * @param {number} entrypoint - Entrypoint number
- */
- async memFinish(entrypoint) {
- const isEntry = entrypoint === 0 ? 1 : 0;
- const pkt = this._appendArray(this._intToByteArray(isEntry), this._intToByteArray(entrypoint));
- await this.checkCommand("leave RAM download mode", this.ESP_MEM_END, pkt, undefined, 200); // XXX: handle non-stub with diff timeout
- }
- /**
- * Configure SPI flash pins
- * @param {number} hspiArg - Argument for SPI attachment
- */
- async flashSpiAttach(hspiArg) {
- const pkt = this._intToByteArray(hspiArg);
- await this.checkCommand("configure SPI flash pins", this.ESP_SPI_ATTACH, pkt);
- }
- /**
- * Scale timeouts which are size-specific.
- * @param {number} secondsPerMb Seconds per megabytes as number
- * @param {number} sizeBytes Size bytes number
- * @returns {number} - Scaled timeout for specified size.
- */
- timeoutPerMb(secondsPerMb, sizeBytes) {
- const result = secondsPerMb * (sizeBytes / 1000000);
- if (result < 3000) {
- return 3000;
- }
- else {
- return result;
- }
- }
- /**
- * Start downloading to Flash (performs an erase)
- * @param {number} size Size to erase
- * @param {number} offset Offset to erase
- * @returns {number} Number of blocks (of size self.FLASH_WRITE_SIZE) to write.
- */
- async flashBegin(size, offset) {
- const numBlocks = Math.floor((size + this.FLASH_WRITE_SIZE - 1) / this.FLASH_WRITE_SIZE);
- const eraseSize = this.chip.getEraseSize(offset, size);
- const d = new Date();
- const t1 = d.getTime();
- let timeout = 3000;
- if (this.IS_STUB == false) {
- timeout = this.timeoutPerMb(this.ERASE_REGION_TIMEOUT_PER_MB, size);
- }
- this.debug("flash begin " + eraseSize + " " + numBlocks + " " + this.FLASH_WRITE_SIZE + " " + offset + " " + size);
- let pkt = this._appendArray(this._intToByteArray(eraseSize), this._intToByteArray(numBlocks));
- pkt = this._appendArray(pkt, this._intToByteArray(this.FLASH_WRITE_SIZE));
- pkt = this._appendArray(pkt, this._intToByteArray(offset));
- if (this.IS_STUB == false) {
- pkt = this._appendArray(pkt, this._intToByteArray(0)); // XXX: Support encrypted
- }
- await this.checkCommand("enter Flash download mode", this.ESP_FLASH_BEGIN, pkt, undefined, timeout);
- const t2 = d.getTime();
- if (size != 0 && this.IS_STUB == false) {
- this.info("Took " + (t2 - t1) / 1000 + "." + ((t2 - t1) % 1000) + "s to erase flash block");
- }
- return numBlocks;
- }
- /**
- * Start downloading compressed data to Flash (performs an erase)
- * @param {number} size Write size
- * @param {number} compsize Compressed size
- * @param {number} offset Offset for write
- * @returns {number} Returns number of blocks (size self.FLASH_WRITE_SIZE) to write.
- */
- async flashDeflBegin(size, compsize, offset) {
- const numBlocks = Math.floor((compsize + this.FLASH_WRITE_SIZE - 1) / this.FLASH_WRITE_SIZE);
- const eraseBlocks = Math.floor((size + this.FLASH_WRITE_SIZE - 1) / this.FLASH_WRITE_SIZE);
- const d = new Date();
- const t1 = d.getTime();
- let writeSize, timeout;
- if (this.IS_STUB) {
- writeSize = size;
- timeout = this.DEFAULT_TIMEOUT;
- }
- else {
- writeSize = eraseBlocks * this.FLASH_WRITE_SIZE;
- timeout = this.timeoutPerMb(this.ERASE_REGION_TIMEOUT_PER_MB, writeSize);
- }
- this.info("Compressed " + size + " bytes to " + compsize + "...");
- let pkt = this._appendArray(this._intToByteArray(writeSize), this._intToByteArray(numBlocks));
- pkt = this._appendArray(pkt, this._intToByteArray(this.FLASH_WRITE_SIZE));
- pkt = this._appendArray(pkt, this._intToByteArray(offset));
- if ((this.chip.CHIP_NAME === "ESP32-S2" ||
- this.chip.CHIP_NAME === "ESP32-S3" ||
- this.chip.CHIP_NAME === "ESP32-C3" ||
- this.chip.CHIP_NAME === "ESP32-C2") &&
- this.IS_STUB === false) {
- pkt = this._appendArray(pkt, this._intToByteArray(0));
- }
- await this.checkCommand("enter compressed flash mode", this.ESP_FLASH_DEFL_BEGIN, pkt, undefined, timeout);
- const t2 = d.getTime();
- if (size != 0 && this.IS_STUB === false) {
- this.info("Took " + (t2 - t1) / 1000 + "." + ((t2 - t1) % 1000) + "s to erase flash block");
- }
- return numBlocks;
- }
- /**
- * Write block to flash, retry if fail
- * @param {Uint8Array} data Unsigned 8-bit array data.
- * @param {number} seq Sequence number
- * @param {number} timeout Timeout in milliseconds (ms)
- */
- async flashBlock(data, seq, timeout) {
- let pkt = this._appendArray(this._intToByteArray(data.length), this._intToByteArray(seq));
- pkt = this._appendArray(pkt, this._intToByteArray(0));
- pkt = this._appendArray(pkt, this._intToByteArray(0));
- pkt = this._appendArray(pkt, data);
- const checksum = this.checksum(data);
- await this.checkCommand("write to target Flash after seq " + seq, this.ESP_FLASH_DATA, pkt, checksum, timeout);
- }
- /**
- * Write block to flash, send compressed, retry if fail
- * @param {Uint8Array} data Unsigned int 8-bit array data to write
- * @param {number} seq Sequence number
- * @param {number} timeout Timeout in milliseconds (ms)
- */
- async flashDeflBlock(data, seq, timeout) {
- let pkt = this._appendArray(this._intToByteArray(data.length), this._intToByteArray(seq));
- pkt = this._appendArray(pkt, this._intToByteArray(0));
- pkt = this._appendArray(pkt, this._intToByteArray(0));
- pkt = this._appendArray(pkt, data);
- const checksum = this.checksum(data);
- this.debug("flash_defl_block " + data[0].toString(16) + " " + data[1].toString(16));
- await this.checkCommand("write compressed data to flash after seq " + seq, this.ESP_FLASH_DEFL_DATA, pkt, checksum, timeout);
- }
- /**
- * Leave flash mode and run/reboot
- * @param {boolean} reboot Reboot after leaving flash mode ?
- */
- async flashFinish(reboot = false) {
- const val = reboot ? 0 : 1;
- const pkt = this._intToByteArray(val);
- await this.checkCommand("leave Flash mode", this.ESP_FLASH_END, pkt);
- }
- /**
- * Leave compressed flash mode and run/reboot
- * @param {boolean} reboot Reboot after leaving flash mode ?
- */
- async flashDeflFinish(reboot = false) {
- const val = reboot ? 0 : 1;
- const pkt = this._intToByteArray(val);
- await this.checkCommand("leave compressed flash mode", this.ESP_FLASH_DEFL_END, pkt);
- }
- /**
- * Run an arbitrary SPI flash command.
- *
- * This function uses the "USR_COMMAND" functionality in the ESP
- * SPI hardware, rather than the precanned commands supported by
- * hardware. So the value of spiflashCommand is an actual command
- * byte, sent over the wire.
- *
- * After writing command byte, writes 'data' to MOSI and then
- * reads back 'readBits' of reply on MISO. Result is a number.
- * @param {number} spiflashCommand Command to execute in SPI
- * @param {Uint8Array} data Data to send
- * @param {number} readBits Number of bits to read
- * @returns {number} Register SPI_W0_REG value
- */
- async runSpiflashCommand(spiflashCommand, data, readBits) {
- // SPI_USR register flags
- const SPI_USR_COMMAND = 1 << 31;
- const SPI_USR_MISO = 1 << 28;
- const SPI_USR_MOSI = 1 << 27;
- // SPI registers, base address differs ESP32* vs 8266
- const base = this.chip.SPI_REG_BASE;
- const SPI_CMD_REG = base + 0x00;
- const SPI_USR_REG = base + this.chip.SPI_USR_OFFS;
- const SPI_USR1_REG = base + this.chip.SPI_USR1_OFFS;
- const SPI_USR2_REG = base + this.chip.SPI_USR2_OFFS;
- const SPI_W0_REG = base + this.chip.SPI_W0_OFFS;
- let setDataLengths;
- if (this.chip.SPI_MOSI_DLEN_OFFS != null) {
- setDataLengths = async (mosiBits, misoBits) => {
- const SPI_MOSI_DLEN_REG = base + this.chip.SPI_MOSI_DLEN_OFFS;
- const SPI_MISO_DLEN_REG = base + this.chip.SPI_MISO_DLEN_OFFS;
- if (mosiBits > 0) {
- await this.writeReg(SPI_MOSI_DLEN_REG, mosiBits - 1);
- }
- if (misoBits > 0) {
- await this.writeReg(SPI_MISO_DLEN_REG, misoBits - 1);
- }
- };
- }
- else {
- setDataLengths = async (mosiBits, misoBits) => {
- const SPI_DATA_LEN_REG = SPI_USR1_REG;
- const SPI_MOSI_BITLEN_S = 17;
- const SPI_MISO_BITLEN_S = 8;
- const mosiMask = mosiBits === 0 ? 0 : mosiBits - 1;
- const misoMask = misoBits === 0 ? 0 : misoBits - 1;
- const val = (misoMask << SPI_MISO_BITLEN_S) | (mosiMask << SPI_MOSI_BITLEN_S);
- await this.writeReg(SPI_DATA_LEN_REG, val);
- };
- }
- const SPI_CMD_USR = 1 << 18;
- const SPI_USR2_COMMAND_LEN_SHIFT = 28;
- if (readBits > 32) {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError("Reading more than 32 bits back from a SPI flash operation is unsupported");
- }
- if (data.length > 64) {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError("Writing more than 64 bytes of data with one SPI command is unsupported");
- }
- const dataBits = data.length * 8;
- const oldSpiUsr = await this.readReg(SPI_USR_REG);
- const oldSpiUsr2 = await this.readReg(SPI_USR2_REG);
- let flags = SPI_USR_COMMAND;
- let i;
- if (readBits > 0) {
- flags |= SPI_USR_MISO;
- }
- if (dataBits > 0) {
- flags |= SPI_USR_MOSI;
- }
- await setDataLengths(dataBits, readBits);
- await this.writeReg(SPI_USR_REG, flags);
- let val = (7 << SPI_USR2_COMMAND_LEN_SHIFT) | spiflashCommand;
- await this.writeReg(SPI_USR2_REG, val);
- if (dataBits == 0) {
- await this.writeReg(SPI_W0_REG, 0);
- }
- else {
- if (data.length % 4 != 0) {
- const padding = new Uint8Array(data.length % 4);
- data = this._appendArray(data, padding);
- }
- let nextReg = SPI_W0_REG;
- for (i = 0; i < data.length - 4; i += 4) {
- val = this._byteArrayToInt(data[i], data[i + 1], data[i + 2], data[i + 3]);
- await this.writeReg(nextReg, val);
- nextReg += 4;
- }
- }
- await this.writeReg(SPI_CMD_REG, SPI_CMD_USR);
- for (i = 0; i < 10; i++) {
- val = (await this.readReg(SPI_CMD_REG)) & SPI_CMD_USR;
- if (val == 0) {
- break;
- }
- }
- if (i === 10) {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError("SPI command did not complete in time");
- }
- const stat = await this.readReg(SPI_W0_REG);
- await this.writeReg(SPI_USR_REG, oldSpiUsr);
- await this.writeReg(SPI_USR2_REG, oldSpiUsr2);
- return stat;
- }
- /**
- * Read flash id by executing the SPIFLASH_RDID flash command.
- * @returns {Promise} Register SPI_W0_REG value
- */
- async readFlashId() {
- const SPIFLASH_RDID = 0x9f;
- const pkt = new Uint8Array(0);
- return await this.runSpiflashCommand(SPIFLASH_RDID, pkt, 24);
- }
- /**
- * Execute the erase flash command
- * @returns {Promise} Erase flash command result
- */
- async eraseFlash() {
- this.info("Erasing flash (this may take a while)...");
- let d = new Date();
- const t1 = d.getTime();
- const ret = await this.checkCommand("erase flash", this.ESP_ERASE_FLASH, undefined, undefined, this.CHIP_ERASE_TIMEOUT);
- d = new Date();
- const t2 = d.getTime();
- this.info("Chip erase completed successfully in " + (t2 - t1) / 1000 + "s");
- return ret;
- }
- /**
- * Convert a number or unsigned 8-bit array to hex string
- * @param {number | Uint8Array } buffer Data to convert to hex string.
- * @returns {string} A hex string
- */
- toHex(buffer) {
- return Array.prototype.map.call(buffer, (x) => ("00" + x.toString(16)).slice(-2)).join("");
- }
- /**
- * Calculate the MD5 Checksum command
- * @param {number} addr Address number
- * @param {number} size Package size
- * @returns {string} MD5 Checksum string
- */
- async flashMd5sum(addr, size) {
- const timeout = this.timeoutPerMb(this.MD5_TIMEOUT_PER_MB, size);
- let pkt = this._appendArray(this._intToByteArray(addr), this._intToByteArray(size));
- pkt = this._appendArray(pkt, this._intToByteArray(0));
- pkt = this._appendArray(pkt, this._intToByteArray(0));
- let res = await this.checkCommand("calculate md5sum", this.ESP_SPI_FLASH_MD5, pkt, undefined, timeout);
- if (res instanceof Uint8Array && res.length > 16) {
- res = res.slice(0, 16);
- }
- const strmd5 = this.toHex(res);
- return strmd5;
- }
- async readFlash(addr, size, onPacketReceived = null) {
- let pkt = this._appendArray(this._intToByteArray(addr), this._intToByteArray(size));
- pkt = this._appendArray(pkt, this._intToByteArray(0x1000));
- pkt = this._appendArray(pkt, this._intToByteArray(1024));
- const res = await this.checkCommand("read flash", this.ESP_READ_FLASH, pkt);
- if (res != 0) {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError("Failed to read memory: " + res);
- }
- let resp = new Uint8Array(0);
- while (resp.length < size) {
- const { value: packet } = await this.transport.read(this.FLASH_READ_TIMEOUT).next();
- if (packet instanceof Uint8Array) {
- if (packet.length > 0) {
- resp = this._appendArray(resp, packet);
- await this.transport.write(this._intToByteArray(resp.length));
- if (onPacketReceived) {
- onPacketReceived(packet, resp.length, size);
- }
- }
- }
- else {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError("Failed to read memory: " + packet);
- }
- }
- return resp;
- }
- /**
- * Upload the flasher ROM bootloader (flasher stub) to the chip.
- * @returns {ROM} The Chip ROM
- */
- async runStub() {
- if (this.syncStubDetected) {
- this.info("Stub is already running. No upload is necessary.");
- return this.chip;
- }
- this.info("Uploading stub...");
- const stubFlasher = await (0,_stubFlasher_js__WEBPACK_IMPORTED_MODULE_4__.getStubJsonByChipName)(this.chip.CHIP_NAME);
- if (stubFlasher === undefined) {
- this.debug("Error loading Stub json");
- throw new Error("Error loading Stub json");
- }
- const stub = [stubFlasher.decodedText, stubFlasher.decodedData];
- for (let i = 0; i < stub.length; i++) {
- if (stub[i]) {
- const offs = i === 0 ? stubFlasher.text_start : stubFlasher.data_start;
- const length = stub[i].length;
- const blocks = Math.floor((length + this.ESP_RAM_BLOCK - 1) / this.ESP_RAM_BLOCK);
- await this.memBegin(length, blocks, this.ESP_RAM_BLOCK, offs);
- for (let seq = 0; seq < blocks; seq++) {
- const fromOffs = seq * this.ESP_RAM_BLOCK;
- const toOffs = fromOffs + this.ESP_RAM_BLOCK;
- await this.memBlock(stub[i].slice(fromOffs, toOffs), seq);
- }
- }
- }
- this.info("Running stub...");
- await this.memFinish(stubFlasher.entry);
- const { value: packetResult } = await this.transport.read(this.DEFAULT_TIMEOUT).next();
- const packetStr = String.fromCharCode(...packetResult);
- if (packetStr !== "OHAI") {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError(`Failed to start stub. Unexpected response ${packetStr}`);
- }
- this.info("Stub running...");
- this.IS_STUB = true;
- return this.chip;
- }
- /**
- * Change the chip baudrate.
- */
- async changeBaud() {
- this.info("Changing baudrate to " + this.baudrate);
- const secondArg = this.IS_STUB ? this.romBaudrate : 0;
- const pkt = this._appendArray(this._intToByteArray(this.baudrate), this._intToByteArray(secondArg));
- await this.command(this.ESP_CHANGE_BAUDRATE, pkt);
- this.info("Changed");
- await this.transport.disconnect();
- await this._sleep(50);
- await this.transport.connect(this.baudrate, this.serialOptions);
- }
- /**
- * Execute the main function of ESPLoader.
- * @param {string} mode Reset mode to use
- * @returns {string} chip ROM
- */
- async main(mode = "default_reset") {
- await this.detectChip(mode);
- const chip = await this.chip.getChipDescription(this);
- this.info("Chip is " + chip);
- this.info("Features: " + (await this.chip.getChipFeatures(this)));
- this.info("Crystal is " + (await this.chip.getCrystalFreq(this)) + "MHz");
- this.info("MAC: " + (await this.chip.readMac(this)));
- await this.chip.readMac(this);
- if (typeof this.chip.postConnect != "undefined") {
- await this.chip.postConnect(this);
- }
- await this.runStub();
- if (this.romBaudrate !== this.baudrate) {
- await this.changeBaud();
- }
- return chip;
- }
- /**
- * Parse a given flash size string to a number
- * @param {string} flsz Flash size to request
- * @returns {number} Flash size number
- */
- parseFlashSizeArg(flsz) {
- if (typeof this.chip.FLASH_SIZES[flsz] === "undefined") {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError("Flash size " + flsz + " is not supported by this chip type. Supported sizes: " + this.chip.FLASH_SIZES);
- }
- return this.chip.FLASH_SIZES[flsz];
- }
- /**
- * Update the image flash parameters with given arguments.
- * @param {string} image binary image as string
- * @param {number} address flash address number
- * @param {string} flashSize Flash size string
- * @param {string} flashMode Flash mode string
- * @param {string} flashFreq Flash frequency string
- * @returns {string} modified image string
- */
- _updateImageFlashParams(image, address, flashSize, flashMode, flashFreq) {
- this.debug("_update_image_flash_params " + flashSize + " " + flashMode + " " + flashFreq);
- if (image.length < 8) {
- return image;
- }
- if (address != this.chip.BOOTLOADER_FLASH_OFFSET) {
- return image;
- }
- if (flashSize === "keep" && flashMode === "keep" && flashFreq === "keep") {
- this.info("Not changing the image");
- return image;
- }
- const magic = parseInt(image[0]);
- let aFlashMode = parseInt(image[2]);
- const flashSizeFreq = parseInt(image[3]);
- if (magic !== this.ESP_IMAGE_MAGIC) {
- this.info("Warning: Image file at 0x" +
- address.toString(16) +
- " doesn't look like an image file, so not changing any flash settings.");
- return image;
- }
- /* XXX: Yet to implement actual image verification */
- if (flashMode !== "keep") {
- const flashModes = { qio: 0, qout: 1, dio: 2, dout: 3 };
- aFlashMode = flashModes[flashMode];
- }
- let aFlashFreq = flashSizeFreq & 0x0f;
- if (flashFreq !== "keep") {
- const flashFreqs = { "40m": 0, "26m": 1, "20m": 2, "80m": 0xf };
- aFlashFreq = flashFreqs[flashFreq];
- }
- let aFlashSize = flashSizeFreq & 0xf0;
- if (flashSize !== "keep") {
- aFlashSize = this.parseFlashSizeArg(flashSize);
- }
- const flashParams = (aFlashMode << 8) | (aFlashFreq + aFlashSize);
- this.info("Flash params set to " + flashParams.toString(16));
- if (parseInt(image[2]) !== aFlashMode << 8) {
- image = image.substring(0, 2) + (aFlashMode << 8).toString() + image.substring(2 + 1);
- }
- if (parseInt(image[3]) !== aFlashFreq + aFlashSize) {
- image = image.substring(0, 3) + (aFlashFreq + aFlashSize).toString() + image.substring(3 + 1);
- }
- return image;
- }
- /**
- * Write set of file images into given address based on given FlashOptions object.
- * @param {FlashOptions} options FlashOptions to configure how and what to write into flash.
- */
- async writeFlash(options) {
- this.debug("EspLoader program");
- if (options.flashSize !== "keep") {
- const flashEnd = this.flashSizeBytes(options.flashSize);
- for (let i = 0; i < options.fileArray.length; i++) {
- if (options.fileArray[i].data.length + options.fileArray[i].address > flashEnd) {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError(`File ${i + 1} doesn't fit in the available flash`);
- }
- }
- }
- if (this.IS_STUB === true && options.eraseAll === true) {
- await this.eraseFlash();
- }
- let image, address;
- for (let i = 0; i < options.fileArray.length; i++) {
- this.debug("Data Length " + options.fileArray[i].data.length);
- image = options.fileArray[i].data;
- this.debug("Image Length " + image.length);
- if (image.length === 0) {
- this.debug("Warning: File is empty");
- continue;
- }
- image = this.ui8ToBstr((0,_util_js__WEBPACK_IMPORTED_MODULE_5__.padTo)(this.bstrToUi8(image), 4));
- address = options.fileArray[i].address;
- image = this._updateImageFlashParams(image, address, options.flashSize, options.flashMode, options.flashFreq);
- let calcmd5 = null;
- if (options.calculateMD5Hash) {
- calcmd5 = options.calculateMD5Hash(image);
- this.debug("Image MD5 " + calcmd5);
- }
- const uncsize = image.length;
- let blocks;
- if (options.compress) {
- const uncimage = this.bstrToUi8(image);
- image = this.ui8ToBstr((0,pako__WEBPACK_IMPORTED_MODULE_1__.deflate)(uncimage, { level: 9 }));
- blocks = await this.flashDeflBegin(uncsize, image.length, address);
- }
- else {
- blocks = await this.flashBegin(uncsize, address);
- }
- let seq = 0;
- let bytesSent = 0;
- const totalBytes = image.length;
- if (options.reportProgress)
- options.reportProgress(i, 0, totalBytes);
- let d = new Date();
- const t1 = d.getTime();
- let timeout = 5000;
- // Create a decompressor to keep track of the size of uncompressed data
- // to be written in each chunk.
- const inflate = new pako__WEBPACK_IMPORTED_MODULE_1__.Inflate({ chunkSize: 1 });
- let totalLenUncompressed = 0;
- inflate.onData = function (chunk) {
- totalLenUncompressed += chunk.byteLength;
- };
- while (image.length > 0) {
- this.debug("Write loop " + address + " " + seq + " " + blocks);
- this.info("Writing at 0x" +
- (address + totalLenUncompressed).toString(16) +
- "... (" +
- Math.floor((100 * (seq + 1)) / blocks) +
- "%)");
- const block = this.bstrToUi8(image.slice(0, this.FLASH_WRITE_SIZE));
- if (options.compress) {
- const lenUncompressedPrevious = totalLenUncompressed;
- inflate.push(block, false);
- const blockUncompressed = totalLenUncompressed - lenUncompressedPrevious;
- let blockTimeout = 3000;
- if (this.timeoutPerMb(this.ERASE_WRITE_TIMEOUT_PER_MB, blockUncompressed) > 3000) {
- blockTimeout = this.timeoutPerMb(this.ERASE_WRITE_TIMEOUT_PER_MB, blockUncompressed);
- }
- if (this.IS_STUB === false) {
- // ROM code writes block to flash before ACKing
- timeout = blockTimeout;
- }
- await this.flashDeflBlock(block, seq, timeout);
- if (this.IS_STUB) {
- // Stub ACKs when block is received, then writes to flash while receiving the block after it
- timeout = blockTimeout;
- }
- }
- else {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError("Yet to handle Non Compressed writes");
- }
- bytesSent += block.length;
- image = image.slice(this.FLASH_WRITE_SIZE, image.length);
- seq++;
- if (options.reportProgress)
- options.reportProgress(i, bytesSent, totalBytes);
- }
- if (this.IS_STUB) {
- await this.readReg(this.CHIP_DETECT_MAGIC_REG_ADDR, timeout);
- }
- d = new Date();
- const t = d.getTime() - t1;
- if (options.compress) {
- this.info("Wrote " +
- uncsize +
- " bytes (" +
- bytesSent +
- " compressed) at 0x" +
- address.toString(16) +
- " in " +
- t / 1000 +
- " seconds.");
- }
- if (calcmd5) {
- const res = await this.flashMd5sum(address, uncsize);
- if (new String(res).valueOf() != new String(calcmd5).valueOf()) {
- this.info("File md5: " + calcmd5);
- this.info("Flash md5: " + res);
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError("MD5 of file does not match data in flash!");
- }
- else {
- this.info("Hash of data verified.");
- }
- }
- }
- this.info("Leaving...");
- if (this.IS_STUB) {
- await this.flashBegin(0, 0);
- if (options.compress) {
- await this.flashDeflFinish();
- }
- else {
- await this.flashFinish();
- }
- }
- }
- /**
- * Read SPI flash manufacturer and device id.
- */
- async flashId() {
- this.debug("flash_id");
- const flashid = await this.readFlashId();
- this.info("Manufacturer: " + (flashid & 0xff).toString(16));
- const flidLowbyte = (flashid >> 16) & 0xff;
- this.info("Device: " + ((flashid >> 8) & 0xff).toString(16) + flidLowbyte.toString(16));
- this.info("Detected flash size: " + this.DETECTED_FLASH_SIZES[flidLowbyte]);
- }
- async getFlashSize() {
- this.debug("flash_id");
- const flashid = await this.readFlashId();
- const flidLowbyte = (flashid >> 16) & 0xff;
- return this.DETECTED_FLASH_SIZES_NUM[flidLowbyte];
- }
- /**
- * Soft reset the device chip. Soft reset with run user code is the closest.
- * @param {boolean} stayInBootloader Flag to indicate if to stay in bootloader
- */
- async softReset(stayInBootloader) {
- if (!this.IS_STUB) {
- if (stayInBootloader) {
- return; // ROM bootloader is already in bootloader!
- }
- // "run user code" is as close to a soft reset as we can do
- await this.flashBegin(0, 0);
- await this.flashFinish(false);
- }
- else if (this.chip.CHIP_NAME != "ESP8266") {
- throw new _types_error_js__WEBPACK_IMPORTED_MODULE_0__.ESPError("Soft resetting is currently only supported on ESP8266");
- }
- else {
- if (stayInBootloader) {
- // soft resetting from the stub loader
- // will re-load the ROM bootloader
- await this.flashBegin(0, 0);
- await this.flashFinish(true);
- }
- else {
- // running user code from stub loader requires some hacks
- // in the stub loader
- await this.command(this.ESP_RUN_USER_CODE, undefined, undefined, false);
- }
- }
- }
- /**
- * Execute this function to execute after operation reset functions.
- * @param {After} mode After operation mode. Default is 'hard_reset'.
- * @param { boolean } usingUsbOtg For 'hard_reset' to specify if using USB-OTG
- */
- async after(mode = "hard_reset", usingUsbOtg) {
- switch (mode) {
- case "hard_reset":
- if (this.resetConstructors.hardReset) {
- this.info("Hard resetting via RTS pin...");
- const hardReset = this.resetConstructors.hardReset(this.transport, usingUsbOtg);
- await hardReset.reset();
- }
- break;
- case "soft_reset":
- this.info("Soft resetting...");
- await this.softReset(false);
- break;
- case "no_reset_stub":
- this.info("Staying in flasher stub.");
- break;
- default:
- this.info("Staying in bootloader.");
- if (this.IS_STUB) {
- this.softReset(true);
- }
- break;
- }
- }
-}
-
-
-/***/ }),
-
-/***/ "./node_modules/esptool-js/lib/index.js":
-/*!**********************************************!*\
- !*** ./node_modules/esptool-js/lib/index.js ***!
- \**********************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ ClassicReset: () => (/* reexport safe */ _reset_js__WEBPACK_IMPORTED_MODULE_1__.ClassicReset),
-/* harmony export */ CustomReset: () => (/* reexport safe */ _reset_js__WEBPACK_IMPORTED_MODULE_1__.CustomReset),
-/* harmony export */ ESPLoader: () => (/* reexport safe */ _esploader_js__WEBPACK_IMPORTED_MODULE_0__.ESPLoader),
-/* harmony export */ HardReset: () => (/* reexport safe */ _reset_js__WEBPACK_IMPORTED_MODULE_1__.HardReset),
-/* harmony export */ ROM: () => (/* reexport safe */ _targets_rom_js__WEBPACK_IMPORTED_MODULE_2__.ROM),
-/* harmony export */ Transport: () => (/* reexport safe */ _webserial_js__WEBPACK_IMPORTED_MODULE_3__.Transport),
-/* harmony export */ UsbJtagSerialReset: () => (/* reexport safe */ _reset_js__WEBPACK_IMPORTED_MODULE_1__.UsbJtagSerialReset),
-/* harmony export */ decodeBase64Data: () => (/* reexport safe */ _stubFlasher_js__WEBPACK_IMPORTED_MODULE_4__.decodeBase64Data),
-/* harmony export */ getStubJsonByChipName: () => (/* reexport safe */ _stubFlasher_js__WEBPACK_IMPORTED_MODULE_4__.getStubJsonByChipName),
-/* harmony export */ validateCustomResetStringSequence: () => (/* reexport safe */ _reset_js__WEBPACK_IMPORTED_MODULE_1__.validateCustomResetStringSequence)
-/* harmony export */ });
-/* harmony import */ var _esploader_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./esploader.js */ "./node_modules/esptool-js/lib/esploader.js");
-/* harmony import */ var _reset_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./reset.js */ "./node_modules/esptool-js/lib/reset.js");
-/* harmony import */ var _targets_rom_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./targets/rom.js */ "./node_modules/esptool-js/lib/targets/rom.js");
-/* harmony import */ var _webserial_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./webserial.js */ "./node_modules/esptool-js/lib/webserial.js");
-/* harmony import */ var _stubFlasher_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./stubFlasher.js */ "./node_modules/esptool-js/lib/stubFlasher.js");
-
-
-
-
-
-
-
-/***/ }),
-
-/***/ "./node_modules/esptool-js/lib/reset.js":
-/*!**********************************************!*\
- !*** ./node_modules/esptool-js/lib/reset.js ***!
- \**********************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ ClassicReset: () => (/* binding */ ClassicReset),
-/* harmony export */ CustomReset: () => (/* binding */ CustomReset),
-/* harmony export */ HardReset: () => (/* binding */ HardReset),
-/* harmony export */ UsbJtagSerialReset: () => (/* binding */ UsbJtagSerialReset),
-/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
-/* harmony export */ validateCustomResetStringSequence: () => (/* binding */ validateCustomResetStringSequence)
-/* harmony export */ });
-/**
- * Sleep for ms milliseconds
- * @param {number} ms Milliseconds to wait
- * @returns {Promise}
- */
-function sleep(ms) {
- return new Promise((resolve) => setTimeout(resolve, ms));
-}
-/**
- * Execute a classic set of commands that will reset the chip.
- *
- * Commands (e.g. R0) are defined by a code (R) and an argument (0).
- *
- * The commands are:
- *
- * D: setDTR - 1=True / 0=False
- *
- * R: setRTS - 1=True / 0=False
- *
- * W: Wait (time delay) - positive integer number (miliseconds)
- *
- * "D0|R1|W100|D1|R0|W50|D0" represents the classic reset strategy
- * @param {Transport} transport Transport class to perform serial communication.
- * @param {number} resetDelay Delay in milliseconds for reset.
- */
-class ClassicReset {
- constructor(transport, resetDelay) {
- this.resetDelay = resetDelay;
- this.transport = transport;
- }
- async reset() {
- await this.transport.setDTR(false);
- await this.transport.setRTS(true);
- await sleep(100);
- await this.transport.setDTR(true);
- await this.transport.setRTS(false);
- await sleep(this.resetDelay);
- await this.transport.setDTR(false);
- }
-}
-/**
- * Execute a set of commands for USB JTAG serial reset.
- *
- * Commands (e.g. R0) are defined by a code (R) and an argument (0).
- *
- * The commands are:
- *
- * D: setDTR - 1=True / 0=False
- *
- * R: setRTS - 1=True / 0=False
- *
- * W: Wait (time delay) - positive integer number (miliseconds)
- * @param {Transport} transport Transport class to perform serial communication.
- */
-class UsbJtagSerialReset {
- constructor(transport) {
- this.transport = transport;
- }
- async reset() {
- await this.transport.setRTS(false);
- await this.transport.setDTR(false);
- await sleep(100);
- await this.transport.setDTR(true);
- await this.transport.setRTS(false);
- await sleep(100);
- await this.transport.setRTS(true);
- await this.transport.setDTR(false);
- await this.transport.setRTS(true);
- await sleep(100);
- await this.transport.setRTS(false);
- await this.transport.setDTR(false);
- }
-}
-/**
- * Execute a set of commands that will hard reset the chip.
- *
- * Commands (e.g. R0) are defined by a code (R) and an argument (0).
- *
- * The commands are:
- *
- * D: setDTR - 1=True / 0=False
- *
- * R: setRTS - 1=True / 0=False
- *
- * W: Wait (time delay) - positive integer number (miliseconds)
- * @param {Transport} transport Transport class to perform serial communication.
- * @param {boolean} usingUsbOtg is it using USB-OTG ?
- */
-class HardReset {
- constructor(transport, usingUsbOtg = false) {
- this.transport = transport;
- this.usingUsbOtg = usingUsbOtg;
- this.transport = transport;
- }
- async reset() {
- if (this.usingUsbOtg) {
- await sleep(200);
- await this.transport.setRTS(false);
- await sleep(200);
- }
- else {
- await sleep(100);
- await this.transport.setRTS(false);
- }
- }
-}
-/**
- * Validate a sequence string based on the following format:
- *
- * Commands (e.g. R0) are defined by a code (R) and an argument (0).
- *
- * The commands are:
- *
- * D: setDTR - 1=True / 0=False
- *
- * R: setRTS - 1=True / 0=False
- *
- * W: Wait (time delay) - positive integer number (miliseconds)
- * @param {string} seqStr Sequence string to validate
- * @returns {boolean} Is the sequence string valid ?
- */
-function validateCustomResetStringSequence(seqStr) {
- const commands = ["D", "R", "W"];
- const commandsList = seqStr.split("|");
- for (const cmd of commandsList) {
- const code = cmd[0];
- const arg = cmd.slice(1);
- if (!commands.includes(code)) {
- return false; // Invalid command code
- }
- if (code === "D" || code === "R") {
- if (arg !== "0" && arg !== "1") {
- return false; // Invalid argument for D and R commands
- }
- }
- else if (code === "W") {
- const delay = parseInt(arg);
- if (isNaN(delay) || delay <= 0) {
- return false; // Invalid argument for W command
- }
- }
- }
- return true; // All commands are valid
-}
-/**
- * Custom reset strategy defined with a string.
- *
- * The sequenceString input string consists of individual commands divided by "|".
- *
- * Commands (e.g. R0) are defined by a code (R) and an argument (0).
- *
- * The commands are:
- *
- * D: setDTR - 1=True / 0=False
- *
- * R: setRTS - 1=True / 0=False
- *
- * W: Wait (time delay) - positive integer number (miliseconds)
- *
- * "D0|R1|W100|D1|R0|W50|D0" represents the classic reset strategy
- * @param {Transport} transport Transport class to perform serial communication.
- * @param {string} sequenceString Custom string sequence for reset strategy
- */
-class CustomReset {
- constructor(transport, sequenceString) {
- this.transport = transport;
- this.sequenceString = sequenceString;
- this.transport = transport;
- }
- async reset() {
- const resetDictionary = {
- D: async (arg) => await this.transport.setDTR(arg),
- R: async (arg) => await this.transport.setRTS(arg),
- W: async (delay) => await sleep(delay),
- };
- try {
- const isValidSequence = validateCustomResetStringSequence(this.sequenceString);
- if (!isValidSequence) {
- return;
- }
- const cmds = this.sequenceString.split("|");
- for (const cmd of cmds) {
- const cmdKey = cmd[0];
- const cmdVal = cmd.slice(1);
- if (cmdKey === "W") {
- await resetDictionary["W"](Number(cmdVal));
- }
- else if (cmdKey === "D" || cmdKey === "R") {
- await resetDictionary[cmdKey](cmdVal === "1");
- }
- }
- }
- catch (error) {
- throw new Error("Invalid custom reset sequence");
- }
- }
-}
-/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ ClassicReset, CustomReset, HardReset, UsbJtagSerialReset, validateCustomResetStringSequence });
-
-
-/***/ }),
-
-/***/ "./node_modules/esptool-js/lib/stubFlasher.js":
-/*!****************************************************!*\
- !*** ./node_modules/esptool-js/lib/stubFlasher.js ***!
- \****************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ decodeBase64Data: () => (/* binding */ decodeBase64Data),
-/* harmony export */ getStubJsonByChipName: () => (/* binding */ getStubJsonByChipName)
-/* harmony export */ });
-/* harmony import */ var atob_lite__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! atob-lite */ "./node_modules/atob-lite/atob-browser.js");
-/* harmony import */ var atob_lite__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(atob_lite__WEBPACK_IMPORTED_MODULE_0__);
-
-/**
- * Import flash stub json for the given chip name.
- * @param {string} chipName Name of chip to obtain flasher stub
- * @returns {Stub} Stub information and decoded text and data
- */
-async function getStubJsonByChipName(chipName) {
- let jsonStub;
- switch (chipName) {
- case "ESP32":
- jsonStub = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_32_json").then(__webpack_require__.t.bind(__webpack_require__, /*! ./targets/stub_flasher/stub_flasher_32.json */ "./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_32.json", 19));
- break;
- case "ESP32-C2":
- jsonStub = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_32c2_json").then(__webpack_require__.t.bind(__webpack_require__, /*! ./targets/stub_flasher/stub_flasher_32c2.json */ "./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_32c2.json", 19));
- break;
- case "ESP32-C3":
- jsonStub = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_32c3_json").then(__webpack_require__.t.bind(__webpack_require__, /*! ./targets/stub_flasher/stub_flasher_32c3.json */ "./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_32c3.json", 19));
- break;
- case "ESP32-C5":
- jsonStub = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_32c5_json").then(__webpack_require__.t.bind(__webpack_require__, /*! ./targets/stub_flasher/stub_flasher_32c5.json */ "./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_32c5.json", 19));
- break;
- case "ESP32-C6":
- jsonStub = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_32c6_json").then(__webpack_require__.t.bind(__webpack_require__, /*! ./targets/stub_flasher/stub_flasher_32c6.json */ "./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_32c6.json", 19));
- break;
- case "ESP32-C61":
- jsonStub = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_32c61_json").then(__webpack_require__.t.bind(__webpack_require__, /*! ./targets/stub_flasher/stub_flasher_32c61.json */ "./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_32c61.json", 19));
- break;
- case "ESP32-H2":
- jsonStub = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_32h2_json").then(__webpack_require__.t.bind(__webpack_require__, /*! ./targets/stub_flasher/stub_flasher_32h2.json */ "./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_32h2.json", 19));
- break;
- case "ESP32-P4":
- jsonStub = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_32p4_json").then(__webpack_require__.t.bind(__webpack_require__, /*! ./targets/stub_flasher/stub_flasher_32p4.json */ "./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_32p4.json", 19));
- break;
- case "ESP32-S2":
- jsonStub = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_32s2_json").then(__webpack_require__.t.bind(__webpack_require__, /*! ./targets/stub_flasher/stub_flasher_32s2.json */ "./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_32s2.json", 19));
- break;
- case "ESP32-S3":
- jsonStub = await __webpack_require__.e(/*! import() */ "node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_32s3_json").then(__webpack_require__.t.bind(__webpack_require__, /*! ./targets/stub_flasher/stub_flasher_32s3.json */ "./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_32s3.json", 19));
- break;
- case "ESP8266":
- jsonStub = await __webpack_require__.e(/*! import() */ "vendors-node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_8266_json").then(__webpack_require__.t.bind(__webpack_require__, /*! ./targets/stub_flasher/stub_flasher_8266.json */ "./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_8266.json", 19));
- break;
- }
- if (jsonStub) {
- return {
- bss_start: jsonStub.bss_start,
- data: jsonStub.data,
- data_start: jsonStub.data_start,
- entry: jsonStub.entry,
- text: jsonStub.text,
- text_start: jsonStub.text_start,
- decodedData: decodeBase64Data(jsonStub.data),
- decodedText: decodeBase64Data(jsonStub.text),
- };
- }
- return;
-}
-/**
- * Convert a base 64 string to Uint8Array.
- * @param {string} dataStr Base64 String to decode
- * @returns {Uint8Array} Decoded Uint8Array
- */
-function decodeBase64Data(dataStr) {
- const decoded = atob_lite__WEBPACK_IMPORTED_MODULE_0___default()(dataStr);
- const chardata = decoded.split("").map(function (x) {
- return x.charCodeAt(0);
- });
- return new Uint8Array(chardata);
-}
-
-
-/***/ }),
-
-/***/ "./node_modules/esptool-js/lib/targets/rom.js":
-/*!****************************************************!*\
- !*** ./node_modules/esptool-js/lib/targets/rom.js ***!
- \****************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ ROM: () => (/* binding */ ROM)
-/* harmony export */ });
-/**
- * Represents a chip ROM with basic registers field and abstract functions.
- */
-class ROM {
- /**
- * Get the chip erase size.
- * @param {number} offset - Offset to start erase.
- * @param {number} size - Size to erase.
- * @returns {number} The erase size of the chip as number.
- */
- getEraseSize(offset, size) {
- return size;
- }
-}
-
-
-/***/ }),
-
-/***/ "./node_modules/esptool-js/lib/types/error.js":
-/*!****************************************************!*\
- !*** ./node_modules/esptool-js/lib/types/error.js ***!
- \****************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ ESPError: () => (/* binding */ ESPError),
-/* harmony export */ TimeoutError: () => (/* binding */ TimeoutError)
-/* harmony export */ });
-/**
- * Represents a Espressif chip error.
- */
-class ESPError extends Error {
-}
-/**
- * Represents a Espressif timeout chip error.
- */
-class TimeoutError extends ESPError {
-}
-
-
-
-/***/ }),
-
-/***/ "./node_modules/esptool-js/lib/util.js":
-/*!*********************************************!*\
- !*** ./node_modules/esptool-js/lib/util.js ***!
- \*********************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ padTo: () => (/* binding */ padTo)
-/* harmony export */ });
-/**
- * Pad to the next alignment boundary
- * @param {Uint8Array} data Uint8Array data to pad
- * @param {number} alignment Alignment boundary to fulfill
- * @param {number} padCharacter Character to fill with
- * @returns {Uint8Array} Padded UInt8Array image
- */
-function padTo(data, alignment, padCharacter = 0xff) {
- const padMod = data.length % alignment;
- if (padMod !== 0) {
- const padding = new Uint8Array(alignment - padMod).fill(padCharacter);
- const paddedData = new Uint8Array(data.length + padding.length);
- paddedData.set(data);
- paddedData.set(padding, data.length);
- return paddedData;
- }
- return data;
-}
-
-
-/***/ }),
-
-/***/ "./node_modules/esptool-js/lib/webserial.js":
-/*!**************************************************!*\
- !*** ./node_modules/esptool-js/lib/webserial.js ***!
- \**************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ Transport: () => (/* binding */ Transport)
-/* harmony export */ });
-/* global SerialPort, ParityType, FlowControlType */
-/**
- * Wrapper class around Webserial API to communicate with the serial device.
- * @param {typeof import("w3c-web-serial").SerialPort} device - Requested device prompted by the browser.
- *
- * ```
- * const port = await navigator.serial.requestPort();
- * ```
- */
-class Transport {
- constructor(device, tracing = false, enableSlipReader = true) {
- this.device = device;
- this.tracing = tracing;
- this.slipReaderEnabled = false;
- this.baudrate = 0;
- this.traceLog = "";
- this.lastTraceTime = Date.now();
- this.buffer = new Uint8Array(0);
- this.SLIP_END = 0xc0;
- this.SLIP_ESC = 0xdb;
- this.SLIP_ESC_END = 0xdc;
- this.SLIP_ESC_ESC = 0xdd;
- this._DTR_state = false;
- this.slipReaderEnabled = enableSlipReader;
- }
- /**
- * Request the serial device vendor ID and Product ID as string.
- * @returns {string} Return the device VendorID and ProductID from SerialPortInfo as formatted string.
- */
- getInfo() {
- const info = this.device.getInfo();
- return info.usbVendorId && info.usbProductId
- ? `WebSerial VendorID 0x${info.usbVendorId.toString(16)} ProductID 0x${info.usbProductId.toString(16)}`
- : "";
- }
- /**
- * Request the serial device product id from SerialPortInfo.
- * @returns {number | undefined} Return the product ID.
- */
- getPid() {
- return this.device.getInfo().usbProductId;
- }
- /**
- * Format received or sent data for tracing output.
- * @param {string} message Message to format as trace line.
- */
- trace(message) {
- const delta = Date.now() - this.lastTraceTime;
- const prefix = `TRACE ${delta.toFixed(3)}`;
- const traceMessage = `${prefix} ${message}`;
- console.log(traceMessage);
- this.traceLog += traceMessage + "\n";
- }
- async returnTrace() {
- try {
- await navigator.clipboard.writeText(this.traceLog);
- console.log("Text copied to clipboard!");
- }
- catch (err) {
- console.error("Failed to copy text:", err);
- }
- }
- hexify(s) {
- return Array.from(s)
- .map((byte) => byte.toString(16).padStart(2, "0"))
- .join("")
- .padEnd(16, " ");
- }
- hexConvert(uint8Array, autoSplit = true) {
- if (autoSplit && uint8Array.length > 16) {
- let result = "";
- let s = uint8Array;
- while (s.length > 0) {
- const line = s.slice(0, 16);
- const asciiLine = String.fromCharCode(...line)
- .split("")
- .map((c) => (c === " " || (c >= " " && c <= "~" && c !== " ") ? c : "."))
- .join("");
- s = s.slice(16);
- result += `\n ${this.hexify(line.slice(0, 8))} ${this.hexify(line.slice(8))} | ${asciiLine}`;
- }
- return result;
- }
- else {
- return this.hexify(uint8Array);
- }
- }
- /**
- * Format data packet using the Serial Line Internet Protocol (SLIP).
- * @param {Uint8Array} data Binary unsigned 8 bit array data to format.
- * @returns {Uint8Array} Formatted unsigned 8 bit data array.
- */
- slipWriter(data) {
- const outData = [];
- outData.push(0xc0);
- for (let i = 0; i < data.length; i++) {
- if (data[i] === 0xdb) {
- outData.push(0xdb, 0xdd);
- }
- else if (data[i] === 0xc0) {
- outData.push(0xdb, 0xdc);
- }
- else {
- outData.push(data[i]);
- }
- }
- outData.push(0xc0);
- return new Uint8Array(outData);
- }
- /**
- * Write binary data to device using the WebSerial device writable stream.
- * @param {Uint8Array} data 8 bit unsigned data array to write to device.
- */
- async write(data) {
- const outData = this.slipWriter(data);
- if (this.device.writable) {
- const writer = this.device.writable.getWriter();
- if (this.tracing) {
- console.log("Write bytes");
- this.trace(`Write ${outData.length} bytes: ${this.hexConvert(outData)}`);
- }
- await writer.write(outData);
- writer.releaseLock();
- }
- }
- /**
- * Append a buffer array after another buffer array
- * @param {Uint8Array} arr1 - First array buffer.
- * @param {Uint8Array} arr2 - magic hex number to select ROM.
- * @returns {Uint8Array} Return a 8 bit unsigned array.
- */
- appendArray(arr1, arr2) {
- const combined = new Uint8Array(arr1.length + arr2.length);
- combined.set(arr1);
- combined.set(arr2, arr1.length);
- return combined;
- }
- // Asynchronous generator to yield incoming data chunks
- async *readLoop(timeout) {
- if (!this.reader)
- return;
- try {
- while (true) {
- const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Read timeout exceeded")), timeout));
- // Await the race between the timeout and the reader read
- const result = await Promise.race([this.reader.read(), timeoutPromise]);
- // If a timeout occurs, result will be null; otherwise, it will have { value, done }
- if (result === null)
- break;
- const { value, done } = result;
- if (done || !value)
- break;
- yield value; // Yield each data chunk
- }
- }
- catch (error) {
- console.error("Error reading from serial port:", error);
- }
- finally {
- this.buffer = new Uint8Array(0);
- }
- }
- // Read a specific number of bytes
- async newRead(numBytes, timeout) {
- if (this.buffer.length >= numBytes) {
- const output = this.buffer.slice(0, numBytes);
- this.buffer = this.buffer.slice(numBytes); // Remove the returned data from buffer
- return output;
- }
- while (this.buffer.length < numBytes) {
- const readLoop = this.readLoop(timeout);
- const { value, done } = await readLoop.next();
- if (done || !value) {
- break;
- }
- // Append the newly read data to the buffer
- this.buffer = this.appendArray(this.buffer, value);
- }
- // Return as much data as possible
- const output = this.buffer.slice(0, numBytes);
- this.buffer = this.buffer.slice(numBytes);
- return output;
- }
- async flushInput() {
- var _a;
- if (this.reader && !(await this.reader.closed)) {
- await this.reader.cancel();
- this.reader.releaseLock();
- this.reader = (_a = this.device.readable) === null || _a === void 0 ? void 0 : _a.getReader();
- }
- }
- async flushOutput() {
- var _a, _b;
- this.buffer = new Uint8Array(0);
- await ((_a = this.device.writable) === null || _a === void 0 ? void 0 : _a.getWriter().close());
- (_b = this.device.writable) === null || _b === void 0 ? void 0 : _b.getWriter().releaseLock();
- }
- // `inWaiting` returns the count of bytes in the buffer
- inWaiting() {
- return this.buffer.length;
- }
- /**
- * Detect if the data read from device is a Fatal or Guru meditation error.
- * @param {Uint8Array} input Data read from device
- */
- detectPanicHandler(input) {
- const guruMeditationRegex = /G?uru Meditation Error: (?:Core \d panic'ed \(([a-zA-Z ]*)\))?/;
- const fatalExceptionRegex = /F?atal exception \(\d+\): (?:([a-zA-Z ]*)?.*epc)?/;
- const inputString = new TextDecoder("utf-8").decode(input);
- const match = inputString.match(guruMeditationRegex) || inputString.match(fatalExceptionRegex);
- if (match) {
- const cause = match[1] || match[2];
- const msg = `Guru Meditation Error detected${cause ? ` (${cause})` : ""}`;
- throw new Error(msg);
- }
- }
- /**
- * Take a data array and return the first well formed packet after
- * replacing the escape sequence. Reads at least 8 bytes.
- * @param {number} timeout Timeout read data.
- * @yields {Uint8Array} Formatted packet using SLIP escape sequences.
- */
- async *read(timeout) {
- var _a;
- if (!this.reader) {
- this.reader = (_a = this.device.readable) === null || _a === void 0 ? void 0 : _a.getReader();
- }
- let partialPacket = null;
- let isEscaping = false;
- let successfulSlip = false;
- while (true) {
- const waitingBytes = this.inWaiting();
- const readBytes = await this.newRead(waitingBytes > 0 ? waitingBytes : 1, timeout);
- if (!readBytes || readBytes.length === 0) {
- const msg = partialPacket === null
- ? successfulSlip
- ? "Serial data stream stopped: Possible serial noise or corruption."
- : "No serial data received."
- : `Packet content transfer stopped`;
- this.trace(msg);
- throw new Error(msg);
- }
- this.trace(`Read ${readBytes.length} bytes: ${this.hexConvert(readBytes)}`);
- let i = 0; // Track position in readBytes
- while (i < readBytes.length) {
- const byte = readBytes[i++];
- if (partialPacket === null) {
- if (byte === this.SLIP_END) {
- partialPacket = new Uint8Array(0); // Start of a new packet
- }
- else {
- this.trace(`Read invalid data: ${this.hexConvert(readBytes)}`);
- const remainingData = await this.newRead(this.inWaiting(), timeout);
- this.trace(`Remaining data in serial buffer: ${this.hexConvert(remainingData)}`);
- this.detectPanicHandler(new Uint8Array([...readBytes, ...(remainingData || [])]));
- throw new Error(`Invalid head of packet (0x${byte.toString(16)}): Possible serial noise or corruption.`);
- }
- }
- else if (isEscaping) {
- isEscaping = false;
- if (byte === this.SLIP_ESC_END) {
- partialPacket = this.appendArray(partialPacket, new Uint8Array([this.SLIP_END]));
- }
- else if (byte === this.SLIP_ESC_ESC) {
- partialPacket = this.appendArray(partialPacket, new Uint8Array([this.SLIP_ESC]));
- }
- else {
- this.trace(`Read invalid data: ${this.hexConvert(readBytes)}`);
- const remainingData = await this.newRead(this.inWaiting(), timeout);
- this.trace(`Remaining data in serial buffer: ${this.hexConvert(remainingData)}`);
- this.detectPanicHandler(new Uint8Array([...readBytes, ...(remainingData || [])]));
- throw new Error(`Invalid SLIP escape (0xdb, 0x${byte.toString(16)})`);
- }
- }
- else if (byte === this.SLIP_ESC) {
- isEscaping = true;
- }
- else if (byte === this.SLIP_END) {
- this.trace(`Received full packet: ${this.hexConvert(partialPacket)}`);
- this.buffer = this.appendArray(this.buffer, readBytes.slice(i));
- yield partialPacket;
- partialPacket = null;
- successfulSlip = true;
- }
- else {
- partialPacket = this.appendArray(partialPacket, new Uint8Array([byte]));
- }
- }
- }
- }
- /**
- * Read from serial device without slip formatting.
- * @yields {Uint8Array} The next number in the Fibonacci sequence.
- */
- async *rawRead() {
- if (!this.reader)
- return;
- try {
- while (true) {
- const { value, done } = await this.reader.read();
- if (done || !value)
- break;
- if (this.tracing) {
- console.log("Raw Read bytes");
- this.trace(`Read ${value.length} bytes: ${this.hexConvert(value)}`);
- }
- yield value; // Yield each data chunk
- }
- }
- catch (error) {
- console.error("Error reading from serial port:", error);
- }
- finally {
- this.buffer = new Uint8Array(0);
- }
- }
- /**
- * Send the RequestToSend (RTS) signal to given state
- * # True for EN=LOW, chip in reset and False EN=HIGH, chip out of reset
- * @param {boolean} state Boolean state to set the signal
- */
- async setRTS(state) {
- await this.device.setSignals({ requestToSend: state });
- // # Work-around for adapters on Windows using the usbser.sys driver:
- // # generate a dummy change to DTR so that the set-control-line-state
- // # request is sent with the updated RTS state and the same DTR state
- // Referenced to esptool.py
- await this.setDTR(this._DTR_state);
- }
- /**
- * Send the dataTerminalReady (DTS) signal to given state
- * # True for IO0=LOW, chip in reset and False IO0=HIGH
- * @param {boolean} state Boolean state to set the signal
- */
- async setDTR(state) {
- this._DTR_state = state;
- await this.device.setSignals({ dataTerminalReady: state });
- }
- /**
- * Connect to serial device using the Webserial open method.
- * @param {number} baud Number baud rate for serial connection. Default is 115200.
- * @param {typeof import("w3c-web-serial").SerialOptions} serialOptions Serial Options for WebUSB SerialPort class.
- */
- async connect(baud = 115200, serialOptions = {}) {
- var _a;
- await this.device.open({
- baudRate: baud,
- dataBits: serialOptions === null || serialOptions === void 0 ? void 0 : serialOptions.dataBits,
- stopBits: serialOptions === null || serialOptions === void 0 ? void 0 : serialOptions.stopBits,
- bufferSize: serialOptions === null || serialOptions === void 0 ? void 0 : serialOptions.bufferSize,
- parity: serialOptions === null || serialOptions === void 0 ? void 0 : serialOptions.parity,
- flowControl: serialOptions === null || serialOptions === void 0 ? void 0 : serialOptions.flowControl,
- });
- this.baudrate = baud;
- this.reader = (_a = this.device.readable) === null || _a === void 0 ? void 0 : _a.getReader();
- }
- async sleep(ms) {
- return new Promise((resolve) => setTimeout(resolve, ms));
- }
- /**
- * Wait for a given timeout ms for serial device unlock.
- * @param {number} timeout Timeout time in milliseconds (ms) to sleep
- */
- async waitForUnlock(timeout) {
- while ((this.device.readable && this.device.readable.locked) ||
- (this.device.writable && this.device.writable.locked)) {
- await this.sleep(timeout);
- }
- }
- /**
- * Disconnect from serial device by running SerialPort.close() after streams unlock.
- */
- async disconnect() {
- var _a, _b;
- if ((_a = this.device.readable) === null || _a === void 0 ? void 0 : _a.locked) {
- await ((_b = this.reader) === null || _b === void 0 ? void 0 : _b.cancel());
- }
- await this.waitForUnlock(400);
- await this.device.close();
- this.reader = undefined;
- }
-}
-
-
-
-/***/ }),
-
-/***/ "./node_modules/improv-wifi-serial-sdk/dist/const.js":
-/*!***********************************************************!*\
- !*** ./node_modules/improv-wifi-serial-sdk/dist/const.js ***!
- \***********************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ ERROR_MSGS: () => (/* binding */ ERROR_MSGS),
-/* harmony export */ ImprovSerialCurrentState: () => (/* binding */ ImprovSerialCurrentState),
-/* harmony export */ ImprovSerialMessageType: () => (/* binding */ ImprovSerialMessageType),
-/* harmony export */ PortNotReady: () => (/* binding */ PortNotReady),
-/* harmony export */ SERIAL_PACKET_HEADER: () => (/* binding */ SERIAL_PACKET_HEADER)
-/* harmony export */ });
-const SERIAL_PACKET_HEADER = [
- "I".charCodeAt(0),
- "M".charCodeAt(0),
- "P".charCodeAt(0),
- "R".charCodeAt(0),
- "O".charCodeAt(0),
- "V".charCodeAt(0),
- 1, // protocol version
-];
-var ImprovSerialMessageType;
-(function (ImprovSerialMessageType) {
- ImprovSerialMessageType[ImprovSerialMessageType["CURRENT_STATE"] = 1] = "CURRENT_STATE";
- ImprovSerialMessageType[ImprovSerialMessageType["ERROR_STATE"] = 2] = "ERROR_STATE";
- ImprovSerialMessageType[ImprovSerialMessageType["RPC"] = 3] = "RPC";
- ImprovSerialMessageType[ImprovSerialMessageType["RPC_RESULT"] = 4] = "RPC_RESULT";
-})(ImprovSerialMessageType || (ImprovSerialMessageType = {}));
-var ImprovSerialCurrentState;
-(function (ImprovSerialCurrentState) {
- ImprovSerialCurrentState[ImprovSerialCurrentState["READY"] = 2] = "READY";
- ImprovSerialCurrentState[ImprovSerialCurrentState["PROVISIONING"] = 3] = "PROVISIONING";
- ImprovSerialCurrentState[ImprovSerialCurrentState["PROVISIONED"] = 4] = "PROVISIONED";
-})(ImprovSerialCurrentState || (ImprovSerialCurrentState = {}));
-const ERROR_MSGS = {
- 0x00: "NO_ERROR",
- 0x01: "INVALID_RPC_PACKET",
- 0x02: "UNKNOWN_RPC_COMMAND",
- 0x03: "UNABLE_TO_CONNECT",
- 0xfe: "TIMEOUT",
- 0xff: "UNKNOWN_ERROR",
-};
-class PortNotReady extends Error {
- constructor() {
- super("Port is not ready");
- }
-}
-
-
-/***/ }),
-
-/***/ "./node_modules/improv-wifi-serial-sdk/dist/serial.js":
-/*!************************************************************!*\
- !*** ./node_modules/improv-wifi-serial-sdk/dist/serial.js ***!
- \************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ ImprovSerial: () => (/* binding */ ImprovSerial)
-/* harmony export */ });
-/* harmony import */ var _const_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./const.js */ "./node_modules/improv-wifi-serial-sdk/dist/const.js");
-/* harmony import */ var _util_sleep__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util/sleep */ "./node_modules/improv-wifi-serial-sdk/dist/util/sleep.js");
-/* harmony import */ var _util_hex_formatter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util/hex-formatter */ "./node_modules/improv-wifi-serial-sdk/dist/util/hex-formatter.js");
-
-
-
-class ImprovSerial extends EventTarget {
- constructor(port, logger) {
- super();
- this.port = port;
- this.logger = logger;
- this.error = 0 /* ImprovSerialErrorState.NO_ERROR */;
- if (port.readable === null) {
- throw new Error("Port is not readable");
- }
- if (port.writable === null) {
- throw new Error("Port is not writable");
- }
- }
- /**
- * Detect Improv Serial, fetch the state and return the next URL if provisioned.
- * @param timeout Timeout in ms to wait for the device to respond. Default to 1000ms.
- */
- async initialize(timeout = 1000) {
- this.logger.log("Initializing Improv Serial");
- this._processInput();
- // To give the input processing time to start.
- await (0,_util_sleep__WEBPACK_IMPORTED_MODULE_1__.sleep)(1000);
- if (this._reader === undefined) {
- throw new _const_js__WEBPACK_IMPORTED_MODULE_0__.PortNotReady();
- }
- try {
- await new Promise(async (resolve, reject) => {
- setTimeout(() => reject(new Error("Improv Wi-Fi Serial not detected")), timeout);
- await this.requestCurrentState();
- resolve(undefined);
- });
- await this.requestInfo();
- }
- catch (err) {
- await this.close();
- throw err;
- }
- return this.info;
- }
- async close() {
- if (!this._reader) {
- return;
- }
- await new Promise((resolve) => {
- this._reader.cancel();
- this.addEventListener("disconnect", resolve, { once: true });
- });
- }
- /**
- * This command will trigger at least one packet,
- * the Current State and if already provisioned,
- * the same response you would get if device provisioning
- * was successful (see below).
- */
- async requestCurrentState() {
- // Request current state and wait for 5s
- let rpcResult;
- try {
- await new Promise(async (resolve, reject) => {
- this.addEventListener("state-changed", resolve, { once: true });
- const cleanupAndReject = (err) => {
- this.removeEventListener("state-changed", resolve);
- reject(err);
- };
- rpcResult = this._sendRPCWithResponse(2 /* ImprovSerialRPCCommand.REQUEST_CURRENT_STATE */, []);
- rpcResult.catch(cleanupAndReject);
- });
- }
- catch (err) {
- this._rpcFeedback = undefined;
- throw new Error(`Error fetching current state: ${err}`);
- }
- // Only if we are provisioned will we get an rpc result
- if (this.state !== _const_js__WEBPACK_IMPORTED_MODULE_0__.ImprovSerialCurrentState.PROVISIONED) {
- this._rpcFeedback = undefined;
- return;
- }
- const data = await rpcResult;
- this.nextUrl = data[0];
- }
- async requestInfo(timeout) {
- const response = await this._sendRPCWithResponse(3 /* ImprovSerialRPCCommand.REQUEST_INFO */, [], timeout);
- this.info = {
- firmware: response[0],
- version: response[1],
- name: response[3],
- chipFamily: response[2],
- };
- }
- async provision(ssid, password, timeout) {
- const encoder = new TextEncoder();
- const ssidEncoded = encoder.encode(ssid);
- const pwEncoded = encoder.encode(password);
- const data = [
- ssidEncoded.length,
- ...ssidEncoded,
- pwEncoded.length,
- ...pwEncoded,
- ];
- const response = await this._sendRPCWithResponse(1 /* ImprovSerialRPCCommand.SEND_WIFI_SETTINGS */, data, timeout);
- this.nextUrl = response[0];
- }
- async scan() {
- const results = await this._sendRPCWithMultipleResponses(4 /* ImprovSerialRPCCommand.REQUEST_WIFI_NETWORKS */, []);
- const ssids = results.map(([name, rssi, secured]) => ({
- name,
- rssi: parseInt(rssi),
- secured: secured === "YES",
- }));
- ssids.sort((a, b) => a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase()));
- return ssids;
- }
- _sendRPC(command, data) {
- this.writePacketToStream(_const_js__WEBPACK_IMPORTED_MODULE_0__.ImprovSerialMessageType.RPC, [
- command,
- data.length,
- ...data,
- ]);
- }
- async _sendRPCWithResponse(command, data, timeout) {
- // Commands that receive feedback will finish when either
- // the state changes or the error code becomes not 0.
- if (this._rpcFeedback) {
- throw new Error("Only 1 RPC command that requires feedback can be active");
- }
- return await this._awaitRPCResultWithTimeout(new Promise((resolve, reject) => {
- this._rpcFeedback = { command, resolve, reject };
- this._sendRPC(command, data);
- }), timeout);
- }
- async _sendRPCWithMultipleResponses(command, data, timeout) {
- // Commands that receive multiple feedbacks will finish when either
- // the state changes or the error code becomes not 0.
- if (this._rpcFeedback) {
- throw new Error("Only 1 RPC command that requires feedback can be active");
- }
- return await this._awaitRPCResultWithTimeout(new Promise((resolve, reject) => {
- this._rpcFeedback = {
- command,
- resolve,
- reject,
- receivedData: [],
- };
- this._sendRPC(command, data);
- }), timeout);
- }
- async _awaitRPCResultWithTimeout(sendRPCPromise, timeout) {
- if (!timeout) {
- return await sendRPCPromise;
- }
- return await new Promise((resolve, reject) => {
- const timeoutRPC = setTimeout(() => this._setError(254 /* ImprovSerialErrorState.TIMEOUT */), timeout);
- sendRPCPromise.finally(() => clearTimeout(timeoutRPC));
- sendRPCPromise.then(resolve, reject);
- });
- }
- async _processInput() {
- // read the data from serial port.
- // current state, error state, rpc result
- this.logger.debug("Starting read loop");
- this._reader = this.port.readable.getReader();
- try {
- let line = [];
- // undefined = not sure if improv packet
- let isImprov;
- // length of improv bytes that we expect
- let improvLength = 0;
- while (true) {
- const { value, done } = await this._reader.read();
- if (done) {
- break;
- }
- if (!value || value.length === 0) {
- continue;
- }
- for (const byte of value) {
- if (isImprov === false) {
- // When it wasn't an improv line, discard everything unti we find new line char
- if (byte === 10) {
- isImprov = undefined;
- }
- continue;
- }
- if (isImprov === true) {
- line.push(byte);
- if (line.length === improvLength) {
- this._handleIncomingPacket(line);
- isImprov = undefined;
- line = [];
- }
- continue;
- }
- if (byte === 10) {
- line = [];
- continue;
- }
- line.push(byte);
- if (line.length !== 9) {
- continue;
- }
- // Check if it's improv
- isImprov = String.fromCharCode(...line.slice(0, 6)) === "IMPROV";
- if (!isImprov) {
- line = [];
- continue;
- }
- // Format:
- // I M P R O V
- // Once we have 9 bytes, we can check if it's an improv packet
- // and extract how much more we need to fetch.
- const packetLength = line[8];
- improvLength = 9 + packetLength + 1; // header + data length + checksum
- }
- }
- }
- catch (err) {
- this.logger.error("Error while reading serial port", err);
- }
- finally {
- this._reader.releaseLock();
- this._reader = undefined;
- }
- this.logger.debug("Finished read loop");
- this.dispatchEvent(new Event("disconnect"));
- }
- _handleIncomingPacket(line) {
- const payload = line.slice(6);
- const version = payload[0];
- const packetType = payload[1];
- const packetLength = payload[2];
- const data = payload.slice(3, 3 + packetLength);
- this.logger.debug("PROCESS", {
- version,
- packetType,
- packetLength,
- data: (0,_util_hex_formatter__WEBPACK_IMPORTED_MODULE_2__.hexFormatter)(data),
- });
- if (version !== 1) {
- this.logger.error("Received unsupported version", version);
- return;
- }
- // Verify checksum
- let packetChecksum = payload[3 + packetLength];
- let calculatedChecksum = 0;
- for (let i = 0; i < line.length - 1; i++) {
- calculatedChecksum += line[i];
- }
- calculatedChecksum = calculatedChecksum & 0xff;
- if (calculatedChecksum !== packetChecksum) {
- this.logger.error(`Received invalid checksum ${packetChecksum}. Expected ${calculatedChecksum}`);
- return;
- }
- if (packetType === _const_js__WEBPACK_IMPORTED_MODULE_0__.ImprovSerialMessageType.CURRENT_STATE) {
- this.state = data[0];
- this.dispatchEvent(new CustomEvent("state-changed", {
- detail: this.state,
- }));
- }
- else if (packetType === _const_js__WEBPACK_IMPORTED_MODULE_0__.ImprovSerialMessageType.ERROR_STATE) {
- this._setError(data[0]);
- }
- else if (packetType === _const_js__WEBPACK_IMPORTED_MODULE_0__.ImprovSerialMessageType.RPC_RESULT) {
- if (!this._rpcFeedback) {
- this.logger.error("Received result while not waiting for one");
- return;
- }
- const rpcCommand = data[0];
- if (rpcCommand !== this._rpcFeedback.command) {
- this.logger.error(`Received result for command ${rpcCommand} but expected ${this._rpcFeedback.command}`);
- return;
- }
- // Chop off rpc command and checksum
- const result = [];
- const totalLength = data[1];
- let idx = 2;
- while (idx < 2 + totalLength) {
- result.push(String.fromCodePoint(...data.slice(idx + 1, idx + data[idx] + 1)));
- idx += data[idx] + 1;
- }
- if ("receivedData" in this._rpcFeedback) {
- if (result.length > 0) {
- this._rpcFeedback.receivedData.push(result);
- }
- else {
- // Result of 0 means we're done.
- this._rpcFeedback.resolve(this._rpcFeedback.receivedData);
- this._rpcFeedback = undefined;
- }
- }
- else {
- this._rpcFeedback.resolve(result);
- this._rpcFeedback = undefined;
- }
- }
- else {
- this.logger.error("Unable to handle packet", payload);
- }
- }
- /**
- * Add header + checksum and write packet to stream
- */
- async writePacketToStream(type, data) {
- const payload = new Uint8Array([
- ..._const_js__WEBPACK_IMPORTED_MODULE_0__.SERIAL_PACKET_HEADER,
- type,
- data.length,
- ...data,
- 0,
- 0, // Will be newline
- ]);
- // Calculate checksum
- payload[payload.length - 2] =
- payload.reduce((sum, cur) => sum + cur, 0) & 0xff;
- payload[payload.length - 1] = 10; // Newline
- this.logger.debug("Writing to stream:", (0,_util_hex_formatter__WEBPACK_IMPORTED_MODULE_2__.hexFormatter)(new Array(...payload)));
- const writer = this.port.writable.getWriter();
- await writer.write(payload);
- try {
- writer.releaseLock();
- }
- catch (err) {
- console.error("Ignoring release lock error", err);
- }
- }
- // Error is either received from device or is a timeout
- _setError(error) {
- this.error = error;
- if (error > 0 && this._rpcFeedback) {
- this._rpcFeedback.reject(_const_js__WEBPACK_IMPORTED_MODULE_0__.ERROR_MSGS[error] || `UNKNOWN_ERROR (${error})`);
- this._rpcFeedback = undefined;
- }
- this.dispatchEvent(new CustomEvent("error-changed", {
- detail: this.error,
- }));
- }
-}
-
-
-/***/ }),
-
-/***/ "./node_modules/improv-wifi-serial-sdk/dist/util/hex-formatter.js":
-/*!************************************************************************!*\
- !*** ./node_modules/improv-wifi-serial-sdk/dist/util/hex-formatter.js ***!
- \************************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ hexFormatter: () => (/* binding */ hexFormatter)
-/* harmony export */ });
-/* harmony import */ var _to_hex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./to-hex */ "./node_modules/improv-wifi-serial-sdk/dist/util/to-hex.js");
-
-const hexFormatter = (bytes) => "[" + bytes.map((value) => (0,_to_hex__WEBPACK_IMPORTED_MODULE_0__.toHex)(value)).join(", ") + "]";
-
-
-/***/ }),
-
-/***/ "./node_modules/improv-wifi-serial-sdk/dist/util/sleep.js":
-/*!****************************************************************!*\
- !*** ./node_modules/improv-wifi-serial-sdk/dist/util/sleep.js ***!
- \****************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ sleep: () => (/* binding */ sleep)
-/* harmony export */ });
-const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
-
-
-/***/ }),
-
-/***/ "./node_modules/improv-wifi-serial-sdk/dist/util/to-hex.js":
-/*!*****************************************************************!*\
- !*** ./node_modules/improv-wifi-serial-sdk/dist/util/to-hex.js ***!
- \*****************************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ toHex: () => (/* binding */ toHex)
-/* harmony export */ });
-const toHex = (value, size = 2) => {
- let hex = value.toString(16).toUpperCase();
- if (hex.startsWith("-")) {
- return "-0x" + hex.substring(1).padStart(size, "0");
- }
- else {
- return "0x" + hex.padStart(size, "0");
- }
-};
-
-
-/***/ }),
-
-/***/ "./node_modules/lit-html/development/directive-helpers.js":
-/*!****************************************************************!*\
- !*** ./node_modules/lit-html/development/directive-helpers.js ***!
- \****************************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ TemplateResultType: () => (/* binding */ TemplateResultType),
-/* harmony export */ clearPart: () => (/* binding */ clearPart),
-/* harmony export */ getCommittedValue: () => (/* binding */ getCommittedValue),
-/* harmony export */ getDirectiveClass: () => (/* binding */ getDirectiveClass),
-/* harmony export */ insertPart: () => (/* binding */ insertPart),
-/* harmony export */ isCompiledTemplateResult: () => (/* binding */ isCompiledTemplateResult),
-/* harmony export */ isDirectiveResult: () => (/* binding */ isDirectiveResult),
-/* harmony export */ isPrimitive: () => (/* binding */ isPrimitive),
-/* harmony export */ isSingleExpression: () => (/* binding */ isSingleExpression),
-/* harmony export */ isTemplateResult: () => (/* binding */ isTemplateResult),
-/* harmony export */ removePart: () => (/* binding */ removePart),
-/* harmony export */ setChildPartValue: () => (/* binding */ setChildPartValue),
-/* harmony export */ setCommittedValue: () => (/* binding */ setCommittedValue)
-/* harmony export */ });
-/* harmony import */ var _lit_html_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lit-html.js */ "./node_modules/lit-html/development/lit-html.js");
-/**
- * @license
- * Copyright 2020 Google LLC
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-const { _ChildPart: ChildPart } = _lit_html_js__WEBPACK_IMPORTED_MODULE_0__._$LH;
-const ENABLE_SHADYDOM_NOPATCH = true;
-const wrap = ENABLE_SHADYDOM_NOPATCH &&
- window.ShadyDOM?.inUse &&
- window.ShadyDOM?.noPatch === true
- ? window.ShadyDOM.wrap
- : (node) => node;
-/**
- * Tests if a value is a primitive value.
- *
- * See https://tc39.github.io/ecma262/#sec-typeof-operator
- */
-const isPrimitive = (value) => value === null || (typeof value != 'object' && typeof value != 'function');
-const TemplateResultType = {
- HTML: 1,
- SVG: 2,
- MATHML: 3,
-};
-/**
- * Tests if a value is a TemplateResult or a CompiledTemplateResult.
- */
-const isTemplateResult = (value, type) => type === undefined
- ? // This property needs to remain unminified.
- value?.['_$litType$'] !== undefined
- : value?.['_$litType$'] === type;
-/**
- * Tests if a value is a CompiledTemplateResult.
- */
-const isCompiledTemplateResult = (value) => {
- return value?.['_$litType$']?.h != null;
-};
-/**
- * Tests if a value is a DirectiveResult.
- */
-const isDirectiveResult = (value) =>
-// This property needs to remain unminified.
-value?.['_$litDirective$'] !== undefined;
-/**
- * Retrieves the Directive class for a DirectiveResult
- */
-const getDirectiveClass = (value) =>
-// This property needs to remain unminified.
-value?.['_$litDirective$'];
-/**
- * Tests whether a part has only a single-expression with no strings to
- * interpolate between.
- *
- * Only AttributePart and PropertyPart can have multiple expressions.
- * Multi-expression parts have a `strings` property and single-expression
- * parts do not.
- */
-const isSingleExpression = (part) => part.strings === undefined;
-const createMarker = () => document.createComment('');
-/**
- * Inserts a ChildPart into the given container ChildPart's DOM, either at the
- * end of the container ChildPart, or before the optional `refPart`.
- *
- * This does not add the part to the containerPart's committed value. That must
- * be done by callers.
- *
- * @param containerPart Part within which to add the new ChildPart
- * @param refPart Part before which to add the new ChildPart; when omitted the
- * part added to the end of the `containerPart`
- * @param part Part to insert, or undefined to create a new part
- */
-const insertPart = (containerPart, refPart, part) => {
- const container = wrap(containerPart._$startNode).parentNode;
- const refNode = refPart === undefined ? containerPart._$endNode : refPart._$startNode;
- if (part === undefined) {
- const startNode = wrap(container).insertBefore(createMarker(), refNode);
- const endNode = wrap(container).insertBefore(createMarker(), refNode);
- part = new ChildPart(startNode, endNode, containerPart, containerPart.options);
- }
- else {
- const endNode = wrap(part._$endNode).nextSibling;
- const oldParent = part._$parent;
- const parentChanged = oldParent !== containerPart;
- if (parentChanged) {
- part._$reparentDisconnectables?.(containerPart);
- // Note that although `_$reparentDisconnectables` updates the part's
- // `_$parent` reference after unlinking from its current parent, that
- // method only exists if Disconnectables are present, so we need to
- // unconditionally set it here
- part._$parent = containerPart;
- // Since the _$isConnected getter is somewhat costly, only
- // read it once we know the subtree has directives that need
- // to be notified
- let newConnectionState;
- if (part._$notifyConnectionChanged !== undefined &&
- (newConnectionState = containerPart._$isConnected) !==
- oldParent._$isConnected) {
- part._$notifyConnectionChanged(newConnectionState);
- }
- }
- if (endNode !== refNode || parentChanged) {
- let start = part._$startNode;
- while (start !== endNode) {
- const n = wrap(start).nextSibling;
- wrap(container).insertBefore(start, refNode);
- start = n;
- }
- }
- }
- return part;
-};
-/**
- * Sets the value of a Part.
- *
- * Note that this should only be used to set/update the value of user-created
- * parts (i.e. those created using `insertPart`); it should not be used
- * by directives to set the value of the directive's container part. Directives
- * should return a value from `update`/`render` to update their part state.
- *
- * For directives that require setting their part value asynchronously, they
- * should extend `AsyncDirective` and call `this.setValue()`.
- *
- * @param part Part to set
- * @param value Value to set
- * @param index For `AttributePart`s, the index to set
- * @param directiveParent Used internally; should not be set by user
- */
-const setChildPartValue = (part, value, directiveParent = part) => {
- part._$setValue(value, directiveParent);
- return part;
-};
-// A sentinel value that can never appear as a part value except when set by
-// live(). Used to force a dirty-check to fail and cause a re-render.
-const RESET_VALUE = {};
-/**
- * Sets the committed value of a ChildPart directly without triggering the
- * commit stage of the part.
- *
- * This is useful in cases where a directive needs to update the part such
- * that the next update detects a value change or not. When value is omitted,
- * the next update will be guaranteed to be detected as a change.
- *
- * @param part
- * @param value
- */
-const setCommittedValue = (part, value = RESET_VALUE) => (part._$committedValue = value);
-/**
- * Returns the committed value of a ChildPart.
- *
- * The committed value is used for change detection and efficient updates of
- * the part. It can differ from the value set by the template or directive in
- * cases where the template value is transformed before being committed.
- *
- * - `TemplateResult`s are committed as a `TemplateInstance`
- * - Iterables are committed as `Array`
- * - All other types are committed as the template value or value returned or
- * set by a directive.
- *
- * @param part
- */
-const getCommittedValue = (part) => part._$committedValue;
-/**
- * Removes a ChildPart from the DOM, including any of its content.
- *
- * @param part The Part to remove
- */
-const removePart = (part) => {
- part._$notifyConnectionChanged?.(false, true);
- let start = part._$startNode;
- const end = wrap(part._$endNode).nextSibling;
- while (start !== end) {
- const n = wrap(start).nextSibling;
- wrap(start).remove();
- start = n;
- }
-};
-const clearPart = (part) => {
- part._$clear();
-};
-//# sourceMappingURL=directive-helpers.js.map
-
-/***/ }),
-
-/***/ "./node_modules/lit-html/development/directives/live.js":
-/*!**************************************************************!*\
- !*** ./node_modules/lit-html/development/directives/live.js ***!
- \**************************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ live: () => (/* binding */ live)
-/* harmony export */ });
-/* harmony import */ var _lit_html_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../lit-html.js */ "./node_modules/lit-html/development/lit-html.js");
-/* harmony import */ var _directive_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../directive.js */ "./node_modules/lit-html/development/directive.js");
-/* harmony import */ var _directive_helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../directive-helpers.js */ "./node_modules/lit-html/development/directive-helpers.js");
-/**
- * @license
- * Copyright 2020 Google LLC
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-
-
-class LiveDirective extends _directive_js__WEBPACK_IMPORTED_MODULE_1__.Directive {
- constructor(partInfo) {
- super(partInfo);
- if (!(partInfo.type === _directive_js__WEBPACK_IMPORTED_MODULE_1__.PartType.PROPERTY ||
- partInfo.type === _directive_js__WEBPACK_IMPORTED_MODULE_1__.PartType.ATTRIBUTE ||
- partInfo.type === _directive_js__WEBPACK_IMPORTED_MODULE_1__.PartType.BOOLEAN_ATTRIBUTE)) {
- throw new Error('The `live` directive is not allowed on child or event bindings');
- }
- if (!(0,_directive_helpers_js__WEBPACK_IMPORTED_MODULE_2__.isSingleExpression)(partInfo)) {
- throw new Error('`live` bindings can only contain a single expression');
- }
- }
- render(value) {
- return value;
- }
- update(part, [value]) {
- if (value === _lit_html_js__WEBPACK_IMPORTED_MODULE_0__.noChange || value === _lit_html_js__WEBPACK_IMPORTED_MODULE_0__.nothing) {
- return value;
- }
- const element = part.element;
- const name = part.name;
- if (part.type === _directive_js__WEBPACK_IMPORTED_MODULE_1__.PartType.PROPERTY) {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- if (value === element[name]) {
- return _lit_html_js__WEBPACK_IMPORTED_MODULE_0__.noChange;
- }
- }
- else if (part.type === _directive_js__WEBPACK_IMPORTED_MODULE_1__.PartType.BOOLEAN_ATTRIBUTE) {
- if (!!value === element.hasAttribute(name)) {
- return _lit_html_js__WEBPACK_IMPORTED_MODULE_0__.noChange;
- }
- }
- else if (part.type === _directive_js__WEBPACK_IMPORTED_MODULE_1__.PartType.ATTRIBUTE) {
- if (element.getAttribute(name) === String(value)) {
- return _lit_html_js__WEBPACK_IMPORTED_MODULE_0__.noChange;
- }
- }
- // Resets the part's value, causing its dirty-check to fail so that it
- // always sets the value.
- (0,_directive_helpers_js__WEBPACK_IMPORTED_MODULE_2__.setCommittedValue)(part);
- return value;
- }
-}
-/**
- * Checks binding values against live DOM values, instead of previously bound
- * values, when determining whether to update the value.
- *
- * This is useful for cases where the DOM value may change from outside of
- * lit-html, such as with a binding to an ` ` element's `value` property,
- * a content editable elements text, or to a custom element that changes it's
- * own properties or attributes.
- *
- * In these cases if the DOM value changes, but the value set through lit-html
- * bindings hasn't, lit-html won't know to update the DOM value and will leave
- * it alone. If this is not what you want--if you want to overwrite the DOM
- * value with the bound value no matter what--use the `live()` directive:
- *
- * ```js
- * html` `
- * ```
- *
- * `live()` performs a strict equality check against the live DOM value, and if
- * the new value is equal to the live value, does nothing. This means that
- * `live()` should not be used when the binding will cause a type conversion. If
- * you use `live()` with an attribute binding, make sure that only strings are
- * passed in, or the binding will update every render.
- */
-const live = (0,_directive_js__WEBPACK_IMPORTED_MODULE_1__.directive)(LiveDirective);
-//# sourceMappingURL=live.js.map
-
-/***/ }),
-
-/***/ "./node_modules/lit-html/development/directives/style-map.js":
-/*!*******************************************************************!*\
- !*** ./node_modules/lit-html/development/directives/style-map.js ***!
- \*******************************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ styleMap: () => (/* binding */ styleMap)
-/* harmony export */ });
-/* harmony import */ var _lit_html_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../lit-html.js */ "./node_modules/lit-html/development/lit-html.js");
-/* harmony import */ var _directive_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../directive.js */ "./node_modules/lit-html/development/directive.js");
-/**
- * @license
- * Copyright 2018 Google LLC
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-
-const important = 'important';
-// The leading space is important
-const importantFlag = ' !' + important;
-// How many characters to remove from a value, as a negative number
-const flagTrim = 0 - importantFlag.length;
-class StyleMapDirective extends _directive_js__WEBPACK_IMPORTED_MODULE_1__.Directive {
- constructor(partInfo) {
- super(partInfo);
- if (partInfo.type !== _directive_js__WEBPACK_IMPORTED_MODULE_1__.PartType.ATTRIBUTE ||
- partInfo.name !== 'style' ||
- partInfo.strings?.length > 2) {
- throw new Error('The `styleMap` directive must be used in the `style` attribute ' +
- 'and must be the only part in the attribute.');
- }
- }
- render(styleInfo) {
- return Object.keys(styleInfo).reduce((style, prop) => {
- const value = styleInfo[prop];
- if (value == null) {
- return style;
- }
- // Convert property names from camel-case to dash-case, i.e.:
- // `backgroundColor` -> `background-color`
- // Vendor-prefixed names need an extra `-` appended to front:
- // `webkitAppearance` -> `-webkit-appearance`
- // Exception is any property name containing a dash, including
- // custom properties; we assume these are already dash-cased i.e.:
- // `--my-button-color` --> `--my-button-color`
- prop = prop.includes('-')
- ? prop
- : prop
- .replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g, '-$&')
- .toLowerCase();
- return style + `${prop}:${value};`;
- }, '');
- }
- update(part, [styleInfo]) {
- const { style } = part.element;
- if (this._previousStyleProperties === undefined) {
- this._previousStyleProperties = new Set(Object.keys(styleInfo));
- return this.render(styleInfo);
- }
- // Remove old properties that no longer exist in styleInfo
- for (const name of this._previousStyleProperties) {
- // If the name isn't in styleInfo or it's null/undefined
- if (styleInfo[name] == null) {
- this._previousStyleProperties.delete(name);
- if (name.includes('-')) {
- style.removeProperty(name);
- }
- else {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- style[name] = null;
- }
- }
- }
- // Add or update properties
- for (const name in styleInfo) {
- const value = styleInfo[name];
- if (value != null) {
- this._previousStyleProperties.add(name);
- const isImportant = typeof value === 'string' && value.endsWith(importantFlag);
- if (name.includes('-') || isImportant) {
- style.setProperty(name, isImportant
- ? value.slice(0, flagTrim)
- : value, isImportant ? important : '');
- }
- else {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- style[name] = value;
- }
- }
- }
- return _lit_html_js__WEBPACK_IMPORTED_MODULE_0__.noChange;
- }
-}
-/**
- * A directive that applies CSS properties to an element.
- *
- * `styleMap` can only be used in the `style` attribute and must be the only
- * expression in the attribute. It takes the property names in the
- * {@link StyleInfo styleInfo} object and adds the properties to the inline
- * style of the element.
- *
- * Property names with dashes (`-`) are assumed to be valid CSS
- * property names and set on the element's style object using `setProperty()`.
- * Names without dashes are assumed to be camelCased JavaScript property names
- * and set on the element's style object using property assignment, allowing the
- * style object to translate JavaScript-style names to CSS property names.
- *
- * For example `styleMap({backgroundColor: 'red', 'border-top': '5px', '--size':
- * '0'})` sets the `background-color`, `border-top` and `--size` properties.
- *
- * @param styleInfo
- * @see {@link https://lit.dev/docs/templates/directives/#stylemap styleMap code samples on Lit.dev}
- */
-const styleMap = (0,_directive_js__WEBPACK_IMPORTED_MODULE_1__.directive)(StyleMapDirective);
-//# sourceMappingURL=style-map.js.map
-
-/***/ }),
-
-/***/ "./node_modules/lit-html/development/static.js":
-/*!*****************************************************!*\
- !*** ./node_modules/lit-html/development/static.js ***!
- \*****************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ html: () => (/* binding */ html),
-/* harmony export */ literal: () => (/* binding */ literal),
-/* harmony export */ mathml: () => (/* binding */ mathml),
-/* harmony export */ svg: () => (/* binding */ svg),
-/* harmony export */ unsafeStatic: () => (/* binding */ unsafeStatic),
-/* harmony export */ withStatic: () => (/* binding */ withStatic)
-/* harmony export */ });
-/* harmony import */ var _lit_html_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./lit-html.js */ "./node_modules/lit-html/development/lit-html.js");
-/**
- * @license
- * Copyright 2020 Google LLC
- * SPDX-License-Identifier: BSD-3-Clause
- */
-// Any new exports need to be added to the export statement in
-// `packages/lit/src/index.all.ts`.
-
-/**
- * Prevents JSON injection attacks.
- *
- * The goals of this brand:
- * 1) fast to check
- * 2) code is small on the wire
- * 3) multiple versions of Lit in a single page will all produce mutually
- * interoperable StaticValues
- * 4) normal JSON.parse (without an unusual reviver) can not produce a
- * StaticValue
- *
- * Symbols satisfy (1), (2), and (4). We use Symbol.for to satisfy (3), but
- * we don't care about the key, so we break ties via (2) and use the empty
- * string.
- */
-const brand = Symbol.for('');
-/** Safely extracts the string part of a StaticValue. */
-const unwrapStaticValue = (value) => {
- if (value?.r !== brand) {
- return undefined;
- }
- return value?.['_$litStatic$'];
-};
-/**
- * Wraps a string so that it behaves like part of the static template
- * strings instead of a dynamic value.
- *
- * Users must take care to ensure that adding the static string to the template
- * results in well-formed HTML, or else templates may break unexpectedly.
- *
- * Note that this function is unsafe to use on untrusted content, as it will be
- * directly parsed into HTML. Do not pass user input to this function
- * without sanitizing it.
- *
- * Static values can be changed, but they will cause a complete re-render
- * since they effectively create a new template.
- */
-const unsafeStatic = (value) => ({
- ['_$litStatic$']: value,
- r: brand,
-});
-const textFromStatic = (value) => {
- if (value['_$litStatic$'] !== undefined) {
- return value['_$litStatic$'];
- }
- else {
- throw new Error(`Value passed to 'literal' function must be a 'literal' result: ${value}. Use 'unsafeStatic' to pass non-literal values, but
- take care to ensure page security.`);
- }
-};
-/**
- * Tags a string literal so that it behaves like part of the static template
- * strings instead of a dynamic value.
- *
- * The only values that may be used in template expressions are other tagged
- * `literal` results or `unsafeStatic` values (note that untrusted content
- * should never be passed to `unsafeStatic`).
- *
- * Users must take care to ensure that adding the static string to the template
- * results in well-formed HTML, or else templates may break unexpectedly.
- *
- * Static values can be changed, but they will cause a complete re-render since
- * they effectively create a new template.
- */
-const literal = (strings, ...values) => ({
- ['_$litStatic$']: values.reduce((acc, v, idx) => acc + textFromStatic(v) + strings[idx + 1], strings[0]),
- r: brand,
-});
-const stringsCache = new Map();
-/**
- * Wraps a lit-html template tag (`html` or `svg`) to add static value support.
- */
-const withStatic = (coreTag) => (strings, ...values) => {
- const l = values.length;
- let staticValue;
- let dynamicValue;
- const staticStrings = [];
- const dynamicValues = [];
- let i = 0;
- let hasStatics = false;
- let s;
- while (i < l) {
- s = strings[i];
- // Collect any unsafeStatic values, and their following template strings
- // so that we treat a run of template strings and unsafe static values as
- // a single template string.
- while (i < l &&
- ((dynamicValue = values[i]),
- (staticValue = unwrapStaticValue(dynamicValue))) !== undefined) {
- s += staticValue + strings[++i];
- hasStatics = true;
- }
- // If the last value is static, we don't need to push it.
- if (i !== l) {
- dynamicValues.push(dynamicValue);
- }
- staticStrings.push(s);
- i++;
- }
- // If the last value isn't static (which would have consumed the last
- // string), then we need to add the last string.
- if (i === l) {
- staticStrings.push(strings[l]);
- }
- if (hasStatics) {
- const key = staticStrings.join('$$lit$$');
- strings = stringsCache.get(key);
- if (strings === undefined) {
- // Beware: in general this pattern is unsafe, and doing so may bypass
- // lit's security checks and allow an attacker to execute arbitrary
- // code and inject arbitrary content.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- staticStrings.raw = staticStrings;
- stringsCache.set(key, (strings = staticStrings));
- }
- values = dynamicValues;
- }
- return coreTag(strings, ...values);
-};
-/**
- * Interprets a template literal as an HTML template that can efficiently
- * render to and update a container.
- *
- * Includes static value support from `lit-html/static.js`.
- */
-const html = withStatic(_lit_html_js__WEBPACK_IMPORTED_MODULE_0__.html);
-/**
- * Interprets a template literal as an SVG template that can efficiently
- * render to and update a container.
- *
- * Includes static value support from `lit-html/static.js`.
- */
-const svg = withStatic(_lit_html_js__WEBPACK_IMPORTED_MODULE_0__.svg);
-/**
- * Interprets a template literal as MathML fragment that can efficiently render
- * to and update a container.
- *
- * Includes static value support from `lit-html/static.js`.
- */
-const mathml = withStatic(_lit_html_js__WEBPACK_IMPORTED_MODULE_0__.mathml);
-//# sourceMappingURL=static.js.map
-
-/***/ }),
-
-/***/ "./node_modules/lit/directives/live.js":
-/*!*********************************************!*\
- !*** ./node_modules/lit/directives/live.js ***!
- \*********************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ live: () => (/* reexport safe */ lit_html_directives_live_js__WEBPACK_IMPORTED_MODULE_0__.live)
-/* harmony export */ });
-/* harmony import */ var lit_html_directives_live_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lit-html/directives/live.js */ "./node_modules/lit-html/development/directives/live.js");
-
-//# sourceMappingURL=live.js.map
-
-
-/***/ }),
-
-/***/ "./node_modules/lit/directives/style-map.js":
-/*!**************************************************!*\
- !*** ./node_modules/lit/directives/style-map.js ***!
- \**************************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ styleMap: () => (/* reexport safe */ lit_html_directives_style_map_js__WEBPACK_IMPORTED_MODULE_0__.styleMap)
-/* harmony export */ });
-/* harmony import */ var lit_html_directives_style_map_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lit-html/directives/style-map.js */ "./node_modules/lit-html/development/directives/style-map.js");
-
-//# sourceMappingURL=style-map.js.map
-
-
-/***/ }),
-
-/***/ "./node_modules/lit/static-html.js":
-/*!*****************************************!*\
- !*** ./node_modules/lit/static-html.js ***!
- \*****************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ html: () => (/* reexport safe */ lit_html_static_js__WEBPACK_IMPORTED_MODULE_0__.html),
-/* harmony export */ literal: () => (/* reexport safe */ lit_html_static_js__WEBPACK_IMPORTED_MODULE_0__.literal),
-/* harmony export */ mathml: () => (/* reexport safe */ lit_html_static_js__WEBPACK_IMPORTED_MODULE_0__.mathml),
-/* harmony export */ svg: () => (/* reexport safe */ lit_html_static_js__WEBPACK_IMPORTED_MODULE_0__.svg),
-/* harmony export */ unsafeStatic: () => (/* reexport safe */ lit_html_static_js__WEBPACK_IMPORTED_MODULE_0__.unsafeStatic),
-/* harmony export */ withStatic: () => (/* reexport safe */ lit_html_static_js__WEBPACK_IMPORTED_MODULE_0__.withStatic)
-/* harmony export */ });
-/* harmony import */ var lit_html_static_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lit-html/static.js */ "./node_modules/lit-html/development/static.js");
-
-//# sourceMappingURL=static-html.js.map
-
-
-/***/ }),
-
-/***/ "./node_modules/pako/dist/pako.esm.mjs":
-/*!*********************************************!*\
- !*** ./node_modules/pako/dist/pako.esm.mjs ***!
- \*********************************************/
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ Deflate: () => (/* binding */ Deflate_1),
-/* harmony export */ Inflate: () => (/* binding */ Inflate_1),
-/* harmony export */ constants: () => (/* binding */ constants_1),
-/* harmony export */ "default": () => (/* binding */ pako),
-/* harmony export */ deflate: () => (/* binding */ deflate_1),
-/* harmony export */ deflateRaw: () => (/* binding */ deflateRaw_1),
-/* harmony export */ gzip: () => (/* binding */ gzip_1),
-/* harmony export */ inflate: () => (/* binding */ inflate_1),
-/* harmony export */ inflateRaw: () => (/* binding */ inflateRaw_1),
-/* harmony export */ ungzip: () => (/* binding */ ungzip_1)
-/* harmony export */ });
-
-/*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) */
-// (C) 1995-2013 Jean-loup Gailly and Mark Adler
-// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
-
-/* eslint-disable space-unary-ops */
-
-/* Public constants ==========================================================*/
-/* ===========================================================================*/
-
-
-//const Z_FILTERED = 1;
-//const Z_HUFFMAN_ONLY = 2;
-//const Z_RLE = 3;
-const Z_FIXED$1 = 4;
-//const Z_DEFAULT_STRATEGY = 0;
-
-/* Possible values of the data_type field (though see inflate()) */
-const Z_BINARY = 0;
-const Z_TEXT = 1;
-//const Z_ASCII = 1; // = Z_TEXT
-const Z_UNKNOWN$1 = 2;
-
-/*============================================================================*/
-
-
-function zero$1(buf) { let len = buf.length; while (--len >= 0) { buf[len] = 0; } }
-
-// From zutil.h
-
-const STORED_BLOCK = 0;
-const STATIC_TREES = 1;
-const DYN_TREES = 2;
-/* The three kinds of block type */
-
-const MIN_MATCH$1 = 3;
-const MAX_MATCH$1 = 258;
-/* The minimum and maximum match lengths */
-
-// From deflate.h
-/* ===========================================================================
- * Internal compression state.
- */
-
-const LENGTH_CODES$1 = 29;
-/* number of length codes, not counting the special END_BLOCK code */
-
-const LITERALS$1 = 256;
-/* number of literal bytes 0..255 */
-
-const L_CODES$1 = LITERALS$1 + 1 + LENGTH_CODES$1;
-/* number of Literal or Length codes, including the END_BLOCK code */
-
-const D_CODES$1 = 30;
-/* number of distance codes */
-
-const BL_CODES$1 = 19;
-/* number of codes used to transfer the bit lengths */
-
-const HEAP_SIZE$1 = 2 * L_CODES$1 + 1;
-/* maximum heap size */
-
-const MAX_BITS$1 = 15;
-/* All codes must not exceed MAX_BITS bits */
-
-const Buf_size = 16;
-/* size of bit buffer in bi_buf */
-
-
-/* ===========================================================================
- * Constants
- */
-
-const MAX_BL_BITS = 7;
-/* Bit length codes must not exceed MAX_BL_BITS bits */
-
-const END_BLOCK = 256;
-/* end of block literal code */
-
-const REP_3_6 = 16;
-/* repeat previous bit length 3-6 times (2 bits of repeat count) */
-
-const REPZ_3_10 = 17;
-/* repeat a zero length 3-10 times (3 bits of repeat count) */
-
-const REPZ_11_138 = 18;
-/* repeat a zero length 11-138 times (7 bits of repeat count) */
-
-/* eslint-disable comma-spacing,array-bracket-spacing */
-const extra_lbits = /* extra bits for each length code */
- new Uint8Array([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]);
-
-const extra_dbits = /* extra bits for each distance code */
- new Uint8Array([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]);
-
-const extra_blbits = /* extra bits for each bit length code */
- new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]);
-
-const bl_order =
- new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]);
-/* eslint-enable comma-spacing,array-bracket-spacing */
-
-/* The lengths of the bit length codes are sent in order of decreasing
- * probability, to avoid transmitting the lengths for unused bit length codes.
- */
-
-/* ===========================================================================
- * Local data. These are initialized only once.
- */
-
-// We pre-fill arrays with 0 to avoid uninitialized gaps
-
-const DIST_CODE_LEN = 512; /* see definition of array dist_code below */
-
-// !!!! Use flat array instead of structure, Freq = i*2, Len = i*2+1
-const static_ltree = new Array((L_CODES$1 + 2) * 2);
-zero$1(static_ltree);
-/* The static literal tree. Since the bit lengths are imposed, there is no
- * need for the L_CODES extra codes used during heap construction. However
- * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
- * below).
- */
-
-const static_dtree = new Array(D_CODES$1 * 2);
-zero$1(static_dtree);
-/* The static distance tree. (Actually a trivial tree since all codes use
- * 5 bits.)
- */
-
-const _dist_code = new Array(DIST_CODE_LEN);
-zero$1(_dist_code);
-/* Distance codes. The first 256 values correspond to the distances
- * 3 .. 258, the last 256 values correspond to the top 8 bits of
- * the 15 bit distances.
- */
-
-const _length_code = new Array(MAX_MATCH$1 - MIN_MATCH$1 + 1);
-zero$1(_length_code);
-/* length code for each normalized match length (0 == MIN_MATCH) */
-
-const base_length = new Array(LENGTH_CODES$1);
-zero$1(base_length);
-/* First normalized length for each code (0 = MIN_MATCH) */
-
-const base_dist = new Array(D_CODES$1);
-zero$1(base_dist);
-/* First normalized distance for each code (0 = distance of 1) */
-
-
-function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_length) {
-
- this.static_tree = static_tree; /* static tree or NULL */
- this.extra_bits = extra_bits; /* extra bits for each code or NULL */
- this.extra_base = extra_base; /* base index for extra_bits */
- this.elems = elems; /* max number of elements in the tree */
- this.max_length = max_length; /* max bit length for the codes */
-
- // show if `static_tree` has data or dummy - needed for monomorphic objects
- this.has_stree = static_tree && static_tree.length;
-}
-
-
-let static_l_desc;
-let static_d_desc;
-let static_bl_desc;
-
-
-function TreeDesc(dyn_tree, stat_desc) {
- this.dyn_tree = dyn_tree; /* the dynamic tree */
- this.max_code = 0; /* largest code with non zero frequency */
- this.stat_desc = stat_desc; /* the corresponding static tree */
-}
-
-
-
-const d_code = (dist) => {
-
- return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
-};
-
-
-/* ===========================================================================
- * Output a short LSB first on the stream.
- * IN assertion: there is enough room in pendingBuf.
- */
-const put_short = (s, w) => {
-// put_byte(s, (uch)((w) & 0xff));
-// put_byte(s, (uch)((ush)(w) >> 8));
- s.pending_buf[s.pending++] = (w) & 0xff;
- s.pending_buf[s.pending++] = (w >>> 8) & 0xff;
-};
-
-
-/* ===========================================================================
- * Send a value on a given number of bits.
- * IN assertion: length <= 16 and value fits in length bits.
- */
-const send_bits = (s, value, length) => {
-
- if (s.bi_valid > (Buf_size - length)) {
- s.bi_buf |= (value << s.bi_valid) & 0xffff;
- put_short(s, s.bi_buf);
- s.bi_buf = value >> (Buf_size - s.bi_valid);
- s.bi_valid += length - Buf_size;
- } else {
- s.bi_buf |= (value << s.bi_valid) & 0xffff;
- s.bi_valid += length;
- }
-};
-
-
-const send_code = (s, c, tree) => {
-
- send_bits(s, tree[c * 2]/*.Code*/, tree[c * 2 + 1]/*.Len*/);
-};
-
-
-/* ===========================================================================
- * Reverse the first len bits of a code, using straightforward code (a faster
- * method would use a table)
- * IN assertion: 1 <= len <= 15
- */
-const bi_reverse = (code, len) => {
-
- let res = 0;
- do {
- res |= code & 1;
- code >>>= 1;
- res <<= 1;
- } while (--len > 0);
- return res >>> 1;
-};
-
-
-/* ===========================================================================
- * Flush the bit buffer, keeping at most 7 bits in it.
- */
-const bi_flush = (s) => {
-
- if (s.bi_valid === 16) {
- put_short(s, s.bi_buf);
- s.bi_buf = 0;
- s.bi_valid = 0;
-
- } else if (s.bi_valid >= 8) {
- s.pending_buf[s.pending++] = s.bi_buf & 0xff;
- s.bi_buf >>= 8;
- s.bi_valid -= 8;
- }
-};
-
-
-/* ===========================================================================
- * Compute the optimal bit lengths for a tree and update the total bit length
- * for the current block.
- * IN assertion: the fields freq and dad are set, heap[heap_max] and
- * above are the tree nodes sorted by increasing frequency.
- * OUT assertions: the field len is set to the optimal bit length, the
- * array bl_count contains the frequencies for each bit length.
- * The length opt_len is updated; static_len is also updated if stree is
- * not null.
- */
-const gen_bitlen = (s, desc) => {
-// deflate_state *s;
-// tree_desc *desc; /* the tree descriptor */
-
- const tree = desc.dyn_tree;
- const max_code = desc.max_code;
- const stree = desc.stat_desc.static_tree;
- const has_stree = desc.stat_desc.has_stree;
- const extra = desc.stat_desc.extra_bits;
- const base = desc.stat_desc.extra_base;
- const max_length = desc.stat_desc.max_length;
- let h; /* heap index */
- let n, m; /* iterate over the tree elements */
- let bits; /* bit length */
- let xbits; /* extra bits */
- let f; /* frequency */
- let overflow = 0; /* number of elements with bit length too large */
-
- for (bits = 0; bits <= MAX_BITS$1; bits++) {
- s.bl_count[bits] = 0;
- }
-
- /* In a first pass, compute the optimal bit lengths (which may
- * overflow in the case of the bit length tree).
- */
- tree[s.heap[s.heap_max] * 2 + 1]/*.Len*/ = 0; /* root of the heap */
-
- for (h = s.heap_max + 1; h < HEAP_SIZE$1; h++) {
- n = s.heap[h];
- bits = tree[tree[n * 2 + 1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1;
- if (bits > max_length) {
- bits = max_length;
- overflow++;
- }
- tree[n * 2 + 1]/*.Len*/ = bits;
- /* We overwrite tree[n].Dad which is no longer needed */
-
- if (n > max_code) { continue; } /* not a leaf node */
-
- s.bl_count[bits]++;
- xbits = 0;
- if (n >= base) {
- xbits = extra[n - base];
- }
- f = tree[n * 2]/*.Freq*/;
- s.opt_len += f * (bits + xbits);
- if (has_stree) {
- s.static_len += f * (stree[n * 2 + 1]/*.Len*/ + xbits);
- }
- }
- if (overflow === 0) { return; }
-
- // Tracev((stderr,"\nbit length overflow\n"));
- /* This happens for example on obj2 and pic of the Calgary corpus */
-
- /* Find the first bit length which could increase: */
- do {
- bits = max_length - 1;
- while (s.bl_count[bits] === 0) { bits--; }
- s.bl_count[bits]--; /* move one leaf down the tree */
- s.bl_count[bits + 1] += 2; /* move one overflow item as its brother */
- s.bl_count[max_length]--;
- /* The brother of the overflow item also moves one step up,
- * but this does not affect bl_count[max_length]
- */
- overflow -= 2;
- } while (overflow > 0);
-
- /* Now recompute all bit lengths, scanning in increasing frequency.
- * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
- * lengths instead of fixing only the wrong ones. This idea is taken
- * from 'ar' written by Haruhiko Okumura.)
- */
- for (bits = max_length; bits !== 0; bits--) {
- n = s.bl_count[bits];
- while (n !== 0) {
- m = s.heap[--h];
- if (m > max_code) { continue; }
- if (tree[m * 2 + 1]/*.Len*/ !== bits) {
- // Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
- s.opt_len += (bits - tree[m * 2 + 1]/*.Len*/) * tree[m * 2]/*.Freq*/;
- tree[m * 2 + 1]/*.Len*/ = bits;
- }
- n--;
- }
- }
-};
-
-
-/* ===========================================================================
- * Generate the codes for a given tree and bit counts (which need not be
- * optimal).
- * IN assertion: the array bl_count contains the bit length statistics for
- * the given tree and the field len is set for all tree elements.
- * OUT assertion: the field code is set for all tree elements of non
- * zero code length.
- */
-const gen_codes = (tree, max_code, bl_count) => {
-// ct_data *tree; /* the tree to decorate */
-// int max_code; /* largest code with non zero frequency */
-// ushf *bl_count; /* number of codes at each bit length */
-
- const next_code = new Array(MAX_BITS$1 + 1); /* next code value for each bit length */
- let code = 0; /* running code value */
- let bits; /* bit index */
- let n; /* code index */
-
- /* The distribution counts are first used to generate the code values
- * without bit reversal.
- */
- for (bits = 1; bits <= MAX_BITS$1; bits++) {
- code = (code + bl_count[bits - 1]) << 1;
- next_code[bits] = code;
- }
- /* Check that the bit counts in bl_count are consistent. The last code
- * must be all ones.
- */
- //Assert (code + bl_count[MAX_BITS]-1 == (1< {
-
- let n; /* iterates over tree elements */
- let bits; /* bit counter */
- let length; /* length value */
- let code; /* code value */
- let dist; /* distance index */
- const bl_count = new Array(MAX_BITS$1 + 1);
- /* number of codes at each bit length for an optimal tree */
-
- // do check in _tr_init()
- //if (static_init_done) return;
-
- /* For some embedded targets, global variables are not initialized: */
-/*#ifdef NO_INIT_GLOBAL_POINTERS
- static_l_desc.static_tree = static_ltree;
- static_l_desc.extra_bits = extra_lbits;
- static_d_desc.static_tree = static_dtree;
- static_d_desc.extra_bits = extra_dbits;
- static_bl_desc.extra_bits = extra_blbits;
-#endif*/
-
- /* Initialize the mapping length (0..255) -> length code (0..28) */
- length = 0;
- for (code = 0; code < LENGTH_CODES$1 - 1; code++) {
- base_length[code] = length;
- for (n = 0; n < (1 << extra_lbits[code]); n++) {
- _length_code[length++] = code;
- }
- }
- //Assert (length == 256, "tr_static_init: length != 256");
- /* Note that the length 255 (match length 258) can be represented
- * in two different ways: code 284 + 5 bits or code 285, so we
- * overwrite length_code[255] to use the best encoding:
- */
- _length_code[length - 1] = code;
-
- /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
- dist = 0;
- for (code = 0; code < 16; code++) {
- base_dist[code] = dist;
- for (n = 0; n < (1 << extra_dbits[code]); n++) {
- _dist_code[dist++] = code;
- }
- }
- //Assert (dist == 256, "tr_static_init: dist != 256");
- dist >>= 7; /* from now on, all distances are divided by 128 */
- for (; code < D_CODES$1; code++) {
- base_dist[code] = dist << 7;
- for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
- _dist_code[256 + dist++] = code;
- }
- }
- //Assert (dist == 256, "tr_static_init: 256+dist != 512");
-
- /* Construct the codes of the static literal tree */
- for (bits = 0; bits <= MAX_BITS$1; bits++) {
- bl_count[bits] = 0;
- }
-
- n = 0;
- while (n <= 143) {
- static_ltree[n * 2 + 1]/*.Len*/ = 8;
- n++;
- bl_count[8]++;
- }
- while (n <= 255) {
- static_ltree[n * 2 + 1]/*.Len*/ = 9;
- n++;
- bl_count[9]++;
- }
- while (n <= 279) {
- static_ltree[n * 2 + 1]/*.Len*/ = 7;
- n++;
- bl_count[7]++;
- }
- while (n <= 287) {
- static_ltree[n * 2 + 1]/*.Len*/ = 8;
- n++;
- bl_count[8]++;
- }
- /* Codes 286 and 287 do not exist, but we must include them in the
- * tree construction to get a canonical Huffman tree (longest code
- * all ones)
- */
- gen_codes(static_ltree, L_CODES$1 + 1, bl_count);
-
- /* The static distance tree is trivial: */
- for (n = 0; n < D_CODES$1; n++) {
- static_dtree[n * 2 + 1]/*.Len*/ = 5;
- static_dtree[n * 2]/*.Code*/ = bi_reverse(n, 5);
- }
-
- // Now data ready and we can init static trees
- static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS$1 + 1, L_CODES$1, MAX_BITS$1);
- static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES$1, MAX_BITS$1);
- static_bl_desc = new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES$1, MAX_BL_BITS);
-
- //static_init_done = true;
-};
-
-
-/* ===========================================================================
- * Initialize a new block.
- */
-const init_block = (s) => {
-
- let n; /* iterates over tree elements */
-
- /* Initialize the trees. */
- for (n = 0; n < L_CODES$1; n++) { s.dyn_ltree[n * 2]/*.Freq*/ = 0; }
- for (n = 0; n < D_CODES$1; n++) { s.dyn_dtree[n * 2]/*.Freq*/ = 0; }
- for (n = 0; n < BL_CODES$1; n++) { s.bl_tree[n * 2]/*.Freq*/ = 0; }
-
- s.dyn_ltree[END_BLOCK * 2]/*.Freq*/ = 1;
- s.opt_len = s.static_len = 0;
- s.sym_next = s.matches = 0;
-};
-
-
-/* ===========================================================================
- * Flush the bit buffer and align the output on a byte boundary
- */
-const bi_windup = (s) =>
-{
- if (s.bi_valid > 8) {
- put_short(s, s.bi_buf);
- } else if (s.bi_valid > 0) {
- //put_byte(s, (Byte)s->bi_buf);
- s.pending_buf[s.pending++] = s.bi_buf;
- }
- s.bi_buf = 0;
- s.bi_valid = 0;
-};
-
-/* ===========================================================================
- * Compares to subtrees, using the tree depth as tie breaker when
- * the subtrees have equal frequency. This minimizes the worst case length.
- */
-const smaller = (tree, n, m, depth) => {
-
- const _n2 = n * 2;
- const _m2 = m * 2;
- return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ ||
- (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]));
-};
-
-/* ===========================================================================
- * Restore the heap property by moving down the tree starting at node k,
- * exchanging a node with the smallest of its two sons if necessary, stopping
- * when the heap property is re-established (each father smaller than its
- * two sons).
- */
-const pqdownheap = (s, tree, k) => {
-// deflate_state *s;
-// ct_data *tree; /* the tree to restore */
-// int k; /* node to move down */
-
- const v = s.heap[k];
- let j = k << 1; /* left son of k */
- while (j <= s.heap_len) {
- /* Set j to the smallest of the two sons: */
- if (j < s.heap_len &&
- smaller(tree, s.heap[j + 1], s.heap[j], s.depth)) {
- j++;
- }
- /* Exit if v is smaller than both sons */
- if (smaller(tree, v, s.heap[j], s.depth)) { break; }
-
- /* Exchange v with the smallest son */
- s.heap[k] = s.heap[j];
- k = j;
-
- /* And continue down the tree, setting j to the left son of k */
- j <<= 1;
- }
- s.heap[k] = v;
-};
-
-
-// inlined manually
-// const SMALLEST = 1;
-
-/* ===========================================================================
- * Send the block data compressed using the given Huffman trees
- */
-const compress_block = (s, ltree, dtree) => {
-// deflate_state *s;
-// const ct_data *ltree; /* literal tree */
-// const ct_data *dtree; /* distance tree */
-
- let dist; /* distance of matched string */
- let lc; /* match length or unmatched char (if dist == 0) */
- let sx = 0; /* running index in sym_buf */
- let code; /* the code to send */
- let extra; /* number of extra bits to send */
-
- if (s.sym_next !== 0) {
- do {
- dist = s.pending_buf[s.sym_buf + sx++] & 0xff;
- dist += (s.pending_buf[s.sym_buf + sx++] & 0xff) << 8;
- lc = s.pending_buf[s.sym_buf + sx++];
- if (dist === 0) {
- send_code(s, lc, ltree); /* send a literal byte */
- //Tracecv(isgraph(lc), (stderr," '%c' ", lc));
- } else {
- /* Here, lc is the match length - MIN_MATCH */
- code = _length_code[lc];
- send_code(s, code + LITERALS$1 + 1, ltree); /* send the length code */
- extra = extra_lbits[code];
- if (extra !== 0) {
- lc -= base_length[code];
- send_bits(s, lc, extra); /* send the extra length bits */
- }
- dist--; /* dist is now the match distance - 1 */
- code = d_code(dist);
- //Assert (code < D_CODES, "bad d_code");
-
- send_code(s, code, dtree); /* send the distance code */
- extra = extra_dbits[code];
- if (extra !== 0) {
- dist -= base_dist[code];
- send_bits(s, dist, extra); /* send the extra distance bits */
- }
- } /* literal or match pair ? */
-
- /* Check that the overlay between pending_buf and sym_buf is ok: */
- //Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
-
- } while (sx < s.sym_next);
- }
-
- send_code(s, END_BLOCK, ltree);
-};
-
-
-/* ===========================================================================
- * Construct one Huffman tree and assigns the code bit strings and lengths.
- * Update the total bit length for the current block.
- * IN assertion: the field freq is set for all tree elements.
- * OUT assertions: the fields len and code are set to the optimal bit length
- * and corresponding code. The length opt_len is updated; static_len is
- * also updated if stree is not null. The field max_code is set.
- */
-const build_tree = (s, desc) => {
-// deflate_state *s;
-// tree_desc *desc; /* the tree descriptor */
-
- const tree = desc.dyn_tree;
- const stree = desc.stat_desc.static_tree;
- const has_stree = desc.stat_desc.has_stree;
- const elems = desc.stat_desc.elems;
- let n, m; /* iterate over heap elements */
- let max_code = -1; /* largest code with non zero frequency */
- let node; /* new node being created */
-
- /* Construct the initial heap, with least frequent element in
- * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
- * heap[0] is not used.
- */
- s.heap_len = 0;
- s.heap_max = HEAP_SIZE$1;
-
- for (n = 0; n < elems; n++) {
- if (tree[n * 2]/*.Freq*/ !== 0) {
- s.heap[++s.heap_len] = max_code = n;
- s.depth[n] = 0;
-
- } else {
- tree[n * 2 + 1]/*.Len*/ = 0;
- }
- }
-
- /* The pkzip format requires that at least one distance code exists,
- * and that at least one bit should be sent even if there is only one
- * possible code. So to avoid special checks later on we force at least
- * two codes of non zero frequency.
- */
- while (s.heap_len < 2) {
- node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
- tree[node * 2]/*.Freq*/ = 1;
- s.depth[node] = 0;
- s.opt_len--;
-
- if (has_stree) {
- s.static_len -= stree[node * 2 + 1]/*.Len*/;
- }
- /* node is 0 or 1 so it does not have extra bits */
- }
- desc.max_code = max_code;
-
- /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
- * establish sub-heaps of increasing lengths:
- */
- for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); }
-
- /* Construct the Huffman tree by repeatedly combining the least two
- * frequent nodes.
- */
- node = elems; /* next internal node of the tree */
- do {
- //pqremove(s, tree, n); /* n = node of least frequency */
- /*** pqremove ***/
- n = s.heap[1/*SMALLEST*/];
- s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--];
- pqdownheap(s, tree, 1/*SMALLEST*/);
- /***/
-
- m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */
-
- s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */
- s.heap[--s.heap_max] = m;
-
- /* Create a new node father of n and m */
- tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/;
- s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1;
- tree[n * 2 + 1]/*.Dad*/ = tree[m * 2 + 1]/*.Dad*/ = node;
-
- /* and insert the new node in the heap */
- s.heap[1/*SMALLEST*/] = node++;
- pqdownheap(s, tree, 1/*SMALLEST*/);
-
- } while (s.heap_len >= 2);
-
- s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/];
-
- /* At this point, the fields freq and dad are set. We can now
- * generate the bit lengths.
- */
- gen_bitlen(s, desc);
-
- /* The field len is now set, we can generate the bit codes */
- gen_codes(tree, max_code, s.bl_count);
-};
-
-
-/* ===========================================================================
- * Scan a literal or distance tree to determine the frequencies of the codes
- * in the bit length tree.
- */
-const scan_tree = (s, tree, max_code) => {
-// deflate_state *s;
-// ct_data *tree; /* the tree to be scanned */
-// int max_code; /* and its largest code of non zero frequency */
-
- let n; /* iterates over all tree elements */
- let prevlen = -1; /* last emitted length */
- let curlen; /* length of current code */
-
- let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */
-
- let count = 0; /* repeat count of the current code */
- let max_count = 7; /* max repeat count */
- let min_count = 4; /* min repeat count */
-
- if (nextlen === 0) {
- max_count = 138;
- min_count = 3;
- }
- tree[(max_code + 1) * 2 + 1]/*.Len*/ = 0xffff; /* guard */
-
- for (n = 0; n <= max_code; n++) {
- curlen = nextlen;
- nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;
-
- if (++count < max_count && curlen === nextlen) {
- continue;
-
- } else if (count < min_count) {
- s.bl_tree[curlen * 2]/*.Freq*/ += count;
-
- } else if (curlen !== 0) {
-
- if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; }
- s.bl_tree[REP_3_6 * 2]/*.Freq*/++;
-
- } else if (count <= 10) {
- s.bl_tree[REPZ_3_10 * 2]/*.Freq*/++;
-
- } else {
- s.bl_tree[REPZ_11_138 * 2]/*.Freq*/++;
- }
-
- count = 0;
- prevlen = curlen;
-
- if (nextlen === 0) {
- max_count = 138;
- min_count = 3;
-
- } else if (curlen === nextlen) {
- max_count = 6;
- min_count = 3;
-
- } else {
- max_count = 7;
- min_count = 4;
- }
- }
-};
-
-
-/* ===========================================================================
- * Send a literal or distance tree in compressed form, using the codes in
- * bl_tree.
- */
-const send_tree = (s, tree, max_code) => {
-// deflate_state *s;
-// ct_data *tree; /* the tree to be scanned */
-// int max_code; /* and its largest code of non zero frequency */
-
- let n; /* iterates over all tree elements */
- let prevlen = -1; /* last emitted length */
- let curlen; /* length of current code */
-
- let nextlen = tree[0 * 2 + 1]/*.Len*/; /* length of next code */
-
- let count = 0; /* repeat count of the current code */
- let max_count = 7; /* max repeat count */
- let min_count = 4; /* min repeat count */
-
- /* tree[max_code+1].Len = -1; */ /* guard already set */
- if (nextlen === 0) {
- max_count = 138;
- min_count = 3;
- }
-
- for (n = 0; n <= max_code; n++) {
- curlen = nextlen;
- nextlen = tree[(n + 1) * 2 + 1]/*.Len*/;
-
- if (++count < max_count && curlen === nextlen) {
- continue;
-
- } else if (count < min_count) {
- do { send_code(s, curlen, s.bl_tree); } while (--count !== 0);
-
- } else if (curlen !== 0) {
- if (curlen !== prevlen) {
- send_code(s, curlen, s.bl_tree);
- count--;
- }
- //Assert(count >= 3 && count <= 6, " 3_6?");
- send_code(s, REP_3_6, s.bl_tree);
- send_bits(s, count - 3, 2);
-
- } else if (count <= 10) {
- send_code(s, REPZ_3_10, s.bl_tree);
- send_bits(s, count - 3, 3);
-
- } else {
- send_code(s, REPZ_11_138, s.bl_tree);
- send_bits(s, count - 11, 7);
- }
-
- count = 0;
- prevlen = curlen;
- if (nextlen === 0) {
- max_count = 138;
- min_count = 3;
-
- } else if (curlen === nextlen) {
- max_count = 6;
- min_count = 3;
-
- } else {
- max_count = 7;
- min_count = 4;
- }
- }
-};
-
-
-/* ===========================================================================
- * Construct the Huffman tree for the bit lengths and return the index in
- * bl_order of the last bit length code to send.
- */
-const build_bl_tree = (s) => {
-
- let max_blindex; /* index of last bit length code of non zero freq */
-
- /* Determine the bit length frequencies for literal and distance trees */
- scan_tree(s, s.dyn_ltree, s.l_desc.max_code);
- scan_tree(s, s.dyn_dtree, s.d_desc.max_code);
-
- /* Build the bit length tree: */
- build_tree(s, s.bl_desc);
- /* opt_len now includes the length of the tree representations, except
- * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
- */
-
- /* Determine the number of bit length codes to send. The pkzip format
- * requires that at least 4 bit length codes be sent. (appnote.txt says
- * 3 but the actual value used is 4.)
- */
- for (max_blindex = BL_CODES$1 - 1; max_blindex >= 3; max_blindex--) {
- if (s.bl_tree[bl_order[max_blindex] * 2 + 1]/*.Len*/ !== 0) {
- break;
- }
- }
- /* Update opt_len to include the bit length tree and counts */
- s.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
- //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
- // s->opt_len, s->static_len));
-
- return max_blindex;
-};
-
-
-/* ===========================================================================
- * Send the header for a block using dynamic Huffman trees: the counts, the
- * lengths of the bit length codes, the literal tree and the distance tree.
- * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
- */
-const send_all_trees = (s, lcodes, dcodes, blcodes) => {
-// deflate_state *s;
-// int lcodes, dcodes, blcodes; /* number of codes for each tree */
-
- let rank; /* index in bl_order */
-
- //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
- //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
- // "too many codes");
- //Tracev((stderr, "\nbl counts: "));
- send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */
- send_bits(s, dcodes - 1, 5);
- send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */
- for (rank = 0; rank < blcodes; rank++) {
- //Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
- send_bits(s, s.bl_tree[bl_order[rank] * 2 + 1]/*.Len*/, 3);
- }
- //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
-
- send_tree(s, s.dyn_ltree, lcodes - 1); /* literal tree */
- //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
-
- send_tree(s, s.dyn_dtree, dcodes - 1); /* distance tree */
- //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
-};
-
-
-/* ===========================================================================
- * Check if the data type is TEXT or BINARY, using the following algorithm:
- * - TEXT if the two conditions below are satisfied:
- * a) There are no non-portable control characters belonging to the
- * "block list" (0..6, 14..25, 28..31).
- * b) There is at least one printable character belonging to the
- * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
- * - BINARY otherwise.
- * - The following partially-portable control characters form a
- * "gray list" that is ignored in this detection algorithm:
- * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
- * IN assertion: the fields Freq of dyn_ltree are set.
- */
-const detect_data_type = (s) => {
- /* block_mask is the bit mask of block-listed bytes
- * set bits 0..6, 14..25, and 28..31
- * 0xf3ffc07f = binary 11110011111111111100000001111111
- */
- let block_mask = 0xf3ffc07f;
- let n;
-
- /* Check for non-textual ("block-listed") bytes. */
- for (n = 0; n <= 31; n++, block_mask >>>= 1) {
- if ((block_mask & 1) && (s.dyn_ltree[n * 2]/*.Freq*/ !== 0)) {
- return Z_BINARY;
- }
- }
-
- /* Check for textual ("allow-listed") bytes. */
- if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 ||
- s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) {
- return Z_TEXT;
- }
- for (n = 32; n < LITERALS$1; n++) {
- if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) {
- return Z_TEXT;
- }
- }
-
- /* There are no "block-listed" or "allow-listed" bytes:
- * this stream either is empty or has tolerated ("gray-listed") bytes only.
- */
- return Z_BINARY;
-};
-
-
-let static_init_done = false;
-
-/* ===========================================================================
- * Initialize the tree data structures for a new zlib stream.
- */
-const _tr_init$1 = (s) =>
-{
-
- if (!static_init_done) {
- tr_static_init();
- static_init_done = true;
- }
-
- s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc);
- s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc);
- s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc);
-
- s.bi_buf = 0;
- s.bi_valid = 0;
-
- /* Initialize the first block of the first file: */
- init_block(s);
-};
-
-
-/* ===========================================================================
- * Send a stored block
- */
-const _tr_stored_block$1 = (s, buf, stored_len, last) => {
-//DeflateState *s;
-//charf *buf; /* input block */
-//ulg stored_len; /* length of input block */
-//int last; /* one if this is the last block for a file */
-
- send_bits(s, (STORED_BLOCK << 1) + (last ? 1 : 0), 3); /* send block type */
- bi_windup(s); /* align on byte boundary */
- put_short(s, stored_len);
- put_short(s, ~stored_len);
- if (stored_len) {
- s.pending_buf.set(s.window.subarray(buf, buf + stored_len), s.pending);
- }
- s.pending += stored_len;
-};
-
-
-/* ===========================================================================
- * Send one empty static block to give enough lookahead for inflate.
- * This takes 10 bits, of which 7 may remain in the bit buffer.
- */
-const _tr_align$1 = (s) => {
- send_bits(s, STATIC_TREES << 1, 3);
- send_code(s, END_BLOCK, static_ltree);
- bi_flush(s);
-};
-
-
-/* ===========================================================================
- * Determine the best encoding for the current block: dynamic trees, static
- * trees or store, and write out the encoded block.
- */
-const _tr_flush_block$1 = (s, buf, stored_len, last) => {
-//DeflateState *s;
-//charf *buf; /* input block, or NULL if too old */
-//ulg stored_len; /* length of input block */
-//int last; /* one if this is the last block for a file */
-
- let opt_lenb, static_lenb; /* opt_len and static_len in bytes */
- let max_blindex = 0; /* index of last bit length code of non zero freq */
-
- /* Build the Huffman trees unless a stored block is forced */
- if (s.level > 0) {
-
- /* Check if the file is binary or text */
- if (s.strm.data_type === Z_UNKNOWN$1) {
- s.strm.data_type = detect_data_type(s);
- }
-
- /* Construct the literal and distance trees */
- build_tree(s, s.l_desc);
- // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
- // s->static_len));
-
- build_tree(s, s.d_desc);
- // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
- // s->static_len));
- /* At this point, opt_len and static_len are the total bit lengths of
- * the compressed block data, excluding the tree representations.
- */
-
- /* Build the bit length tree for the above two trees, and get the index
- * in bl_order of the last bit length code to send.
- */
- max_blindex = build_bl_tree(s);
-
- /* Determine the best encoding. Compute the block lengths in bytes. */
- opt_lenb = (s.opt_len + 3 + 7) >>> 3;
- static_lenb = (s.static_len + 3 + 7) >>> 3;
-
- // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
- // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
- // s->sym_next / 3));
-
- if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; }
-
- } else {
- // Assert(buf != (char*)0, "lost buf");
- opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
- }
-
- if ((stored_len + 4 <= opt_lenb) && (buf !== -1)) {
- /* 4: two words for the lengths */
-
- /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
- * Otherwise we can't have processed more than WSIZE input bytes since
- * the last block flush, because compression would have been
- * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
- * transform a block into a stored block.
- */
- _tr_stored_block$1(s, buf, stored_len, last);
-
- } else if (s.strategy === Z_FIXED$1 || static_lenb === opt_lenb) {
-
- send_bits(s, (STATIC_TREES << 1) + (last ? 1 : 0), 3);
- compress_block(s, static_ltree, static_dtree);
-
- } else {
- send_bits(s, (DYN_TREES << 1) + (last ? 1 : 0), 3);
- send_all_trees(s, s.l_desc.max_code + 1, s.d_desc.max_code + 1, max_blindex + 1);
- compress_block(s, s.dyn_ltree, s.dyn_dtree);
- }
- // Assert (s->compressed_len == s->bits_sent, "bad compressed size");
- /* The above check is made mod 2^32, for files larger than 512 MB
- * and uLong implemented on 32 bits.
- */
- init_block(s);
-
- if (last) {
- bi_windup(s);
- }
- // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
- // s->compressed_len-7*last));
-};
-
-/* ===========================================================================
- * Save the match info and tally the frequency counts. Return true if
- * the current block must be flushed.
- */
-const _tr_tally$1 = (s, dist, lc) => {
-// deflate_state *s;
-// unsigned dist; /* distance of matched string */
-// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
-
- s.pending_buf[s.sym_buf + s.sym_next++] = dist;
- s.pending_buf[s.sym_buf + s.sym_next++] = dist >> 8;
- s.pending_buf[s.sym_buf + s.sym_next++] = lc;
- if (dist === 0) {
- /* lc is the unmatched char */
- s.dyn_ltree[lc * 2]/*.Freq*/++;
- } else {
- s.matches++;
- /* Here, lc is the match length - MIN_MATCH */
- dist--; /* dist = match distance - 1 */
- //Assert((ush)dist < (ush)MAX_DIST(s) &&
- // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
- // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
-
- s.dyn_ltree[(_length_code[lc] + LITERALS$1 + 1) * 2]/*.Freq*/++;
- s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++;
- }
-
- return (s.sym_next === s.sym_end);
-};
-
-var _tr_init_1 = _tr_init$1;
-var _tr_stored_block_1 = _tr_stored_block$1;
-var _tr_flush_block_1 = _tr_flush_block$1;
-var _tr_tally_1 = _tr_tally$1;
-var _tr_align_1 = _tr_align$1;
-
-var trees = {
- _tr_init: _tr_init_1,
- _tr_stored_block: _tr_stored_block_1,
- _tr_flush_block: _tr_flush_block_1,
- _tr_tally: _tr_tally_1,
- _tr_align: _tr_align_1
-};
-
-// Note: adler32 takes 12% for level 0 and 2% for level 6.
-// It isn't worth it to make additional optimizations as in original.
-// Small size is preferable.
-
-// (C) 1995-2013 Jean-loup Gailly and Mark Adler
-// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
-
-const adler32 = (adler, buf, len, pos) => {
- let s1 = (adler & 0xffff) |0,
- s2 = ((adler >>> 16) & 0xffff) |0,
- n = 0;
-
- while (len !== 0) {
- // Set limit ~ twice less than 5552, to keep
- // s2 in 31-bits, because we force signed ints.
- // in other case %= will fail.
- n = len > 2000 ? 2000 : len;
- len -= n;
-
- do {
- s1 = (s1 + buf[pos++]) |0;
- s2 = (s2 + s1) |0;
- } while (--n);
-
- s1 %= 65521;
- s2 %= 65521;
- }
-
- return (s1 | (s2 << 16)) |0;
-};
-
-
-var adler32_1 = adler32;
-
-// Note: we can't get significant speed boost here.
-// So write code to minimize size - no pregenerated tables
-// and array tools dependencies.
-
-// (C) 1995-2013 Jean-loup Gailly and Mark Adler
-// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
-
-// Use ordinary array, since untyped makes no boost here
-const makeTable = () => {
- let c, table = [];
-
- for (var n = 0; n < 256; n++) {
- c = n;
- for (var k = 0; k < 8; k++) {
- c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
- }
- table[n] = c;
- }
-
- return table;
-};
-
-// Create table on load. Just 255 signed longs. Not a problem.
-const crcTable = new Uint32Array(makeTable());
-
-
-const crc32 = (crc, buf, len, pos) => {
- const t = crcTable;
- const end = pos + len;
-
- crc ^= -1;
-
- for (let i = pos; i < end; i++) {
- crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];
- }
-
- return (crc ^ (-1)); // >>> 0;
-};
-
-
-var crc32_1 = crc32;
-
-// (C) 1995-2013 Jean-loup Gailly and Mark Adler
-// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
-
-var messages = {
- 2: 'need dictionary', /* Z_NEED_DICT 2 */
- 1: 'stream end', /* Z_STREAM_END 1 */
- 0: '', /* Z_OK 0 */
- '-1': 'file error', /* Z_ERRNO (-1) */
- '-2': 'stream error', /* Z_STREAM_ERROR (-2) */
- '-3': 'data error', /* Z_DATA_ERROR (-3) */
- '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */
- '-5': 'buffer error', /* Z_BUF_ERROR (-5) */
- '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */
-};
-
-// (C) 1995-2013 Jean-loup Gailly and Mark Adler
-// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
-
-var constants$2 = {
-
- /* Allowed flush values; see deflate() and inflate() below for details */
- Z_NO_FLUSH: 0,
- Z_PARTIAL_FLUSH: 1,
- Z_SYNC_FLUSH: 2,
- Z_FULL_FLUSH: 3,
- Z_FINISH: 4,
- Z_BLOCK: 5,
- Z_TREES: 6,
-
- /* Return codes for the compression/decompression functions. Negative values
- * are errors, positive values are used for special but normal events.
- */
- Z_OK: 0,
- Z_STREAM_END: 1,
- Z_NEED_DICT: 2,
- Z_ERRNO: -1,
- Z_STREAM_ERROR: -2,
- Z_DATA_ERROR: -3,
- Z_MEM_ERROR: -4,
- Z_BUF_ERROR: -5,
- //Z_VERSION_ERROR: -6,
-
- /* compression levels */
- Z_NO_COMPRESSION: 0,
- Z_BEST_SPEED: 1,
- Z_BEST_COMPRESSION: 9,
- Z_DEFAULT_COMPRESSION: -1,
-
-
- Z_FILTERED: 1,
- Z_HUFFMAN_ONLY: 2,
- Z_RLE: 3,
- Z_FIXED: 4,
- Z_DEFAULT_STRATEGY: 0,
-
- /* Possible values of the data_type field (though see inflate()) */
- Z_BINARY: 0,
- Z_TEXT: 1,
- //Z_ASCII: 1, // = Z_TEXT (deprecated)
- Z_UNKNOWN: 2,
-
- /* The deflate compression method */
- Z_DEFLATED: 8
- //Z_NULL: null // Use -1 or null inline, depending on var type
-};
-
-// (C) 1995-2013 Jean-loup Gailly and Mark Adler
-// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
-
-const { _tr_init, _tr_stored_block, _tr_flush_block, _tr_tally, _tr_align } = trees;
-
-
-
-
-/* Public constants ==========================================================*/
-/* ===========================================================================*/
-
-const {
- Z_NO_FLUSH: Z_NO_FLUSH$2, Z_PARTIAL_FLUSH, Z_FULL_FLUSH: Z_FULL_FLUSH$1, Z_FINISH: Z_FINISH$3, Z_BLOCK: Z_BLOCK$1,
- Z_OK: Z_OK$3, Z_STREAM_END: Z_STREAM_END$3, Z_STREAM_ERROR: Z_STREAM_ERROR$2, Z_DATA_ERROR: Z_DATA_ERROR$2, Z_BUF_ERROR: Z_BUF_ERROR$1,
- Z_DEFAULT_COMPRESSION: Z_DEFAULT_COMPRESSION$1,
- Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED, Z_DEFAULT_STRATEGY: Z_DEFAULT_STRATEGY$1,
- Z_UNKNOWN,
- Z_DEFLATED: Z_DEFLATED$2
-} = constants$2;
-
-/*============================================================================*/
-
-
-const MAX_MEM_LEVEL = 9;
-/* Maximum value for memLevel in deflateInit2 */
-const MAX_WBITS$1 = 15;
-/* 32K LZ77 window */
-const DEF_MEM_LEVEL = 8;
-
-
-const LENGTH_CODES = 29;
-/* number of length codes, not counting the special END_BLOCK code */
-const LITERALS = 256;
-/* number of literal bytes 0..255 */
-const L_CODES = LITERALS + 1 + LENGTH_CODES;
-/* number of Literal or Length codes, including the END_BLOCK code */
-const D_CODES = 30;
-/* number of distance codes */
-const BL_CODES = 19;
-/* number of codes used to transfer the bit lengths */
-const HEAP_SIZE = 2 * L_CODES + 1;
-/* maximum heap size */
-const MAX_BITS = 15;
-/* All codes must not exceed MAX_BITS bits */
-
-const MIN_MATCH = 3;
-const MAX_MATCH = 258;
-const MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
-
-const PRESET_DICT = 0x20;
-
-const INIT_STATE = 42; /* zlib header -> BUSY_STATE */
-//#ifdef GZIP
-const GZIP_STATE = 57; /* gzip header -> BUSY_STATE | EXTRA_STATE */
-//#endif
-const EXTRA_STATE = 69; /* gzip extra block -> NAME_STATE */
-const NAME_STATE = 73; /* gzip file name -> COMMENT_STATE */
-const COMMENT_STATE = 91; /* gzip comment -> HCRC_STATE */
-const HCRC_STATE = 103; /* gzip header CRC -> BUSY_STATE */
-const BUSY_STATE = 113; /* deflate -> FINISH_STATE */
-const FINISH_STATE = 666; /* stream complete */
-
-const BS_NEED_MORE = 1; /* block not completed, need more input or more output */
-const BS_BLOCK_DONE = 2; /* block flush performed */
-const BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */
-const BS_FINISH_DONE = 4; /* finish done, accept no more input or output */
-
-const OS_CODE = 0x03; // Unix :) . Don't detect, use this default.
-
-const err = (strm, errorCode) => {
- strm.msg = messages[errorCode];
- return errorCode;
-};
-
-const rank = (f) => {
- return ((f) * 2) - ((f) > 4 ? 9 : 0);
-};
-
-const zero = (buf) => {
- let len = buf.length; while (--len >= 0) { buf[len] = 0; }
-};
-
-/* ===========================================================================
- * Slide the hash table when sliding the window down (could be avoided with 32
- * bit values at the expense of memory usage). We slide even when level == 0 to
- * keep the hash table consistent if we switch back to level > 0 later.
- */
-const slide_hash = (s) => {
- let n, m;
- let p;
- let wsize = s.w_size;
-
- n = s.hash_size;
- p = n;
- do {
- m = s.head[--p];
- s.head[p] = (m >= wsize ? m - wsize : 0);
- } while (--n);
- n = wsize;
-//#ifndef FASTEST
- p = n;
- do {
- m = s.prev[--p];
- s.prev[p] = (m >= wsize ? m - wsize : 0);
- /* If n is not on any hash chain, prev[n] is garbage but
- * its value will never be used.
- */
- } while (--n);
-//#endif
-};
-
-/* eslint-disable new-cap */
-let HASH_ZLIB = (s, prev, data) => ((prev << s.hash_shift) ^ data) & s.hash_mask;
-// This hash causes less collisions, https://github.com/nodeca/pako/issues/135
-// But breaks binary compatibility
-//let HASH_FAST = (s, prev, data) => ((prev << 8) + (prev >> 8) + (data << 4)) & s.hash_mask;
-let HASH = HASH_ZLIB;
-
-
-/* =========================================================================
- * Flush as much pending output as possible. All deflate() output, except for
- * some deflate_stored() output, goes through this function so some
- * applications may wish to modify it to avoid allocating a large
- * strm->next_out buffer and copying into it. (See also read_buf()).
- */
-const flush_pending = (strm) => {
- const s = strm.state;
-
- //_tr_flush_bits(s);
- let len = s.pending;
- if (len > strm.avail_out) {
- len = strm.avail_out;
- }
- if (len === 0) { return; }
-
- strm.output.set(s.pending_buf.subarray(s.pending_out, s.pending_out + len), strm.next_out);
- strm.next_out += len;
- s.pending_out += len;
- strm.total_out += len;
- strm.avail_out -= len;
- s.pending -= len;
- if (s.pending === 0) {
- s.pending_out = 0;
- }
-};
-
-
-const flush_block_only = (s, last) => {
- _tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last);
- s.block_start = s.strstart;
- flush_pending(s.strm);
-};
-
-
-const put_byte = (s, b) => {
- s.pending_buf[s.pending++] = b;
-};
-
-
-/* =========================================================================
- * Put a short in the pending buffer. The 16-bit value is put in MSB order.
- * IN assertion: the stream state is correct and there is enough room in
- * pending_buf.
- */
-const putShortMSB = (s, b) => {
-
- // put_byte(s, (Byte)(b >> 8));
-// put_byte(s, (Byte)(b & 0xff));
- s.pending_buf[s.pending++] = (b >>> 8) & 0xff;
- s.pending_buf[s.pending++] = b & 0xff;
-};
-
-
-/* ===========================================================================
- * Read a new buffer from the current input stream, update the adler32
- * and total number of bytes read. All deflate() input goes through
- * this function so some applications may wish to modify it to avoid
- * allocating a large strm->input buffer and copying from it.
- * (See also flush_pending()).
- */
-const read_buf = (strm, buf, start, size) => {
-
- let len = strm.avail_in;
-
- if (len > size) { len = size; }
- if (len === 0) { return 0; }
-
- strm.avail_in -= len;
-
- // zmemcpy(buf, strm->next_in, len);
- buf.set(strm.input.subarray(strm.next_in, strm.next_in + len), start);
- if (strm.state.wrap === 1) {
- strm.adler = adler32_1(strm.adler, buf, len, start);
- }
-
- else if (strm.state.wrap === 2) {
- strm.adler = crc32_1(strm.adler, buf, len, start);
- }
-
- strm.next_in += len;
- strm.total_in += len;
-
- return len;
-};
-
-
-/* ===========================================================================
- * Set match_start to the longest match starting at the given string and
- * return its length. Matches shorter or equal to prev_length are discarded,
- * in which case the result is equal to prev_length and match_start is
- * garbage.
- * IN assertions: cur_match is the head of the hash chain for the current
- * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
- * OUT assertion: the match length is not greater than s->lookahead.
- */
-const longest_match = (s, cur_match) => {
-
- let chain_length = s.max_chain_length; /* max hash chain length */
- let scan = s.strstart; /* current string */
- let match; /* matched string */
- let len; /* length of current match */
- let best_len = s.prev_length; /* best match length so far */
- let nice_match = s.nice_match; /* stop if match long enough */
- const limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ?
- s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/;
-
- const _win = s.window; // shortcut
-
- const wmask = s.w_mask;
- const prev = s.prev;
-
- /* Stop when cur_match becomes <= limit. To simplify the code,
- * we prevent matches with the string of window index 0.
- */
-
- const strend = s.strstart + MAX_MATCH;
- let scan_end1 = _win[scan + best_len - 1];
- let scan_end = _win[scan + best_len];
-
- /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
- * It is easy to get rid of this optimization if necessary.
- */
- // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
-
- /* Do not waste too much time if we already have a good match: */
- if (s.prev_length >= s.good_match) {
- chain_length >>= 2;
- }
- /* Do not look for matches beyond the end of the input. This is necessary
- * to make deflate deterministic.
- */
- if (nice_match > s.lookahead) { nice_match = s.lookahead; }
-
- // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
-
- do {
- // Assert(cur_match < s->strstart, "no future");
- match = cur_match;
-
- /* Skip to next match if the match length cannot increase
- * or if the match length is less than 2. Note that the checks below
- * for insufficient lookahead only occur occasionally for performance
- * reasons. Therefore uninitialized memory will be accessed, and
- * conditional jumps will be made that depend on those values.
- * However the length of the match is limited to the lookahead, so
- * the output of deflate is not affected by the uninitialized values.
- */
-
- if (_win[match + best_len] !== scan_end ||
- _win[match + best_len - 1] !== scan_end1 ||
- _win[match] !== _win[scan] ||
- _win[++match] !== _win[scan + 1]) {
- continue;
- }
-
- /* The check at best_len-1 can be removed because it will be made
- * again later. (This heuristic is not always a win.)
- * It is not necessary to compare scan[2] and match[2] since they
- * are always equal when the other bytes match, given that
- * the hash keys are equal and that HASH_BITS >= 8.
- */
- scan += 2;
- match++;
- // Assert(*scan == *match, "match[2]?");
-
- /* We check for insufficient lookahead only every 8th comparison;
- * the 256th check will be made at strstart+258.
- */
- do {
- /*jshint noempty:false*/
- } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
- _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
- _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
- _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
- scan < strend);
-
- // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
-
- len = MAX_MATCH - (strend - scan);
- scan = strend - MAX_MATCH;
-
- if (len > best_len) {
- s.match_start = cur_match;
- best_len = len;
- if (len >= nice_match) {
- break;
- }
- scan_end1 = _win[scan + best_len - 1];
- scan_end = _win[scan + best_len];
- }
- } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0);
-
- if (best_len <= s.lookahead) {
- return best_len;
- }
- return s.lookahead;
-};
-
-
-/* ===========================================================================
- * Fill the window when the lookahead becomes insufficient.
- * Updates strstart and lookahead.
- *
- * IN assertion: lookahead < MIN_LOOKAHEAD
- * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
- * At least one byte has been read, or avail_in == 0; reads are
- * performed for at least two bytes (required for the zip translate_eol
- * option -- not supported here).
- */
-const fill_window = (s) => {
-
- const _w_size = s.w_size;
- let n, more, str;
-
- //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
-
- do {
- more = s.window_size - s.lookahead - s.strstart;
-
- // JS ints have 32 bit, block below not needed
- /* Deal with !@#$% 64K limit: */
- //if (sizeof(int) <= 2) {
- // if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
- // more = wsize;
- //
- // } else if (more == (unsigned)(-1)) {
- // /* Very unlikely, but possible on 16 bit machine if
- // * strstart == 0 && lookahead == 1 (input done a byte at time)
- // */
- // more--;
- // }
- //}
-
-
- /* If the window is almost full and there is insufficient lookahead,
- * move the upper half to the lower one to make room in the upper half.
- */
- if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {
-
- s.window.set(s.window.subarray(_w_size, _w_size + _w_size - more), 0);
- s.match_start -= _w_size;
- s.strstart -= _w_size;
- /* we now have strstart >= MAX_DIST */
- s.block_start -= _w_size;
- if (s.insert > s.strstart) {
- s.insert = s.strstart;
- }
- slide_hash(s);
- more += _w_size;
- }
- if (s.strm.avail_in === 0) {
- break;
- }
-
- /* If there was no sliding:
- * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
- * more == window_size - lookahead - strstart
- * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
- * => more >= window_size - 2*WSIZE + 2
- * In the BIG_MEM or MMAP case (not yet supported),
- * window_size == input_size + MIN_LOOKAHEAD &&
- * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
- * Otherwise, window_size == 2*WSIZE so more >= 2.
- * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
- */
- //Assert(more >= 2, "more < 2");
- n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more);
- s.lookahead += n;
-
- /* Initialize the hash value now that we have some input: */
- if (s.lookahead + s.insert >= MIN_MATCH) {
- str = s.strstart - s.insert;
- s.ins_h = s.window[str];
-
- /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */
- s.ins_h = HASH(s, s.ins_h, s.window[str + 1]);
-//#if MIN_MATCH != 3
-// Call update_hash() MIN_MATCH-3 more times
-//#endif
- while (s.insert) {
- /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
- s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]);
-
- s.prev[str & s.w_mask] = s.head[s.ins_h];
- s.head[s.ins_h] = str;
- str++;
- s.insert--;
- if (s.lookahead + s.insert < MIN_MATCH) {
- break;
- }
- }
- }
- /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
- * but this is not important since only literal bytes will be emitted.
- */
-
- } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0);
-
- /* If the WIN_INIT bytes after the end of the current data have never been
- * written, then zero those bytes in order to avoid memory check reports of
- * the use of uninitialized (or uninitialised as Julian writes) bytes by
- * the longest match routines. Update the high water mark for the next
- * time through here. WIN_INIT is set to MAX_MATCH since the longest match
- * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
- */
-// if (s.high_water < s.window_size) {
-// const curr = s.strstart + s.lookahead;
-// let init = 0;
-//
-// if (s.high_water < curr) {
-// /* Previous high water mark below current data -- zero WIN_INIT
-// * bytes or up to end of window, whichever is less.
-// */
-// init = s.window_size - curr;
-// if (init > WIN_INIT)
-// init = WIN_INIT;
-// zmemzero(s->window + curr, (unsigned)init);
-// s->high_water = curr + init;
-// }
-// else if (s->high_water < (ulg)curr + WIN_INIT) {
-// /* High water mark at or above current data, but below current data
-// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
-// * to end of window, whichever is less.
-// */
-// init = (ulg)curr + WIN_INIT - s->high_water;
-// if (init > s->window_size - s->high_water)
-// init = s->window_size - s->high_water;
-// zmemzero(s->window + s->high_water, (unsigned)init);
-// s->high_water += init;
-// }
-// }
-//
-// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
-// "not enough room for search");
-};
-
-/* ===========================================================================
- * Copy without compression as much as possible from the input stream, return
- * the current block state.
- *
- * In case deflateParams() is used to later switch to a non-zero compression
- * level, s->matches (otherwise unused when storing) keeps track of the number
- * of hash table slides to perform. If s->matches is 1, then one hash table
- * slide will be done when switching. If s->matches is 2, the maximum value
- * allowed here, then the hash table will be cleared, since two or more slides
- * is the same as a clear.
- *
- * deflate_stored() is written to minimize the number of times an input byte is
- * copied. It is most efficient with large input and output buffers, which
- * maximizes the opportunites to have a single copy from next_in to next_out.
- */
-const deflate_stored = (s, flush) => {
-
- /* Smallest worthy block size when not flushing or finishing. By default
- * this is 32K. This can be as small as 507 bytes for memLevel == 1. For
- * large input and output buffers, the stored block size will be larger.
- */
- let min_block = s.pending_buf_size - 5 > s.w_size ? s.w_size : s.pending_buf_size - 5;
-
- /* Copy as many min_block or larger stored blocks directly to next_out as
- * possible. If flushing, copy the remaining available input to next_out as
- * stored blocks, if there is enough space.
- */
- let len, left, have, last = 0;
- let used = s.strm.avail_in;
- do {
- /* Set len to the maximum size block that we can copy directly with the
- * available input data and output space. Set left to how much of that
- * would be copied from what's left in the window.
- */
- len = 65535/* MAX_STORED */; /* maximum deflate stored block length */
- have = (s.bi_valid + 42) >> 3; /* number of header bytes */
- if (s.strm.avail_out < have) { /* need room for header */
- break;
- }
- /* maximum stored block length that will fit in avail_out: */
- have = s.strm.avail_out - have;
- left = s.strstart - s.block_start; /* bytes left in window */
- if (len > left + s.strm.avail_in) {
- len = left + s.strm.avail_in; /* limit len to the input */
- }
- if (len > have) {
- len = have; /* limit len to the output */
- }
-
- /* If the stored block would be less than min_block in length, or if
- * unable to copy all of the available input when flushing, then try
- * copying to the window and the pending buffer instead. Also don't
- * write an empty block when flushing -- deflate() does that.
- */
- if (len < min_block && ((len === 0 && flush !== Z_FINISH$3) ||
- flush === Z_NO_FLUSH$2 ||
- len !== left + s.strm.avail_in)) {
- break;
- }
-
- /* Make a dummy stored block in pending to get the header bytes,
- * including any pending bits. This also updates the debugging counts.
- */
- last = flush === Z_FINISH$3 && len === left + s.strm.avail_in ? 1 : 0;
- _tr_stored_block(s, 0, 0, last);
-
- /* Replace the lengths in the dummy stored block with len. */
- s.pending_buf[s.pending - 4] = len;
- s.pending_buf[s.pending - 3] = len >> 8;
- s.pending_buf[s.pending - 2] = ~len;
- s.pending_buf[s.pending - 1] = ~len >> 8;
-
- /* Write the stored block header bytes. */
- flush_pending(s.strm);
-
-//#ifdef ZLIB_DEBUG
-// /* Update debugging counts for the data about to be copied. */
-// s->compressed_len += len << 3;
-// s->bits_sent += len << 3;
-//#endif
-
- /* Copy uncompressed bytes from the window to next_out. */
- if (left) {
- if (left > len) {
- left = len;
- }
- //zmemcpy(s->strm->next_out, s->window + s->block_start, left);
- s.strm.output.set(s.window.subarray(s.block_start, s.block_start + left), s.strm.next_out);
- s.strm.next_out += left;
- s.strm.avail_out -= left;
- s.strm.total_out += left;
- s.block_start += left;
- len -= left;
- }
-
- /* Copy uncompressed bytes directly from next_in to next_out, updating
- * the check value.
- */
- if (len) {
- read_buf(s.strm, s.strm.output, s.strm.next_out, len);
- s.strm.next_out += len;
- s.strm.avail_out -= len;
- s.strm.total_out += len;
- }
- } while (last === 0);
-
- /* Update the sliding window with the last s->w_size bytes of the copied
- * data, or append all of the copied data to the existing window if less
- * than s->w_size bytes were copied. Also update the number of bytes to
- * insert in the hash tables, in the event that deflateParams() switches to
- * a non-zero compression level.
- */
- used -= s.strm.avail_in; /* number of input bytes directly copied */
- if (used) {
- /* If any input was used, then no unused input remains in the window,
- * therefore s->block_start == s->strstart.
- */
- if (used >= s.w_size) { /* supplant the previous history */
- s.matches = 2; /* clear hash */
- //zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);
- s.window.set(s.strm.input.subarray(s.strm.next_in - s.w_size, s.strm.next_in), 0);
- s.strstart = s.w_size;
- s.insert = s.strstart;
- }
- else {
- if (s.window_size - s.strstart <= used) {
- /* Slide the window down. */
- s.strstart -= s.w_size;
- //zmemcpy(s->window, s->window + s->w_size, s->strstart);
- s.window.set(s.window.subarray(s.w_size, s.w_size + s.strstart), 0);
- if (s.matches < 2) {
- s.matches++; /* add a pending slide_hash() */
- }
- if (s.insert > s.strstart) {
- s.insert = s.strstart;
- }
- }
- //zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
- s.window.set(s.strm.input.subarray(s.strm.next_in - used, s.strm.next_in), s.strstart);
- s.strstart += used;
- s.insert += used > s.w_size - s.insert ? s.w_size - s.insert : used;
- }
- s.block_start = s.strstart;
- }
- if (s.high_water < s.strstart) {
- s.high_water = s.strstart;
- }
-
- /* If the last block was written to next_out, then done. */
- if (last) {
- return BS_FINISH_DONE;
- }
-
- /* If flushing and all input has been consumed, then done. */
- if (flush !== Z_NO_FLUSH$2 && flush !== Z_FINISH$3 &&
- s.strm.avail_in === 0 && s.strstart === s.block_start) {
- return BS_BLOCK_DONE;
- }
-
- /* Fill the window with any remaining input. */
- have = s.window_size - s.strstart;
- if (s.strm.avail_in > have && s.block_start >= s.w_size) {
- /* Slide the window down. */
- s.block_start -= s.w_size;
- s.strstart -= s.w_size;
- //zmemcpy(s->window, s->window + s->w_size, s->strstart);
- s.window.set(s.window.subarray(s.w_size, s.w_size + s.strstart), 0);
- if (s.matches < 2) {
- s.matches++; /* add a pending slide_hash() */
- }
- have += s.w_size; /* more space now */
- if (s.insert > s.strstart) {
- s.insert = s.strstart;
- }
- }
- if (have > s.strm.avail_in) {
- have = s.strm.avail_in;
- }
- if (have) {
- read_buf(s.strm, s.window, s.strstart, have);
- s.strstart += have;
- s.insert += have > s.w_size - s.insert ? s.w_size - s.insert : have;
- }
- if (s.high_water < s.strstart) {
- s.high_water = s.strstart;
- }
-
- /* There was not enough avail_out to write a complete worthy or flushed
- * stored block to next_out. Write a stored block to pending instead, if we
- * have enough input for a worthy block, or if flushing and there is enough
- * room for the remaining input as a stored block in the pending buffer.
- */
- have = (s.bi_valid + 42) >> 3; /* number of header bytes */
- /* maximum stored block length that will fit in pending: */
- have = s.pending_buf_size - have > 65535/* MAX_STORED */ ? 65535/* MAX_STORED */ : s.pending_buf_size - have;
- min_block = have > s.w_size ? s.w_size : have;
- left = s.strstart - s.block_start;
- if (left >= min_block ||
- ((left || flush === Z_FINISH$3) && flush !== Z_NO_FLUSH$2 &&
- s.strm.avail_in === 0 && left <= have)) {
- len = left > have ? have : left;
- last = flush === Z_FINISH$3 && s.strm.avail_in === 0 &&
- len === left ? 1 : 0;
- _tr_stored_block(s, s.block_start, len, last);
- s.block_start += len;
- flush_pending(s.strm);
- }
-
- /* We've done all we can with the available input and output. */
- return last ? BS_FINISH_STARTED : BS_NEED_MORE;
-};
-
-
-/* ===========================================================================
- * Compress as much as possible from the input stream, return the current
- * block state.
- * This function does not perform lazy evaluation of matches and inserts
- * new strings in the dictionary only for unmatched strings or for short
- * matches. It is used only for the fast compression options.
- */
-const deflate_fast = (s, flush) => {
-
- let hash_head; /* head of the hash chain */
- let bflush; /* set if current block must be flushed */
-
- for (;;) {
- /* Make sure that we always have enough lookahead, except
- * at the end of the input file. We need MAX_MATCH bytes
- * for the next match, plus MIN_MATCH bytes to insert the
- * string following the next match.
- */
- if (s.lookahead < MIN_LOOKAHEAD) {
- fill_window(s);
- if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH$2) {
- return BS_NEED_MORE;
- }
- if (s.lookahead === 0) {
- break; /* flush the current block */
- }
- }
-
- /* Insert the string window[strstart .. strstart+2] in the
- * dictionary, and set hash_head to the head of the hash chain:
- */
- hash_head = 0/*NIL*/;
- if (s.lookahead >= MIN_MATCH) {
- /*** INSERT_STRING(s, s.strstart, hash_head); ***/
- s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);
- hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
- s.head[s.ins_h] = s.strstart;
- /***/
- }
-
- /* Find the longest match, discarding those <= prev_length.
- * At this point we have always match_length < MIN_MATCH
- */
- if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) {
- /* To simplify the code, we prevent matches with the string
- * of window index 0 (in particular we have to avoid a match
- * of the string with itself at the start of the input file).
- */
- s.match_length = longest_match(s, hash_head);
- /* longest_match() sets match_start */
- }
- if (s.match_length >= MIN_MATCH) {
- // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only
-
- /*** _tr_tally_dist(s, s.strstart - s.match_start,
- s.match_length - MIN_MATCH, bflush); ***/
- bflush = _tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH);
-
- s.lookahead -= s.match_length;
-
- /* Insert new strings in the hash table only if the match length
- * is not too large. This saves time but degrades compression.
- */
- if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) {
- s.match_length--; /* string at strstart already in table */
- do {
- s.strstart++;
- /*** INSERT_STRING(s, s.strstart, hash_head); ***/
- s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);
- hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
- s.head[s.ins_h] = s.strstart;
- /***/
- /* strstart never exceeds WSIZE-MAX_MATCH, so there are
- * always MIN_MATCH bytes ahead.
- */
- } while (--s.match_length !== 0);
- s.strstart++;
- } else
- {
- s.strstart += s.match_length;
- s.match_length = 0;
- s.ins_h = s.window[s.strstart];
- /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */
- s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + 1]);
-
-//#if MIN_MATCH != 3
-// Call UPDATE_HASH() MIN_MATCH-3 more times
-//#endif
- /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
- * matter since it will be recomputed at next deflate call.
- */
- }
- } else {
- /* No match, output a literal byte */
- //Tracevv((stderr,"%c", s.window[s.strstart]));
- /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
- bflush = _tr_tally(s, 0, s.window[s.strstart]);
-
- s.lookahead--;
- s.strstart++;
- }
- if (bflush) {
- /*** FLUSH_BLOCK(s, 0); ***/
- flush_block_only(s, false);
- if (s.strm.avail_out === 0) {
- return BS_NEED_MORE;
- }
- /***/
- }
- }
- s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1);
- if (flush === Z_FINISH$3) {
- /*** FLUSH_BLOCK(s, 1); ***/
- flush_block_only(s, true);
- if (s.strm.avail_out === 0) {
- return BS_FINISH_STARTED;
- }
- /***/
- return BS_FINISH_DONE;
- }
- if (s.sym_next) {
- /*** FLUSH_BLOCK(s, 0); ***/
- flush_block_only(s, false);
- if (s.strm.avail_out === 0) {
- return BS_NEED_MORE;
- }
- /***/
- }
- return BS_BLOCK_DONE;
-};
-
-/* ===========================================================================
- * Same as above, but achieves better compression. We use a lazy
- * evaluation for matches: a match is finally adopted only if there is
- * no better match at the next window position.
- */
-const deflate_slow = (s, flush) => {
-
- let hash_head; /* head of hash chain */
- let bflush; /* set if current block must be flushed */
-
- let max_insert;
-
- /* Process the input block. */
- for (;;) {
- /* Make sure that we always have enough lookahead, except
- * at the end of the input file. We need MAX_MATCH bytes
- * for the next match, plus MIN_MATCH bytes to insert the
- * string following the next match.
- */
- if (s.lookahead < MIN_LOOKAHEAD) {
- fill_window(s);
- if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH$2) {
- return BS_NEED_MORE;
- }
- if (s.lookahead === 0) { break; } /* flush the current block */
- }
-
- /* Insert the string window[strstart .. strstart+2] in the
- * dictionary, and set hash_head to the head of the hash chain:
- */
- hash_head = 0/*NIL*/;
- if (s.lookahead >= MIN_MATCH) {
- /*** INSERT_STRING(s, s.strstart, hash_head); ***/
- s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);
- hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
- s.head[s.ins_h] = s.strstart;
- /***/
- }
-
- /* Find the longest match, discarding those <= prev_length.
- */
- s.prev_length = s.match_length;
- s.prev_match = s.match_start;
- s.match_length = MIN_MATCH - 1;
-
- if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match &&
- s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) {
- /* To simplify the code, we prevent matches with the string
- * of window index 0 (in particular we have to avoid a match
- * of the string with itself at the start of the input file).
- */
- s.match_length = longest_match(s, hash_head);
- /* longest_match() sets match_start */
-
- if (s.match_length <= 5 &&
- (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) {
-
- /* If prev_match is also MIN_MATCH, match_start is garbage
- * but we will ignore the current match anyway.
- */
- s.match_length = MIN_MATCH - 1;
- }
- }
- /* If there was a match at the previous step and the current
- * match is not better, output the previous match:
- */
- if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) {
- max_insert = s.strstart + s.lookahead - MIN_MATCH;
- /* Do not insert strings in hash table beyond this. */
-
- //check_match(s, s.strstart-1, s.prev_match, s.prev_length);
-
- /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match,
- s.prev_length - MIN_MATCH, bflush);***/
- bflush = _tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH);
- /* Insert in hash table all strings up to the end of the match.
- * strstart-1 and strstart are already inserted. If there is not
- * enough lookahead, the last two strings are not inserted in
- * the hash table.
- */
- s.lookahead -= s.prev_length - 1;
- s.prev_length -= 2;
- do {
- if (++s.strstart <= max_insert) {
- /*** INSERT_STRING(s, s.strstart, hash_head); ***/
- s.ins_h = HASH(s, s.ins_h, s.window[s.strstart + MIN_MATCH - 1]);
- hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
- s.head[s.ins_h] = s.strstart;
- /***/
- }
- } while (--s.prev_length !== 0);
- s.match_available = 0;
- s.match_length = MIN_MATCH - 1;
- s.strstart++;
-
- if (bflush) {
- /*** FLUSH_BLOCK(s, 0); ***/
- flush_block_only(s, false);
- if (s.strm.avail_out === 0) {
- return BS_NEED_MORE;
- }
- /***/
- }
-
- } else if (s.match_available) {
- /* If there was no match at the previous position, output a
- * single literal. If there was a match but the current match
- * is longer, truncate the previous match to a single literal.
- */
- //Tracevv((stderr,"%c", s->window[s->strstart-1]));
- /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
- bflush = _tr_tally(s, 0, s.window[s.strstart - 1]);
-
- if (bflush) {
- /*** FLUSH_BLOCK_ONLY(s, 0) ***/
- flush_block_only(s, false);
- /***/
- }
- s.strstart++;
- s.lookahead--;
- if (s.strm.avail_out === 0) {
- return BS_NEED_MORE;
- }
- } else {
- /* There is no previous match to compare with, wait for
- * the next step to decide.
- */
- s.match_available = 1;
- s.strstart++;
- s.lookahead--;
- }
- }
- //Assert (flush != Z_NO_FLUSH, "no flush?");
- if (s.match_available) {
- //Tracevv((stderr,"%c", s->window[s->strstart-1]));
- /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
- bflush = _tr_tally(s, 0, s.window[s.strstart - 1]);
-
- s.match_available = 0;
- }
- s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1;
- if (flush === Z_FINISH$3) {
- /*** FLUSH_BLOCK(s, 1); ***/
- flush_block_only(s, true);
- if (s.strm.avail_out === 0) {
- return BS_FINISH_STARTED;
- }
- /***/
- return BS_FINISH_DONE;
- }
- if (s.sym_next) {
- /*** FLUSH_BLOCK(s, 0); ***/
- flush_block_only(s, false);
- if (s.strm.avail_out === 0) {
- return BS_NEED_MORE;
- }
- /***/
- }
-
- return BS_BLOCK_DONE;
-};
-
-
-/* ===========================================================================
- * For Z_RLE, simply look for runs of bytes, generate matches only of distance
- * one. Do not maintain a hash table. (It will be regenerated if this run of
- * deflate switches away from Z_RLE.)
- */
-const deflate_rle = (s, flush) => {
-
- let bflush; /* set if current block must be flushed */
- let prev; /* byte at distance one to match */
- let scan, strend; /* scan goes up to strend for length of run */
-
- const _win = s.window;
-
- for (;;) {
- /* Make sure that we always have enough lookahead, except
- * at the end of the input file. We need MAX_MATCH bytes
- * for the longest run, plus one for the unrolled loop.
- */
- if (s.lookahead <= MAX_MATCH) {
- fill_window(s);
- if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH$2) {
- return BS_NEED_MORE;
- }
- if (s.lookahead === 0) { break; } /* flush the current block */
- }
-
- /* See how many times the previous byte repeats */
- s.match_length = 0;
- if (s.lookahead >= MIN_MATCH && s.strstart > 0) {
- scan = s.strstart - 1;
- prev = _win[scan];
- if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {
- strend = s.strstart + MAX_MATCH;
- do {
- /*jshint noempty:false*/
- } while (prev === _win[++scan] && prev === _win[++scan] &&
- prev === _win[++scan] && prev === _win[++scan] &&
- prev === _win[++scan] && prev === _win[++scan] &&
- prev === _win[++scan] && prev === _win[++scan] &&
- scan < strend);
- s.match_length = MAX_MATCH - (strend - scan);
- if (s.match_length > s.lookahead) {
- s.match_length = s.lookahead;
- }
- }
- //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
- }
-
- /* Emit match if have run of MIN_MATCH or longer, else emit literal */
- if (s.match_length >= MIN_MATCH) {
- //check_match(s, s.strstart, s.strstart - 1, s.match_length);
-
- /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/
- bflush = _tr_tally(s, 1, s.match_length - MIN_MATCH);
-
- s.lookahead -= s.match_length;
- s.strstart += s.match_length;
- s.match_length = 0;
- } else {
- /* No match, output a literal byte */
- //Tracevv((stderr,"%c", s->window[s->strstart]));
- /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
- bflush = _tr_tally(s, 0, s.window[s.strstart]);
-
- s.lookahead--;
- s.strstart++;
- }
- if (bflush) {
- /*** FLUSH_BLOCK(s, 0); ***/
- flush_block_only(s, false);
- if (s.strm.avail_out === 0) {
- return BS_NEED_MORE;
- }
- /***/
- }
- }
- s.insert = 0;
- if (flush === Z_FINISH$3) {
- /*** FLUSH_BLOCK(s, 1); ***/
- flush_block_only(s, true);
- if (s.strm.avail_out === 0) {
- return BS_FINISH_STARTED;
- }
- /***/
- return BS_FINISH_DONE;
- }
- if (s.sym_next) {
- /*** FLUSH_BLOCK(s, 0); ***/
- flush_block_only(s, false);
- if (s.strm.avail_out === 0) {
- return BS_NEED_MORE;
- }
- /***/
- }
- return BS_BLOCK_DONE;
-};
-
-/* ===========================================================================
- * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
- * (It will be regenerated if this run of deflate switches away from Huffman.)
- */
-const deflate_huff = (s, flush) => {
-
- let bflush; /* set if current block must be flushed */
-
- for (;;) {
- /* Make sure that we have a literal to write. */
- if (s.lookahead === 0) {
- fill_window(s);
- if (s.lookahead === 0) {
- if (flush === Z_NO_FLUSH$2) {
- return BS_NEED_MORE;
- }
- break; /* flush the current block */
- }
- }
-
- /* Output a literal byte */
- s.match_length = 0;
- //Tracevv((stderr,"%c", s->window[s->strstart]));
- /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
- bflush = _tr_tally(s, 0, s.window[s.strstart]);
- s.lookahead--;
- s.strstart++;
- if (bflush) {
- /*** FLUSH_BLOCK(s, 0); ***/
- flush_block_only(s, false);
- if (s.strm.avail_out === 0) {
- return BS_NEED_MORE;
- }
- /***/
- }
- }
- s.insert = 0;
- if (flush === Z_FINISH$3) {
- /*** FLUSH_BLOCK(s, 1); ***/
- flush_block_only(s, true);
- if (s.strm.avail_out === 0) {
- return BS_FINISH_STARTED;
- }
- /***/
- return BS_FINISH_DONE;
- }
- if (s.sym_next) {
- /*** FLUSH_BLOCK(s, 0); ***/
- flush_block_only(s, false);
- if (s.strm.avail_out === 0) {
- return BS_NEED_MORE;
- }
- /***/
- }
- return BS_BLOCK_DONE;
-};
-
-/* Values for max_lazy_match, good_match and max_chain_length, depending on
- * the desired pack level (0..9). The values given below have been tuned to
- * exclude worst case performance for pathological files. Better values may be
- * found for specific files.
- */
-function Config(good_length, max_lazy, nice_length, max_chain, func) {
-
- this.good_length = good_length;
- this.max_lazy = max_lazy;
- this.nice_length = nice_length;
- this.max_chain = max_chain;
- this.func = func;
-}
-
-const configuration_table = [
- /* good lazy nice chain */
- new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */
- new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */
- new Config(4, 5, 16, 8, deflate_fast), /* 2 */
- new Config(4, 6, 32, 32, deflate_fast), /* 3 */
-
- new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */
- new Config(8, 16, 32, 32, deflate_slow), /* 5 */
- new Config(8, 16, 128, 128, deflate_slow), /* 6 */
- new Config(8, 32, 128, 256, deflate_slow), /* 7 */
- new Config(32, 128, 258, 1024, deflate_slow), /* 8 */
- new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */
-];
-
-
-/* ===========================================================================
- * Initialize the "longest match" routines for a new zlib stream
- */
-const lm_init = (s) => {
-
- s.window_size = 2 * s.w_size;
-
- /*** CLEAR_HASH(s); ***/
- zero(s.head); // Fill with NIL (= 0);
-
- /* Set the default configuration parameters:
- */
- s.max_lazy_match = configuration_table[s.level].max_lazy;
- s.good_match = configuration_table[s.level].good_length;
- s.nice_match = configuration_table[s.level].nice_length;
- s.max_chain_length = configuration_table[s.level].max_chain;
-
- s.strstart = 0;
- s.block_start = 0;
- s.lookahead = 0;
- s.insert = 0;
- s.match_length = s.prev_length = MIN_MATCH - 1;
- s.match_available = 0;
- s.ins_h = 0;
-};
-
-
-function DeflateState() {
- this.strm = null; /* pointer back to this zlib stream */
- this.status = 0; /* as the name implies */
- this.pending_buf = null; /* output still pending */
- this.pending_buf_size = 0; /* size of pending_buf */
- this.pending_out = 0; /* next pending byte to output to the stream */
- this.pending = 0; /* nb of bytes in the pending buffer */
- this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */
- this.gzhead = null; /* gzip header information to write */
- this.gzindex = 0; /* where in extra, name, or comment */
- this.method = Z_DEFLATED$2; /* can only be DEFLATED */
- this.last_flush = -1; /* value of flush param for previous deflate call */
-
- this.w_size = 0; /* LZ77 window size (32K by default) */
- this.w_bits = 0; /* log2(w_size) (8..16) */
- this.w_mask = 0; /* w_size - 1 */
-
- this.window = null;
- /* Sliding window. Input bytes are read into the second half of the window,
- * and move to the first half later to keep a dictionary of at least wSize
- * bytes. With this organization, matches are limited to a distance of
- * wSize-MAX_MATCH bytes, but this ensures that IO is always
- * performed with a length multiple of the block size.
- */
-
- this.window_size = 0;
- /* Actual size of window: 2*wSize, except when the user input buffer
- * is directly used as sliding window.
- */
-
- this.prev = null;
- /* Link to older string with same hash index. To limit the size of this
- * array to 64K, this link is maintained only for the last 32K strings.
- * An index in this array is thus a window index modulo 32K.
- */
-
- this.head = null; /* Heads of the hash chains or NIL. */
-
- this.ins_h = 0; /* hash index of string to be inserted */
- this.hash_size = 0; /* number of elements in hash table */
- this.hash_bits = 0; /* log2(hash_size) */
- this.hash_mask = 0; /* hash_size-1 */
-
- this.hash_shift = 0;
- /* Number of bits by which ins_h must be shifted at each input
- * step. It must be such that after MIN_MATCH steps, the oldest
- * byte no longer takes part in the hash key, that is:
- * hash_shift * MIN_MATCH >= hash_bits
- */
-
- this.block_start = 0;
- /* Window position at the beginning of the current output block. Gets
- * negative when the window is moved backwards.
- */
-
- this.match_length = 0; /* length of best match */
- this.prev_match = 0; /* previous match */
- this.match_available = 0; /* set if previous match exists */
- this.strstart = 0; /* start of string to insert */
- this.match_start = 0; /* start of matching string */
- this.lookahead = 0; /* number of valid bytes ahead in window */
-
- this.prev_length = 0;
- /* Length of the best match at previous step. Matches not greater than this
- * are discarded. This is used in the lazy match evaluation.
- */
-
- this.max_chain_length = 0;
- /* To speed up deflation, hash chains are never searched beyond this
- * length. A higher limit improves compression ratio but degrades the
- * speed.
- */
-
- this.max_lazy_match = 0;
- /* Attempt to find a better match only when the current match is strictly
- * smaller than this value. This mechanism is used only for compression
- * levels >= 4.
- */
- // That's alias to max_lazy_match, don't use directly
- //this.max_insert_length = 0;
- /* Insert new strings in the hash table only if the match length is not
- * greater than this length. This saves time but degrades compression.
- * max_insert_length is used only for compression levels <= 3.
- */
-
- this.level = 0; /* compression level (1..9) */
- this.strategy = 0; /* favor or force Huffman coding*/
-
- this.good_match = 0;
- /* Use a faster search when the previous match is longer than this */
-
- this.nice_match = 0; /* Stop searching when current match exceeds this */
-
- /* used by trees.c: */
-
- /* Didn't use ct_data typedef below to suppress compiler warning */
-
- // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
- // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
- // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
-
- // Use flat array of DOUBLE size, with interleaved fata,
- // because JS does not support effective
- this.dyn_ltree = new Uint16Array(HEAP_SIZE * 2);
- this.dyn_dtree = new Uint16Array((2 * D_CODES + 1) * 2);
- this.bl_tree = new Uint16Array((2 * BL_CODES + 1) * 2);
- zero(this.dyn_ltree);
- zero(this.dyn_dtree);
- zero(this.bl_tree);
-
- this.l_desc = null; /* desc. for literal tree */
- this.d_desc = null; /* desc. for distance tree */
- this.bl_desc = null; /* desc. for bit length tree */
-
- //ush bl_count[MAX_BITS+1];
- this.bl_count = new Uint16Array(MAX_BITS + 1);
- /* number of codes at each bit length for an optimal tree */
-
- //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
- this.heap = new Uint16Array(2 * L_CODES + 1); /* heap used to build the Huffman trees */
- zero(this.heap);
-
- this.heap_len = 0; /* number of elements in the heap */
- this.heap_max = 0; /* element of largest frequency */
- /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
- * The same heap array is used to build all trees.
- */
-
- this.depth = new Uint16Array(2 * L_CODES + 1); //uch depth[2*L_CODES+1];
- zero(this.depth);
- /* Depth of each subtree used as tie breaker for trees of equal frequency
- */
-
- this.sym_buf = 0; /* buffer for distances and literals/lengths */
-
- this.lit_bufsize = 0;
- /* Size of match buffer for literals/lengths. There are 4 reasons for
- * limiting lit_bufsize to 64K:
- * - frequencies can be kept in 16 bit counters
- * - if compression is not successful for the first block, all input
- * data is still in the window so we can still emit a stored block even
- * when input comes from standard input. (This can also be done for
- * all blocks if lit_bufsize is not greater than 32K.)
- * - if compression is not successful for a file smaller than 64K, we can
- * even emit a stored file instead of a stored block (saving 5 bytes).
- * This is applicable only for zip (not gzip or zlib).
- * - creating new Huffman trees less frequently may not provide fast
- * adaptation to changes in the input data statistics. (Take for
- * example a binary file with poorly compressible code followed by
- * a highly compressible string table.) Smaller buffer sizes give
- * fast adaptation but have of course the overhead of transmitting
- * trees more frequently.
- * - I can't count above 4
- */
-
- this.sym_next = 0; /* running index in sym_buf */
- this.sym_end = 0; /* symbol table full when sym_next reaches this */
-
- this.opt_len = 0; /* bit length of current block with optimal trees */
- this.static_len = 0; /* bit length of current block with static trees */
- this.matches = 0; /* number of string matches in current block */
- this.insert = 0; /* bytes at end of window left to insert */
-
-
- this.bi_buf = 0;
- /* Output buffer. bits are inserted starting at the bottom (least
- * significant bits).
- */
- this.bi_valid = 0;
- /* Number of valid bits in bi_buf. All bits above the last valid bit
- * are always zero.
- */
-
- // Used for window memory init. We safely ignore it for JS. That makes
- // sense only for pointers and memory check tools.
- //this.high_water = 0;
- /* High water mark offset in window for initialized bytes -- bytes above
- * this are set to zero in order to avoid memory check warnings when
- * longest match routines access bytes past the input. This is then
- * updated to the new high water mark.
- */
-}
-
-
-/* =========================================================================
- * Check for a valid deflate stream state. Return 0 if ok, 1 if not.
- */
-const deflateStateCheck = (strm) => {
-
- if (!strm) {
- return 1;
- }
- const s = strm.state;
- if (!s || s.strm !== strm || (s.status !== INIT_STATE &&
-//#ifdef GZIP
- s.status !== GZIP_STATE &&
-//#endif
- s.status !== EXTRA_STATE &&
- s.status !== NAME_STATE &&
- s.status !== COMMENT_STATE &&
- s.status !== HCRC_STATE &&
- s.status !== BUSY_STATE &&
- s.status !== FINISH_STATE)) {
- return 1;
- }
- return 0;
-};
-
-
-const deflateResetKeep = (strm) => {
-
- if (deflateStateCheck(strm)) {
- return err(strm, Z_STREAM_ERROR$2);
- }
-
- strm.total_in = strm.total_out = 0;
- strm.data_type = Z_UNKNOWN;
-
- const s = strm.state;
- s.pending = 0;
- s.pending_out = 0;
-
- if (s.wrap < 0) {
- s.wrap = -s.wrap;
- /* was made negative by deflate(..., Z_FINISH); */
- }
- s.status =
-//#ifdef GZIP
- s.wrap === 2 ? GZIP_STATE :
-//#endif
- s.wrap ? INIT_STATE : BUSY_STATE;
- strm.adler = (s.wrap === 2) ?
- 0 // crc32(0, Z_NULL, 0)
- :
- 1; // adler32(0, Z_NULL, 0)
- s.last_flush = -2;
- _tr_init(s);
- return Z_OK$3;
-};
-
-
-const deflateReset = (strm) => {
-
- const ret = deflateResetKeep(strm);
- if (ret === Z_OK$3) {
- lm_init(strm.state);
- }
- return ret;
-};
-
-
-const deflateSetHeader = (strm, head) => {
-
- if (deflateStateCheck(strm) || strm.state.wrap !== 2) {
- return Z_STREAM_ERROR$2;
- }
- strm.state.gzhead = head;
- return Z_OK$3;
-};
-
-
-const deflateInit2 = (strm, level, method, windowBits, memLevel, strategy) => {
-
- if (!strm) { // === Z_NULL
- return Z_STREAM_ERROR$2;
- }
- let wrap = 1;
-
- if (level === Z_DEFAULT_COMPRESSION$1) {
- level = 6;
- }
-
- if (windowBits < 0) { /* suppress zlib wrapper */
- wrap = 0;
- windowBits = -windowBits;
- }
-
- else if (windowBits > 15) {
- wrap = 2; /* write gzip wrapper instead */
- windowBits -= 16;
- }
-
-
- if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED$2 ||
- windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
- strategy < 0 || strategy > Z_FIXED || (windowBits === 8 && wrap !== 1)) {
- return err(strm, Z_STREAM_ERROR$2);
- }
-
-
- if (windowBits === 8) {
- windowBits = 9;
- }
- /* until 256-byte window bug fixed */
-
- const s = new DeflateState();
-
- strm.state = s;
- s.strm = strm;
- s.status = INIT_STATE; /* to pass state test in deflateReset() */
-
- s.wrap = wrap;
- s.gzhead = null;
- s.w_bits = windowBits;
- s.w_size = 1 << s.w_bits;
- s.w_mask = s.w_size - 1;
-
- s.hash_bits = memLevel + 7;
- s.hash_size = 1 << s.hash_bits;
- s.hash_mask = s.hash_size - 1;
- s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH);
-
- s.window = new Uint8Array(s.w_size * 2);
- s.head = new Uint16Array(s.hash_size);
- s.prev = new Uint16Array(s.w_size);
-
- // Don't need mem init magic for JS.
- //s.high_water = 0; /* nothing written to s->window yet */
-
- s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
-
- /* We overlay pending_buf and sym_buf. This works since the average size
- * for length/distance pairs over any compressed block is assured to be 31
- * bits or less.
- *
- * Analysis: The longest fixed codes are a length code of 8 bits plus 5
- * extra bits, for lengths 131 to 257. The longest fixed distance codes are
- * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
- * possible fixed-codes length/distance pair is then 31 bits total.
- *
- * sym_buf starts one-fourth of the way into pending_buf. So there are
- * three bytes in sym_buf for every four bytes in pending_buf. Each symbol
- * in sym_buf is three bytes -- two for the distance and one for the
- * literal/length. As each symbol is consumed, the pointer to the next
- * sym_buf value to read moves forward three bytes. From that symbol, up to
- * 31 bits are written to pending_buf. The closest the written pending_buf
- * bits gets to the next sym_buf symbol to read is just before the last
- * code is written. At that time, 31*(n-2) bits have been written, just
- * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at
- * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1
- * symbols are written.) The closest the writing gets to what is unread is
- * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and
- * can range from 128 to 32768.
- *
- * Therefore, at a minimum, there are 142 bits of space between what is
- * written and what is read in the overlain buffers, so the symbols cannot
- * be overwritten by the compressed data. That space is actually 139 bits,
- * due to the three-bit fixed-code block header.
- *
- * That covers the case where either Z_FIXED is specified, forcing fixed
- * codes, or when the use of fixed codes is chosen, because that choice
- * results in a smaller compressed block than dynamic codes. That latter
- * condition then assures that the above analysis also covers all dynamic
- * blocks. A dynamic-code block will only be chosen to be emitted if it has
- * fewer bits than a fixed-code block would for the same set of symbols.
- * Therefore its average symbol length is assured to be less than 31. So
- * the compressed data for a dynamic block also cannot overwrite the
- * symbols from which it is being constructed.
- */
-
- s.pending_buf_size = s.lit_bufsize * 4;
- s.pending_buf = new Uint8Array(s.pending_buf_size);
-
- // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`)
- //s->sym_buf = s->pending_buf + s->lit_bufsize;
- s.sym_buf = s.lit_bufsize;
-
- //s->sym_end = (s->lit_bufsize - 1) * 3;
- s.sym_end = (s.lit_bufsize - 1) * 3;
- /* We avoid equality with lit_bufsize*3 because of wraparound at 64K
- * on 16 bit machines and because stored blocks are restricted to
- * 64K-1 bytes.
- */
-
- s.level = level;
- s.strategy = strategy;
- s.method = method;
-
- return deflateReset(strm);
-};
-
-const deflateInit = (strm, level) => {
-
- return deflateInit2(strm, level, Z_DEFLATED$2, MAX_WBITS$1, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY$1);
-};
-
-
-/* ========================================================================= */
-const deflate$2 = (strm, flush) => {
-
- if (deflateStateCheck(strm) || flush > Z_BLOCK$1 || flush < 0) {
- return strm ? err(strm, Z_STREAM_ERROR$2) : Z_STREAM_ERROR$2;
- }
-
- const s = strm.state;
-
- if (!strm.output ||
- (strm.avail_in !== 0 && !strm.input) ||
- (s.status === FINISH_STATE && flush !== Z_FINISH$3)) {
- return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR$1 : Z_STREAM_ERROR$2);
- }
-
- const old_flush = s.last_flush;
- s.last_flush = flush;
-
- /* Flush as much pending output as possible */
- if (s.pending !== 0) {
- flush_pending(strm);
- if (strm.avail_out === 0) {
- /* Since avail_out is 0, deflate will be called again with
- * more output space, but possibly with both pending and
- * avail_in equal to zero. There won't be anything to do,
- * but this is not an error situation so make sure we
- * return OK instead of BUF_ERROR at next call of deflate:
- */
- s.last_flush = -1;
- return Z_OK$3;
- }
-
- /* Make sure there is something to do and avoid duplicate consecutive
- * flushes. For repeated and useless calls with Z_FINISH, we keep
- * returning Z_STREAM_END instead of Z_BUF_ERROR.
- */
- } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) &&
- flush !== Z_FINISH$3) {
- return err(strm, Z_BUF_ERROR$1);
- }
-
- /* User must not provide more input after the first FINISH: */
- if (s.status === FINISH_STATE && strm.avail_in !== 0) {
- return err(strm, Z_BUF_ERROR$1);
- }
-
- /* Write the header */
- if (s.status === INIT_STATE && s.wrap === 0) {
- s.status = BUSY_STATE;
- }
- if (s.status === INIT_STATE) {
- /* zlib header */
- let header = (Z_DEFLATED$2 + ((s.w_bits - 8) << 4)) << 8;
- let level_flags = -1;
-
- if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) {
- level_flags = 0;
- } else if (s.level < 6) {
- level_flags = 1;
- } else if (s.level === 6) {
- level_flags = 2;
- } else {
- level_flags = 3;
- }
- header |= (level_flags << 6);
- if (s.strstart !== 0) { header |= PRESET_DICT; }
- header += 31 - (header % 31);
-
- putShortMSB(s, header);
-
- /* Save the adler32 of the preset dictionary: */
- if (s.strstart !== 0) {
- putShortMSB(s, strm.adler >>> 16);
- putShortMSB(s, strm.adler & 0xffff);
- }
- strm.adler = 1; // adler32(0L, Z_NULL, 0);
- s.status = BUSY_STATE;
-
- /* Compression must start with an empty pending buffer */
- flush_pending(strm);
- if (s.pending !== 0) {
- s.last_flush = -1;
- return Z_OK$3;
- }
- }
-//#ifdef GZIP
- if (s.status === GZIP_STATE) {
- /* gzip header */
- strm.adler = 0; //crc32(0L, Z_NULL, 0);
- put_byte(s, 31);
- put_byte(s, 139);
- put_byte(s, 8);
- if (!s.gzhead) { // s->gzhead == Z_NULL
- put_byte(s, 0);
- put_byte(s, 0);
- put_byte(s, 0);
- put_byte(s, 0);
- put_byte(s, 0);
- put_byte(s, s.level === 9 ? 2 :
- (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
- 4 : 0));
- put_byte(s, OS_CODE);
- s.status = BUSY_STATE;
-
- /* Compression must start with an empty pending buffer */
- flush_pending(strm);
- if (s.pending !== 0) {
- s.last_flush = -1;
- return Z_OK$3;
- }
- }
- else {
- put_byte(s, (s.gzhead.text ? 1 : 0) +
- (s.gzhead.hcrc ? 2 : 0) +
- (!s.gzhead.extra ? 0 : 4) +
- (!s.gzhead.name ? 0 : 8) +
- (!s.gzhead.comment ? 0 : 16)
- );
- put_byte(s, s.gzhead.time & 0xff);
- put_byte(s, (s.gzhead.time >> 8) & 0xff);
- put_byte(s, (s.gzhead.time >> 16) & 0xff);
- put_byte(s, (s.gzhead.time >> 24) & 0xff);
- put_byte(s, s.level === 9 ? 2 :
- (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
- 4 : 0));
- put_byte(s, s.gzhead.os & 0xff);
- if (s.gzhead.extra && s.gzhead.extra.length) {
- put_byte(s, s.gzhead.extra.length & 0xff);
- put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);
- }
- if (s.gzhead.hcrc) {
- strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending, 0);
- }
- s.gzindex = 0;
- s.status = EXTRA_STATE;
- }
- }
- if (s.status === EXTRA_STATE) {
- if (s.gzhead.extra/* != Z_NULL*/) {
- let beg = s.pending; /* start of bytes to update crc */
- let left = (s.gzhead.extra.length & 0xffff) - s.gzindex;
- while (s.pending + left > s.pending_buf_size) {
- let copy = s.pending_buf_size - s.pending;
- // zmemcpy(s.pending_buf + s.pending,
- // s.gzhead.extra + s.gzindex, copy);
- s.pending_buf.set(s.gzhead.extra.subarray(s.gzindex, s.gzindex + copy), s.pending);
- s.pending = s.pending_buf_size;
- //--- HCRC_UPDATE(beg) ---//
- if (s.gzhead.hcrc && s.pending > beg) {
- strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
- }
- //---//
- s.gzindex += copy;
- flush_pending(strm);
- if (s.pending !== 0) {
- s.last_flush = -1;
- return Z_OK$3;
- }
- beg = 0;
- left -= copy;
- }
- // JS specific: s.gzhead.extra may be TypedArray or Array for backward compatibility
- // TypedArray.slice and TypedArray.from don't exist in IE10-IE11
- let gzhead_extra = new Uint8Array(s.gzhead.extra);
- // zmemcpy(s->pending_buf + s->pending,
- // s->gzhead->extra + s->gzindex, left);
- s.pending_buf.set(gzhead_extra.subarray(s.gzindex, s.gzindex + left), s.pending);
- s.pending += left;
- //--- HCRC_UPDATE(beg) ---//
- if (s.gzhead.hcrc && s.pending > beg) {
- strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
- }
- //---//
- s.gzindex = 0;
- }
- s.status = NAME_STATE;
- }
- if (s.status === NAME_STATE) {
- if (s.gzhead.name/* != Z_NULL*/) {
- let beg = s.pending; /* start of bytes to update crc */
- let val;
- do {
- if (s.pending === s.pending_buf_size) {
- //--- HCRC_UPDATE(beg) ---//
- if (s.gzhead.hcrc && s.pending > beg) {
- strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
- }
- //---//
- flush_pending(strm);
- if (s.pending !== 0) {
- s.last_flush = -1;
- return Z_OK$3;
- }
- beg = 0;
- }
- // JS specific: little magic to add zero terminator to end of string
- if (s.gzindex < s.gzhead.name.length) {
- val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;
- } else {
- val = 0;
- }
- put_byte(s, val);
- } while (val !== 0);
- //--- HCRC_UPDATE(beg) ---//
- if (s.gzhead.hcrc && s.pending > beg) {
- strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
- }
- //---//
- s.gzindex = 0;
- }
- s.status = COMMENT_STATE;
- }
- if (s.status === COMMENT_STATE) {
- if (s.gzhead.comment/* != Z_NULL*/) {
- let beg = s.pending; /* start of bytes to update crc */
- let val;
- do {
- if (s.pending === s.pending_buf_size) {
- //--- HCRC_UPDATE(beg) ---//
- if (s.gzhead.hcrc && s.pending > beg) {
- strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
- }
- //---//
- flush_pending(strm);
- if (s.pending !== 0) {
- s.last_flush = -1;
- return Z_OK$3;
- }
- beg = 0;
- }
- // JS specific: little magic to add zero terminator to end of string
- if (s.gzindex < s.gzhead.comment.length) {
- val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;
- } else {
- val = 0;
- }
- put_byte(s, val);
- } while (val !== 0);
- //--- HCRC_UPDATE(beg) ---//
- if (s.gzhead.hcrc && s.pending > beg) {
- strm.adler = crc32_1(strm.adler, s.pending_buf, s.pending - beg, beg);
- }
- //---//
- }
- s.status = HCRC_STATE;
- }
- if (s.status === HCRC_STATE) {
- if (s.gzhead.hcrc) {
- if (s.pending + 2 > s.pending_buf_size) {
- flush_pending(strm);
- if (s.pending !== 0) {
- s.last_flush = -1;
- return Z_OK$3;
- }
- }
- put_byte(s, strm.adler & 0xff);
- put_byte(s, (strm.adler >> 8) & 0xff);
- strm.adler = 0; //crc32(0L, Z_NULL, 0);
- }
- s.status = BUSY_STATE;
-
- /* Compression must start with an empty pending buffer */
- flush_pending(strm);
- if (s.pending !== 0) {
- s.last_flush = -1;
- return Z_OK$3;
- }
- }
-//#endif
-
- /* Start a new block or continue the current one.
- */
- if (strm.avail_in !== 0 || s.lookahead !== 0 ||
- (flush !== Z_NO_FLUSH$2 && s.status !== FINISH_STATE)) {
- let bstate = s.level === 0 ? deflate_stored(s, flush) :
- s.strategy === Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
- s.strategy === Z_RLE ? deflate_rle(s, flush) :
- configuration_table[s.level].func(s, flush);
-
- if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) {
- s.status = FINISH_STATE;
- }
- if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) {
- if (strm.avail_out === 0) {
- s.last_flush = -1;
- /* avoid BUF_ERROR next call, see above */
- }
- return Z_OK$3;
- /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
- * of deflate should use the same flush parameter to make sure
- * that the flush is complete. So we don't have to output an
- * empty block here, this will be done at next call. This also
- * ensures that for a very small output buffer, we emit at most
- * one empty block.
- */
- }
- if (bstate === BS_BLOCK_DONE) {
- if (flush === Z_PARTIAL_FLUSH) {
- _tr_align(s);
- }
- else if (flush !== Z_BLOCK$1) { /* FULL_FLUSH or SYNC_FLUSH */
-
- _tr_stored_block(s, 0, 0, false);
- /* For a full flush, this empty block will be recognized
- * as a special marker by inflate_sync().
- */
- if (flush === Z_FULL_FLUSH$1) {
- /*** CLEAR_HASH(s); ***/ /* forget history */
- zero(s.head); // Fill with NIL (= 0);
-
- if (s.lookahead === 0) {
- s.strstart = 0;
- s.block_start = 0;
- s.insert = 0;
- }
- }
- }
- flush_pending(strm);
- if (strm.avail_out === 0) {
- s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */
- return Z_OK$3;
- }
- }
- }
-
- if (flush !== Z_FINISH$3) { return Z_OK$3; }
- if (s.wrap <= 0) { return Z_STREAM_END$3; }
-
- /* Write the trailer */
- if (s.wrap === 2) {
- put_byte(s, strm.adler & 0xff);
- put_byte(s, (strm.adler >> 8) & 0xff);
- put_byte(s, (strm.adler >> 16) & 0xff);
- put_byte(s, (strm.adler >> 24) & 0xff);
- put_byte(s, strm.total_in & 0xff);
- put_byte(s, (strm.total_in >> 8) & 0xff);
- put_byte(s, (strm.total_in >> 16) & 0xff);
- put_byte(s, (strm.total_in >> 24) & 0xff);
- }
- else
- {
- putShortMSB(s, strm.adler >>> 16);
- putShortMSB(s, strm.adler & 0xffff);
- }
-
- flush_pending(strm);
- /* If avail_out is zero, the application will call deflate again
- * to flush the rest.
- */
- if (s.wrap > 0) { s.wrap = -s.wrap; }
- /* write the trailer only once! */
- return s.pending !== 0 ? Z_OK$3 : Z_STREAM_END$3;
-};
-
-
-const deflateEnd = (strm) => {
-
- if (deflateStateCheck(strm)) {
- return Z_STREAM_ERROR$2;
- }
-
- const status = strm.state.status;
-
- strm.state = null;
-
- return status === BUSY_STATE ? err(strm, Z_DATA_ERROR$2) : Z_OK$3;
-};
-
-
-/* =========================================================================
- * Initializes the compression dictionary from the given byte
- * sequence without producing any compressed output.
- */
-const deflateSetDictionary = (strm, dictionary) => {
-
- let dictLength = dictionary.length;
-
- if (deflateStateCheck(strm)) {
- return Z_STREAM_ERROR$2;
- }
-
- const s = strm.state;
- const wrap = s.wrap;
-
- if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) {
- return Z_STREAM_ERROR$2;
- }
-
- /* when using zlib wrappers, compute Adler-32 for provided dictionary */
- if (wrap === 1) {
- /* adler32(strm->adler, dictionary, dictLength); */
- strm.adler = adler32_1(strm.adler, dictionary, dictLength, 0);
- }
-
- s.wrap = 0; /* avoid computing Adler-32 in read_buf */
-
- /* if dictionary would fill window, just replace the history */
- if (dictLength >= s.w_size) {
- if (wrap === 0) { /* already empty otherwise */
- /*** CLEAR_HASH(s); ***/
- zero(s.head); // Fill with NIL (= 0);
- s.strstart = 0;
- s.block_start = 0;
- s.insert = 0;
- }
- /* use the tail */
- // dictionary = dictionary.slice(dictLength - s.w_size);
- let tmpDict = new Uint8Array(s.w_size);
- tmpDict.set(dictionary.subarray(dictLength - s.w_size, dictLength), 0);
- dictionary = tmpDict;
- dictLength = s.w_size;
- }
- /* insert dictionary into window and hash */
- const avail = strm.avail_in;
- const next = strm.next_in;
- const input = strm.input;
- strm.avail_in = dictLength;
- strm.next_in = 0;
- strm.input = dictionary;
- fill_window(s);
- while (s.lookahead >= MIN_MATCH) {
- let str = s.strstart;
- let n = s.lookahead - (MIN_MATCH - 1);
- do {
- /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
- s.ins_h = HASH(s, s.ins_h, s.window[str + MIN_MATCH - 1]);
-
- s.prev[str & s.w_mask] = s.head[s.ins_h];
-
- s.head[s.ins_h] = str;
- str++;
- } while (--n);
- s.strstart = str;
- s.lookahead = MIN_MATCH - 1;
- fill_window(s);
- }
- s.strstart += s.lookahead;
- s.block_start = s.strstart;
- s.insert = s.lookahead;
- s.lookahead = 0;
- s.match_length = s.prev_length = MIN_MATCH - 1;
- s.match_available = 0;
- strm.next_in = next;
- strm.input = input;
- strm.avail_in = avail;
- s.wrap = wrap;
- return Z_OK$3;
-};
-
-
-var deflateInit_1 = deflateInit;
-var deflateInit2_1 = deflateInit2;
-var deflateReset_1 = deflateReset;
-var deflateResetKeep_1 = deflateResetKeep;
-var deflateSetHeader_1 = deflateSetHeader;
-var deflate_2$1 = deflate$2;
-var deflateEnd_1 = deflateEnd;
-var deflateSetDictionary_1 = deflateSetDictionary;
-var deflateInfo = 'pako deflate (from Nodeca project)';
-
-/* Not implemented
-module.exports.deflateBound = deflateBound;
-module.exports.deflateCopy = deflateCopy;
-module.exports.deflateGetDictionary = deflateGetDictionary;
-module.exports.deflateParams = deflateParams;
-module.exports.deflatePending = deflatePending;
-module.exports.deflatePrime = deflatePrime;
-module.exports.deflateTune = deflateTune;
-*/
-
-var deflate_1$2 = {
- deflateInit: deflateInit_1,
- deflateInit2: deflateInit2_1,
- deflateReset: deflateReset_1,
- deflateResetKeep: deflateResetKeep_1,
- deflateSetHeader: deflateSetHeader_1,
- deflate: deflate_2$1,
- deflateEnd: deflateEnd_1,
- deflateSetDictionary: deflateSetDictionary_1,
- deflateInfo: deflateInfo
-};
-
-const _has = (obj, key) => {
- return Object.prototype.hasOwnProperty.call(obj, key);
-};
-
-var assign = function (obj /*from1, from2, from3, ...*/) {
- const sources = Array.prototype.slice.call(arguments, 1);
- while (sources.length) {
- const source = sources.shift();
- if (!source) { continue; }
-
- if (typeof source !== 'object') {
- throw new TypeError(source + 'must be non-object');
- }
-
- for (const p in source) {
- if (_has(source, p)) {
- obj[p] = source[p];
- }
- }
- }
-
- return obj;
-};
-
-
-// Join array of chunks to single array.
-var flattenChunks = (chunks) => {
- // calculate data length
- let len = 0;
-
- for (let i = 0, l = chunks.length; i < l; i++) {
- len += chunks[i].length;
- }
-
- // join chunks
- const result = new Uint8Array(len);
-
- for (let i = 0, pos = 0, l = chunks.length; i < l; i++) {
- let chunk = chunks[i];
- result.set(chunk, pos);
- pos += chunk.length;
- }
-
- return result;
-};
-
-var common = {
- assign: assign,
- flattenChunks: flattenChunks
-};
-
-// String encode/decode helpers
-
-
-// Quick check if we can use fast array to bin string conversion
-//
-// - apply(Array) can fail on Android 2.2
-// - apply(Uint8Array) can fail on iOS 5.1 Safari
-//
-let STR_APPLY_UIA_OK = true;
-
-try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; }
-
-
-// Table with utf8 lengths (calculated by first byte of sequence)
-// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
-// because max possible codepoint is 0x10ffff
-const _utf8len = new Uint8Array(256);
-for (let q = 0; q < 256; q++) {
- _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);
-}
-_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start
-
-
-// convert string to array (typed, when possible)
-var string2buf = (str) => {
- if (typeof TextEncoder === 'function' && TextEncoder.prototype.encode) {
- return new TextEncoder().encode(str);
- }
-
- let buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
-
- // count binary size
- for (m_pos = 0; m_pos < str_len; m_pos++) {
- c = str.charCodeAt(m_pos);
- if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
- c2 = str.charCodeAt(m_pos + 1);
- if ((c2 & 0xfc00) === 0xdc00) {
- c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
- m_pos++;
- }
- }
- buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;
- }
-
- // allocate buffer
- buf = new Uint8Array(buf_len);
-
- // convert
- for (i = 0, m_pos = 0; i < buf_len; m_pos++) {
- c = str.charCodeAt(m_pos);
- if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
- c2 = str.charCodeAt(m_pos + 1);
- if ((c2 & 0xfc00) === 0xdc00) {
- c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
- m_pos++;
- }
- }
- if (c < 0x80) {
- /* one byte */
- buf[i++] = c;
- } else if (c < 0x800) {
- /* two bytes */
- buf[i++] = 0xC0 | (c >>> 6);
- buf[i++] = 0x80 | (c & 0x3f);
- } else if (c < 0x10000) {
- /* three bytes */
- buf[i++] = 0xE0 | (c >>> 12);
- buf[i++] = 0x80 | (c >>> 6 & 0x3f);
- buf[i++] = 0x80 | (c & 0x3f);
- } else {
- /* four bytes */
- buf[i++] = 0xf0 | (c >>> 18);
- buf[i++] = 0x80 | (c >>> 12 & 0x3f);
- buf[i++] = 0x80 | (c >>> 6 & 0x3f);
- buf[i++] = 0x80 | (c & 0x3f);
- }
- }
-
- return buf;
-};
-
-// Helper
-const buf2binstring = (buf, len) => {
- // On Chrome, the arguments in a function call that are allowed is `65534`.
- // If the length of the buffer is smaller than that, we can use this optimization,
- // otherwise we will take a slower path.
- if (len < 65534) {
- if (buf.subarray && STR_APPLY_UIA_OK) {
- return String.fromCharCode.apply(null, buf.length === len ? buf : buf.subarray(0, len));
- }
- }
-
- let result = '';
- for (let i = 0; i < len; i++) {
- result += String.fromCharCode(buf[i]);
- }
- return result;
-};
-
-
-// convert array to string
-var buf2string = (buf, max) => {
- const len = max || buf.length;
-
- if (typeof TextDecoder === 'function' && TextDecoder.prototype.decode) {
- return new TextDecoder().decode(buf.subarray(0, max));
- }
-
- let i, out;
-
- // Reserve max possible length (2 words per char)
- // NB: by unknown reasons, Array is significantly faster for
- // String.fromCharCode.apply than Uint16Array.
- const utf16buf = new Array(len * 2);
-
- for (out = 0, i = 0; i < len;) {
- let c = buf[i++];
- // quick process ascii
- if (c < 0x80) { utf16buf[out++] = c; continue; }
-
- let c_len = _utf8len[c];
- // skip 5 & 6 byte codes
- if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }
-
- // apply mask on first byte
- c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
- // join the rest
- while (c_len > 1 && i < len) {
- c = (c << 6) | (buf[i++] & 0x3f);
- c_len--;
- }
-
- // terminated by end of string?
- if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }
-
- if (c < 0x10000) {
- utf16buf[out++] = c;
- } else {
- c -= 0x10000;
- utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);
- utf16buf[out++] = 0xdc00 | (c & 0x3ff);
- }
- }
-
- return buf2binstring(utf16buf, out);
-};
-
-
-// Calculate max possible position in utf8 buffer,
-// that will not break sequence. If that's not possible
-// - (very small limits) return max size as is.
-//
-// buf[] - utf8 bytes array
-// max - length limit (mandatory);
-var utf8border = (buf, max) => {
-
- max = max || buf.length;
- if (max > buf.length) { max = buf.length; }
-
- // go back from last position, until start of sequence found
- let pos = max - 1;
- while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }
-
- // Very small and broken sequence,
- // return max, because we should return something anyway.
- if (pos < 0) { return max; }
-
- // If we came to start of buffer - that means buffer is too small,
- // return max too.
- if (pos === 0) { return max; }
-
- return (pos + _utf8len[buf[pos]] > max) ? pos : max;
-};
-
-var strings = {
- string2buf: string2buf,
- buf2string: buf2string,
- utf8border: utf8border
-};
-
-// (C) 1995-2013 Jean-loup Gailly and Mark Adler
-// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
-
-function ZStream() {
- /* next input byte */
- this.input = null; // JS specific, because we have no pointers
- this.next_in = 0;
- /* number of bytes available at input */
- this.avail_in = 0;
- /* total number of input bytes read so far */
- this.total_in = 0;
- /* next output byte should be put there */
- this.output = null; // JS specific, because we have no pointers
- this.next_out = 0;
- /* remaining free space at output */
- this.avail_out = 0;
- /* total number of bytes output so far */
- this.total_out = 0;
- /* last error message, NULL if no error */
- this.msg = ''/*Z_NULL*/;
- /* not visible by applications */
- this.state = null;
- /* best guess about the data type: binary or text */
- this.data_type = 2/*Z_UNKNOWN*/;
- /* adler32 value of the uncompressed data */
- this.adler = 0;
-}
-
-var zstream = ZStream;
-
-const toString$1 = Object.prototype.toString;
-
-/* Public constants ==========================================================*/
-/* ===========================================================================*/
-
-const {
- Z_NO_FLUSH: Z_NO_FLUSH$1, Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH: Z_FINISH$2,
- Z_OK: Z_OK$2, Z_STREAM_END: Z_STREAM_END$2,
- Z_DEFAULT_COMPRESSION,
- Z_DEFAULT_STRATEGY,
- Z_DEFLATED: Z_DEFLATED$1
-} = constants$2;
-
-/* ===========================================================================*/
-
-
-/**
- * class Deflate
- *
- * Generic JS-style wrapper for zlib calls. If you don't need
- * streaming behaviour - use more simple functions: [[deflate]],
- * [[deflateRaw]] and [[gzip]].
- **/
-
-/* internal
- * Deflate.chunks -> Array
- *
- * Chunks of output data, if [[Deflate#onData]] not overridden.
- **/
-
-/**
- * Deflate.result -> Uint8Array
- *
- * Compressed result, generated by default [[Deflate#onData]]
- * and [[Deflate#onEnd]] handlers. Filled after you push last chunk
- * (call [[Deflate#push]] with `Z_FINISH` / `true` param).
- **/
-
-/**
- * Deflate.err -> Number
- *
- * Error code after deflate finished. 0 (Z_OK) on success.
- * You will not need it in real life, because deflate errors
- * are possible only on wrong options or bad `onData` / `onEnd`
- * custom handlers.
- **/
-
-/**
- * Deflate.msg -> String
- *
- * Error message, if [[Deflate.err]] != 0
- **/
-
-
-/**
- * new Deflate(options)
- * - options (Object): zlib deflate options.
- *
- * Creates new deflator instance with specified params. Throws exception
- * on bad params. Supported options:
- *
- * - `level`
- * - `windowBits`
- * - `memLevel`
- * - `strategy`
- * - `dictionary`
- *
- * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
- * for more information on these.
- *
- * Additional options, for internal needs:
- *
- * - `chunkSize` - size of generated data chunks (16K by default)
- * - `raw` (Boolean) - do raw deflate
- * - `gzip` (Boolean) - create gzip wrapper
- * - `header` (Object) - custom header for gzip
- * - `text` (Boolean) - true if compressed data believed to be text
- * - `time` (Number) - modification time, unix timestamp
- * - `os` (Number) - operation system code
- * - `extra` (Array) - array of bytes with extra data (max 65536)
- * - `name` (String) - file name (binary string)
- * - `comment` (String) - comment (binary string)
- * - `hcrc` (Boolean) - true if header crc should be added
- *
- * ##### Example:
- *
- * ```javascript
- * const pako = require('pako')
- * , chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9])
- * , chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]);
- *
- * const deflate = new pako.Deflate({ level: 3});
- *
- * deflate.push(chunk1, false);
- * deflate.push(chunk2, true); // true -> last chunk
- *
- * if (deflate.err) { throw new Error(deflate.err); }
- *
- * console.log(deflate.result);
- * ```
- **/
-function Deflate$1(options) {
- this.options = common.assign({
- level: Z_DEFAULT_COMPRESSION,
- method: Z_DEFLATED$1,
- chunkSize: 16384,
- windowBits: 15,
- memLevel: 8,
- strategy: Z_DEFAULT_STRATEGY
- }, options || {});
-
- let opt = this.options;
-
- if (opt.raw && (opt.windowBits > 0)) {
- opt.windowBits = -opt.windowBits;
- }
-
- else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) {
- opt.windowBits += 16;
- }
-
- this.err = 0; // error code, if happens (0 = Z_OK)
- this.msg = ''; // error message
- this.ended = false; // used to avoid multiple onEnd() calls
- this.chunks = []; // chunks of compressed data
-
- this.strm = new zstream();
- this.strm.avail_out = 0;
-
- let status = deflate_1$2.deflateInit2(
- this.strm,
- opt.level,
- opt.method,
- opt.windowBits,
- opt.memLevel,
- opt.strategy
- );
-
- if (status !== Z_OK$2) {
- throw new Error(messages[status]);
- }
-
- if (opt.header) {
- deflate_1$2.deflateSetHeader(this.strm, opt.header);
- }
-
- if (opt.dictionary) {
- let dict;
- // Convert data if needed
- if (typeof opt.dictionary === 'string') {
- // If we need to compress text, change encoding to utf8.
- dict = strings.string2buf(opt.dictionary);
- } else if (toString$1.call(opt.dictionary) === '[object ArrayBuffer]') {
- dict = new Uint8Array(opt.dictionary);
- } else {
- dict = opt.dictionary;
- }
-
- status = deflate_1$2.deflateSetDictionary(this.strm, dict);
-
- if (status !== Z_OK$2) {
- throw new Error(messages[status]);
- }
-
- this._dict_set = true;
- }
-}
-
-/**
- * Deflate#push(data[, flush_mode]) -> Boolean
- * - data (Uint8Array|ArrayBuffer|String): input data. Strings will be
- * converted to utf8 byte sequence.
- * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
- * See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.
- *
- * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with
- * new compressed chunks. Returns `true` on success. The last data block must
- * have `flush_mode` Z_FINISH (or `true`). That will flush internal pending
- * buffers and call [[Deflate#onEnd]].
- *
- * On fail call [[Deflate#onEnd]] with error code and return false.
- *
- * ##### Example
- *
- * ```javascript
- * push(chunk, false); // push one of data chunks
- * ...
- * push(chunk, true); // push last chunk
- * ```
- **/
-Deflate$1.prototype.push = function (data, flush_mode) {
- const strm = this.strm;
- const chunkSize = this.options.chunkSize;
- let status, _flush_mode;
-
- if (this.ended) { return false; }
-
- if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;
- else _flush_mode = flush_mode === true ? Z_FINISH$2 : Z_NO_FLUSH$1;
-
- // Convert data if needed
- if (typeof data === 'string') {
- // If we need to compress text, change encoding to utf8.
- strm.input = strings.string2buf(data);
- } else if (toString$1.call(data) === '[object ArrayBuffer]') {
- strm.input = new Uint8Array(data);
- } else {
- strm.input = data;
- }
-
- strm.next_in = 0;
- strm.avail_in = strm.input.length;
-
- for (;;) {
- if (strm.avail_out === 0) {
- strm.output = new Uint8Array(chunkSize);
- strm.next_out = 0;
- strm.avail_out = chunkSize;
- }
-
- // Make sure avail_out > 6 to avoid repeating markers
- if ((_flush_mode === Z_SYNC_FLUSH || _flush_mode === Z_FULL_FLUSH) && strm.avail_out <= 6) {
- this.onData(strm.output.subarray(0, strm.next_out));
- strm.avail_out = 0;
- continue;
- }
-
- status = deflate_1$2.deflate(strm, _flush_mode);
-
- // Ended => flush and finish
- if (status === Z_STREAM_END$2) {
- if (strm.next_out > 0) {
- this.onData(strm.output.subarray(0, strm.next_out));
- }
- status = deflate_1$2.deflateEnd(this.strm);
- this.onEnd(status);
- this.ended = true;
- return status === Z_OK$2;
- }
-
- // Flush if out buffer full
- if (strm.avail_out === 0) {
- this.onData(strm.output);
- continue;
- }
-
- // Flush if requested and has data
- if (_flush_mode > 0 && strm.next_out > 0) {
- this.onData(strm.output.subarray(0, strm.next_out));
- strm.avail_out = 0;
- continue;
- }
-
- if (strm.avail_in === 0) break;
- }
-
- return true;
-};
-
-
-/**
- * Deflate#onData(chunk) -> Void
- * - chunk (Uint8Array): output data.
- *
- * By default, stores data blocks in `chunks[]` property and glue
- * those in `onEnd`. Override this handler, if you need another behaviour.
- **/
-Deflate$1.prototype.onData = function (chunk) {
- this.chunks.push(chunk);
-};
-
-
-/**
- * Deflate#onEnd(status) -> Void
- * - status (Number): deflate status. 0 (Z_OK) on success,
- * other if not.
- *
- * Called once after you tell deflate that the input stream is
- * complete (Z_FINISH). By default - join collected chunks,
- * free memory and fill `results` / `err` properties.
- **/
-Deflate$1.prototype.onEnd = function (status) {
- // On success - join
- if (status === Z_OK$2) {
- this.result = common.flattenChunks(this.chunks);
- }
- this.chunks = [];
- this.err = status;
- this.msg = this.strm.msg;
-};
-
-
-/**
- * deflate(data[, options]) -> Uint8Array
- * - data (Uint8Array|ArrayBuffer|String): input data to compress.
- * - options (Object): zlib deflate options.
- *
- * Compress `data` with deflate algorithm and `options`.
- *
- * Supported options are:
- *
- * - level
- * - windowBits
- * - memLevel
- * - strategy
- * - dictionary
- *
- * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
- * for more information on these.
- *
- * Sugar (options):
- *
- * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
- * negative windowBits implicitly.
- *
- * ##### Example:
- *
- * ```javascript
- * const pako = require('pako')
- * const data = new Uint8Array([1,2,3,4,5,6,7,8,9]);
- *
- * console.log(pako.deflate(data));
- * ```
- **/
-function deflate$1(input, options) {
- const deflator = new Deflate$1(options);
-
- deflator.push(input, true);
-
- // That will never happens, if you don't cheat with options :)
- if (deflator.err) { throw deflator.msg || messages[deflator.err]; }
-
- return deflator.result;
-}
-
-
-/**
- * deflateRaw(data[, options]) -> Uint8Array
- * - data (Uint8Array|ArrayBuffer|String): input data to compress.
- * - options (Object): zlib deflate options.
- *
- * The same as [[deflate]], but creates raw data, without wrapper
- * (header and adler32 crc).
- **/
-function deflateRaw$1(input, options) {
- options = options || {};
- options.raw = true;
- return deflate$1(input, options);
-}
-
-
-/**
- * gzip(data[, options]) -> Uint8Array
- * - data (Uint8Array|ArrayBuffer|String): input data to compress.
- * - options (Object): zlib deflate options.
- *
- * The same as [[deflate]], but create gzip wrapper instead of
- * deflate one.
- **/
-function gzip$1(input, options) {
- options = options || {};
- options.gzip = true;
- return deflate$1(input, options);
-}
-
-
-var Deflate_1$1 = Deflate$1;
-var deflate_2 = deflate$1;
-var deflateRaw_1$1 = deflateRaw$1;
-var gzip_1$1 = gzip$1;
-var constants$1 = constants$2;
-
-var deflate_1$1 = {
- Deflate: Deflate_1$1,
- deflate: deflate_2,
- deflateRaw: deflateRaw_1$1,
- gzip: gzip_1$1,
- constants: constants$1
-};
-
-// (C) 1995-2013 Jean-loup Gailly and Mark Adler
-// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
-
-// See state defs from inflate.js
-const BAD$1 = 16209; /* got a data error -- remain here until reset */
-const TYPE$1 = 16191; /* i: waiting for type bits, including last-flag bit */
-
-/*
- Decode literal, length, and distance codes and write out the resulting
- literal and match bytes until either not enough input or output is
- available, an end-of-block is encountered, or a data error is encountered.
- When large enough input and output buffers are supplied to inflate(), for
- example, a 16K input buffer and a 64K output buffer, more than 95% of the
- inflate execution time is spent in this routine.
-
- Entry assumptions:
-
- state.mode === LEN
- strm.avail_in >= 6
- strm.avail_out >= 258
- start >= strm.avail_out
- state.bits < 8
-
- On return, state.mode is one of:
-
- LEN -- ran out of enough output space or enough available input
- TYPE -- reached end of block code, inflate() to interpret next block
- BAD -- error in block data
-
- Notes:
-
- - The maximum input bits used by a length/distance pair is 15 bits for the
- length code, 5 bits for the length extra, 15 bits for the distance code,
- and 13 bits for the distance extra. This totals 48 bits, or six bytes.
- Therefore if strm.avail_in >= 6, then there is enough input to avoid
- checking for available input while decoding.
-
- - The maximum bytes that a single length/distance pair can output is 258
- bytes, which is the maximum length that can be coded. inflate_fast()
- requires strm.avail_out >= 258 for each loop to avoid checking for
- output space.
- */
-var inffast = function inflate_fast(strm, start) {
- let _in; /* local strm.input */
- let last; /* have enough input while in < last */
- let _out; /* local strm.output */
- let beg; /* inflate()'s initial strm.output */
- let end; /* while out < end, enough space available */
-//#ifdef INFLATE_STRICT
- let dmax; /* maximum distance from zlib header */
-//#endif
- let wsize; /* window size or zero if not using window */
- let whave; /* valid bytes in the window */
- let wnext; /* window write index */
- // Use `s_window` instead `window`, avoid conflict with instrumentation tools
- let s_window; /* allocated sliding window, if wsize != 0 */
- let hold; /* local strm.hold */
- let bits; /* local strm.bits */
- let lcode; /* local strm.lencode */
- let dcode; /* local strm.distcode */
- let lmask; /* mask for first level of length codes */
- let dmask; /* mask for first level of distance codes */
- let here; /* retrieved table entry */
- let op; /* code bits, operation, extra bits, or */
- /* window position, window bytes to copy */
- let len; /* match length, unused bytes */
- let dist; /* match distance */
- let from; /* where to copy match from */
- let from_source;
-
-
- let input, output; // JS specific, because we have no pointers
-
- /* copy state to local variables */
- const state = strm.state;
- //here = state.here;
- _in = strm.next_in;
- input = strm.input;
- last = _in + (strm.avail_in - 5);
- _out = strm.next_out;
- output = strm.output;
- beg = _out - (start - strm.avail_out);
- end = _out + (strm.avail_out - 257);
-//#ifdef INFLATE_STRICT
- dmax = state.dmax;
-//#endif
- wsize = state.wsize;
- whave = state.whave;
- wnext = state.wnext;
- s_window = state.window;
- hold = state.hold;
- bits = state.bits;
- lcode = state.lencode;
- dcode = state.distcode;
- lmask = (1 << state.lenbits) - 1;
- dmask = (1 << state.distbits) - 1;
-
-
- /* decode literals and length/distances until end-of-block or not enough
- input data or output space */
-
- top:
- do {
- if (bits < 15) {
- hold += input[_in++] << bits;
- bits += 8;
- hold += input[_in++] << bits;
- bits += 8;
- }
-
- here = lcode[hold & lmask];
-
- dolen:
- for (;;) { // Goto emulation
- op = here >>> 24/*here.bits*/;
- hold >>>= op;
- bits -= op;
- op = (here >>> 16) & 0xff/*here.op*/;
- if (op === 0) { /* literal */
- //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
- // "inflate: literal '%c'\n" :
- // "inflate: literal 0x%02x\n", here.val));
- output[_out++] = here & 0xffff/*here.val*/;
- }
- else if (op & 16) { /* length base */
- len = here & 0xffff/*here.val*/;
- op &= 15; /* number of extra bits */
- if (op) {
- if (bits < op) {
- hold += input[_in++] << bits;
- bits += 8;
- }
- len += hold & ((1 << op) - 1);
- hold >>>= op;
- bits -= op;
- }
- //Tracevv((stderr, "inflate: length %u\n", len));
- if (bits < 15) {
- hold += input[_in++] << bits;
- bits += 8;
- hold += input[_in++] << bits;
- bits += 8;
- }
- here = dcode[hold & dmask];
-
- dodist:
- for (;;) { // goto emulation
- op = here >>> 24/*here.bits*/;
- hold >>>= op;
- bits -= op;
- op = (here >>> 16) & 0xff/*here.op*/;
-
- if (op & 16) { /* distance base */
- dist = here & 0xffff/*here.val*/;
- op &= 15; /* number of extra bits */
- if (bits < op) {
- hold += input[_in++] << bits;
- bits += 8;
- if (bits < op) {
- hold += input[_in++] << bits;
- bits += 8;
- }
- }
- dist += hold & ((1 << op) - 1);
-//#ifdef INFLATE_STRICT
- if (dist > dmax) {
- strm.msg = 'invalid distance too far back';
- state.mode = BAD$1;
- break top;
- }
-//#endif
- hold >>>= op;
- bits -= op;
- //Tracevv((stderr, "inflate: distance %u\n", dist));
- op = _out - beg; /* max distance in output */
- if (dist > op) { /* see if copy from window */
- op = dist - op; /* distance back in window */
- if (op > whave) {
- if (state.sane) {
- strm.msg = 'invalid distance too far back';
- state.mode = BAD$1;
- break top;
- }
-
-// (!) This block is disabled in zlib defaults,
-// don't enable it for binary compatibility
-//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
-// if (len <= op - whave) {
-// do {
-// output[_out++] = 0;
-// } while (--len);
-// continue top;
-// }
-// len -= op - whave;
-// do {
-// output[_out++] = 0;
-// } while (--op > whave);
-// if (op === 0) {
-// from = _out - dist;
-// do {
-// output[_out++] = output[from++];
-// } while (--len);
-// continue top;
-// }
-//#endif
- }
- from = 0; // window index
- from_source = s_window;
- if (wnext === 0) { /* very common case */
- from += wsize - op;
- if (op < len) { /* some from window */
- len -= op;
- do {
- output[_out++] = s_window[from++];
- } while (--op);
- from = _out - dist; /* rest from output */
- from_source = output;
- }
- }
- else if (wnext < op) { /* wrap around window */
- from += wsize + wnext - op;
- op -= wnext;
- if (op < len) { /* some from end of window */
- len -= op;
- do {
- output[_out++] = s_window[from++];
- } while (--op);
- from = 0;
- if (wnext < len) { /* some from start of window */
- op = wnext;
- len -= op;
- do {
- output[_out++] = s_window[from++];
- } while (--op);
- from = _out - dist; /* rest from output */
- from_source = output;
- }
- }
- }
- else { /* contiguous in window */
- from += wnext - op;
- if (op < len) { /* some from window */
- len -= op;
- do {
- output[_out++] = s_window[from++];
- } while (--op);
- from = _out - dist; /* rest from output */
- from_source = output;
- }
- }
- while (len > 2) {
- output[_out++] = from_source[from++];
- output[_out++] = from_source[from++];
- output[_out++] = from_source[from++];
- len -= 3;
- }
- if (len) {
- output[_out++] = from_source[from++];
- if (len > 1) {
- output[_out++] = from_source[from++];
- }
- }
- }
- else {
- from = _out - dist; /* copy direct from output */
- do { /* minimum length is three */
- output[_out++] = output[from++];
- output[_out++] = output[from++];
- output[_out++] = output[from++];
- len -= 3;
- } while (len > 2);
- if (len) {
- output[_out++] = output[from++];
- if (len > 1) {
- output[_out++] = output[from++];
- }
- }
- }
- }
- else if ((op & 64) === 0) { /* 2nd level distance code */
- here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
- continue dodist;
- }
- else {
- strm.msg = 'invalid distance code';
- state.mode = BAD$1;
- break top;
- }
-
- break; // need to emulate goto via "continue"
- }
- }
- else if ((op & 64) === 0) { /* 2nd level length code */
- here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
- continue dolen;
- }
- else if (op & 32) { /* end-of-block */
- //Tracevv((stderr, "inflate: end of block\n"));
- state.mode = TYPE$1;
- break top;
- }
- else {
- strm.msg = 'invalid literal/length code';
- state.mode = BAD$1;
- break top;
- }
-
- break; // need to emulate goto via "continue"
- }
- } while (_in < last && _out < end);
-
- /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
- len = bits >> 3;
- _in -= len;
- bits -= len << 3;
- hold &= (1 << bits) - 1;
-
- /* update state and return */
- strm.next_in = _in;
- strm.next_out = _out;
- strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));
- strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));
- state.hold = hold;
- state.bits = bits;
- return;
-};
-
-// (C) 1995-2013 Jean-loup Gailly and Mark Adler
-// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
-
-const MAXBITS = 15;
-const ENOUGH_LENS$1 = 852;
-const ENOUGH_DISTS$1 = 592;
-//const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
-
-const CODES$1 = 0;
-const LENS$1 = 1;
-const DISTS$1 = 2;
-
-const lbase = new Uint16Array([ /* Length codes 257..285 base */
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
- 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
-]);
-
-const lext = new Uint8Array([ /* Length codes 257..285 extra */
- 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
- 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78
-]);
-
-const dbase = new Uint16Array([ /* Distance codes 0..29 base */
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
- 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
- 8193, 12289, 16385, 24577, 0, 0
-]);
-
-const dext = new Uint8Array([ /* Distance codes 0..29 extra */
- 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
- 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
- 28, 28, 29, 29, 64, 64
-]);
-
-const inflate_table = (type, lens, lens_index, codes, table, table_index, work, opts) =>
-{
- const bits = opts.bits;
- //here = opts.here; /* table entry for duplication */
-
- let len = 0; /* a code's length in bits */
- let sym = 0; /* index of code symbols */
- let min = 0, max = 0; /* minimum and maximum code lengths */
- let root = 0; /* number of index bits for root table */
- let curr = 0; /* number of index bits for current table */
- let drop = 0; /* code bits to drop for sub-table */
- let left = 0; /* number of prefix codes available */
- let used = 0; /* code entries in table used */
- let huff = 0; /* Huffman code */
- let incr; /* for incrementing code, index */
- let fill; /* index for replicating entries */
- let low; /* low bits for current root entry */
- let mask; /* mask for low root bits */
- let next; /* next available space in table */
- let base = null; /* base value table to use */
-// let shoextra; /* extra bits table to use */
- let match; /* use base and extra for symbol >= match */
- const count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */
- const offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */
- let extra = null;
-
- let here_bits, here_op, here_val;
-
- /*
- Process a set of code lengths to create a canonical Huffman code. The
- code lengths are lens[0..codes-1]. Each length corresponds to the
- symbols 0..codes-1. The Huffman code is generated by first sorting the
- symbols by length from short to long, and retaining the symbol order
- for codes with equal lengths. Then the code starts with all zero bits
- for the first code of the shortest length, and the codes are integer
- increments for the same length, and zeros are appended as the length
- increases. For the deflate format, these bits are stored backwards
- from their more natural integer increment ordering, and so when the
- decoding tables are built in the large loop below, the integer codes
- are incremented backwards.
-
- This routine assumes, but does not check, that all of the entries in
- lens[] are in the range 0..MAXBITS. The caller must assure this.
- 1..MAXBITS is interpreted as that code length. zero means that that
- symbol does not occur in this code.
-
- The codes are sorted by computing a count of codes for each length,
- creating from that a table of starting indices for each length in the
- sorted table, and then entering the symbols in order in the sorted
- table. The sorted table is work[], with that space being provided by
- the caller.
-
- The length counts are used for other purposes as well, i.e. finding
- the minimum and maximum length codes, determining if there are any
- codes at all, checking for a valid set of lengths, and looking ahead
- at length counts to determine sub-table sizes when building the
- decoding tables.
- */
-
- /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
- for (len = 0; len <= MAXBITS; len++) {
- count[len] = 0;
- }
- for (sym = 0; sym < codes; sym++) {
- count[lens[lens_index + sym]]++;
- }
-
- /* bound code lengths, force root to be within code lengths */
- root = bits;
- for (max = MAXBITS; max >= 1; max--) {
- if (count[max] !== 0) { break; }
- }
- if (root > max) {
- root = max;
- }
- if (max === 0) { /* no symbols to code at all */
- //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */
- //table.bits[opts.table_index] = 1; //here.bits = (var char)1;
- //table.val[opts.table_index++] = 0; //here.val = (var short)0;
- table[table_index++] = (1 << 24) | (64 << 16) | 0;
-
-
- //table.op[opts.table_index] = 64;
- //table.bits[opts.table_index] = 1;
- //table.val[opts.table_index++] = 0;
- table[table_index++] = (1 << 24) | (64 << 16) | 0;
-
- opts.bits = 1;
- return 0; /* no symbols, but wait for decoding to report error */
- }
- for (min = 1; min < max; min++) {
- if (count[min] !== 0) { break; }
- }
- if (root < min) {
- root = min;
- }
-
- /* check for an over-subscribed or incomplete set of lengths */
- left = 1;
- for (len = 1; len <= MAXBITS; len++) {
- left <<= 1;
- left -= count[len];
- if (left < 0) {
- return -1;
- } /* over-subscribed */
- }
- if (left > 0 && (type === CODES$1 || max !== 1)) {
- return -1; /* incomplete set */
- }
-
- /* generate offsets into symbol table for each length for sorting */
- offs[1] = 0;
- for (len = 1; len < MAXBITS; len++) {
- offs[len + 1] = offs[len] + count[len];
- }
-
- /* sort symbols by length, by symbol order within each length */
- for (sym = 0; sym < codes; sym++) {
- if (lens[lens_index + sym] !== 0) {
- work[offs[lens[lens_index + sym]]++] = sym;
- }
- }
-
- /*
- Create and fill in decoding tables. In this loop, the table being
- filled is at next and has curr index bits. The code being used is huff
- with length len. That code is converted to an index by dropping drop
- bits off of the bottom. For codes where len is less than drop + curr,
- those top drop + curr - len bits are incremented through all values to
- fill the table with replicated entries.
-
- root is the number of index bits for the root table. When len exceeds
- root, sub-tables are created pointed to by the root entry with an index
- of the low root bits of huff. This is saved in low to check for when a
- new sub-table should be started. drop is zero when the root table is
- being filled, and drop is root when sub-tables are being filled.
-
- When a new sub-table is needed, it is necessary to look ahead in the
- code lengths to determine what size sub-table is needed. The length
- counts are used for this, and so count[] is decremented as codes are
- entered in the tables.
-
- used keeps track of how many table entries have been allocated from the
- provided *table space. It is checked for LENS and DIST tables against
- the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
- the initial root table size constants. See the comments in inftrees.h
- for more information.
-
- sym increments through all symbols, and the loop terminates when
- all codes of length max, i.e. all codes, have been processed. This
- routine permits incomplete codes, so another loop after this one fills
- in the rest of the decoding tables with invalid code markers.
- */
-
- /* set up for code type */
- // poor man optimization - use if-else instead of switch,
- // to avoid deopts in old v8
- if (type === CODES$1) {
- base = extra = work; /* dummy value--not used */
- match = 20;
-
- } else if (type === LENS$1) {
- base = lbase;
- extra = lext;
- match = 257;
-
- } else { /* DISTS */
- base = dbase;
- extra = dext;
- match = 0;
- }
-
- /* initialize opts for loop */
- huff = 0; /* starting code */
- sym = 0; /* starting code symbol */
- len = min; /* starting code length */
- next = table_index; /* current table to fill in */
- curr = root; /* current table index bits */
- drop = 0; /* current bits to drop from code for index */
- low = -1; /* trigger new sub-table when len > root */
- used = 1 << root; /* use root table entries */
- mask = used - 1; /* mask for comparing low */
-
- /* check available table space */
- if ((type === LENS$1 && used > ENOUGH_LENS$1) ||
- (type === DISTS$1 && used > ENOUGH_DISTS$1)) {
- return 1;
- }
-
- /* process all codes and make table entries */
- for (;;) {
- /* create table entry */
- here_bits = len - drop;
- if (work[sym] + 1 < match) {
- here_op = 0;
- here_val = work[sym];
- }
- else if (work[sym] >= match) {
- here_op = extra[work[sym] - match];
- here_val = base[work[sym] - match];
- }
- else {
- here_op = 32 + 64; /* end of block */
- here_val = 0;
- }
-
- /* replicate for those indices with low len bits equal to huff */
- incr = 1 << (len - drop);
- fill = 1 << curr;
- min = fill; /* save offset to next table */
- do {
- fill -= incr;
- table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;
- } while (fill !== 0);
-
- /* backwards increment the len-bit code huff */
- incr = 1 << (len - 1);
- while (huff & incr) {
- incr >>= 1;
- }
- if (incr !== 0) {
- huff &= incr - 1;
- huff += incr;
- } else {
- huff = 0;
- }
-
- /* go to next symbol, update count, len */
- sym++;
- if (--count[len] === 0) {
- if (len === max) { break; }
- len = lens[lens_index + work[sym]];
- }
-
- /* create new sub-table if needed */
- if (len > root && (huff & mask) !== low) {
- /* if first time, transition to sub-tables */
- if (drop === 0) {
- drop = root;
- }
-
- /* increment past last table */
- next += min; /* here min is 1 << curr */
-
- /* determine length of next table */
- curr = len - drop;
- left = 1 << curr;
- while (curr + drop < max) {
- left -= count[curr + drop];
- if (left <= 0) { break; }
- curr++;
- left <<= 1;
- }
-
- /* check for enough space */
- used += 1 << curr;
- if ((type === LENS$1 && used > ENOUGH_LENS$1) ||
- (type === DISTS$1 && used > ENOUGH_DISTS$1)) {
- return 1;
- }
-
- /* point entry in root table to sub-table */
- low = huff & mask;
- /*table.op[low] = curr;
- table.bits[low] = root;
- table.val[low] = next - opts.table_index;*/
- table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;
- }
- }
-
- /* fill in remaining table entry if code is incomplete (guaranteed to have
- at most one remaining entry, since if the code is incomplete, the
- maximum code length that was allowed to get this far is one bit) */
- if (huff !== 0) {
- //table.op[next + huff] = 64; /* invalid code marker */
- //table.bits[next + huff] = len - drop;
- //table.val[next + huff] = 0;
- table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;
- }
-
- /* set return parameters */
- //opts.table_index += used;
- opts.bits = root;
- return 0;
-};
-
-
-var inftrees = inflate_table;
-
-// (C) 1995-2013 Jean-loup Gailly and Mark Adler
-// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
-
-
-
-
-
-
-const CODES = 0;
-const LENS = 1;
-const DISTS = 2;
-
-/* Public constants ==========================================================*/
-/* ===========================================================================*/
-
-const {
- Z_FINISH: Z_FINISH$1, Z_BLOCK, Z_TREES,
- Z_OK: Z_OK$1, Z_STREAM_END: Z_STREAM_END$1, Z_NEED_DICT: Z_NEED_DICT$1, Z_STREAM_ERROR: Z_STREAM_ERROR$1, Z_DATA_ERROR: Z_DATA_ERROR$1, Z_MEM_ERROR: Z_MEM_ERROR$1, Z_BUF_ERROR,
- Z_DEFLATED
-} = constants$2;
-
-
-/* STATES ====================================================================*/
-/* ===========================================================================*/
-
-
-const HEAD = 16180; /* i: waiting for magic header */
-const FLAGS = 16181; /* i: waiting for method and flags (gzip) */
-const TIME = 16182; /* i: waiting for modification time (gzip) */
-const OS = 16183; /* i: waiting for extra flags and operating system (gzip) */
-const EXLEN = 16184; /* i: waiting for extra length (gzip) */
-const EXTRA = 16185; /* i: waiting for extra bytes (gzip) */
-const NAME = 16186; /* i: waiting for end of file name (gzip) */
-const COMMENT = 16187; /* i: waiting for end of comment (gzip) */
-const HCRC = 16188; /* i: waiting for header crc (gzip) */
-const DICTID = 16189; /* i: waiting for dictionary check value */
-const DICT = 16190; /* waiting for inflateSetDictionary() call */
-const TYPE = 16191; /* i: waiting for type bits, including last-flag bit */
-const TYPEDO = 16192; /* i: same, but skip check to exit inflate on new block */
-const STORED = 16193; /* i: waiting for stored size (length and complement) */
-const COPY_ = 16194; /* i/o: same as COPY below, but only first time in */
-const COPY = 16195; /* i/o: waiting for input or output to copy stored block */
-const TABLE = 16196; /* i: waiting for dynamic block table lengths */
-const LENLENS = 16197; /* i: waiting for code length code lengths */
-const CODELENS = 16198; /* i: waiting for length/lit and distance code lengths */
-const LEN_ = 16199; /* i: same as LEN below, but only first time in */
-const LEN = 16200; /* i: waiting for length/lit/eob code */
-const LENEXT = 16201; /* i: waiting for length extra bits */
-const DIST = 16202; /* i: waiting for distance code */
-const DISTEXT = 16203; /* i: waiting for distance extra bits */
-const MATCH = 16204; /* o: waiting for output space to copy string */
-const LIT = 16205; /* o: waiting for output space to write literal */
-const CHECK = 16206; /* i: waiting for 32-bit check value */
-const LENGTH = 16207; /* i: waiting for 32-bit length (gzip) */
-const DONE = 16208; /* finished check, done -- remain here until reset */
-const BAD = 16209; /* got a data error -- remain here until reset */
-const MEM = 16210; /* got an inflate() memory error -- remain here until reset */
-const SYNC = 16211; /* looking for synchronization bytes to restart inflate() */
-
-/* ===========================================================================*/
-
-
-
-const ENOUGH_LENS = 852;
-const ENOUGH_DISTS = 592;
-//const ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
-
-const MAX_WBITS = 15;
-/* 32K LZ77 window */
-const DEF_WBITS = MAX_WBITS;
-
-
-const zswap32 = (q) => {
-
- return (((q >>> 24) & 0xff) +
- ((q >>> 8) & 0xff00) +
- ((q & 0xff00) << 8) +
- ((q & 0xff) << 24));
-};
-
-
-function InflateState() {
- this.strm = null; /* pointer back to this zlib stream */
- this.mode = 0; /* current inflate mode */
- this.last = false; /* true if processing last block */
- this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip,
- bit 2 true to validate check value */
- this.havedict = false; /* true if dictionary provided */
- this.flags = 0; /* gzip header method and flags (0 if zlib), or
- -1 if raw or no header yet */
- this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */
- this.check = 0; /* protected copy of check value */
- this.total = 0; /* protected copy of output count */
- // TODO: may be {}
- this.head = null; /* where to save gzip header information */
-
- /* sliding window */
- this.wbits = 0; /* log base 2 of requested window size */
- this.wsize = 0; /* window size or zero if not using window */
- this.whave = 0; /* valid bytes in the window */
- this.wnext = 0; /* window write index */
- this.window = null; /* allocated sliding window, if needed */
-
- /* bit accumulator */
- this.hold = 0; /* input bit accumulator */
- this.bits = 0; /* number of bits in "in" */
-
- /* for string and stored block copying */
- this.length = 0; /* literal or length of data to copy */
- this.offset = 0; /* distance back to copy string from */
-
- /* for table and code decoding */
- this.extra = 0; /* extra bits needed */
-
- /* fixed and dynamic code tables */
- this.lencode = null; /* starting table for length/literal codes */
- this.distcode = null; /* starting table for distance codes */
- this.lenbits = 0; /* index bits for lencode */
- this.distbits = 0; /* index bits for distcode */
-
- /* dynamic table building */
- this.ncode = 0; /* number of code length code lengths */
- this.nlen = 0; /* number of length code lengths */
- this.ndist = 0; /* number of distance code lengths */
- this.have = 0; /* number of code lengths in lens[] */
- this.next = null; /* next available space in codes[] */
-
- this.lens = new Uint16Array(320); /* temporary storage for code lengths */
- this.work = new Uint16Array(288); /* work area for code table building */
-
- /*
- because we don't have pointers in js, we use lencode and distcode directly
- as buffers so we don't need codes
- */
- //this.codes = new Int32Array(ENOUGH); /* space for code tables */
- this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */
- this.distdyn = null; /* dynamic table for distance codes (JS specific) */
- this.sane = 0; /* if false, allow invalid distance too far */
- this.back = 0; /* bits back of last unprocessed length/lit */
- this.was = 0; /* initial length of match */
-}
-
-
-const inflateStateCheck = (strm) => {
-
- if (!strm) {
- return 1;
- }
- const state = strm.state;
- if (!state || state.strm !== strm ||
- state.mode < HEAD || state.mode > SYNC) {
- return 1;
- }
- return 0;
-};
-
-
-const inflateResetKeep = (strm) => {
-
- if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }
- const state = strm.state;
- strm.total_in = strm.total_out = state.total = 0;
- strm.msg = ''; /*Z_NULL*/
- if (state.wrap) { /* to support ill-conceived Java test suite */
- strm.adler = state.wrap & 1;
- }
- state.mode = HEAD;
- state.last = 0;
- state.havedict = 0;
- state.flags = -1;
- state.dmax = 32768;
- state.head = null/*Z_NULL*/;
- state.hold = 0;
- state.bits = 0;
- //state.lencode = state.distcode = state.next = state.codes;
- state.lencode = state.lendyn = new Int32Array(ENOUGH_LENS);
- state.distcode = state.distdyn = new Int32Array(ENOUGH_DISTS);
-
- state.sane = 1;
- state.back = -1;
- //Tracev((stderr, "inflate: reset\n"));
- return Z_OK$1;
-};
-
-
-const inflateReset = (strm) => {
-
- if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }
- const state = strm.state;
- state.wsize = 0;
- state.whave = 0;
- state.wnext = 0;
- return inflateResetKeep(strm);
-
-};
-
-
-const inflateReset2 = (strm, windowBits) => {
- let wrap;
-
- /* get the state */
- if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }
- const state = strm.state;
-
- /* extract wrap request from windowBits parameter */
- if (windowBits < 0) {
- wrap = 0;
- windowBits = -windowBits;
- }
- else {
- wrap = (windowBits >> 4) + 5;
- if (windowBits < 48) {
- windowBits &= 15;
- }
- }
-
- /* set number of window bits, free window if different */
- if (windowBits && (windowBits < 8 || windowBits > 15)) {
- return Z_STREAM_ERROR$1;
- }
- if (state.window !== null && state.wbits !== windowBits) {
- state.window = null;
- }
-
- /* update state and reset the rest of it */
- state.wrap = wrap;
- state.wbits = windowBits;
- return inflateReset(strm);
-};
-
-
-const inflateInit2 = (strm, windowBits) => {
-
- if (!strm) { return Z_STREAM_ERROR$1; }
- //strm.msg = Z_NULL; /* in case we return an error */
-
- const state = new InflateState();
-
- //if (state === Z_NULL) return Z_MEM_ERROR;
- //Tracev((stderr, "inflate: allocated\n"));
- strm.state = state;
- state.strm = strm;
- state.window = null/*Z_NULL*/;
- state.mode = HEAD; /* to pass state test in inflateReset2() */
- const ret = inflateReset2(strm, windowBits);
- if (ret !== Z_OK$1) {
- strm.state = null/*Z_NULL*/;
- }
- return ret;
-};
-
-
-const inflateInit = (strm) => {
-
- return inflateInit2(strm, DEF_WBITS);
-};
-
-
-/*
- Return state with length and distance decoding tables and index sizes set to
- fixed code decoding. Normally this returns fixed tables from inffixed.h.
- If BUILDFIXED is defined, then instead this routine builds the tables the
- first time it's called, and returns those tables the first time and
- thereafter. This reduces the size of the code by about 2K bytes, in
- exchange for a little execution time. However, BUILDFIXED should not be
- used for threaded applications, since the rewriting of the tables and virgin
- may not be thread-safe.
- */
-let virgin = true;
-
-let lenfix, distfix; // We have no pointers in JS, so keep tables separate
-
-
-const fixedtables = (state) => {
-
- /* build fixed huffman tables if first call (may not be thread safe) */
- if (virgin) {
- lenfix = new Int32Array(512);
- distfix = new Int32Array(32);
-
- /* literal/length table */
- let sym = 0;
- while (sym < 144) { state.lens[sym++] = 8; }
- while (sym < 256) { state.lens[sym++] = 9; }
- while (sym < 280) { state.lens[sym++] = 7; }
- while (sym < 288) { state.lens[sym++] = 8; }
-
- inftrees(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 });
-
- /* distance table */
- sym = 0;
- while (sym < 32) { state.lens[sym++] = 5; }
-
- inftrees(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 });
-
- /* do this just once */
- virgin = false;
- }
-
- state.lencode = lenfix;
- state.lenbits = 9;
- state.distcode = distfix;
- state.distbits = 5;
-};
-
-
-/*
- Update the window with the last wsize (normally 32K) bytes written before
- returning. If window does not exist yet, create it. This is only called
- when a window is already in use, or when output has been written during this
- inflate call, but the end of the deflate stream has not been reached yet.
- It is also called to create a window for dictionary data when a dictionary
- is loaded.
-
- Providing output buffers larger than 32K to inflate() should provide a speed
- advantage, since only the last 32K of output is copied to the sliding window
- upon return from inflate(), and since all distances after the first 32K of
- output will fall in the output data, making match copies simpler and faster.
- The advantage may be dependent on the size of the processor's data caches.
- */
-const updatewindow = (strm, src, end, copy) => {
-
- let dist;
- const state = strm.state;
-
- /* if it hasn't been done already, allocate space for the window */
- if (state.window === null) {
- state.wsize = 1 << state.wbits;
- state.wnext = 0;
- state.whave = 0;
-
- state.window = new Uint8Array(state.wsize);
- }
-
- /* copy state->wsize or less output bytes into the circular window */
- if (copy >= state.wsize) {
- state.window.set(src.subarray(end - state.wsize, end), 0);
- state.wnext = 0;
- state.whave = state.wsize;
- }
- else {
- dist = state.wsize - state.wnext;
- if (dist > copy) {
- dist = copy;
- }
- //zmemcpy(state->window + state->wnext, end - copy, dist);
- state.window.set(src.subarray(end - copy, end - copy + dist), state.wnext);
- copy -= dist;
- if (copy) {
- //zmemcpy(state->window, end - copy, copy);
- state.window.set(src.subarray(end - copy, end), 0);
- state.wnext = copy;
- state.whave = state.wsize;
- }
- else {
- state.wnext += dist;
- if (state.wnext === state.wsize) { state.wnext = 0; }
- if (state.whave < state.wsize) { state.whave += dist; }
- }
- }
- return 0;
-};
-
-
-const inflate$2 = (strm, flush) => {
-
- let state;
- let input, output; // input/output buffers
- let next; /* next input INDEX */
- let put; /* next output INDEX */
- let have, left; /* available input and output */
- let hold; /* bit buffer */
- let bits; /* bits in bit buffer */
- let _in, _out; /* save starting available input and output */
- let copy; /* number of stored or match bytes to copy */
- let from; /* where to copy match bytes from */
- let from_source;
- let here = 0; /* current decoding table entry */
- let here_bits, here_op, here_val; // paked "here" denormalized (JS specific)
- //let last; /* parent table entry */
- let last_bits, last_op, last_val; // paked "last" denormalized (JS specific)
- let len; /* length to copy for repeats, bits to drop */
- let ret; /* return code */
- const hbuf = new Uint8Array(4); /* buffer for gzip header crc calculation */
- let opts;
-
- let n; // temporary variable for NEED_BITS
-
- const order = /* permutation of code lengths */
- new Uint8Array([ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]);
-
-
- if (inflateStateCheck(strm) || !strm.output ||
- (!strm.input && strm.avail_in !== 0)) {
- return Z_STREAM_ERROR$1;
- }
-
- state = strm.state;
- if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */
-
-
- //--- LOAD() ---
- put = strm.next_out;
- output = strm.output;
- left = strm.avail_out;
- next = strm.next_in;
- input = strm.input;
- have = strm.avail_in;
- hold = state.hold;
- bits = state.bits;
- //---
-
- _in = have;
- _out = left;
- ret = Z_OK$1;
-
- inf_leave: // goto emulation
- for (;;) {
- switch (state.mode) {
- case HEAD:
- if (state.wrap === 0) {
- state.mode = TYPEDO;
- break;
- }
- //=== NEEDBITS(16);
- while (bits < 16) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */
- if (state.wbits === 0) {
- state.wbits = 15;
- }
- state.check = 0/*crc32(0L, Z_NULL, 0)*/;
- //=== CRC2(state.check, hold);
- hbuf[0] = hold & 0xff;
- hbuf[1] = (hold >>> 8) & 0xff;
- state.check = crc32_1(state.check, hbuf, 2, 0);
- //===//
-
- //=== INITBITS();
- hold = 0;
- bits = 0;
- //===//
- state.mode = FLAGS;
- break;
- }
- if (state.head) {
- state.head.done = false;
- }
- if (!(state.wrap & 1) || /* check if zlib header allowed */
- (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {
- strm.msg = 'incorrect header check';
- state.mode = BAD;
- break;
- }
- if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) {
- strm.msg = 'unknown compression method';
- state.mode = BAD;
- break;
- }
- //--- DROPBITS(4) ---//
- hold >>>= 4;
- bits -= 4;
- //---//
- len = (hold & 0x0f)/*BITS(4)*/ + 8;
- if (state.wbits === 0) {
- state.wbits = len;
- }
- if (len > 15 || len > state.wbits) {
- strm.msg = 'invalid window size';
- state.mode = BAD;
- break;
- }
-
- // !!! pako patch. Force use `options.windowBits` if passed.
- // Required to always use max window size by default.
- state.dmax = 1 << state.wbits;
- //state.dmax = 1 << len;
-
- state.flags = 0; /* indicate zlib header */
- //Tracev((stderr, "inflate: zlib header ok\n"));
- strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
- state.mode = hold & 0x200 ? DICTID : TYPE;
- //=== INITBITS();
- hold = 0;
- bits = 0;
- //===//
- break;
- case FLAGS:
- //=== NEEDBITS(16); */
- while (bits < 16) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- state.flags = hold;
- if ((state.flags & 0xff) !== Z_DEFLATED) {
- strm.msg = 'unknown compression method';
- state.mode = BAD;
- break;
- }
- if (state.flags & 0xe000) {
- strm.msg = 'unknown header flags set';
- state.mode = BAD;
- break;
- }
- if (state.head) {
- state.head.text = ((hold >> 8) & 1);
- }
- if ((state.flags & 0x0200) && (state.wrap & 4)) {
- //=== CRC2(state.check, hold);
- hbuf[0] = hold & 0xff;
- hbuf[1] = (hold >>> 8) & 0xff;
- state.check = crc32_1(state.check, hbuf, 2, 0);
- //===//
- }
- //=== INITBITS();
- hold = 0;
- bits = 0;
- //===//
- state.mode = TIME;
- /* falls through */
- case TIME:
- //=== NEEDBITS(32); */
- while (bits < 32) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- if (state.head) {
- state.head.time = hold;
- }
- if ((state.flags & 0x0200) && (state.wrap & 4)) {
- //=== CRC4(state.check, hold)
- hbuf[0] = hold & 0xff;
- hbuf[1] = (hold >>> 8) & 0xff;
- hbuf[2] = (hold >>> 16) & 0xff;
- hbuf[3] = (hold >>> 24) & 0xff;
- state.check = crc32_1(state.check, hbuf, 4, 0);
- //===
- }
- //=== INITBITS();
- hold = 0;
- bits = 0;
- //===//
- state.mode = OS;
- /* falls through */
- case OS:
- //=== NEEDBITS(16); */
- while (bits < 16) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- if (state.head) {
- state.head.xflags = (hold & 0xff);
- state.head.os = (hold >> 8);
- }
- if ((state.flags & 0x0200) && (state.wrap & 4)) {
- //=== CRC2(state.check, hold);
- hbuf[0] = hold & 0xff;
- hbuf[1] = (hold >>> 8) & 0xff;
- state.check = crc32_1(state.check, hbuf, 2, 0);
- //===//
- }
- //=== INITBITS();
- hold = 0;
- bits = 0;
- //===//
- state.mode = EXLEN;
- /* falls through */
- case EXLEN:
- if (state.flags & 0x0400) {
- //=== NEEDBITS(16); */
- while (bits < 16) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- state.length = hold;
- if (state.head) {
- state.head.extra_len = hold;
- }
- if ((state.flags & 0x0200) && (state.wrap & 4)) {
- //=== CRC2(state.check, hold);
- hbuf[0] = hold & 0xff;
- hbuf[1] = (hold >>> 8) & 0xff;
- state.check = crc32_1(state.check, hbuf, 2, 0);
- //===//
- }
- //=== INITBITS();
- hold = 0;
- bits = 0;
- //===//
- }
- else if (state.head) {
- state.head.extra = null/*Z_NULL*/;
- }
- state.mode = EXTRA;
- /* falls through */
- case EXTRA:
- if (state.flags & 0x0400) {
- copy = state.length;
- if (copy > have) { copy = have; }
- if (copy) {
- if (state.head) {
- len = state.head.extra_len - state.length;
- if (!state.head.extra) {
- // Use untyped array for more convenient processing later
- state.head.extra = new Uint8Array(state.head.extra_len);
- }
- state.head.extra.set(
- input.subarray(
- next,
- // extra field is limited to 65536 bytes
- // - no need for additional size check
- next + copy
- ),
- /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/
- len
- );
- //zmemcpy(state.head.extra + len, next,
- // len + copy > state.head.extra_max ?
- // state.head.extra_max - len : copy);
- }
- if ((state.flags & 0x0200) && (state.wrap & 4)) {
- state.check = crc32_1(state.check, input, copy, next);
- }
- have -= copy;
- next += copy;
- state.length -= copy;
- }
- if (state.length) { break inf_leave; }
- }
- state.length = 0;
- state.mode = NAME;
- /* falls through */
- case NAME:
- if (state.flags & 0x0800) {
- if (have === 0) { break inf_leave; }
- copy = 0;
- do {
- // TODO: 2 or 1 bytes?
- len = input[next + copy++];
- /* use constant limit because in js we should not preallocate memory */
- if (state.head && len &&
- (state.length < 65536 /*state.head.name_max*/)) {
- state.head.name += String.fromCharCode(len);
- }
- } while (len && copy < have);
-
- if ((state.flags & 0x0200) && (state.wrap & 4)) {
- state.check = crc32_1(state.check, input, copy, next);
- }
- have -= copy;
- next += copy;
- if (len) { break inf_leave; }
- }
- else if (state.head) {
- state.head.name = null;
- }
- state.length = 0;
- state.mode = COMMENT;
- /* falls through */
- case COMMENT:
- if (state.flags & 0x1000) {
- if (have === 0) { break inf_leave; }
- copy = 0;
- do {
- len = input[next + copy++];
- /* use constant limit because in js we should not preallocate memory */
- if (state.head && len &&
- (state.length < 65536 /*state.head.comm_max*/)) {
- state.head.comment += String.fromCharCode(len);
- }
- } while (len && copy < have);
- if ((state.flags & 0x0200) && (state.wrap & 4)) {
- state.check = crc32_1(state.check, input, copy, next);
- }
- have -= copy;
- next += copy;
- if (len) { break inf_leave; }
- }
- else if (state.head) {
- state.head.comment = null;
- }
- state.mode = HCRC;
- /* falls through */
- case HCRC:
- if (state.flags & 0x0200) {
- //=== NEEDBITS(16); */
- while (bits < 16) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- if ((state.wrap & 4) && hold !== (state.check & 0xffff)) {
- strm.msg = 'header crc mismatch';
- state.mode = BAD;
- break;
- }
- //=== INITBITS();
- hold = 0;
- bits = 0;
- //===//
- }
- if (state.head) {
- state.head.hcrc = ((state.flags >> 9) & 1);
- state.head.done = true;
- }
- strm.adler = state.check = 0;
- state.mode = TYPE;
- break;
- case DICTID:
- //=== NEEDBITS(32); */
- while (bits < 32) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- strm.adler = state.check = zswap32(hold);
- //=== INITBITS();
- hold = 0;
- bits = 0;
- //===//
- state.mode = DICT;
- /* falls through */
- case DICT:
- if (state.havedict === 0) {
- //--- RESTORE() ---
- strm.next_out = put;
- strm.avail_out = left;
- strm.next_in = next;
- strm.avail_in = have;
- state.hold = hold;
- state.bits = bits;
- //---
- return Z_NEED_DICT$1;
- }
- strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
- state.mode = TYPE;
- /* falls through */
- case TYPE:
- if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; }
- /* falls through */
- case TYPEDO:
- if (state.last) {
- //--- BYTEBITS() ---//
- hold >>>= bits & 7;
- bits -= bits & 7;
- //---//
- state.mode = CHECK;
- break;
- }
- //=== NEEDBITS(3); */
- while (bits < 3) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- state.last = (hold & 0x01)/*BITS(1)*/;
- //--- DROPBITS(1) ---//
- hold >>>= 1;
- bits -= 1;
- //---//
-
- switch ((hold & 0x03)/*BITS(2)*/) {
- case 0: /* stored block */
- //Tracev((stderr, "inflate: stored block%s\n",
- // state.last ? " (last)" : ""));
- state.mode = STORED;
- break;
- case 1: /* fixed block */
- fixedtables(state);
- //Tracev((stderr, "inflate: fixed codes block%s\n",
- // state.last ? " (last)" : ""));
- state.mode = LEN_; /* decode codes */
- if (flush === Z_TREES) {
- //--- DROPBITS(2) ---//
- hold >>>= 2;
- bits -= 2;
- //---//
- break inf_leave;
- }
- break;
- case 2: /* dynamic block */
- //Tracev((stderr, "inflate: dynamic codes block%s\n",
- // state.last ? " (last)" : ""));
- state.mode = TABLE;
- break;
- case 3:
- strm.msg = 'invalid block type';
- state.mode = BAD;
- }
- //--- DROPBITS(2) ---//
- hold >>>= 2;
- bits -= 2;
- //---//
- break;
- case STORED:
- //--- BYTEBITS() ---// /* go to byte boundary */
- hold >>>= bits & 7;
- bits -= bits & 7;
- //---//
- //=== NEEDBITS(32); */
- while (bits < 32) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {
- strm.msg = 'invalid stored block lengths';
- state.mode = BAD;
- break;
- }
- state.length = hold & 0xffff;
- //Tracev((stderr, "inflate: stored length %u\n",
- // state.length));
- //=== INITBITS();
- hold = 0;
- bits = 0;
- //===//
- state.mode = COPY_;
- if (flush === Z_TREES) { break inf_leave; }
- /* falls through */
- case COPY_:
- state.mode = COPY;
- /* falls through */
- case COPY:
- copy = state.length;
- if (copy) {
- if (copy > have) { copy = have; }
- if (copy > left) { copy = left; }
- if (copy === 0) { break inf_leave; }
- //--- zmemcpy(put, next, copy); ---
- output.set(input.subarray(next, next + copy), put);
- //---//
- have -= copy;
- next += copy;
- left -= copy;
- put += copy;
- state.length -= copy;
- break;
- }
- //Tracev((stderr, "inflate: stored end\n"));
- state.mode = TYPE;
- break;
- case TABLE:
- //=== NEEDBITS(14); */
- while (bits < 14) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;
- //--- DROPBITS(5) ---//
- hold >>>= 5;
- bits -= 5;
- //---//
- state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;
- //--- DROPBITS(5) ---//
- hold >>>= 5;
- bits -= 5;
- //---//
- state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;
- //--- DROPBITS(4) ---//
- hold >>>= 4;
- bits -= 4;
- //---//
-//#ifndef PKZIP_BUG_WORKAROUND
- if (state.nlen > 286 || state.ndist > 30) {
- strm.msg = 'too many length or distance symbols';
- state.mode = BAD;
- break;
- }
-//#endif
- //Tracev((stderr, "inflate: table sizes ok\n"));
- state.have = 0;
- state.mode = LENLENS;
- /* falls through */
- case LENLENS:
- while (state.have < state.ncode) {
- //=== NEEDBITS(3);
- while (bits < 3) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);
- //--- DROPBITS(3) ---//
- hold >>>= 3;
- bits -= 3;
- //---//
- }
- while (state.have < 19) {
- state.lens[order[state.have++]] = 0;
- }
- // We have separate tables & no pointers. 2 commented lines below not needed.
- //state.next = state.codes;
- //state.lencode = state.next;
- // Switch to use dynamic table
- state.lencode = state.lendyn;
- state.lenbits = 7;
-
- opts = { bits: state.lenbits };
- ret = inftrees(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts);
- state.lenbits = opts.bits;
-
- if (ret) {
- strm.msg = 'invalid code lengths set';
- state.mode = BAD;
- break;
- }
- //Tracev((stderr, "inflate: code lengths ok\n"));
- state.have = 0;
- state.mode = CODELENS;
- /* falls through */
- case CODELENS:
- while (state.have < state.nlen + state.ndist) {
- for (;;) {
- here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/
- here_bits = here >>> 24;
- here_op = (here >>> 16) & 0xff;
- here_val = here & 0xffff;
-
- if ((here_bits) <= bits) { break; }
- //--- PULLBYTE() ---//
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- //---//
- }
- if (here_val < 16) {
- //--- DROPBITS(here.bits) ---//
- hold >>>= here_bits;
- bits -= here_bits;
- //---//
- state.lens[state.have++] = here_val;
- }
- else {
- if (here_val === 16) {
- //=== NEEDBITS(here.bits + 2);
- n = here_bits + 2;
- while (bits < n) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- //--- DROPBITS(here.bits) ---//
- hold >>>= here_bits;
- bits -= here_bits;
- //---//
- if (state.have === 0) {
- strm.msg = 'invalid bit length repeat';
- state.mode = BAD;
- break;
- }
- len = state.lens[state.have - 1];
- copy = 3 + (hold & 0x03);//BITS(2);
- //--- DROPBITS(2) ---//
- hold >>>= 2;
- bits -= 2;
- //---//
- }
- else if (here_val === 17) {
- //=== NEEDBITS(here.bits + 3);
- n = here_bits + 3;
- while (bits < n) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- //--- DROPBITS(here.bits) ---//
- hold >>>= here_bits;
- bits -= here_bits;
- //---//
- len = 0;
- copy = 3 + (hold & 0x07);//BITS(3);
- //--- DROPBITS(3) ---//
- hold >>>= 3;
- bits -= 3;
- //---//
- }
- else {
- //=== NEEDBITS(here.bits + 7);
- n = here_bits + 7;
- while (bits < n) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- //--- DROPBITS(here.bits) ---//
- hold >>>= here_bits;
- bits -= here_bits;
- //---//
- len = 0;
- copy = 11 + (hold & 0x7f);//BITS(7);
- //--- DROPBITS(7) ---//
- hold >>>= 7;
- bits -= 7;
- //---//
- }
- if (state.have + copy > state.nlen + state.ndist) {
- strm.msg = 'invalid bit length repeat';
- state.mode = BAD;
- break;
- }
- while (copy--) {
- state.lens[state.have++] = len;
- }
- }
- }
-
- /* handle error breaks in while */
- if (state.mode === BAD) { break; }
-
- /* check for end-of-block code (better have one) */
- if (state.lens[256] === 0) {
- strm.msg = 'invalid code -- missing end-of-block';
- state.mode = BAD;
- break;
- }
-
- /* build code tables -- note: do not change the lenbits or distbits
- values here (9 and 6) without reading the comments in inftrees.h
- concerning the ENOUGH constants, which depend on those values */
- state.lenbits = 9;
-
- opts = { bits: state.lenbits };
- ret = inftrees(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);
- // We have separate tables & no pointers. 2 commented lines below not needed.
- // state.next_index = opts.table_index;
- state.lenbits = opts.bits;
- // state.lencode = state.next;
-
- if (ret) {
- strm.msg = 'invalid literal/lengths set';
- state.mode = BAD;
- break;
- }
-
- state.distbits = 6;
- //state.distcode.copy(state.codes);
- // Switch to use dynamic table
- state.distcode = state.distdyn;
- opts = { bits: state.distbits };
- ret = inftrees(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);
- // We have separate tables & no pointers. 2 commented lines below not needed.
- // state.next_index = opts.table_index;
- state.distbits = opts.bits;
- // state.distcode = state.next;
-
- if (ret) {
- strm.msg = 'invalid distances set';
- state.mode = BAD;
- break;
- }
- //Tracev((stderr, 'inflate: codes ok\n'));
- state.mode = LEN_;
- if (flush === Z_TREES) { break inf_leave; }
- /* falls through */
- case LEN_:
- state.mode = LEN;
- /* falls through */
- case LEN:
- if (have >= 6 && left >= 258) {
- //--- RESTORE() ---
- strm.next_out = put;
- strm.avail_out = left;
- strm.next_in = next;
- strm.avail_in = have;
- state.hold = hold;
- state.bits = bits;
- //---
- inffast(strm, _out);
- //--- LOAD() ---
- put = strm.next_out;
- output = strm.output;
- left = strm.avail_out;
- next = strm.next_in;
- input = strm.input;
- have = strm.avail_in;
- hold = state.hold;
- bits = state.bits;
- //---
-
- if (state.mode === TYPE) {
- state.back = -1;
- }
- break;
- }
- state.back = 0;
- for (;;) {
- here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/
- here_bits = here >>> 24;
- here_op = (here >>> 16) & 0xff;
- here_val = here & 0xffff;
-
- if (here_bits <= bits) { break; }
- //--- PULLBYTE() ---//
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- //---//
- }
- if (here_op && (here_op & 0xf0) === 0) {
- last_bits = here_bits;
- last_op = here_op;
- last_val = here_val;
- for (;;) {
- here = state.lencode[last_val +
- ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
- here_bits = here >>> 24;
- here_op = (here >>> 16) & 0xff;
- here_val = here & 0xffff;
-
- if ((last_bits + here_bits) <= bits) { break; }
- //--- PULLBYTE() ---//
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- //---//
- }
- //--- DROPBITS(last.bits) ---//
- hold >>>= last_bits;
- bits -= last_bits;
- //---//
- state.back += last_bits;
- }
- //--- DROPBITS(here.bits) ---//
- hold >>>= here_bits;
- bits -= here_bits;
- //---//
- state.back += here_bits;
- state.length = here_val;
- if (here_op === 0) {
- //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
- // "inflate: literal '%c'\n" :
- // "inflate: literal 0x%02x\n", here.val));
- state.mode = LIT;
- break;
- }
- if (here_op & 32) {
- //Tracevv((stderr, "inflate: end of block\n"));
- state.back = -1;
- state.mode = TYPE;
- break;
- }
- if (here_op & 64) {
- strm.msg = 'invalid literal/length code';
- state.mode = BAD;
- break;
- }
- state.extra = here_op & 15;
- state.mode = LENEXT;
- /* falls through */
- case LENEXT:
- if (state.extra) {
- //=== NEEDBITS(state.extra);
- n = state.extra;
- while (bits < n) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
- //--- DROPBITS(state.extra) ---//
- hold >>>= state.extra;
- bits -= state.extra;
- //---//
- state.back += state.extra;
- }
- //Tracevv((stderr, "inflate: length %u\n", state.length));
- state.was = state.length;
- state.mode = DIST;
- /* falls through */
- case DIST:
- for (;;) {
- here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/
- here_bits = here >>> 24;
- here_op = (here >>> 16) & 0xff;
- here_val = here & 0xffff;
-
- if ((here_bits) <= bits) { break; }
- //--- PULLBYTE() ---//
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- //---//
- }
- if ((here_op & 0xf0) === 0) {
- last_bits = here_bits;
- last_op = here_op;
- last_val = here_val;
- for (;;) {
- here = state.distcode[last_val +
- ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];
- here_bits = here >>> 24;
- here_op = (here >>> 16) & 0xff;
- here_val = here & 0xffff;
-
- if ((last_bits + here_bits) <= bits) { break; }
- //--- PULLBYTE() ---//
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- //---//
- }
- //--- DROPBITS(last.bits) ---//
- hold >>>= last_bits;
- bits -= last_bits;
- //---//
- state.back += last_bits;
- }
- //--- DROPBITS(here.bits) ---//
- hold >>>= here_bits;
- bits -= here_bits;
- //---//
- state.back += here_bits;
- if (here_op & 64) {
- strm.msg = 'invalid distance code';
- state.mode = BAD;
- break;
- }
- state.offset = here_val;
- state.extra = (here_op) & 15;
- state.mode = DISTEXT;
- /* falls through */
- case DISTEXT:
- if (state.extra) {
- //=== NEEDBITS(state.extra);
- n = state.extra;
- while (bits < n) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;
- //--- DROPBITS(state.extra) ---//
- hold >>>= state.extra;
- bits -= state.extra;
- //---//
- state.back += state.extra;
- }
-//#ifdef INFLATE_STRICT
- if (state.offset > state.dmax) {
- strm.msg = 'invalid distance too far back';
- state.mode = BAD;
- break;
- }
-//#endif
- //Tracevv((stderr, "inflate: distance %u\n", state.offset));
- state.mode = MATCH;
- /* falls through */
- case MATCH:
- if (left === 0) { break inf_leave; }
- copy = _out - left;
- if (state.offset > copy) { /* copy from window */
- copy = state.offset - copy;
- if (copy > state.whave) {
- if (state.sane) {
- strm.msg = 'invalid distance too far back';
- state.mode = BAD;
- break;
- }
-// (!) This block is disabled in zlib defaults,
-// don't enable it for binary compatibility
-//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
-// Trace((stderr, "inflate.c too far\n"));
-// copy -= state.whave;
-// if (copy > state.length) { copy = state.length; }
-// if (copy > left) { copy = left; }
-// left -= copy;
-// state.length -= copy;
-// do {
-// output[put++] = 0;
-// } while (--copy);
-// if (state.length === 0) { state.mode = LEN; }
-// break;
-//#endif
- }
- if (copy > state.wnext) {
- copy -= state.wnext;
- from = state.wsize - copy;
- }
- else {
- from = state.wnext - copy;
- }
- if (copy > state.length) { copy = state.length; }
- from_source = state.window;
- }
- else { /* copy from output */
- from_source = output;
- from = put - state.offset;
- copy = state.length;
- }
- if (copy > left) { copy = left; }
- left -= copy;
- state.length -= copy;
- do {
- output[put++] = from_source[from++];
- } while (--copy);
- if (state.length === 0) { state.mode = LEN; }
- break;
- case LIT:
- if (left === 0) { break inf_leave; }
- output[put++] = state.length;
- left--;
- state.mode = LEN;
- break;
- case CHECK:
- if (state.wrap) {
- //=== NEEDBITS(32);
- while (bits < 32) {
- if (have === 0) { break inf_leave; }
- have--;
- // Use '|' instead of '+' to make sure that result is signed
- hold |= input[next++] << bits;
- bits += 8;
- }
- //===//
- _out -= left;
- strm.total_out += _out;
- state.total += _out;
- if ((state.wrap & 4) && _out) {
- strm.adler = state.check =
- /*UPDATE_CHECK(state.check, put - _out, _out);*/
- (state.flags ? crc32_1(state.check, output, _out, put - _out) : adler32_1(state.check, output, _out, put - _out));
-
- }
- _out = left;
- // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too
- if ((state.wrap & 4) && (state.flags ? hold : zswap32(hold)) !== state.check) {
- strm.msg = 'incorrect data check';
- state.mode = BAD;
- break;
- }
- //=== INITBITS();
- hold = 0;
- bits = 0;
- //===//
- //Tracev((stderr, "inflate: check matches trailer\n"));
- }
- state.mode = LENGTH;
- /* falls through */
- case LENGTH:
- if (state.wrap && state.flags) {
- //=== NEEDBITS(32);
- while (bits < 32) {
- if (have === 0) { break inf_leave; }
- have--;
- hold += input[next++] << bits;
- bits += 8;
- }
- //===//
- if ((state.wrap & 4) && hold !== (state.total & 0xffffffff)) {
- strm.msg = 'incorrect length check';
- state.mode = BAD;
- break;
- }
- //=== INITBITS();
- hold = 0;
- bits = 0;
- //===//
- //Tracev((stderr, "inflate: length matches trailer\n"));
- }
- state.mode = DONE;
- /* falls through */
- case DONE:
- ret = Z_STREAM_END$1;
- break inf_leave;
- case BAD:
- ret = Z_DATA_ERROR$1;
- break inf_leave;
- case MEM:
- return Z_MEM_ERROR$1;
- case SYNC:
- /* falls through */
- default:
- return Z_STREAM_ERROR$1;
- }
- }
-
- // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave"
-
- /*
- Return from inflate(), updating the total counts and the check value.
- If there was no progress during the inflate() call, return a buffer
- error. Call updatewindow() to create and/or update the window state.
- Note: a memory error from inflate() is non-recoverable.
- */
-
- //--- RESTORE() ---
- strm.next_out = put;
- strm.avail_out = left;
- strm.next_in = next;
- strm.avail_in = have;
- state.hold = hold;
- state.bits = bits;
- //---
-
- if (state.wsize || (_out !== strm.avail_out && state.mode < BAD &&
- (state.mode < CHECK || flush !== Z_FINISH$1))) {
- if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) ;
- }
- _in -= strm.avail_in;
- _out -= strm.avail_out;
- strm.total_in += _in;
- strm.total_out += _out;
- state.total += _out;
- if ((state.wrap & 4) && _out) {
- strm.adler = state.check = /*UPDATE_CHECK(state.check, strm.next_out - _out, _out);*/
- (state.flags ? crc32_1(state.check, output, _out, strm.next_out - _out) : adler32_1(state.check, output, _out, strm.next_out - _out));
- }
- strm.data_type = state.bits + (state.last ? 64 : 0) +
- (state.mode === TYPE ? 128 : 0) +
- (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);
- if (((_in === 0 && _out === 0) || flush === Z_FINISH$1) && ret === Z_OK$1) {
- ret = Z_BUF_ERROR;
- }
- return ret;
-};
-
-
-const inflateEnd = (strm) => {
-
- if (inflateStateCheck(strm)) {
- return Z_STREAM_ERROR$1;
- }
-
- let state = strm.state;
- if (state.window) {
- state.window = null;
- }
- strm.state = null;
- return Z_OK$1;
-};
-
-
-const inflateGetHeader = (strm, head) => {
-
- /* check state */
- if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }
- const state = strm.state;
- if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR$1; }
-
- /* save header structure */
- state.head = head;
- head.done = false;
- return Z_OK$1;
-};
-
-
-const inflateSetDictionary = (strm, dictionary) => {
- const dictLength = dictionary.length;
-
- let state;
- let dictid;
- let ret;
-
- /* check state */
- if (inflateStateCheck(strm)) { return Z_STREAM_ERROR$1; }
- state = strm.state;
-
- if (state.wrap !== 0 && state.mode !== DICT) {
- return Z_STREAM_ERROR$1;
- }
-
- /* check for correct dictionary identifier */
- if (state.mode === DICT) {
- dictid = 1; /* adler32(0, null, 0)*/
- /* dictid = adler32(dictid, dictionary, dictLength); */
- dictid = adler32_1(dictid, dictionary, dictLength, 0);
- if (dictid !== state.check) {
- return Z_DATA_ERROR$1;
- }
- }
- /* copy dictionary to window using updatewindow(), which will amend the
- existing dictionary if appropriate */
- ret = updatewindow(strm, dictionary, dictLength, dictLength);
- if (ret) {
- state.mode = MEM;
- return Z_MEM_ERROR$1;
- }
- state.havedict = 1;
- // Tracev((stderr, "inflate: dictionary set\n"));
- return Z_OK$1;
-};
-
-
-var inflateReset_1 = inflateReset;
-var inflateReset2_1 = inflateReset2;
-var inflateResetKeep_1 = inflateResetKeep;
-var inflateInit_1 = inflateInit;
-var inflateInit2_1 = inflateInit2;
-var inflate_2$1 = inflate$2;
-var inflateEnd_1 = inflateEnd;
-var inflateGetHeader_1 = inflateGetHeader;
-var inflateSetDictionary_1 = inflateSetDictionary;
-var inflateInfo = 'pako inflate (from Nodeca project)';
-
-/* Not implemented
-module.exports.inflateCodesUsed = inflateCodesUsed;
-module.exports.inflateCopy = inflateCopy;
-module.exports.inflateGetDictionary = inflateGetDictionary;
-module.exports.inflateMark = inflateMark;
-module.exports.inflatePrime = inflatePrime;
-module.exports.inflateSync = inflateSync;
-module.exports.inflateSyncPoint = inflateSyncPoint;
-module.exports.inflateUndermine = inflateUndermine;
-module.exports.inflateValidate = inflateValidate;
-*/
-
-var inflate_1$2 = {
- inflateReset: inflateReset_1,
- inflateReset2: inflateReset2_1,
- inflateResetKeep: inflateResetKeep_1,
- inflateInit: inflateInit_1,
- inflateInit2: inflateInit2_1,
- inflate: inflate_2$1,
- inflateEnd: inflateEnd_1,
- inflateGetHeader: inflateGetHeader_1,
- inflateSetDictionary: inflateSetDictionary_1,
- inflateInfo: inflateInfo
-};
-
-// (C) 1995-2013 Jean-loup Gailly and Mark Adler
-// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
-//
-// This software is provided 'as-is', without any express or implied
-// warranty. In no event will the authors be held liable for any damages
-// arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose,
-// including commercial applications, and to alter it and redistribute it
-// freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not
-// claim that you wrote the original software. If you use this software
-// in a product, an acknowledgment in the product documentation would be
-// appreciated but is not required.
-// 2. Altered source versions must be plainly marked as such, and must not be
-// misrepresented as being the original software.
-// 3. This notice may not be removed or altered from any source distribution.
-
-function GZheader() {
- /* true if compressed data believed to be text */
- this.text = 0;
- /* modification time */
- this.time = 0;
- /* extra flags (not used when writing a gzip file) */
- this.xflags = 0;
- /* operating system */
- this.os = 0;
- /* pointer to extra field or Z_NULL if none */
- this.extra = null;
- /* extra field length (valid if extra != Z_NULL) */
- this.extra_len = 0; // Actually, we don't need it in JS,
- // but leave for few code modifications
-
- //
- // Setup limits is not necessary because in js we should not preallocate memory
- // for inflate use constant limit in 65536 bytes
- //
-
- /* space at extra (only when reading header) */
- // this.extra_max = 0;
- /* pointer to zero-terminated file name or Z_NULL */
- this.name = '';
- /* space at name (only when reading header) */
- // this.name_max = 0;
- /* pointer to zero-terminated comment or Z_NULL */
- this.comment = '';
- /* space at comment (only when reading header) */
- // this.comm_max = 0;
- /* true if there was or will be a header crc */
- this.hcrc = 0;
- /* true when done reading gzip header (not used when writing a gzip file) */
- this.done = false;
-}
-
-var gzheader = GZheader;
-
-const toString = Object.prototype.toString;
-
-/* Public constants ==========================================================*/
-/* ===========================================================================*/
-
-const {
- Z_NO_FLUSH, Z_FINISH,
- Z_OK, Z_STREAM_END, Z_NEED_DICT, Z_STREAM_ERROR, Z_DATA_ERROR, Z_MEM_ERROR
-} = constants$2;
-
-/* ===========================================================================*/
-
-
-/**
- * class Inflate
- *
- * Generic JS-style wrapper for zlib calls. If you don't need
- * streaming behaviour - use more simple functions: [[inflate]]
- * and [[inflateRaw]].
- **/
-
-/* internal
- * inflate.chunks -> Array
- *
- * Chunks of output data, if [[Inflate#onData]] not overridden.
- **/
-
-/**
- * Inflate.result -> Uint8Array|String
- *
- * Uncompressed result, generated by default [[Inflate#onData]]
- * and [[Inflate#onEnd]] handlers. Filled after you push last chunk
- * (call [[Inflate#push]] with `Z_FINISH` / `true` param).
- **/
-
-/**
- * Inflate.err -> Number
- *
- * Error code after inflate finished. 0 (Z_OK) on success.
- * Should be checked if broken data possible.
- **/
-
-/**
- * Inflate.msg -> String
- *
- * Error message, if [[Inflate.err]] != 0
- **/
-
-
-/**
- * new Inflate(options)
- * - options (Object): zlib inflate options.
- *
- * Creates new inflator instance with specified params. Throws exception
- * on bad params. Supported options:
- *
- * - `windowBits`
- * - `dictionary`
- *
- * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
- * for more information on these.
- *
- * Additional options, for internal needs:
- *
- * - `chunkSize` - size of generated data chunks (16K by default)
- * - `raw` (Boolean) - do raw inflate
- * - `to` (String) - if equal to 'string', then result will be converted
- * from utf8 to utf16 (javascript) string. When string output requested,
- * chunk length can differ from `chunkSize`, depending on content.
- *
- * By default, when no options set, autodetect deflate/gzip data format via
- * wrapper header.
- *
- * ##### Example:
- *
- * ```javascript
- * const pako = require('pako')
- * const chunk1 = new Uint8Array([1,2,3,4,5,6,7,8,9])
- * const chunk2 = new Uint8Array([10,11,12,13,14,15,16,17,18,19]);
- *
- * const inflate = new pako.Inflate({ level: 3});
- *
- * inflate.push(chunk1, false);
- * inflate.push(chunk2, true); // true -> last chunk
- *
- * if (inflate.err) { throw new Error(inflate.err); }
- *
- * console.log(inflate.result);
- * ```
- **/
-function Inflate$1(options) {
- this.options = common.assign({
- chunkSize: 1024 * 64,
- windowBits: 15,
- to: ''
- }, options || {});
-
- const opt = this.options;
-
- // Force window size for `raw` data, if not set directly,
- // because we have no header for autodetect.
- if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {
- opt.windowBits = -opt.windowBits;
- if (opt.windowBits === 0) { opt.windowBits = -15; }
- }
-
- // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate
- if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&
- !(options && options.windowBits)) {
- opt.windowBits += 32;
- }
-
- // Gzip header has no info about windows size, we can do autodetect only
- // for deflate. So, if window size not set, force it to max when gzip possible
- if ((opt.windowBits > 15) && (opt.windowBits < 48)) {
- // bit 3 (16) -> gzipped data
- // bit 4 (32) -> autodetect gzip/deflate
- if ((opt.windowBits & 15) === 0) {
- opt.windowBits |= 15;
- }
- }
-
- this.err = 0; // error code, if happens (0 = Z_OK)
- this.msg = ''; // error message
- this.ended = false; // used to avoid multiple onEnd() calls
- this.chunks = []; // chunks of compressed data
-
- this.strm = new zstream();
- this.strm.avail_out = 0;
-
- let status = inflate_1$2.inflateInit2(
- this.strm,
- opt.windowBits
- );
-
- if (status !== Z_OK) {
- throw new Error(messages[status]);
- }
-
- this.header = new gzheader();
-
- inflate_1$2.inflateGetHeader(this.strm, this.header);
-
- // Setup dictionary
- if (opt.dictionary) {
- // Convert data if needed
- if (typeof opt.dictionary === 'string') {
- opt.dictionary = strings.string2buf(opt.dictionary);
- } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') {
- opt.dictionary = new Uint8Array(opt.dictionary);
- }
- if (opt.raw) { //In raw mode we need to set the dictionary early
- status = inflate_1$2.inflateSetDictionary(this.strm, opt.dictionary);
- if (status !== Z_OK) {
- throw new Error(messages[status]);
- }
- }
- }
-}
-
-/**
- * Inflate#push(data[, flush_mode]) -> Boolean
- * - data (Uint8Array|ArrayBuffer): input data
- * - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE
- * flush modes. See constants. Skipped or `false` means Z_NO_FLUSH,
- * `true` means Z_FINISH.
- *
- * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with
- * new output chunks. Returns `true` on success. If end of stream detected,
- * [[Inflate#onEnd]] will be called.
- *
- * `flush_mode` is not needed for normal operation, because end of stream
- * detected automatically. You may try to use it for advanced things, but
- * this functionality was not tested.
- *
- * On fail call [[Inflate#onEnd]] with error code and return false.
- *
- * ##### Example
- *
- * ```javascript
- * push(chunk, false); // push one of data chunks
- * ...
- * push(chunk, true); // push last chunk
- * ```
- **/
-Inflate$1.prototype.push = function (data, flush_mode) {
- const strm = this.strm;
- const chunkSize = this.options.chunkSize;
- const dictionary = this.options.dictionary;
- let status, _flush_mode, last_avail_out;
-
- if (this.ended) return false;
-
- if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;
- else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH;
-
- // Convert data if needed
- if (toString.call(data) === '[object ArrayBuffer]') {
- strm.input = new Uint8Array(data);
- } else {
- strm.input = data;
- }
-
- strm.next_in = 0;
- strm.avail_in = strm.input.length;
-
- for (;;) {
- if (strm.avail_out === 0) {
- strm.output = new Uint8Array(chunkSize);
- strm.next_out = 0;
- strm.avail_out = chunkSize;
- }
-
- status = inflate_1$2.inflate(strm, _flush_mode);
-
- if (status === Z_NEED_DICT && dictionary) {
- status = inflate_1$2.inflateSetDictionary(strm, dictionary);
-
- if (status === Z_OK) {
- status = inflate_1$2.inflate(strm, _flush_mode);
- } else if (status === Z_DATA_ERROR) {
- // Replace code with more verbose
- status = Z_NEED_DICT;
- }
- }
-
- // Skip snyc markers if more data follows and not raw mode
- while (strm.avail_in > 0 &&
- status === Z_STREAM_END &&
- strm.state.wrap > 0 &&
- data[strm.next_in] !== 0)
- {
- inflate_1$2.inflateReset(strm);
- status = inflate_1$2.inflate(strm, _flush_mode);
- }
-
- switch (status) {
- case Z_STREAM_ERROR:
- case Z_DATA_ERROR:
- case Z_NEED_DICT:
- case Z_MEM_ERROR:
- this.onEnd(status);
- this.ended = true;
- return false;
- }
-
- // Remember real `avail_out` value, because we may patch out buffer content
- // to align utf8 strings boundaries.
- last_avail_out = strm.avail_out;
-
- if (strm.next_out) {
- if (strm.avail_out === 0 || status === Z_STREAM_END) {
-
- if (this.options.to === 'string') {
-
- let next_out_utf8 = strings.utf8border(strm.output, strm.next_out);
-
- let tail = strm.next_out - next_out_utf8;
- let utf8str = strings.buf2string(strm.output, next_out_utf8);
-
- // move tail & realign counters
- strm.next_out = tail;
- strm.avail_out = chunkSize - tail;
- if (tail) strm.output.set(strm.output.subarray(next_out_utf8, next_out_utf8 + tail), 0);
-
- this.onData(utf8str);
-
- } else {
- this.onData(strm.output.length === strm.next_out ? strm.output : strm.output.subarray(0, strm.next_out));
- }
- }
- }
-
- // Must repeat iteration if out buffer is full
- if (status === Z_OK && last_avail_out === 0) continue;
-
- // Finalize if end of stream reached.
- if (status === Z_STREAM_END) {
- status = inflate_1$2.inflateEnd(this.strm);
- this.onEnd(status);
- this.ended = true;
- return true;
- }
-
- if (strm.avail_in === 0) break;
- }
-
- return true;
-};
-
-
-/**
- * Inflate#onData(chunk) -> Void
- * - chunk (Uint8Array|String): output data. When string output requested,
- * each chunk will be string.
- *
- * By default, stores data blocks in `chunks[]` property and glue
- * those in `onEnd`. Override this handler, if you need another behaviour.
- **/
-Inflate$1.prototype.onData = function (chunk) {
- this.chunks.push(chunk);
-};
-
-
-/**
- * Inflate#onEnd(status) -> Void
- * - status (Number): inflate status. 0 (Z_OK) on success,
- * other if not.
- *
- * Called either after you tell inflate that the input stream is
- * complete (Z_FINISH). By default - join collected chunks,
- * free memory and fill `results` / `err` properties.
- **/
-Inflate$1.prototype.onEnd = function (status) {
- // On success - join
- if (status === Z_OK) {
- if (this.options.to === 'string') {
- this.result = this.chunks.join('');
- } else {
- this.result = common.flattenChunks(this.chunks);
- }
- }
- this.chunks = [];
- this.err = status;
- this.msg = this.strm.msg;
-};
-
-
-/**
- * inflate(data[, options]) -> Uint8Array|String
- * - data (Uint8Array|ArrayBuffer): input data to decompress.
- * - options (Object): zlib inflate options.
- *
- * Decompress `data` with inflate/ungzip and `options`. Autodetect
- * format via wrapper header by default. That's why we don't provide
- * separate `ungzip` method.
- *
- * Supported options are:
- *
- * - windowBits
- *
- * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
- * for more information.
- *
- * Sugar (options):
- *
- * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
- * negative windowBits implicitly.
- * - `to` (String) - if equal to 'string', then result will be converted
- * from utf8 to utf16 (javascript) string. When string output requested,
- * chunk length can differ from `chunkSize`, depending on content.
- *
- *
- * ##### Example:
- *
- * ```javascript
- * const pako = require('pako');
- * const input = pako.deflate(new Uint8Array([1,2,3,4,5,6,7,8,9]));
- * let output;
- *
- * try {
- * output = pako.inflate(input);
- * } catch (err) {
- * console.log(err);
- * }
- * ```
- **/
-function inflate$1(input, options) {
- const inflator = new Inflate$1(options);
-
- inflator.push(input);
-
- // That will never happens, if you don't cheat with options :)
- if (inflator.err) throw inflator.msg || messages[inflator.err];
-
- return inflator.result;
-}
-
-
-/**
- * inflateRaw(data[, options]) -> Uint8Array|String
- * - data (Uint8Array|ArrayBuffer): input data to decompress.
- * - options (Object): zlib inflate options.
- *
- * The same as [[inflate]], but creates raw data, without wrapper
- * (header and adler32 crc).
- **/
-function inflateRaw$1(input, options) {
- options = options || {};
- options.raw = true;
- return inflate$1(input, options);
-}
-
-
-/**
- * ungzip(data[, options]) -> Uint8Array|String
- * - data (Uint8Array|ArrayBuffer): input data to decompress.
- * - options (Object): zlib inflate options.
- *
- * Just shortcut to [[inflate]], because it autodetects format
- * by header.content. Done for convenience.
- **/
-
-
-var Inflate_1$1 = Inflate$1;
-var inflate_2 = inflate$1;
-var inflateRaw_1$1 = inflateRaw$1;
-var ungzip$1 = inflate$1;
-var constants = constants$2;
-
-var inflate_1$1 = {
- Inflate: Inflate_1$1,
- inflate: inflate_2,
- inflateRaw: inflateRaw_1$1,
- ungzip: ungzip$1,
- constants: constants
-};
-
-const { Deflate, deflate, deflateRaw, gzip } = deflate_1$1;
-
-const { Inflate, inflate, inflateRaw, ungzip } = inflate_1$1;
-
-
-
-var Deflate_1 = Deflate;
-var deflate_1 = deflate;
-var deflateRaw_1 = deflateRaw;
-var gzip_1 = gzip;
-var Inflate_1 = Inflate;
-var inflate_1 = inflate;
-var inflateRaw_1 = inflateRaw;
-var ungzip_1 = ungzip;
-var constants_1 = constants$2;
-
-var pako = {
- Deflate: Deflate_1,
- deflate: deflate_1,
- deflateRaw: deflateRaw_1,
- gzip: gzip_1,
- Inflate: Inflate_1,
- inflate: inflate_1,
- inflateRaw: inflateRaw_1,
- ungzip: ungzip_1,
- constants: constants_1
-};
-
-
-
-
-/***/ })
-
-}]);
-//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVuZG9ycy1ub2RlX21vZHVsZXNfZXNwLXdlYi10b29sc19kaXN0X2luc3RhbGwtZGlhbG9nX2pzLmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUMwQjtBQUNuQixlQUFlLHdDQUFHLFFBQVEsa0hBQWtILDhHQUE4RywwR0FBMEcsOEdBQThHLG9CQUFvQiwrQ0FBK0Msa0JBQWtCLG1CQUFtQiw4Q0FBOEMsMENBQTBDLGVBQWUsa0JBQWtCLGVBQWUsOEJBQThCLG1FQUFtRSxjQUFjLFlBQVksWUFBWSxXQUFXLE1BQU0sZ0JBQWdCLFlBQVksU0FBUyxVQUFVLGFBQWEsa0JBQWtCLFdBQVcsVUFBVSxlQUFlLGlDQUFpQyxZQUFZLFdBQVcsV0FBVyxzQkFBc0IsYUFBYSxZQUFZLHFCQUFxQixtQkFBbUIsa0JBQWtCLFdBQVcsMkJBQTJCLFFBQVEsa0JBQWtCLHFCQUFxQixzQkFBc0IsU0FBUywrRkFBK0YsbUJBQW1CLG1EQUFtRCxzQkFBc0IsWUFBWSxtR0FBbUcsa0JBQWtCLFVBQVUsK0JBQStCLHNDQUFzQyxrRUFBa0UscUJBQXFCLHlDQUF5QyxVQUFVLCtCQUErQixrRUFBa0UsbUJBQW1CLFVBQVUsNEZBQTRGLGlEQUFpRCxZQUFZLGdEQUFnRCw2R0FBNkcsOEVBQThFLDhHQUE4RyxrRkFBa0Ysb0JBQW9CLG1IQUFtSCx1RkFBdUYsMEhBQTBILDJGQUEyRixNQUFNLGtGQUFrRiwwQ0FBMEMseUNBQXlDLFlBQVksV0FBVyxxQ0FBcUMsVUFBVSxXQUFXLFdBQVcsb0NBQW9DLFdBQVcsTUFBTSx5QkFBeUIsMERBQTBELDBCQUEwQiwyREFBMkQsZ0JBQWdCLHlCQUF5QiwwREFBMEQsMEJBQTBCLDJEQUEyRCw4Q0FBOEMseURBQXlELDBEQUEwRCxzQkFBc0Isd0RBQXdELHFCQUFxQiwwREFBMEQsd0RBQXdELHVCQUF1Qix5QkFBeUIsb0NBQW9DLDBDQUEwQyxzQ0FBc0MsS0FBSyxTQUFTLHdC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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQix5Q0FBUTtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixJQUFJLFlBQVk7QUFDakMsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaURBQWlELDREQUFTO0FBQzFEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVCxLQUFLLElBQUksaUJBQWlCO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSyxJQUFJLGlCQUFpQjtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNPO0FBQ1AsK0NBQStDLCtCQUErQjtBQUM5RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ087QUFDUCw2Q0FBNkMsK0JBQStCO0FBQzVFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0EsK0NBQStDLCtCQUErQjtBQUM5RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7QUN4SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLCtLQUErSztBQUMvTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLCtEQUErRDtBQUM3RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxrRUFBa0U7QUFDaEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsV0FBVztBQUNsRCx3Q0FBd0MsWUFBWTtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwREFBMEQsZ0RBQWdEO0FBQzFHO0FBQ0E7QUFDQTtBQUNBLHlEQUF5RCxnREFBZ0Q7QUFDekc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLHFIQUFxSDtBQUNySTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0Isd0lBQXdJO0FBQ3hKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7OztBQ3pZQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkMsMkJBQTJCO0FBQ3hFO0FBQ0EsNkNBQTZDLDJCQUEyQjtBQUN4RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxREFBcUQ7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7OztBQy9STztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQLG9DQUFvQyxvQkFBb0I7QUFDeEQ7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7QUNkTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7Ozs7Ozs7Ozs7Ozs7OztBQ1hPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7QUNoQk87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4REFBOEQ7QUFDOUQ7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtEQUFrRDtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkM7QUFDM0M7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNPO0FBQ1A7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNuTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNtRDtBQUNlO0FBQ2M7QUFDaEYsNEJBQTRCLG9EQUFTO0FBQ3JDO0FB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R0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxvREFBb0Q7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUEsZUFBZTtBQUNmO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsd0JBQXdCO0FBQ3hCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsNkJBQTZCOztBQUU3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHVCQUF1Qjs7QUFFdkIsdUNBQXVDOztBQUV2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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Q0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0JBQW9COztBQUVwQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHNCQUFzQjs7QUFFdEI7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4REFBOEQ7QUFDOUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkJBQTJCO0FBQzNCLDJCQUEyQjs7QUFFM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUIsOEJBQThCO0FBQzlCLDhCQUE4QjtBQUM5Qiw4QkFBOEI7QUFDOUIsOEJBQThCO0FBQzlCO0FBQ0EsOEJBQThCO0FBQzlCO0FBQ0EsOEJBQThCO0FBQzlCLDhCQUE4QjtBQUM5Qiw4QkFBOEI7QUFDOUI7QUFDQSw4QkFBOEI7QUFDOUIsOEJBQThCO0FBQzlCLDhCQUE4QjtBQUM5Qiw4QkFBOEI7QUFDOUIsOEJBQThCO0FBQzlCLDhCQUE4QjtBQUM5Qiw4QkFBOEI7QUFDOUIsOEJBQThCO0FBQzlCLDhCQUE4QjtBQUM5QjtBQUNBLDhCQUE4QjtBQUM5Qiw4QkFBOEI7QUFDOUIsOEJBQThCO0FBQzlCOzs7QUFHQSxxQkFBcUI7O0FBRXJCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx1Q0FBdUM7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCO0FBQ0EsNEJBQTRCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCO0FBQzlCO0FBQ0EsOEJBQThCO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7O0FBRVo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRDtBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtB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QUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBOztBQUVBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxRQUFRLHFDQUFxQzs7QUFFN0MsUUFBUSx1Q0FBdUM7Ozs7QUFJL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRXlPIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9jaGVja2JveC9pbnRlcm5hbC9jaGVja2JveC1zdHlsZXMuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9jaGVja2JveC9pbnRlcm5hbC9jaGVja2JveC5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL2VsZXZhdGlvbi9lbGV2YXRpb24uanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9lbGV2YXRpb24vaW50ZXJuYWwvZWxldmF0aW9uLXN0eWxlcy5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL2VsZXZhdGlvbi9pbnRlcm5hbC9lbGV2YXRpb24uanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9maWVsZC9maWxsZWQtZmllbGQuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9maWVsZC9pbnRlcm5hbC9maWVsZC5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL2ZpZWxkL2ludGVybmFsL2ZpbGxlZC1maWVsZC5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL2ZpZWxkL2ludGVybmFsL2ZpbGxlZC1zdHlsZXMuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9maWVsZC9pbnRlcm5hbC9zaGFyZWQtc3R5bGVzLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL0BtYXRlcmlhbC93ZWIvaWNvbmJ1dHRvbi9pbnRlcm5hbC9pY29uLWJ1dHRvbi5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL2ljb25idXR0b24vaW50ZXJuYWwvc2hhcmVkLXN0eWxlcy5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL2ljb25idXR0b24vaW50ZXJuYWwvc3RhbmRhcmQtc3R5bGVzLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL0BtYXRlcmlhbC93ZWIvaW50ZXJuYWwvY29udHJvbGxlci9pcy1ydGwuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9pbnRlcm5hbC9jb250cm9sbGVyL3N0cmluZy1jb252ZXJ0ZXIuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9sYWJzL2JlaGF2aW9ycy9jb25zdHJhaW50LXZhbGlkYXRpb24uanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9sYWJzL2JlaGF2aW9ycy9mb3JtLWFzc29jaWF0ZWQuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9sYWJzL2JlaGF2aW9ycy9vbi1yZXBvcnQtdmFsaWRpdHkuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9sYWJzL2JlaGF2aW9ycy92YWxpZGF0b3JzL2NoZWNrYm94LXZhbGlkYXRvci5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL2xhYnMvYmVoYXZpb3JzL3ZhbGlkYXRvcnMvc2VsZWN0LXZhbGlkYXRvci5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL2xhYnMvYmVoYXZpb3JzL3ZhbGlkYXRvcnMvdGV4dC1maWVsZC12YWxpZGF0b3IuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9sYWJzL2JlaGF2aW9ycy92YWxpZGF0b3JzL3ZhbGlkYXRvci5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL2xhYnMvaXRlbS9pbnRlcm5hbC9pdGVtLXN0eWxlcy5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL2xhYnMvaXRlbS9pbnRlcm5hbC9pdGVtLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL0BtYXRlcmlhbC93ZWIvbGFicy9pdGVtL2l0ZW0uanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9saXN0L2ludGVybmFsL2xpc3QtY29udHJvbGxlci5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL2xpc3QvaW50ZXJuYWwvbGlzdC1uYXZpZ2F0aW9uLWhlbHBlcnMuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9saXN0L2ludGVybmFsL2xpc3Qtc3R5bGVzLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL0BtYXRlcmlhbC93ZWIvbGlzdC9pbnRlcm5hbC9saXN0LmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL0BtYXRlcmlhbC93ZWIvbGlzdC9pbnRlcm5hbC9saXN0aXRlbS9saXN0LWl0ZW0tc3R5bGVzLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL0BtYXRlcmlhbC93ZWIvbGlzdC9pbnRlcm5hbC9saXN0aXRlbS9saXN0LWl0ZW0uanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9tZW51L2ludGVybmFsL2NvbnRyb2xsZXJzL21lbnVJdGVtQ29udHJvbGxlci5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL21lbnUvaW50ZXJuYWwvY29udHJvbGxlcnMvc2hhcmVkLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL0BtYXRlcmlhbC93ZWIvbWVudS9pbnRlcm5hbC9jb250cm9sbGVycy9zdXJmYWNlUG9zaXRpb25Db250cm9sbGVyLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL0BtYXRlcmlhbC93ZWIvbWVudS9pbnRlcm5hbC9jb250cm9sbGVycy90eXBlYWhlYWRDb250cm9sbGVyLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL0BtYXRlcmlhbC93ZWIvbWVudS9pbnRlcm5hbC9tZW51LXN0eWxlcy5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL21lbnUvaW50ZXJuYWwvbWVudS5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL21lbnUvaW50ZXJuYWwvbWVudWl0ZW0vbWVudS1pdGVtLXN0eWxlcy5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL21lbnUvbWVudS5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL3Byb2dyZXNzL2ludGVybmFsL2NpcmN1bGFyLXByb2dyZXNzLXN0eWxlcy5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL3Byb2dyZXNzL2ludGVybmFsL2NpcmN1bGFyLXByb2dyZXNzLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL0BtYXRlcmlhbC93ZWIvcHJvZ3Jlc3MvaW50ZXJuYWwvcHJvZ3Jlc3MuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9zZWxlY3QvaW50ZXJuYWwvZmlsbGVkLXNlbGVjdC1zdHlsZXMuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9zZWxlY3QvaW50ZXJuYWwvZmlsbGVkLXNlbGVjdC5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL3NlbGVjdC9pbnRlcm5hbC9zZWxlY3QuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9zZWxlY3QvaW50ZXJuYWwvc2VsZWN0b3B0aW9uL3NlbGVjdC1vcHRpb24uanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9zZWxlY3QvaW50ZXJuYWwvc2VsZWN0b3B0aW9uL3NlbGVjdE9wdGlvbkNvbnRyb2xsZXIuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi9zZWxlY3QvaW50ZXJuYWwvc2hhcmVkLXN0eWxlcy5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL3NlbGVjdC9pbnRlcm5hbC9zaGFyZWQuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvQG1hdGVyaWFsL3dlYi90ZXh0ZmllbGQvaW50ZXJuYWwvZmlsbGVkLXN0eWxlcy5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL3RleHRmaWVsZC9pbnRlcm5hbC9maWxsZWQtdGV4dC1maWVsZC5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9AbWF0ZXJpYWwvd2ViL3RleHRmaWVsZC9pbnRlcm5hbC9zaGFyZWQtc3R5bGVzLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL0BtYXRlcmlhbC93ZWIvdGV4dGZpZWxkL2ludGVybmFsL3RleHQtZmllbGQuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvYXRvYi1saXRlL2F0b2ItYnJvd3Nlci5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3Atd2ViLXRvb2xzL2Rpc3QvY29tcG9uZW50cy9ldy1jaGVja2JveC5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3Atd2ViLXRvb2xzL2Rpc3QvY29tcG9uZW50cy9ldy1jaXJjdWxhci1wcm9ncmVzcy5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3Atd2ViLXRvb2xzL2Rpc3QvY29tcG9uZW50cy9ldy1kaXZpZGVyLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2VzcC13ZWItdG9vbHMvZGlzdC9jb21wb25lbnRzL2V3LWZpbGxlZC1zZWxlY3QuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvZXNwLXdlYi10b29scy9kaXN0L2NvbXBvbmVudHMvZXctZmlsbGVkLXRleHQtZmllbGQuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvZXNwLXdlYi10b29scy9kaXN0L2NvbXBvbmVudHMvZXctaWNvbi1idXR0b24uanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvZXNwLXdlYi10b29scy9kaXN0L2NvbXBvbmVudHMvZXctbGlzdC1pdGVtLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2VzcC13ZWItdG9vbHMvZGlzdC9jb21wb25lbnRzL2V3LWxpc3QuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvZXNwLXdlYi10b29scy9kaXN0L2NvbXBvbmVudHMvZXctc2VsZWN0LW9wdGlvbi5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3Atd2ViLXRvb2xzL2Rpc3QvY29tcG9uZW50cy9ld3QtY29uc29sZS5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3Atd2ViLXRvb2xzL2Rpc3QvY29tcG9uZW50cy9zdmcuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvZXNwLXdlYi10b29scy9kaXN0L2ZsYXNoLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2VzcC13ZWItdG9vbHMvZGlzdC9pbnN0YWxsLWRpYWxvZy5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3Atd2ViLXRvb2xzL2Rpc3QvcGFnZXMvZXd0LXBhZ2UtbWVzc2FnZS5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3Atd2ViLXRvb2xzL2Rpc3QvcGFnZXMvZXd0LXBhZ2UtcHJvZ3Jlc3MuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvZXNwLXdlYi10b29scy9kaXN0L3V0aWwvY29uc29sZS1jb2xvci5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3Atd2ViLXRvb2xzL2Rpc3QvdXRpbC9maWxlLWRvd25sb2FkLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2VzcC13ZWItdG9vbHMvZGlzdC91dGlsL2ZpcmUtZXZlbnQuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvZXNwLXdlYi10b29scy9kaXN0L3V0aWwvbGluZS1icmVhay10cmFuc2Zvcm1lci5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3Atd2ViLXRvb2xzL2Rpc3QvdXRpbC9tYW5pZmVzdC5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3Atd2ViLXRvb2xzL2Rpc3QvdXRpbC9yZXNldC5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3Atd2ViLXRvb2xzL2Rpc3QvdXRpbC9zbGVlcC5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3Atd2ViLXRvb2xzL2Rpc3QvdXRpbC90aW1lc3RhbXAtdHJhbnNmb3JtZXIuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvZXNwLXdlYi10b29scy9kaXN0L3ZlcnNpb24uanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvZXNwdG9vbC1qcy9saWIvZXNwbG9hZGVyLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2VzcHRvb2wtanMvbGliL2luZGV4LmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2VzcHRvb2wtanMvbGliL3Jlc2V0LmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2VzcHRvb2wtanMvbGliL3N0dWJGbGFzaGVyLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2VzcHRvb2wtanMvbGliL3RhcmdldHMvcm9tLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2VzcHRvb2wtanMvbGliL3R5cGVzL2Vycm9yLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2VzcHRvb2wtanMvbGliL3V0aWwuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvZXNwdG9vbC1qcy9saWIvd2Vic2VyaWFsLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2ltcHJvdi13aWZpLXNlcmlhbC1zZGsvZGlzdC9jb25zdC5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9pbXByb3Ytd2lmaS1zZXJpYWwtc2RrL2Rpc3Qvc2VyaWFsLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2ltcHJvdi13aWZpLXNlcmlhbC1zZGsvZGlzdC91dGlsL2hleC1mb3JtYXR0ZXIuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvaW1wcm92LXdpZmktc2VyaWFsLXNkay9kaXN0L3V0aWwvc2xlZXAuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvaW1wcm92LXdpZmktc2VyaWFsLXNkay9kaXN0L3V0aWwvdG8taGV4LmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2xpdC1odG1sL2RldmVsb3BtZW50L2RpcmVjdGl2ZS1oZWxwZXJzLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2xpdC1odG1sL2RldmVsb3BtZW50L2RpcmVjdGl2ZXMvbGl2ZS5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9saXQtaHRtbC9kZXZlbG9wbWVudC9kaXJlY3RpdmVzL3N0eWxlLW1hcC5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9saXQtaHRtbC9kZXZlbG9wbWVudC9zdGF0aWMuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvbGl0L2RpcmVjdGl2ZXMvbGl2ZS5qcyIsIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9saXQvZGlyZWN0aXZlcy9zdHlsZS1tYXAuanMiLCJ3ZWJwYWNrOi8vVGFjdGlsaXR5IFdlYiBJbnN0YWxsZXIvLi9ub2RlX21vZHVsZXMvbGl0L3N0YXRpYy1odG1sLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL3Bha28vZGlzdC9wYWtvLmVzbS5tanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjQgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuLy8gR2VuZXJhdGVkIHN0eWxlc2hlZXQgZm9yIC4vY2hlY2tib3gvaW50ZXJuYWwvY2hlY2tib3gtc3R5bGVzLmNzcy5cbmltcG9ydCB7IGNzcyB9IGZyb20gJ2xpdCc7XG5leHBvcnQgY29uc3Qgc3R5bGVzID0gY3NzIGA6aG9zdHtib3JkZXItc3RhcnQtc3RhcnQtcmFkaXVzOnZhcigtLW1kLWNoZWNrYm94LWNvbnRhaW5lci1zaGFwZS1zdGFydC1zdGFydCwgdmFyKC0tbWQtY2hlY2tib3gtY29udGFpbmVyLXNoYXBlLCAycHgpKTtib3JkZXItc3RhcnQtZW5kLXJhZGl1czp2YXIoLS1tZC1jaGVja2JveC1jb250YWluZXItc2hhcGUtc3RhcnQtZW5kLCB2YXIoLS1tZC1jaGVja2JveC1jb250YWluZXItc2hhcGUsIDJweCkpO2JvcmRlci1lbmQtZW5kLXJhZGl1czp2YXIoLS1tZC1jaGVja2JveC1jb250YWluZXItc2hhcGUtZW5kLWVuZCwgdmFyKC0tbWQtY2hlY2tib3gtY29udGFpbmVyLXNoYXBlLCAycHgpKTtib3JkZXItZW5kLXN0YXJ0LXJhZGl1czp2YXIoLS1tZC1jaGVja2JveC1jb250YWluZXItc2hhcGUtZW5kLXN0YXJ0LCB2YXIoLS1tZC1jaGVja2JveC1jb250YWluZXItc2hhcGUsIDJweCkpO2Rpc3BsYXk6aW5saW5lLWZsZXg7aGVpZ2h0OnZhcigtLW1kLWNoZWNrYm94LWNvbnRhaW5lci1zaXplLCAxOHB4KTtwb3NpdGlvbjpyZWxhdGl2ZTt2ZXJ0aWNhbC1hbGlnbjp0b3A7d2lkdGg6dmFyKC0tbWQtY2hlY2tib3gtY29udGFpbmVyLXNpemUsIDE4cHgpOy13ZWJraXQtdGFwLWhpZ2hsaWdodC1jb2xvcjpyZ2JhKDAsMCwwLDApO2N1cnNvcjpwb2ludGVyfTpob3N0KFtkaXNhYmxlZF0pe2N1cnNvcjpkZWZhdWx0fTpob3N0KFt0b3VjaC10YXJnZXQ9d3JhcHBlcl0pe21hcmdpbjptYXgoMHB4LCg0OHB4IC0gdmFyKC0tbWQtY2hlY2tib3gtY29udGFpbmVyLXNpemUsIDE4cHgpKS8yKX1tZC1mb2N1cy1yaW5ne2hlaWdodDo0NHB4O2luc2V0OnVuc2V0O3dpZHRoOjQ0cHh9aW5wdXR7YXBwZWFyYW5jZTpub25lO2hlaWdodDo0OHB4O21hcmdpbjowO29wYWNpdHk6MDtvdXRsaW5lOm5vbmU7cG9zaXRpb246YWJzb2x1dGU7d2lkdGg6NDhweDt6LWluZGV4OjE7Y3Vyc29yOmluaGVyaXR9Omhvc3QoW3RvdWNoLXRhcmdldD1ub25lXSkgaW5wdXR7aGVpZ2h0OjEwMCU7d2lkdGg6MTAwJX0uY29udGFpbmVye2JvcmRlci1yYWRpdXM6aW5oZXJpdDtkaXNwbGF5OmZsZXg7aGVpZ2h0OjEwMCU7cGxhY2UtY29udGVudDpjZW50ZXI7cGxhY2UtaXRlbXM6Y2VudGVyO3Bvc2l0aW9uOnJlbGF0aXZlO3dpZHRoOjEwMCV9Lm91dGxpbmUsLmJhY2tncm91bmQsLmljb257aW5zZXQ6MDtwb3NpdGlvbjphYnNvbHV0ZX0ub3V0bGluZSwuYmFja2dyb3VuZHtib3JkZXItcmFkaXVzOmluaGVyaXR9Lm91dGxpbmV7Ym9yZGVyLWNvbG9yOnZhcigtLW1kLWNoZWNrYm94LW91dGxpbmUtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTtib3JkZXItc3R5bGU6c29saWQ7Ym9yZGVyLXdpZHRoOnZhcigtLW1kLWNoZWNrYm94LW91dGxpbmUtd2lkdGgsIDJweCk7Ym94LXNpemluZzpib3JkZXItYm94fS5iYWNrZ3JvdW5ke2JhY2tncm91bmQtY29sb3I6dmFyKC0tbWQtY2hlY2tib3gtc2VsZWN0ZWQtY29udGFpbmVyLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItcHJpbWFyeSwgIzY3NTBhNCkpfS5iYWNrZ3JvdW5kLC5pY29ue29wYWNpdHk6MDt0cmFuc2l0aW9uLWR1cmF0aW9uOjE1MG1zLDUwbXM7dHJhbnNpdGlvbi1wcm9wZXJ0eTp0cmFuc2Zvcm0sb3BhY2l0eTt0cmFuc2l0aW9uLXRpbWluZy1mdW5jdGlvbjpjdWJpYy1iZXppZXIoMC4zLCAwLCAwLjgsIDAuMTUpLGxpbmVhcjt0cmFuc2Zvcm06c2NhbGUoMC42KX06d2hlcmUoLnNlbGVjdGVkKSA6aXMoLmJhY2tncm91bmQsLmljb24pe29wYWNpdHk6MTt0cmFuc2l0aW9uLWR1cmF0aW9uOjM1MG1zLDUwbXM7dHJhbnNpdGlvbi10aW1pbmctZnVuY3Rpb246Y3ViaWMtYmV6aWVyKDAuMDUsIDAuNywgMC4xLCAxKSxsaW5lYXI7dHJhbnNmb3JtOnNjYWxlKDEpfW1kLXJpcHBsZXtib3JkZXItcmFkaXVzOnZhcigtLW1kLWNoZWNrYm94LXN0YXRlLWxheWVyLXNoYXBlLCB2YXIoLS1tZC1zeXMtc2hhcGUtY29ybmVyLWZ1bGwsIDk5OTlweCkpO2hlaWdodDp2YXIoLS1tZC1jaGVja2JveC1zdGF0ZS1sYXllci1zaXplLCA0MHB4KTtpbnNldDp1bnNldDt3aWR0aDp2YXIoLS1tZC1jaGVja2JveC1zdGF0ZS1sYXllci1zaXplLCA0MHB4KTstLW1kLXJpcHBsZS1ob3Zlci1jb2xvcjogdmFyKC0tbWQtY2hlY2tib3gtaG92ZXItc3RhdGUtbGF5ZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1tZC1yaXBwbGUtaG92ZXItb3BhY2l0eTogdmFyKC0tbWQtY2hlY2tib3gtaG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eSwgMC4wOCk7LS1tZC1yaXBwbGUtcHJlc3NlZC1jb2xvcjogdmFyKC0tbWQtY2hlY2tib3gtcHJlc3NlZC1zdGF0ZS1sYXllci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKTstLW1kLXJpcHBsZS1wcmVzc2VkLW9wYWNpdHk6IHZhcigtLW1kLWNoZWNrYm94LXByZXNzZWQtc3RhdGUtbGF5ZXItb3BhY2l0eSwgMC4xMil9LnNlbGVjdGVkIG1kLXJpcHBsZXstLW1kLXJpcHBsZS1ob3Zlci1jb2xvcjogdmFyKC0tbWQtY2hlY2tib3gtc2VsZWN0ZWQtaG92ZXItc3RhdGUtbGF5ZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1wcmltYXJ5LCAjNjc1MGE0KSk7LS1tZC1yaXBwbGUtaG92ZXItb3BhY2l0eTogdmFyKC0tbWQtY2hlY2tib3gtc2VsZWN0ZWQtaG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eSwgMC4wOCk7LS1tZC1yaXBwbGUtcHJlc3NlZC1jb2xvcjogdmFyKC0tbWQtY2hlY2tib3gtc2VsZWN0ZWQtcHJlc3NlZC1zdGF0ZS1sYXllci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLW1kLXJpcHBsZS1wcmVzc2VkLW9wYWNpdHk6IHZhcigtLW1kLWNoZWNrYm94LXNlbGVjdGVkLXByZXNzZWQtc3RhdGUtbGF5ZXItb3BhY2l0eSwgMC4xMil9Lmljb257ZmlsbDp2YXIoLS1tZC1jaGVja2JveC1zZWxlY3RlZC1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tcHJpbWFyeSwgI2ZmZikpO2hlaWdodDp2YXIoLS1tZC1jaGVja2JveC1pY29uLXNpemUsIDE4cHgpO3dpZHRoOnZhcigtLW1kLWNoZWNrYm94LWljb24tc2l6ZSwgMThweCl9Lm1hcmsuc2hvcnR7aGVpZ2h0OjJweDt0cmFuc2l0aW9uLXByb3BlcnR5OnRyYW5zZm9ybSxoZWlnaHQ7d2lkdGg6MnB4fS5tYXJrLmxvbmd7aGVpZ2h0OjJweDt0cmFuc2l0aW9uLXByb3BlcnR5OnRyYW5zZm9ybSx3aWR0aDt3aWR0aDoxMHB4fS5tYXJre2FuaW1hdGlvbi1kdXJhdGlvbjoxNTBtczthbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOmN1YmljLWJlemllcigwLjMsIDAsIDAuOCwgMC4xNSk7dHJhbnNpdGlvbi1kdXJhdGlvbjoxNTBtczt0cmFuc2l0aW9uLXRpbWluZy1mdW5jdGlvbjpjdWJpYy1iZXppZXIoMC4zLCAwLCAwLjgsIDAuMTUpfS5zZWxlY3RlZCAubWFya3thbmltYXRpb24tZHVyYXRpb246MzUwbXM7YW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjpjdWJpYy1iZXppZXIoMC4wNSwgMC43LCAwLjEsIDEpO3RyYW5zaXRpb24tZHVyYXRpb246MzUwbXM7dHJhbnNpdGlvbi10aW1pbmctZnVuY3Rpb246Y3ViaWMtYmV6aWVyKDAuMDUsIDAuNywgMC4xLCAxKX0uY2hlY2tlZCAubWFyaywucHJldi1jaGVja2VkLnVuc2VsZWN0ZWQgLm1hcmt7dHJhbnNmb3JtOnNjYWxlWSgtMSkgdHJhbnNsYXRlKDdweCwgLTE0cHgpIHJvdGF0ZSg0NWRlZyl9LmNoZWNrZWQgLm1hcmsuc2hvcnQsLnByZXYtY2hlY2tlZC51bnNlbGVjdGVkIC5tYXJrLnNob3J0e2hlaWdodDo1LjY1Njg1NDI0OTVweH0uY2hlY2tlZCAubWFyay5sb25nLC5wcmV2LWNoZWNrZWQudW5zZWxlY3RlZCAubWFyay5sb25ne3dpZHRoOjExLjMxMzcwODQ5OXB4fS5pbmRldGVybWluYXRlIC5tYXJrLC5wcmV2LWluZGV0ZXJtaW5hdGUudW5zZWxlY3RlZCAubWFya3t0cmFuc2Zvcm06c2NhbGVZKC0xKSB0cmFuc2xhdGUoNHB4LCAtMTBweCkgcm90YXRlKDBkZWcpfS5wcmV2LXVuc2VsZWN0ZWQgLm1hcmt7dHJhbnNpdGlvbi1wcm9wZXJ0eTpub25lfS5wcmV2LXVuc2VsZWN0ZWQuY2hlY2tlZCAubWFyay5sb25ne2FuaW1hdGlvbi1uYW1lOnByZXYtdW5zZWxlY3RlZC10by1jaGVja2VkfUBrZXlmcmFtZXMgcHJldi11bnNlbGVjdGVkLXRvLWNoZWNrZWR7ZnJvbXt3aWR0aDowfX06d2hlcmUoOmhvdmVyKSAub3V0bGluZXtib3JkZXItY29sb3I6dmFyKC0tbWQtY2hlY2tib3gtaG92ZXItb3V0bGluZS1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTtib3JkZXItd2lkdGg6dmFyKC0tbWQtY2hlY2tib3gtaG92ZXItb3V0bGluZS13aWR0aCwgMnB4KX06d2hlcmUoOmhvdmVyKSAuYmFja2dyb3VuZHtiYWNrZ3JvdW5kOnZhcigtLW1kLWNoZWNrYm94LXNlbGVjdGVkLWhvdmVyLWNvbnRhaW5lci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKX06d2hlcmUoOmhvdmVyKSAuaWNvbntmaWxsOnZhcigtLW1kLWNoZWNrYm94LXNlbGVjdGVkLWhvdmVyLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1wcmltYXJ5LCAjZmZmKSl9OndoZXJlKDpmb2N1cy13aXRoaW4pIC5vdXRsaW5le2JvcmRlci1jb2xvcjp2YXIoLS1tZC1jaGVja2JveC1mb2N1cy1vdXRsaW5lLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpO2JvcmRlci13aWR0aDp2YXIoLS1tZC1jaGVja2JveC1mb2N1cy1vdXRsaW5lLXdpZHRoLCAycHgpfTp3aGVyZSg6Zm9jdXMtd2l0aGluKSAuYmFja2dyb3VuZHtiYWNrZ3JvdW5kOnZhcigtLW1kLWNoZWNrYm94LXNlbGVjdGVkLWZvY3VzLWNvbnRhaW5lci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKX06d2hlcmUoOmZvY3VzLXdpdGhpbikgLmljb257ZmlsbDp2YXIoLS1tZC1jaGVja2JveC1zZWxlY3RlZC1mb2N1cy1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tcHJpbWFyeSwgI2ZmZikpfTp3aGVyZSg6YWN0aXZlKSAub3V0bGluZXtib3JkZXItY29sb3I6dmFyKC0tbWQtY2hlY2tib3gtcHJlc3NlZC1vdXRsaW5lLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpO2JvcmRlci13aWR0aDp2YXIoLS1tZC1jaGVja2JveC1wcmVzc2VkLW91dGxpbmUtd2lkdGgsIDJweCl9OndoZXJlKDphY3RpdmUpIC5iYWNrZ3JvdW5ke2JhY2tncm91bmQ6dmFyKC0tbWQtY2hlY2tib3gtc2VsZWN0ZWQtcHJlc3NlZC1jb250YWluZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1wcmltYXJ5LCAjNjc1MGE0KSl9OndoZXJlKDphY3RpdmUpIC5pY29ue2ZpbGw6dmFyKC0tbWQtY2hlY2tib3gtc2VsZWN0ZWQtcHJlc3NlZC1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tcHJpbWFyeSwgI2ZmZikpfTp3aGVyZSguZGlzYWJsZWQsLnByZXYtZGlzYWJsZWQpIDppcyguYmFja2dyb3VuZCwuaWNvbiwubWFyayl7YW5pbWF0aW9uLWR1cmF0aW9uOjBzO3RyYW5zaXRpb24tZHVyYXRpb246MHN9OndoZXJlKC5kaXNhYmxlZCkgLm91dGxpbmV7Ym9yZGVyLWNvbG9yOnZhcigtLW1kLWNoZWNrYm94LWRpc2FibGVkLW91dGxpbmUtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7Ym9yZGVyLXdpZHRoOnZhcigtLW1kLWNoZWNrYm94LWRpc2FibGVkLW91dGxpbmUtd2lkdGgsIDJweCk7b3BhY2l0eTp2YXIoLS1tZC1jaGVja2JveC1kaXNhYmxlZC1jb250YWluZXItb3BhY2l0eSwgMC4zOCl9OndoZXJlKC5zZWxlY3RlZC5kaXNhYmxlZCkgLm91dGxpbmV7dmlzaWJpbGl0eTpoaWRkZW59OndoZXJlKC5zZWxlY3RlZC5kaXNhYmxlZCkgLmJhY2tncm91bmR7YmFja2dyb3VuZDp2YXIoLS1tZC1jaGVja2JveC1zZWxlY3RlZC1kaXNhYmxlZC1jb250YWluZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7b3BhY2l0eTp2YXIoLS1tZC1jaGVja2JveC1zZWxlY3RlZC1kaXNhYmxlZC1jb250YWluZXItb3BhY2l0eSwgMC4zOCl9OndoZXJlKC5kaXNhYmxlZCkgLmljb257ZmlsbDp2YXIoLS1tZC1jaGVja2JveC1zZWxlY3RlZC1kaXNhYmxlZC1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itc3VyZmFjZSwgI2ZlZjdmZikpfUBtZWRpYShmb3JjZWQtY29sb3JzOiBhY3RpdmUpey5iYWNrZ3JvdW5ke2JhY2tncm91bmQtY29sb3I6Q2FudmFzVGV4dH0uc2VsZWN0ZWQuZGlzYWJsZWQgLmJhY2tncm91bmR7YmFja2dyb3VuZC1jb2xvcjpHcmF5VGV4dDtvcGFjaXR5OjF9Lm91dGxpbmV7Ym9yZGVyLWNvbG9yOkNhbnZhc1RleHR9LmRpc2FibGVkIC5vdXRsaW5le2JvcmRlci1jb2xvcjpHcmF5VGV4dDtvcGFjaXR5OjF9Lmljb257ZmlsbDpDYW52YXN9fVxuYDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWNoZWNrYm94LXN0eWxlcy5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBfX2RlY29yYXRlIH0gZnJvbSBcInRzbGliXCI7XG5pbXBvcnQgJy4uLy4uL2ZvY3VzL21kLWZvY3VzLXJpbmcuanMnO1xuaW1wb3J0ICcuLi8uLi9yaXBwbGUvcmlwcGxlLmpzJztcbmltcG9ydCB7IGh0bWwsIGlzU2VydmVyLCBMaXRFbGVtZW50LCBub3RoaW5nIH0gZnJvbSAnbGl0JztcbmltcG9ydCB7IHByb3BlcnR5LCBxdWVyeSwgc3RhdGUgfSBmcm9tICdsaXQvZGVjb3JhdG9ycy5qcyc7XG5pbXBvcnQgeyBjbGFzc01hcCB9IGZyb20gJ2xpdC9kaXJlY3RpdmVzL2NsYXNzLW1hcC5qcyc7XG5pbXBvcnQgeyBtaXhpbkRlbGVnYXRlc0FyaWEgfSBmcm9tICcuLi8uLi9pbnRlcm5hbC9hcmlhL2RlbGVnYXRlLmpzJztcbmltcG9ydCB7IGRpc3BhdGNoQWN0aXZhdGlvbkNsaWNrLCBpc0FjdGl2YXRpb25DbGljaywgfSBmcm9tICcuLi8uLi9pbnRlcm5hbC9ldmVudHMvZm9ybS1sYWJlbC1hY3RpdmF0aW9uLmpzJztcbmltcG9ydCB7IHJlZGlzcGF0Y2hFdmVudCB9IGZyb20gJy4uLy4uL2ludGVybmFsL2V2ZW50cy9yZWRpc3BhdGNoLWV2ZW50LmpzJztcbmltcG9ydCB7IGNyZWF0ZVZhbGlkYXRvciwgZ2V0VmFsaWRpdHlBbmNob3IsIG1peGluQ29uc3RyYWludFZhbGlkYXRpb24sIH0gZnJvbSAnLi4vLi4vbGFicy9iZWhhdmlvcnMvY29uc3RyYWludC12YWxpZGF0aW9uLmpzJztcbmltcG9ydCB7IG1peGluRWxlbWVudEludGVybmFscyB9IGZyb20gJy4uLy4uL2xhYnMvYmVoYXZpb3JzL2VsZW1lbnQtaW50ZXJuYWxzLmpzJztcbmltcG9ydCB7IGdldEZvcm1TdGF0ZSwgZ2V0Rm9ybVZhbHVlLCBtaXhpbkZvcm1Bc3NvY2lhdGVkLCB9IGZyb20gJy4uLy4uL2xhYnMvYmVoYXZpb3JzL2Zvcm0tYXNzb2NpYXRlZC5qcyc7XG5pbXBvcnQgeyBDaGVja2JveFZhbGlkYXRvciB9IGZyb20gJy4uLy4uL2xhYnMvYmVoYXZpb3JzL3ZhbGlkYXRvcnMvY2hlY2tib3gtdmFsaWRhdG9yLmpzJztcbi8vIFNlcGFyYXRlIHZhcmlhYmxlIG5lZWRlZCBmb3IgY2xvc3VyZS5cbmNvbnN0IGNoZWNrYm94QmFzZUNsYXNzID0gbWl4aW5EZWxlZ2F0ZXNBcmlhKG1peGluQ29uc3RyYWludFZhbGlkYXRpb24obWl4aW5Gb3JtQXNzb2NpYXRlZChtaXhpbkVsZW1lbnRJbnRlcm5hbHMoTGl0RWxlbWVudCkpKSk7XG4vKipcbiAqIEEgY2hlY2tib3ggY29tcG9uZW50LlxuICpcbiAqXG4gKiBAZmlyZXMgY2hhbmdlIHtFdmVudH0gVGhlIG5hdGl2ZSBgY2hhbmdlYCBldmVudCBvblxuICogW2A8aW5wdXQ+YF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0hUTUxFbGVtZW50L2NoYW5nZV9ldmVudClcbiAqIC0tYnViYmxlc1xuICogQGZpcmVzIGlucHV0IHtJbnB1dEV2ZW50fSBUaGUgbmF0aXZlIGBpbnB1dGAgZXZlbnQgb25cbiAqIFtgPGlucHV0PmBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9IVE1MRWxlbWVudC9pbnB1dF9ldmVudClcbiAqIC0tYnViYmxlcyAtLWNvbXBvc2VkXG4gKi9cbmV4cG9ydCBjbGFzcyBDaGVja2JveCBleHRlbmRzIGNoZWNrYm94QmFzZUNsYXNzIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdoZXRoZXIgb3Igbm90IHRoZSBjaGVja2JveCBpcyBzZWxlY3RlZC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuY2hlY2tlZCA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogV2hldGhlciBvciBub3QgdGhlIGNoZWNrYm94IGlzIGluZGV0ZXJtaW5hdGUuXG4gICAgICAgICAqXG4gICAgICAgICAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0hUTUwvRWxlbWVudC9pbnB1dC9jaGVja2JveCNpbmRldGVybWluYXRlX3N0YXRlX2NoZWNrYm94ZXNcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaW5kZXRlcm1pbmF0ZSA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogV2hlbiB0cnVlLCByZXF1aXJlIHRoZSBjaGVja2JveCB0byBiZSBzZWxlY3RlZCB3aGVuIHBhcnRpY2lwYXRpbmcgaW5cbiAgICAgICAgICogZm9ybSBzdWJtaXNzaW9uLlxuICAgICAgICAgKlxuICAgICAgICAgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVE1ML0VsZW1lbnQvaW5wdXQvY2hlY2tib3gjdmFsaWRhdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5yZXF1aXJlZCA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIHZhbHVlIG9mIHRoZSBjaGVja2JveCB0aGF0IGlzIHN1Ym1pdHRlZCB3aXRoIGEgZm9ybSB3aGVuIHNlbGVjdGVkLlxuICAgICAgICAgKlxuICAgICAgICAgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVE1ML0VsZW1lbnQvaW5wdXQvY2hlY2tib3gjdmFsdWVcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMudmFsdWUgPSAnb24nO1xuICAgICAgICB0aGlzLnByZXZDaGVja2VkID0gZmFsc2U7XG4gICAgICAgIHRoaXMucHJldkRpc2FibGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMucHJldkluZGV0ZXJtaW5hdGUgPSBmYWxzZTtcbiAgICAgICAgaWYgKCFpc1NlcnZlcikge1xuICAgICAgICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghaXNBY3RpdmF0aW9uQ2xpY2soZXZlbnQpIHx8ICF0aGlzLmlucHV0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5mb2N1cygpO1xuICAgICAgICAgICAgICAgIGRpc3BhdGNoQWN0aXZhdGlvbkNsaWNrKHRoaXMuaW5wdXQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdXBkYXRlKGNoYW5nZWQpIHtcbiAgICAgICAgaWYgKGNoYW5nZWQuaGFzKCdjaGVja2VkJykgfHxcbiAgICAgICAgICAgIGNoYW5nZWQuaGFzKCdkaXNhYmxlZCcpIHx8XG4gICAgICAgICAgICBjaGFuZ2VkLmhhcygnaW5kZXRlcm1pbmF0ZScpKSB7XG4gICAgICAgICAgICB0aGlzLnByZXZDaGVja2VkID0gY2hhbmdlZC5nZXQoJ2NoZWNrZWQnKSA/PyB0aGlzLmNoZWNrZWQ7XG4gICAgICAgICAgICB0aGlzLnByZXZEaXNhYmxlZCA9IGNoYW5nZWQuZ2V0KCdkaXNhYmxlZCcpID8/IHRoaXMuZGlzYWJsZWQ7XG4gICAgICAgICAgICB0aGlzLnByZXZJbmRldGVybWluYXRlID1cbiAgICAgICAgICAgICAgICBjaGFuZ2VkLmdldCgnaW5kZXRlcm1pbmF0ZScpID8/IHRoaXMuaW5kZXRlcm1pbmF0ZTtcbiAgICAgICAgfVxuICAgICAgICBzdXBlci51cGRhdGUoY2hhbmdlZCk7XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgY29uc3QgcHJldk5vbmUgPSAhdGhpcy5wcmV2Q2hlY2tlZCAmJiAhdGhpcy5wcmV2SW5kZXRlcm1pbmF0ZTtcbiAgICAgICAgY29uc3QgcHJldkNoZWNrZWQgPSB0aGlzLnByZXZDaGVja2VkICYmICF0aGlzLnByZXZJbmRldGVybWluYXRlO1xuICAgICAgICBjb25zdCBwcmV2SW5kZXRlcm1pbmF0ZSA9IHRoaXMucHJldkluZGV0ZXJtaW5hdGU7XG4gICAgICAgIGNvbnN0IGlzQ2hlY2tlZCA9IHRoaXMuY2hlY2tlZCAmJiAhdGhpcy5pbmRldGVybWluYXRlO1xuICAgICAgICBjb25zdCBpc0luZGV0ZXJtaW5hdGUgPSB0aGlzLmluZGV0ZXJtaW5hdGU7XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lckNsYXNzZXMgPSBjbGFzc01hcCh7XG4gICAgICAgICAgICAnZGlzYWJsZWQnOiB0aGlzLmRpc2FibGVkLFxuICAgICAgICAgICAgJ3NlbGVjdGVkJzogaXNDaGVja2VkIHx8IGlzSW5kZXRlcm1pbmF0ZSxcbiAgICAgICAgICAgICd1bnNlbGVjdGVkJzogIWlzQ2hlY2tlZCAmJiAhaXNJbmRldGVybWluYXRlLFxuICAgICAgICAgICAgJ2NoZWNrZWQnOiBpc0NoZWNrZWQsXG4gICAgICAgICAgICAnaW5kZXRlcm1pbmF0ZSc6IGlzSW5kZXRlcm1pbmF0ZSxcbiAgICAgICAgICAgICdwcmV2LXVuc2VsZWN0ZWQnOiBwcmV2Tm9uZSxcbiAgICAgICAgICAgICdwcmV2LWNoZWNrZWQnOiBwcmV2Q2hlY2tlZCxcbiAgICAgICAgICAgICdwcmV2LWluZGV0ZXJtaW5hdGUnOiBwcmV2SW5kZXRlcm1pbmF0ZSxcbiAgICAgICAgICAgICdwcmV2LWRpc2FibGVkJzogdGhpcy5wcmV2RGlzYWJsZWQsXG4gICAgICAgIH0pO1xuICAgICAgICAvLyBOZWVkZWQgZm9yIGNsb3N1cmUgY29uZm9ybWFuY2VcbiAgICAgICAgY29uc3QgeyBhcmlhTGFiZWwsIGFyaWFJbnZhbGlkIH0gPSB0aGlzO1xuICAgICAgICAvLyBOb3RlOiA8aW5wdXQ+IG5lZWRzIHRvIGJlIHJlbmRlcmVkIGJlZm9yZSB0aGUgPHN2Zz4gZm9yXG4gICAgICAgIC8vIGZvcm0ucmVwb3J0VmFsaWRpdHkoKSB0byB3b3JrIGluIENocm9tZS5cbiAgICAgICAgcmV0dXJuIGh0bWwgYFxuICAgICAgPGRpdiBjbGFzcz1cImNvbnRhaW5lciAke2NvbnRhaW5lckNsYXNzZXN9XCI+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgICAgaWQ9XCJpbnB1dFwiXG4gICAgICAgICAgYXJpYS1jaGVja2VkPSR7aXNJbmRldGVybWluYXRlID8gJ21peGVkJyA6IG5vdGhpbmd9XG4gICAgICAgICAgYXJpYS1sYWJlbD0ke2FyaWFMYWJlbCB8fCBub3RoaW5nfVxuICAgICAgICAgIGFyaWEtaW52YWxpZD0ke2FyaWFJbnZhbGlkIHx8IG5vdGhpbmd9XG4gICAgICAgICAgP2Rpc2FibGVkPSR7dGhpcy5kaXNhYmxlZH1cbiAgICAgICAgICA/cmVxdWlyZWQ9JHt0aGlzLnJlcXVpcmVkfVxuICAgICAgICAgIC5pbmRldGVybWluYXRlPSR7dGhpcy5pbmRldGVybWluYXRlfVxuICAgICAgICAgIC5jaGVja2VkPSR7dGhpcy5jaGVja2VkfVxuICAgICAgICAgIEBpbnB1dD0ke3RoaXMuaGFuZGxlSW5wdXR9XG4gICAgICAgICAgQGNoYW5nZT0ke3RoaXMuaGFuZGxlQ2hhbmdlfSAvPlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJvdXRsaW5lXCI+PC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJiYWNrZ3JvdW5kXCI+PC9kaXY+XG4gICAgICAgIDxtZC1mb2N1cy1yaW5nIHBhcnQ9XCJmb2N1cy1yaW5nXCIgZm9yPVwiaW5wdXRcIj48L21kLWZvY3VzLXJpbmc+XG4gICAgICAgIDxtZC1yaXBwbGUgZm9yPVwiaW5wdXRcIiA/ZGlzYWJsZWQ9JHt0aGlzLmRpc2FibGVkfT48L21kLXJpcHBsZT5cbiAgICAgICAgPHN2ZyBjbGFzcz1cImljb25cIiB2aWV3Qm94PVwiMCAwIDE4IDE4XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+XG4gICAgICAgICAgPHJlY3QgY2xhc3M9XCJtYXJrIHNob3J0XCIgLz5cbiAgICAgICAgICA8cmVjdCBjbGFzcz1cIm1hcmsgbG9uZ1wiIC8+XG4gICAgICAgIDwvc3ZnPlxuICAgICAgPC9kaXY+XG4gICAgYDtcbiAgICB9XG4gICAgaGFuZGxlSW5wdXQoZXZlbnQpIHtcbiAgICAgICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0O1xuICAgICAgICB0aGlzLmNoZWNrZWQgPSB0YXJnZXQuY2hlY2tlZDtcbiAgICAgICAgdGhpcy5pbmRldGVybWluYXRlID0gdGFyZ2V0LmluZGV0ZXJtaW5hdGU7XG4gICAgICAgIC8vIDxpbnB1dD4gJ2lucHV0JyBldmVudCBidWJibGVzIGFuZCBpcyBjb21wb3NlZCwgZG9uJ3QgcmUtZGlzcGF0Y2ggaXQuXG4gICAgfVxuICAgIGhhbmRsZUNoYW5nZShldmVudCkge1xuICAgICAgICAvLyA8aW5wdXQ+ICdjaGFuZ2UnIGV2ZW50IGlzIG5vdCBjb21wb3NlZCwgcmUtZGlzcGF0Y2ggaXQuXG4gICAgICAgIHJlZGlzcGF0Y2hFdmVudCh0aGlzLCBldmVudCk7XG4gICAgfVxuICAgIFtnZXRGb3JtVmFsdWVdKCkge1xuICAgICAgICBpZiAoIXRoaXMuY2hlY2tlZCB8fCB0aGlzLmluZGV0ZXJtaW5hdGUpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICAgIH1cbiAgICBbZ2V0Rm9ybVN0YXRlXSgpIHtcbiAgICAgICAgcmV0dXJuIFN0cmluZyh0aGlzLmNoZWNrZWQpO1xuICAgIH1cbiAgICBmb3JtUmVzZXRDYWxsYmFjaygpIHtcbiAgICAgICAgLy8gVGhlIGNoZWNrZWQgcHJvcGVydHkgZG9lcyBub3QgcmVmbGVjdCwgc28gdGhlIG9yaWdpbmFsIGF0dHJpYnV0ZSBzZXQgYnlcbiAgICAgICAgLy8gdGhlIHVzZXIgaXMgdXNlZCB0byBkZXRlcm1pbmUgdGhlIGRlZmF1bHQgdmFsdWUuXG4gICAgICAgIHRoaXMuY2hlY2tlZCA9IHRoaXMuaGFzQXR0cmlidXRlKCdjaGVja2VkJyk7XG4gICAgfVxuICAgIGZvcm1TdGF0ZVJlc3RvcmVDYWxsYmFjayhzdGF0ZSkge1xuICAgICAgICB0aGlzLmNoZWNrZWQgPSBzdGF0ZSA9PT0gJ3RydWUnO1xuICAgIH1cbiAgICBbY3JlYXRlVmFsaWRhdG9yXSgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDaGVja2JveFZhbGlkYXRvcigoKSA9PiB0aGlzKTtcbiAgICB9XG4gICAgW2dldFZhbGlkaXR5QW5jaG9yXSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaW5wdXQ7XG4gICAgfVxufVxuLyoqIEBub2NvbGxhcHNlICovXG5DaGVja2JveC5zaGFkb3dSb290T3B0aW9ucyA9IHtcbiAgICAuLi5MaXRFbGVtZW50LnNoYWRvd1Jvb3RPcHRpb25zLFxuICAgIGRlbGVnYXRlc0ZvY3VzOiB0cnVlLFxufTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiB9KVxuXSwgQ2hlY2tib3gucHJvdG90eXBlLCBcImNoZWNrZWRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiB9KVxuXSwgQ2hlY2tib3gucHJvdG90eXBlLCBcImluZGV0ZXJtaW5hdGVcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiB9KVxuXSwgQ2hlY2tib3gucHJvdG90eXBlLCBcInJlcXVpcmVkXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSgpXG5dLCBDaGVja2JveC5wcm90b3R5cGUsIFwidmFsdWVcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHN0YXRlKClcbl0sIENoZWNrYm94LnByb3RvdHlwZSwgXCJwcmV2Q2hlY2tlZFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgc3RhdGUoKVxuXSwgQ2hlY2tib3gucHJvdG90eXBlLCBcInByZXZEaXNhYmxlZFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgc3RhdGUoKVxuXSwgQ2hlY2tib3gucHJvdG90eXBlLCBcInByZXZJbmRldGVybWluYXRlXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBxdWVyeSgnaW5wdXQnKVxuXSwgQ2hlY2tib3gucHJvdG90eXBlLCBcImlucHV0XCIsIHZvaWQgMCk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jaGVja2JveC5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMiBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBfX2RlY29yYXRlIH0gZnJvbSBcInRzbGliXCI7XG5pbXBvcnQgeyBjdXN0b21FbGVtZW50IH0gZnJvbSAnbGl0L2RlY29yYXRvcnMuanMnO1xuaW1wb3J0IHsgRWxldmF0aW9uIH0gZnJvbSAnLi9pbnRlcm5hbC9lbGV2YXRpb24uanMnO1xuaW1wb3J0IHsgc3R5bGVzIH0gZnJvbSAnLi9pbnRlcm5hbC9lbGV2YXRpb24tc3R5bGVzLmpzJztcbi8qKlxuICogVGhlIGA8bWQtZWxldmF0aW9uPmAgY3VzdG9tIGVsZW1lbnQgd2l0aCBkZWZhdWx0IHN0eWxlcy5cbiAqXG4gKiBFbGV2YXRpb24gaXMgdGhlIHJlbGF0aXZlIGRpc3RhbmNlIGJldHdlZW4gdHdvIHN1cmZhY2VzIGFsb25nIHRoZSB6LWF4aXMuXG4gKlxuICogQGZpbmFsXG4gKiBAc3VwcHJlc3Mge3Zpc2liaWxpdHl9XG4gKi9cbmxldCBNZEVsZXZhdGlvbiA9IGNsYXNzIE1kRWxldmF0aW9uIGV4dGVuZHMgRWxldmF0aW9uIHtcbn07XG5NZEVsZXZhdGlvbi5zdHlsZXMgPSBbc3R5bGVzXTtcbk1kRWxldmF0aW9uID0gX19kZWNvcmF0ZShbXG4gICAgY3VzdG9tRWxlbWVudCgnbWQtZWxldmF0aW9uJylcbl0sIE1kRWxldmF0aW9uKTtcbmV4cG9ydCB7IE1kRWxldmF0aW9uIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1lbGV2YXRpb24uanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjQgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuLy8gR2VuZXJhdGVkIHN0eWxlc2hlZXQgZm9yIC4vZWxldmF0aW9uL2ludGVybmFsL2VsZXZhdGlvbi1zdHlsZXMuY3NzLlxuaW1wb3J0IHsgY3NzIH0gZnJvbSAnbGl0JztcbmV4cG9ydCBjb25zdCBzdHlsZXMgPSBjc3MgYDpob3N0LC5zaGFkb3csLnNoYWRvdzo6YmVmb3JlLC5zaGFkb3c6OmFmdGVye2JvcmRlci1yYWRpdXM6aW5oZXJpdDtpbnNldDowO3Bvc2l0aW9uOmFic29sdXRlO3RyYW5zaXRpb24tZHVyYXRpb246aW5oZXJpdDt0cmFuc2l0aW9uLXByb3BlcnR5OmluaGVyaXQ7dHJhbnNpdGlvbi10aW1pbmctZnVuY3Rpb246aW5oZXJpdH06aG9zdHtkaXNwbGF5OmZsZXg7cG9pbnRlci1ldmVudHM6bm9uZTt0cmFuc2l0aW9uLXByb3BlcnR5OmJveC1zaGFkb3csb3BhY2l0eX0uc2hhZG93OjpiZWZvcmUsLnNoYWRvdzo6YWZ0ZXJ7Y29udGVudDpcIlwiO3RyYW5zaXRpb24tcHJvcGVydHk6Ym94LXNoYWRvdyxvcGFjaXR5Oy0tX2xldmVsOiB2YXIoLS1tZC1lbGV2YXRpb24tbGV2ZWwsIDApOy0tX3NoYWRvdy1jb2xvcjogdmFyKC0tbWQtZWxldmF0aW9uLXNoYWRvdy1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXNoYWRvdywgIzAwMCkpfS5zaGFkb3c6OmJlZm9yZXtib3gtc2hhZG93OjBweCBjYWxjKDFweCooY2xhbXAoMCx2YXIoLS1fbGV2ZWwpLDEpICsgY2xhbXAoMCx2YXIoLS1fbGV2ZWwpIC0gMywxKSArIDIqY2xhbXAoMCx2YXIoLS1fbGV2ZWwpIC0gNCwxKSkpIGNhbGMoMXB4KigyKmNsYW1wKDAsdmFyKC0tX2xldmVsKSwxKSArIGNsYW1wKDAsdmFyKC0tX2xldmVsKSAtIDIsMSkgKyBjbGFtcCgwLHZhcigtLV9sZXZlbCkgLSA0LDEpKSkgMHB4IHZhcigtLV9zaGFkb3ctY29sb3IpO29wYWNpdHk6LjN9LnNoYWRvdzo6YWZ0ZXJ7Ym94LXNoYWRvdzowcHggY2FsYygxcHgqKGNsYW1wKDAsdmFyKC0tX2xldmVsKSwxKSArIGNsYW1wKDAsdmFyKC0tX2xldmVsKSAtIDEsMSkgKyAyKmNsYW1wKDAsdmFyKC0tX2xldmVsKSAtIDIsMykpKSBjYWxjKDFweCooMypjbGFtcCgwLHZhcigtLV9sZXZlbCksMikgKyAyKmNsYW1wKDAsdmFyKC0tX2xldmVsKSAtIDIsMykpKSBjYWxjKDFweCooY2xhbXAoMCx2YXIoLS1fbGV2ZWwpLDQpICsgMipjbGFtcCgwLHZhcigtLV9sZXZlbCkgLSA0LDEpKSkgdmFyKC0tX3NoYWRvdy1jb2xvcik7b3BhY2l0eTouMTV9XG5gO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZWxldmF0aW9uLXN0eWxlcy5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMiBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBodG1sLCBMaXRFbGVtZW50IH0gZnJvbSAnbGl0Jztcbi8qKlxuICogQSBjb21wb25lbnQgZm9yIGVsZXZhdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIEVsZXZhdGlvbiBleHRlbmRzIExpdEVsZW1lbnQge1xuICAgIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgICAgICBzdXBlci5jb25uZWN0ZWRDYWxsYmFjaygpO1xuICAgICAgICAvLyBOZWVkZWQgZm9yIFZvaWNlT3Zlciwgd2hpY2ggd2lsbCBjcmVhdGUgYSBcImdyb3VwXCIgaWYgdGhlIGVsZW1lbnQgaXMgYVxuICAgICAgICAvLyBzaWJsaW5nIHRvIG90aGVyIGNvbnRlbnQuXG4gICAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsICd0cnVlJyk7XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYDxzcGFuIGNsYXNzPVwic2hhZG93XCI+PC9zcGFuPmA7XG4gICAgfVxufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZWxldmF0aW9uLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbmltcG9ydCB7IF9fZGVjb3JhdGUgfSBmcm9tIFwidHNsaWJcIjtcbmltcG9ydCB7IGN1c3RvbUVsZW1lbnQgfSBmcm9tICdsaXQvZGVjb3JhdG9ycy5qcyc7XG5pbXBvcnQgeyBGaWxsZWRGaWVsZCB9IGZyb20gJy4vaW50ZXJuYWwvZmlsbGVkLWZpZWxkLmpzJztcbmltcG9ydCB7IHN0eWxlcyBhcyBmaWxsZWRTdHlsZXMgfSBmcm9tICcuL2ludGVybmFsL2ZpbGxlZC1zdHlsZXMuanMnO1xuaW1wb3J0IHsgc3R5bGVzIGFzIHNoYXJlZFN0eWxlcyB9IGZyb20gJy4vaW50ZXJuYWwvc2hhcmVkLXN0eWxlcy5qcyc7XG4vKipcbiAqIFRPRE8oYi8yMjg1MjU3OTcpOiBhZGQgZG9jc1xuICogQGZpbmFsXG4gKiBAc3VwcHJlc3Mge3Zpc2liaWxpdHl9XG4gKi9cbmxldCBNZEZpbGxlZEZpZWxkID0gY2xhc3MgTWRGaWxsZWRGaWVsZCBleHRlbmRzIEZpbGxlZEZpZWxkIHtcbn07XG5NZEZpbGxlZEZpZWxkLnN0eWxlcyA9IFtzaGFyZWRTdHlsZXMsIGZpbGxlZFN0eWxlc107XG5NZEZpbGxlZEZpZWxkID0gX19kZWNvcmF0ZShbXG4gICAgY3VzdG9tRWxlbWVudCgnbWQtZmlsbGVkLWZpZWxkJylcbl0sIE1kRmlsbGVkRmllbGQpO1xuZXhwb3J0IHsgTWRGaWxsZWRGaWVsZCB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZmlsbGVkLWZpZWxkLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbmltcG9ydCB7IF9fZGVjb3JhdGUgfSBmcm9tIFwidHNsaWJcIjtcbmltcG9ydCB7IGh0bWwsIExpdEVsZW1lbnQsIG5vdGhpbmcsIHJlbmRlciwgfSBmcm9tICdsaXQnO1xuaW1wb3J0IHsgcHJvcGVydHksIHF1ZXJ5LCBxdWVyeUFzc2lnbmVkRWxlbWVudHMsIHN0YXRlIH0gZnJvbSAnbGl0L2RlY29yYXRvcnMuanMnO1xuaW1wb3J0IHsgY2xhc3NNYXAgfSBmcm9tICdsaXQvZGlyZWN0aXZlcy9jbGFzcy1tYXAuanMnO1xuaW1wb3J0IHsgRUFTSU5HIH0gZnJvbSAnLi4vLi4vaW50ZXJuYWwvbW90aW9uL2FuaW1hdGlvbi5qcyc7XG4vKipcbiAqIEEgZmllbGQgY29tcG9uZW50LlxuICovXG5leHBvcnQgY2xhc3MgRmllbGQgZXh0ZW5kcyBMaXRFbGVtZW50IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgdGhpcy5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVycm9yID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZm9jdXNlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmxhYmVsID0gJyc7XG4gICAgICAgIHRoaXMubm9Bc3RlcmlzayA9IGZhbHNlO1xuICAgICAgICB0aGlzLnBvcHVsYXRlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlcXVpcmVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMucmVzaXphYmxlID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc3VwcG9ydGluZ1RleHQgPSAnJztcbiAgICAgICAgdGhpcy5lcnJvclRleHQgPSAnJztcbiAgICAgICAgdGhpcy5jb3VudCA9IC0xO1xuICAgICAgICB0aGlzLm1heCA9IC0xO1xuICAgICAgICAvKipcbiAgICAgICAgICogV2hldGhlciBvciBub3QgdGhlIGZpZWxkIGhhcyBsZWFkaW5nIGNvbnRlbnQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmhhc1N0YXJ0ID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXaGV0aGVyIG9yIG5vdCB0aGUgZmllbGQgaGFzIHRyYWlsaW5nIGNvbnRlbnQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmhhc0VuZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLmlzQW5pbWF0aW5nID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXaGVuIHNldCB0byB0cnVlLCB0aGUgZXJyb3IgdGV4dCdzIGByb2xlPVwiYWxlcnRcImAgd2lsbCBiZSByZW1vdmVkLCB0aGVuXG4gICAgICAgICAqIHJlLWFkZGVkIGFmdGVyIGFuIGFuaW1hdGlvbiBmcmFtZS4gVGhpcyB3aWxsIHJlLWFubm91bmNlIGFuIGVycm9yIG1lc3NhZ2VcbiAgICAgICAgICogdG8gc2NyZWVuIHJlYWRlcnMuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnJlZnJlc2hFcnJvckFsZXJ0ID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZGlzYWJsZVRyYW5zaXRpb25zID0gZmFsc2U7XG4gICAgfVxuICAgIGdldCBjb3VudGVyVGV4dCgpIHtcbiAgICAgICAgLy8gQ291bnQgYW5kIG1heCBhcmUgdHlwZWQgYXMgbnVtYmVyLCBidXQgY2FuIGJlIHNldCB0byBudWxsIHdoZW4gTGl0IHJlbW92ZXNcbiAgICAgICAgLy8gdGhlaXIgYXR0cmlidXRlcy4gVGhlc2UgZ2V0dGVycyBjb2VyY2UgYmFjayB0byBhIG51bWJlciBmb3IgY2FsY3VsYXRpb25zLlxuICAgICAgICBjb25zdCBjb3VudEFzTnVtYmVyID0gdGhpcy5jb3VudCA/PyAtMTtcbiAgICAgICAgY29uc3QgbWF4QXNOdW1iZXIgPSB0aGlzLm1heCA/PyAtMTtcbiAgICAgICAgLy8gQ291bnRlciBkb2VzIG5vdCBzaG93IGlmIGNvdW50IGlzIG5lZ2F0aXZlLCBvciBtYXggaXMgbmVnYXRpdmUgb3IgMC5cbiAgICAgICAgaWYgKGNvdW50QXNOdW1iZXIgPCAwIHx8IG1heEFzTnVtYmVyIDw9IDApIHtcbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYCR7Y291bnRBc051bWJlcn0gLyAke21heEFzTnVtYmVyfWA7XG4gICAgfVxuICAgIGdldCBzdXBwb3J0aW5nT3JFcnJvclRleHQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVycm9yICYmIHRoaXMuZXJyb3JUZXh0ID8gdGhpcy5lcnJvclRleHQgOiB0aGlzLnN1cHBvcnRpbmdUZXh0O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZS1hbm5vdW5jZXMgdGhlIGZpZWxkJ3MgZXJyb3Igc3VwcG9ydGluZyB0ZXh0IHRvIHNjcmVlbiByZWFkZXJzLlxuICAgICAqXG4gICAgICogRXJyb3IgdGV4dCBhbm5vdW5jZXMgdG8gc2NyZWVuIHJlYWRlcnMgYW55dGltZSBpdCBpcyB2aXNpYmxlIGFuZCBjaGFuZ2VzLlxuICAgICAqIFVzZSB0aGUgbWV0aG9kIHRvIHJlLWFubm91bmNlIHRoZSBtZXNzYWdlIHdoZW4gdGhlIHRleHQgaGFzIG5vdCBjaGFuZ2VkLFxuICAgICAqIGJ1dCBhbm5vdW5jZW1lbnQgaXMgc3RpbGwgbmVlZGVkIChzdWNoIGFzIGZvciBgcmVwb3J0VmFsaWRpdHkoKWApLlxuICAgICAqL1xuICAgIHJlYW5ub3VuY2VFcnJvcigpIHtcbiAgICAgICAgdGhpcy5yZWZyZXNoRXJyb3JBbGVydCA9IHRydWU7XG4gICAgfVxuICAgIHVwZGF0ZShwcm9wcykge1xuICAgICAgICAvLyBDbGllbnQtc2lkZSBwcm9wZXJ0eSB1cGRhdGVzXG4gICAgICAgIGNvbnN0IGlzRGlzYWJsZWRDaGFuZ2luZyA9IHByb3BzLmhhcygnZGlzYWJsZWQnKSAmJiBwcm9wcy5nZXQoJ2Rpc2FibGVkJykgIT09IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGlzRGlzYWJsZWRDaGFuZ2luZykge1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlVHJhbnNpdGlvbnMgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdoZW4gZGlzYWJsaW5nLCByZW1vdmUgZm9jdXMgc3R5bGVzIGlmIGZvY3VzZWQuXG4gICAgICAgIGlmICh0aGlzLmRpc2FibGVkICYmIHRoaXMuZm9jdXNlZCkge1xuICAgICAgICAgICAgcHJvcHMuc2V0KCdmb2N1c2VkJywgdHJ1ZSk7XG4gICAgICAgICAgICB0aGlzLmZvY3VzZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBBbmltYXRlIGlmIGZvY3VzZWQgb3IgcG9wdWxhdGVkIGNoYW5nZS5cbiAgICAgICAgdGhpcy5hbmltYXRlTGFiZWxJZk5lZWRlZCh7XG4gICAgICAgICAgICB3YXNGb2N1c2VkOiBwcm9wcy5nZXQoJ2ZvY3VzZWQnKSxcbiAgICAgICAgICAgIHdhc1BvcHVsYXRlZDogcHJvcHMuZ2V0KCdwb3B1bGF0ZWQnKSxcbiAgICAgICAgfSk7XG4gICAgICAgIHN1cGVyLnVwZGF0ZShwcm9wcyk7XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgY29uc3QgZmxvYXRpbmdMYWJlbCA9IHRoaXMucmVuZGVyTGFiZWwoLyppc0Zsb2F0aW5nKi8gdHJ1ZSk7XG4gICAgICAgIGNvbnN0IHJlc3RpbmdMYWJlbCA9IHRoaXMucmVuZGVyTGFiZWwoLyppc0Zsb2F0aW5nKi8gZmFsc2UpO1xuICAgICAgICBjb25zdCBvdXRsaW5lID0gdGhpcy5yZW5kZXJPdXRsaW5lPy4oZmxvYXRpbmdMYWJlbCk7XG4gICAgICAgIGNvbnN0IGNsYXNzZXMgPSB7XG4gICAgICAgICAgICAnZGlzYWJsZWQnOiB0aGlzLmRpc2FibGVkLFxuICAgICAgICAgICAgJ2Rpc2FibGUtdHJhbnNpdGlvbnMnOiB0aGlzLmRpc2FibGVUcmFuc2l0aW9ucyxcbiAgICAgICAgICAgICdlcnJvcic6IHRoaXMuZXJyb3IgJiYgIXRoaXMuZGlzYWJsZWQsXG4gICAgICAgICAgICAnZm9jdXNlZCc6IHRoaXMuZm9jdXNlZCxcbiAgICAgICAgICAgICd3aXRoLXN0YXJ0JzogdGhpcy5oYXNTdGFydCxcbiAgICAgICAgICAgICd3aXRoLWVuZCc6IHRoaXMuaGFzRW5kLFxuICAgICAgICAgICAgJ3BvcHVsYXRlZCc6IHRoaXMucG9wdWxhdGVkLFxuICAgICAgICAgICAgJ3Jlc2l6YWJsZSc6IHRoaXMucmVzaXphYmxlLFxuICAgICAgICAgICAgJ3JlcXVpcmVkJzogdGhpcy5yZXF1aXJlZCxcbiAgICAgICAgICAgICduby1sYWJlbCc6ICF0aGlzLmxhYmVsLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gaHRtbCBgXG4gICAgICA8ZGl2IGNsYXNzPVwiZmllbGQgJHtjbGFzc01hcChjbGFzc2VzKX1cIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbnRhaW5lci1vdmVyZmxvd1wiPlxuICAgICAgICAgICR7dGhpcy5yZW5kZXJCYWNrZ3JvdW5kPy4oKX1cbiAgICAgICAgICA8c2xvdCBuYW1lPVwiY29udGFpbmVyXCI+PC9zbG90PlxuICAgICAgICAgICR7dGhpcy5yZW5kZXJTdGF0ZUxheWVyPy4oKX0gJHt0aGlzLnJlbmRlckluZGljYXRvcj8uKCl9ICR7b3V0bGluZX1cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29udGFpbmVyXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3RhcnRcIj5cbiAgICAgICAgICAgICAgPHNsb3QgbmFtZT1cInN0YXJ0XCI+PC9zbG90PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWlkZGxlXCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsYWJlbC13cmFwcGVyXCI+XG4gICAgICAgICAgICAgICAgJHtyZXN0aW5nTGFiZWx9ICR7b3V0bGluZSA/IG5vdGhpbmcgOiBmbG9hdGluZ0xhYmVsfVxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbnRlbnRcIj5cbiAgICAgICAgICAgICAgICA8c2xvdD48L3Nsb3Q+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZW5kXCI+XG4gICAgICAgICAgICAgIDxzbG90IG5hbWU9XCJlbmRcIj48L3Nsb3Q+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgICR7dGhpcy5yZW5kZXJTdXBwb3J0aW5nVGV4dCgpfVxuICAgICAgPC9kaXY+XG4gICAgYDtcbiAgICB9XG4gICAgdXBkYXRlZChjaGFuZ2VkKSB7XG4gICAgICAgIGlmIChjaGFuZ2VkLmhhcygnc3VwcG9ydGluZ1RleHQnKSB8fFxuICAgICAgICAgICAgY2hhbmdlZC5oYXMoJ2Vycm9yVGV4dCcpIHx8XG4gICAgICAgICAgICBjaGFuZ2VkLmhhcygnY291bnQnKSB8fFxuICAgICAgICAgICAgY2hhbmdlZC5oYXMoJ21heCcpKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVNsb3R0ZWRBcmlhRGVzY3JpYmVkQnkoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5yZWZyZXNoRXJyb3JBbGVydCkge1xuICAgICAgICAgICAgLy8gVGhlIHBhc3QgcmVuZGVyIGN5Y2xlIHJlbW92ZWQgdGhlIHJvbGU9XCJhbGVydFwiIGZyb20gdGhlIGVycm9yIG1lc3NhZ2UuXG4gICAgICAgICAgICAvLyBSZS1hZGQgaXQgYWZ0ZXIgYW4gYW5pbWF0aW9uIGZyYW1lIHRvIHJlLWFubm91bmNlIHRoZSBlcnJvci5cbiAgICAgICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWZyZXNoRXJyb3JBbGVydCA9IGZhbHNlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZGlzYWJsZVRyYW5zaXRpb25zKSB7XG4gICAgICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZGlzYWJsZVRyYW5zaXRpb25zID0gZmFsc2U7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZW5kZXJTdXBwb3J0aW5nVGV4dCgpIHtcbiAgICAgICAgY29uc3QgeyBzdXBwb3J0aW5nT3JFcnJvclRleHQsIGNvdW50ZXJUZXh0IH0gPSB0aGlzO1xuICAgICAgICBpZiAoIXN1cHBvcnRpbmdPckVycm9yVGV4dCAmJiAhY291bnRlclRleHQpIHtcbiAgICAgICAgICAgIHJldHVybiBub3RoaW5nO1xuICAgICAgICB9XG4gICAgICAgIC8vIEFsd2F5cyByZW5kZXIgdGhlIHN1cHBvcnRpbmcgdGV4dCBzcGFuIHNvIHRoYXQgb3VyIGBzcGFjZS1hcm91bmRgXG4gICAgICAgIC8vIGNvbnRhaW5lciBwdXRzIHRoZSBjb3VudGVyIGF0IHRoZSBlbmQuXG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gaHRtbCBgPHNwYW4+JHtzdXBwb3J0aW5nT3JFcnJvclRleHR9PC9zcGFuPmA7XG4gICAgICAgIC8vIENvbmRpdGlvbmFsbHkgcmVuZGVyIGNvdW50ZXIgc28gd2UgZG9uJ3QgcmVuZGVyIHRoZSBleHRyYSBgZ2FwYC5cbiAgICAgICAgLy8gVE9ETyhiLzI0NDQ3MzQzNSk6IGFkZCBhcmlhLWxhYmVsIGFuZCBhbm5vdW5jZW1lbnRzXG4gICAgICAgIGNvbnN0IGVuZCA9IGNvdW50ZXJUZXh0XG4gICAgICAgICAgICA/IGh0bWwgYDxzcGFuIGNsYXNzPVwiY291bnRlclwiPiR7Y291bnRlclRleHR9PC9zcGFuPmBcbiAgICAgICAgICAgIDogbm90aGluZztcbiAgICAgICAgLy8gQW5ub3VuY2UgaWYgdGhlcmUgaXMgYW4gZXJyb3IgYW5kIGVycm9yIHRleHQgdmlzaWJsZS5cbiAgICAgICAgLy8gSWYgcmVmcmVzaEVycm9yQWxlcnQgaXMgdHJ1ZSwgZG8gbm90IGFubm91bmNlLiBUaGlzIHdpbGwgcmVtb3ZlIHRoZVxuICAgICAgICAvLyByb2xlPVwiYWxlcnRcIiBhdHRyaWJ1dGUuIEFub3RoZXIgcmVuZGVyIGN5Y2xlIHdpbGwgaGFwcGVuIGFmdGVyIGFuXG4gICAgICAgIC8vIGFuaW1hdGlvbiBmcmFtZSB0byByZS1hZGQgdGhlIHJvbGUuXG4gICAgICAgIGNvbnN0IHNob3VsZEVycm9yQW5ub3VuY2UgPSB0aGlzLmVycm9yICYmIHRoaXMuZXJyb3JUZXh0ICYmICF0aGlzLnJlZnJlc2hFcnJvckFsZXJ0O1xuICAgICAgICBjb25zdCByb2xlID0gc2hvdWxkRXJyb3JBbm5vdW5jZSA/ICdhbGVydCcgOiBub3RoaW5nO1xuICAgICAgICByZXR1cm4gaHRtbCBgXG4gICAgICA8ZGl2IGNsYXNzPVwic3VwcG9ydGluZy10ZXh0XCIgcm9sZT0ke3JvbGV9PiR7c3RhcnR9JHtlbmR9PC9kaXY+XG4gICAgICA8c2xvdFxuICAgICAgICBuYW1lPVwiYXJpYS1kZXNjcmliZWRieVwiXG4gICAgICAgIEBzbG90Y2hhbmdlPSR7dGhpcy51cGRhdGVTbG90dGVkQXJpYURlc2NyaWJlZEJ5fT48L3Nsb3Q+XG4gICAgYDtcbiAgICB9XG4gICAgdXBkYXRlU2xvdHRlZEFyaWFEZXNjcmliZWRCeSgpIHtcbiAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHRoaXMuc2xvdHRlZEFyaWFEZXNjcmliZWRCeSkge1xuICAgICAgICAgICAgcmVuZGVyKGh0bWwgYCR7dGhpcy5zdXBwb3J0aW5nT3JFcnJvclRleHR9ICR7dGhpcy5jb3VudGVyVGV4dH1gLCBlbGVtZW50KTtcbiAgICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdoaWRkZW4nLCAnJyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmVuZGVyTGFiZWwoaXNGbG9hdGluZykge1xuICAgICAgICBpZiAoIXRoaXMubGFiZWwpIHtcbiAgICAgICAgICAgIHJldHVybiBub3RoaW5nO1xuICAgICAgICB9XG4gICAgICAgIGxldCB2aXNpYmxlO1xuICAgICAgICBpZiAoaXNGbG9hdGluZykge1xuICAgICAgICAgICAgLy8gRmxvYXRpbmcgbGFiZWwgaXMgdmlzaWJsZSB3aGVuIGZvY3VzZWQvcG9wdWxhdGVkIG9yIHdoZW4gYW5pbWF0aW5nLlxuICAgICAgICAgICAgdmlzaWJsZSA9IHRoaXMuZm9jdXNlZCB8fCB0aGlzLnBvcHVsYXRlZCB8fCB0aGlzLmlzQW5pbWF0aW5nO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gUmVzdGluZyBsYWJlbCBpcyB2aXNpYmxlIHdoZW4gdW5mb2N1c2VkLiBJdCBpcyBuZXZlciB2aXNpYmxlIHdoaWxlXG4gICAgICAgICAgICAvLyBhbmltYXRpbmcuXG4gICAgICAgICAgICB2aXNpYmxlID0gIXRoaXMuZm9jdXNlZCAmJiAhdGhpcy5wb3B1bGF0ZWQgJiYgIXRoaXMuaXNBbmltYXRpbmc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2xhc3NlcyA9IHtcbiAgICAgICAgICAgICdoaWRkZW4nOiAhdmlzaWJsZSxcbiAgICAgICAgICAgICdmbG9hdGluZyc6IGlzRmxvYXRpbmcsXG4gICAgICAgICAgICAncmVzdGluZyc6ICFpc0Zsb2F0aW5nLFxuICAgICAgICB9O1xuICAgICAgICAvLyBBZGQgJyonIGlmIGEgbGFiZWwgaXMgcHJlc2VudCBhbmQgdGhlIGZpZWxkIGlzIHJlcXVpcmVkXG4gICAgICAgIGNvbnN0IGxhYmVsVGV4dCA9IGAke3RoaXMubGFiZWx9JHt0aGlzLnJlcXVpcmVkICYmICF0aGlzLm5vQXN0ZXJpc2sgPyAnKicgOiAnJ31gO1xuICAgICAgICByZXR1cm4gaHRtbCBgXG4gICAgICA8c3BhbiBjbGFzcz1cImxhYmVsICR7Y2xhc3NNYXAoY2xhc3Nlcyl9XCIgYXJpYS1oaWRkZW49JHshdmlzaWJsZX1cbiAgICAgICAgPiR7bGFiZWxUZXh0fTwvc3BhblxuICAgICAgPlxuICAgIGA7XG4gICAgfVxuICAgIGFuaW1hdGVMYWJlbElmTmVlZGVkKHsgd2FzRm9jdXNlZCwgd2FzUG9wdWxhdGVkLCB9KSB7XG4gICAgICAgIGlmICghdGhpcy5sYWJlbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHdhc0ZvY3VzZWQgPz89IHRoaXMuZm9jdXNlZDtcbiAgICAgICAgd2FzUG9wdWxhdGVkID8/PSB0aGlzLnBvcHVsYXRlZDtcbiAgICAgICAgY29uc3Qgd2FzRmxvYXRpbmcgPSB3YXNGb2N1c2VkIHx8IHdhc1BvcHVsYXRlZDtcbiAgICAgICAgY29uc3Qgc2hvdWxkQmVGbG9hdGluZyA9IHRoaXMuZm9jdXNlZCB8fCB0aGlzLnBvcHVsYXRlZDtcbiAgICAgICAgaWYgKHdhc0Zsb2F0aW5nID09PSBzaG91bGRCZUZsb2F0aW5nKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pc0FuaW1hdGluZyA9IHRydWU7XG4gICAgICAgIHRoaXMubGFiZWxBbmltYXRpb24/LmNhbmNlbCgpO1xuICAgICAgICAvLyBPbmx5IG9uZSBsYWJlbCBpcyB2aXNpYmxlIGF0IGEgdGltZSBmb3IgY2xlYXJlciB0ZXh0IHJlbmRlcmluZy5cbiAgICAgICAgLy8gVGhlIGZsb2F0aW5nIGxhYmVsIGlzIHZpc2libGUgYW5kIHVzZWQgZHVyaW5nIGFuaW1hdGlvbi4gQXQgdGhlIGVuZCBvZlxuICAgICAgICAvLyB0aGUgYW5pbWF0aW9uLCBpdCB3aWxsIGVpdGhlciByZW1haW4gdmlzaWJsZSAoaWYgZmxvYXRpbmcpIG9yIGhpZGUgYW5kXG4gICAgICAgIC8vIHRoZSByZXN0aW5nIGxhYmVsIHdpbGwgYmUgc2hvd24uXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFdlIGRvbid0IHVzZSBmb3J3YXJkIGZpbGxpbmcgYmVjYXVzZSBpZiB0aGUgZGltZW5zaW9ucyBvZiB0aGUgdGV4dCBmaWVsZFxuICAgICAgICAvLyBjaGFuZ2UgKGxlYWRpbmcgaWNvbiByZW1vdmVkLCBkZW5zaXR5IGNoYW5nZXMsIGV0YyksIHRoZW4gdGhlIGFuaW1hdGlvblxuICAgICAgICAvLyB3aWxsIGJlIGluYWNjdXJhdGUuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFJlLWNhbGN1bGF0aW5nIHRoZSBhbmltYXRpb24gZWFjaCB0aW1lIHdpbGwgcHJldmVudCBhbnkgdmlzdWFsIGdsaXRjaGVzXG4gICAgICAgIC8vIGZyb20gYXBwZWFyaW5nLlxuICAgICAgICAvLyBUT0RPKGIvMjQxMTEzMzQ1KTogdXNlIGFuaW1hdGlvbiB0b2tlbnNcbiAgICAgICAgdGhpcy5sYWJlbEFuaW1hdGlvbiA9IHRoaXMuZmxvYXRpbmdMYWJlbEVsPy5hbmltYXRlKHRoaXMuZ2V0TGFiZWxLZXlmcmFtZXMoKSwgeyBkdXJhdGlvbjogMTUwLCBlYXNpbmc6IEVBU0lORy5TVEFOREFSRCB9KTtcbiAgICAgICAgdGhpcy5sYWJlbEFuaW1hdGlvbj8uYWRkRXZlbnRMaXN0ZW5lcignZmluaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgLy8gQXQgdGhlIGVuZCBvZiB0aGUgYW5pbWF0aW9uLCB1cGRhdGUgdGhlIHZpc2libGUgbGFiZWwuXG4gICAgICAgICAgICB0aGlzLmlzQW5pbWF0aW5nID0gZmFsc2U7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBnZXRMYWJlbEtleWZyYW1lcygpIHtcbiAgICAgICAgY29uc3QgeyBmbG9hdGluZ0xhYmVsRWwsIHJlc3RpbmdMYWJlbEVsIH0gPSB0aGlzO1xuICAgICAgICBpZiAoIWZsb2F0aW5nTGFiZWxFbCB8fCAhcmVzdGluZ0xhYmVsRWwpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IHg6IGZsb2F0aW5nWCwgeTogZmxvYXRpbmdZLCBoZWlnaHQ6IGZsb2F0aW5nSGVpZ2h0LCB9ID0gZmxvYXRpbmdMYWJlbEVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICBjb25zdCB7IHg6IHJlc3RpbmdYLCB5OiByZXN0aW5nWSwgaGVpZ2h0OiByZXN0aW5nSGVpZ2h0LCB9ID0gcmVzdGluZ0xhYmVsRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnN0IGZsb2F0aW5nU2Nyb2xsV2lkdGggPSBmbG9hdGluZ0xhYmVsRWwuc2Nyb2xsV2lkdGg7XG4gICAgICAgIGNvbnN0IHJlc3RpbmdTY3JvbGxXaWR0aCA9IHJlc3RpbmdMYWJlbEVsLnNjcm9sbFdpZHRoO1xuICAgICAgICAvLyBTY2FsZSBieSB3aWR0aCByYXRpbyBpbnN0ZWFkIG9mIGZvbnQgc2l6ZSBzaW5jZSBsZXR0ZXItc3BhY2luZyB3aWxsIHNjYWxlXG4gICAgICAgIC8vIGluY29ycmVjdGx5LiBVc2luZyB0aGUgd2lkdGggd2UgY2FuIGJldHRlciBhcHByb3hpbWF0ZSB0aGUgYWRqdXN0ZWRcbiAgICAgICAgLy8gc2NhbGUgYW5kIGNvbXBlbnNhdGUgZm9yIHRyYWNraW5nIGFuZCBvdmVyZmxvdy5cbiAgICAgICAgLy8gKHVzZSBzY3JvbGxXaWR0aCBpbnN0ZWFkIG9mIHdpZHRoIHRvIGFjY291bnQgZm9yIGNsaXBwZWQgbGFiZWxzKVxuICAgICAgICBjb25zdCBzY2FsZSA9IHJlc3RpbmdTY3JvbGxXaWR0aCAvIGZsb2F0aW5nU2Nyb2xsV2lkdGg7XG4gICAgICAgIGNvbnN0IHhEZWx0YSA9IHJlc3RpbmdYIC0gZmxvYXRpbmdYO1xuICAgICAgICAvLyBUaGUgbGluZS1oZWlnaHQgb2YgdGhlIHJlc3RpbmcgYW5kIGZsb2F0aW5nIGxhYmVsIGFyZSBkaWZmZXJlbnQuIFdoZW5cbiAgICAgICAgLy8gd2UgbW92ZSB0aGUgZmxvYXRpbmcgbGFiZWwgZG93biB0byB0aGUgcmVzdGluZyBsYWJlbCdzIHBvc2l0aW9uLCBpdCB3b24ndFxuICAgICAgICAvLyBleGFjdGx5IG1hdGNoIGJlY2F1c2Ugb2YgdGhpcy4gV2UgbmVlZCB0byBhZGp1c3QgYnkgaGFsZiBvZiB3aGF0IHRoZVxuICAgICAgICAvLyBmaW5hbCBzY2FsZWQgZmxvYXRpbmcgbGFiZWwncyBoZWlnaHQgd2lsbCBiZS5cbiAgICAgICAgY29uc3QgeURlbHRhID0gcmVzdGluZ1kgLVxuICAgICAgICAgICAgZmxvYXRpbmdZICtcbiAgICAgICAgICAgIE1hdGgucm91bmQoKHJlc3RpbmdIZWlnaHQgLSBmbG9hdGluZ0hlaWdodCAqIHNjYWxlKSAvIDIpO1xuICAgICAgICAvLyBDcmVhdGUgdGhlIHR3byB0cmFuc2Zvcm1zOiBmbG9hdGluZyB0byByZXN0aW5nICh1c2luZyB0aGUgY2FsY3VsYXRpb25zXG4gICAgICAgIC8vIGFib3ZlKSwgYW5kIHJlc3RpbmcgdG8gZmxvYXRpbmcgKHJlLXNldHRpbmcgdGhlIHRyYW5zZm9ybSB0byBpbml0aWFsXG4gICAgICAgIC8vIHZhbHVlcykuXG4gICAgICAgIGNvbnN0IHJlc3RUcmFuc2Zvcm0gPSBgdHJhbnNsYXRlWCgke3hEZWx0YX1weCkgdHJhbnNsYXRlWSgke3lEZWx0YX1weCkgc2NhbGUoJHtzY2FsZX0pYDtcbiAgICAgICAgY29uc3QgZmxvYXRUcmFuc2Zvcm0gPSBgdHJhbnNsYXRlWCgwKSB0cmFuc2xhdGVZKDApIHNjYWxlKDEpYDtcbiAgICAgICAgLy8gQ29uc3RyYWluIHRoZSBmbG9hdGluZyBsYWJlbHMgd2lkdGggdG8gYSBzY2FsZWQgcGVyY2VudGFnZSBvZiB0aGVcbiAgICAgICAgLy8gcmVzdGluZyBsYWJlbCdzIHdpZHRoLiBUaGlzIHdpbGwgcHJldmVudCBsb25nIGNsaXBwZWQgbGFiZWxzIGZyb21cbiAgICAgICAgLy8gb3ZlcmZsb3dpbmcgdGhlIGNvbnRhaW5lci5cbiAgICAgICAgY29uc3QgcmVzdGluZ0NsaWVudFdpZHRoID0gcmVzdGluZ0xhYmVsRWwuY2xpZW50V2lkdGg7XG4gICAgICAgIGNvbnN0IGlzUmVzdGluZ0NsaXBwZWQgPSByZXN0aW5nU2Nyb2xsV2lkdGggPiByZXN0aW5nQ2xpZW50V2lkdGg7XG4gICAgICAgIGNvbnN0IHdpZHRoID0gaXNSZXN0aW5nQ2xpcHBlZCA/IGAke3Jlc3RpbmdDbGllbnRXaWR0aCAvIHNjYWxlfXB4YCA6ICcnO1xuICAgICAgICBpZiAodGhpcy5mb2N1c2VkIHx8IHRoaXMucG9wdWxhdGVkKSB7XG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgIHsgdHJhbnNmb3JtOiByZXN0VHJhbnNmb3JtLCB3aWR0aCB9LFxuICAgICAgICAgICAgICAgIHsgdHJhbnNmb3JtOiBmbG9hdFRyYW5zZm9ybSwgd2lkdGggfSxcbiAgICAgICAgICAgIF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIHsgdHJhbnNmb3JtOiBmbG9hdFRyYW5zZm9ybSwgd2lkdGggfSxcbiAgICAgICAgICAgIHsgdHJhbnNmb3JtOiByZXN0VHJhbnNmb3JtLCB3aWR0aCB9LFxuICAgICAgICBdO1xuICAgIH1cbiAgICBnZXRTdXJmYWNlUG9zaXRpb25DbGllbnRSZWN0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb250YWluZXJFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB9XG59XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IEJvb2xlYW4gfSlcbl0sIEZpZWxkLnByb3RvdHlwZSwgXCJkaXNhYmxlZFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuIH0pXG5dLCBGaWVsZC5wcm90b3R5cGUsIFwiZXJyb3JcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiB9KVxuXSwgRmllbGQucHJvdG90eXBlLCBcImZvY3VzZWRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KClcbl0sIEZpZWxkLnByb3RvdHlwZSwgXCJsYWJlbFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCBhdHRyaWJ1dGU6ICduby1hc3RlcmlzaycgfSlcbl0sIEZpZWxkLnByb3RvdHlwZSwgXCJub0FzdGVyaXNrXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IEJvb2xlYW4gfSlcbl0sIEZpZWxkLnByb3RvdHlwZSwgXCJwb3B1bGF0ZWRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiB9KVxuXSwgRmllbGQucHJvdG90eXBlLCBcInJlcXVpcmVkXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IEJvb2xlYW4gfSlcbl0sIEZpZWxkLnByb3RvdHlwZSwgXCJyZXNpemFibGVcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgYXR0cmlidXRlOiAnc3VwcG9ydGluZy10ZXh0JyB9KVxuXSwgRmllbGQucHJvdG90eXBlLCBcInN1cHBvcnRpbmdUZXh0XCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ2Vycm9yLXRleHQnIH0pXG5dLCBGaWVsZC5wcm90b3R5cGUsIFwiZXJyb3JUZXh0XCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IE51bWJlciB9KVxuXSwgRmllbGQucHJvdG90eXBlLCBcImNvdW50XCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IE51bWJlciB9KVxuXSwgRmllbGQucHJvdG90eXBlLCBcIm1heFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCBhdHRyaWJ1dGU6ICdoYXMtc3RhcnQnIH0pXG5dLCBGaWVsZC5wcm90b3R5cGUsIFwiaGFzU3RhcnRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgYXR0cmlidXRlOiAnaGFzLWVuZCcgfSlcbl0sIEZpZWxkLnByb3RvdHlwZSwgXCJoYXNFbmRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHF1ZXJ5QXNzaWduZWRFbGVtZW50cyh7IHNsb3Q6ICdhcmlhLWRlc2NyaWJlZGJ5JyB9KVxuXSwgRmllbGQucHJvdG90eXBlLCBcInNsb3R0ZWRBcmlhRGVzY3JpYmVkQnlcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHN0YXRlKClcbl0sIEZpZWxkLnByb3RvdHlwZSwgXCJpc0FuaW1hdGluZ1wiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgc3RhdGUoKVxuXSwgRmllbGQucHJvdG90eXBlLCBcInJlZnJlc2hFcnJvckFsZXJ0XCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBzdGF0ZSgpXG5dLCBGaWVsZC5wcm90b3R5cGUsIFwiZGlzYWJsZVRyYW5zaXRpb25zXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBxdWVyeSgnLmxhYmVsLmZsb2F0aW5nJylcbl0sIEZpZWxkLnByb3RvdHlwZSwgXCJmbG9hdGluZ0xhYmVsRWxcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHF1ZXJ5KCcubGFiZWwucmVzdGluZycpXG5dLCBGaWVsZC5wcm90b3R5cGUsIFwicmVzdGluZ0xhYmVsRWxcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHF1ZXJ5KCcuY29udGFpbmVyJylcbl0sIEZpZWxkLnByb3RvdHlwZSwgXCJjb250YWluZXJFbFwiLCB2b2lkIDApO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZmllbGQuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjEgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuaW1wb3J0IHsgaHRtbCB9IGZyb20gJ2xpdCc7XG5pbXBvcnQgeyBGaWVsZCB9IGZyb20gJy4vZmllbGQuanMnO1xuLyoqXG4gKiBBIGZpbGxlZCBmaWVsZCBjb21wb25lbnQuXG4gKi9cbmV4cG9ydCBjbGFzcyBGaWxsZWRGaWVsZCBleHRlbmRzIEZpZWxkIHtcbiAgICByZW5kZXJCYWNrZ3JvdW5kKCkge1xuICAgICAgICByZXR1cm4gaHRtbCBgIDxkaXYgY2xhc3M9XCJiYWNrZ3JvdW5kXCI+PC9kaXY+IGA7XG4gICAgfVxuICAgIHJlbmRlclN0YXRlTGF5ZXIoKSB7XG4gICAgICAgIHJldHVybiBodG1sIGAgPGRpdiBjbGFzcz1cInN0YXRlLWxheWVyXCI+PC9kaXY+IGA7XG4gICAgfVxuICAgIHJlbmRlckluZGljYXRvcigpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYDxkaXYgY2xhc3M9XCJhY3RpdmUtaW5kaWNhdG9yXCI+PC9kaXY+YDtcbiAgICB9XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1maWxsZWQtZmllbGQuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjQgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuLy8gR2VuZXJhdGVkIHN0eWxlc2hlZXQgZm9yIC4vZmllbGQvaW50ZXJuYWwvZmlsbGVkLXN0eWxlcy5jc3MuXG5pbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuZXhwb3J0IGNvbnN0IHN0eWxlcyA9IGNzcyBgQGxheWVyIHN0eWxlc3s6aG9zdHstLV9hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtYWN0aXZlLWluZGljYXRvci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2FjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0OiB2YXIoLS1tZC1maWxsZWQtZmllbGQtYWN0aXZlLWluZGljYXRvci1oZWlnaHQsIDFweCk7LS1fYm90dG9tLXNwYWNlOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtYm90dG9tLXNwYWNlLCAxNnB4KTstLV9jb250YWluZXItY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1jb250YWluZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1zdXJmYWNlLWNvbnRhaW5lci1oaWdoZXN0LCAjZTZlMGU5KSk7LS1fY29udGVudC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWNvbnRlbnQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1fY29udGVudC1mb250OiB2YXIoLS1tZC1maWxsZWQtZmllbGQtY29udGVudC1mb250LCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbGFyZ2UtZm9udCwgdmFyKC0tbWQtcmVmLXR5cGVmYWNlLXBsYWluLCBSb2JvdG8pKSk7LS1fY29udGVudC1saW5lLWhlaWdodDogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWNvbnRlbnQtbGluZS1oZWlnaHQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS1saW5lLWhlaWdodCwgMS41cmVtKSk7LS1fY29udGVudC1zaXplOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtY29udGVudC1zaXplLCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbGFyZ2Utc2l6ZSwgMXJlbSkpOy0tX2NvbnRlbnQtc3BhY2U6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1jb250ZW50LXNwYWNlLCAxNnB4KTstLV9jb250ZW50LXdlaWdodDogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWNvbnRlbnQtd2VpZ2h0LCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbGFyZ2Utd2VpZ2h0LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2Utd2VpZ2h0LXJlZ3VsYXIsIDQwMCkpKTstLV9kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtYWN0aXZlLWluZGljYXRvci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV9kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodDogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0LCAxcHgpOy0tX2Rpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3Itb3BhY2l0eTogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3Itb3BhY2l0eSwgMC4zOCk7LS1fZGlzYWJsZWQtY29udGFpbmVyLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtY29udGFpbmVyLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2Rpc2FibGVkLWNvbnRhaW5lci1vcGFjaXR5OiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtY29udGFpbmVyLW9wYWNpdHksIDAuMDQpOy0tX2Rpc2FibGVkLWNvbnRlbnQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1jb250ZW50LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2Rpc2FibGVkLWNvbnRlbnQtb3BhY2l0eTogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLWNvbnRlbnQtb3BhY2l0eSwgMC4zOCk7LS1fZGlzYWJsZWQtbGFiZWwtdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLWxhYmVsLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1fZGlzYWJsZWQtbGFiZWwtdGV4dC1vcGFjaXR5OiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtbGFiZWwtdGV4dC1vcGFjaXR5LCAwLjM4KTstLV9kaXNhYmxlZC1sZWFkaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1sZWFkaW5nLWNvbnRlbnQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1fZGlzYWJsZWQtbGVhZGluZy1jb250ZW50LW9wYWNpdHk6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1sZWFkaW5nLWNvbnRlbnQtb3BhY2l0eSwgMC4zOCk7LS1fZGlzYWJsZWQtc3VwcG9ydGluZy10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtc3VwcG9ydGluZy10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2Rpc2FibGVkLXN1cHBvcnRpbmctdGV4dC1vcGFjaXR5OiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtc3VwcG9ydGluZy10ZXh0LW9wYWNpdHksIDAuMzgpOy0tX2Rpc2FibGVkLXRyYWlsaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC10cmFpbGluZy1jb250ZW50LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2Rpc2FibGVkLXRyYWlsaW5nLWNvbnRlbnQtb3BhY2l0eTogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLXRyYWlsaW5nLWNvbnRlbnQtb3BhY2l0eSwgMC4zOCk7LS1fZXJyb3ItYWN0aXZlLWluZGljYXRvci1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1lcnJvciwgI2IzMjYxZSkpOy0tX2Vycm9yLWNvbnRlbnQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci1jb250ZW50LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2Vycm9yLWZvY3VzLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci1mb2N1cy1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItZXJyb3IsICNiMzI2MWUpKTstLV9lcnJvci1mb2N1cy1jb250ZW50LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZXJyb3ItZm9jdXMtY29udGVudC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2Vycm9yLWZvY3VzLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci1mb2N1cy1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItZXJyb3IsICNiMzI2MWUpKTstLV9lcnJvci1mb2N1cy1sZWFkaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci1mb2N1cy1sZWFkaW5nLWNvbnRlbnQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV9lcnJvci1mb2N1cy1zdXBwb3J0aW5nLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci1mb2N1cy1zdXBwb3J0aW5nLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1lcnJvciwgI2IzMjYxZSkpOy0tX2Vycm9yLWZvY3VzLXRyYWlsaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci1mb2N1cy10cmFpbGluZy1jb250ZW50LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItZXJyb3IsICNiMzI2MWUpKTstLV9lcnJvci1ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZXJyb3ItaG92ZXItYWN0aXZlLWluZGljYXRvci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLWVycm9yLWNvbnRhaW5lciwgIzQxMGUwYikpOy0tX2Vycm9yLWhvdmVyLWNvbnRlbnQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci1ob3Zlci1jb250ZW50LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2Vycm9yLWhvdmVyLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci1ob3Zlci1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tZXJyb3ItY29udGFpbmVyLCAjNDEwZTBiKSk7LS1fZXJyb3ItaG92ZXItbGVhZGluZy1jb250ZW50LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZXJyb3ItaG92ZXItbGVhZGluZy1jb250ZW50LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fZXJyb3ItaG92ZXItc3RhdGUtbGF5ZXItY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci1ob3Zlci1zdGF0ZS1sYXllci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV9lcnJvci1ob3Zlci1zdGF0ZS1sYXllci1vcGFjaXR5OiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZXJyb3ItaG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eSwgMC4wOCk7LS1fZXJyb3ItaG92ZXItc3VwcG9ydGluZy10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZXJyb3ItaG92ZXItc3VwcG9ydGluZy10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItZXJyb3IsICNiMzI2MWUpKTstLV9lcnJvci1ob3Zlci10cmFpbGluZy1jb250ZW50LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZXJyb3ItaG92ZXItdHJhaWxpbmctY29udGVudC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLWVycm9yLWNvbnRhaW5lciwgIzQxMGUwYikpOy0tX2Vycm9yLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItZXJyb3IsICNiMzI2MWUpKTstLV9lcnJvci1sZWFkaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci1sZWFkaW5nLWNvbnRlbnQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV9lcnJvci1zdXBwb3J0aW5nLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci1zdXBwb3J0aW5nLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1lcnJvciwgI2IzMjYxZSkpOy0tX2Vycm9yLXRyYWlsaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1lcnJvci10cmFpbGluZy1jb250ZW50LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItZXJyb3IsICNiMzI2MWUpKTstLV9mb2N1cy1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtZm9jdXMtYWN0aXZlLWluZGljYXRvci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKTstLV9mb2N1cy1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodDogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWZvY3VzLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0LCAzcHgpOy0tX2ZvY3VzLWNvbnRlbnQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1mb2N1cy1jb250ZW50LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2ZvY3VzLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1mb2N1cy1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItcHJpbWFyeSwgIzY3NTBhNCkpOy0tX2ZvY3VzLWxlYWRpbmctY29udGVudC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWZvY3VzLWxlYWRpbmctY29udGVudC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2ZvY3VzLXN1cHBvcnRpbmctdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWZvY3VzLXN1cHBvcnRpbmctdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2ZvY3VzLXRyYWlsaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1mb2N1cy10cmFpbGluZy1jb250ZW50LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1faG92ZXItYWN0aXZlLWluZGljYXRvci1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWhvdmVyLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1faG92ZXItYWN0aXZlLWluZGljYXRvci1oZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodCwgMXB4KTstLV9ob3Zlci1jb250ZW50LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtaG92ZXItY29udGVudC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV9ob3Zlci1sYWJlbC10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtaG92ZXItbGFiZWwtdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2hvdmVyLWxlYWRpbmctY29udGVudC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWhvdmVyLWxlYWRpbmctY29udGVudC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2hvdmVyLXN0YXRlLWxheWVyLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtaG92ZXItc3RhdGUtbGF5ZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1faG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eTogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWhvdmVyLXN0YXRlLWxheWVyLW9wYWNpdHksIDAuMDgpOy0tX2hvdmVyLXN1cHBvcnRpbmctdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWhvdmVyLXN1cHBvcnRpbmctdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2hvdmVyLXRyYWlsaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1ob3Zlci10cmFpbGluZy1jb250ZW50LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fbGFiZWwtdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWxhYmVsLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV9sYWJlbC10ZXh0LWZvbnQ6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1sYWJlbC10ZXh0LWZvbnQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS1mb250LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2UtcGxhaW4sIFJvYm90bykpKTstLV9sYWJlbC10ZXh0LWxpbmUtaGVpZ2h0OiB2YXIoLS1tZC1maWxsZWQtZmllbGQtbGFiZWwtdGV4dC1saW5lLWhlaWdodCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LWxhcmdlLWxpbmUtaGVpZ2h0LCAxLjVyZW0pKTstLV9sYWJlbC10ZXh0LXBvcHVsYXRlZC1saW5lLWhlaWdodDogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWxhYmVsLXRleHQtcG9wdWxhdGVkLWxpbmUtaGVpZ2h0LCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktc21hbGwtbGluZS1oZWlnaHQsIDFyZW0pKTstLV9sYWJlbC10ZXh0LXBvcHVsYXRlZC1zaXplOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtbGFiZWwtdGV4dC1wb3B1bGF0ZWQtc2l6ZSwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LXNtYWxsLXNpemUsIDAuNzVyZW0pKTstLV9sYWJlbC10ZXh0LXNpemU6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1sYWJlbC10ZXh0LXNpemUsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS1zaXplLCAxcmVtKSk7LS1fbGFiZWwtdGV4dC13ZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1sYWJlbC10ZXh0LXdlaWdodCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LWxhcmdlLXdlaWdodCwgdmFyKC0tbWQtcmVmLXR5cGVmYWNlLXdlaWdodC1yZWd1bGFyLCA0MDApKSk7LS1fbGVhZGluZy1jb250ZW50LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtbGVhZGluZy1jb250ZW50LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fbGVhZGluZy1zcGFjZTogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWxlYWRpbmctc3BhY2UsIDE2cHgpOy0tX3N1cHBvcnRpbmctdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLXN1cHBvcnRpbmctdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX3N1cHBvcnRpbmctdGV4dC1mb250OiB2YXIoLS1tZC1maWxsZWQtZmllbGQtc3VwcG9ydGluZy10ZXh0LWZvbnQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1zbWFsbC1mb250LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2UtcGxhaW4sIFJvYm90bykpKTstLV9zdXBwb3J0aW5nLXRleHQtbGVhZGluZy1zcGFjZTogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLXN1cHBvcnRpbmctdGV4dC1sZWFkaW5nLXNwYWNlLCAxNnB4KTstLV9zdXBwb3J0aW5nLXRleHQtbGluZS1oZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1zdXBwb3J0aW5nLXRleHQtbGluZS1oZWlnaHQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1zbWFsbC1saW5lLWhlaWdodCwgMXJlbSkpOy0tX3N1cHBvcnRpbmctdGV4dC1zaXplOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtc3VwcG9ydGluZy10ZXh0LXNpemUsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1zbWFsbC1zaXplLCAwLjc1cmVtKSk7LS1fc3VwcG9ydGluZy10ZXh0LXRvcC1zcGFjZTogdmFyKC0tbWQtZmlsbGVkLWZpZWxkLXN1cHBvcnRpbmctdGV4dC10b3Atc3BhY2UsIDRweCk7LS1fc3VwcG9ydGluZy10ZXh0LXRyYWlsaW5nLXNwYWNlOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtc3VwcG9ydGluZy10ZXh0LXRyYWlsaW5nLXNwYWNlLCAxNnB4KTstLV9zdXBwb3J0aW5nLXRleHQtd2VpZ2h0OiB2YXIoLS1tZC1maWxsZWQtZmllbGQtc3VwcG9ydGluZy10ZXh0LXdlaWdodCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LXNtYWxsLXdlaWdodCwgdmFyKC0tbWQtcmVmLXR5cGVmYWNlLXdlaWdodC1yZWd1bGFyLCA0MDApKSk7LS1fdG9wLXNwYWNlOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtdG9wLXNwYWNlLCAxNnB4KTstLV90cmFpbGluZy1jb250ZW50LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtdHJhaWxpbmctY29udGVudC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX3RyYWlsaW5nLXNwYWNlOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtdHJhaWxpbmctc3BhY2UsIDE2cHgpOy0tX3dpdGgtbGFiZWwtYm90dG9tLXNwYWNlOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtd2l0aC1sYWJlbC1ib3R0b20tc3BhY2UsIDhweCk7LS1fd2l0aC1sYWJlbC10b3Atc3BhY2U6IHZhcigtLW1kLWZpbGxlZC1maWVsZC13aXRoLWxhYmVsLXRvcC1zcGFjZSwgOHB4KTstLV93aXRoLWxlYWRpbmctY29udGVudC1sZWFkaW5nLXNwYWNlOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtd2l0aC1sZWFkaW5nLWNvbnRlbnQtbGVhZGluZy1zcGFjZSwgMTJweCk7LS1fd2l0aC10cmFpbGluZy1jb250ZW50LXRyYWlsaW5nLXNwYWNlOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtd2l0aC10cmFpbGluZy1jb250ZW50LXRyYWlsaW5nLXNwYWNlLCAxMnB4KTstLV9jb250YWluZXItc2hhcGUtc3RhcnQtc3RhcnQ6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1jb250YWluZXItc2hhcGUtc3RhcnQtc3RhcnQsIHZhcigtLW1kLWZpbGxlZC1maWVsZC1jb250YWluZXItc2hhcGUsIHZhcigtLW1kLXN5cy1zaGFwZS1jb3JuZXItZXh0cmEtc21hbGwsIDRweCkpKTstLV9jb250YWluZXItc2hhcGUtc3RhcnQtZW5kOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtY29udGFpbmVyLXNoYXBlLXN0YXJ0LWVuZCwgdmFyKC0tbWQtZmlsbGVkLWZpZWxkLWNvbnRhaW5lci1zaGFwZSwgdmFyKC0tbWQtc3lzLXNoYXBlLWNvcm5lci1leHRyYS1zbWFsbCwgNHB4KSkpOy0tX2NvbnRhaW5lci1zaGFwZS1lbmQtZW5kOiB2YXIoLS1tZC1maWxsZWQtZmllbGQtY29udGFpbmVyLXNoYXBlLWVuZC1lbmQsIHZhcigtLW1kLWZpbGxlZC1maWVsZC1jb250YWluZXItc2hhcGUsIHZhcigtLW1kLXN5cy1zaGFwZS1jb3JuZXItbm9uZSwgMHB4KSkpOy0tX2NvbnRhaW5lci1zaGFwZS1lbmQtc3RhcnQ6IHZhcigtLW1kLWZpbGxlZC1maWVsZC1jb250YWluZXItc2hhcGUtZW5kLXN0YXJ0LCB2YXIoLS1tZC1maWxsZWQtZmllbGQtY29udGFpbmVyLXNoYXBlLCB2YXIoLS1tZC1zeXMtc2hhcGUtY29ybmVyLW5vbmUsIDBweCkpKX0uYmFja2dyb3VuZCwuc3RhdGUtbGF5ZXJ7Ym9yZGVyLXJhZGl1czppbmhlcml0O2luc2V0OjA7cG9pbnRlci1ldmVudHM6bm9uZTtwb3NpdGlvbjphYnNvbHV0ZX0uYmFja2dyb3VuZHtiYWNrZ3JvdW5kOnZhcigtLV9jb250YWluZXItY29sb3IpfS5zdGF0ZS1sYXllcnt2aXNpYmlsaXR5OmhpZGRlbn0uZmllbGQ6bm90KC5kaXNhYmxlZCk6aG92ZXIgLnN0YXRlLWxheWVye3Zpc2liaWxpdHk6dmlzaWJsZX0ubGFiZWwuZmxvYXRpbmd7cG9zaXRpb246YWJzb2x1dGU7dG9wOnZhcigtLV93aXRoLWxhYmVsLXRvcC1zcGFjZSl9LmZpZWxkOm5vdCgud2l0aC1zdGFydCkgLmxhYmVsLXdyYXBwZXJ7bWFyZ2luLWlubGluZS1zdGFydDp2YXIoLS1fbGVhZGluZy1zcGFjZSl9LmZpZWxkOm5vdCgud2l0aC1lbmQpIC5sYWJlbC13cmFwcGVye21hcmdpbi1pbmxpbmUtZW5kOnZhcigtLV90cmFpbGluZy1zcGFjZSl9LmFjdGl2ZS1pbmRpY2F0b3J7aW5zZXQ6YXV0byAwIDAgMDtwb2ludGVyLWV2ZW50czpub25lO3Bvc2l0aW9uOmFic29sdXRlO3dpZHRoOjEwMCU7ei1pbmRleDoxfS5hY3RpdmUtaW5kaWNhdG9yOjpiZWZvcmUsLmFjdGl2ZS1pbmRpY2F0b3I6OmFmdGVye2JvcmRlci1ib3R0b206dmFyKC0tX2FjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0KSBzb2xpZCB2YXIoLS1fYWN0aXZlLWluZGljYXRvci1jb2xvcik7aW5zZXQ6YXV0byAwIDAgMDtjb250ZW50OlwiXCI7cG9zaXRpb246YWJzb2x1dGU7d2lkdGg6MTAwJX0uYWN0aXZlLWluZGljYXRvcjo6YWZ0ZXJ7b3BhY2l0eTowO3RyYW5zaXRpb246b3BhY2l0eSAxNTBtcyBjdWJpYy1iZXppZXIoMC4yLCAwLCAwLCAxKX0uZm9jdXNlZCAuYWN0aXZlLWluZGljYXRvcjo6YWZ0ZXJ7b3BhY2l0eToxfS5maWVsZDpub3QoLndpdGgtc3RhcnQpIC5jb250ZW50IDo6c2xvdHRlZCgqKXtwYWRkaW5nLWlubGluZS1zdGFydDp2YXIoLS1fbGVhZGluZy1zcGFjZSl9LmZpZWxkOm5vdCgud2l0aC1lbmQpIC5jb250ZW50IDo6c2xvdHRlZCgqKXtwYWRkaW5nLWlubGluZS1lbmQ6dmFyKC0tX3RyYWlsaW5nLXNwYWNlKX0uZmllbGQ6bm90KC5uby1sYWJlbCkgLmNvbnRlbnQgOjpzbG90dGVkKDpub3QodGV4dGFyZWEpKXtwYWRkaW5nLWJvdHRvbTp2YXIoLS1fd2l0aC1sYWJlbC1ib3R0b20tc3BhY2UpO3BhZGRpbmctdG9wOmNhbGModmFyKC0tX3dpdGgtbGFiZWwtdG9wLXNwYWNlKSArIHZhcigtLV9sYWJlbC10ZXh0LXBvcHVsYXRlZC1saW5lLWhlaWdodCkpfS5maWVsZDpub3QoLm5vLWxhYmVsKSAuY29udGVudCA6OnNsb3R0ZWQodGV4dGFyZWEpe21hcmdpbi1ib3R0b206dmFyKC0tX3dpdGgtbGFiZWwtYm90dG9tLXNwYWNlKTttYXJnaW4tdG9wOmNhbGModmFyKC0tX3dpdGgtbGFiZWwtdG9wLXNwYWNlKSArIHZhcigtLV9sYWJlbC10ZXh0LXBvcHVsYXRlZC1saW5lLWhlaWdodCkpfTpob3ZlciAuYWN0aXZlLWluZGljYXRvcjo6YmVmb3Jle2JvcmRlci1ib3R0b20tY29sb3I6dmFyKC0tX2hvdmVyLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3IpO2JvcmRlci1ib3R0b20td2lkdGg6dmFyKC0tX2hvdmVyLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0KX0uYWN0aXZlLWluZGljYXRvcjo6YWZ0ZXJ7Ym9yZGVyLWJvdHRvbS1jb2xvcjp2YXIoLS1fZm9jdXMtYWN0aXZlLWluZGljYXRvci1jb2xvcik7Ym9yZGVyLWJvdHRvbS13aWR0aDp2YXIoLS1fZm9jdXMtYWN0aXZlLWluZGljYXRvci1oZWlnaHQpfTpob3ZlciAuc3RhdGUtbGF5ZXJ7YmFja2dyb3VuZDp2YXIoLS1faG92ZXItc3RhdGUtbGF5ZXItY29sb3IpO29wYWNpdHk6dmFyKC0tX2hvdmVyLXN0YXRlLWxheWVyLW9wYWNpdHkpfS5kaXNhYmxlZCAuYWN0aXZlLWluZGljYXRvcjo6YmVmb3Jle2JvcmRlci1ib3R0b20tY29sb3I6dmFyKC0tX2Rpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3IpO2JvcmRlci1ib3R0b20td2lkdGg6dmFyKC0tX2Rpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0KTtvcGFjaXR5OnZhcigtLV9kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLW9wYWNpdHkpfS5kaXNhYmxlZCAuYmFja2dyb3VuZHtiYWNrZ3JvdW5kOnZhcigtLV9kaXNhYmxlZC1jb250YWluZXItY29sb3IpO29wYWNpdHk6dmFyKC0tX2Rpc2FibGVkLWNvbnRhaW5lci1vcGFjaXR5KX0uZXJyb3IgLmFjdGl2ZS1pbmRpY2F0b3I6OmJlZm9yZXtib3JkZXItYm90dG9tLWNvbG9yOnZhcigtLV9lcnJvci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yKX0uZXJyb3I6aG92ZXIgLmFjdGl2ZS1pbmRpY2F0b3I6OmJlZm9yZXtib3JkZXItYm90dG9tLWNvbG9yOnZhcigtLV9lcnJvci1ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yKX0uZXJyb3I6aG92ZXIgLnN0YXRlLWxheWVye2JhY2tncm91bmQ6dmFyKC0tX2Vycm9yLWhvdmVyLXN0YXRlLWxheWVyLWNvbG9yKTtvcGFjaXR5OnZhcigtLV9lcnJvci1ob3Zlci1zdGF0ZS1sYXllci1vcGFjaXR5KX0uZXJyb3IgLmFjdGl2ZS1pbmRpY2F0b3I6OmFmdGVye2JvcmRlci1ib3R0b20tY29sb3I6dmFyKC0tX2Vycm9yLWZvY3VzLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3IpfS5yZXNpemFibGUgLmNvbnRhaW5lcntib3R0b206dmFyKC0tX2ZvY3VzLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0KTtjbGlwLXBhdGg6aW5zZXQodmFyKC0tX2ZvY3VzLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0KSAwIDAgMCl9LnJlc2l6YWJsZSAuY29udGFpbmVyPip7dG9wOnZhcigtLV9mb2N1cy1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodCl9fUBsYXllciBoY217QG1lZGlhKGZvcmNlZC1jb2xvcnM6IGFjdGl2ZSl7LmRpc2FibGVkIC5hY3RpdmUtaW5kaWNhdG9yOjpiZWZvcmV7Ym9yZGVyLWNvbG9yOkdyYXlUZXh0O29wYWNpdHk6MX19fVxuYDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWZpbGxlZC1zdHlsZXMuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjQgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuLy8gR2VuZXJhdGVkIHN0eWxlc2hlZXQgZm9yIC4vZmllbGQvaW50ZXJuYWwvc2hhcmVkLXN0eWxlcy5jc3MuXG5pbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuZXhwb3J0IGNvbnN0IHN0eWxlcyA9IGNzcyBgOmhvc3R7ZGlzcGxheTppbmxpbmUtZmxleDtyZXNpemU6Ym90aH0uZmllbGR7ZGlzcGxheTpmbGV4O2ZsZXg6MTtmbGV4LWRpcmVjdGlvbjpjb2x1bW47d3JpdGluZy1tb2RlOmhvcml6b250YWwtdGI7bWF4LXdpZHRoOjEwMCV9LmNvbnRhaW5lci1vdmVyZmxvd3tib3JkZXItc3RhcnQtc3RhcnQtcmFkaXVzOnZhcigtLV9jb250YWluZXItc2hhcGUtc3RhcnQtc3RhcnQpO2JvcmRlci1zdGFydC1lbmQtcmFkaXVzOnZhcigtLV9jb250YWluZXItc2hhcGUtc3RhcnQtZW5kKTtib3JkZXItZW5kLWVuZC1yYWRpdXM6dmFyKC0tX2NvbnRhaW5lci1zaGFwZS1lbmQtZW5kKTtib3JkZXItZW5kLXN0YXJ0LXJhZGl1czp2YXIoLS1fY29udGFpbmVyLXNoYXBlLWVuZC1zdGFydCk7ZGlzcGxheTpmbGV4O2hlaWdodDoxMDAlO3Bvc2l0aW9uOnJlbGF0aXZlfS5jb250YWluZXJ7YWxpZ24taXRlbXM6Y2VudGVyO2JvcmRlci1yYWRpdXM6aW5oZXJpdDtkaXNwbGF5OmZsZXg7ZmxleDoxO21heC1oZWlnaHQ6MTAwJTttaW4taGVpZ2h0OjEwMCU7bWluLXdpZHRoOm1pbi1jb250ZW50O3Bvc2l0aW9uOnJlbGF0aXZlfS5maWVsZCwuY29udGFpbmVyLW92ZXJmbG93e3Jlc2l6ZTppbmhlcml0fS5yZXNpemFibGU6bm90KC5kaXNhYmxlZCkgLmNvbnRhaW5lcntyZXNpemU6aW5oZXJpdDtvdmVyZmxvdzpoaWRkZW59LmRpc2FibGVke3BvaW50ZXItZXZlbnRzOm5vbmV9c2xvdFtuYW1lPWNvbnRhaW5lcl17Ym9yZGVyLXJhZGl1czppbmhlcml0fXNsb3RbbmFtZT1jb250YWluZXJdOjpzbG90dGVkKCope2JvcmRlci1yYWRpdXM6aW5oZXJpdDtpbnNldDowO3BvaW50ZXItZXZlbnRzOm5vbmU7cG9zaXRpb246YWJzb2x1dGV9QGxheWVyIHN0eWxlc3suc3RhcnQsLm1pZGRsZSwuZW5ke2Rpc3BsYXk6ZmxleDtib3gtc2l6aW5nOmJvcmRlci1ib3g7aGVpZ2h0OjEwMCU7cG9zaXRpb246cmVsYXRpdmV9LnN0YXJ0e2NvbG9yOnZhcigtLV9sZWFkaW5nLWNvbnRlbnQtY29sb3IpfS5lbmR7Y29sb3I6dmFyKC0tX3RyYWlsaW5nLWNvbnRlbnQtY29sb3IpfS5zdGFydCwuZW5ke2FsaWduLWl0ZW1zOmNlbnRlcjtqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyfS53aXRoLXN0YXJ0IC5zdGFydHttYXJnaW4taW5saW5lOnZhcigtLV93aXRoLWxlYWRpbmctY29udGVudC1sZWFkaW5nLXNwYWNlKSB2YXIoLS1fY29udGVudC1zcGFjZSl9LndpdGgtZW5kIC5lbmR7bWFyZ2luLWlubGluZTp2YXIoLS1fY29udGVudC1zcGFjZSkgdmFyKC0tX3dpdGgtdHJhaWxpbmctY29udGVudC10cmFpbGluZy1zcGFjZSl9Lm1pZGRsZXthbGlnbi1pdGVtczpzdHJldGNoO2FsaWduLXNlbGY6YmFzZWxpbmU7ZmxleDoxfS5jb250ZW50e2NvbG9yOnZhcigtLV9jb250ZW50LWNvbG9yKTtkaXNwbGF5OmZsZXg7ZmxleDoxO29wYWNpdHk6MDt0cmFuc2l0aW9uOm9wYWNpdHkgODNtcyBjdWJpYy1iZXppZXIoMC4yLCAwLCAwLCAxKX0ubm8tbGFiZWwgLmNvbnRlbnQsLmZvY3VzZWQgLmNvbnRlbnQsLnBvcHVsYXRlZCAuY29udGVudHtvcGFjaXR5OjE7dHJhbnNpdGlvbi1kZWxheTo2N21zfTppcyguZGlzYWJsZWQsLmRpc2FibGUtdHJhbnNpdGlvbnMpIC5jb250ZW50e3RyYW5zaXRpb246bm9uZX0uY29udGVudCA6OnNsb3R0ZWQoKil7YWxsOnVuc2V0O2NvbG9yOmN1cnJlbnRDb2xvcjtmb250LWZhbWlseTp2YXIoLS1fY29udGVudC1mb250KTtmb250LXNpemU6dmFyKC0tX2NvbnRlbnQtc2l6ZSk7bGluZS1oZWlnaHQ6dmFyKC0tX2NvbnRlbnQtbGluZS1oZWlnaHQpO2ZvbnQtd2VpZ2h0OnZhcigtLV9jb250ZW50LXdlaWdodCk7d2lkdGg6MTAwJTtvdmVyZmxvdy13cmFwOnJldmVydDt3aGl0ZS1zcGFjZTpyZXZlcnR9LmNvbnRlbnQgOjpzbG90dGVkKDpub3QodGV4dGFyZWEpKXtwYWRkaW5nLXRvcDp2YXIoLS1fdG9wLXNwYWNlKTtwYWRkaW5nLWJvdHRvbTp2YXIoLS1fYm90dG9tLXNwYWNlKX0uY29udGVudCA6OnNsb3R0ZWQodGV4dGFyZWEpe21hcmdpbi10b3A6dmFyKC0tX3RvcC1zcGFjZSk7bWFyZ2luLWJvdHRvbTp2YXIoLS1fYm90dG9tLXNwYWNlKX06aG92ZXIgLmNvbnRlbnR7Y29sb3I6dmFyKC0tX2hvdmVyLWNvbnRlbnQtY29sb3IpfTpob3ZlciAuc3RhcnR7Y29sb3I6dmFyKC0tX2hvdmVyLWxlYWRpbmctY29udGVudC1jb2xvcil9OmhvdmVyIC5lbmR7Y29sb3I6dmFyKC0tX2hvdmVyLXRyYWlsaW5nLWNvbnRlbnQtY29sb3IpfS5mb2N1c2VkIC5jb250ZW50e2NvbG9yOnZhcigtLV9mb2N1cy1jb250ZW50LWNvbG9yKX0uZm9jdXNlZCAuc3RhcnR7Y29sb3I6dmFyKC0tX2ZvY3VzLWxlYWRpbmctY29udGVudC1jb2xvcil9LmZvY3VzZWQgLmVuZHtjb2xvcjp2YXIoLS1fZm9jdXMtdHJhaWxpbmctY29udGVudC1jb2xvcil9LmRpc2FibGVkIC5jb250ZW50e2NvbG9yOnZhcigtLV9kaXNhYmxlZC1jb250ZW50LWNvbG9yKX0uZGlzYWJsZWQubm8tbGFiZWwgLmNvbnRlbnQsLmRpc2FibGVkLmZvY3VzZWQgLmNvbnRlbnQsLmRpc2FibGVkLnBvcHVsYXRlZCAuY29udGVudHtvcGFjaXR5OnZhcigtLV9kaXNhYmxlZC1jb250ZW50LW9wYWNpdHkpfS5kaXNhYmxlZCAuc3RhcnR7Y29sb3I6dmFyKC0tX2Rpc2FibGVkLWxlYWRpbmctY29udGVudC1jb2xvcik7b3BhY2l0eTp2YXIoLS1fZGlzYWJsZWQtbGVhZGluZy1jb250ZW50LW9wYWNpdHkpfS5kaXNhYmxlZCAuZW5ke2NvbG9yOnZhcigtLV9kaXNhYmxlZC10cmFpbGluZy1jb250ZW50LWNvbG9yKTtvcGFjaXR5OnZhcigtLV9kaXNhYmxlZC10cmFpbGluZy1jb250ZW50LW9wYWNpdHkpfS5lcnJvciAuY29udGVudHtjb2xvcjp2YXIoLS1fZXJyb3ItY29udGVudC1jb2xvcil9LmVycm9yIC5zdGFydHtjb2xvcjp2YXIoLS1fZXJyb3ItbGVhZGluZy1jb250ZW50LWNvbG9yKX0uZXJyb3IgLmVuZHtjb2xvcjp2YXIoLS1fZXJyb3ItdHJhaWxpbmctY29udGVudC1jb2xvcil9LmVycm9yOmhvdmVyIC5jb250ZW50e2NvbG9yOnZhcigtLV9lcnJvci1ob3Zlci1jb250ZW50LWNvbG9yKX0uZXJyb3I6aG92ZXIgLnN0YXJ0e2NvbG9yOnZhcigtLV9lcnJvci1ob3Zlci1sZWFkaW5nLWNvbnRlbnQtY29sb3IpfS5lcnJvcjpob3ZlciAuZW5ke2NvbG9yOnZhcigtLV9lcnJvci1ob3Zlci10cmFpbGluZy1jb250ZW50LWNvbG9yKX0uZXJyb3IuZm9jdXNlZCAuY29udGVudHtjb2xvcjp2YXIoLS1fZXJyb3ItZm9jdXMtY29udGVudC1jb2xvcil9LmVycm9yLmZvY3VzZWQgLnN0YXJ0e2NvbG9yOnZhcigtLV9lcnJvci1mb2N1cy1sZWFkaW5nLWNvbnRlbnQtY29sb3IpfS5lcnJvci5mb2N1c2VkIC5lbmR7Y29sb3I6dmFyKC0tX2Vycm9yLWZvY3VzLXRyYWlsaW5nLWNvbnRlbnQtY29sb3IpfX1AbGF5ZXIgaGNte0BtZWRpYShmb3JjZWQtY29sb3JzOiBhY3RpdmUpey5kaXNhYmxlZCA6aXMoLnN0YXJ0LC5jb250ZW50LC5lbmQpe2NvbG9yOkdyYXlUZXh0O29wYWNpdHk6MX19fUBsYXllciBzdHlsZXN7LmxhYmVse2JveC1zaXppbmc6Ym9yZGVyLWJveDtjb2xvcjp2YXIoLS1fbGFiZWwtdGV4dC1jb2xvcik7b3ZlcmZsb3c6aGlkZGVuO21heC13aWR0aDoxMDAlO3RleHQtb3ZlcmZsb3c6ZWxsaXBzaXM7d2hpdGUtc3BhY2U6bm93cmFwO3otaW5kZXg6MTtmb250LWZhbWlseTp2YXIoLS1fbGFiZWwtdGV4dC1mb250KTtmb250LXNpemU6dmFyKC0tX2xhYmVsLXRleHQtc2l6ZSk7bGluZS1oZWlnaHQ6dmFyKC0tX2xhYmVsLXRleHQtbGluZS1oZWlnaHQpO2ZvbnQtd2VpZ2h0OnZhcigtLV9sYWJlbC10ZXh0LXdlaWdodCk7d2lkdGg6bWluLWNvbnRlbnR9LmxhYmVsLXdyYXBwZXJ7aW5zZXQ6MDtwb2ludGVyLWV2ZW50czpub25lO3Bvc2l0aW9uOmFic29sdXRlfS5sYWJlbC5yZXN0aW5ne3Bvc2l0aW9uOmFic29sdXRlO3RvcDp2YXIoLS1fdG9wLXNwYWNlKX0ubGFiZWwuZmxvYXRpbmd7Zm9udC1zaXplOnZhcigtLV9sYWJlbC10ZXh0LXBvcHVsYXRlZC1zaXplKTtsaW5lLWhlaWdodDp2YXIoLS1fbGFiZWwtdGV4dC1wb3B1bGF0ZWQtbGluZS1oZWlnaHQpO3RyYW5zZm9ybS1vcmlnaW46dG9wIGxlZnR9LmxhYmVsLmhpZGRlbntvcGFjaXR5OjB9Lm5vLWxhYmVsIC5sYWJlbHtkaXNwbGF5Om5vbmV9LmxhYmVsLXdyYXBwZXJ7aW5zZXQ6MDtwb3NpdGlvbjphYnNvbHV0ZTt0ZXh0LWFsaWduOmluaXRpYWx9OmhvdmVyIC5sYWJlbHtjb2xvcjp2YXIoLS1faG92ZXItbGFiZWwtdGV4dC1jb2xvcil9LmZvY3VzZWQgLmxhYmVse2NvbG9yOnZhcigtLV9mb2N1cy1sYWJlbC10ZXh0LWNvbG9yKX0uZGlzYWJsZWQgLmxhYmVse2NvbG9yOnZhcigtLV9kaXNhYmxlZC1sYWJlbC10ZXh0LWNvbG9yKX0uZGlzYWJsZWQgLmxhYmVsOm5vdCguaGlkZGVuKXtvcGFjaXR5OnZhcigtLV9kaXNhYmxlZC1sYWJlbC10ZXh0LW9wYWNpdHkpfS5lcnJvciAubGFiZWx7Y29sb3I6dmFyKC0tX2Vycm9yLWxhYmVsLXRleHQtY29sb3IpfS5lcnJvcjpob3ZlciAubGFiZWx7Y29sb3I6dmFyKC0tX2Vycm9yLWhvdmVyLWxhYmVsLXRleHQtY29sb3IpfS5lcnJvci5mb2N1c2VkIC5sYWJlbHtjb2xvcjp2YXIoLS1fZXJyb3ItZm9jdXMtbGFiZWwtdGV4dC1jb2xvcil9fUBsYXllciBoY217QG1lZGlhKGZvcmNlZC1jb2xvcnM6IGFjdGl2ZSl7LmRpc2FibGVkIC5sYWJlbDpub3QoLmhpZGRlbil7Y29sb3I6R3JheVRleHQ7b3BhY2l0eToxfX19QGxheWVyIHN0eWxlc3suc3VwcG9ydGluZy10ZXh0e2NvbG9yOnZhcigtLV9zdXBwb3J0aW5nLXRleHQtY29sb3IpO2Rpc3BsYXk6ZmxleDtmb250LWZhbWlseTp2YXIoLS1fc3VwcG9ydGluZy10ZXh0LWZvbnQpO2ZvbnQtc2l6ZTp2YXIoLS1fc3VwcG9ydGluZy10ZXh0LXNpemUpO2xpbmUtaGVpZ2h0OnZhcigtLV9zdXBwb3J0aW5nLXRleHQtbGluZS1oZWlnaHQpO2ZvbnQtd2VpZ2h0OnZhcigtLV9zdXBwb3J0aW5nLXRleHQtd2VpZ2h0KTtnYXA6MTZweDtqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjtwYWRkaW5nLWlubGluZS1zdGFydDp2YXIoLS1fc3VwcG9ydGluZy10ZXh0LWxlYWRpbmctc3BhY2UpO3BhZGRpbmctaW5saW5lLWVuZDp2YXIoLS1fc3VwcG9ydGluZy10ZXh0LXRyYWlsaW5nLXNwYWNlKTtwYWRkaW5nLXRvcDp2YXIoLS1fc3VwcG9ydGluZy10ZXh0LXRvcC1zcGFjZSl9LnN1cHBvcnRpbmctdGV4dCA6bnRoLWNoaWxkKDIpe2ZsZXgtc2hyaW5rOjB9OmhvdmVyIC5zdXBwb3J0aW5nLXRleHR7Y29sb3I6dmFyKC0tX2hvdmVyLXN1cHBvcnRpbmctdGV4dC1jb2xvcil9LmZvY3VzIC5zdXBwb3J0aW5nLXRleHR7Y29sb3I6dmFyKC0tX2ZvY3VzLXN1cHBvcnRpbmctdGV4dC1jb2xvcil9LmRpc2FibGVkIC5zdXBwb3J0aW5nLXRleHR7Y29sb3I6dmFyKC0tX2Rpc2FibGVkLXN1cHBvcnRpbmctdGV4dC1jb2xvcik7b3BhY2l0eTp2YXIoLS1fZGlzYWJsZWQtc3VwcG9ydGluZy10ZXh0LW9wYWNpdHkpfS5lcnJvciAuc3VwcG9ydGluZy10ZXh0e2NvbG9yOnZhcigtLV9lcnJvci1zdXBwb3J0aW5nLXRleHQtY29sb3IpfS5lcnJvcjpob3ZlciAuc3VwcG9ydGluZy10ZXh0e2NvbG9yOnZhcigtLV9lcnJvci1ob3Zlci1zdXBwb3J0aW5nLXRleHQtY29sb3IpfS5lcnJvci5mb2N1cyAuc3VwcG9ydGluZy10ZXh0e2NvbG9yOnZhcigtLV9lcnJvci1mb2N1cy1zdXBwb3J0aW5nLXRleHQtY29sb3IpfX1AbGF5ZXIgaGNte0BtZWRpYShmb3JjZWQtY29sb3JzOiBhY3RpdmUpey5kaXNhYmxlZCAuc3VwcG9ydGluZy10ZXh0e2NvbG9yOkdyYXlUZXh0O29wYWNpdHk6MX19fVxuYDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXNoYXJlZC1zdHlsZXMuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMTggR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuaW1wb3J0IHsgX19kZWNvcmF0ZSB9IGZyb20gXCJ0c2xpYlwiO1xuaW1wb3J0ICcuLi8uLi9mb2N1cy9tZC1mb2N1cy1yaW5nLmpzJztcbmltcG9ydCAnLi4vLi4vcmlwcGxlL3JpcHBsZS5qcyc7XG5pbXBvcnQgeyBodG1sLCBpc1NlcnZlciwgTGl0RWxlbWVudCwgbm90aGluZyB9IGZyb20gJ2xpdCc7XG5pbXBvcnQgeyBwcm9wZXJ0eSwgc3RhdGUgfSBmcm9tICdsaXQvZGVjb3JhdG9ycy5qcyc7XG5pbXBvcnQgeyBjbGFzc01hcCB9IGZyb20gJ2xpdC9kaXJlY3RpdmVzL2NsYXNzLW1hcC5qcyc7XG5pbXBvcnQgeyBsaXRlcmFsLCBodG1sIGFzIHN0YXRpY0h0bWwgfSBmcm9tICdsaXQvc3RhdGljLWh0bWwuanMnO1xuaW1wb3J0IHsgbWl4aW5EZWxlZ2F0ZXNBcmlhIH0gZnJvbSAnLi4vLi4vaW50ZXJuYWwvYXJpYS9kZWxlZ2F0ZS5qcyc7XG5pbXBvcnQgeyBzZXR1cEZvcm1TdWJtaXR0ZXIsIH0gZnJvbSAnLi4vLi4vaW50ZXJuYWwvY29udHJvbGxlci9mb3JtLXN1Ym1pdHRlci5qcyc7XG5pbXBvcnQgeyBpc1J0bCB9IGZyb20gJy4uLy4uL2ludGVybmFsL2NvbnRyb2xsZXIvaXMtcnRsLmpzJztcbmltcG9ydCB7IGludGVybmFscywgbWl4aW5FbGVtZW50SW50ZXJuYWxzLCB9IGZyb20gJy4uLy4uL2xhYnMvYmVoYXZpb3JzL2VsZW1lbnQtaW50ZXJuYWxzLmpzJztcbi8vIFNlcGFyYXRlIHZhcmlhYmxlIG5lZWRlZCBmb3IgY2xvc3VyZS5cbmNvbnN0IGljb25CdXR0b25CYXNlQ2xhc3MgPSBtaXhpbkRlbGVnYXRlc0FyaWEobWl4aW5FbGVtZW50SW50ZXJuYWxzKExpdEVsZW1lbnQpKTtcbi8qKlxuICogQSBidXR0b24gZm9yIHJlbmRlcmluZyBpY29ucy5cbiAqXG4gKiBAZmlyZXMgaW5wdXQge0lucHV0RXZlbnR9IERpc3BhdGNoZWQgd2hlbiBhIHRvZ2dsZSBidXR0b24gdG9nZ2xlcyAtLWJ1YmJsZXNcbiAqIC0tY29tcG9zZWRcbiAqIEBmaXJlcyBjaGFuZ2Uge0V2ZW50fSBEaXNwYXRjaGVkIHdoZW4gYSB0b2dnbGUgYnV0dG9uIHRvZ2dsZXMgLS1idWJibGVzXG4gKi9cbmV4cG9ydCBjbGFzcyBJY29uQnV0dG9uIGV4dGVuZHMgaWNvbkJ1dHRvbkJhc2VDbGFzcyB7XG4gICAgZ2V0IG5hbWUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEF0dHJpYnV0ZSgnbmFtZScpID8/ICcnO1xuICAgIH1cbiAgICBzZXQgbmFtZShuYW1lKSB7XG4gICAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCduYW1lJywgbmFtZSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoZSBhc3NvY2lhdGVkIGZvcm0gZWxlbWVudCB3aXRoIHdoaWNoIHRoaXMgZWxlbWVudCdzIHZhbHVlIHdpbGwgc3VibWl0LlxuICAgICAqL1xuICAgIGdldCBmb3JtKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tpbnRlcm5hbHNdLmZvcm07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoZSBsYWJlbHMgdGhpcyBlbGVtZW50IGlzIGFzc29jaWF0ZWQgd2l0aC5cbiAgICAgKi9cbiAgICBnZXQgbGFiZWxzKCkge1xuICAgICAgICByZXR1cm4gdGhpc1tpbnRlcm5hbHNdLmxhYmVscztcbiAgICB9XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEaXNhYmxlcyB0aGUgaWNvbiBidXR0b24gYW5kIG1ha2VzIGl0IG5vbi1pbnRlcmFjdGl2ZS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFwiU29mdC1kaXNhYmxlc1wiIHRoZSBpY29uIGJ1dHRvbiAoZGlzYWJsZWQgYnV0IHN0aWxsIGZvY3VzYWJsZSkuXG4gICAgICAgICAqXG4gICAgICAgICAqIFVzZSB0aGlzIHdoZW4gYW4gaWNvbiBidXR0b24gbmVlZHMgaW5jcmVhc2VkIHZpc2liaWxpdHkgd2hlbiBkaXNhYmxlZC4gU2VlXG4gICAgICAgICAqIGh0dHBzOi8vd3d3LnczLm9yZy9XQUkvQVJJQS9hcGcvcHJhY3RpY2VzL2tleWJvYXJkLWludGVyZmFjZS8ja2JkX2Rpc2FibGVkX2NvbnRyb2xzXG4gICAgICAgICAqIGZvciBtb3JlIGd1aWRhbmNlIG9uIHdoZW4gdGhpcyBpcyBuZWVkZWQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnNvZnREaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogRmxpcHMgdGhlIGljb24gaWYgaXQgaXMgaW4gYW4gUlRMIGNvbnRleHQgYXQgc3RhcnR1cC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZmxpcEljb25JblJ0bCA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyB0aGUgdW5kZXJseWluZyBgSFRNTEFuY2hvckVsZW1lbnRgJ3MgYGhyZWZgIHJlc291cmNlIGF0dHJpYnV0ZS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaHJlZiA9ICcnO1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIGZpbGVuYW1lIHRvIHVzZSB3aGVuIGRvd25sb2FkaW5nIHRoZSBsaW5rZWQgcmVzb3VyY2UuXG4gICAgICAgICAqIElmIG5vdCBzcGVjaWZpZWQsIHRoZSBicm93c2VyIHdpbGwgZGV0ZXJtaW5lIGEgZmlsZW5hbWUuXG4gICAgICAgICAqIFRoaXMgaXMgb25seSBhcHBsaWNhYmxlIHdoZW4gdGhlIGljb24gYnV0dG9uIGlzIHVzZWQgYXMgYSBsaW5rIChgaHJlZmAgaXMgc2V0KS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZG93bmxvYWQgPSAnJztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNldHMgdGhlIHVuZGVybHlpbmcgYEhUTUxBbmNob3JFbGVtZW50YCdzIGB0YXJnZXRgIGF0dHJpYnV0ZS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMudGFyZ2V0ID0gJyc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgYGFyaWEtbGFiZWxgIG9mIHRoZSBidXR0b24gd2hlbiB0aGUgYnV0dG9uIGlzIHRvZ2dsZWFibGUgYW5kIHNlbGVjdGVkLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5hcmlhTGFiZWxTZWxlY3RlZCA9ICcnO1xuICAgICAgICAvKipcbiAgICAgICAgICogV2hlbiB0cnVlLCB0aGUgYnV0dG9uIHdpbGwgdG9nZ2xlIGJldHdlZW4gc2VsZWN0ZWQgYW5kIHVuc2VsZWN0ZWRcbiAgICAgICAgICogc3RhdGVzXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnRvZ2dsZSA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyB0aGUgc2VsZWN0ZWQgc3RhdGUuIFdoZW4gZmFsc2UsIGRpc3BsYXlzIHRoZSBkZWZhdWx0IGljb24uIFdoZW4gdHJ1ZSxcbiAgICAgICAgICogZGlzcGxheXMgdGhlIHNlbGVjdGVkIGljb24sIG9yIHRoZSBkZWZhdWx0IGljb24gSWYgbm8gYHNsb3Q9XCJzZWxlY3RlZFwiYFxuICAgICAgICAgKiBpY29uIGlzIHByb3ZpZGVkLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5zZWxlY3RlZCA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIGRlZmF1bHQgYmVoYXZpb3Igb2YgdGhlIGJ1dHRvbi4gTWF5IGJlIFwiYnV0dG9uXCIsIFwicmVzZXRcIiwgb3IgXCJzdWJtaXRcIlxuICAgICAgICAgKiAoZGVmYXVsdCkuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnR5cGUgPSAnc3VibWl0JztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSB2YWx1ZSBhZGRlZCB0byBhIGZvcm0gd2l0aCB0aGUgYnV0dG9uJ3MgbmFtZSB3aGVuIHRoZSBidXR0b24gc3VibWl0cyBhXG4gICAgICAgICAqIGZvcm0uXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnZhbHVlID0gJyc7XG4gICAgICAgIHRoaXMuZmxpcEljb24gPSBpc1J0bCh0aGlzLCB0aGlzLmZsaXBJY29uSW5SdGwpO1xuICAgICAgICBpZiAoIWlzU2VydmVyKSB7XG4gICAgICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5oYW5kbGVDbGljay5iaW5kKHRoaXMpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB3aWxsVXBkYXRlKCkge1xuICAgICAgICAvLyBMaW5rIGJ1dHRvbnMgY2Fubm90IGJlIGRpc2FibGVkIG9yIHNvZnQtZGlzYWJsZWQuXG4gICAgICAgIGlmICh0aGlzLmhyZWYpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuc29mdERpc2FibGVkID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmVuZGVyKCkge1xuICAgICAgICBjb25zdCB0YWcgPSB0aGlzLmhyZWYgPyBsaXRlcmFsIGBkaXZgIDogbGl0ZXJhbCBgYnV0dG9uYDtcbiAgICAgICAgLy8gTmVlZGVkIGZvciBjbG9zdXJlIGNvbmZvcm1hbmNlXG4gICAgICAgIGNvbnN0IHsgYXJpYUxhYmVsLCBhcmlhSGFzUG9wdXAsIGFyaWFFeHBhbmRlZCB9ID0gdGhpcztcbiAgICAgICAgY29uc3QgaGFzVG9nZ2xlZEFyaWFMYWJlbCA9IGFyaWFMYWJlbCAmJiB0aGlzLmFyaWFMYWJlbFNlbGVjdGVkO1xuICAgICAgICBjb25zdCBhcmlhUHJlc3NlZFZhbHVlID0gIXRoaXMudG9nZ2xlID8gbm90aGluZyA6IHRoaXMuc2VsZWN0ZWQ7XG4gICAgICAgIGxldCBhcmlhTGFiZWxWYWx1ZSA9IG5vdGhpbmc7XG4gICAgICAgIGlmICghdGhpcy5ocmVmKSB7XG4gICAgICAgICAgICBhcmlhTGFiZWxWYWx1ZSA9XG4gICAgICAgICAgICAgICAgaGFzVG9nZ2xlZEFyaWFMYWJlbCAmJiB0aGlzLnNlbGVjdGVkXG4gICAgICAgICAgICAgICAgICAgID8gdGhpcy5hcmlhTGFiZWxTZWxlY3RlZFxuICAgICAgICAgICAgICAgICAgICA6IGFyaWFMYWJlbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RhdGljSHRtbCBgPCR7dGFnfVxuICAgICAgICBjbGFzcz1cImljb24tYnV0dG9uICR7Y2xhc3NNYXAodGhpcy5nZXRSZW5kZXJDbGFzc2VzKCkpfVwiXG4gICAgICAgIGlkPVwiYnV0dG9uXCJcbiAgICAgICAgYXJpYS1sYWJlbD1cIiR7YXJpYUxhYmVsVmFsdWUgfHwgbm90aGluZ31cIlxuICAgICAgICBhcmlhLWhhc3BvcHVwPVwiJHsoIXRoaXMuaHJlZiAmJiBhcmlhSGFzUG9wdXApIHx8IG5vdGhpbmd9XCJcbiAgICAgICAgYXJpYS1leHBhbmRlZD1cIiR7KCF0aGlzLmhyZWYgJiYgYXJpYUV4cGFuZGVkKSB8fCBub3RoaW5nfVwiXG4gICAgICAgIGFyaWEtcHJlc3NlZD1cIiR7YXJpYVByZXNzZWRWYWx1ZX1cIlxuICAgICAgICBhcmlhLWRpc2FibGVkPSR7KCF0aGlzLmhyZWYgJiYgdGhpcy5zb2Z0RGlzYWJsZWQpIHx8IG5vdGhpbmd9XG4gICAgICAgID9kaXNhYmxlZD1cIiR7IXRoaXMuaHJlZiAmJiB0aGlzLmRpc2FibGVkfVwiXG4gICAgICAgIEBjbGljaz1cIiR7dGhpcy5oYW5kbGVDbGlja09uQ2hpbGR9XCI+XG4gICAgICAgICR7dGhpcy5yZW5kZXJGb2N1c1JpbmcoKX1cbiAgICAgICAgJHt0aGlzLnJlbmRlclJpcHBsZSgpfVxuICAgICAgICAkeyF0aGlzLnNlbGVjdGVkID8gdGhpcy5yZW5kZXJJY29uKCkgOiBub3RoaW5nfVxuICAgICAgICAke3RoaXMuc2VsZWN0ZWQgPyB0aGlzLnJlbmRlclNlbGVjdGVkSWNvbigpIDogbm90aGluZ31cbiAgICAgICAgJHt0aGlzLmhyZWYgPyB0aGlzLnJlbmRlckxpbmsoKSA6IHRoaXMucmVuZGVyVG91Y2hUYXJnZXQoKX1cbiAgPC8ke3RhZ30+YDtcbiAgICB9XG4gICAgcmVuZGVyTGluaygpIHtcbiAgICAgICAgLy8gTmVlZGVkIGZvciBjbG9zdXJlIGNvbmZvcm1hbmNlXG4gICAgICAgIGNvbnN0IHsgYXJpYUxhYmVsIH0gPSB0aGlzO1xuICAgICAgICByZXR1cm4gaHRtbCBgXG4gICAgICA8YVxuICAgICAgICBjbGFzcz1cImxpbmtcIlxuICAgICAgICBpZD1cImxpbmtcIlxuICAgICAgICBocmVmPVwiJHt0aGlzLmhyZWZ9XCJcbiAgICAgICAgZG93bmxvYWQ9XCIke3RoaXMuZG93bmxvYWQgfHwgbm90aGluZ31cIlxuICAgICAgICB0YXJnZXQ9XCIke3RoaXMudGFyZ2V0IHx8IG5vdGhpbmd9XCJcbiAgICAgICAgYXJpYS1sYWJlbD1cIiR7YXJpYUxhYmVsIHx8IG5vdGhpbmd9XCI+XG4gICAgICAgICR7dGhpcy5yZW5kZXJUb3VjaFRhcmdldCgpfVxuICAgICAgPC9hPlxuICAgIGA7XG4gICAgfVxuICAgIGdldFJlbmRlckNsYXNzZXMoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAnZmxpcC1pY29uJzogdGhpcy5mbGlwSWNvbixcbiAgICAgICAgICAgICdzZWxlY3RlZCc6IHRoaXMudG9nZ2xlICYmIHRoaXMuc2VsZWN0ZWQsXG4gICAgICAgIH07XG4gICAgfVxuICAgIHJlbmRlckljb24oKSB7XG4gICAgICAgIHJldHVybiBodG1sIGA8c3BhbiBjbGFzcz1cImljb25cIj48c2xvdD48L3Nsb3Q+PC9zcGFuPmA7XG4gICAgfVxuICAgIHJlbmRlclNlbGVjdGVkSWNvbigpIHtcbiAgICAgICAgLy8gVXNlIGRlZmF1bHQgc2xvdCBhcyBmYWxsYmFjayB0byBub3QgcmVxdWlyZSBzcGVjaWZ5aW5nIG11bHRpcGxlIGljb25zXG4gICAgICAgIHJldHVybiBodG1sIGA8c3BhbiBjbGFzcz1cImljb24gaWNvbi0tc2VsZWN0ZWRcIlxuICAgICAgPjxzbG90IG5hbWU9XCJzZWxlY3RlZFwiPjxzbG90Pjwvc2xvdD48L3Nsb3RcbiAgICA+PC9zcGFuPmA7XG4gICAgfVxuICAgIHJlbmRlclRvdWNoVGFyZ2V0KCkge1xuICAgICAgICByZXR1cm4gaHRtbCBgPHNwYW4gY2xhc3M9XCJ0b3VjaFwiPjwvc3Bhbj5gO1xuICAgIH1cbiAgICByZW5kZXJGb2N1c1JpbmcoKSB7XG4gICAgICAgIC8vIFRPRE8oYi8zMTAwNDY5MzgpOiB1c2UgdGhlIHNhbWUgaWQgZm9yIGJvdGggZWxlbWVudHNcbiAgICAgICAgcmV0dXJuIGh0bWwgYDxtZC1mb2N1cy1yaW5nXG4gICAgICBwYXJ0PVwiZm9jdXMtcmluZ1wiXG4gICAgICBmb3I9JHt0aGlzLmhyZWYgPyAnbGluaycgOiAnYnV0dG9uJ30+PC9tZC1mb2N1cy1yaW5nPmA7XG4gICAgfVxuICAgIHJlbmRlclJpcHBsZSgpIHtcbiAgICAgICAgY29uc3QgaXNSaXBwbGVEaXNhYmxlZCA9ICF0aGlzLmhyZWYgJiYgKHRoaXMuZGlzYWJsZWQgfHwgdGhpcy5zb2Z0RGlzYWJsZWQpO1xuICAgICAgICAvLyBUT0RPKGIvMzEwMDQ2OTM4KTogdXNlIHRoZSBzYW1lIGlkIGZvciBib3RoIGVsZW1lbnRzXG4gICAgICAgIHJldHVybiBodG1sIGA8bWQtcmlwcGxlXG4gICAgICBmb3I9JHt0aGlzLmhyZWYgPyAnbGluaycgOiBub3RoaW5nfVxuICAgICAgP2Rpc2FibGVkPVwiJHtpc1JpcHBsZURpc2FibGVkfVwiPjwvbWQtcmlwcGxlPmA7XG4gICAgfVxuICAgIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgICAgICB0aGlzLmZsaXBJY29uID0gaXNSdGwodGhpcywgdGhpcy5mbGlwSWNvbkluUnRsKTtcbiAgICAgICAgc3VwZXIuY29ubmVjdGVkQ2FsbGJhY2soKTtcbiAgICB9XG4gICAgLyoqIEhhbmRsZXMgYSBjbGljayBvbiB0aGlzIGVsZW1lbnQuICovXG4gICAgaGFuZGxlQ2xpY2soZXZlbnQpIHtcbiAgICAgICAgLy8gSWYgdGhlIGljb24gYnV0dG9uIGlzIHNvZnQtZGlzYWJsZWQsIHdlIG5lZWQgdG8gZXhwbGljaXRseSBwcmV2ZW50IHRoZVxuICAgICAgICAvLyBjbGljayBmcm9tIHByb3BhZ2F0aW5nIHRvIG90aGVyIGV2ZW50IGxpc3RlbmVycyBhcyB3ZWxsIGFzIHByZXZlbnQgdGhlXG4gICAgICAgIC8vIGRlZmF1bHQgYWN0aW9uLlxuICAgICAgICBpZiAoIXRoaXMuaHJlZiAmJiB0aGlzLnNvZnREaXNhYmxlZCkge1xuICAgICAgICAgICAgZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgYSBjbGljayBvbiB0aGUgY2hpbGQgPGRpdj4gb3IgPGJ1dHRvbj4gZWxlbWVudCB3aXRoaW4gdGhpc1xuICAgICAqIGVsZW1lbnQncyBzaGFkb3cgRE9NLlxuICAgICAqL1xuICAgIGFzeW5jIGhhbmRsZUNsaWNrT25DaGlsZChldmVudCkge1xuICAgICAgICAvLyBBbGxvdyB0aGUgZXZlbnQgdG8gcHJvcGFnYXRlXG4gICAgICAgIGF3YWl0IDA7XG4gICAgICAgIGlmICghdGhpcy50b2dnbGUgfHxcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZWQgfHxcbiAgICAgICAgICAgIHRoaXMuc29mdERpc2FibGVkIHx8XG4gICAgICAgICAgICBldmVudC5kZWZhdWx0UHJldmVudGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZWxlY3RlZCA9ICF0aGlzLnNlbGVjdGVkO1xuICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IElucHV0RXZlbnQoJ2lucHV0JywgeyBidWJibGVzOiB0cnVlLCBjb21wb3NlZDogdHJ1ZSB9KSk7XG4gICAgICAgIC8vIEJ1YmJsZXMgYnV0IGRvZXMgbm90IGNvbXBvc2UgdG8gbWltaWMgbmF0aXZlIGJyb3dzZXIgPGlucHV0PiAmIDxzZWxlY3Q+XG4gICAgICAgIC8vIEFkZGl0aW9uYWxseSwgbmF0aXZlIGNoYW5nZSBldmVudCBpcyBub3QgYW4gSW5wdXRFdmVudC5cbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudCgnY2hhbmdlJywgeyBidWJibGVzOiB0cnVlIH0pKTtcbiAgICB9XG59XG4oKCkgPT4ge1xuICAgIHNldHVwRm9ybVN1Ym1pdHRlcihJY29uQnV0dG9uKTtcbn0pKCk7XG4vKiogQG5vY29sbGFwc2UgKi9cbkljb25CdXR0b24uZm9ybUFzc29jaWF0ZWQgPSB0cnVlO1xuLyoqIEBub2NvbGxhcHNlICovXG5JY29uQnV0dG9uLnNoYWRvd1Jvb3RPcHRpb25zID0ge1xuICAgIG1vZGU6ICdvcGVuJyxcbiAgICBkZWxlZ2F0ZXNGb2N1czogdHJ1ZSxcbn07XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IEJvb2xlYW4sIHJlZmxlY3Q6IHRydWUgfSlcbl0sIEljb25CdXR0b24ucHJvdG90eXBlLCBcImRpc2FibGVkXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IEJvb2xlYW4sIGF0dHJpYnV0ZTogJ3NvZnQtZGlzYWJsZWQnLCByZWZsZWN0OiB0cnVlIH0pXG5dLCBJY29uQnV0dG9uLnByb3RvdHlwZSwgXCJzb2Z0RGlzYWJsZWRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgYXR0cmlidXRlOiAnZmxpcC1pY29uLWluLXJ0bCcgfSlcbl0sIEljb25CdXR0b24ucHJvdG90eXBlLCBcImZsaXBJY29uSW5SdGxcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KClcbl0sIEljb25CdXR0b24ucHJvdG90eXBlLCBcImhyZWZcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KClcbl0sIEljb25CdXR0b24ucHJvdG90eXBlLCBcImRvd25sb2FkXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSgpXG5dLCBJY29uQnV0dG9uLnByb3RvdHlwZSwgXCJ0YXJnZXRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgYXR0cmlidXRlOiAnYXJpYS1sYWJlbC1zZWxlY3RlZCcgfSlcbl0sIEljb25CdXR0b24ucHJvdG90eXBlLCBcImFyaWFMYWJlbFNlbGVjdGVkXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IEJvb2xlYW4gfSlcbl0sIEljb25CdXR0b24ucHJvdG90eXBlLCBcInRvZ2dsZVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCByZWZsZWN0OiB0cnVlIH0pXG5dLCBJY29uQnV0dG9uLnByb3RvdHlwZSwgXCJzZWxlY3RlZFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoKVxuXSwgSWNvbkJ1dHRvbi5wcm90b3R5cGUsIFwidHlwZVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyByZWZsZWN0OiB0cnVlIH0pXG5dLCBJY29uQnV0dG9uLnByb3RvdHlwZSwgXCJ2YWx1ZVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgc3RhdGUoKVxuXSwgSWNvbkJ1dHRvbi5wcm90b3R5cGUsIFwiZmxpcEljb25cIiwgdm9pZCAwKTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWljb24tYnV0dG9uLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDI0IEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbi8vIEdlbmVyYXRlZCBzdHlsZXNoZWV0IGZvciAuL2ljb25idXR0b24vaW50ZXJuYWwvc2hhcmVkLXN0eWxlcy5jc3MuXG5pbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuZXhwb3J0IGNvbnN0IHN0eWxlcyA9IGNzcyBgOmhvc3R7ZGlzcGxheTppbmxpbmUtZmxleDtvdXRsaW5lOm5vbmU7LXdlYmtpdC10YXAtaGlnaGxpZ2h0LWNvbG9yOnJnYmEoMCwwLDAsMCk7aGVpZ2h0OnZhcigtLV9jb250YWluZXItaGVpZ2h0KTt3aWR0aDp2YXIoLS1fY29udGFpbmVyLXdpZHRoKTtqdXN0aWZ5LWNvbnRlbnQ6Y2VudGVyfTpob3N0KFt0b3VjaC10YXJnZXQ9d3JhcHBlcl0pe21hcmdpbjptYXgoMHB4LCg0OHB4IC0gdmFyKC0tX2NvbnRhaW5lci1oZWlnaHQpKS8yKSBtYXgoMHB4LCg0OHB4IC0gdmFyKC0tX2NvbnRhaW5lci13aWR0aCkpLzIpfW1kLWZvY3VzLXJpbmd7LS1tZC1mb2N1cy1yaW5nLXNoYXBlLXN0YXJ0LXN0YXJ0OiB2YXIoLS1fY29udGFpbmVyLXNoYXBlLXN0YXJ0LXN0YXJ0KTstLW1kLWZvY3VzLXJpbmctc2hhcGUtc3RhcnQtZW5kOiB2YXIoLS1fY29udGFpbmVyLXNoYXBlLXN0YXJ0LWVuZCk7LS1tZC1mb2N1cy1yaW5nLXNoYXBlLWVuZC1lbmQ6IHZhcigtLV9jb250YWluZXItc2hhcGUtZW5kLWVuZCk7LS1tZC1mb2N1cy1yaW5nLXNoYXBlLWVuZC1zdGFydDogdmFyKC0tX2NvbnRhaW5lci1zaGFwZS1lbmQtc3RhcnQpfTpob3N0KDppcyhbZGlzYWJsZWRdLFtzb2Z0LWRpc2FibGVkXSkpe3BvaW50ZXItZXZlbnRzOm5vbmV9Lmljb24tYnV0dG9ue3BsYWNlLWl0ZW1zOmNlbnRlcjtiYWNrZ3JvdW5kOm5vbmU7Ym9yZGVyOm5vbmU7Ym94LXNpemluZzpib3JkZXItYm94O2N1cnNvcjpwb2ludGVyO2Rpc3BsYXk6ZmxleDtwbGFjZS1jb250ZW50OmNlbnRlcjtvdXRsaW5lOm5vbmU7cGFkZGluZzowO3Bvc2l0aW9uOnJlbGF0aXZlO3RleHQtZGVjb3JhdGlvbjpub25lO3VzZXItc2VsZWN0Om5vbmU7ei1pbmRleDowO2ZsZXg6MTtib3JkZXItc3RhcnQtc3RhcnQtcmFkaXVzOnZhcigtLV9jb250YWluZXItc2hhcGUtc3RhcnQtc3RhcnQpO2JvcmRlci1zdGFydC1lbmQtcmFkaXVzOnZhcigtLV9jb250YWluZXItc2hhcGUtc3RhcnQtZW5kKTtib3JkZXItZW5kLXN0YXJ0LXJhZGl1czp2YXIoLS1fY29udGFpbmVyLXNoYXBlLWVuZC1zdGFydCk7Ym9yZGVyLWVuZC1lbmQtcmFkaXVzOnZhcigtLV9jb250YWluZXItc2hhcGUtZW5kLWVuZCl9Lmljb24gOjpzbG90dGVkKCope2ZvbnQtc2l6ZTp2YXIoLS1faWNvbi1zaXplKTtoZWlnaHQ6dmFyKC0tX2ljb24tc2l6ZSk7d2lkdGg6dmFyKC0tX2ljb24tc2l6ZSk7Zm9udC13ZWlnaHQ6aW5oZXJpdH1tZC1yaXBwbGV7ei1pbmRleDotMTtib3JkZXItc3RhcnQtc3RhcnQtcmFkaXVzOnZhcigtLV9jb250YWluZXItc2hhcGUtc3RhcnQtc3RhcnQpO2JvcmRlci1zdGFydC1lbmQtcmFkaXVzOnZhcigtLV9jb250YWluZXItc2hhcGUtc3RhcnQtZW5kKTtib3JkZXItZW5kLXN0YXJ0LXJhZGl1czp2YXIoLS1fY29udGFpbmVyLXNoYXBlLWVuZC1zdGFydCk7Ym9yZGVyLWVuZC1lbmQtcmFkaXVzOnZhcigtLV9jb250YWluZXItc2hhcGUtZW5kLWVuZCl9LmZsaXAtaWNvbiAuaWNvbnt0cmFuc2Zvcm06c2NhbGVYKC0xKX0uaWNvbntkaXNwbGF5OmlubGluZS1mbGV4fS5saW5re2Rpc3BsYXk6Z3JpZDtoZWlnaHQ6MTAwJTtvdXRsaW5lOm5vbmU7cGxhY2UtaXRlbXM6Y2VudGVyO3Bvc2l0aW9uOmFic29sdXRlO3dpZHRoOjEwMCV9LnRvdWNoe3Bvc2l0aW9uOmFic29sdXRlO2hlaWdodDptYXgoNDhweCwxMDAlKTt3aWR0aDptYXgoNDhweCwxMDAlKX06aG9zdChbdG91Y2gtdGFyZ2V0PW5vbmVdKSAudG91Y2h7ZGlzcGxheTpub25lfUBtZWRpYShmb3JjZWQtY29sb3JzOiBhY3RpdmUpezpob3N0KDppcyhbZGlzYWJsZWRdLFtzb2Z0LWRpc2FibGVkXSkpey0tX2Rpc2FibGVkLWljb24tY29sb3I6IEdyYXlUZXh0Oy0tX2Rpc2FibGVkLWljb24tb3BhY2l0eTogMX19XG5gO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2hhcmVkLXN0eWxlcy5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyNCBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG4vLyBHZW5lcmF0ZWQgc3R5bGVzaGVldCBmb3IgLi9pY29uYnV0dG9uL2ludGVybmFsL3N0YW5kYXJkLXN0eWxlcy5jc3MuXG5pbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuZXhwb3J0IGNvbnN0IHN0eWxlcyA9IGNzcyBgOmhvc3R7LS1fZGlzYWJsZWQtaWNvbi1jb2xvcjogdmFyKC0tbWQtaWNvbi1idXR0b24tZGlzYWJsZWQtaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV9kaXNhYmxlZC1pY29uLW9wYWNpdHk6IHZhcigtLW1kLWljb24tYnV0dG9uLWRpc2FibGVkLWljb24tb3BhY2l0eSwgMC4zOCk7LS1faWNvbi1zaXplOiB2YXIoLS1tZC1pY29uLWJ1dHRvbi1pY29uLXNpemUsIDI0cHgpOy0tX3NlbGVjdGVkLWZvY3VzLWljb24tY29sb3I6IHZhcigtLW1kLWljb24tYnV0dG9uLXNlbGVjdGVkLWZvY3VzLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1wcmltYXJ5LCAjNjc1MGE0KSk7LS1fc2VsZWN0ZWQtaG92ZXItaWNvbi1jb2xvcjogdmFyKC0tbWQtaWNvbi1idXR0b24tc2VsZWN0ZWQtaG92ZXItaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKTstLV9zZWxlY3RlZC1ob3Zlci1zdGF0ZS1sYXllci1jb2xvcjogdmFyKC0tbWQtaWNvbi1idXR0b24tc2VsZWN0ZWQtaG92ZXItc3RhdGUtbGF5ZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1wcmltYXJ5LCAjNjc1MGE0KSk7LS1fc2VsZWN0ZWQtaG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eTogdmFyKC0tbWQtaWNvbi1idXR0b24tc2VsZWN0ZWQtaG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eSwgMC4wOCk7LS1fc2VsZWN0ZWQtaWNvbi1jb2xvcjogdmFyKC0tbWQtaWNvbi1idXR0b24tc2VsZWN0ZWQtaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKTstLV9zZWxlY3RlZC1wcmVzc2VkLWljb24tY29sb3I6IHZhcigtLW1kLWljb24tYnV0dG9uLXNlbGVjdGVkLXByZXNzZWQtaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKTstLV9zZWxlY3RlZC1wcmVzc2VkLXN0YXRlLWxheWVyLWNvbG9yOiB2YXIoLS1tZC1pY29uLWJ1dHRvbi1zZWxlY3RlZC1wcmVzc2VkLXN0YXRlLWxheWVyLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItcHJpbWFyeSwgIzY3NTBhNCkpOy0tX3NlbGVjdGVkLXByZXNzZWQtc3RhdGUtbGF5ZXItb3BhY2l0eTogdmFyKC0tbWQtaWNvbi1idXR0b24tc2VsZWN0ZWQtcHJlc3NlZC1zdGF0ZS1sYXllci1vcGFjaXR5LCAwLjEyKTstLV9zdGF0ZS1sYXllci1oZWlnaHQ6IHZhcigtLW1kLWljb24tYnV0dG9uLXN0YXRlLWxheWVyLWhlaWdodCwgNDBweCk7LS1fc3RhdGUtbGF5ZXItc2hhcGU6IHZhcigtLW1kLWljb24tYnV0dG9uLXN0YXRlLWxheWVyLXNoYXBlLCB2YXIoLS1tZC1zeXMtc2hhcGUtY29ybmVyLWZ1bGwsIDk5OTlweCkpOy0tX3N0YXRlLWxheWVyLXdpZHRoOiB2YXIoLS1tZC1pY29uLWJ1dHRvbi1zdGF0ZS1sYXllci13aWR0aCwgNDBweCk7LS1fZm9jdXMtaWNvbi1jb2xvcjogdmFyKC0tbWQtaWNvbi1idXR0b24tZm9jdXMtaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2hvdmVyLWljb24tY29sb3I6IHZhcigtLW1kLWljb24tYnV0dG9uLWhvdmVyLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV9ob3Zlci1zdGF0ZS1sYXllci1jb2xvcjogdmFyKC0tbWQtaWNvbi1idXR0b24taG92ZXItc3RhdGUtbGF5ZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV9ob3Zlci1zdGF0ZS1sYXllci1vcGFjaXR5OiB2YXIoLS1tZC1pY29uLWJ1dHRvbi1ob3Zlci1zdGF0ZS1sYXllci1vcGFjaXR5LCAwLjA4KTstLV9pY29uLWNvbG9yOiB2YXIoLS1tZC1pY29uLWJ1dHRvbi1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fcHJlc3NlZC1pY29uLWNvbG9yOiB2YXIoLS1tZC1pY29uLWJ1dHRvbi1wcmVzc2VkLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV9wcmVzc2VkLXN0YXRlLWxheWVyLWNvbG9yOiB2YXIoLS1tZC1pY29uLWJ1dHRvbi1wcmVzc2VkLXN0YXRlLWxheWVyLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fcHJlc3NlZC1zdGF0ZS1sYXllci1vcGFjaXR5OiB2YXIoLS1tZC1pY29uLWJ1dHRvbi1wcmVzc2VkLXN0YXRlLWxheWVyLW9wYWNpdHksIDAuMTIpOy0tX2NvbnRhaW5lci1zaGFwZS1zdGFydC1zdGFydDogMDstLV9jb250YWluZXItc2hhcGUtc3RhcnQtZW5kOiAwOy0tX2NvbnRhaW5lci1zaGFwZS1lbmQtZW5kOiAwOy0tX2NvbnRhaW5lci1zaGFwZS1lbmQtc3RhcnQ6IDA7LS1fY29udGFpbmVyLWhlaWdodDogMDstLV9jb250YWluZXItd2lkdGg6IDA7aGVpZ2h0OnZhcigtLV9zdGF0ZS1sYXllci1oZWlnaHQpO3dpZHRoOnZhcigtLV9zdGF0ZS1sYXllci13aWR0aCl9Omhvc3QoW3RvdWNoLXRhcmdldD13cmFwcGVyXSl7bWFyZ2luOm1heCgwcHgsKDQ4cHggLSB2YXIoLS1fc3RhdGUtbGF5ZXItaGVpZ2h0KSkvMikgbWF4KDBweCwoNDhweCAtIHZhcigtLV9zdGF0ZS1sYXllci13aWR0aCkpLzIpfW1kLWZvY3VzLXJpbmd7LS1tZC1mb2N1cy1yaW5nLXNoYXBlLXN0YXJ0LXN0YXJ0OiB2YXIoLS1fc3RhdGUtbGF5ZXItc2hhcGUpOy0tbWQtZm9jdXMtcmluZy1zaGFwZS1zdGFydC1lbmQ6IHZhcigtLV9zdGF0ZS1sYXllci1zaGFwZSk7LS1tZC1mb2N1cy1yaW5nLXNoYXBlLWVuZC1lbmQ6IHZhcigtLV9zdGF0ZS1sYXllci1zaGFwZSk7LS1tZC1mb2N1cy1yaW5nLXNoYXBlLWVuZC1zdGFydDogdmFyKC0tX3N0YXRlLWxheWVyLXNoYXBlKX0uc3RhbmRhcmR7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDAsMCwwLDApO2NvbG9yOnZhcigtLV9pY29uLWNvbG9yKTstLW1kLXJpcHBsZS1ob3Zlci1jb2xvcjogdmFyKC0tX2hvdmVyLXN0YXRlLWxheWVyLWNvbG9yKTstLW1kLXJpcHBsZS1ob3Zlci1vcGFjaXR5OiB2YXIoLS1faG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eSk7LS1tZC1yaXBwbGUtcHJlc3NlZC1jb2xvcjogdmFyKC0tX3ByZXNzZWQtc3RhdGUtbGF5ZXItY29sb3IpOy0tbWQtcmlwcGxlLXByZXNzZWQtb3BhY2l0eTogdmFyKC0tX3ByZXNzZWQtc3RhdGUtbGF5ZXItb3BhY2l0eSl9LnN0YW5kYXJkOmhvdmVye2NvbG9yOnZhcigtLV9ob3Zlci1pY29uLWNvbG9yKX0uc3RhbmRhcmQ6Zm9jdXN7Y29sb3I6dmFyKC0tX2ZvY3VzLWljb24tY29sb3IpfS5zdGFuZGFyZDphY3RpdmV7Y29sb3I6dmFyKC0tX3ByZXNzZWQtaWNvbi1jb2xvcil9LnN0YW5kYXJkOmlzKDpkaXNhYmxlZCxbYXJpYS1kaXNhYmxlZD10cnVlXSl7Y29sb3I6dmFyKC0tX2Rpc2FibGVkLWljb24tY29sb3IpfW1kLXJpcHBsZXtib3JkZXItcmFkaXVzOnZhcigtLV9zdGF0ZS1sYXllci1zaGFwZSl9LnN0YW5kYXJkOmlzKDpkaXNhYmxlZCxbYXJpYS1kaXNhYmxlZD10cnVlXSl7b3BhY2l0eTp2YXIoLS1fZGlzYWJsZWQtaWNvbi1vcGFjaXR5KX0uc2VsZWN0ZWR7LS1tZC1yaXBwbGUtaG92ZXItY29sb3I6IHZhcigtLV9zZWxlY3RlZC1ob3Zlci1zdGF0ZS1sYXllci1jb2xvcik7LS1tZC1yaXBwbGUtaG92ZXItb3BhY2l0eTogdmFyKC0tX3NlbGVjdGVkLWhvdmVyLXN0YXRlLWxheWVyLW9wYWNpdHkpOy0tbWQtcmlwcGxlLXByZXNzZWQtY29sb3I6IHZhcigtLV9zZWxlY3RlZC1wcmVzc2VkLXN0YXRlLWxheWVyLWNvbG9yKTstLW1kLXJpcHBsZS1wcmVzc2VkLW9wYWNpdHk6IHZhcigtLV9zZWxlY3RlZC1wcmVzc2VkLXN0YXRlLWxheWVyLW9wYWNpdHkpfS5zZWxlY3RlZDpub3QoOmRpc2FibGVkLFthcmlhLWRpc2FibGVkPXRydWVdKXtjb2xvcjp2YXIoLS1fc2VsZWN0ZWQtaWNvbi1jb2xvcil9LnNlbGVjdGVkOm5vdCg6ZGlzYWJsZWQsW2FyaWEtZGlzYWJsZWQ9dHJ1ZV0pOmhvdmVye2NvbG9yOnZhcigtLV9zZWxlY3RlZC1ob3Zlci1pY29uLWNvbG9yKX0uc2VsZWN0ZWQ6bm90KDpkaXNhYmxlZCxbYXJpYS1kaXNhYmxlZD10cnVlXSk6Zm9jdXN7Y29sb3I6dmFyKC0tX3NlbGVjdGVkLWZvY3VzLWljb24tY29sb3IpfS5zZWxlY3RlZDpub3QoOmRpc2FibGVkLFthcmlhLWRpc2FibGVkPXRydWVdKTphY3RpdmV7Y29sb3I6dmFyKC0tX3NlbGVjdGVkLXByZXNzZWQtaWNvbi1jb2xvcil9XG5gO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c3RhbmRhcmQtc3R5bGVzLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIyIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbi8qKlxuICogUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIGVsZW1lbnQgaXMgaW4gYSByaWdodC10by1sZWZ0IGRpcmVjdGlvbi5cbiAqXG4gKiBAcGFyYW0gZWwgRWxlbWVudCB0byBkZXRlcm1pbmUgZGlyZWN0aW9uIGZyb21cbiAqIEBwYXJhbSBzaG91bGRDaGVjayBPcHRpb25hbC4gSWYgYGZhbHNlYCwgcmV0dXJuIGBmYWxzZWAgd2l0aG91dCBjaGVja2luZ1xuICogICAgIGRpcmVjdGlvbi4gRGV0ZXJtaW5pbmcgdGhlIGRpcmVjdGlvbiBvZiBgZWxgIGlzIHNvbWV3aGF0IGV4cGVuc2l2ZSwgc29cbiAqICAgICB0aGlzIHBhcmFtZXRlciBjYW4gYmUgdXNlZCBhcyBhIGNvbmRpdGlvbmFsIGd1YXJkLiBEZWZhdWx0cyB0byBgdHJ1ZWAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1J0bChlbCwgc2hvdWxkQ2hlY2sgPSB0cnVlKSB7XG4gICAgcmV0dXJuIChzaG91bGRDaGVjayAmJlxuICAgICAgICBnZXRDb21wdXRlZFN0eWxlKGVsKS5nZXRQcm9wZXJ0eVZhbHVlKCdkaXJlY3Rpb24nKS50cmltKCkgPT09ICdydGwnKTtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWlzLXJ0bC5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMiBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5leHBvcnQgY29uc3Qgc3RyaW5nQ29udmVydGVyID0ge1xuICAgIGZyb21BdHRyaWJ1dGUodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID8/ICcnO1xuICAgIH0sXG4gICAgdG9BdHRyaWJ1dGUodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlIHx8IG51bGw7XG4gICAgfSxcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1zdHJpbmctY29udmVydGVyLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIzIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbmltcG9ydCB7IGlzU2VydmVyIH0gZnJvbSAnbGl0JztcbmltcG9ydCB7IGludGVybmFscyB9IGZyb20gJy4vZWxlbWVudC1pbnRlcm5hbHMuanMnO1xuLyoqXG4gKiBBIHN5bWJvbCBwcm9wZXJ0eSB1c2VkIHRvIGNyZWF0ZSBhIGNvbnN0cmFpbnQgdmFsaWRhdGlvbiBgVmFsaWRhdG9yYC5cbiAqIFJlcXVpcmVkIGZvciBhbGwgYG1peGluQ29uc3RyYWludFZhbGlkYXRpb24oKWAgZWxlbWVudHMuXG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVWYWxpZGF0b3IgPSBTeW1ib2woJ2NyZWF0ZVZhbGlkYXRvcicpO1xuLyoqXG4gKiBBIHN5bWJvbCBwcm9wZXJ0eSB1c2VkIHRvIHJldHVybiBhbiBhbmNob3IgZm9yIGNvbnN0cmFpbnQgdmFsaWRhdGlvbiBwb3B1cHMuXG4gKiBSZXF1aXJlZCBmb3IgYWxsIGBtaXhpbkNvbnN0cmFpbnRWYWxpZGF0aW9uKClgIGVsZW1lbnRzLlxuICovXG5leHBvcnQgY29uc3QgZ2V0VmFsaWRpdHlBbmNob3IgPSBTeW1ib2woJ2dldFZhbGlkaXR5QW5jaG9yJyk7XG4vLyBQcml2YXRlIHN5bWJvbCBtZW1iZXJzLCB1c2VkIHRvIGF2b2lkIG5hbWUgY2xhc2hpbmcuXG5jb25zdCBwcml2YXRlVmFsaWRhdG9yID0gU3ltYm9sKCdwcml2YXRlVmFsaWRhdG9yJyk7XG5jb25zdCBwcml2YXRlU3luY1ZhbGlkaXR5ID0gU3ltYm9sKCdwcml2YXRlU3luY1ZhbGlkaXR5Jyk7XG5jb25zdCBwcml2YXRlQ3VzdG9tVmFsaWRhdGlvbk1lc3NhZ2UgPSBTeW1ib2woJ3ByaXZhdGVDdXN0b21WYWxpZGF0aW9uTWVzc2FnZScpO1xuLyoqXG4gKiBNaXhlcyBpbiBjb25zdHJhaW50IHZhbGlkYXRpb24gQVBJcyBmb3IgYW4gZWxlbWVudC5cbiAqXG4gKiBTZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRNTC9Db25zdHJhaW50X3ZhbGlkYXRpb25cbiAqIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogSW1wbGVtZW50YXRpb25zIG11c3QgcHJvdmlkZSBhIHZhbGlkYXRvciB0byBjYWNoZSBhbmQgY29tcHV0ZSBpdHMgdmFsaWRpdHksXG4gKiBhbG9uZyB3aXRoIGEgc2hhZG93IHJvb3QgZWxlbWVudCB0byBhbmNob3IgdmFsaWRhdGlvbiBwb3B1cHMgdG8uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiBjb25zdCBiYXNlQ2xhc3MgPSBtaXhpbkNvbnN0cmFpbnRWYWxpZGF0aW9uKFxuICogICBtaXhpbkZvcm1Bc3NvY2lhdGVkKG1peGluRWxlbWVudEludGVybmFscyhMaXRFbGVtZW50KSlcbiAqICk7XG4gKlxuICogY2xhc3MgTXlDaGVja2JveCBleHRlbmRzIGJhc2VDbGFzcyB7XG4gKiAgIFxcQHByb3BlcnR5KHt0eXBlOiBCb29sZWFufSkgY2hlY2tlZCA9IGZhbHNlO1xuICogICBcXEBwcm9wZXJ0eSh7dHlwZTogQm9vbGVhbn0pIHJlcXVpcmVkID0gZmFsc2U7XG4gKlxuICogICBbY3JlYXRlVmFsaWRhdG9yXSgpIHtcbiAqICAgICByZXR1cm4gbmV3IENoZWNrYm94VmFsaWRhdG9yKCgpID0+IHRoaXMpO1xuICogICB9XG4gKlxuICogICBbZ2V0VmFsaWRpdHlBbmNob3JdKCkge1xuICogICAgIHJldHVybiB0aGlzLnJlbmRlclJvb3QucXVlcnlTZWxlY3RvcignLnJvb3QnKTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogQHBhcmFtIGJhc2UgVGhlIGNsYXNzIHRvIG1peCBmdW5jdGlvbmFsaXR5IGludG8uXG4gKiBAcmV0dXJuIFRoZSBwcm92aWRlZCBjbGFzcyB3aXRoIGBDb25zdHJhaW50VmFsaWRhdGlvbmAgbWl4ZWQgaW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtaXhpbkNvbnN0cmFpbnRWYWxpZGF0aW9uKGJhc2UpIHtcbiAgICB2YXIgX2E7XG4gICAgY2xhc3MgQ29uc3RyYWludFZhbGlkYXRpb25FbGVtZW50IGV4dGVuZHMgYmFzZSB7XG4gICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogTmVlZGVkIGZvciBTYWZhcmksIHNlZSBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MjYxNDMyXG4gICAgICAgICAgICAgKiBSZXBsYWNlIHdpdGggdGhpc1tpbnRlcm5hbHNdLnZhbGlkaXR5LmN1c3RvbUVycm9yIHdoZW4gcmVzb2x2ZWQuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHRoaXNbX2FdID0gJyc7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0IHZhbGlkaXR5KCkge1xuICAgICAgICAgICAgdGhpc1twcml2YXRlU3luY1ZhbGlkaXR5XSgpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbaW50ZXJuYWxzXS52YWxpZGl0eTtcbiAgICAgICAgfVxuICAgICAgICBnZXQgdmFsaWRhdGlvbk1lc3NhZ2UoKSB7XG4gICAgICAgICAgICB0aGlzW3ByaXZhdGVTeW5jVmFsaWRpdHldKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tpbnRlcm5hbHNdLnZhbGlkYXRpb25NZXNzYWdlO1xuICAgICAgICB9XG4gICAgICAgIGdldCB3aWxsVmFsaWRhdGUoKSB7XG4gICAgICAgICAgICB0aGlzW3ByaXZhdGVTeW5jVmFsaWRpdHldKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tpbnRlcm5hbHNdLndpbGxWYWxpZGF0ZTtcbiAgICAgICAgfVxuICAgICAgICBjaGVja1ZhbGlkaXR5KCkge1xuICAgICAgICAgICAgdGhpc1twcml2YXRlU3luY1ZhbGlkaXR5XSgpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbaW50ZXJuYWxzXS5jaGVja1ZhbGlkaXR5KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmVwb3J0VmFsaWRpdHkoKSB7XG4gICAgICAgICAgICB0aGlzW3ByaXZhdGVTeW5jVmFsaWRpdHldKCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tpbnRlcm5hbHNdLnJlcG9ydFZhbGlkaXR5KCk7XG4gICAgICAgIH1cbiAgICAgICAgc2V0Q3VzdG9tVmFsaWRpdHkoZXJyb3IpIHtcbiAgICAgICAgICAgIHRoaXNbcHJpdmF0ZUN1c3RvbVZhbGlkYXRpb25NZXNzYWdlXSA9IGVycm9yO1xuICAgICAgICAgICAgdGhpc1twcml2YXRlU3luY1ZhbGlkaXR5XSgpO1xuICAgICAgICB9XG4gICAgICAgIHJlcXVlc3RVcGRhdGUobmFtZSwgb2xkVmFsdWUsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHN1cGVyLnJlcXVlc3RVcGRhdGUobmFtZSwgb2xkVmFsdWUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpc1twcml2YXRlU3luY1ZhbGlkaXR5XSgpO1xuICAgICAgICB9XG4gICAgICAgIGZpcnN0VXBkYXRlZChjaGFuZ2VkKSB7XG4gICAgICAgICAgICBzdXBlci5maXJzdFVwZGF0ZWQoY2hhbmdlZCk7XG4gICAgICAgICAgICAvLyBTeW5jIHRoZSB2YWxpZGl0eSBhZ2FpbiB3aGVuIHRoZSBlbGVtZW50IGZpcnN0IHJlbmRlcnMsIHNpbmNlIHRoZVxuICAgICAgICAgICAgLy8gdmFsaWRpdHkgYW5jaG9yIGlzIG5vdyBhdmFpbGFibGUuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gRWxlbWVudHMgdGhhdCBgZGVsZWdhdGVzRm9jdXM6IHRydWVgIHRvIGFuIGA8aW5wdXQ+YCB3aWxsIHRocm93IGFuXG4gICAgICAgICAgICAvLyBlcnJvciBpbiBDaHJvbWUgYW5kIFNhZmFyaSB3aGVuIGEgZm9ybSB0cmllcyB0byBzdWJtaXQgb3IgY2FsbFxuICAgICAgICAgICAgLy8gYGZvcm0ucmVwb3J0VmFsaWRpdHkoKWA6XG4gICAgICAgICAgICAvLyBcIkFuIGludmFsaWQgZm9ybSBjb250cm9sIHdpdGggbmFtZT0nJyBpcyBub3QgZm9jdXNhYmxlXCJcbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBUaGUgdmFsaWRpdHkgYW5jaG9yIE1VU1QgYmUgcHJvdmlkZWQgaW4gYGludGVybmFscy5zZXRWYWxpZGl0eSgpYCBhbmRcbiAgICAgICAgICAgIC8vIE1VU1QgYmUgdGhlIGA8aW5wdXQ+YCBlbGVtZW50IHJlbmRlcmVkLlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIFNlZSBodHRwczovL2xpdC5kZXYvcGxheWdyb3VuZC8jZ2lzdD02YzI2ZTQxOGUwMDEwZjdhNWFhYzE1MDA1Y2RlOGJkZVxuICAgICAgICAgICAgLy8gZm9yIGEgcmVwcm9kdWN0aW9uLlxuICAgICAgICAgICAgdGhpc1twcml2YXRlU3luY1ZhbGlkaXR5XSgpO1xuICAgICAgICB9XG4gICAgICAgIFsoX2EgPSBwcml2YXRlQ3VzdG9tVmFsaWRhdGlvbk1lc3NhZ2UsIHByaXZhdGVTeW5jVmFsaWRpdHkpXSgpIHtcbiAgICAgICAgICAgIGlmIChpc1NlcnZlcikge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpc1twcml2YXRlVmFsaWRhdG9yXSkge1xuICAgICAgICAgICAgICAgIHRoaXNbcHJpdmF0ZVZhbGlkYXRvcl0gPSB0aGlzW2NyZWF0ZVZhbGlkYXRvcl0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHsgdmFsaWRpdHksIHZhbGlkYXRpb25NZXNzYWdlOiBub25DdXN0b21WYWxpZGF0aW9uTWVzc2FnZSB9ID0gdGhpc1twcml2YXRlVmFsaWRhdG9yXS5nZXRWYWxpZGl0eSgpO1xuICAgICAgICAgICAgY29uc3QgY3VzdG9tRXJyb3IgPSAhIXRoaXNbcHJpdmF0ZUN1c3RvbVZhbGlkYXRpb25NZXNzYWdlXTtcbiAgICAgICAgICAgIGNvbnN0IHZhbGlkYXRpb25NZXNzYWdlID0gdGhpc1twcml2YXRlQ3VzdG9tVmFsaWRhdGlvbk1lc3NhZ2VdIHx8IG5vbkN1c3RvbVZhbGlkYXRpb25NZXNzYWdlO1xuICAgICAgICAgICAgdGhpc1tpbnRlcm5hbHNdLnNldFZhbGlkaXR5KHsgLi4udmFsaWRpdHksIGN1c3RvbUVycm9yIH0sIHZhbGlkYXRpb25NZXNzYWdlLCB0aGlzW2dldFZhbGlkaXR5QW5jaG9yXSgpID8/IHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICAgICAgW2NyZWF0ZVZhbGlkYXRvcl0oKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltcGxlbWVudCBbY3JlYXRlVmFsaWRhdG9yXScpO1xuICAgICAgICB9XG4gICAgICAgIFtnZXRWYWxpZGl0eUFuY2hvcl0oKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltcGxlbWVudCBbZ2V0VmFsaWRpdHlBbmNob3JdJyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIENvbnN0cmFpbnRWYWxpZGF0aW9uRWxlbWVudDtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWNvbnN0cmFpbnQtdmFsaWRhdGlvbi5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBfX2RlY29yYXRlIH0gZnJvbSBcInRzbGliXCI7XG5pbXBvcnQgeyBwcm9wZXJ0eSB9IGZyb20gJ2xpdC9kZWNvcmF0b3JzLmpzJztcbmltcG9ydCB7IGludGVybmFscyB9IGZyb20gJy4vZWxlbWVudC1pbnRlcm5hbHMuanMnO1xuLyoqXG4gKiBBIHN5bWJvbCBwcm9wZXJ0eSB0byByZXRyaWV2ZSB0aGUgZm9ybSB2YWx1ZSBmb3IgYW4gZWxlbWVudC5cbiAqL1xuZXhwb3J0IGNvbnN0IGdldEZvcm1WYWx1ZSA9IFN5bWJvbCgnZ2V0Rm9ybVZhbHVlJyk7XG4vKipcbiAqIEEgc3ltYm9sIHByb3BlcnR5IHRvIHJldHJpZXZlIHRoZSBmb3JtIHN0YXRlIGZvciBhbiBlbGVtZW50LlxuICovXG5leHBvcnQgY29uc3QgZ2V0Rm9ybVN0YXRlID0gU3ltYm9sKCdnZXRGb3JtU3RhdGUnKTtcbi8qKlxuICogTWl4ZXMgaW4gZm9ybS1hc3NvY2lhdGVkIGJlaGF2aW9yIGZvciBhIGNsYXNzLiBUaGlzIGFsbG93cyBhbiBlbGVtZW50IHRvIGFkZFxuICogdmFsdWVzIHRvIGA8Zm9ybT5gIGVsZW1lbnRzLlxuICpcbiAqIEltcGxlbWVudGluZyBjbGFzc2VzIHNob3VsZCBwcm92aWRlIGEgYFtmb3JtVmFsdWVdYCB0byByZXR1cm4gdGhlIGN1cnJlbnRcbiAqIHZhbHVlIG9mIHRoZSBlbGVtZW50LCBhcyB3ZWxsIGFzIHJlc2V0IGFuZCByZXN0b3JlIGNhbGxiYWNrcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIGNvbnN0IGJhc2UgPSBtaXhpbkZvcm1Bc3NvY2lhdGVkKG1peGluRWxlbWVudEludGVybmFscyhMaXRFbGVtZW50KSk7XG4gKlxuICogY2xhc3MgTXlDb250cm9sIGV4dGVuZHMgYmFzZSB7XG4gKiAgIFxcQHByb3BlcnR5KClcbiAqICAgdmFsdWUgPSAnJztcbiAqXG4gKiAgIG92ZXJyaWRlIFtnZXRGb3JtVmFsdWVdKCkge1xuICogICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICogICB9XG4gKlxuICogICBvdmVycmlkZSBmb3JtUmVzZXRDYWxsYmFjaygpIHtcbiAqICAgICBjb25zdCBkZWZhdWx0VmFsdWUgPSB0aGlzLmdldEF0dHJpYnV0ZSgndmFsdWUnKTtcbiAqICAgICB0aGlzLnZhbHVlID0gZGVmYXVsdFZhbHVlO1xuICogICB9XG4gKlxuICogICBvdmVycmlkZSBmb3JtU3RhdGVSZXN0b3JlQ2FsbGJhY2soc3RhdGU6IHN0cmluZykge1xuICogICAgIHRoaXMudmFsdWUgPSBzdGF0ZTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogRWxlbWVudHMgbWF5IG9wdGlvbmFsbHkgcHJvdmlkZSBhIGBbZm9ybVN0YXRlXWAgaWYgdGhlaXIgdmFsdWVzIGRvIG5vdFxuICogcmVwcmVzZW50IHRoZSBzdGF0ZSBvZiB0aGUgY29tcG9uZW50LlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogY29uc3QgYmFzZSA9IG1peGluRm9ybUFzc29jaWF0ZWQobWl4aW5FbGVtZW50SW50ZXJuYWxzKExpdEVsZW1lbnQpKTtcbiAqXG4gKiBjbGFzcyBNeUNoZWNrYm94IGV4dGVuZHMgYmFzZSB7XG4gKiAgIFxcQHByb3BlcnR5KClcbiAqICAgdmFsdWUgPSAnb24nO1xuICpcbiAqICAgXFxAcHJvcGVydHkoe3R5cGU6IEJvb2xlYW59KVxuICogICBjaGVja2VkID0gZmFsc2U7XG4gKlxuICogICBvdmVycmlkZSBbZ2V0Rm9ybVZhbHVlXSgpIHtcbiAqICAgICByZXR1cm4gdGhpcy5jaGVja2VkID8gdGhpcy52YWx1ZSA6IG51bGw7XG4gKiAgIH1cbiAqXG4gKiAgIG92ZXJyaWRlIFtnZXRGb3JtU3RhdGVdKCkge1xuICogICAgIHJldHVybiBTdHJpbmcodGhpcy5jaGVja2VkKTtcbiAqICAgfVxuICpcbiAqICAgb3ZlcnJpZGUgZm9ybVJlc2V0Q2FsbGJhY2soKSB7XG4gKiAgICAgY29uc3QgZGVmYXVsdFZhbHVlID0gdGhpcy5oYXNBdHRyaWJ1dGUoJ2NoZWNrZWQnKTtcbiAqICAgICB0aGlzLmNoZWNrZWQgPSBkZWZhdWx0VmFsdWU7XG4gKiAgIH1cbiAqXG4gKiAgIG92ZXJyaWRlIGZvcm1TdGF0ZVJlc3RvcmVDYWxsYmFjayhzdGF0ZTogc3RyaW5nKSB7XG4gKiAgICAgdGhpcy5jaGVja2VkID0gQm9vbGVhbihzdGF0ZSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICpcbiAqIElNUE9SVEFOVDogUmVxdWlyZXMgZGVjbGFyZXMgZm9yIGxpdC1hbmFseXplclxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiBjb25zdCBiYXNlID0gbWl4aW5Gb3JtQXNzb2NpYXRlZChtaXhpbkVsZW1lbnRJbnRlcm5hbHMoTGl0RWxlbWVudCkpO1xuICogY2xhc3MgTXlDb250cm9sIGV4dGVuZHMgYmFzZSB7XG4gKiAgIC8vIFdyaXRhYmxlIG1peGluIHByb3BlcnRpZXMgZm9yIGxpdC1odG1sIGJpbmRpbmcsIG5lZWRlZCBmb3IgbGl0LWFuYWx5emVyXG4gKiAgIGRlY2xhcmUgZGlzYWJsZWQ6IGJvb2xlYW47XG4gKiAgIGRlY2xhcmUgbmFtZTogc3RyaW5nO1xuICogfVxuICogYGBgXG4gKlxuICogQHBhcmFtIGJhc2UgVGhlIGNsYXNzIHRvIG1peCBmdW5jdGlvbmFsaXR5IGludG8uIFRoZSBiYXNlIGNsYXNzIG11c3QgdXNlXG4gKiAgICAgYG1peGluRWxlbWVudEludGVybmFscygpYC5cbiAqIEByZXR1cm4gVGhlIHByb3ZpZGVkIGNsYXNzIHdpdGggYEZvcm1Bc3NvY2lhdGVkYCBtaXhlZCBpbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1peGluRm9ybUFzc29jaWF0ZWQoYmFzZSkge1xuICAgIGNsYXNzIEZvcm1Bc3NvY2lhdGVkRWxlbWVudCBleHRlbmRzIGJhc2Uge1xuICAgICAgICBnZXQgZm9ybSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW2ludGVybmFsc10uZm9ybTtcbiAgICAgICAgfVxuICAgICAgICBnZXQgbGFiZWxzKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbaW50ZXJuYWxzXS5sYWJlbHM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVXNlIEBwcm9wZXJ0eSBmb3IgdGhlIGBuYW1lYCBhbmQgYGRpc2FibGVkYCBwcm9wZXJ0aWVzIHRvIGFkZCB0aGVtIHRvIHRoZVxuICAgICAgICAvLyBgb2JzZXJ2ZWRBdHRyaWJ1dGVzYCBhcnJheSBhbmQgdHJpZ2dlciBgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKClgLlxuICAgICAgICAvL1xuICAgICAgICAvLyBXZSBkb24ndCB1c2UgTGl0J3MgZGVmYXVsdCBnZXR0ZXIvc2V0dGVyIChgbm9BY2Nlc3NvcjogdHJ1ZWApIGJlY2F1c2VcbiAgICAgICAgLy8gdGhlIGF0dHJpYnV0ZXMgbmVlZCB0byBiZSB1cGRhdGVkIHN5bmNocm9ub3VzbHkgdG8gd29yayB3aXRoIHN5bmNocm9ub3VzXG4gICAgICAgIC8vIGZvcm0gQVBJcywgYW5kIExpdCB1cGRhdGVzIGF0dHJpYnV0ZXMgYXN5bmMgYnkgZGVmYXVsdC5cbiAgICAgICAgZ2V0IG5hbWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRBdHRyaWJ1dGUoJ25hbWUnKSA/PyAnJztcbiAgICAgICAgfVxuICAgICAgICBzZXQgbmFtZShuYW1lKSB7XG4gICAgICAgICAgICAvLyBOb3RlOiBzZXR0aW5nIG5hbWUgdG8gbnVsbCBvciBlbXB0eSBkb2VzIG5vdCByZW1vdmUgdGhlIGF0dHJpYnV0ZS5cbiAgICAgICAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCduYW1lJywgbmFtZSk7XG4gICAgICAgICAgICAvLyBXZSBkb24ndCBuZWVkIHRvIGNhbGwgYHJlcXVlc3RVcGRhdGUoKWAgc2luY2UgaXQncyBjYWxsZWQgc3luY2hyb25vdXNseVxuICAgICAgICAgICAgLy8gaW4gYGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygpYC5cbiAgICAgICAgfVxuICAgICAgICBnZXQgZGlzYWJsZWQoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gICAgICAgIH1cbiAgICAgICAgc2V0IGRpc2FibGVkKGRpc2FibGVkKSB7XG4gICAgICAgICAgICB0aGlzLnRvZ2dsZUF0dHJpYnV0ZSgnZGlzYWJsZWQnLCBkaXNhYmxlZCk7XG4gICAgICAgICAgICAvLyBXZSBkb24ndCBuZWVkIHRvIGNhbGwgYHJlcXVlc3RVcGRhdGUoKWAgc2luY2UgaXQncyBjYWxsZWQgc3luY2hyb25vdXNseVxuICAgICAgICAgICAgLy8gaW4gYGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygpYC5cbiAgICAgICAgfVxuICAgICAgICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgb2xkLCB2YWx1ZSkge1xuICAgICAgICAgICAgLy8gTWFudWFsbHkgYHJlcXVlc3RVcGRhdGUoKWAgZm9yIGBuYW1lYCBhbmQgYGRpc2FibGVkYCB3aGVuIHRoZWlyXG4gICAgICAgICAgICAvLyBhdHRyaWJ1dGUgb3IgcHJvcGVydHkgY2hhbmdlcy5cbiAgICAgICAgICAgIC8vIFRoZSBwcm9wZXJ0aWVzIHVwZGF0ZSB0aGVpciBhdHRyaWJ1dGVzLCBzbyB0aGlzIGNhbGxiYWNrIGlzIGludm9rZWRcbiAgICAgICAgICAgIC8vIGltbWVkaWF0ZWx5IHdoZW4gdGhlIHByb3BlcnRpZXMgYXJlIHNldC4gV2UgY2FsbCBgcmVxdWVzdFVwZGF0ZSgpYCBoZXJlXG4gICAgICAgICAgICAvLyBpbnN0ZWFkIG9mIGxldHRpbmcgTGl0IHNldCB0aGUgcHJvcGVydGllcyBmcm9tIHRoZSBhdHRyaWJ1dGUgY2hhbmdlLlxuICAgICAgICAgICAgLy8gVGhhdCB3b3VsZCBjYXVzZSB0aGUgcHJvcGVydGllcyB0byByZS1zZXQgdGhlIGF0dHJpYnV0ZSBhbmQgaW52b2tlIHRoaXNcbiAgICAgICAgICAgIC8vIGNhbGxiYWNrIGFnYWluIGluIGEgbG9vcC4gVGhpcyBsZWFkcyB0byBzdGFsZSBzdGF0ZSB3aGVuIExpdCB0cmllcyB0b1xuICAgICAgICAgICAgLy8gZGV0ZXJtaW5lIGlmIGEgcHJvcGVydHkgY2hhbmdlZCBvciBub3QuXG4gICAgICAgICAgICBpZiAobmFtZSA9PT0gJ25hbWUnIHx8IG5hbWUgPT09ICdkaXNhYmxlZCcpIHtcbiAgICAgICAgICAgICAgICAvLyBEaXNhYmxlZCdzIHZhbHVlIGlzIG9ubHkgZmFsc2UgaWYgdGhlIGF0dHJpYnV0ZSBpcyBtaXNzaW5nIGFuZCBudWxsLlxuICAgICAgICAgICAgICAgIGNvbnN0IG9sZFZhbHVlID0gbmFtZSA9PT0gJ2Rpc2FibGVkJyA/IG9sZCAhPT0gbnVsbCA6IG9sZDtcbiAgICAgICAgICAgICAgICAvLyBUcmlnZ2VyIGEgbGl0IHVwZGF0ZSB3aGVuIHRoZSBhdHRyaWJ1dGUgY2hhbmdlcy5cbiAgICAgICAgICAgICAgICB0aGlzLnJlcXVlc3RVcGRhdGUobmFtZSwgb2xkVmFsdWUpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN1cGVyLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBvbGQsIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICByZXF1ZXN0VXBkYXRlKG5hbWUsIG9sZFZhbHVlLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBzdXBlci5yZXF1ZXN0VXBkYXRlKG5hbWUsIG9sZFZhbHVlLCBvcHRpb25zKTtcbiAgICAgICAgICAgIC8vIElmIGFueSBwcm9wZXJ0aWVzIGNoYW5nZSwgdXBkYXRlIHRoZSBmb3JtIHZhbHVlLCB3aGljaCBtYXkgaGF2ZSBjaGFuZ2VkXG4gICAgICAgICAgICAvLyBhcyB3ZWxsLlxuICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBmb3JtIHZhbHVlIHN5bmNocm9ub3VzbHkgaW4gYHJlcXVlc3RVcGRhdGUoKWAgcmF0aGVyIHRoYW5cbiAgICAgICAgICAgIC8vIGB1cGRhdGUoKWAgb3IgYHVwZGF0ZWQoKWAsIHdoaWNoIGFyZSBhc3luYy4gVGhpcyBpcyBuZWNlc3NhcnkgdG8gZW5zdXJlXG4gICAgICAgICAgICAvLyB0aGF0IGZvcm0gZGF0YSBpcyB1cGRhdGVkIGluIHRpbWUgZm9yIHN5bmNocm9ub3VzIGV2ZW50IGxpc3RlbmVycy5cbiAgICAgICAgICAgIHRoaXNbaW50ZXJuYWxzXS5zZXRGb3JtVmFsdWUodGhpc1tnZXRGb3JtVmFsdWVdKCksIHRoaXNbZ2V0Rm9ybVN0YXRlXSgpKTtcbiAgICAgICAgfVxuICAgICAgICBbZ2V0Rm9ybVZhbHVlXSgpIHtcbiAgICAgICAgICAgIC8vIENsb3N1cmUgZG9lcyBub3QgYWxsb3cgYWJzdHJhY3Qgc3ltYm9sIG1lbWJlcnMsIHNvIGEgZGVmYXVsdFxuICAgICAgICAgICAgLy8gaW1wbGVtZW50YXRpb24gaXMgbmVlZGVkLlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbXBsZW1lbnQgW2dldEZvcm1WYWx1ZV0nKTtcbiAgICAgICAgfVxuICAgICAgICBbZ2V0Rm9ybVN0YXRlXSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW2dldEZvcm1WYWx1ZV0oKTtcbiAgICAgICAgfVxuICAgICAgICBmb3JtRGlzYWJsZWRDYWxsYmFjayhkaXNhYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5kaXNhYmxlZCA9IGRpc2FibGVkO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKiBAbm9jb2xsYXBzZSAqL1xuICAgIEZvcm1Bc3NvY2lhdGVkRWxlbWVudC5mb3JtQXNzb2NpYXRlZCA9IHRydWU7XG4gICAgX19kZWNvcmF0ZShbXG4gICAgICAgIHByb3BlcnR5KHsgbm9BY2Nlc3NvcjogdHJ1ZSB9KVxuICAgIF0sIEZvcm1Bc3NvY2lhdGVkRWxlbWVudC5wcm90b3R5cGUsIFwibmFtZVwiLCBudWxsKTtcbiAgICBfX2RlY29yYXRlKFtcbiAgICAgICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCBub0FjY2Vzc29yOiB0cnVlIH0pXG4gICAgXSwgRm9ybUFzc29jaWF0ZWRFbGVtZW50LnByb3RvdHlwZSwgXCJkaXNhYmxlZFwiLCBudWxsKTtcbiAgICByZXR1cm4gRm9ybUFzc29jaWF0ZWRFbGVtZW50O1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Zm9ybS1hc3NvY2lhdGVkLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIzIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbmltcG9ydCB7IGlzU2VydmVyIH0gZnJvbSAnbGl0JztcbmltcG9ydCB7IGludGVybmFscyB9IGZyb20gJy4vZWxlbWVudC1pbnRlcm5hbHMuanMnO1xuLyoqXG4gKiBBIHN5bWJvbCBwcm9wZXJ0eSB1c2VkIGZvciBhIGNhbGxiYWNrIHdoZW4gdmFsaWRpdHkgaGFzIGJlZW4gcmVwb3J0ZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBvblJlcG9ydFZhbGlkaXR5ID0gU3ltYm9sKCdvblJlcG9ydFZhbGlkaXR5Jyk7XG4vLyBQcml2YXRlIHN5bWJvbCBtZW1iZXJzLCB1c2VkIHRvIGF2b2lkIG5hbWUgY2xhc2hpbmcuXG5jb25zdCBwcml2YXRlQ2xlYW51cEZvcm1MaXN0ZW5lcnMgPSBTeW1ib2woJ3ByaXZhdGVDbGVhbnVwRm9ybUxpc3RlbmVycycpO1xuY29uc3QgcHJpdmF0ZURvTm90UmVwb3J0SW52YWxpZCA9IFN5bWJvbCgncHJpdmF0ZURvTm90UmVwb3J0SW52YWxpZCcpO1xuY29uc3QgcHJpdmF0ZUlzU2VsZlJlcG9ydGluZ1ZhbGlkaXR5ID0gU3ltYm9sKCdwcml2YXRlSXNTZWxmUmVwb3J0aW5nVmFsaWRpdHknKTtcbmNvbnN0IHByaXZhdGVDYWxsT25SZXBvcnRWYWxpZGl0eSA9IFN5bWJvbCgncHJpdmF0ZUNhbGxPblJlcG9ydFZhbGlkaXR5Jyk7XG4vKipcbiAqIE1peGVzIGluIGEgY2FsbGJhY2sgZm9yIGNvbnN0cmFpbnQgdmFsaWRhdGlvbiB3aGVuIHZhbGlkaXR5IHNob3VsZCBiZVxuICogc3R5bGVkIGFuZCByZXBvcnRlZCB0byB0aGUgdXNlci5cbiAqXG4gKiBUaGlzIGlzIGNvbW1vbmx5IHVzZWQgaW4gdGV4dC1maWVsZC1saWtlIGNvbnRyb2xzIHRoYXQgZGlzcGxheSBlcnJvciBzdHlsZXNcbiAqIGFuZCBlcnJvciBtZXNzYWdlcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIGNvbnN0IGJhc2VDbGFzcyA9IG1peGluT25SZXBvcnRWYWxpZGl0eShcbiAqICAgbWl4aW5Db25zdHJhaW50VmFsaWRhdGlvbihcbiAqICAgICBtaXhpbkZvcm1Bc3NvY2lhdGVkKG1peGluRWxlbWVudEludGVybmFscyhMaXRFbGVtZW50KSksXG4gKiAgICksXG4gKiApO1xuICpcbiAqIGNsYXNzIE15RmllbGQgZXh0ZW5kcyBiYXNlQ2xhc3Mge1xuICogICBcXEBwcm9wZXJ0eSh7dHlwZTogQm9vbGVhbn0pIGVycm9yID0gZmFsc2U7XG4gKiAgIFxcQHByb3BlcnR5KCkgZXJyb3JNZXNzYWdlID0gJyc7XG4gKlxuICogICBbb25SZXBvcnRWYWxpZGl0eV0oaW52YWxpZEV2ZW50OiBFdmVudCB8IG51bGwpIHtcbiAqICAgICB0aGlzLmVycm9yID0gISFpbnZhbGlkRXZlbnQ7XG4gKiAgICAgdGhpcy5lcnJvck1lc3NhZ2UgPSB0aGlzLnZhbGlkYXRpb25NZXNzYWdlO1xuICpcbiAqICAgICAvLyBPcHRpb25hbGx5IHByZXZlbnQgcGxhdGZvcm0gcG9wdXAgZnJvbSBkaXNwbGF5aW5nXG4gKiAgICAgaW52YWxpZEV2ZW50Py5wcmV2ZW50RGVmYXVsdCgpO1xuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0gYmFzZSBUaGUgY2xhc3MgdG8gbWl4IGZ1bmN0aW9uYWxpdHkgaW50by5cbiAqIEByZXR1cm4gVGhlIHByb3ZpZGVkIGNsYXNzIHdpdGggYE9uUmVwb3J0VmFsaWRpdHlgIG1peGVkIGluLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbWl4aW5PblJlcG9ydFZhbGlkaXR5KGJhc2UpIHtcbiAgICB2YXIgX2EsIF9iLCBfYztcbiAgICBjbGFzcyBPblJlcG9ydFZhbGlkaXR5RWxlbWVudCBleHRlbmRzIGJhc2Uge1xuICAgICAgICAvLyBNaXhpbnMgbXVzdCBoYXZlIGEgY29uc3RydWN0b3Igd2l0aCBgLi4uYXJnczogYW55W11gXG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgICAgICAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgICAgICAgICAgc3VwZXIoLi4uYXJncyk7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFVzZWQgdG8gY2xlYW4gdXAgZXZlbnQgbGlzdGVuZXJzIHdoZW4gYSBuZXcgZm9ybSBpcyBhc3NvY2lhdGVkLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICB0aGlzW19hXSA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVXNlZCB0byBkZXRlcm1pbmUgaWYgYW4gaW52YWxpZCBldmVudCBzaG91bGQgcmVwb3J0IHZhbGlkaXR5LiBJbnZhbGlkXG4gICAgICAgICAgICAgKiBldmVudHMgZnJvbSBgY2hlY2tWYWxpZGl0eSgpYCBkbyBub3QgdHJpZ2dlciByZXBvcnRpbmcuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHRoaXNbX2JdID0gZmFsc2U7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFVzZWQgdG8gZGV0ZXJtaW5lIGlmIHRoZSBjb250cm9sIGlzIHJlcG9ydGluZyB2YWxpZGl0eSBmcm9tIGl0c2VsZiwgb3JcbiAgICAgICAgICAgICAqIGlmIGEgYDxmb3JtPmAgaXMgY2F1c2luZyB0aGUgdmFsaWRpdHkgcmVwb3J0LiBGb3JtcyBoYXZlIGRpZmZlcmVudFxuICAgICAgICAgICAgICogY29udHJvbCBmb2N1c2luZyBiZWhhdmlvci5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdGhpc1tfY10gPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChpc1NlcnZlcikge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignaW52YWxpZCcsIChpbnZhbGlkRXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBMaXN0ZW4gZm9yIGludmFsaWQgZXZlbnRzIGRpc3BhdGNoZWQgYnkgYSBgPGZvcm0+YCB3aGVuIGl0IHRyaWVzIHRvXG4gICAgICAgICAgICAgICAgLy8gc3VibWl0IGFuZCB0aGUgZWxlbWVudCBpcyBpbnZhbGlkLiBXZSBpZ25vcmUgZXZlbnRzIGRpc3BhdGNoZWQgd2hlblxuICAgICAgICAgICAgICAgIC8vIGNhbGxpbmcgYGNoZWNrVmFsaWRpdHkoKWAgYXMgd2VsbCBhcyB1bnRydXN0ZWQgZXZlbnRzLCBzaW5jZSB0aGVcbiAgICAgICAgICAgICAgICAvLyBgcmVwb3J0VmFsaWRpdHkoKWAgYW5kIGA8Zm9ybT5gLWRpc3BhdGNoZWQgZXZlbnRzIGFyZSBhbHdheXNcbiAgICAgICAgICAgICAgICAvLyB0cnVzdGVkLlxuICAgICAgICAgICAgICAgIGlmICh0aGlzW3ByaXZhdGVEb05vdFJlcG9ydEludmFsaWRdIHx8ICFpbnZhbGlkRXZlbnQuaXNUcnVzdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdpbnZhbGlkJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAvLyBBIG5vcm1hbCBidWJibGluZyBwaGFzZSBldmVudCBsaXN0ZW5lci4gQnkgYWRkaW5nIGl0IGhlcmUsIHdlXG4gICAgICAgICAgICAgICAgICAgIC8vIGVuc3VyZSBpdCdzIHRoZSBsYXN0IGV2ZW50IGxpc3RlbmVyIHRoYXQgaXMgY2FsbGVkIGR1cmluZyB0aGVcbiAgICAgICAgICAgICAgICAgICAgLy8gYnViYmxpbmcgcGhhc2UuXG4gICAgICAgICAgICAgICAgICAgIHRoaXNbcHJpdmF0ZUNhbGxPblJlcG9ydFZhbGlkaXR5XShpbnZhbGlkRXZlbnQpO1xuICAgICAgICAgICAgICAgIH0sIHsgb25jZTogdHJ1ZSB9KTtcbiAgICAgICAgICAgIH0sIHtcbiAgICAgICAgICAgICAgICAvLyBMaXN0ZW4gZHVyaW5nIHRoZSBjYXB0dXJlIHBoYXNlLCB3aGljaCB3aWxsIGhhcHBlbiBiZWZvcmUgdGhlXG4gICAgICAgICAgICAgICAgLy8gYnViYmxpbmcgcGhhc2UuIFRoYXQgd2F5LCB3ZSBjYW4gYWRkIGEgZmluYWwgZXZlbnQgbGlzdGVuZXIgdGhhdFxuICAgICAgICAgICAgICAgIC8vIHdpbGwgcnVuIGFmdGVyIG90aGVyIGV2ZW50IGxpc3RlbmVycywgYW5kIHdlIGNhbiBjaGVjayBpZiBpdCB3YXNcbiAgICAgICAgICAgICAgICAvLyBkZWZhdWx0IHByZXZlbnRlZC4gVGhpcyB3b3JrcyBiZWNhdXNlIGludmFsaWQgZG9lcyBub3QgYnViYmxlLlxuICAgICAgICAgICAgICAgIGNhcHR1cmU6IHRydWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBjaGVja1ZhbGlkaXR5KCkge1xuICAgICAgICAgICAgdGhpc1twcml2YXRlRG9Ob3RSZXBvcnRJbnZhbGlkXSA9IHRydWU7XG4gICAgICAgICAgICBjb25zdCB2YWxpZCA9IHN1cGVyLmNoZWNrVmFsaWRpdHkoKTtcbiAgICAgICAgICAgIHRoaXNbcHJpdmF0ZURvTm90UmVwb3J0SW52YWxpZF0gPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiB2YWxpZDtcbiAgICAgICAgfVxuICAgICAgICByZXBvcnRWYWxpZGl0eSgpIHtcbiAgICAgICAgICAgIHRoaXNbcHJpdmF0ZUlzU2VsZlJlcG9ydGluZ1ZhbGlkaXR5XSA9IHRydWU7XG4gICAgICAgICAgICBjb25zdCB2YWxpZCA9IHN1cGVyLnJlcG9ydFZhbGlkaXR5KCk7XG4gICAgICAgICAgICAvLyBDb25zdHJ1Y3RvcidzIGludmFsaWQgbGlzdGVuZXIgd2lsbCBoYW5kbGUgcmVwb3J0aW5nIGludmFsaWQgZXZlbnRzLlxuICAgICAgICAgICAgaWYgKHZhbGlkKSB7XG4gICAgICAgICAgICAgICAgdGhpc1twcml2YXRlQ2FsbE9uUmVwb3J0VmFsaWRpdHldKG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpc1twcml2YXRlSXNTZWxmUmVwb3J0aW5nVmFsaWRpdHldID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gdmFsaWQ7XG4gICAgICAgIH1cbiAgICAgICAgWyhfYSA9IHByaXZhdGVDbGVhbnVwRm9ybUxpc3RlbmVycywgX2IgPSBwcml2YXRlRG9Ob3RSZXBvcnRJbnZhbGlkLCBfYyA9IHByaXZhdGVJc1NlbGZSZXBvcnRpbmdWYWxpZGl0eSwgcHJpdmF0ZUNhbGxPblJlcG9ydFZhbGlkaXR5KV0oaW52YWxpZEV2ZW50KSB7XG4gICAgICAgICAgICAvLyBTaW5jZSBpbnZhbGlkIGV2ZW50cyBkbyBub3QgYnViYmxlIHRvIHBhcmVudCBsaXN0ZW5lcnMsIGFuZCBiZWNhdXNlXG4gICAgICAgICAgICAvLyBvdXIgaW52YWxpZCBsaXN0ZW5lcnMgYXJlIGFkZGVkIGxhemlseSBhZnRlciBvdGhlciBsaXN0ZW5lcnMsIHdlIGNhblxuICAgICAgICAgICAgLy8gcmVsaWFibHkgcmVhZCBgZGVmYXVsdFByZXZlbnRlZGAgc3luY2hyb25vdXNseSB3aXRob3V0IHdvcnJ5aW5nXG4gICAgICAgICAgICAvLyBhYm91dCB3YWl0aW5nIGZvciBhbm90aGVyIGxpc3RlbmVyIHRoYXQgY291bGQgY2FuY2VsIGl0LlxuICAgICAgICAgICAgY29uc3Qgd2FzQ2FuY2VsZWQgPSBpbnZhbGlkRXZlbnQ/LmRlZmF1bHRQcmV2ZW50ZWQ7XG4gICAgICAgICAgICBpZiAod2FzQ2FuY2VsZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzW29uUmVwb3J0VmFsaWRpdHldKGludmFsaWRFdmVudCk7XG4gICAgICAgICAgICAvLyBJZiBhbiBpbXBsZW1lbnRhdGlvbiBjYWxscyBpbnZhbGlkRXZlbnQucHJldmVudERlZmF1bHQoKSB0byBzdG9wIHRoZVxuICAgICAgICAgICAgLy8gcGxhdGZvcm0gcG9wdXAgZnJvbSBkaXNwbGF5aW5nLCBmb2N1c2luZyBpcyBhbHNvIHByZXZlbnRlZCwgc28gd2UgbmVlZFxuICAgICAgICAgICAgLy8gdG8gbWFudWFsbHkgZm9jdXMuXG4gICAgICAgICAgICBjb25zdCBpbXBsZW1lbnRhdGlvbkNhbmNlbGVkRm9jdXMgPSAhd2FzQ2FuY2VsZWQgJiYgaW52YWxpZEV2ZW50Py5kZWZhdWx0UHJldmVudGVkO1xuICAgICAgICAgICAgaWYgKCFpbXBsZW1lbnRhdGlvbkNhbmNlbGVkRm9jdXMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBUaGUgY29udHJvbCBzaG91bGQgYmUgZm9jdXNlZCB3aGVuOlxuICAgICAgICAgICAgLy8gLSBgY29udHJvbC5yZXBvcnRWYWxpZGl0eSgpYCBpcyBjYWxsZWQgKHNlbGYtcmVwb3J0aW5nKS5cbiAgICAgICAgICAgIC8vIC0gYSBmb3JtIGlzIHJlcG9ydGluZyB2YWxpZGl0eSBmb3IgaXRzIGNvbnRyb2xzIGFuZCB0aGlzIGlzIHRoZSBmaXJzdFxuICAgICAgICAgICAgLy8gICBpbnZhbGlkIGNvbnRyb2wuXG4gICAgICAgICAgICBpZiAodGhpc1twcml2YXRlSXNTZWxmUmVwb3J0aW5nVmFsaWRpdHldIHx8XG4gICAgICAgICAgICAgICAgaXNGaXJzdEludmFsaWRDb250cm9sSW5Gb3JtKHRoaXNbaW50ZXJuYWxzXS5mb3JtLCB0aGlzKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZm9jdXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBbb25SZXBvcnRWYWxpZGl0eV0oaW52YWxpZEV2ZW50KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltcGxlbWVudCBbb25SZXBvcnRWYWxpZGl0eV0nKTtcbiAgICAgICAgfVxuICAgICAgICBmb3JtQXNzb2NpYXRlZENhbGxiYWNrKGZvcm0pIHtcbiAgICAgICAgICAgIC8vIGNhbid0IHVzZSBzdXBlci5mb3JtQXNzb2NpYXRlZENhbGxiYWNrPy4oKSBkdWUgdG8gY2xvc3VyZVxuICAgICAgICAgICAgaWYgKHN1cGVyLmZvcm1Bc3NvY2lhdGVkQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBzdXBlci5mb3JtQXNzb2NpYXRlZENhbGxiYWNrKGZvcm0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQ2xlYW4gdXAgcHJldmlvdXMgZm9ybSBsaXN0ZW5lcnMuXG4gICAgICAgICAgICB0aGlzW3ByaXZhdGVDbGVhbnVwRm9ybUxpc3RlbmVyc10uYWJvcnQoKTtcbiAgICAgICAgICAgIGlmICghZm9ybSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXNbcHJpdmF0ZUNsZWFudXBGb3JtTGlzdGVuZXJzXSA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICAgICAgICAgIC8vIEFkZCBhIGxpc3RlbmVyIHRoYXQgZmlyZXMgd2hlbiB0aGUgZm9ybSBydW5zIGNvbnN0cmFpbnQgdmFsaWRhdGlvbiBhbmRcbiAgICAgICAgICAgIC8vIHRoZSBjb250cm9sIGlzIHZhbGlkLCBzbyB0aGF0IGl0IG1heSByZW1vdmUgaXRzIGVycm9yIHN0eWxlcy5cbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBUaGlzIGhhcHBlbnMgb24gYGZvcm0ucmVwb3J0VmFsaWRpdHkoKWAgYW5kIGBmb3JtLnJlcXVlc3RTdWJtaXQoKWBcbiAgICAgICAgICAgIC8vIChib3RoIHdoZW4gdGhlIHN1Ym1pdCBmYWlscyBhbmQgcGFzc2VzKS5cbiAgICAgICAgICAgIGFkZEZvcm1SZXBvcnRWYWxpZExpc3RlbmVyKHRoaXMsIGZvcm0sICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzW3ByaXZhdGVDYWxsT25SZXBvcnRWYWxpZGl0eV0obnVsbCk7XG4gICAgICAgICAgICB9LCB0aGlzW3ByaXZhdGVDbGVhbnVwRm9ybUxpc3RlbmVyc10uc2lnbmFsKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gT25SZXBvcnRWYWxpZGl0eUVsZW1lbnQ7XG59XG4vKipcbiAqIEFkZCBhIGxpc3RlbmVyIHRoYXQgZmlyZXMgd2hlbiBhIGZvcm0gcnVucyBjb25zdHJhaW50IHZhbGlkYXRpb24gb24gYSBjb250cm9sXG4gKiBhbmQgaXQgaXMgdmFsaWQuIFRoaXMgaXMgbmVlZGVkIHRvIGNsZWFyIHByZXZpb3VzbHkgaW52YWxpZCBzdHlsZXMuXG4gKlxuICogQHBhcmFtIGNvbnRyb2wgVGhlIGNvbnRyb2wgb2YgdGhlIGZvcm0gdG8gbGlzdGVuIGZvciB2YWxpZCBldmVudHMuXG4gKiBAcGFyYW0gZm9ybSBUaGUgY29udHJvbCdzIGZvcm0gdGhhdCBjYW4gcnVuIGNvbnN0cmFpbnQgdmFsaWRhdGlvbi5cbiAqIEBwYXJhbSBvbkNvbnRyb2xWYWxpZCBBIGxpc3RlbmVyIHRoYXQgaXMgY2FsbGVkIHdoZW4gdGhlIGZvcm0gcnVucyBjb25zdHJhaW50XG4gKiAgICAgdmFsaWRhdGlvbiBhbmQgdGhlIGNvbnRyb2wgaXMgdmFsaWQuXG4gKiBAcGFyYW0gY2xlYW51cCBBIGNsZWFudXAgc2lnbmFsIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXG4gKi9cbmZ1bmN0aW9uIGFkZEZvcm1SZXBvcnRWYWxpZExpc3RlbmVyKGNvbnRyb2wsIGZvcm0sIG9uQ29udHJvbFZhbGlkLCBjbGVhbnVwKSB7XG4gICAgY29uc3QgdmFsaWRhdGVIb29rcyA9IGdldEZvcm1WYWxpZGF0ZUhvb2tzKGZvcm0pO1xuICAgIC8vIFdoZW4gYSBmb3JtIHZhbGlkYXRlcyBpdHMgY29udHJvbHMsIGNoZWNrIGlmIGFuIGludmFsaWQgZXZlbnQgaXMgZGlzcGF0Y2hlZFxuICAgIC8vIG9uIHRoZSBjb250cm9sLiBJZiBpdCBpcyBub3QsIHRoZW4gaW5mb3JtIHRoZSBjb250cm9sIHRvIHJlcG9ydCBpdHMgdmFsaWRcbiAgICAvLyBzdGF0ZS5cbiAgICBsZXQgY29udHJvbEZpcmVkSW52YWxpZCA9IGZhbHNlO1xuICAgIGxldCBjbGVhbnVwSW52YWxpZExpc3RlbmVyO1xuICAgIGxldCBpc05leHRTdWJtaXRGcm9tSG9vayA9IGZhbHNlO1xuICAgIHZhbGlkYXRlSG9va3MuYWRkRXZlbnRMaXN0ZW5lcignYmVmb3JlJywgKCkgPT4ge1xuICAgICAgICBpc05leHRTdWJtaXRGcm9tSG9vayA9IHRydWU7XG4gICAgICAgIGNsZWFudXBJbnZhbGlkTGlzdGVuZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAgICAgIGNvbnRyb2xGaXJlZEludmFsaWQgPSBmYWxzZTtcbiAgICAgICAgY29udHJvbC5hZGRFdmVudExpc3RlbmVyKCdpbnZhbGlkJywgKCkgPT4ge1xuICAgICAgICAgICAgY29udHJvbEZpcmVkSW52YWxpZCA9IHRydWU7XG4gICAgICAgIH0sIHtcbiAgICAgICAgICAgIHNpZ25hbDogY2xlYW51cEludmFsaWRMaXN0ZW5lci5zaWduYWwsXG4gICAgICAgIH0pO1xuICAgIH0sIHsgc2lnbmFsOiBjbGVhbnVwIH0pO1xuICAgIHZhbGlkYXRlSG9va3MuYWRkRXZlbnRMaXN0ZW5lcignYWZ0ZXInLCAoKSA9PiB7XG4gICAgICAgIGlzTmV4dFN1Ym1pdEZyb21Ib29rID0gZmFsc2U7XG4gICAgICAgIGNsZWFudXBJbnZhbGlkTGlzdGVuZXI/LmFib3J0KCk7XG4gICAgICAgIGlmIChjb250cm9sRmlyZWRJbnZhbGlkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgb25Db250cm9sVmFsaWQoKTtcbiAgICB9LCB7IHNpZ25hbDogY2xlYW51cCB9KTtcbiAgICAvLyBUaGUgYWJvdmUgaG9va3MgaGFuZGxlIGltcGVyYXRpdmVseSBzdWJtaXR0aW5nIHRoZSBmb3JtLCBidXQgbm90XG4gICAgLy8gZGVjbGFyYXRpdmVseSBzdWJtaXR0aW5nIHRoZSBmb3JtLiBUaGlzIGhhcHBlbnMgd2hlbjpcbiAgICAvLyAxLiBBIG5vbi1jdXN0b20gZWxlbWVudCBgPGJ1dHRvbiB0eXBlPVwic3VibWl0XCI+YCBpcyBjbGlja2VkLlxuICAgIC8vIDIuIEVudGVyIGlzIHByZXNzZWQgb24gYSBub24tY3VzdG9tIGVsZW1lbnQgdGV4dCBlZGl0YWJsZSBgPGlucHV0PmAuXG4gICAgZm9ybS5hZGRFdmVudExpc3RlbmVyKCdzdWJtaXQnLCAoKSA9PiB7XG4gICAgICAgIC8vIFRoaXMgc3VibWl0IHdhcyBmcm9tIGBmb3JtLnJlcXVlc3RTdWJtaXQoKWAsIHdoaWNoIGFscmVhZHkgY2FsbHMgdGhlXG4gICAgICAgIC8vIGxpc3RlbmVyLlxuICAgICAgICBpZiAoaXNOZXh0U3VibWl0RnJvbUhvb2spIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBvbkNvbnRyb2xWYWxpZCgpO1xuICAgIH0sIHtcbiAgICAgICAgc2lnbmFsOiBjbGVhbnVwLFxuICAgIH0pO1xuICAgIC8vIE5vdGU6IGl0IGlzIGEga25vd24gbGltaXRhdGlvbiB0aGF0IHdlIGNhbm5vdCBkZXRlY3QgaWYgYSBmb3JtIHRyaWVzIHRvXG4gICAgLy8gc3VibWl0IGRlY2xhcmF0aXZlbHksIGJ1dCBmYWlscyB0byBkbyBzbyBiZWNhdXNlIGFuIHVucmVsYXRlZCBzaWJsaW5nXG4gICAgLy8gY29udHJvbCBmYWlsZWQgaXRzIGNvbnN0cmFpbnQgdmFsaWRhdGlvbi5cbiAgICAvL1xuICAgIC8vIFNpbmNlIHdlIGNhbm5vdCBkZXRlY3Qgd2hlbiB0aGF0IGhhcHBlbnMsIGEgcHJldmlvdXNseSBpbnZhbGlkIGNvbnRyb2wgbWF5XG4gICAgLy8gbm90IGNsZWFyIGl0cyBlcnJvciBzdHlsaW5nIHdoZW4gaXQgYmVjb21lcyB2YWxpZCBhZ2Fpbi5cbiAgICAvL1xuICAgIC8vIFRvIHdvcmsgYXJvdW5kIHRoaXMsIGNhbGwgYGZvcm0ucmVwb3J0VmFsaWRpdHkoKWAgd2hlbiBzdWJtaXR0aW5nIGEgZm9ybVxuICAgIC8vIGRlY2xhcmF0aXZlbHkuIFRoaXMgY2FuIGJlIGRvd24gb24gdGhlIGA8YnV0dG9uIHR5cGU9XCJzdWJtaXRcIj5gJ3MgY2xpY2sgb3JcbiAgICAvLyB0aGUgdGV4dCBlZGl0YWJsZSBgPGlucHV0PmAncyAnRW50ZXInIGtleWRvd24uXG59XG5jb25zdCBGT1JNX1ZBTElEQVRFX0hPT0tTID0gbmV3IFdlYWtNYXAoKTtcbi8qKlxuICogR2V0IGEgaG9va3MgYEV2ZW50VGFyZ2V0YCB0aGF0IGRpc3BhdGNoZXMgJ2JlZm9yZScgYW5kICdhZnRlcicgZXZlbnRzIHRoYXRcbiAqIGZpcmUgYmVmb3JlIGEgZm9ybSBydW5zIGNvbnN0cmFpbnQgdmFsaWRhdGlvbiBhbmQgaW1tZWRpYXRlbHkgYWZ0ZXIgaXRcbiAqIGZpbmlzaGVzIHJ1bm5pbmcgY29uc3RyYWludCB2YWxpZGF0aW9uIG9uIGl0cyBjb250cm9scy5cbiAqXG4gKiBUaGlzIGhhcHBlbnMgZHVyaW5nIGBmb3JtLnJlcG9ydFZhbGlkaXR5KClgIGFuZCBgZm9ybS5yZXF1ZXN0U3VibWl0KClgLlxuICpcbiAqIEBwYXJhbSBmb3JtIFRoZSBmb3JtIHRvIGdldCBvciBzZXQgdXAgaG9va3MgZm9yLlxuICogQHJldHVybiBBIGhvb2tzIGBFdmVudFRhcmdldGAgdG8gYWRkIGxpc3RlbmVycyB0by5cbiAqL1xuZnVuY3Rpb24gZ2V0Rm9ybVZhbGlkYXRlSG9va3MoZm9ybSkge1xuICAgIGlmICghRk9STV9WQUxJREFURV9IT09LUy5oYXMoZm9ybSkpIHtcbiAgICAgICAgLy8gUGF0Y2ggZm9ybSBtZXRob2RzIHRvIGFkZCBldmVudCBsaXN0ZW5lciBob29rcy4gVGhlc2UgYXJlIG5lZWRlZCB0byByZWFjdFxuICAgICAgICAvLyB0byBmb3JtIGJlaGF2aW9ycyB0aGF0IGRvIG5vdCBkaXNwYXRjaCBldmVudHMsIHN1Y2ggYXMgYSBmb3JtIGFza2luZyBpdHNcbiAgICAgICAgLy8gY29udHJvbHMgdG8gcmVwb3J0IHRoZWlyIHZhbGlkaXR5LlxuICAgICAgICAvL1xuICAgICAgICAvLyBXZSBzaG91bGQgb25seSBwYXRjaCB0aGUgbWV0aG9kcyBvbmNlLCBzaW5jZSBtdWx0aXBsZSBjb250cm9scyBhbmQgb3RoZXJcbiAgICAgICAgLy8gZm9yY2VzIG1heSB3YW50IHRvIHBhdGNoIHRoaXMgbWV0aG9kLiBXZSBjYW5ub3QgcmVsaWFibHkgY2xlYW4gaXQgdXAgaWZcbiAgICAgICAgLy8gdGhlcmUgYXJlIG11bHRpcGxlIHBhdGNoZWQgYW5kIHJlLXBhdGNoZWQgbWV0aG9kcyByZWZlcnJpbmcgaG9sZGluZ1xuICAgICAgICAvLyByZWZlcmVuY2VzIHRvIGVhY2ggb3RoZXIuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIEluc3RlYWQsIHdlIG5ldmVyIGNsZWFuIHVwIHRoZSBwYXRjaCBidXQgYWRkIGFuZCBjbGVhbiB1cCBldmVudCBsaXN0ZW5lcnNcbiAgICAgICAgLy8gYWRkZWQgdG8gdGhlIGhvb2tzIGFmdGVyIHRoZSBwYXRjaC5cbiAgICAgICAgY29uc3QgaG9va3MgPSBuZXcgRXZlbnRUYXJnZXQoKTtcbiAgICAgICAgRk9STV9WQUxJREFURV9IT09LUy5zZXQoZm9ybSwgaG9va3MpO1xuICAgICAgICAvLyBBZGQgaG9va3MgdG8gc3VwcG9ydCBub3RpZnlpbmcgYmVmb3JlIGFuZCBhZnRlciBhIGZvcm0gaGFzIHJ1biBjb25zdHJhaW50XG4gICAgICAgIC8vIHZhbGlkYXRpb24gb24gaXRzIGNvbnRyb2xzLlxuICAgICAgICAvLyBOb3RlOiBgZm9ybS5zdWJtaXQoKWAgZG9lcyBub3QgcnVuIGNvbnN0cmFpbnQgdmFsaWRhdGlvbiBwZXIgc3BlYy5cbiAgICAgICAgZm9yIChjb25zdCBtZXRob2ROYW1lIG9mIFsncmVwb3J0VmFsaWRpdHknLCAncmVxdWVzdFN1Ym1pdCddKSB7XG4gICAgICAgICAgICBjb25zdCBzdXBlck1ldGhvZCA9IGZvcm1bbWV0aG9kTmFtZV07XG4gICAgICAgICAgICBmb3JtW21ldGhvZE5hbWVdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGhvb2tzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdiZWZvcmUnKSk7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gUmVmbGVjdC5hcHBseShzdXBlck1ldGhvZCwgdGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICBob29rcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudCgnYWZ0ZXInKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIEZPUk1fVkFMSURBVEVfSE9PS1MuZ2V0KGZvcm0pO1xufVxuLyoqXG4gKiBDaGVja3MgaWYgYSBjb250cm9sIGlzIHRoZSBmaXJzdCBpbnZhbGlkIGNvbnRyb2wgaW4gYSBmb3JtLlxuICpcbiAqIEBwYXJhbSBmb3JtIFRoZSBjb250cm9sJ3MgZm9ybS4gV2hlbiBgbnVsbGAsIHRoZSBjb250cm9sIGRvZXNuJ3QgaGF2ZSBhIGZvcm1cbiAqICAgICBhbmQgdGhlIG1ldGhvZCByZXR1cm5zIHRydWUuXG4gKiBAcGFyYW0gY29udHJvbCBUaGUgY29udHJvbCB0byBjaGVjay5cbiAqIEByZXR1cm4gVHJ1ZSBpZiB0aGVyZSBpcyBubyBmb3JtIG9yIGlmIHRoZSBjb250cm9sIGlzIHRoZSBmb3JtJ3MgZmlyc3RcbiAqICAgICBpbnZhbGlkIGNvbnRyb2wuXG4gKi9cbmZ1bmN0aW9uIGlzRmlyc3RJbnZhbGlkQ29udHJvbEluRm9ybShmb3JtLCBjb250cm9sKSB7XG4gICAgaWYgKCFmb3JtKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBsZXQgZmlyc3RJbnZhbGlkQ29udHJvbDtcbiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZm9ybS5lbGVtZW50cykge1xuICAgICAgICBpZiAoZWxlbWVudC5tYXRjaGVzKCc6aW52YWxpZCcpKSB7XG4gICAgICAgICAgICBmaXJzdEludmFsaWRDb250cm9sID0gZWxlbWVudDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmaXJzdEludmFsaWRDb250cm9sID09PSBjb250cm9sO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9b24tcmVwb3J0LXZhbGlkaXR5LmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIzIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbmltcG9ydCB7IFZhbGlkYXRvciB9IGZyb20gJy4vdmFsaWRhdG9yLmpzJztcbi8qKlxuICogQSB2YWxpZGF0b3IgdGhhdCBwcm92aWRlcyBjb25zdHJhaW50IHZhbGlkYXRpb24gdGhhdCBlbXVsYXRlc1xuICogYDxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIj5gIHZhbGlkYXRpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBDaGVja2JveFZhbGlkYXRvciBleHRlbmRzIFZhbGlkYXRvciB7XG4gICAgY29tcHV0ZVZhbGlkaXR5KHN0YXRlKSB7XG4gICAgICAgIGlmICghdGhpcy5jaGVja2JveENvbnRyb2wpIHtcbiAgICAgICAgICAgIC8vIExhemlseSBjcmVhdGUgdGhlIHBsYXRmb3JtIGlucHV0XG4gICAgICAgICAgICB0aGlzLmNoZWNrYm94Q29udHJvbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0Jyk7XG4gICAgICAgICAgICB0aGlzLmNoZWNrYm94Q29udHJvbC50eXBlID0gJ2NoZWNrYm94JztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNoZWNrYm94Q29udHJvbC5jaGVja2VkID0gc3RhdGUuY2hlY2tlZDtcbiAgICAgICAgdGhpcy5jaGVja2JveENvbnRyb2wucmVxdWlyZWQgPSBzdGF0ZS5yZXF1aXJlZDtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHZhbGlkaXR5OiB0aGlzLmNoZWNrYm94Q29udHJvbC52YWxpZGl0eSxcbiAgICAgICAgICAgIHZhbGlkYXRpb25NZXNzYWdlOiB0aGlzLmNoZWNrYm94Q29udHJvbC52YWxpZGF0aW9uTWVzc2FnZSxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZXF1YWxzKHByZXYsIG5leHQpIHtcbiAgICAgICAgcmV0dXJuIHByZXYuY2hlY2tlZCA9PT0gbmV4dC5jaGVja2VkICYmIHByZXYucmVxdWlyZWQgPT09IG5leHQucmVxdWlyZWQ7XG4gICAgfVxuICAgIGNvcHkoeyBjaGVja2VkLCByZXF1aXJlZCB9KSB7XG4gICAgICAgIHJldHVybiB7IGNoZWNrZWQsIHJlcXVpcmVkIH07XG4gICAgfVxufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y2hlY2tib3gtdmFsaWRhdG9yLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIzIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbmltcG9ydCB7IGh0bWwsIHJlbmRlciB9IGZyb20gJ2xpdCc7XG5pbXBvcnQgeyBWYWxpZGF0b3IgfSBmcm9tICcuL3ZhbGlkYXRvci5qcyc7XG4vKipcbiAqIEEgdmFsaWRhdG9yIHRoYXQgcHJvdmlkZXMgY29uc3RyYWludCB2YWxpZGF0aW9uIHRoYXQgZW11bGF0ZXMgYDxzZWxlY3Q+YFxuICogdmFsaWRhdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIFNlbGVjdFZhbGlkYXRvciBleHRlbmRzIFZhbGlkYXRvciB7XG4gICAgY29tcHV0ZVZhbGlkaXR5KHN0YXRlKSB7XG4gICAgICAgIGlmICghdGhpcy5zZWxlY3RDb250cm9sKSB7XG4gICAgICAgICAgICAvLyBMYXppbHkgY3JlYXRlIHRoZSBwbGF0Zm9ybSBzZWxlY3RcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0Q29udHJvbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NlbGVjdCcpO1xuICAgICAgICB9XG4gICAgICAgIHJlbmRlcihodG1sIGA8b3B0aW9uIHZhbHVlPSR7c3RhdGUudmFsdWV9Pjwvb3B0aW9uPmAsIHRoaXMuc2VsZWN0Q29udHJvbCk7XG4gICAgICAgIHRoaXMuc2VsZWN0Q29udHJvbC52YWx1ZSA9IHN0YXRlLnZhbHVlO1xuICAgICAgICB0aGlzLnNlbGVjdENvbnRyb2wucmVxdWlyZWQgPSBzdGF0ZS5yZXF1aXJlZDtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHZhbGlkaXR5OiB0aGlzLnNlbGVjdENvbnRyb2wudmFsaWRpdHksXG4gICAgICAgICAgICB2YWxpZGF0aW9uTWVzc2FnZTogdGhpcy5zZWxlY3RDb250cm9sLnZhbGlkYXRpb25NZXNzYWdlLFxuICAgICAgICB9O1xuICAgIH1cbiAgICBlcXVhbHMocHJldiwgbmV4dCkge1xuICAgICAgICByZXR1cm4gcHJldi52YWx1ZSA9PT0gbmV4dC52YWx1ZSAmJiBwcmV2LnJlcXVpcmVkID09PSBuZXh0LnJlcXVpcmVkO1xuICAgIH1cbiAgICBjb3B5KHsgdmFsdWUsIHJlcXVpcmVkIH0pIHtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWUsIHJlcXVpcmVkIH07XG4gICAgfVxufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2VsZWN0LXZhbGlkYXRvci5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBWYWxpZGF0b3IgfSBmcm9tICcuL3ZhbGlkYXRvci5qcyc7XG4vKipcbiAqIEEgdmFsaWRhdG9yIHRoYXQgcHJvdmlkZXMgY29uc3RyYWludCB2YWxpZGF0aW9uIHRoYXQgZW11bGF0ZXMgYDxpbnB1dD5gIGFuZFxuICogYDx0ZXh0YXJlYT5gIHZhbGlkYXRpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBUZXh0RmllbGRWYWxpZGF0b3IgZXh0ZW5kcyBWYWxpZGF0b3Ige1xuICAgIGNvbXB1dGVWYWxpZGl0eSh7IHN0YXRlLCByZW5kZXJlZENvbnRyb2wgfSkge1xuICAgICAgICBsZXQgaW5wdXRPclRleHRBcmVhID0gcmVuZGVyZWRDb250cm9sO1xuICAgICAgICBpZiAoaXNJbnB1dFN0YXRlKHN0YXRlKSAmJiAhaW5wdXRPclRleHRBcmVhKSB7XG4gICAgICAgICAgICAvLyBHZXQgY2FjaGVkIDxpbnB1dD4gb3IgY3JlYXRlIGl0LlxuICAgICAgICAgICAgaW5wdXRPclRleHRBcmVhID0gdGhpcy5pbnB1dENvbnRyb2wgfHwgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKTtcbiAgICAgICAgICAgIC8vIENhY2hlIHRoZSA8aW5wdXQ+IHRvIHJlLXVzZSBpdCBuZXh0IHRpbWUuXG4gICAgICAgICAgICB0aGlzLmlucHV0Q29udHJvbCA9IGlucHV0T3JUZXh0QXJlYTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghaW5wdXRPclRleHRBcmVhKSB7XG4gICAgICAgICAgICAvLyBHZXQgY2FjaGVkIDx0ZXh0YXJlYT4gb3IgY3JlYXRlIGl0LlxuICAgICAgICAgICAgaW5wdXRPclRleHRBcmVhID1cbiAgICAgICAgICAgICAgICB0aGlzLnRleHRBcmVhQ29udHJvbCB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0ZXh0YXJlYScpO1xuICAgICAgICAgICAgLy8gQ2FjaGUgdGhlIDx0ZXh0YXJlYT4gdG8gcmUtdXNlIGl0IG5leHQgdGltZS5cbiAgICAgICAgICAgIHRoaXMudGV4dEFyZWFDb250cm9sID0gaW5wdXRPclRleHRBcmVhO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNldCB0aGlzIHZhcmlhYmxlIHNvIHdlIGNhbiBjaGVjayBpdCBmb3IgaW5wdXQtc3BlY2lmaWMgcHJvcGVydGllcy5cbiAgICAgICAgY29uc3QgaW5wdXQgPSBpc0lucHV0U3RhdGUoc3RhdGUpXG4gICAgICAgICAgICA/IGlucHV0T3JUZXh0QXJlYVxuICAgICAgICAgICAgOiBudWxsO1xuICAgICAgICAvLyBTZXQgaW5wdXQncyBcInR5cGVcIiBmaXJzdCwgc2luY2UgdGhpcyBjYW4gY2hhbmdlIHRoZSBvdGhlciBwcm9wZXJ0aWVzXG4gICAgICAgIGlmIChpbnB1dCkge1xuICAgICAgICAgICAgaW5wdXQudHlwZSA9IHN0YXRlLnR5cGU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlucHV0T3JUZXh0QXJlYS52YWx1ZSAhPT0gc3RhdGUudmFsdWUpIHtcbiAgICAgICAgICAgIC8vIE9ubHkgcHJvZ3JhbW1hdGljYWxseSBzZXQgdGhlIHZhbHVlIGlmIHRoZXJlJ3MgYSBkaWZmZXJlbmNlLiBXaGVuIHVzaW5nXG4gICAgICAgICAgICAvLyB0aGUgcmVuZGVyZWQgY29udHJvbCwgdGhlIHZhbHVlIHdpbGwgYWx3YXlzIGJlIHVwIHRvIGRhdGUuIFNldHRpbmcgdGhlXG4gICAgICAgICAgICAvLyBwcm9wZXJ0eSAoZXZlbiBpZiBpdCdzIHRoZSBzYW1lIHN0cmluZykgd2lsbCByZXNldCB0aGUgaW50ZXJuYWwgPGlucHV0PlxuICAgICAgICAgICAgLy8gZGlydHkgZmxhZywgbWFraW5nIG1pbmxlbmd0aCBhbmQgbWF4bGVuZ3RoIHZhbGlkYXRpb24gcmVzZXQuXG4gICAgICAgICAgICBpbnB1dE9yVGV4dEFyZWEudmFsdWUgPSBzdGF0ZS52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpbnB1dE9yVGV4dEFyZWEucmVxdWlyZWQgPSBzdGF0ZS5yZXF1aXJlZDtcbiAgICAgICAgLy8gVGhlIGZvbGxvd2luZyBJRExBdHRyaWJ1dGUgcHJvcGVydGllcyB3aWxsIGFsd2F5cyBoeWRyYXRlIGFuIGF0dHJpYnV0ZSxcbiAgICAgICAgLy8gZXZlbiBpZiBzZXQgdG8gYSB0aGUgZGVmYXVsdCB2YWx1ZSAoJycgb3IgLTEpLiBUaGUgcHJlc2VuY2Ugb2YgdGhlXG4gICAgICAgIC8vIGF0dHJpYnV0ZSB0cmlnZ2VycyBjb25zdHJhaW50IHZhbGlkYXRpb24sIHNvIHdlIG11c3QgcmVtb3ZlIHRoZSBhdHRyaWJ1dGVcbiAgICAgICAgLy8gd2hlbiBlbXB0eS5cbiAgICAgICAgaWYgKGlucHV0KSB7XG4gICAgICAgICAgICBjb25zdCBpbnB1dFN0YXRlID0gc3RhdGU7XG4gICAgICAgICAgICBpZiAoaW5wdXRTdGF0ZS5wYXR0ZXJuKSB7XG4gICAgICAgICAgICAgICAgaW5wdXQucGF0dGVybiA9IGlucHV0U3RhdGUucGF0dGVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlucHV0LnJlbW92ZUF0dHJpYnV0ZSgncGF0dGVybicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlucHV0U3RhdGUubWluKSB7XG4gICAgICAgICAgICAgICAgaW5wdXQubWluID0gaW5wdXRTdGF0ZS5taW47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbnB1dC5yZW1vdmVBdHRyaWJ1dGUoJ21pbicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlucHV0U3RhdGUubWF4KSB7XG4gICAgICAgICAgICAgICAgaW5wdXQubWF4ID0gaW5wdXRTdGF0ZS5tYXg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbnB1dC5yZW1vdmVBdHRyaWJ1dGUoJ21heCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlucHV0U3RhdGUuc3RlcCkge1xuICAgICAgICAgICAgICAgIGlucHV0LnN0ZXAgPSBpbnB1dFN0YXRlLnN0ZXA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpbnB1dC5yZW1vdmVBdHRyaWJ1dGUoJ3N0ZXAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBVc2UgLTEgdG8gcmVwcmVzZW50IG5vIG1pbmxlbmd0aCBhbmQgbWF4bGVuZ3RoLCB3aGljaCBpcyB3aGF0IHRoZVxuICAgICAgICAvLyBwbGF0Zm9ybSBpbnB1dCByZXR1cm5zLiBIb3dldmVyLCBpdCB3aWxsIHRocm93IGFuIGVycm9yIGlmIHlvdSB0cnkgdG9cbiAgICAgICAgLy8gbWFudWFsbHkgc2V0IGl0IHRvIC0xLlxuICAgICAgICAvL1xuICAgICAgICAvLyBXaGlsZSB0aGUgdHlwZSBpcyBgbnVtYmVyYCwgaXQgbWF5IGFjdHVhbGx5IGJlIGBudWxsYCBhdCBydW50aW1lLlxuICAgICAgICAvLyBgbnVsbCA+IC0xYCBpcyB0cnVlIHNpbmNlIGBudWxsYCBjb2VyY2VzIHRvIGAwYCwgc28gd2UgZGVmYXVsdCBudWxsIGFuZFxuICAgICAgICAvLyB1bmRlZmluZWQgdG8gLTEuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFdlIHNldCBhdHRyaWJ1dGVzIGluc3RlYWQgb2YgcHJvcGVydGllcyBzaW5jZSBzZXR0aW5nIGEgcHJvcGVydHkgbWF5XG4gICAgICAgIC8vIHRocm93IGFuIG91dCBvZiBib3VuZHMgZXJyb3IgaW4gcmVsYXRpb24gdG8gdGhlIG90aGVyIHByb3BlcnR5LlxuICAgICAgICAvLyBBdHRyaWJ1dGVzIHdpbGwgbm90IHRocm93IGVycm9ycyB3aGlsZSB0aGUgc3RhdGUgaXMgdXBkYXRpbmcuXG4gICAgICAgIGlmICgoc3RhdGUubWluTGVuZ3RoID8/IC0xKSA+IC0xKSB7XG4gICAgICAgICAgICBpbnB1dE9yVGV4dEFyZWEuc2V0QXR0cmlidXRlKCdtaW5sZW5ndGgnLCBTdHJpbmcoc3RhdGUubWluTGVuZ3RoKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpbnB1dE9yVGV4dEFyZWEucmVtb3ZlQXR0cmlidXRlKCdtaW5sZW5ndGgnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKHN0YXRlLm1heExlbmd0aCA/PyAtMSkgPiAtMSkge1xuICAgICAgICAgICAgaW5wdXRPclRleHRBcmVhLnNldEF0dHJpYnV0ZSgnbWF4bGVuZ3RoJywgU3RyaW5nKHN0YXRlLm1heExlbmd0aCkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaW5wdXRPclRleHRBcmVhLnJlbW92ZUF0dHJpYnV0ZSgnbWF4bGVuZ3RoJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHZhbGlkaXR5OiBpbnB1dE9yVGV4dEFyZWEudmFsaWRpdHksXG4gICAgICAgICAgICB2YWxpZGF0aW9uTWVzc2FnZTogaW5wdXRPclRleHRBcmVhLnZhbGlkYXRpb25NZXNzYWdlLFxuICAgICAgICB9O1xuICAgIH1cbiAgICBlcXVhbHMoeyBzdGF0ZTogcHJldiB9LCB7IHN0YXRlOiBuZXh0IH0pIHtcbiAgICAgICAgLy8gQ2hlY2sgc2hhcmVkIGlucHV0IGFuZCB0ZXh0YXJlYSBwcm9wZXJ0aWVzXG4gICAgICAgIGNvbnN0IGlucHV0T3JUZXh0QXJlYUVxdWFsID0gcHJldi50eXBlID09PSBuZXh0LnR5cGUgJiZcbiAgICAgICAgICAgIHByZXYudmFsdWUgPT09IG5leHQudmFsdWUgJiZcbiAgICAgICAgICAgIHByZXYucmVxdWlyZWQgPT09IG5leHQucmVxdWlyZWQgJiZcbiAgICAgICAgICAgIHByZXYubWluTGVuZ3RoID09PSBuZXh0Lm1pbkxlbmd0aCAmJlxuICAgICAgICAgICAgcHJldi5tYXhMZW5ndGggPT09IG5leHQubWF4TGVuZ3RoO1xuICAgICAgICBpZiAoIWlzSW5wdXRTdGF0ZShwcmV2KSB8fCAhaXNJbnB1dFN0YXRlKG5leHQpKSB7XG4gICAgICAgICAgICAvLyBCb3RoIGFyZSB0ZXh0YXJlYXMsIGFsbCByZWxldmFudCBwcm9wZXJ0aWVzIGFyZSBlcXVhbC5cbiAgICAgICAgICAgIHJldHVybiBpbnB1dE9yVGV4dEFyZWFFcXVhbDtcbiAgICAgICAgfVxuICAgICAgICAvLyBDaGVjayBhZGRpdGlvbmFsIGlucHV0LXNwZWNpZmljIHByb3BlcnRpZXMuXG4gICAgICAgIHJldHVybiAoaW5wdXRPclRleHRBcmVhRXF1YWwgJiZcbiAgICAgICAgICAgIHByZXYucGF0dGVybiA9PT0gbmV4dC5wYXR0ZXJuICYmXG4gICAgICAgICAgICBwcmV2Lm1pbiA9PT0gbmV4dC5taW4gJiZcbiAgICAgICAgICAgIHByZXYubWF4ID09PSBuZXh0Lm1heCAmJlxuICAgICAgICAgICAgcHJldi5zdGVwID09PSBuZXh0LnN0ZXApO1xuICAgIH1cbiAgICBjb3B5KHsgc3RhdGUgfSkge1xuICAgICAgICAvLyBEb24ndCBob2xkIGEgcmVmZXJlbmNlIHRvIHRoZSByZW5kZXJlZCBjb250cm9sIHdoZW4gY29weWluZyBzaW5jZSB3ZVxuICAgICAgICAvLyBkb24ndCB1c2UgaXQgd2hlbiBjaGVja2luZyBpZiB0aGUgc3RhdGUgY2hhbmdlZC5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHN0YXRlOiBpc0lucHV0U3RhdGUoc3RhdGUpXG4gICAgICAgICAgICAgICAgPyB0aGlzLmNvcHlJbnB1dChzdGF0ZSlcbiAgICAgICAgICAgICAgICA6IHRoaXMuY29weVRleHRBcmVhKHN0YXRlKSxcbiAgICAgICAgICAgIHJlbmRlcmVkQ29udHJvbDogbnVsbCxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgY29weUlucHV0KHN0YXRlKSB7XG4gICAgICAgIGNvbnN0IHsgdHlwZSwgcGF0dGVybiwgbWluLCBtYXgsIHN0ZXAgfSA9IHN0YXRlO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4udGhpcy5jb3B5U2hhcmVkU3RhdGUoc3RhdGUpLFxuICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgIHBhdHRlcm4sXG4gICAgICAgICAgICBtaW4sXG4gICAgICAgICAgICBtYXgsXG4gICAgICAgICAgICBzdGVwLFxuICAgICAgICB9O1xuICAgIH1cbiAgICBjb3B5VGV4dEFyZWEoc3RhdGUpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLnRoaXMuY29weVNoYXJlZFN0YXRlKHN0YXRlKSxcbiAgICAgICAgICAgIHR5cGU6IHN0YXRlLnR5cGUsXG4gICAgICAgIH07XG4gICAgfVxuICAgIGNvcHlTaGFyZWRTdGF0ZSh7IHZhbHVlLCByZXF1aXJlZCwgbWluTGVuZ3RoLCBtYXhMZW5ndGgsIH0pIHtcbiAgICAgICAgcmV0dXJuIHsgdmFsdWUsIHJlcXVpcmVkLCBtaW5MZW5ndGgsIG1heExlbmd0aCB9O1xuICAgIH1cbn1cbmZ1bmN0aW9uIGlzSW5wdXRTdGF0ZShzdGF0ZSkge1xuICAgIHJldHVybiBzdGF0ZS50eXBlICE9PSAndGV4dGFyZWEnO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dGV4dC1maWVsZC12YWxpZGF0b3IuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjMgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuLyoqXG4gKiBBIGNsYXNzIHRoYXQgY29tcHV0ZXMgYW5kIGNhY2hlcyBgVmFsaWRpdHlTdGF0ZUZsYWdzYCBmb3IgYSBjb21wb25lbnQgd2l0aFxuICogYSBnaXZlbiBgU3RhdGVgIGludGVyZmFjZS5cbiAqXG4gKiBDYWNoZWQgcGVyZm9ybWFuY2UgYmVmb3JlIGNvbXB1dGluZyB2YWxpZGl0eSBpcyBpbXBvcnRhbnQgc2luY2UgY29uc3RyYWludFxuICogdmFsaWRhdGlvbiBtdXN0IGJlIGNoZWNrZWQgZnJlcXVlbnRseSBhbmQgc3luY2hyb25vdXNseSB3aGVuIHByb3BlcnRpZXNcbiAqIGNoYW5nZS5cbiAqXG4gKiBAdGVtcGxhdGUgU3RhdGUgVGhlIGV4cGVjdGVkIGludGVyZmFjZSBvZiBwcm9wZXJ0aWVzIHJlbGV2YW50IHRvIGNvbnN0cmFpbnRcbiAqICAgICB2YWxpZGF0aW9uLlxuICovXG5leHBvcnQgY2xhc3MgVmFsaWRhdG9yIHtcbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IHZhbGlkYXRvci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBnZXRDdXJyZW50U3RhdGUgQSBjYWxsYmFjayB0aGF0IHJldHVybnMgdGhlIGN1cnJlbnQgc3RhdGUgb2ZcbiAgICAgKiAgICAgY29uc3RyYWludCB2YWxpZGF0aW9uLXJlbGF0ZWQgcHJvcGVydGllcy5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihnZXRDdXJyZW50U3RhdGUpIHtcbiAgICAgICAgdGhpcy5nZXRDdXJyZW50U3RhdGUgPSBnZXRDdXJyZW50U3RhdGU7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgY3VycmVudCB2YWxpZGl0eSBzdGF0ZSBhbmQgbWVzc2FnZS4gVGhpcyBpcyBjYWNoZWQgYW5kIHJldHVybnMgaWZcbiAgICAgICAgICogY29uc3RyYWludCB2YWxpZGF0aW9uIHN0YXRlIGRvZXMgbm90IGNoYW5nZS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuY3VycmVudFZhbGlkaXR5ID0ge1xuICAgICAgICAgICAgdmFsaWRpdHk6IHt9LFxuICAgICAgICAgICAgdmFsaWRhdGlvbk1lc3NhZ2U6ICcnLFxuICAgICAgICB9O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IGBWYWxpZGl0eVN0YXRlRmxhZ3NgIGFuZCB2YWxpZGF0aW9uIG1lc3NhZ2UgZm9yIHRoZVxuICAgICAqIHZhbGlkYXRvci5cbiAgICAgKlxuICAgICAqIElmIHRoZSBjb25zdHJhaW50IHZhbGlkYXRpb24gc3RhdGUgaGFzIG5vdCBjaGFuZ2VkLCB0aGlzIHdpbGwgcmV0dXJuIGFcbiAgICAgKiBjYWNoZWQgcmVzdWx0LiBUaGlzIGlzIGltcG9ydGFudCBzaW5jZSBgZ2V0VmFsaWRpdHkoKWAgY2FuIGJlIGNhbGxlZFxuICAgICAqIGZyZXF1ZW50bHkgaW4gcmVzcG9uc2UgdG8gc3luY2hyb25vdXMgcHJvcGVydHkgY2hhbmdlcy5cbiAgICAgKlxuICAgICAqIEByZXR1cm4gVGhlIGN1cnJlbnQgdmFsaWRpdHkgYW5kIHZhbGlkYXRpb24gbWVzc2FnZS5cbiAgICAgKi9cbiAgICBnZXRWYWxpZGl0eSgpIHtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSB0aGlzLmdldEN1cnJlbnRTdGF0ZSgpO1xuICAgICAgICBjb25zdCBoYXNTdGF0ZUNoYW5nZWQgPSAhdGhpcy5wcmV2U3RhdGUgfHwgIXRoaXMuZXF1YWxzKHRoaXMucHJldlN0YXRlLCBzdGF0ZSk7XG4gICAgICAgIGlmICghaGFzU3RhdGVDaGFuZ2VkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jdXJyZW50VmFsaWRpdHk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyB2YWxpZGl0eSwgdmFsaWRhdGlvbk1lc3NhZ2UgfSA9IHRoaXMuY29tcHV0ZVZhbGlkaXR5KHN0YXRlKTtcbiAgICAgICAgdGhpcy5wcmV2U3RhdGUgPSB0aGlzLmNvcHkoc3RhdGUpO1xuICAgICAgICB0aGlzLmN1cnJlbnRWYWxpZGl0eSA9IHtcbiAgICAgICAgICAgIHZhbGlkYXRpb25NZXNzYWdlLFxuICAgICAgICAgICAgdmFsaWRpdHk6IHtcbiAgICAgICAgICAgICAgICAvLyBDaGFuZ2UgYW55IGBWYWxpZGl0eVN0YXRlYCBpbnN0YW5jZXMgaW50byBgVmFsaWRpdHlTdGF0ZUZsYWdzYCBzaW5jZVxuICAgICAgICAgICAgICAgIC8vIGBWYWxpZGl0eVN0YXRlYCBjYW5ub3QgYmUgZWFzaWx5IGB7Li4uc3ByZWFkfWAuXG4gICAgICAgICAgICAgICAgYmFkSW5wdXQ6IHZhbGlkaXR5LmJhZElucHV0LFxuICAgICAgICAgICAgICAgIGN1c3RvbUVycm9yOiB2YWxpZGl0eS5jdXN0b21FcnJvcixcbiAgICAgICAgICAgICAgICBwYXR0ZXJuTWlzbWF0Y2g6IHZhbGlkaXR5LnBhdHRlcm5NaXNtYXRjaCxcbiAgICAgICAgICAgICAgICByYW5nZU92ZXJmbG93OiB2YWxpZGl0eS5yYW5nZU92ZXJmbG93LFxuICAgICAgICAgICAgICAgIHJhbmdlVW5kZXJmbG93OiB2YWxpZGl0eS5yYW5nZVVuZGVyZmxvdyxcbiAgICAgICAgICAgICAgICBzdGVwTWlzbWF0Y2g6IHZhbGlkaXR5LnN0ZXBNaXNtYXRjaCxcbiAgICAgICAgICAgICAgICB0b29Mb25nOiB2YWxpZGl0eS50b29Mb25nLFxuICAgICAgICAgICAgICAgIHRvb1Nob3J0OiB2YWxpZGl0eS50b29TaG9ydCxcbiAgICAgICAgICAgICAgICB0eXBlTWlzbWF0Y2g6IHZhbGlkaXR5LnR5cGVNaXNtYXRjaCxcbiAgICAgICAgICAgICAgICB2YWx1ZU1pc3Npbmc6IHZhbGlkaXR5LnZhbHVlTWlzc2luZyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRWYWxpZGl0eTtcbiAgICB9XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD12YWxpZGF0b3IuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjQgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuLy8gR2VuZXJhdGVkIHN0eWxlc2hlZXQgZm9yIC4vbGFicy9pdGVtL2ludGVybmFsL2l0ZW0tc3R5bGVzLmNzcy5cbmltcG9ydCB7IGNzcyB9IGZyb20gJ2xpdCc7XG5leHBvcnQgY29uc3Qgc3R5bGVzID0gY3NzIGA6aG9zdHtjb2xvcjp2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCk7Zm9udC1mYW1pbHk6dmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LWxhcmdlLWZvbnQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS1wbGFpbiwgUm9ib3RvKSk7Zm9udC1zaXplOnZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS1zaXplLCAxcmVtKTtmb250LXdlaWdodDp2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbGFyZ2Utd2VpZ2h0LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2Utd2VpZ2h0LXJlZ3VsYXIsIDQwMCkpO2xpbmUtaGVpZ2h0OnZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS1saW5lLWhlaWdodCwgMS41cmVtKTthbGlnbi1pdGVtczpjZW50ZXI7Ym94LXNpemluZzpib3JkZXItYm94O2Rpc3BsYXk6ZmxleDtnYXA6MTZweDttaW4taGVpZ2h0OjU2cHg7b3ZlcmZsb3c6aGlkZGVuO3BhZGRpbmc6MTJweCAxNnB4O3Bvc2l0aW9uOnJlbGF0aXZlO3RleHQtb3ZlcmZsb3c6ZWxsaXBzaXN9Omhvc3QoW211bHRpbGluZV0pe21pbi1oZWlnaHQ6NzJweH1bbmFtZT1vdmVybGluZV17Y29sb3I6dmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0Zik7Zm9udC1mYW1pbHk6dmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1sYWJlbC1zbWFsbC1mb250LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2UtcGxhaW4sIFJvYm90bykpO2ZvbnQtc2l6ZTp2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWxhYmVsLXNtYWxsLXNpemUsIDAuNjg3NXJlbSk7Zm9udC13ZWlnaHQ6dmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1sYWJlbC1zbWFsbC13ZWlnaHQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS13ZWlnaHQtbWVkaXVtLCA1MDApKTtsaW5lLWhlaWdodDp2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWxhYmVsLXNtYWxsLWxpbmUtaGVpZ2h0LCAxcmVtKX1bbmFtZT1zdXBwb3J0aW5nLXRleHRde2NvbG9yOnZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpO2ZvbnQtZmFtaWx5OnZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1tZWRpdW0tZm9udCwgdmFyKC0tbWQtcmVmLXR5cGVmYWNlLXBsYWluLCBSb2JvdG8pKTtmb250LXNpemU6dmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LW1lZGl1bS1zaXplLCAwLjg3NXJlbSk7Zm9udC13ZWlnaHQ6dmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LW1lZGl1bS13ZWlnaHQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS13ZWlnaHQtcmVndWxhciwgNDAwKSk7bGluZS1oZWlnaHQ6dmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LW1lZGl1bS1saW5lLWhlaWdodCwgMS4yNXJlbSl9W25hbWU9dHJhaWxpbmctc3VwcG9ydGluZy10ZXh0XXtjb2xvcjp2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKTtmb250LWZhbWlseTp2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWxhYmVsLXNtYWxsLWZvbnQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS1wbGFpbiwgUm9ib3RvKSk7Zm9udC1zaXplOnZhcigtLW1kLXN5cy10eXBlc2NhbGUtbGFiZWwtc21hbGwtc2l6ZSwgMC42ODc1cmVtKTtmb250LXdlaWdodDp2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWxhYmVsLXNtYWxsLXdlaWdodCwgdmFyKC0tbWQtcmVmLXR5cGVmYWNlLXdlaWdodC1tZWRpdW0sIDUwMCkpO2xpbmUtaGVpZ2h0OnZhcigtLW1kLXN5cy10eXBlc2NhbGUtbGFiZWwtc21hbGwtbGluZS1oZWlnaHQsIDFyZW0pfVtuYW1lPWNvbnRhaW5lcl06OnNsb3R0ZWQoKil7aW5zZXQ6MDtwb3NpdGlvbjphYnNvbHV0ZX0uZGVmYXVsdC1zbG90e2Rpc3BsYXk6aW5saW5lfS5kZWZhdWx0LXNsb3QsLnRleHQgOjpzbG90dGVkKCope292ZXJmbG93OmhpZGRlbjt0ZXh0LW92ZXJmbG93OmVsbGlwc2lzfS50ZXh0e2Rpc3BsYXk6ZmxleDtmbGV4OjE7ZmxleC1kaXJlY3Rpb246Y29sdW1uO292ZXJmbG93OmhpZGRlbn1cbmA7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pdGVtLXN0eWxlcy5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBfX2RlY29yYXRlIH0gZnJvbSBcInRzbGliXCI7XG5pbXBvcnQgeyBodG1sLCBMaXRFbGVtZW50IH0gZnJvbSAnbGl0JztcbmltcG9ydCB7IHByb3BlcnR5LCBxdWVyeUFsbCB9IGZyb20gJ2xpdC9kZWNvcmF0b3JzLmpzJztcbi8qKlxuICogQW4gaXRlbSBsYXlvdXQgY29tcG9uZW50LlxuICovXG5leHBvcnQgY2xhc3MgSXRlbSBleHRlbmRzIExpdEVsZW1lbnQge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICAvKipcbiAgICAgICAgICogT25seSBuZWVkZWQgZm9yIFNTUi5cbiAgICAgICAgICpcbiAgICAgICAgICogQWRkIHRoaXMgYXR0cmlidXRlIHdoZW4gYW4gaXRlbSBoYXMgdHdvIGxpbmVzIHRvIGF2b2lkIGEgRmxhc2ggT2YgVW5zdHlsZWRcbiAgICAgICAgICogQ29udGVudC4gVGhpcyBhdHRyaWJ1dGUgaXMgbm90IG5lZWRlZCBmb3Igc2luZ2xlIGxpbmUgaXRlbXMgb3IgaXRlbXMgd2l0aFxuICAgICAgICAgKiB0aHJlZSBvciBtb3JlIGxpbmVzLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5tdWx0aWxpbmUgPSBmYWxzZTtcbiAgICB9XG4gICAgcmVuZGVyKCkge1xuICAgICAgICByZXR1cm4gaHRtbCBgXG4gICAgICA8c2xvdCBuYW1lPVwiY29udGFpbmVyXCI+PC9zbG90PlxuICAgICAgPHNsb3QgY2xhc3M9XCJub24tdGV4dFwiIG5hbWU9XCJzdGFydFwiPjwvc2xvdD5cbiAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0XCI+XG4gICAgICAgIDxzbG90IG5hbWU9XCJvdmVybGluZVwiIEBzbG90Y2hhbmdlPSR7dGhpcy5oYW5kbGVUZXh0U2xvdENoYW5nZX0+PC9zbG90PlxuICAgICAgICA8c2xvdFxuICAgICAgICAgIGNsYXNzPVwiZGVmYXVsdC1zbG90XCJcbiAgICAgICAgICBAc2xvdGNoYW5nZT0ke3RoaXMuaGFuZGxlVGV4dFNsb3RDaGFuZ2V9Pjwvc2xvdD5cbiAgICAgICAgPHNsb3QgbmFtZT1cImhlYWRsaW5lXCIgQHNsb3RjaGFuZ2U9JHt0aGlzLmhhbmRsZVRleHRTbG90Q2hhbmdlfT48L3Nsb3Q+XG4gICAgICAgIDxzbG90XG4gICAgICAgICAgbmFtZT1cInN1cHBvcnRpbmctdGV4dFwiXG4gICAgICAgICAgQHNsb3RjaGFuZ2U9JHt0aGlzLmhhbmRsZVRleHRTbG90Q2hhbmdlfT48L3Nsb3Q+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxzbG90IGNsYXNzPVwibm9uLXRleHRcIiBuYW1lPVwidHJhaWxpbmctc3VwcG9ydGluZy10ZXh0XCI+PC9zbG90PlxuICAgICAgPHNsb3QgY2xhc3M9XCJub24tdGV4dFwiIG5hbWU9XCJlbmRcIj48L3Nsb3Q+XG4gICAgYDtcbiAgICB9XG4gICAgaGFuZGxlVGV4dFNsb3RDaGFuZ2UoKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIHRoZXJlJ3MgbW9yZSB0aGFuIG9uZSB0ZXh0IHNsb3Qgd2l0aCBjb250ZW50LiBJZiBzbywgdGhlIGl0ZW0gaXNcbiAgICAgICAgLy8gbXVsdGlsaW5lLCB3aGljaCBoYXMgYSBkaWZmZXJlbnQgbWluLWhlaWdodCB0aGFuIHNpbmdsZSBsaW5lIGl0ZW1zLlxuICAgICAgICBsZXQgaXNNdWx0aWxpbmUgPSBmYWxzZTtcbiAgICAgICAgbGV0IHNsb3RzV2l0aENvbnRlbnQgPSAwO1xuICAgICAgICBmb3IgKGNvbnN0IHNsb3Qgb2YgdGhpcy50ZXh0U2xvdHMpIHtcbiAgICAgICAgICAgIGlmIChzbG90SGFzQ29udGVudChzbG90KSkge1xuICAgICAgICAgICAgICAgIHNsb3RzV2l0aENvbnRlbnQgKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzbG90c1dpdGhDb250ZW50ID4gMSkge1xuICAgICAgICAgICAgICAgIGlzTXVsdGlsaW5lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLm11bHRpbGluZSA9IGlzTXVsdGlsaW5lO1xuICAgIH1cbn1cbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgcmVmbGVjdDogdHJ1ZSB9KVxuXSwgSXRlbS5wcm90b3R5cGUsIFwibXVsdGlsaW5lXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBxdWVyeUFsbCgnLnRleHQgc2xvdCcpXG5dLCBJdGVtLnByb3RvdHlwZSwgXCJ0ZXh0U2xvdHNcIiwgdm9pZCAwKTtcbmZ1bmN0aW9uIHNsb3RIYXNDb250ZW50KHNsb3QpIHtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2Ygc2xvdC5hc3NpZ25lZE5vZGVzKHsgZmxhdHRlbjogdHJ1ZSB9KSkge1xuICAgICAgICAvLyBBc3N1bWUgdGhlcmUncyBjb250ZW50IGlmIHRoZXJlJ3MgYW4gZWxlbWVudCBzbG90dGVkIGluXG4gICAgICAgIGNvbnN0IGlzRWxlbWVudCA9IG5vZGUubm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFO1xuICAgICAgICAvLyBJZiB0aGVyZSdzIG9ubHkgdGV4dCBub2RlcyBmb3IgdGhlIGRlZmF1bHQgc2xvdCwgY2hlY2sgaWYgdGhlcmUnc1xuICAgICAgICAvLyBub24td2hpdGVzcGFjZS5cbiAgICAgICAgY29uc3QgaXNUZXh0V2l0aENvbnRlbnQgPSBub2RlLm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSAmJiBub2RlLnRleHRDb250ZW50Py5tYXRjaCgvXFxTLyk7XG4gICAgICAgIGlmIChpc0VsZW1lbnQgfHwgaXNUZXh0V2l0aENvbnRlbnQpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWl0ZW0uanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjMgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuaW1wb3J0IHsgX19kZWNvcmF0ZSB9IGZyb20gXCJ0c2xpYlwiO1xuaW1wb3J0IHsgY3VzdG9tRWxlbWVudCB9IGZyb20gJ2xpdC9kZWNvcmF0b3JzLmpzJztcbmltcG9ydCB7IEl0ZW0gfSBmcm9tICcuL2ludGVybmFsL2l0ZW0uanMnO1xuaW1wb3J0IHsgc3R5bGVzIH0gZnJvbSAnLi9pbnRlcm5hbC9pdGVtLXN0eWxlcy5qcyc7XG4vKipcbiAqIEFuIGl0ZW0gbGF5b3V0IGNvbXBvbmVudCB0aGF0IGNhbiBiZSB1c2VkIGluc2lkZSBsaXN0IGl0ZW1zIHRvIGdpdmUgdGhlbVxuICogdGhlaXIgY3VzdG9taXphYmxlIHN0cnVjdHVyZS5cbiAqXG4gKiBgPG1kLWl0ZW0+YCBkb2VzIG5vdCBoYXZlIGFueSBmdW5jdGlvbmFsaXR5LCB3aGljaCBtdXN0IGJlIGFkZGVkIGJ5IHRoZVxuICogY29tcG9uZW50IHVzaW5nIGl0LlxuICpcbiAqIEFsbCB0ZXh0IHdpbGwgd3JhcCB1bmxlc3MgYHdoaXRlLXNwYWNlOiBub3dyYXBgIGlzIHNldCBvbiB0aGUgaXRlbSBvciBhbnkgb2ZcbiAqIGl0cyBjaGlsZHJlbi5cbiAqXG4gKiBTbG90cyBhdmFpbGFibGU6XG4gKiAtIGA8ZGVmYXVsdD5gOiBUaGUgaGVhZGxpbmUsIG9yIGN1c3RvbSBjb250ZW50LlxuICogLSBgaGVhZGxpbmVgOiBUaGUgZmlyc3QgbGluZS5cbiAqIC0gYHN1cHBvcnRpbmctdGV4dGA6IFN1cHBvcnRpbmcgdGV4dCBsaW5lcyB1bmRlcm5lYXRoIHRoZSBoZWFkbGluZS5cbiAqIC0gYHRyYWlsaW5nLXN1cHBvcnRpbmctdGV4dGA6IEEgc21hbGwgdGV4dCBzbmlwcGV0IGF0IHRoZSBlbmQgb2YgdGhlIGl0ZW0uXG4gKiAtIGBzdGFydGA6IEFueSBsZWFkaW5nIGNvbnRlbnQsIHN1Y2ggYXMgaWNvbnMsIGF2YXRhcnMsIG9yIGNoZWNrYm94ZXMuXG4gKiAtIGBlbmRgOiBBbnkgdHJhaWxpbmcgY29udGVudCwgc3VjaCBhcyBpY29ucyBhbmQgYnV0dG9ucy5cbiAqIC0gYGNvbnRhaW5lcmA6IEJhY2tncm91bmQgY29udGFpbmVyIGNvbnRlbnQsIGludGVuZGVkIGZvciBhZGRpbmcgYWRkaXRpb25hbFxuICogICAgIHN0eWxlcywgc3VjaCBhcyByaXBwbGVzIG9yIGZvY3VzIHJpbmdzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBodG1sXG4gKiA8bWQtaXRlbT5TaW5nbGUgbGluZTwvbWQtaXRlbT5cbiAqXG4gKiA8bWQtaXRlbT5cbiAqICAgPGRpdiBjbGFzcz1cImN1c3RvbS1jb250ZW50XCI+Li4uPC9kaXY+XG4gKiA8L21kLWl0ZW0+XG4gKlxuICogPCEtLSBDbGFzc2ljIDEgdG8gMysgbGluZSBsaXN0IGl0ZW1zIC0tPlxuICogPG1kLWl0ZW0+XG4gKiAgIDxtZC1pY29uIHNsb3Q9XCJzdGFydFwiPmltYWdlPC9tZC1pY29uPlxuICogICA8ZGl2IHNsb3Q9XCJvdmVybGluZVwiPk92ZXJsaW5lPC9kaXY+XG4gKiAgIDxkaXYgc2xvdD1cImhlYWRsaW5lXCI+SGVhZGxpbmU8L2Rpdj5cbiAqICAgPGRpdj1cInN1cHBvcnRpbmctdGV4dFwiPlN1cHBvcnRpbmcgdGV4dDwvZGl2PlxuICogICA8ZGl2PVwidHJhaWxpbmctc3VwcG9ydGluZy10ZXh0XCI+VHJhaWxpbmc8L2Rpdj5cbiAqICAgPG1kLWljb24gc2xvdD1cImVuZFwiPmltYWdlPC9tZC1pY29uPlxuICogPC9tZC1pdGVtPlxuICogYGBgXG4gKlxuICogV2hlbiB3cmFwcGluZyBgPG1kLWl0ZW0+YCwgZm9yd2FyZCB0aGUgYXZhaWxhYmxlIHNsb3RzIHRvIHVzZSB0aGUgc2FtZSBzbG90XG4gKiBzdHJ1Y3R1cmUgZm9yIHRoZSB3cmFwcGluZyBjb21wb25lbnQgKHRoaXMgaXMgd2hhdCBgPG1kLWxpc3QtaXRlbT5gIGRvZXMpLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBodG1sXG4gKiA8bWQtaXRlbT5cbiAqICAgPHNsb3Q+PC9zbG90PlxuICogICA8c2xvdCBuYW1lPVwib3ZlcmxpbmVcIiBzbG90PVwib3ZlcmxpbmVcIj48L3Nsb3Q+XG4gKiAgIDxzbG90IG5hbWU9XCJoZWFkbGluZVwiIHNsb3Q9XCJoZWFkbGluZVwiPjwvc2xvdD5cbiAqICAgPHNsb3QgbmFtZT1cInN1cHBvcnRpbmctdGV4dFwiIHNsb3Q9XCJzdXBwb3J0aW5nLXRleHRcIj48L3Nsb3Q+XG4gKiAgIDxzbG90IG5hbWU9XCJ0cmFpbGluZy1zdXBwb3J0aW5nLXRleHRcIlxuICogICAgICAgc2xvdD1cInRyYWlsaW5nLXN1cHBvcnRpbmctdGV4dFwiPjwvc2xvdD5cbiAqICAgPHNsb3QgbmFtZT1cInN0YXJ0XCIgc2xvdD1cInN0YXJ0XCI+PC9zbG90PlxuICogICA8c2xvdCBuYW1lPVwiZW5kXCIgc2xvdD1cImVuZFwiPjwvc2xvdD5cbiAqIDwvbWQtaXRlbT5cbiAqIGBgYFxuICpcbiAqIEBmaW5hbFxuICogQHN1cHByZXNzIHt2aXNpYmlsaXR5fVxuICovXG5sZXQgTWRJdGVtID0gY2xhc3MgTWRJdGVtIGV4dGVuZHMgSXRlbSB7XG59O1xuTWRJdGVtLnN0eWxlcyA9IFtzdHlsZXNdO1xuTWRJdGVtID0gX19kZWNvcmF0ZShbXG4gICAgY3VzdG9tRWxlbWVudCgnbWQtaXRlbScpXG5dLCBNZEl0ZW0pO1xuZXhwb3J0IHsgTWRJdGVtIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pdGVtLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIzIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbmltcG9ydCB7IGFjdGl2YXRlRmlyc3RJdGVtLCBhY3RpdmF0ZUxhc3RJdGVtLCBhY3RpdmF0ZU5leHRJdGVtLCBhY3RpdmF0ZVByZXZpb3VzSXRlbSwgZ2V0QWN0aXZlSXRlbSwgZ2V0Rmlyc3RBY3RpdmF0YWJsZUl0ZW0sIH0gZnJvbSAnLi9saXN0LW5hdmlnYXRpb24taGVscGVycy5qcyc7XG4vLyBUT0RPOiBtb3ZlIHRoaXMgZmlsZSB0byBMaXN0IGFuZCBtYWtlIExpc3QgdXNlIHRoaXNcbi8qKlxuICogRGVmYXVsdCBrZXlzIHRoYXQgdHJpZ2dlciBuYXZpZ2F0aW9uLlxuICovXG4vLyB0c2xpbnQ6ZGlzYWJsZTplbmZvcmNlLW5hbWUtY2FzaW5nIEZvbGxvd2luZyBFbnVtIHN0eWxlXG5leHBvcnQgY29uc3QgTmF2aWdhYmxlS2V5cyA9IHtcbiAgICBBcnJvd0Rvd246ICdBcnJvd0Rvd24nLFxuICAgIEFycm93TGVmdDogJ0Fycm93TGVmdCcsXG4gICAgQXJyb3dVcDogJ0Fycm93VXAnLFxuICAgIEFycm93UmlnaHQ6ICdBcnJvd1JpZ2h0JyxcbiAgICBIb21lOiAnSG9tZScsXG4gICAgRW5kOiAnRW5kJyxcbn07XG4vKipcbiAqIEEgY29udHJvbGxlciB0aGF0IGhhbmRsZXMgbGlzdCBrZXlib2FyZCBuYXZpZ2F0aW9uIGFuZCBpdGVtIG1hbmFnZW1lbnQuXG4gKi9cbmV4cG9ydCBjbGFzcyBMaXN0Q29udHJvbGxlciB7XG4gICAgY29uc3RydWN0b3IoY29uZmlnKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIYW5kbGVzIGtleWJvYXJkIG5hdmlnYXRpb24uIFNob3VsZCBiZSBib3VuZCB0byB0aGUgbm9kZSB0aGF0IHdpbGwgYWN0IGFzXG4gICAgICAgICAqIHRoZSBMaXN0LlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5oYW5kbGVLZXlkb3duID0gKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBrZXkgPSBldmVudC5rZXk7XG4gICAgICAgICAgICBpZiAoZXZlbnQuZGVmYXVsdFByZXZlbnRlZCB8fCAhdGhpcy5pc05hdmlnYWJsZUtleShrZXkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gZG8gbm90IHVzZSB0aGlzLml0ZW1zIGRpcmVjdGx5IGluIHVwY29taW5nIGNhbGN1bGF0aW9ucyBzbyB3ZSBkb24ndFxuICAgICAgICAgICAgLy8gcmUtcXVlcnkgdGhlIERPTSB1bm5lY2Vzc2FyaWx5XG4gICAgICAgICAgICBjb25zdCBpdGVtcyA9IHRoaXMuaXRlbXM7XG4gICAgICAgICAgICBpZiAoIWl0ZW1zLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGFjdGl2ZUl0ZW1SZWNvcmQgPSBnZXRBY3RpdmVJdGVtKGl0ZW1zLCB0aGlzLmlzQWN0aXZhdGFibGUpO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIGNvbnN0IGlzUnRsID0gdGhpcy5pc1J0bCgpO1xuICAgICAgICAgICAgY29uc3QgaW5saW5lUHJldmlvdXMgPSBpc1J0bFxuICAgICAgICAgICAgICAgID8gTmF2aWdhYmxlS2V5cy5BcnJvd1JpZ2h0XG4gICAgICAgICAgICAgICAgOiBOYXZpZ2FibGVLZXlzLkFycm93TGVmdDtcbiAgICAgICAgICAgIGNvbnN0IGlubGluZU5leHQgPSBpc1J0bFxuICAgICAgICAgICAgICAgID8gTmF2aWdhYmxlS2V5cy5BcnJvd0xlZnRcbiAgICAgICAgICAgICAgICA6IE5hdmlnYWJsZUtleXMuQXJyb3dSaWdodDtcbiAgICAgICAgICAgIGxldCBuZXh0QWN0aXZlSXRlbSA9IG51bGw7XG4gICAgICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgICAgIC8vIEFjdGl2YXRlIHRoZSBuZXh0IGl0ZW1cbiAgICAgICAgICAgICAgICBjYXNlIE5hdmlnYWJsZUtleXMuQXJyb3dEb3duOlxuICAgICAgICAgICAgICAgIGNhc2UgaW5saW5lTmV4dDpcbiAgICAgICAgICAgICAgICAgICAgbmV4dEFjdGl2ZUl0ZW0gPSBhY3RpdmF0ZU5leHRJdGVtKGl0ZW1zLCBhY3RpdmVJdGVtUmVjb3JkLCB0aGlzLmlzQWN0aXZhdGFibGUsIHRoaXMud3JhcE5hdmlnYXRpb24oKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIC8vIEFjdGl2YXRlIHRoZSBwcmV2aW91cyBpdGVtXG4gICAgICAgICAgICAgICAgY2FzZSBOYXZpZ2FibGVLZXlzLkFycm93VXA6XG4gICAgICAgICAgICAgICAgY2FzZSBpbmxpbmVQcmV2aW91czpcbiAgICAgICAgICAgICAgICAgICAgbmV4dEFjdGl2ZUl0ZW0gPSBhY3RpdmF0ZVByZXZpb3VzSXRlbShpdGVtcywgYWN0aXZlSXRlbVJlY29yZCwgdGhpcy5pc0FjdGl2YXRhYmxlLCB0aGlzLndyYXBOYXZpZ2F0aW9uKCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAvLyBBY3RpdmF0ZSB0aGUgZmlyc3QgaXRlbVxuICAgICAgICAgICAgICAgIGNhc2UgTmF2aWdhYmxlS2V5cy5Ib21lOlxuICAgICAgICAgICAgICAgICAgICBuZXh0QWN0aXZlSXRlbSA9IGFjdGl2YXRlRmlyc3RJdGVtKGl0ZW1zLCB0aGlzLmlzQWN0aXZhdGFibGUpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAvLyBBY3RpdmF0ZSB0aGUgbGFzdCBpdGVtXG4gICAgICAgICAgICAgICAgY2FzZSBOYXZpZ2FibGVLZXlzLkVuZDpcbiAgICAgICAgICAgICAgICAgICAgbmV4dEFjdGl2ZUl0ZW0gPSBhY3RpdmF0ZUxhc3RJdGVtKGl0ZW1zLCB0aGlzLmlzQWN0aXZhdGFibGUpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChuZXh0QWN0aXZlSXRlbSAmJlxuICAgICAgICAgICAgICAgIGFjdGl2ZUl0ZW1SZWNvcmQgJiZcbiAgICAgICAgICAgICAgICBhY3RpdmVJdGVtUmVjb3JkLml0ZW0gIT09IG5leHRBY3RpdmVJdGVtKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgYSBuZXcgaXRlbSB3YXMgYWN0aXZhdGVkLCByZW1vdmUgdGhlIHRhYmluZGV4IG9mIHRoZSBwcmV2aW91c1xuICAgICAgICAgICAgICAgIC8vIGFjdGl2YXRlZCBpdGVtLlxuICAgICAgICAgICAgICAgIGFjdGl2ZUl0ZW1SZWNvcmQuaXRlbS50YWJJbmRleCA9IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogTGlzdGVuZXIgdG8gYmUgYm91bmQgdG8gdGhlIGBkZWFjdGl2YXRlLWl0ZW1zYCBpdGVtIGV2ZW50LlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5vbkRlYWN0aXZhdGVJdGVtcyA9ICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5pdGVtcztcbiAgICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykge1xuICAgICAgICAgICAgICAgIHRoaXMuZGVhY3RpdmF0ZUl0ZW0oaXRlbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBMaXN0ZW5lciB0byBiZSBib3VuZCB0byB0aGUgYHJlcXVlc3QtYWN0aXZhdGlvbmAgaXRlbSBldmVudC4uXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLm9uUmVxdWVzdEFjdGl2YXRpb24gPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIHRoaXMub25EZWFjdGl2YXRlSXRlbXMoKTtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcbiAgICAgICAgICAgIHRoaXMuYWN0aXZhdGVJdGVtKHRhcmdldCk7XG4gICAgICAgICAgICB0YXJnZXQuZm9jdXMoKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIExpc3RlbmVyIHRvIGJlIGJvdW5kIHRvIHRoZSBgc2xvdGNoYW5nZWAgZXZlbnQgZm9yIHRoZSBzbG90IHRoYXQgcmVuZGVyc1xuICAgICAgICAgKiB0aGUgaXRlbXMuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLm9uU2xvdGNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5pdGVtcztcbiAgICAgICAgICAgIC8vIFdoZXRoZXIgd2UgaGF2ZSBlbmNvdW50ZXJlZCBhbiBpdGVtIHRoYXQgaGFzIGJlZW4gYWN0aXZhdGVkXG4gICAgICAgICAgICBsZXQgZW5jb3VudGVyZWRBY3RpdmF0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGlzQWN0aXZhdGVkID0gIWl0ZW0uZGlzYWJsZWQgJiYgaXRlbS50YWJJbmRleCA+IC0xO1xuICAgICAgICAgICAgICAgIGlmIChpc0FjdGl2YXRlZCAmJiAhZW5jb3VudGVyZWRBY3RpdmF0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZW5jb3VudGVyZWRBY3RpdmF0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBpdGVtLnRhYkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIERlYWN0aXZhdGUgdGhlIHJlc3QgaW5jbHVkaW5nIGRpc2FibGVkXG4gICAgICAgICAgICAgICAgaXRlbS50YWJJbmRleCA9IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGVuY291bnRlcmVkQWN0aXZhdGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZmlyc3RBY3RpdmF0YWJsZUl0ZW0gPSBnZXRGaXJzdEFjdGl2YXRhYmxlSXRlbShpdGVtcywgdGhpcy5pc0FjdGl2YXRhYmxlKTtcbiAgICAgICAgICAgIGlmICghZmlyc3RBY3RpdmF0YWJsZUl0ZW0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaXJzdEFjdGl2YXRhYmxlSXRlbS50YWJJbmRleCA9IDA7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHsgaXNJdGVtLCBnZXRQb3NzaWJsZUl0ZW1zLCBpc1J0bCwgZGVhY3RpdmF0ZUl0ZW0sIGFjdGl2YXRlSXRlbSwgaXNOYXZpZ2FibGVLZXksIGlzQWN0aXZhdGFibGUsIHdyYXBOYXZpZ2F0aW9uLCB9ID0gY29uZmlnO1xuICAgICAgICB0aGlzLmlzSXRlbSA9IGlzSXRlbTtcbiAgICAgICAgdGhpcy5nZXRQb3NzaWJsZUl0ZW1zID0gZ2V0UG9zc2libGVJdGVtcztcbiAgICAgICAgdGhpcy5pc1J0bCA9IGlzUnRsO1xuICAgICAgICB0aGlzLmRlYWN0aXZhdGVJdGVtID0gZGVhY3RpdmF0ZUl0ZW07XG4gICAgICAgIHRoaXMuYWN0aXZhdGVJdGVtID0gYWN0aXZhdGVJdGVtO1xuICAgICAgICB0aGlzLmlzTmF2aWdhYmxlS2V5ID0gaXNOYXZpZ2FibGVLZXk7XG4gICAgICAgIHRoaXMuaXNBY3RpdmF0YWJsZSA9IGlzQWN0aXZhdGFibGU7XG4gICAgICAgIHRoaXMud3JhcE5hdmlnYXRpb24gPSB3cmFwTmF2aWdhdGlvbiA/PyAoKCkgPT4gdHJ1ZSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoZSBpdGVtcyBiZWluZyBtYW5hZ2VkIGJ5IHRoZSBsaXN0LiBBZGRpdGlvbmFsbHksIGF0dGVtcHRzIHRvIHNlZSBpZiB0aGVcbiAgICAgKiBvYmplY3QgaGFzIGEgc3ViLWl0ZW0gaW4gdGhlIGAuaXRlbWAgcHJvcGVydHkuXG4gICAgICovXG4gICAgZ2V0IGl0ZW1zKCkge1xuICAgICAgICBjb25zdCBtYXliZUl0ZW1zID0gdGhpcy5nZXRQb3NzaWJsZUl0ZW1zKCk7XG4gICAgICAgIGNvbnN0IGl0ZW1zID0gW107XG4gICAgICAgIGZvciAoY29uc3QgaXRlbU9yUGFyZW50IG9mIG1heWJlSXRlbXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGlzSXRlbSA9IHRoaXMuaXNJdGVtKGl0ZW1PclBhcmVudCk7XG4gICAgICAgICAgICAvLyBpZiB0aGUgaXRlbSBpcyBhIGxpc3QgaXRlbSwgYWRkIGl0IHRvIHRoZSBsaXN0IG9mIGl0ZW1zXG4gICAgICAgICAgICBpZiAoaXNJdGVtKSB7XG4gICAgICAgICAgICAgICAgaXRlbXMucHVzaChpdGVtT3JQYXJlbnQpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSWYgdGhlIGl0ZW0gZXhwb3NlcyBhbiBgaXRlbWAgcHJvcGVydHkgY2hlY2sgaWYgaXQgaXMgYSBsaXN0IGl0ZW0uXG4gICAgICAgICAgICBjb25zdCBzdWJJdGVtID0gaXRlbU9yUGFyZW50Lml0ZW07XG4gICAgICAgICAgICBpZiAoc3ViSXRlbSAmJiB0aGlzLmlzSXRlbShzdWJJdGVtKSkge1xuICAgICAgICAgICAgICAgIGl0ZW1zLnB1c2goc3ViSXRlbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGl0ZW1zO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBY3RpdmF0ZXMgdGhlIG5leHQgaXRlbSBpbiB0aGUgbGlzdC4gSWYgYXQgdGhlIGVuZCBvZiB0aGUgbGlzdCwgdGhlIGZpcnN0XG4gICAgICogaXRlbSB3aWxsIGJlIGFjdGl2YXRlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4gVGhlIGFjdGl2YXRlZCBsaXN0IGl0ZW0gb3IgYG51bGxgIGlmIHRoZXJlIGFyZSBubyBpdGVtcy5cbiAgICAgKi9cbiAgICBhY3RpdmF0ZU5leHRJdGVtKCkge1xuICAgICAgICBjb25zdCBpdGVtcyA9IHRoaXMuaXRlbXM7XG4gICAgICAgIGNvbnN0IGFjdGl2ZUl0ZW1SZWNvcmQgPSBnZXRBY3RpdmVJdGVtKGl0ZW1zLCB0aGlzLmlzQWN0aXZhdGFibGUpO1xuICAgICAgICBpZiAoYWN0aXZlSXRlbVJlY29yZCkge1xuICAgICAgICAgICAgYWN0aXZlSXRlbVJlY29yZC5pdGVtLnRhYkluZGV4ID0gLTE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFjdGl2YXRlTmV4dEl0ZW0oaXRlbXMsIGFjdGl2ZUl0ZW1SZWNvcmQsIHRoaXMuaXNBY3RpdmF0YWJsZSwgdGhpcy53cmFwTmF2aWdhdGlvbigpKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQWN0aXZhdGVzIHRoZSBwcmV2aW91cyBpdGVtIGluIHRoZSBsaXN0LiBJZiBhdCB0aGUgc3RhcnQgb2YgdGhlIGxpc3QsIHRoZVxuICAgICAqIGxhc3QgaXRlbSB3aWxsIGJlIGFjdGl2YXRlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4gVGhlIGFjdGl2YXRlZCBsaXN0IGl0ZW0gb3IgYG51bGxgIGlmIHRoZXJlIGFyZSBubyBpdGVtcy5cbiAgICAgKi9cbiAgICBhY3RpdmF0ZVByZXZpb3VzSXRlbSgpIHtcbiAgICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLml0ZW1zO1xuICAgICAgICBjb25zdCBhY3RpdmVJdGVtUmVjb3JkID0gZ2V0QWN0aXZlSXRlbShpdGVtcywgdGhpcy5pc0FjdGl2YXRhYmxlKTtcbiAgICAgICAgaWYgKGFjdGl2ZUl0ZW1SZWNvcmQpIHtcbiAgICAgICAgICAgIGFjdGl2ZUl0ZW1SZWNvcmQuaXRlbS50YWJJbmRleCA9IC0xO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhY3RpdmF0ZVByZXZpb3VzSXRlbShpdGVtcywgYWN0aXZlSXRlbVJlY29yZCwgdGhpcy5pc0FjdGl2YXRhYmxlLCB0aGlzLndyYXBOYXZpZ2F0aW9uKCkpO1xuICAgIH1cbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWxpc3QtY29udHJvbGxlci5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG4vKipcbiAqIEFjdGl2YXRlcyB0aGUgZmlyc3Qgbm9uLWRpc2FibGVkIGl0ZW0gb2YgYSBnaXZlbiBhcnJheSBvZiBpdGVtcy5cbiAqXG4gKiBAcGFyYW0gaXRlbXMge0FycmF5PExpc3RJdGVtPn0gVGhlIGl0ZW1zIGZyb20gd2hpY2ggdG8gYWN0aXZhdGUgdGhlXG4gKiAgICAgZmlyc3QgaXRlbS5cbiAqIEBwYXJhbSBpc0FjdGl2YXRhYmxlIEZ1bmN0aW9uIHRvIGRldGVybWluZSBpZiBhbiBpdGVtIGNhbiBiZSAgYWN0aXZhdGVkLlxuICogICAgIERlZmF1bHRzIHRvIG5vbi1kaXNhYmxlZCBpdGVtcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFjdGl2YXRlRmlyc3RJdGVtKGl0ZW1zLCBpc0FjdGl2YXRhYmxlID0gKGlzSXRlbU5vdERpc2FibGVkKSkge1xuICAgIC8vIE5PVEU6IFRoZXNlIHNlbGVjdG9yIGZ1bmN0aW9ucyBhcmUgc3RhdGljIGFuZCBub3Qgb24gdGhlIGluc3RhbmNlIHN1Y2hcbiAgICAvLyB0aGF0IG11bHRpcGxlIG9wZXJhdGlvbnMgY2FuIGJlIGNoYWluZWQgYW5kIHdlIGRvIG5vdCBoYXZlIHRvIHJlLXF1ZXJ5XG4gICAgLy8gdGhlIERPTVxuICAgIGNvbnN0IGZpcnN0SXRlbSA9IGdldEZpcnN0QWN0aXZhdGFibGVJdGVtKGl0ZW1zLCBpc0FjdGl2YXRhYmxlKTtcbiAgICBpZiAoZmlyc3RJdGVtKSB7XG4gICAgICAgIGZpcnN0SXRlbS50YWJJbmRleCA9IDA7XG4gICAgICAgIGZpcnN0SXRlbS5mb2N1cygpO1xuICAgIH1cbiAgICByZXR1cm4gZmlyc3RJdGVtO1xufVxuLyoqXG4gKiBBY3RpdmF0ZXMgdGhlIGxhc3Qgbm9uLWRpc2FibGVkIGl0ZW0gb2YgYSBnaXZlbiBhcnJheSBvZiBpdGVtcy5cbiAqXG4gKiBAcGFyYW0gaXRlbXMge0FycmF5PExpc3RJdGVtPn0gVGhlIGl0ZW1zIGZyb20gd2hpY2ggdG8gYWN0aXZhdGUgdGhlXG4gKiAgICAgbGFzdCBpdGVtLlxuICogQHBhcmFtIGlzQWN0aXZhdGFibGUgRnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGlmIGFuIGl0ZW0gY2FuIGJlICBhY3RpdmF0ZWQuXG4gKiAgICAgRGVmYXVsdHMgdG8gbm9uLWRpc2FibGVkIGl0ZW1zLlxuICogQG5vY29sbGFwc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFjdGl2YXRlTGFzdEl0ZW0oaXRlbXMsIGlzQWN0aXZhdGFibGUgPSAoaXNJdGVtTm90RGlzYWJsZWQpKSB7XG4gICAgY29uc3QgbGFzdEl0ZW0gPSBnZXRMYXN0QWN0aXZhdGFibGVJdGVtKGl0ZW1zLCBpc0FjdGl2YXRhYmxlKTtcbiAgICBpZiAobGFzdEl0ZW0pIHtcbiAgICAgICAgbGFzdEl0ZW0udGFiSW5kZXggPSAwO1xuICAgICAgICBsYXN0SXRlbS5mb2N1cygpO1xuICAgIH1cbiAgICByZXR1cm4gbGFzdEl0ZW07XG59XG4vKipcbiAqIERlYWN0aXZhdGVzIHRoZSBjdXJyZW50bHkgYWN0aXZlIGl0ZW0gb2YgYSBnaXZlbiBhcnJheSBvZiBpdGVtcy5cbiAqXG4gKiBAcGFyYW0gaXRlbXMge0FycmF5PExpc3RJdGVtPn0gVGhlIGl0ZW1zIGZyb20gd2hpY2ggdG8gZGVhY3RpdmF0ZSB0aGVcbiAqICAgICBhY3RpdmUgaXRlbS5cbiAqIEBwYXJhbSBpc0FjdGl2YXRhYmxlIEZ1bmN0aW9uIHRvIGRldGVybWluZSBpZiBhbiBpdGVtIGNhbiBiZSAgYWN0aXZhdGVkLlxuICogICAgIERlZmF1bHRzIHRvIG5vbi1kaXNhYmxlZCBpdGVtcy5cbiAqIEByZXR1cm4gQSByZWNvcmQgb2YgdGhlIGRlbGVzZWxjdGVkIGFjdGl2YXRlZCBpdGVtIGluY2x1ZGluZyB0aGUgaXRlbSBhbmRcbiAqICAgICB0aGUgaW5kZXggb2YgdGhlIGl0ZW0gb3IgYG51bGxgIGlmIG5vbmUgYXJlIGRlYWN0aXZhdGVkLlxuICogQG5vY29sbGFwc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlYWN0aXZhdGVBY3RpdmVJdGVtKGl0ZW1zLCBpc0FjdGl2YXRhYmxlID0gKGlzSXRlbU5vdERpc2FibGVkKSkge1xuICAgIGNvbnN0IGFjdGl2ZUl0ZW0gPSBnZXRBY3RpdmVJdGVtKGl0ZW1zLCBpc0FjdGl2YXRhYmxlKTtcbiAgICBpZiAoYWN0aXZlSXRlbSkge1xuICAgICAgICBhY3RpdmVJdGVtLml0ZW0udGFiSW5kZXggPSAtMTtcbiAgICB9XG4gICAgcmV0dXJuIGFjdGl2ZUl0ZW07XG59XG4vKipcbiAqIFJldHJpZXZlcyB0aGUgZmlyc3QgYWN0aXZhdGVkIGl0ZW0gb2YgYSBnaXZlbiBhcnJheSBvZiBpdGVtcy5cbiAqXG4gKiBAcGFyYW0gaXRlbXMge0FycmF5PExpc3RJdGVtPn0gVGhlIGl0ZW1zIHRvIHNlYXJjaC5cbiAqIEBwYXJhbSBpc0FjdGl2YXRhYmxlIEZ1bmN0aW9uIHRvIGRldGVybWluZSBpZiBhbiBpdGVtIGNhbiBiZSAgYWN0aXZhdGVkLlxuICogICAgIERlZmF1bHRzIHRvIG5vbi1kaXNhYmxlZCBpdGVtcy5cbiAqIEByZXR1cm4gQSByZWNvcmQgb2YgdGhlIGZpcnN0IGFjdGl2YXRlZCBpdGVtIGluY2x1ZGluZyB0aGUgaXRlbSBhbmQgdGhlXG4gKiAgICAgaW5kZXggb2YgdGhlIGl0ZW0gb3IgYG51bGxgIGlmIG5vbmUgYXJlIGFjdGl2YXRlZC5cbiAqIEBub2NvbGxhcHNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBY3RpdmVJdGVtKGl0ZW1zLCBpc0FjdGl2YXRhYmxlID0gKGlzSXRlbU5vdERpc2FibGVkKSkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaXRlbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgaXRlbSA9IGl0ZW1zW2ldO1xuICAgICAgICBpZiAoaXRlbS50YWJJbmRleCA9PT0gMCAmJiBpc0FjdGl2YXRhYmxlKGl0ZW0pKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGl0ZW0sXG4gICAgICAgICAgICAgICAgaW5kZXg6IGksXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuLyoqXG4gKiBSZXRyaWV2ZXMgdGhlIGZpcnN0IG5vbi1kaXNhYmxlZCBpdGVtIG9mIGEgZ2l2ZW4gYXJyYXkgb2YgaXRlbXMuIFRoaXNcbiAqIHRoZSBmaXJzdCBpdGVtIHRoYXQgaXMgbm90IGRpc2FibGVkLlxuICpcbiAqIEBwYXJhbSBpdGVtcyB7QXJyYXk8TGlzdEl0ZW0+fSBUaGUgaXRlbXMgdG8gc2VhcmNoLlxuICogQHBhcmFtIGlzQWN0aXZhdGFibGUgRnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGlmIGFuIGl0ZW0gY2FuIGJlICBhY3RpdmF0ZWQuXG4gKiAgICAgRGVmYXVsdHMgdG8gbm9uLWRpc2FibGVkIGl0ZW1zLlxuICogQHJldHVybiBUaGUgZmlyc3QgYWN0aXZhdGFibGUgaXRlbSBvciBgbnVsbGAgaWYgbm9uZSBhcmUgYWN0aXZhdGFibGUuXG4gKiBAbm9jb2xsYXBzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0Rmlyc3RBY3RpdmF0YWJsZUl0ZW0oaXRlbXMsIGlzQWN0aXZhdGFibGUgPSAoaXNJdGVtTm90RGlzYWJsZWQpKSB7XG4gICAgZm9yIChjb25zdCBpdGVtIG9mIGl0ZW1zKSB7XG4gICAgICAgIGlmIChpc0FjdGl2YXRhYmxlKGl0ZW0pKSB7XG4gICAgICAgICAgICByZXR1cm4gaXRlbTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbi8qKlxuICogUmV0cmlldmVzIHRoZSBsYXN0IG5vbi1kaXNhYmxlZCBpdGVtIG9mIGEgZ2l2ZW4gYXJyYXkgb2YgaXRlbXMuXG4gKlxuICogQHBhcmFtIGl0ZW1zIHtBcnJheTxMaXN0SXRlbT59IFRoZSBpdGVtcyB0byBzZWFyY2guXG4gKiBAcGFyYW0gaXNBY3RpdmF0YWJsZSBGdW5jdGlvbiB0byBkZXRlcm1pbmUgaWYgYW4gaXRlbSBjYW4gYmUgIGFjdGl2YXRlZC5cbiAqICAgICBEZWZhdWx0cyB0byBub24tZGlzYWJsZWQgaXRlbXMuXG4gKiBAcmV0dXJuIFRoZSBsYXN0IGFjdGl2YXRhYmxlIGl0ZW0gb3IgYG51bGxgIGlmIG5vbmUgYXJlIGFjdGl2YXRhYmxlLlxuICogQG5vY29sbGFwc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldExhc3RBY3RpdmF0YWJsZUl0ZW0oaXRlbXMsIGlzQWN0aXZhdGFibGUgPSAoaXNJdGVtTm90RGlzYWJsZWQpKSB7XG4gICAgZm9yIChsZXQgaSA9IGl0ZW1zLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGNvbnN0IGl0ZW0gPSBpdGVtc1tpXTtcbiAgICAgICAgaWYgKGlzQWN0aXZhdGFibGUoaXRlbSkpIHtcbiAgICAgICAgICAgIHJldHVybiBpdGVtO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuLyoqXG4gKiBSZXRyaWV2ZXMgdGhlIG5leHQgbm9uLWRpc2FibGVkIGl0ZW0gb2YgYSBnaXZlbiBhcnJheSBvZiBpdGVtcy5cbiAqXG4gKiBAcGFyYW0gaXRlbXMge0FycmF5PExpc3RJdGVtPn0gVGhlIGl0ZW1zIHRvIHNlYXJjaC5cbiAqIEBwYXJhbSBpbmRleCB7e2luZGV4OiBudW1iZXJ9fSBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gKiBAcGFyYW0gaXNBY3RpdmF0YWJsZSBGdW5jdGlvbiB0byBkZXRlcm1pbmUgaWYgYW4gaXRlbSBjYW4gYmUgIGFjdGl2YXRlZC5cbiAqICAgICBEZWZhdWx0cyB0byBub24tZGlzYWJsZWQgaXRlbXMuXG4gKiBAcGFyYW0gd3JhcCBJZiB0cnVlLCB0aGVuIHRoZSBuZXh0IGl0ZW0gYXQgdGhlIGVuZCBvZiB0aGUgbGlzdCBpcyB0aGUgZmlyc3RcbiAqICAgICBpdGVtLiBEZWZhdWx0cyB0byB0cnVlLlxuICogQHJldHVybiBUaGUgbmV4dCBhY3RpdmF0YWJsZSBpdGVtIG9yIGBudWxsYCBpZiBub25lIGFyZSBhY3RpdmF0YWJsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE5leHRJdGVtKGl0ZW1zLCBpbmRleCwgaXNBY3RpdmF0YWJsZSA9IChpc0l0ZW1Ob3REaXNhYmxlZCksIHdyYXAgPSB0cnVlKSB7XG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCBpdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBuZXh0SW5kZXggPSAoaSArIGluZGV4KSAlIGl0ZW1zLmxlbmd0aDtcbiAgICAgICAgaWYgKG5leHRJbmRleCA8IGluZGV4ICYmICF3cmFwKSB7XG4gICAgICAgICAgICAvLyBSZXR1cm4gaWYgdGhlIGluZGV4IGxvb3BzIGJhY2sgdG8gdGhlIGJlZ2lubmluZyBhbmQgbm90IHdyYXBwaW5nLlxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaXRlbSA9IGl0ZW1zW25leHRJbmRleF07XG4gICAgICAgIGlmIChpc0FjdGl2YXRhYmxlKGl0ZW0pKSB7XG4gICAgICAgICAgICByZXR1cm4gaXRlbTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaXRlbXNbaW5kZXhdID8gaXRlbXNbaW5kZXhdIDogbnVsbDtcbn1cbi8qKlxuICogUmV0cmlldmVzIHRoZSBwcmV2aW91cyBub24tZGlzYWJsZWQgaXRlbSBvZiBhIGdpdmVuIGFycmF5IG9mIGl0ZW1zLlxuICpcbiAqIEBwYXJhbSBpdGVtcyB7QXJyYXk8TGlzdEl0ZW0+fSBUaGUgaXRlbXMgdG8gc2VhcmNoLlxuICogQHBhcmFtIGluZGV4IHt7aW5kZXg6IG51bWJlcn19IFRoZSBpbmRleCB0byBzZWFyY2ggZnJvbS5cbiAqIEBwYXJhbSBpc0FjdGl2YXRhYmxlIEZ1bmN0aW9uIHRvIGRldGVybWluZSBpZiBhbiBpdGVtIGNhbiBiZSAgYWN0aXZhdGVkLlxuICogICAgIERlZmF1bHRzIHRvIG5vbi1kaXNhYmxlZCBpdGVtcy5cbiAqIEBwYXJhbSB3cmFwIElmIHRydWUsIHRoZW4gdGhlIHByZXZpb3VzIGl0ZW0gYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgbGlzdCBpc1xuICogICAgIHRoZSBsYXN0IGl0ZW0uIERlZmF1bHRzIHRvIHRydWUuXG4gKiBAcmV0dXJuIFRoZSBwcmV2aW91cyBhY3RpdmF0YWJsZSBpdGVtIG9yIGBudWxsYCBpZiBub25lIGFyZSBhY3RpdmF0YWJsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFByZXZJdGVtKGl0ZW1zLCBpbmRleCwgaXNBY3RpdmF0YWJsZSA9IChpc0l0ZW1Ob3REaXNhYmxlZCksIHdyYXAgPSB0cnVlKSB7XG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCBpdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBwcmV2SW5kZXggPSAoaW5kZXggLSBpICsgaXRlbXMubGVuZ3RoKSAlIGl0ZW1zLmxlbmd0aDtcbiAgICAgICAgaWYgKHByZXZJbmRleCA+IGluZGV4ICYmICF3cmFwKSB7XG4gICAgICAgICAgICAvLyBSZXR1cm4gaWYgdGhlIGluZGV4IGxvb3BzIGJhY2sgdG8gdGhlIGVuZCBhbmQgbm90IHdyYXBwaW5nLlxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaXRlbSA9IGl0ZW1zW3ByZXZJbmRleF07XG4gICAgICAgIGlmIChpc0FjdGl2YXRhYmxlKGl0ZW0pKSB7XG4gICAgICAgICAgICByZXR1cm4gaXRlbTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaXRlbXNbaW5kZXhdID8gaXRlbXNbaW5kZXhdIDogbnVsbDtcbn1cbi8qKlxuICogQWN0aXZhdGVzIHRoZSBuZXh0IGl0ZW0gYW5kIGZvY3VzZXMgaXQuIElmIG5vdGhpbmcgaXMgY3VycmVudGx5IGFjdGl2YXRlZCxcbiAqIGFjdGl2YXRlcyB0aGUgZmlyc3QgaXRlbS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFjdGl2YXRlTmV4dEl0ZW0oaXRlbXMsIGFjdGl2ZUl0ZW1SZWNvcmQsIGlzQWN0aXZhdGFibGUgPSAoaXNJdGVtTm90RGlzYWJsZWQpLCB3cmFwID0gdHJ1ZSkge1xuICAgIGlmIChhY3RpdmVJdGVtUmVjb3JkKSB7XG4gICAgICAgIGNvbnN0IG5leHQgPSBnZXROZXh0SXRlbShpdGVtcywgYWN0aXZlSXRlbVJlY29yZC5pbmRleCwgaXNBY3RpdmF0YWJsZSwgd3JhcCk7XG4gICAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgICAgICBuZXh0LnRhYkluZGV4ID0gMDtcbiAgICAgICAgICAgIG5leHQuZm9jdXMoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV4dDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBhY3RpdmF0ZUZpcnN0SXRlbShpdGVtcywgaXNBY3RpdmF0YWJsZSk7XG4gICAgfVxufVxuLyoqXG4gKiBBY3RpdmF0ZXMgdGhlIHByZXZpb3VzIGl0ZW0gYW5kIGZvY3VzZXMgaXQuIElmIG5vdGhpbmcgaXMgY3VycmVudGx5XG4gKiBhY3RpdmF0ZWQsIGFjdGl2YXRlcyB0aGUgbGFzdCBpdGVtLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYWN0aXZhdGVQcmV2aW91c0l0ZW0oaXRlbXMsIGFjdGl2ZUl0ZW1SZWNvcmQsIGlzQWN0aXZhdGFibGUgPSAoaXNJdGVtTm90RGlzYWJsZWQpLCB3cmFwID0gdHJ1ZSkge1xuICAgIGlmIChhY3RpdmVJdGVtUmVjb3JkKSB7XG4gICAgICAgIGNvbnN0IHByZXYgPSBnZXRQcmV2SXRlbShpdGVtcywgYWN0aXZlSXRlbVJlY29yZC5pbmRleCwgaXNBY3RpdmF0YWJsZSwgd3JhcCk7XG4gICAgICAgIGlmIChwcmV2KSB7XG4gICAgICAgICAgICBwcmV2LnRhYkluZGV4ID0gMDtcbiAgICAgICAgICAgIHByZXYuZm9jdXMoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcHJldjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBhY3RpdmF0ZUxhc3RJdGVtKGl0ZW1zLCBpc0FjdGl2YXRhYmxlKTtcbiAgICB9XG59XG4vKipcbiAqIENyZWF0ZXMgYW4gZXZlbnQgdGhhdCByZXF1ZXN0cyB0aGUgcGFyZW50IG1kLWxpc3QgdG8gZGVhY3RpdmF0ZSBhbGwgb3RoZXJcbiAqIGl0ZW1zLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRGVhY3RpdmF0ZUl0ZW1zRXZlbnQoKSB7XG4gICAgcmV0dXJuIG5ldyBFdmVudCgnZGVhY3RpdmF0ZS1pdGVtcycsIHsgYnViYmxlczogdHJ1ZSwgY29tcG9zZWQ6IHRydWUgfSk7XG59XG4vKipcbiAqIENyZWF0ZXMgYW4gZXZlbnQgdGhhdCByZXF1ZXN0cyB0aGUgbWVudSB0byBzZXQgYHRhYmluZGV4PTBgIG9uIHRoZSBpdGVtIGFuZFxuICogZm9jdXMgaXQuIFdlIHVzZSB0aGlzIHBhdHRlcm4gYmVjYXVzZSBMaXN0IGtlZXBzIHRyYWNrIG9mIHdoYXQgZWxlbWVudCBpc1xuICogYWN0aXZlIGluIHRoZSBMaXN0IGJ5IG1haW50YWluaW5nIHRhYmluZGV4LiBXZSBkbyBub3Qgd2FudCBsaXN0IGl0ZW1zXG4gKiB0byBzZXQgdGFiaW5kZXggb24gdGhlbXNlbHZlcyBvciBmb2N1cyB0aGVtc2VsdmVzIHNvIHRoYXQgd2UgY2FuIG9yZ2FuaXplIGFsbFxuICogdGhhdCBsb2dpYyBpbiB0aGUgcGFyZW50IExpc3QgYW5kIE1lbnVzLCBhbmQgbGlzdCBpdGVtIHN0YXlzIGFzIGR1bWIgYXNcbiAqIHBvc3NpYmxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVxdWVzdEFjdGl2YXRpb25FdmVudCgpIHtcbiAgICByZXR1cm4gbmV3IEV2ZW50KCdyZXF1ZXN0LWFjdGl2YXRpb24nLCB7IGJ1YmJsZXM6IHRydWUsIGNvbXBvc2VkOiB0cnVlIH0pO1xufVxuLyoqXG4gKiBUaGUgZGVmYXVsdCBgaXNBY3RpdmF0YWJsZWAgZnVuY3Rpb24sIHdoaWNoIGNoZWNrcyBpZiBhbiBpdGVtIGlzIG5vdFxuICogZGlzYWJsZWQuXG4gKlxuICogQHBhcmFtIGl0ZW0gVGhlIGl0ZW0gdG8gY2hlY2suXG4gKiBAcmV0dXJuIHRydWUgaWYgYGl0ZW0uZGlzYWJsZWRgIGlzIGBmYWxzZS5cbiAqL1xuZnVuY3Rpb24gaXNJdGVtTm90RGlzYWJsZWQoaXRlbSkge1xuICAgIHJldHVybiAhaXRlbS5kaXNhYmxlZDtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWxpc3QtbmF2aWdhdGlvbi1oZWxwZXJzLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDI0IEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbi8vIEdlbmVyYXRlZCBzdHlsZXNoZWV0IGZvciAuL2xpc3QvaW50ZXJuYWwvbGlzdC1zdHlsZXMuY3NzLlxuaW1wb3J0IHsgY3NzIH0gZnJvbSAnbGl0JztcbmV4cG9ydCBjb25zdCBzdHlsZXMgPSBjc3MgYDpob3N0e2JhY2tncm91bmQ6dmFyKC0tbWQtbGlzdC1jb250YWluZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1zdXJmYWNlLCAjZmVmN2ZmKSk7Y29sb3I6dW5zZXQ7ZGlzcGxheTpmbGV4O2ZsZXgtZGlyZWN0aW9uOmNvbHVtbjtvdXRsaW5lOm5vbmU7cGFkZGluZzo4cHggMDtwb3NpdGlvbjpyZWxhdGl2ZX1cbmA7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1saXN0LXN0eWxlcy5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBfX2RlY29yYXRlIH0gZnJvbSBcInRzbGliXCI7XG5pbXBvcnQgeyBodG1sLCBpc1NlcnZlciwgTGl0RWxlbWVudCB9IGZyb20gJ2xpdCc7XG5pbXBvcnQgeyBxdWVyeUFzc2lnbmVkRWxlbWVudHMgfSBmcm9tICdsaXQvZGVjb3JhdG9ycy5qcyc7XG5pbXBvcnQgeyBMaXN0Q29udHJvbGxlciwgTmF2aWdhYmxlS2V5cyB9IGZyb20gJy4vbGlzdC1jb250cm9sbGVyLmpzJztcbmNvbnN0IE5BVklHQUJMRV9LRVlfU0VUID0gbmV3IFNldChPYmplY3QudmFsdWVzKE5hdmlnYWJsZUtleXMpKTtcbi8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTplbmZvcmNlLWNvbW1lbnRzLW9uLWV4cG9ydGVkLXN5bWJvbHNcbmV4cG9ydCBjbGFzcyBMaXN0IGV4dGVuZHMgTGl0RWxlbWVudCB7XG4gICAgLyoqIEBleHBvcnQgKi9cbiAgICBnZXQgaXRlbXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RDb250cm9sbGVyLml0ZW1zO1xuICAgIH1cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5saXN0Q29udHJvbGxlciA9IG5ldyBMaXN0Q29udHJvbGxlcih7XG4gICAgICAgICAgICBpc0l0ZW06IChpdGVtKSA9PiBpdGVtLmhhc0F0dHJpYnV0ZSgnbWQtbGlzdC1pdGVtJyksXG4gICAgICAgICAgICBnZXRQb3NzaWJsZUl0ZW1zOiAoKSA9PiB0aGlzLnNsb3RJdGVtcyxcbiAgICAgICAgICAgIGlzUnRsOiAoKSA9PiBnZXRDb21wdXRlZFN0eWxlKHRoaXMpLmRpcmVjdGlvbiA9PT0gJ3J0bCcsXG4gICAgICAgICAgICBkZWFjdGl2YXRlSXRlbTogKGl0ZW0pID0+IHtcbiAgICAgICAgICAgICAgICBpdGVtLnRhYkluZGV4ID0gLTE7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYWN0aXZhdGVJdGVtOiAoaXRlbSkgPT4ge1xuICAgICAgICAgICAgICAgIGl0ZW0udGFiSW5kZXggPSAwO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzTmF2aWdhYmxlS2V5OiAoa2V5KSA9PiBOQVZJR0FCTEVfS0VZX1NFVC5oYXMoa2V5KSxcbiAgICAgICAgICAgIGlzQWN0aXZhdGFibGU6IChpdGVtKSA9PiAhaXRlbS5kaXNhYmxlZCAmJiBpdGVtLnR5cGUgIT09ICd0ZXh0JyxcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuaW50ZXJuYWxzID0gXG4gICAgICAgIC8vIENhc3QgbmVlZGVkIGZvciBjbG9zdXJlXG4gICAgICAgIHRoaXMuYXR0YWNoSW50ZXJuYWxzKCk7XG4gICAgICAgIGlmICghaXNTZXJ2ZXIpIHtcbiAgICAgICAgICAgIHRoaXMuaW50ZXJuYWxzLnJvbGUgPSAnbGlzdCc7XG4gICAgICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLmxpc3RDb250cm9sbGVyLmhhbmRsZUtleWRvd24pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYFxuICAgICAgPHNsb3RcbiAgICAgICAgQGRlYWN0aXZhdGUtaXRlbXM9JHt0aGlzLmxpc3RDb250cm9sbGVyLm9uRGVhY3RpdmF0ZUl0ZW1zfVxuICAgICAgICBAcmVxdWVzdC1hY3RpdmF0aW9uPSR7dGhpcy5saXN0Q29udHJvbGxlci5vblJlcXVlc3RBY3RpdmF0aW9ufVxuICAgICAgICBAc2xvdGNoYW5nZT0ke3RoaXMubGlzdENvbnRyb2xsZXIub25TbG90Y2hhbmdlfT5cbiAgICAgIDwvc2xvdD5cbiAgICBgO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBY3RpdmF0ZXMgdGhlIG5leHQgaXRlbSBpbiB0aGUgbGlzdC4gSWYgYXQgdGhlIGVuZCBvZiB0aGUgbGlzdCwgdGhlIGZpcnN0XG4gICAgICogaXRlbSB3aWxsIGJlIGFjdGl2YXRlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4gVGhlIGFjdGl2YXRlZCBsaXN0IGl0ZW0gb3IgYG51bGxgIGlmIHRoZXJlIGFyZSBubyBpdGVtcy5cbiAgICAgKi9cbiAgICBhY3RpdmF0ZU5leHRJdGVtKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5saXN0Q29udHJvbGxlci5hY3RpdmF0ZU5leHRJdGVtKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFjdGl2YXRlcyB0aGUgcHJldmlvdXMgaXRlbSBpbiB0aGUgbGlzdC4gSWYgYXQgdGhlIHN0YXJ0IG9mIHRoZSBsaXN0LCB0aGVcbiAgICAgKiBsYXN0IGl0ZW0gd2lsbCBiZSBhY3RpdmF0ZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIFRoZSBhY3RpdmF0ZWQgbGlzdCBpdGVtIG9yIGBudWxsYCBpZiB0aGVyZSBhcmUgbm8gaXRlbXMuXG4gICAgICovXG4gICAgYWN0aXZhdGVQcmV2aW91c0l0ZW0oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RDb250cm9sbGVyLmFjdGl2YXRlUHJldmlvdXNJdGVtKCk7XG4gICAgfVxufVxuX19kZWNvcmF0ZShbXG4gICAgcXVlcnlBc3NpZ25lZEVsZW1lbnRzKHsgZmxhdHRlbjogdHJ1ZSB9KVxuXSwgTGlzdC5wcm90b3R5cGUsIFwic2xvdEl0ZW1zXCIsIHZvaWQgMCk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1saXN0LmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDI0IEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbi8vIEdlbmVyYXRlZCBzdHlsZXNoZWV0IGZvciAuL2xpc3QvaW50ZXJuYWwvbGlzdGl0ZW0vbGlzdC1pdGVtLXN0eWxlcy5jc3MuXG5pbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuZXhwb3J0IGNvbnN0IHN0eWxlcyA9IGNzcyBgOmhvc3R7ZGlzcGxheTpmbGV4Oy13ZWJraXQtdGFwLWhpZ2hsaWdodC1jb2xvcjpyZ2JhKDAsMCwwLDApOy0tbWQtcmlwcGxlLWhvdmVyLWNvbG9yOiB2YXIoLS1tZC1saXN0LWl0ZW0taG92ZXItc3RhdGUtbGF5ZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1tZC1yaXBwbGUtaG92ZXItb3BhY2l0eTogdmFyKC0tbWQtbGlzdC1pdGVtLWhvdmVyLXN0YXRlLWxheWVyLW9wYWNpdHksIDAuMDgpOy0tbWQtcmlwcGxlLXByZXNzZWQtY29sb3I6IHZhcigtLW1kLWxpc3QtaXRlbS1wcmVzc2VkLXN0YXRlLWxheWVyLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tbWQtcmlwcGxlLXByZXNzZWQtb3BhY2l0eTogdmFyKC0tbWQtbGlzdC1pdGVtLXByZXNzZWQtc3RhdGUtbGF5ZXItb3BhY2l0eSwgMC4xMil9Omhvc3QoOmlzKFt0eXBlPWJ1dHRvbl06bm90KFtkaXNhYmxlZF0pLFt0eXBlPWxpbmtdKSl7Y3Vyc29yOnBvaW50ZXJ9bWQtZm9jdXMtcmluZ3t6LWluZGV4OjE7LS1tZC1mb2N1cy1yaW5nLXNoYXBlOiA4cHh9YSxidXR0b24sbGl7YmFja2dyb3VuZDpub25lO2JvcmRlcjpub25lO2N1cnNvcjppbmhlcml0O3BhZGRpbmc6MDttYXJnaW46MDt0ZXh0LWFsaWduOnVuc2V0O3RleHQtZGVjb3JhdGlvbjpub25lfS5saXN0LWl0ZW17Ym9yZGVyLXJhZGl1czppbmhlcml0O2Rpc3BsYXk6ZmxleDtmbGV4OjE7bWF4LXdpZHRoOmluaGVyaXQ7bWluLXdpZHRoOmluaGVyaXQ7b3V0bGluZTpub25lOy13ZWJraXQtdGFwLWhpZ2hsaWdodC1jb2xvcjpyZ2JhKDAsMCwwLDApO3dpZHRoOjEwMCV9Lmxpc3QtaXRlbS5pbnRlcmFjdGl2ZXtjdXJzb3I6cG9pbnRlcn0ubGlzdC1pdGVtLmRpc2FibGVke29wYWNpdHk6dmFyKC0tbWQtbGlzdC1pdGVtLWRpc2FibGVkLW9wYWNpdHksIDAuMyk7cG9pbnRlci1ldmVudHM6bm9uZX1bc2xvdD1jb250YWluZXJde3BvaW50ZXItZXZlbnRzOm5vbmV9bWQtcmlwcGxle2JvcmRlci1yYWRpdXM6aW5oZXJpdH1tZC1pdGVte2JvcmRlci1yYWRpdXM6aW5oZXJpdDtmbGV4OjE7aGVpZ2h0OjEwMCU7Y29sb3I6dmFyKC0tbWQtbGlzdC1pdGVtLWxhYmVsLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7Zm9udC1mYW1pbHk6dmFyKC0tbWQtbGlzdC1pdGVtLWxhYmVsLXRleHQtZm9udCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LWxhcmdlLWZvbnQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS1wbGFpbiwgUm9ib3RvKSkpO2ZvbnQtc2l6ZTp2YXIoLS1tZC1saXN0LWl0ZW0tbGFiZWwtdGV4dC1zaXplLCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbGFyZ2Utc2l6ZSwgMXJlbSkpO2xpbmUtaGVpZ2h0OnZhcigtLW1kLWxpc3QtaXRlbS1sYWJlbC10ZXh0LWxpbmUtaGVpZ2h0LCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbGFyZ2UtbGluZS1oZWlnaHQsIDEuNXJlbSkpO2ZvbnQtd2VpZ2h0OnZhcigtLW1kLWxpc3QtaXRlbS1sYWJlbC10ZXh0LXdlaWdodCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LWxhcmdlLXdlaWdodCwgdmFyKC0tbWQtcmVmLXR5cGVmYWNlLXdlaWdodC1yZWd1bGFyLCA0MDApKSk7bWluLWhlaWdodDp2YXIoLS1tZC1saXN0LWl0ZW0tb25lLWxpbmUtY29udGFpbmVyLWhlaWdodCwgNTZweCk7cGFkZGluZy10b3A6dmFyKC0tbWQtbGlzdC1pdGVtLXRvcC1zcGFjZSwgMTJweCk7cGFkZGluZy1ib3R0b206dmFyKC0tbWQtbGlzdC1pdGVtLWJvdHRvbS1zcGFjZSwgMTJweCk7cGFkZGluZy1pbmxpbmUtc3RhcnQ6dmFyKC0tbWQtbGlzdC1pdGVtLWxlYWRpbmctc3BhY2UsIDE2cHgpO3BhZGRpbmctaW5saW5lLWVuZDp2YXIoLS1tZC1saXN0LWl0ZW0tdHJhaWxpbmctc3BhY2UsIDE2cHgpfW1kLWl0ZW1bbXVsdGlsaW5lXXttaW4taGVpZ2h0OnZhcigtLW1kLWxpc3QtaXRlbS10d28tbGluZS1jb250YWluZXItaGVpZ2h0LCA3MnB4KX1bc2xvdD1zdXBwb3J0aW5nLXRleHRde2NvbG9yOnZhcigtLW1kLWxpc3QtaXRlbS1zdXBwb3J0aW5nLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTtmb250LWZhbWlseTp2YXIoLS1tZC1saXN0LWl0ZW0tc3VwcG9ydGluZy10ZXh0LWZvbnQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1tZWRpdW0tZm9udCwgdmFyKC0tbWQtcmVmLXR5cGVmYWNlLXBsYWluLCBSb2JvdG8pKSk7Zm9udC1zaXplOnZhcigtLW1kLWxpc3QtaXRlbS1zdXBwb3J0aW5nLXRleHQtc2l6ZSwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LW1lZGl1bS1zaXplLCAwLjg3NXJlbSkpO2xpbmUtaGVpZ2h0OnZhcigtLW1kLWxpc3QtaXRlbS1zdXBwb3J0aW5nLXRleHQtbGluZS1oZWlnaHQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1tZWRpdW0tbGluZS1oZWlnaHQsIDEuMjVyZW0pKTtmb250LXdlaWdodDp2YXIoLS1tZC1saXN0LWl0ZW0tc3VwcG9ydGluZy10ZXh0LXdlaWdodCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LW1lZGl1bS13ZWlnaHQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS13ZWlnaHQtcmVndWxhciwgNDAwKSkpfVtzbG90PXRyYWlsaW5nLXN1cHBvcnRpbmctdGV4dF17Y29sb3I6dmFyKC0tbWQtbGlzdC1pdGVtLXRyYWlsaW5nLXN1cHBvcnRpbmctdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpO2ZvbnQtZmFtaWx5OnZhcigtLW1kLWxpc3QtaXRlbS10cmFpbGluZy1zdXBwb3J0aW5nLXRleHQtZm9udCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1sYWJlbC1zbWFsbC1mb250LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2UtcGxhaW4sIFJvYm90bykpKTtmb250LXNpemU6dmFyKC0tbWQtbGlzdC1pdGVtLXRyYWlsaW5nLXN1cHBvcnRpbmctdGV4dC1zaXplLCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWxhYmVsLXNtYWxsLXNpemUsIDAuNjg3NXJlbSkpO2xpbmUtaGVpZ2h0OnZhcigtLW1kLWxpc3QtaXRlbS10cmFpbGluZy1zdXBwb3J0aW5nLXRleHQtbGluZS1oZWlnaHQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtbGFiZWwtc21hbGwtbGluZS1oZWlnaHQsIDFyZW0pKTtmb250LXdlaWdodDp2YXIoLS1tZC1saXN0LWl0ZW0tdHJhaWxpbmctc3VwcG9ydGluZy10ZXh0LXdlaWdodCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1sYWJlbC1zbWFsbC13ZWlnaHQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS13ZWlnaHQtbWVkaXVtLCA1MDApKSl9OmlzKFtzbG90PXN0YXJ0XSxbc2xvdD1lbmRdKTo6c2xvdHRlZCgqKXtmaWxsOmN1cnJlbnRDb2xvcn1bc2xvdD1zdGFydF17Y29sb3I6dmFyKC0tbWQtbGlzdC1pdGVtLWxlYWRpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpfVtzbG90PWVuZF17Y29sb3I6dmFyKC0tbWQtbGlzdC1pdGVtLXRyYWlsaW5nLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKX1AbWVkaWEoZm9yY2VkLWNvbG9yczogYWN0aXZlKXsuZGlzYWJsZWQgc2xvdHtjb2xvcjpHcmF5VGV4dH0ubGlzdC1pdGVtLmRpc2FibGVke2NvbG9yOkdyYXlUZXh0O29wYWNpdHk6MX19XG5gO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9bGlzdC1pdGVtLXN0eWxlcy5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMiBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBfX2RlY29yYXRlIH0gZnJvbSBcInRzbGliXCI7XG5pbXBvcnQgJy4uLy4uLy4uL2ZvY3VzL21kLWZvY3VzLXJpbmcuanMnO1xuaW1wb3J0ICcuLi8uLi8uLi9sYWJzL2l0ZW0vaXRlbS5qcyc7XG5pbXBvcnQgJy4uLy4uLy4uL3JpcHBsZS9yaXBwbGUuanMnO1xuaW1wb3J0IHsgaHRtbCwgTGl0RWxlbWVudCwgbm90aGluZyB9IGZyb20gJ2xpdCc7XG5pbXBvcnQgeyBwcm9wZXJ0eSwgcXVlcnkgfSBmcm9tICdsaXQvZGVjb3JhdG9ycy5qcyc7XG5pbXBvcnQgeyBjbGFzc01hcCB9IGZyb20gJ2xpdC9kaXJlY3RpdmVzL2NsYXNzLW1hcC5qcyc7XG5pbXBvcnQgeyBsaXRlcmFsLCBodG1sIGFzIHN0YXRpY0h0bWwgfSBmcm9tICdsaXQvc3RhdGljLWh0bWwuanMnO1xuaW1wb3J0IHsgbWl4aW5EZWxlZ2F0ZXNBcmlhIH0gZnJvbSAnLi4vLi4vLi4vaW50ZXJuYWwvYXJpYS9kZWxlZ2F0ZS5qcyc7XG5pbXBvcnQgeyBjcmVhdGVSZXF1ZXN0QWN0aXZhdGlvbkV2ZW50LCB9IGZyb20gJy4uL2xpc3QtbmF2aWdhdGlvbi1oZWxwZXJzLmpzJztcbi8vIFNlcGFyYXRlIHZhcmlhYmxlIG5lZWRlZCBmb3IgY2xvc3VyZS5cbmNvbnN0IGxpc3RJdGVtQmFzZUNsYXNzID0gbWl4aW5EZWxlZ2F0ZXNBcmlhKExpdEVsZW1lbnQpO1xuLyoqXG4gKiBAZmlyZXMgcmVxdWVzdC1hY3RpdmF0aW9uIHtFdmVudH0gUmVxdWVzdHMgdGhlIGxpc3QgdG8gc2V0IGB0YWJpbmRleD0wYCBvblxuICogdGhlIGl0ZW0gYW5kIGZvY3VzIGl0LiAtLWJ1YmJsZXMgLS1jb21wb3NlZFxuICovXG5leHBvcnQgY2xhc3MgTGlzdEl0ZW1FbCBleHRlbmRzIGxpc3RJdGVtQmFzZUNsYXNzIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIERpc2FibGVzIHRoZSBpdGVtIGFuZCBtYWtlcyBpdCBub24tc2VsZWN0YWJsZSBhbmQgbm9uLWludGVyYWN0aXZlLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyB0aGUgYmVoYXZpb3Igb2YgdGhlIGxpc3QgaXRlbSwgZGVmYXVsdHMgdG8gXCJ0ZXh0XCIuIENoYW5nZSB0byBcImxpbmtcIiBvclxuICAgICAgICAgKiBcImJ1dHRvblwiIGZvciBpbnRlcmFjdGl2ZSBpdGVtcy5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMudHlwZSA9ICd0ZXh0JztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJFQURPTkxZLiBTZXRzIHRoZSBgbWQtbGlzdC1pdGVtYCBhdHRyaWJ1dGUgb24gdGhlIGVsZW1lbnQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmlzTGlzdEl0ZW0gPSB0cnVlO1xuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyB0aGUgdW5kZXJseWluZyBgSFRNTEFuY2hvckVsZW1lbnRgJ3MgYGhyZWZgIHJlc291cmNlIGF0dHJpYnV0ZS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaHJlZiA9ICcnO1xuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyB0aGUgdW5kZXJseWluZyBgSFRNTEFuY2hvckVsZW1lbnRgJ3MgYHRhcmdldGAgYXR0cmlidXRlIHdoZW4gYGhyZWZgIGlzXG4gICAgICAgICAqIHNldC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMudGFyZ2V0ID0gJyc7XG4gICAgfVxuICAgIGdldCBpc0Rpc2FibGVkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kaXNhYmxlZCAmJiB0aGlzLnR5cGUgIT09ICdsaW5rJztcbiAgICB9XG4gICAgd2lsbFVwZGF0ZShjaGFuZ2VkKSB7XG4gICAgICAgIGlmICh0aGlzLmhyZWYpIHtcbiAgICAgICAgICAgIHRoaXMudHlwZSA9ICdsaW5rJztcbiAgICAgICAgfVxuICAgICAgICBzdXBlci53aWxsVXBkYXRlKGNoYW5nZWQpO1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlbmRlckxpc3RJdGVtKGh0bWwgYFxuICAgICAgPG1kLWl0ZW0+XG4gICAgICAgIDxkaXYgc2xvdD1cImNvbnRhaW5lclwiPlxuICAgICAgICAgICR7dGhpcy5yZW5kZXJSaXBwbGUoKX0gJHt0aGlzLnJlbmRlckZvY3VzUmluZygpfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPHNsb3QgbmFtZT1cInN0YXJ0XCIgc2xvdD1cInN0YXJ0XCI+PC9zbG90PlxuICAgICAgICA8c2xvdCBuYW1lPVwiZW5kXCIgc2xvdD1cImVuZFwiPjwvc2xvdD5cbiAgICAgICAgJHt0aGlzLnJlbmRlckJvZHkoKX1cbiAgICAgIDwvbWQtaXRlbT5cbiAgICBgKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcm9vdCBsaXN0IGl0ZW0uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gY29udGVudCB0aGUgY2hpbGQgY29udGVudCBvZiB0aGUgbGlzdCBpdGVtLlxuICAgICAqL1xuICAgIHJlbmRlckxpc3RJdGVtKGNvbnRlbnQpIHtcbiAgICAgICAgY29uc3QgaXNBbmNob3IgPSB0aGlzLnR5cGUgPT09ICdsaW5rJztcbiAgICAgICAgbGV0IHRhZztcbiAgICAgICAgc3dpdGNoICh0aGlzLnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2xpbmsnOlxuICAgICAgICAgICAgICAgIHRhZyA9IGxpdGVyYWwgYGFgO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnYnV0dG9uJzpcbiAgICAgICAgICAgICAgICB0YWcgPSBsaXRlcmFsIGBidXR0b25gO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGNhc2UgJ3RleHQnOlxuICAgICAgICAgICAgICAgIHRhZyA9IGxpdGVyYWwgYGxpYDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpc0ludGVyYWN0aXZlID0gdGhpcy50eXBlICE9PSAndGV4dCc7XG4gICAgICAgIC8vIFRPRE8oYi8yNjUzMzk4NjYpOiBhbm5vdW5jZSBcImJ1dHRvblwiL1wibGlua1wiIGluc2lkZSBvZiBhIGxpc3QgaXRlbS4gVW50aWxcbiAgICAgICAgLy8gdGhlbiBhbGwgYXJlIFwibGlzdGl0ZW1cIiByb2xlcyBmb3IgY29ycmVjdCBhbm5vdW5jZW1lbnQuXG4gICAgICAgIGNvbnN0IHRhcmdldCA9IGlzQW5jaG9yICYmICEhdGhpcy50YXJnZXQgPyB0aGlzLnRhcmdldCA6IG5vdGhpbmc7XG4gICAgICAgIHJldHVybiBzdGF0aWNIdG1sIGBcbiAgICAgIDwke3RhZ31cbiAgICAgICAgaWQ9XCJpdGVtXCJcbiAgICAgICAgdGFiaW5kZXg9XCIke3RoaXMuaXNEaXNhYmxlZCB8fCAhaXNJbnRlcmFjdGl2ZSA/IC0xIDogMH1cIlxuICAgICAgICA/ZGlzYWJsZWQ9JHt0aGlzLmlzRGlzYWJsZWR9XG4gICAgICAgIHJvbGU9XCJsaXN0aXRlbVwiXG4gICAgICAgIGFyaWEtc2VsZWN0ZWQ9JHt0aGlzLmFyaWFTZWxlY3RlZCB8fCBub3RoaW5nfVxuICAgICAgICBhcmlhLWNoZWNrZWQ9JHt0aGlzLmFyaWFDaGVja2VkIHx8IG5vdGhpbmd9XG4gICAgICAgIGFyaWEtZXhwYW5kZWQ9JHt0aGlzLmFyaWFFeHBhbmRlZCB8fCBub3RoaW5nfVxuICAgICAgICBhcmlhLWhhc3BvcHVwPSR7dGhpcy5hcmlhSGFzUG9wdXAgfHwgbm90aGluZ31cbiAgICAgICAgY2xhc3M9XCJsaXN0LWl0ZW0gJHtjbGFzc01hcCh0aGlzLmdldFJlbmRlckNsYXNzZXMoKSl9XCJcbiAgICAgICAgaHJlZj0ke3RoaXMuaHJlZiB8fCBub3RoaW5nfVxuICAgICAgICB0YXJnZXQ9JHt0YXJnZXR9XG4gICAgICAgIEBmb2N1cz0ke3RoaXMub25Gb2N1c31cbiAgICAgID4ke2NvbnRlbnR9PC8ke3RhZ30+XG4gICAgYDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlcyByZW5kZXJpbmcgb2YgdGhlIHJpcHBsZSBlbGVtZW50LlxuICAgICAqL1xuICAgIHJlbmRlclJpcHBsZSgpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3RleHQnKSB7XG4gICAgICAgICAgICByZXR1cm4gbm90aGluZztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaHRtbCBgIDxtZC1yaXBwbGVcbiAgICAgIHBhcnQ9XCJyaXBwbGVcIlxuICAgICAgZm9yPVwiaXRlbVwiXG4gICAgICA/ZGlzYWJsZWQ9JHt0aGlzLmlzRGlzYWJsZWR9PjwvbWQtcmlwcGxlPmA7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgcmVuZGVyaW5nIG9mIHRoZSBmb2N1cyByaW5nLlxuICAgICAqL1xuICAgIHJlbmRlckZvY3VzUmluZygpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3RleHQnKSB7XG4gICAgICAgICAgICByZXR1cm4gbm90aGluZztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaHRtbCBgIDxtZC1mb2N1cy1yaW5nXG4gICAgICBAdmlzaWJpbGl0eS1jaGFuZ2VkPSR7dGhpcy5vbkZvY3VzUmluZ1Zpc2liaWxpdHlDaGFuZ2VkfVxuICAgICAgcGFydD1cImZvY3VzLXJpbmdcIlxuICAgICAgZm9yPVwiaXRlbVwiXG4gICAgICBpbndhcmQ+PC9tZC1mb2N1cy1yaW5nPmA7XG4gICAgfVxuICAgIG9uRm9jdXNSaW5nVmlzaWJpbGl0eUNoYW5nZWQoZSkgeyB9XG4gICAgLyoqXG4gICAgICogQ2xhc3NlcyBhcHBsaWVkIHRvIHRoZSBsaXN0IGl0ZW0gcm9vdC5cbiAgICAgKi9cbiAgICBnZXRSZW5kZXJDbGFzc2VzKCkge1xuICAgICAgICByZXR1cm4geyAnZGlzYWJsZWQnOiB0aGlzLmlzRGlzYWJsZWQgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlcyByZW5kZXJpbmcgdGhlIGhlYWRsaW5lIGFuZCBzdXBwb3J0aW5nIHRleHQuXG4gICAgICovXG4gICAgcmVuZGVyQm9keSgpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYFxuICAgICAgPHNsb3Q+PC9zbG90PlxuICAgICAgPHNsb3QgbmFtZT1cIm92ZXJsaW5lXCIgc2xvdD1cIm92ZXJsaW5lXCI+PC9zbG90PlxuICAgICAgPHNsb3QgbmFtZT1cImhlYWRsaW5lXCIgc2xvdD1cImhlYWRsaW5lXCI+PC9zbG90PlxuICAgICAgPHNsb3QgbmFtZT1cInN1cHBvcnRpbmctdGV4dFwiIHNsb3Q9XCJzdXBwb3J0aW5nLXRleHRcIj48L3Nsb3Q+XG4gICAgICA8c2xvdFxuICAgICAgICBuYW1lPVwidHJhaWxpbmctc3VwcG9ydGluZy10ZXh0XCJcbiAgICAgICAgc2xvdD1cInRyYWlsaW5nLXN1cHBvcnRpbmctdGV4dFwiPjwvc2xvdD5cbiAgICBgO1xuICAgIH1cbiAgICBvbkZvY3VzKCkge1xuICAgICAgICBpZiAodGhpcy50YWJJbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBIYW5kbGVzIHRoZSBjYXNlIHdoZXJlIHRoZSB1c2VyIGNsaWNrcyBvbiB0aGUgZWxlbWVudCBhbmQgdGhlbiB0YWJzLlxuICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQoY3JlYXRlUmVxdWVzdEFjdGl2YXRpb25FdmVudCgpKTtcbiAgICB9XG4gICAgZm9jdXMoKSB7XG4gICAgICAgIC8vIFRPRE8oYi8zMDAzMzQ1MDkpOiBuZWVkZWQgZm9yIHNvbWUgY2FzZXMgd2hlcmUgZGVsZWdhdGVzRm9jdXMgZG9lc24ndFxuICAgICAgICAvLyB3b3JrIHByb2dyYW1tYXRpY2FsbHkgbGlrZSBpbiBGRiBhbmQgc2VsZWN0LW9wdGlvblxuICAgICAgICB0aGlzLmxpc3RJdGVtUm9vdD8uZm9jdXMoKTtcbiAgICB9XG4gICAgY2xpY2soKSB7XG4gICAgICAgIGlmICghdGhpcy5saXN0SXRlbVJvb3QpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSBlbGVtZW50IGhhcyBub3QgZmluaXNoZWQgcmVuZGVyaW5nLCBjYWxsIHN1cGVyIHRvIGVuc3VyZSBjbGlja1xuICAgICAgICAgICAgLy8gZXZlbnRzIGFyZSBkaXNwYXRjaGVkLlxuICAgICAgICAgICAgc3VwZXIuY2xpY2soKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBGb3J3YXJkIGNsaWNrIHRvIHRoZSBlbGVtZW50IHRvIGVuc3VyZSBsaW5rIDxhPi5jbGljaygpIHdvcmtzIGNvcnJlY3RseS5cbiAgICAgICAgdGhpcy5saXN0SXRlbVJvb3QuY2xpY2soKTtcbiAgICB9XG59XG4vKiogQG5vY29sbGFwc2UgKi9cbkxpc3RJdGVtRWwuc2hhZG93Um9vdE9wdGlvbnMgPSB7XG4gICAgLi4uTGl0RWxlbWVudC5zaGFkb3dSb290T3B0aW9ucyxcbiAgICBkZWxlZ2F0ZXNGb2N1czogdHJ1ZSxcbn07XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IEJvb2xlYW4sIHJlZmxlY3Q6IHRydWUgfSlcbl0sIExpc3RJdGVtRWwucHJvdG90eXBlLCBcImRpc2FibGVkXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHJlZmxlY3Q6IHRydWUgfSlcbl0sIExpc3RJdGVtRWwucHJvdG90eXBlLCBcInR5cGVcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgYXR0cmlidXRlOiAnbWQtbGlzdC1pdGVtJywgcmVmbGVjdDogdHJ1ZSB9KVxuXSwgTGlzdEl0ZW1FbC5wcm90b3R5cGUsIFwiaXNMaXN0SXRlbVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoKVxuXSwgTGlzdEl0ZW1FbC5wcm90b3R5cGUsIFwiaHJlZlwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoKVxuXSwgTGlzdEl0ZW1FbC5wcm90b3R5cGUsIFwidGFyZ2V0XCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBxdWVyeSgnLmxpc3QtaXRlbScpXG5dLCBMaXN0SXRlbUVsLnByb3RvdHlwZSwgXCJsaXN0SXRlbVJvb3RcIiwgdm9pZCAwKTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWxpc3QtaXRlbS5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBDbG9zZVJlYXNvbiwgY3JlYXRlRGVmYXVsdENsb3NlTWVudUV2ZW50LCBpc0Nsb3NhYmxlS2V5LCB9IGZyb20gJy4vc2hhcmVkLmpzJztcbi8qKlxuICogQSBjb250cm9sbGVyIHRoYXQgcHJvdmlkZXMgbW9zdCBmdW5jdGlvbmFsaXR5IG9mIGFuIGVsZW1lbnQgdGhhdCBpbXBsZW1lbnRzXG4gKiB0aGUgTWVudUl0ZW0gaW50ZXJmYWNlLlxuICovXG5leHBvcnQgY2xhc3MgTWVudUl0ZW1Db250cm9sbGVyIHtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gaG9zdCBUaGUgTWVudUl0ZW0gaW4gd2hpY2ggdG8gYXR0YWNoIHRoaXMgY29udHJvbGxlciB0by5cbiAgICAgKiBAcGFyYW0gY29uZmlnIFRoZSBvYmplY3QgdGhhdCBjb25maWd1cmVzIHRoaXMgY29udHJvbGxlcidzIGJlaGF2aW9yLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGhvc3QsIGNvbmZpZykge1xuICAgICAgICB0aGlzLmhvc3QgPSBob3N0O1xuICAgICAgICB0aGlzLmludGVybmFsVHlwZWFoZWFkVGV4dCA9IG51bGw7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBCaW5kIHRoaXMgY2xpY2sgbGlzdGVuZXIgdG8gdGhlIGludGVyYWN0aXZlIGVsZW1lbnQuIEhhbmRsZXMgY2xvc2luZyB0aGVcbiAgICAgICAgICogbWVudS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMub25DbGljayA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmhvc3Qua2VlcE9wZW4pXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgdGhpcy5ob3N0LmRpc3BhdGNoRXZlbnQoY3JlYXRlRGVmYXVsdENsb3NlTWVudUV2ZW50KHRoaXMuaG9zdCwge1xuICAgICAgICAgICAgICAgIGtpbmQ6IENsb3NlUmVhc29uLkNMSUNLX1NFTEVDVElPTixcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEJpbmQgdGhpcyBjbGljayBsaXN0ZW5lciB0byB0aGUgaW50ZXJhY3RpdmUgZWxlbWVudC4gSGFuZGxlcyBjbG9zaW5nIHRoZVxuICAgICAgICAgKiBtZW51LlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5vbktleWRvd24gPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSBpbnRlcmFjdGl2ZSBlbGVtZW50IGlzIGFuIGFuY2hvciB0YWcuIElmIHNvLCBjbGljayBpdC5cbiAgICAgICAgICAgIGlmICh0aGlzLmhvc3QuaHJlZiAmJiBldmVudC5jb2RlID09PSAnRW50ZXInKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaW50ZXJhY3RpdmVFbGVtZW50ID0gdGhpcy5nZXRJbnRlcmFjdGl2ZUVsZW1lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAoaW50ZXJhY3RpdmVFbGVtZW50IGluc3RhbmNlb2YgSFRNTEFuY2hvckVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJhY3RpdmVFbGVtZW50LmNsaWNrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGV2ZW50LmRlZmF1bHRQcmV2ZW50ZWQpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgLy8gSWYgdGhlIGhvc3QgaGFzIGtlZXBPcGVuID0gdHJ1ZSB3ZSBzaG91bGQgaWdub3JlIGNsaWNrcyAmIFNwYWNlL0VudGVyLFxuICAgICAgICAgICAgLy8gaG93ZXZlciB3ZSBhbHdheXMgbWFpbnRhaW4gdGhlIGFiaWxpdHkgdG8gY2xvc2UgYSBtZW51IHdpdGggYSBleHBsaWNpdFxuICAgICAgICAgICAgLy8gYGVzY2FwZWAga2V5cHJlc3MuXG4gICAgICAgICAgICBjb25zdCBrZXlDb2RlID0gZXZlbnQuY29kZTtcbiAgICAgICAgICAgIGlmICh0aGlzLmhvc3Qua2VlcE9wZW4gJiYga2V5Q29kZSAhPT0gJ0VzY2FwZScpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgaWYgKGlzQ2xvc2FibGVLZXkoa2V5Q29kZSkpIHtcbiAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9zdC5kaXNwYXRjaEV2ZW50KGNyZWF0ZURlZmF1bHRDbG9zZU1lbnVFdmVudCh0aGlzLmhvc3QsIHtcbiAgICAgICAgICAgICAgICAgICAga2luZDogQ2xvc2VSZWFzb24uS0VZRE9XTixcbiAgICAgICAgICAgICAgICAgICAga2V5OiBrZXlDb2RlLFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRIZWFkbGluZUVsZW1lbnRzID0gY29uZmlnLmdldEhlYWRsaW5lRWxlbWVudHM7XG4gICAgICAgIHRoaXMuZ2V0U3VwcG9ydGluZ1RleHRFbGVtZW50cyA9IGNvbmZpZy5nZXRTdXBwb3J0aW5nVGV4dEVsZW1lbnRzO1xuICAgICAgICB0aGlzLmdldERlZmF1bHRFbGVtZW50cyA9IGNvbmZpZy5nZXREZWZhdWx0RWxlbWVudHM7XG4gICAgICAgIHRoaXMuZ2V0SW50ZXJhY3RpdmVFbGVtZW50ID0gY29uZmlnLmdldEludGVyYWN0aXZlRWxlbWVudDtcbiAgICAgICAgdGhpcy5ob3N0LmFkZENvbnRyb2xsZXIodGhpcyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoZSB0ZXh0IHRoYXQgaXMgc2VsZWN0YWJsZSB2aWEgdHlwZWFoZWFkLiBJZiBub3Qgc2V0LCBkZWZhdWx0cyB0byB0aGVcbiAgICAgKiBpbm5lclRleHQgb2YgdGhlIGl0ZW0gc2xvdHRlZCBpbnRvIHRoZSBgXCJoZWFkbGluZVwiYCBzbG90LCBhbmQgaWYgdGhlcmUgYXJlXG4gICAgICogbm8gc2xvdHRlZCBlbGVtZW50cyBpbnRvIGhlYWRsaW5lLCB0aGVuIGl0IGNoZWNrcyB0aGUgX2RlZmF1bHRfIHNsb3QsIGFuZFxuICAgICAqIHRoZW4gdGhlIGBcInN1cHBvcnRpbmctdGV4dFwiYCBzbG90IGlmIG5vdGhpbmcgaXMgaW4gX2RlZmF1bHRfLlxuICAgICAqL1xuICAgIGdldCB0eXBlYWhlYWRUZXh0KCkge1xuICAgICAgICBpZiAodGhpcy5pbnRlcm5hbFR5cGVhaGVhZFRleHQgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmludGVybmFsVHlwZWFoZWFkVGV4dDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBoZWFkbGluZUVsZW1lbnRzID0gdGhpcy5nZXRIZWFkbGluZUVsZW1lbnRzKCk7XG4gICAgICAgIGNvbnN0IHRleHRQYXJ0cyA9IFtdO1xuICAgICAgICBoZWFkbGluZUVsZW1lbnRzLmZvckVhY2goKGhlYWRsaW5lRWxlbWVudCkgPT4ge1xuICAgICAgICAgICAgaWYgKGhlYWRsaW5lRWxlbWVudC50ZXh0Q29udGVudCAmJiBoZWFkbGluZUVsZW1lbnQudGV4dENvbnRlbnQudHJpbSgpKSB7XG4gICAgICAgICAgICAgICAgdGV4dFBhcnRzLnB1c2goaGVhZGxpbmVFbGVtZW50LnRleHRDb250ZW50LnRyaW0oKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBJZiB0aGVyZSBhcmUgbm8gaGVhZGxpbmUgZWxlbWVudHMsIGNoZWNrIHRoZSBkZWZhdWx0IHNsb3QncyB0ZXh0IGNvbnRlbnRcbiAgICAgICAgaWYgKHRleHRQYXJ0cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuZ2V0RGVmYXVsdEVsZW1lbnRzKCkuZm9yRWFjaCgoZGVmYXVsdEVsZW1lbnQpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZGVmYXVsdEVsZW1lbnQudGV4dENvbnRlbnQgJiYgZGVmYXVsdEVsZW1lbnQudGV4dENvbnRlbnQudHJpbSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRQYXJ0cy5wdXNoKGRlZmF1bHRFbGVtZW50LnRleHRDb250ZW50LnRyaW0oKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSWYgdGhlcmUgYXJlIG5vIGhlYWRsaW5lIG5vciBkZWZhdWx0IHNsb3QgZWxlbWVudHMsIGNoZWNrIHRoZVxuICAgICAgICAvL3N1cHBvcnRpbmctdGV4dCBzbG90J3MgdGV4dCBjb250ZW50XG4gICAgICAgIGlmICh0ZXh0UGFydHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB0aGlzLmdldFN1cHBvcnRpbmdUZXh0RWxlbWVudHMoKS5mb3JFYWNoKChzdXBwb3J0aW5nVGV4dEVsZW1lbnQpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoc3VwcG9ydGluZ1RleHRFbGVtZW50LnRleHRDb250ZW50ICYmXG4gICAgICAgICAgICAgICAgICAgIHN1cHBvcnRpbmdUZXh0RWxlbWVudC50ZXh0Q29udGVudC50cmltKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGV4dFBhcnRzLnB1c2goc3VwcG9ydGluZ1RleHRFbGVtZW50LnRleHRDb250ZW50LnRyaW0oKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRleHRQYXJ0cy5qb2luKCcgJyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoZSByZWNvbW1lbmRlZCB0YWcgbmFtZSB0byByZW5kZXIgYXMgdGhlIGxpc3QgaXRlbS5cbiAgICAgKi9cbiAgICBnZXQgdGFnTmFtZSgpIHtcbiAgICAgICAgY29uc3QgdHlwZSA9IHRoaXMuaG9zdC50eXBlO1xuICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ2xpbmsnOlxuICAgICAgICAgICAgICAgIHJldHVybiAnYSc7XG4gICAgICAgICAgICBjYXNlICdidXR0b24nOlxuICAgICAgICAgICAgICAgIHJldHVybiAnYnV0dG9uJztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjYXNlICdtZW51aXRlbSc6XG4gICAgICAgICAgICBjYXNlICdvcHRpb24nOlxuICAgICAgICAgICAgICAgIHJldHVybiAnbGknO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoZSByZWNvbW1lbmRlZCByb2xlIG9mIHRoZSBtZW51IGl0ZW0uXG4gICAgICovXG4gICAgZ2V0IHJvbGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhvc3QudHlwZSA9PT0gJ29wdGlvbicgPyAnb3B0aW9uJyA6ICdtZW51aXRlbSc7XG4gICAgfVxuICAgIGhvc3RDb25uZWN0ZWQoKSB7XG4gICAgICAgIHRoaXMuaG9zdC50b2dnbGVBdHRyaWJ1dGUoJ21kLW1lbnUtaXRlbScsIHRydWUpO1xuICAgIH1cbiAgICBob3N0VXBkYXRlKCkge1xuICAgICAgICBpZiAodGhpcy5ob3N0LmhyZWYpIHtcbiAgICAgICAgICAgIHRoaXMuaG9zdC50eXBlID0gJ2xpbmsnO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFVzZSB0byBzZXQgdGhlIHR5cGVhaGVhZFRleHQgd2hlbiBpdCBjaGFuZ2VzLlxuICAgICAqL1xuICAgIHNldFR5cGVhaGVhZFRleHQodGV4dCkge1xuICAgICAgICB0aGlzLmludGVybmFsVHlwZWFoZWFkVGV4dCA9IHRleHQ7XG4gICAgfVxufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9bWVudUl0ZW1Db250cm9sbGVyLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIzIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbi8qKlxuICogQ3JlYXRlcyBhbiBldmVudCB0aGF0IGNsb3NlcyBhbnkgcGFyZW50IG1lbnVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ2xvc2VNZW51RXZlbnQoaW5pdGlhdG9yLCByZWFzb24pIHtcbiAgICByZXR1cm4gbmV3IEN1c3RvbUV2ZW50KCdjbG9zZS1tZW51Jywge1xuICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICBjb21wb3NlZDogdHJ1ZSxcbiAgICAgICAgZGV0YWlsOiB7IGluaXRpYXRvciwgcmVhc29uLCBpdGVtUGF0aDogW2luaXRpYXRvcl0gfSxcbiAgICB9KTtcbn1cbi8qKlxuICogQ3JlYXRlcyBhbiBldmVudCB0aGF0IHNpZ25hbHMgdG8gdGhlIG1lbnUgdGhhdCBpdCBzaG91bGQgc3RheSBvcGVuIG9uIHRoZVxuICogZm9jdXNvdXQgZXZlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTdGF5T3Blbk9uRm9jdXNvdXRFdmVudCgpIHtcbiAgICByZXR1cm4gbmV3IEV2ZW50KCdzdGF5LW9wZW4tb24tZm9jdXNvdXQnLCB7IGJ1YmJsZXM6IHRydWUsIGNvbXBvc2VkOiB0cnVlIH0pO1xufVxuLyoqXG4gKiBDcmVhdGVzIGFuIGV2ZW50IHRoYXQgc2lnbmFscyB0byB0aGUgbWVudSB0aGF0IGl0IHNob3VsZCBjbG9zZSBvcGVuIG9uIHRoZVxuICogZm9jdXNvdXQgZXZlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDbG9zZU9uRm9jdXNvdXRFdmVudCgpIHtcbiAgICByZXR1cm4gbmV3IEV2ZW50KCdjbG9zZS1vbi1mb2N1c291dCcsIHsgYnViYmxlczogdHJ1ZSwgY29tcG9zZWQ6IHRydWUgfSk7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBkZWZhdWx0IGNsb3NlIG1lbnUgZXZlbnQgdXNlZCBieSBtZC1tZW51LlxuICovXG5leHBvcnQgY29uc3QgY3JlYXRlRGVmYXVsdENsb3NlTWVudUV2ZW50ID0gKGNyZWF0ZUNsb3NlTWVudUV2ZW50KTtcbi8qKlxuICogQ3JlYXRlcyBhbiBldmVudCB0aGF0IHJlcXVlc3RzIHRoZSBnaXZlbiBpdGVtIGJlIHNlbGVjdGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRGVhY3RpdmF0ZVR5cGVhaGVhZEV2ZW50KCkge1xuICAgIHJldHVybiBuZXcgRXZlbnQoJ2RlYWN0aXZhdGUtdHlwZWFoZWFkJywgeyBidWJibGVzOiB0cnVlLCBjb21wb3NlZDogdHJ1ZSB9KTtcbn1cbi8qKlxuICogQ3JlYXRlcyBhbiBldmVudCB0aGF0IHJlcXVlc3RzIHRoZSB0eXBlYWhlYWQgZnVuY3Rpb25hbGl0eSBvZiBjb250YWluaW5nIG1lbnVcbiAqIGJlIGFjdGl2YXRlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUFjdGl2YXRlVHlwZWFoZWFkRXZlbnQoKSB7XG4gICAgcmV0dXJuIG5ldyBFdmVudCgnYWN0aXZhdGUtdHlwZWFoZWFkJywgeyBidWJibGVzOiB0cnVlLCBjb21wb3NlZDogdHJ1ZSB9KTtcbn1cbi8qKlxuICogS2V5cyB0aGF0IGFyZSB1c2VkIHRvIG5hdmlnYXRlIG1lbnVzLlxuICovXG4vLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6ZW5mb3JjZS1uYW1lLWNhc2luZyBXZSBhcmUgbWltaWNraW5nIGVudW0gc3R5bGVcbmV4cG9ydCBjb25zdCBOYXZpZ2FibGVLZXkgPSB7XG4gICAgVVA6ICdBcnJvd1VwJyxcbiAgICBET1dOOiAnQXJyb3dEb3duJyxcbiAgICBSSUdIVDogJ0Fycm93UmlnaHQnLFxuICAgIExFRlQ6ICdBcnJvd0xlZnQnLFxufTtcbi8qKlxuICogS2V5cyB0aGF0IGFyZSB1c2VkIGZvciBzZWxlY3Rpb24gaW4gbWVudXMuXG4gKi9cbi8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTplbmZvcmNlLW5hbWUtY2FzaW5nIFdlIGFyZSBtaW1pY2tpbmcgZW51bSBzdHlsZVxuZXhwb3J0IGNvbnN0IFNlbGVjdGlvbktleSA9IHtcbiAgICBTUEFDRTogJ1NwYWNlJyxcbiAgICBFTlRFUjogJ0VudGVyJyxcbn07XG4vKipcbiAqIERlZmF1bHQgY2xvc2UgYFJlYXNvbmAga2luZCB2YWx1ZXMuXG4gKi9cbi8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTplbmZvcmNlLW5hbWUtY2FzaW5nIFdlIGFyZSBtaW1pY2tpbmcgZW51bSBzdHlsZVxuZXhwb3J0IGNvbnN0IENsb3NlUmVhc29uID0ge1xuICAgIENMSUNLX1NFTEVDVElPTjogJ2NsaWNrLXNlbGVjdGlvbicsXG4gICAgS0VZRE9XTjogJ2tleWRvd24nLFxufTtcbi8qKlxuICogS2V5cyB0aGF0IGNhbiBjbG9zZSBtZW51cy5cbiAqL1xuLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmVuZm9yY2UtbmFtZS1jYXNpbmcgV2UgYXJlIG1pbWlja2luZyBlbnVtIHN0eWxlXG5leHBvcnQgY29uc3QgS2V5ZG93bkNsb3NlS2V5ID0ge1xuICAgIEVTQ0FQRTogJ0VzY2FwZScsXG4gICAgU1BBQ0U6IFNlbGVjdGlvbktleS5TUEFDRSxcbiAgICBFTlRFUjogU2VsZWN0aW9uS2V5LkVOVEVSLFxufTtcbi8qKlxuICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBnaXZlbiBrZXkgY29kZSBpcyBhIGtleSBjb2RlIHRoYXQgc2hvdWxkIGNsb3NlIHRoZVxuICogbWVudS5cbiAqXG4gKiBAcGFyYW0gY29kZSBUaGUgS2V5Ym9hcmRFdmVudCBjb2RlIHRvIGNoZWNrLlxuICogQHJldHVybiBXaGV0aGVyIG9yIG5vdCB0aGUga2V5IGNvZGUgaXMgaW4gdGhlIHByZWRldGVybWluZWQgbGlzdCB0byBjbG9zZSB0aGVcbiAqIG1lbnUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Nsb3NhYmxlS2V5KGNvZGUpIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhLZXlkb3duQ2xvc2VLZXkpLnNvbWUoKHZhbHVlKSA9PiB2YWx1ZSA9PT0gY29kZSk7XG59XG4vKipcbiAqIERldGVybWluZXMgd2hldGhlciB0aGUgZ2l2ZW4ga2V5IGNvZGUgaXMgYSBrZXkgY29kZSB0aGF0IHNob3VsZCBzZWxlY3QgYSBtZW51XG4gKiBpdGVtLlxuICpcbiAqIEBwYXJhbSBjb2RlIFRoZXkgS2V5Ym9hcmRFdmVudCBjb2RlIHRvIGNoZWNrLlxuICogQHJldHVybiBXaGV0aGVyIG9yIG5vdCB0aGUga2V5IGNvZGUgaXMgaW4gdGhlIHByZWRldGVybWluZWQgbGlzdCB0byBzZWxlY3QgYVxuICogbWVudSBpdGVtLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTZWxlY3RhYmxlS2V5KGNvZGUpIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhTZWxlY3Rpb25LZXkpLnNvbWUoKHZhbHVlKSA9PiB2YWx1ZSA9PT0gY29kZSk7XG59XG4vKipcbiAqIERldGVybWluZXMgd2hldGhlciBhIHRhcmdldCBlbGVtZW50IGlzIGNvbnRhaW5lZCBpbnNpZGUgYW5vdGhlciBlbGVtZW50J3NcbiAqIGNvbXBvc2VkIHRyZWUuXG4gKlxuICogQHBhcmFtIHRhcmdldCBUaGUgcG90ZW50aWFsIGNvbnRhaW5lZCBlbGVtZW50LlxuICogQHBhcmFtIGNvbnRhaW5lciBUaGUgcG90ZW50aWFsIGNvbnRhaW5pbmcgZWxlbWVudCBvZiB0aGUgdGFyZ2V0LlxuICogQHJldHVybnMgV2hldGhlciB0aGUgdGFyZ2V0IGVsZW1lbnQgaXMgY29udGFpbmVkIGluc2lkZSB0aGUgY29udGFpbmVyJ3NcbiAqIGNvbXBvc2VkIHN1YnRyZWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRWxlbWVudEluU3VidHJlZSh0YXJnZXQsIGNvbnRhaW5lcikge1xuICAgIC8vIERpc3BhdGNoIGEgY29tcG9zZWQsIGJ1YmJsaW5nIGV2ZW50IHRvIGNoZWNrIGl0cyBwYXRoIHRvIHNlZSBpZiB0aGVcbiAgICAvLyBuZXdseS1mb2N1c2VkIGVsZW1lbnQgaXMgY29udGFpbmVkIGluIGNvbnRhaW5lcidzIHN1YnRyZWVcbiAgICBjb25zdCBmb2N1c0V2ID0gbmV3IEV2ZW50KCdtZC1jb250YWlucycsIHsgYnViYmxlczogdHJ1ZSwgY29tcG9zZWQ6IHRydWUgfSk7XG4gICAgbGV0IGNvbXBvc2VkUGF0aCA9IFtdO1xuICAgIGNvbnN0IGxpc3RlbmVyID0gKGV2KSA9PiB7XG4gICAgICAgIGNvbXBvc2VkUGF0aCA9IGV2LmNvbXBvc2VkUGF0aCgpO1xuICAgIH07XG4gICAgY29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ21kLWNvbnRhaW5zJywgbGlzdGVuZXIpO1xuICAgIHRhcmdldC5kaXNwYXRjaEV2ZW50KGZvY3VzRXYpO1xuICAgIGNvbnRhaW5lci5yZW1vdmVFdmVudExpc3RlbmVyKCdtZC1jb250YWlucycsIGxpc3RlbmVyKTtcbiAgICBjb25zdCBpc0NvbnRhaW5lZCA9IGNvbXBvc2VkUGF0aC5sZW5ndGggPiAwO1xuICAgIHJldHVybiBpc0NvbnRhaW5lZDtcbn1cbi8qKlxuICogRWxlbWVudCB0byBmb2N1cyBvbiB3aGVuIG1lbnUgaXMgZmlyc3Qgb3BlbmVkLlxuICovXG4vLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6ZW5mb3JjZS1uYW1lLWNhc2luZyBXZSBhcmUgbWltaWNraW5nIGVudW0gc3R5bGVcbmV4cG9ydCBjb25zdCBGb2N1c1N0YXRlID0ge1xuICAgIE5PTkU6ICdub25lJyxcbiAgICBMSVNUX1JPT1Q6ICdsaXN0LXJvb3QnLFxuICAgIEZJUlNUX0lURU06ICdmaXJzdC1pdGVtJyxcbiAgICBMQVNUX0lURU06ICdsYXN0LWl0ZW0nLFxufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXNoYXJlZC5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG4vKipcbiAqIEFuIGVudW0gb2Ygc3VwcG9ydGVkIE1lbnUgY29ybmVyc1xuICovXG4vLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6ZW5mb3JjZS1uYW1lLWNhc2luZyBXZSBhcmUgbWltaWNraW5nIGVudW0gc3R5bGVcbmV4cG9ydCBjb25zdCBDb3JuZXIgPSB7XG4gICAgRU5EX1NUQVJUOiAnZW5kLXN0YXJ0JyxcbiAgICBFTkRfRU5EOiAnZW5kLWVuZCcsXG4gICAgU1RBUlRfU1RBUlQ6ICdzdGFydC1zdGFydCcsXG4gICAgU1RBUlRfRU5EOiAnc3RhcnQtZW5kJyxcbn07XG4vKipcbiAqIEdpdmVuIGEgc3VyZmFjZSwgYW4gYW5jaG9yLCBjb3JuZXJzLCBhbmQgc29tZSBvcHRpb25zLCB0aGlzIHN1cmZhY2Ugd2lsbFxuICogY2FsY3VsYXRlIHRoZSBwb3NpdGlvbiBvZiBhIHN1cmZhY2UgdG8gYWxpZ24gdGhlIHR3byBnaXZlbiBjb3JuZXJzIGFuZCBrZWVwXG4gKiB0aGUgc3VyZmFjZSBpbnNpZGUgdGhlIHdpbmRvdyB2aWV3cG9ydC4gSXQgYWxzbyBwcm92aWRlcyBhIFN0eWxlSW5mbyBtYXAgdGhhdFxuICogY2FuIGJlIGFwcGxpZWQgdG8gdGhlIHN1cmZhY2UgdG8gaGFuZGxlIHZpc2libGlsaXR5IGFuZCBwb3NpdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIFN1cmZhY2VQb3NpdGlvbkNvbnRyb2xsZXIge1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBob3N0IFRoZSBob3N0IHRvIGNvbm5lY3QgdGhlIGNvbnRyb2xsZXIgdG8uXG4gICAgICogQHBhcmFtIGdldFByb3BlcnRpZXMgQSBmdW5jdGlvbiB0aGF0IHJldHVybnMgdGhlIHByb3BlcnRpZXMgZm9yIHRoZVxuICAgICAqIGNvbnRyb2xsZXIuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoaG9zdCwgZ2V0UHJvcGVydGllcykge1xuICAgICAgICB0aGlzLmhvc3QgPSBob3N0O1xuICAgICAgICB0aGlzLmdldFByb3BlcnRpZXMgPSBnZXRQcm9wZXJ0aWVzO1xuICAgICAgICAvLyBUaGUgY3VycmVudCBzdHlsZXMgdG8gYXBwbHkgdG8gdGhlIHN1cmZhY2UuXG4gICAgICAgIHRoaXMuc3VyZmFjZVN0eWxlc0ludGVybmFsID0ge1xuICAgICAgICAgICAgJ2Rpc3BsYXknOiAnbm9uZScsXG4gICAgICAgIH07XG4gICAgICAgIC8vIFByZXZpb3VzIHZhbHVlcyBzdG9yZWQgZm9yIGNoYW5nZSBkZXRlY3Rpb24uIE9wZW4gY2hhbmdlIGRldGVjdGlvbiBpc1xuICAgICAgICAvLyBjYWxjdWxhdGVkIHNlcGFyYXRlbHkgc28gaW5pdGlhbGl6ZSBpdCBoZXJlLlxuICAgICAgICB0aGlzLmxhc3RWYWx1ZXMgPSB7XG4gICAgICAgICAgICBpc09wZW46IGZhbHNlLFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhvc3QuYWRkQ29udHJvbGxlcih0aGlzKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhlIFN0eWxlSW5mbyBtYXAgdG8gYXBwbHkgdG8gdGhlIHN1cmZhY2UgdmlhIExpdCdzIHN0eWxlbWFwXG4gICAgICovXG4gICAgZ2V0IHN1cmZhY2VTdHlsZXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN1cmZhY2VTdHlsZXNJbnRlcm5hbDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlcyB0aGUgc3VyZmFjZSdzIG5ldyBwb3NpdGlvbiByZXF1aXJlZCBzbyB0aGF0IHRoZSBzdXJmYWNlJ3NcbiAgICAgKiBgc3VyZmFjZUNvcm5lcmAgYWxpZ25zIHRvIHRoZSBhbmNob3IncyBgYW5jaG9yQ29ybmVyYCB3aGlsZSBrZWVwaW5nIHRoZVxuICAgICAqIHN1cmZhY2UgaW5zaWRlIHRoZSB3aW5kb3cgdmlld3BvcnQuIFRoaXMgcG9zaXRpb25pbmcgYWxzbyByZXNwZWN0cyBSVEwgYnlcbiAgICAgKiBjaGVja2luZyBgZ2V0Q29tcHV0ZWRTdHlsZSgpYCBvbiB0aGUgc3VyZmFjZSBlbGVtZW50LlxuICAgICAqL1xuICAgIGFzeW5jIHBvc2l0aW9uKCkge1xuICAgICAgICBjb25zdCB7IHN1cmZhY2VFbCwgYW5jaG9yRWwsIGFuY2hvckNvcm5lcjogYW5jaG9yQ29ybmVyUmF3LCBzdXJmYWNlQ29ybmVyOiBzdXJmYWNlQ29ybmVyUmF3LCBwb3NpdGlvbmluZywgeE9mZnNldCwgeU9mZnNldCwgZGlzYWJsZUJsb2NrRmxpcCwgZGlzYWJsZUlubGluZUZsaXAsIHJlcG9zaXRpb25TdHJhdGVneSwgfSA9IHRoaXMuZ2V0UHJvcGVydGllcygpO1xuICAgICAgICBjb25zdCBhbmNob3JDb3JuZXIgPSBhbmNob3JDb3JuZXJSYXcudG9Mb3dlckNhc2UoKS50cmltKCk7XG4gICAgICAgIGNvbnN0IHN1cmZhY2VDb3JuZXIgPSBzdXJmYWNlQ29ybmVyUmF3LnRvTG93ZXJDYXNlKCkudHJpbSgpO1xuICAgICAgICBpZiAoIXN1cmZhY2VFbCB8fCAhYW5jaG9yRWwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBTdG9yZSB0aGVzZSBiZWZvcmUgd2UgcG90ZW50aWFsbHkgcmVzaXplIHRoZSB3aW5kb3cgd2l0aCB0aGUgbmV4dCBzZXQgb2ZcbiAgICAgICAgLy8gbGluZXNcbiAgICAgICAgY29uc3Qgd2luZG93SW5uZXJXaWR0aCA9IHdpbmRvdy5pbm5lcldpZHRoO1xuICAgICAgICBjb25zdCB3aW5kb3dJbm5lckhlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodDtcbiAgICAgICAgY29uc3QgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGRpdi5zdHlsZS5vcGFjaXR5ID0gJzAnO1xuICAgICAgICBkaXYuc3R5bGUucG9zaXRpb24gPSAnZml4ZWQnO1xuICAgICAgICBkaXYuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgICAgIGRpdi5zdHlsZS5pbnNldCA9ICcwJztcbiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChkaXYpO1xuICAgICAgICBjb25zdCBzY3JvbGxiYXJUZXN0UmVjdCA9IGRpdi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgZGl2LnJlbW92ZSgpO1xuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHdpZHRocyBvZiB0aGUgc2Nyb2xsYmFycyBpbiB0aGUgaW5saW5lIGFuZCBibG9jayBkaXJlY3Rpb25zXG4gICAgICAgIC8vIHRvIGFjY291bnQgZm9yIHdpbmRvdy1yZWxhdGl2ZSBjYWxjdWxhdGlvbnMuXG4gICAgICAgIGNvbnN0IGJsb2NrU2Nyb2xsYmFySGVpZ2h0ID0gd2luZG93LmlubmVySGVpZ2h0IC0gc2Nyb2xsYmFyVGVzdFJlY3QuYm90dG9tO1xuICAgICAgICBjb25zdCBpbmxpbmVTY3JvbGxiYXJXaWR0aCA9IHdpbmRvdy5pbm5lcldpZHRoIC0gc2Nyb2xsYmFyVGVzdFJlY3QucmlnaHQ7XG4gICAgICAgIC8vIFBhaW50IHRoZSBzdXJmYWNlIHRyYW5zcGFyZW50bHkgc28gdGhhdCB3ZSBjYW4gZ2V0IHRoZSBwb3NpdGlvbiBhbmQgdGhlXG4gICAgICAgIC8vIHJlY3QgaW5mbyBvZiB0aGUgc3VyZmFjZS5cbiAgICAgICAgdGhpcy5zdXJmYWNlU3R5bGVzSW50ZXJuYWwgPSB7XG4gICAgICAgICAgICAnZGlzcGxheSc6ICdibG9jaycsXG4gICAgICAgICAgICAnb3BhY2l0eSc6ICcwJyxcbiAgICAgICAgfTtcbiAgICAgICAgLy8gV2FpdCBmb3IgaXQgdG8gYmUgdmlzaWJsZS5cbiAgICAgICAgdGhpcy5ob3N0LnJlcXVlc3RVcGRhdGUoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5ob3N0LnVwZGF0ZUNvbXBsZXRlO1xuICAgICAgICAvLyBTYWZhcmkgaGFzIGEgYnVnIHRoYXQgbWFrZXMgcG9wb3ZlcnMgcmVuZGVyIGluY29ycmVjdGx5IGlmIHRoZSBub2RlIGlzXG4gICAgICAgIC8vIG1hZGUgdmlzaWJsZSArIEFuaW1hdGlvbiBGcmFtZSBiZWZvcmUgY2FsbGluZyBzaG93UG9wb3ZlcigpLlxuICAgICAgICAvLyBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MjY0MDY5XG4gICAgICAgIC8vIGFsc28gdGhlIGNhc3QgaXMgcmVxdWlyZWQgZHVlIHRvIGRpZmZlcmluZyBUUyB0eXBlcyBpbiBHb29nbGUgYW5kIE9TUy5cbiAgICAgICAgaWYgKHN1cmZhY2VFbC5wb3BvdmVyICYmXG4gICAgICAgICAgICBzdXJmYWNlRWwuaXNDb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIHN1cmZhY2VFbC5zaG93UG9wb3ZlcigpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN1cmZhY2VSZWN0ID0gc3VyZmFjZUVsLmdldFN1cmZhY2VQb3NpdGlvbkNsaWVudFJlY3RcbiAgICAgICAgICAgID8gc3VyZmFjZUVsLmdldFN1cmZhY2VQb3NpdGlvbkNsaWVudFJlY3QoKVxuICAgICAgICAgICAgOiBzdXJmYWNlRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnN0IGFuY2hvclJlY3QgPSBhbmNob3JFbC5nZXRTdXJmYWNlUG9zaXRpb25DbGllbnRSZWN0XG4gICAgICAgICAgICA/IGFuY2hvckVsLmdldFN1cmZhY2VQb3NpdGlvbkNsaWVudFJlY3QoKVxuICAgICAgICAgICAgOiBhbmNob3JFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgY29uc3QgW3N1cmZhY2VCbG9jaywgc3VyZmFjZUlubGluZV0gPSBzdXJmYWNlQ29ybmVyLnNwbGl0KCctJyk7XG4gICAgICAgIGNvbnN0IFthbmNob3JCbG9jaywgYW5jaG9ySW5saW5lXSA9IGFuY2hvckNvcm5lci5zcGxpdCgnLScpO1xuICAgICAgICAvLyBMVFIgZGVwZW5kcyBvbiB0aGUgZGlyZWN0aW9uIG9mIHRoZSBTVVJGQUNFIG5vdCB0aGUgYW5jaG9yLlxuICAgICAgICBjb25zdCBpc0xUUiA9IGdldENvbXB1dGVkU3R5bGUoc3VyZmFjZUVsKS5kaXJlY3Rpb24gPT09ICdsdHInO1xuICAgICAgICAvKlxuICAgICAgICAgKiBGb3IgbW9yZSBvbiBpbmxpbmUgYW5kIGJsb2NrIGRpbWVuc2lvbnMsIHNlZSBNRE4gYXJ0aWNsZTpcbiAgICAgICAgICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTL0NTU19sb2dpY2FsX3Byb3BlcnRpZXNfYW5kX3ZhbHVlc1xuICAgICAgICAgKlxuICAgICAgICAgKiDilIzilIDilIDilIDilIDilIAgaW5saW5lL2Jsb2NrRG9jdW1lbnRPZmZzZXQgIGlubGluZVNjcm9sbGJhcldpZHRoXG4gICAgICAgICAqIOKUgiAgICAgICDilIIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilIJcbiAgICAgICAgICog4pSCICAgICDilIzilIDilrzilIDilIDilIDilIDilIDilJAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilIJEb2N1bWVudFxuICAgICAgICAgKiDilIIgICAg4pSM4pS84pSA4pSA4pSA4pSA4pSA4pSA4pSA4pS04pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pS84pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSQXG4gICAgICAgICAqIOKUgiAgICDilILilIIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIOKUgiAgICAgICAg4pSCXG4gICAgICAgICAqIOKUlOKUgOKUgOKWuiDilILilIIg4pSM4pSA4pSA4pSA4pSA4pSAIGlubGluZS9ibG9ja1dpbmRvd09mZnNldCAgICAgIOKUgiAgICAgICAg4pSCXG4gICAgICAgICAqICAgICAg4pSC4pSCIOKUgiAgICAgICDilIIgICAgICAgICAgICAgICAgICAgICAgICAgICAg4pa8ICAgICAgICDilIJcbiAgICAgICAgICogICAgICDilILilIIg4pSCICAgICDilIzilIDilrzilIDilIDilIDilJAgICAgICAgICAgICAgICAgIFdpbmRvd+KUjOKUkCAgICAgICAg4pSCXG4gICAgICAgICAqICAgICAg4pSU4pSkIOKUgiAgICDilIzilLzilIDilIDilIDilIDilIDilLTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilLzilIIgICAgICAgIOKUglxuICAgICAgICAgKiAgICAgICDilIIg4pSCICAgIOKUguKUgiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg4pSC4pSCICAgICAgICDilIJcbiAgICAgICAgICogICAgICAg4pSCIOKUlOKUgOKUgOKWuiDilILilIIgIOKUjOKUgOKUgGlubGluZS9ibG9ja0FuY2hvck9mZnNldOKUguKUgiAgICAgICAg4pSCXG4gICAgICAgICAqICAgICAgIOKUgiAgICAgIOKUguKUgiAg4pSCICAgICDilIIgICAgICAgICAgICAgICAgICAgIOKUguKUgiAgICAgICAg4pSCXG4gICAgICAgICAqICAgICAgIOKUgiAgICAgIOKUlOKUpCAg4pSCICDilIzilIDilIDilrzilIDilIDilIDilJAgICAgICAgICAgICAgICAg4pSC4pSCICAgICAgICDilIJcbiAgICAgICAgICogICAgICAg4pSCICAgICAgIOKUgiAg4pSCIOKUjOKUvOKUgOKUgOKUgOKUgOKUgOKUgOKUpCAgICAgICAgICAgICAgICDilILilIIgICAgICAgIOKUglxuICAgICAgICAgKiAgICAgICDilIIgICAgICAg4pSCICDilJTilIDilrrilIJBbmNob3LilIIgICAgICAgICAgICAgICAg4pSC4pSCICAgICAgICDilIJcbiAgICAgICAgICogICAgICAg4pSCICAgICAgIOKUgiAgICDilJTilLTilIDilIDilIDilIDilIDilIDilJggICAgICAgICAgICAgICAg4pSC4pSCICAgICAgICDilIJcbiAgICAgICAgICogICAgICAg4pSCICAgICAgIOKUgiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg4pSC4pSCICAgICAgICDilIJcbiAgICAgICAgICogICAgICAg4pSCICAgICAgIOKUgiAgICAg4pSM4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pS84pS84pSA4pSA4pSA4pSA4pSQICAg4pSCXG4gICAgICAgICAqICAgICAgIOKUgiAgICAgICDilIIgICAgIOKUgiBTdXJmYWNlICAgICAgICAgICAgICAg4pSC4pSCICAgIOKUgiAgIOKUglxuICAgICAgICAgKiAgICAgICDilIIgICAgICAg4pSCICAgICDilIIgICAgICAgICAgICAgICAgICAgICAgIOKUguKUgiAgICDilIIgICDilIJcbiAgICAgICAgICogICAgICAg4pSCICAgICAgIOKUgiAgICAg4pSCICAgICAgICAgICAgICAgICAgICAgICDilILilIIgICAg4pSCICAg4pSCXG4gICAgICAgICAqICAgICAgIOKUgiAgICAgICDilIIgICAgIOKUgiAgICAgICAgICAgICAgICAgICAgICAg4pSC4pSCICAgIOKUgiAgIOKUglxuICAgICAgICAgKiAgICAgICDilIIgICAgICAg4pSCICAgICDilIIgICAgICAgICAgICAgICAgICAgICAgIOKUguKUgiAgICDilIIgICDilIJcbiAgICAgICAgICogICAgICAg4pSCICAgICAg4pSM4pS84pSA4pSA4pSA4pSA4pSA4pS84pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pS84pSCICAgIOKUgiAgIOKUglxuICAgICAgICAgKiAgICAgICDilIIgICDilIzilIDilrrilLTilIDilIDilIDilIDilIDilIDilLzilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJggICAg4pSc4pSQICDilIJcbiAgICAgICAgICogICAgICAg4pSCICAg4pSCICAgICAgICAg4pSCIGlubGluZS9ibG9ja09PQkNvcnJlY3Rpb24gICDilILilIIgIOKUglxuICAgICAgICAgKiAgICAgICDilIIgICDilIIgICAgICAgICDilIIgICAgICAgICAgICAgICAgICAgICAgICAg4pSCICAg4pSC4pSCICDilIJcbiAgICAgICAgICogICAgICAg4pSCICAg4pSCICAgICAgICAg4pSCICAgICAgICAgICAgICAgICAgICAgICAgIOKUnOKUgOKUgOKWuuKUnOKUgiAg4pSCXG4gICAgICAgICAqICAgICAgIOKUgiAgIOKUgiAgICAgICAgIOKUgiAgICAgICAgICAgICAgICAgICAgICAgICDilIIgICDilILilIIgIOKUglxuICAgICAgICAgKiAgICAgICDilIIgICDilIIgICAgICAgICDilJTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJDilrzilIDilIDilIDilLzilJggIOKUglxuICAgICAgICAgKiAgICAgICDilIIgIGJsb2NrU2Nyb2xsYmFySGVpZ2h0ICAgICAgICAgICAgICAgIOKUlOKUgOKUgOKUgOKUgOKUmCAgIOKUglxuICAgICAgICAgKiAgICAgICDilIIgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIOKUglxuICAgICAgICAgKiAgICAgICDilJTilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilJhcbiAgICAgICAgICovXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgYmxvY2sgcG9zaXRpb25pbmcgcHJvcGVydGllc1xuICAgICAgICBsZXQgeyBibG9ja0luc2V0LCBibG9ja091dE9mQm91bmRzQ29ycmVjdGlvbiwgc3VyZmFjZUJsb2NrUHJvcGVydHkgfSA9IHRoaXMuY2FsY3VsYXRlQmxvY2soe1xuICAgICAgICAgICAgc3VyZmFjZVJlY3QsXG4gICAgICAgICAgICBhbmNob3JSZWN0LFxuICAgICAgICAgICAgYW5jaG9yQmxvY2ssXG4gICAgICAgICAgICBzdXJmYWNlQmxvY2ssXG4gICAgICAgICAgICB5T2Zmc2V0LFxuICAgICAgICAgICAgcG9zaXRpb25pbmcsXG4gICAgICAgICAgICB3aW5kb3dJbm5lckhlaWdodCxcbiAgICAgICAgICAgIGJsb2NrU2Nyb2xsYmFySGVpZ2h0LFxuICAgICAgICB9KTtcbiAgICAgICAgLy8gSWYgdGhlIHN1cmZhY2Ugc2hvdWxkIGJlIG91dCBvZiBib3VuZHMgaW4gdGhlIGJsb2NrIGRpcmVjdGlvbiwgZmxpcCB0aGVcbiAgICAgICAgLy8gc3VyZmFjZSBhbmQgYW5jaG9yIGNvcm5lciBibG9jayB2YWx1ZXMgYW5kIHJlY2FsY3VsYXRlXG4gICAgICAgIGlmIChibG9ja091dE9mQm91bmRzQ29ycmVjdGlvbiAmJiAhZGlzYWJsZUJsb2NrRmxpcCkge1xuICAgICAgICAgICAgY29uc3QgZmxpcHBlZFN1cmZhY2VCbG9jayA9IHN1cmZhY2VCbG9jayA9PT0gJ3N0YXJ0JyA/ICdlbmQnIDogJ3N0YXJ0JztcbiAgICAgICAgICAgIGNvbnN0IGZsaXBwZWRBbmNob3JCbG9jayA9IGFuY2hvckJsb2NrID09PSAnc3RhcnQnID8gJ2VuZCcgOiAnc3RhcnQnO1xuICAgICAgICAgICAgY29uc3QgZmxpcHBlZEJsb2NrID0gdGhpcy5jYWxjdWxhdGVCbG9jayh7XG4gICAgICAgICAgICAgICAgc3VyZmFjZVJlY3QsXG4gICAgICAgICAgICAgICAgYW5jaG9yUmVjdCxcbiAgICAgICAgICAgICAgICBhbmNob3JCbG9jazogZmxpcHBlZEFuY2hvckJsb2NrLFxuICAgICAgICAgICAgICAgIHN1cmZhY2VCbG9jazogZmxpcHBlZFN1cmZhY2VCbG9jayxcbiAgICAgICAgICAgICAgICB5T2Zmc2V0LFxuICAgICAgICAgICAgICAgIHBvc2l0aW9uaW5nLFxuICAgICAgICAgICAgICAgIHdpbmRvd0lubmVySGVpZ2h0LFxuICAgICAgICAgICAgICAgIGJsb2NrU2Nyb2xsYmFySGVpZ2h0LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAvLyBJbiB0aGUgY2FzZSB0aGF0IHRoZSBmbGlwcGVkIHZlcmlvbiB3b3VsZCByZXF1aXJlIGxlc3Mgb3V0IG9mIGJvdW5kc1xuICAgICAgICAgICAgLy8gY29ycmVjdGluZywgdXNlIHRoZSBmbGlwcGVkIGNvcm5lciBibG9jayB2YWx1ZXNcbiAgICAgICAgICAgIGlmIChibG9ja091dE9mQm91bmRzQ29ycmVjdGlvbiA+IGZsaXBwZWRCbG9jay5ibG9ja091dE9mQm91bmRzQ29ycmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGJsb2NrSW5zZXQgPSBmbGlwcGVkQmxvY2suYmxvY2tJbnNldDtcbiAgICAgICAgICAgICAgICBibG9ja091dE9mQm91bmRzQ29ycmVjdGlvbiA9IGZsaXBwZWRCbG9jay5ibG9ja091dE9mQm91bmRzQ29ycmVjdGlvbjtcbiAgICAgICAgICAgICAgICBzdXJmYWNlQmxvY2tQcm9wZXJ0eSA9IGZsaXBwZWRCbG9jay5zdXJmYWNlQmxvY2tQcm9wZXJ0eTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGlubGluZSBwb3NpdGlvbmluZyBwcm9wZXJ0aWVzXG4gICAgICAgIGxldCB7IGlubGluZUluc2V0LCBpbmxpbmVPdXRPZkJvdW5kc0NvcnJlY3Rpb24sIHN1cmZhY2VJbmxpbmVQcm9wZXJ0eSB9ID0gdGhpcy5jYWxjdWxhdGVJbmxpbmUoe1xuICAgICAgICAgICAgc3VyZmFjZVJlY3QsXG4gICAgICAgICAgICBhbmNob3JSZWN0LFxuICAgICAgICAgICAgYW5jaG9ySW5saW5lLFxuICAgICAgICAgICAgc3VyZmFjZUlubGluZSxcbiAgICAgICAgICAgIHhPZmZzZXQsXG4gICAgICAgICAgICBwb3NpdGlvbmluZyxcbiAgICAgICAgICAgIGlzTFRSLFxuICAgICAgICAgICAgd2luZG93SW5uZXJXaWR0aCxcbiAgICAgICAgICAgIGlubGluZVNjcm9sbGJhcldpZHRoLFxuICAgICAgICB9KTtcbiAgICAgICAgLy8gSWYgdGhlIHN1cmZhY2Ugc2hvdWxkIGJlIG91dCBvZiBib3VuZHMgaW4gdGhlIGlubGluZSBkaXJlY3Rpb24sIGZsaXAgdGhlXG4gICAgICAgIC8vIHN1cmZhY2UgYW5kIGFuY2hvciBjb3JuZXIgaW5saW5lIHZhbHVlcyBhbmQgcmVjYWxjdWxhdGVcbiAgICAgICAgaWYgKGlubGluZU91dE9mQm91bmRzQ29ycmVjdGlvbiAmJiAhZGlzYWJsZUlubGluZUZsaXApIHtcbiAgICAgICAgICAgIGNvbnN0IGZsaXBwZWRTdXJmYWNlSW5saW5lID0gc3VyZmFjZUlubGluZSA9PT0gJ3N0YXJ0JyA/ICdlbmQnIDogJ3N0YXJ0JztcbiAgICAgICAgICAgIGNvbnN0IGZsaXBwZWRBbmNob3JJbmxpbmUgPSBhbmNob3JJbmxpbmUgPT09ICdzdGFydCcgPyAnZW5kJyA6ICdzdGFydCc7XG4gICAgICAgICAgICBjb25zdCBmbGlwcGVkSW5saW5lID0gdGhpcy5jYWxjdWxhdGVJbmxpbmUoe1xuICAgICAgICAgICAgICAgIHN1cmZhY2VSZWN0LFxuICAgICAgICAgICAgICAgIGFuY2hvclJlY3QsXG4gICAgICAgICAgICAgICAgYW5jaG9ySW5saW5lOiBmbGlwcGVkQW5jaG9ySW5saW5lLFxuICAgICAgICAgICAgICAgIHN1cmZhY2VJbmxpbmU6IGZsaXBwZWRTdXJmYWNlSW5saW5lLFxuICAgICAgICAgICAgICAgIHhPZmZzZXQsXG4gICAgICAgICAgICAgICAgcG9zaXRpb25pbmcsXG4gICAgICAgICAgICAgICAgaXNMVFIsXG4gICAgICAgICAgICAgICAgd2luZG93SW5uZXJXaWR0aCxcbiAgICAgICAgICAgICAgICBpbmxpbmVTY3JvbGxiYXJXaWR0aCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgLy8gSW4gdGhlIGNhc2UgdGhhdCB0aGUgZmxpcHBlZCB2ZXJpb24gd291bGQgcmVxdWlyZSBsZXNzIG91dCBvZiBib3VuZHNcbiAgICAgICAgICAgIC8vIGNvcnJlY3RpbmcsIHVzZSB0aGUgZmxpcHBlZCBjb3JuZXIgaW5saW5lIHZhbHVlc1xuICAgICAgICAgICAgaWYgKE1hdGguYWJzKGlubGluZU91dE9mQm91bmRzQ29ycmVjdGlvbikgPlxuICAgICAgICAgICAgICAgIE1hdGguYWJzKGZsaXBwZWRJbmxpbmUuaW5saW5lT3V0T2ZCb3VuZHNDb3JyZWN0aW9uKSkge1xuICAgICAgICAgICAgICAgIGlubGluZUluc2V0ID0gZmxpcHBlZElubGluZS5pbmxpbmVJbnNldDtcbiAgICAgICAgICAgICAgICBpbmxpbmVPdXRPZkJvdW5kc0NvcnJlY3Rpb24gPSBmbGlwcGVkSW5saW5lLmlubGluZU91dE9mQm91bmRzQ29ycmVjdGlvbjtcbiAgICAgICAgICAgICAgICBzdXJmYWNlSW5saW5lUHJvcGVydHkgPSBmbGlwcGVkSW5saW5lLnN1cmZhY2VJbmxpbmVQcm9wZXJ0eTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBJZiB3ZSBhcmUgc2ltcGx5IHJlcG9zaXRpb25pbmcgdGhlIHN1cmZhY2UgYmFjayBpbnNpZGUgdGhlIHZpZXdwb3J0LFxuICAgICAgICAvLyBzdWJ0cmFjdCB0aGUgb3V0IG9mIGJvdW5kcyBjb3JyZWN0aW9uIHZhbHVlcyBmcm9tIHRoZSBwb3NpdGlvbmluZy5cbiAgICAgICAgaWYgKHJlcG9zaXRpb25TdHJhdGVneSA9PT0gJ21vdmUnKSB7XG4gICAgICAgICAgICBibG9ja0luc2V0ID0gYmxvY2tJbnNldCAtIGJsb2NrT3V0T2ZCb3VuZHNDb3JyZWN0aW9uO1xuICAgICAgICAgICAgaW5saW5lSW5zZXQgPSBpbmxpbmVJbnNldCAtIGlubGluZU91dE9mQm91bmRzQ29ycmVjdGlvbjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN1cmZhY2VTdHlsZXNJbnRlcm5hbCA9IHtcbiAgICAgICAgICAgICdkaXNwbGF5JzogJ2Jsb2NrJyxcbiAgICAgICAgICAgICdvcGFjaXR5JzogJzEnLFxuICAgICAgICAgICAgW3N1cmZhY2VCbG9ja1Byb3BlcnR5XTogYCR7YmxvY2tJbnNldH1weGAsXG4gICAgICAgICAgICBbc3VyZmFjZUlubGluZVByb3BlcnR5XTogYCR7aW5saW5lSW5zZXR9cHhgLFxuICAgICAgICB9O1xuICAgICAgICAvLyBJbiB0aGUgY2FzZSB0aGF0IHdlIGFyZSByZXNpemluZyB0aGUgc3VyZmFjZSB0byBzdGF5IGluc2lkZSB0aGUgdmlld3BvcnRcbiAgICAgICAgLy8gd2UgbmVlZCB0byBzZXQgaGVpZ2h0IGFuZCB3aWR0aCBvbiB0aGUgc3VyZmFjZS5cbiAgICAgICAgaWYgKHJlcG9zaXRpb25TdHJhdGVneSA9PT0gJ3Jlc2l6ZScpIHtcbiAgICAgICAgICAgIC8vIEFkZCBhIGhlaWdodCBwcm9wZXJ0eSB0byB0aGUgc3R5bGVzIGlmIHRoZXJlIGlzIGJsb2NrIGhlaWdodCBjb3JyZWN0aW9uXG4gICAgICAgICAgICBpZiAoYmxvY2tPdXRPZkJvdW5kc0NvcnJlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN1cmZhY2VTdHlsZXNJbnRlcm5hbFsnaGVpZ2h0J10gPSBgJHtzdXJmYWNlUmVjdC5oZWlnaHQgLSBibG9ja091dE9mQm91bmRzQ29ycmVjdGlvbn1weGA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBBZGQgYSB3aWR0aCBwcm9wZXJ0eSB0byB0aGUgc3R5bGVzIGlmIHRoZXJlIGlzIGJsb2NrIGhlaWdodCBjb3JyZWN0aW9uXG4gICAgICAgICAgICBpZiAoaW5saW5lT3V0T2ZCb3VuZHNDb3JyZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdXJmYWNlU3R5bGVzSW50ZXJuYWxbJ3dpZHRoJ10gPSBgJHtzdXJmYWNlUmVjdC53aWR0aCAtIGlubGluZU91dE9mQm91bmRzQ29ycmVjdGlvbn1weGA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ob3N0LnJlcXVlc3RVcGRhdGUoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlcyB0aGUgY3NzIHByb3BlcnR5LCB0aGUgaW5zZXQsIGFuZCB0aGUgb3V0IG9mIGJvdW5kcyBjb3JyZWN0aW9uXG4gICAgICogZm9yIHRoZSBzdXJmYWNlIGluIHRoZSBibG9jayBkaXJlY3Rpb24uXG4gICAgICovXG4gICAgY2FsY3VsYXRlQmxvY2soY29uZmlnKSB7XG4gICAgICAgIGNvbnN0IHsgc3VyZmFjZVJlY3QsIGFuY2hvclJlY3QsIGFuY2hvckJsb2NrLCBzdXJmYWNlQmxvY2ssIHlPZmZzZXQsIHBvc2l0aW9uaW5nLCB3aW5kb3dJbm5lckhlaWdodCwgYmxvY2tTY3JvbGxiYXJIZWlnaHQsIH0gPSBjb25maWc7XG4gICAgICAgIC8vIFdlIHVzZSBudW1iZXIgYm9vbGVhbnMgdG8gbXVsdGlwbHkgdmFsdWVzIHJhdGhlciB0aGFuIGBpZmAgLyB0ZXJuYXJ5XG4gICAgICAgIC8vIHN0YXRlbWVudHMgYmVjYXVzZSBpdCBfaGVhdmlseV8gY3V0cyBkb3duIG9uIG5lc3RpbmcgYW5kIHJlYWRhYmlsaXR5XG4gICAgICAgIGNvbnN0IHJlbGF0aXZlVG9XaW5kb3cgPSBwb3NpdGlvbmluZyA9PT0gJ2ZpeGVkJyB8fCBwb3NpdGlvbmluZyA9PT0gJ2RvY3VtZW50JyA/IDEgOiAwO1xuICAgICAgICBjb25zdCByZWxhdGl2ZVRvRG9jdW1lbnQgPSBwb3NpdGlvbmluZyA9PT0gJ2RvY3VtZW50JyA/IDEgOiAwO1xuICAgICAgICBjb25zdCBpc1N1cmZhY2VCbG9ja1N0YXJ0ID0gc3VyZmFjZUJsb2NrID09PSAnc3RhcnQnID8gMSA6IDA7XG4gICAgICAgIGNvbnN0IGlzU3VyZmFjZUJsb2NrRW5kID0gc3VyZmFjZUJsb2NrID09PSAnZW5kJyA/IDEgOiAwO1xuICAgICAgICBjb25zdCBpc09uZUJsb2NrRW5kID0gYW5jaG9yQmxvY2sgIT09IHN1cmZhY2VCbG9jayA/IDEgOiAwO1xuICAgICAgICAvLyBXaGV0aGVyIG9yIG5vdCB0byBhcHBseSB0aGUgaGVpZ2h0IG9mIHRoZSBhbmNob3JcbiAgICAgICAgY29uc3QgYmxvY2tBbmNob3JPZmZzZXQgPSBpc09uZUJsb2NrRW5kICogYW5jaG9yUmVjdC5oZWlnaHQgKyB5T2Zmc2V0O1xuICAgICAgICAvLyBUaGUgYWJzb2x1dGUgYmxvY2sgcG9zaXRpb24gb2YgdGhlIGFuY2hvciByZWxhdGl2ZSB0byB3aW5kb3dcbiAgICAgICAgY29uc3QgYmxvY2tUb3BMYXllck9mZnNldCA9IGlzU3VyZmFjZUJsb2NrU3RhcnQgKiBhbmNob3JSZWN0LnRvcCArXG4gICAgICAgICAgICBpc1N1cmZhY2VCbG9ja0VuZCAqXG4gICAgICAgICAgICAgICAgKHdpbmRvd0lubmVySGVpZ2h0IC0gYW5jaG9yUmVjdC5ib3R0b20gLSBibG9ja1Njcm9sbGJhckhlaWdodCk7XG4gICAgICAgIGNvbnN0IGJsb2NrRG9jdW1lbnRPZmZzZXQgPSBpc1N1cmZhY2VCbG9ja1N0YXJ0ICogd2luZG93LnNjcm9sbFkgLSBpc1N1cmZhY2VCbG9ja0VuZCAqIHdpbmRvdy5zY3JvbGxZO1xuICAgICAgICAvLyBJZiB0aGUgc3VyZmFjZSdzIGJsb2NrIHdvdWxkIGJlIG91dCBvZiBib3VuZHMgb2YgdGhlIHdpbmRvdywgbW92ZSBpdCBiYWNrXG4gICAgICAgIC8vIGluXG4gICAgICAgIGNvbnN0IGJsb2NrT3V0T2ZCb3VuZHNDb3JyZWN0aW9uID0gTWF0aC5hYnMoTWF0aC5taW4oMCwgd2luZG93SW5uZXJIZWlnaHQgLVxuICAgICAgICAgICAgYmxvY2tUb3BMYXllck9mZnNldCAtXG4gICAgICAgICAgICBibG9ja0FuY2hvck9mZnNldCAtXG4gICAgICAgICAgICBzdXJmYWNlUmVjdC5oZWlnaHQpKTtcbiAgICAgICAgLy8gVGhlIGJsb2NrIGxvZ2ljYWwgdmFsdWUgb2YgdGhlIHN1cmZhY2VcbiAgICAgICAgY29uc3QgYmxvY2tJbnNldCA9IHJlbGF0aXZlVG9XaW5kb3cgKiBibG9ja1RvcExheWVyT2Zmc2V0ICtcbiAgICAgICAgICAgIHJlbGF0aXZlVG9Eb2N1bWVudCAqIGJsb2NrRG9jdW1lbnRPZmZzZXQgK1xuICAgICAgICAgICAgYmxvY2tBbmNob3JPZmZzZXQ7XG4gICAgICAgIGNvbnN0IHN1cmZhY2VCbG9ja1Byb3BlcnR5ID0gc3VyZmFjZUJsb2NrID09PSAnc3RhcnQnID8gJ2luc2V0LWJsb2NrLXN0YXJ0JyA6ICdpbnNldC1ibG9jay1lbmQnO1xuICAgICAgICByZXR1cm4geyBibG9ja0luc2V0LCBibG9ja091dE9mQm91bmRzQ29ycmVjdGlvbiwgc3VyZmFjZUJsb2NrUHJvcGVydHkgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlcyB0aGUgY3NzIHByb3BlcnR5LCB0aGUgaW5zZXQsIGFuZCB0aGUgb3V0IG9mIGJvdW5kcyBjb3JyZWN0aW9uXG4gICAgICogZm9yIHRoZSBzdXJmYWNlIGluIHRoZSBpbmxpbmUgZGlyZWN0aW9uLlxuICAgICAqL1xuICAgIGNhbGN1bGF0ZUlubGluZShjb25maWcpIHtcbiAgICAgICAgY29uc3QgeyBpc0xUUjogaXNMVFJCb29sLCBzdXJmYWNlSW5saW5lLCBhbmNob3JJbmxpbmUsIGFuY2hvclJlY3QsIHN1cmZhY2VSZWN0LCB4T2Zmc2V0LCBwb3NpdGlvbmluZywgd2luZG93SW5uZXJXaWR0aCwgaW5saW5lU2Nyb2xsYmFyV2lkdGgsIH0gPSBjb25maWc7XG4gICAgICAgIC8vIFdlIHVzZSBudW1iZXIgYm9vbGVhbnMgdG8gbXVsdGlwbHkgdmFsdWVzIHJhdGhlciB0aGFuIGBpZmAgLyB0ZXJuYXJ5XG4gICAgICAgIC8vIHN0YXRlbWVudHMgYmVjYXVzZSBpdCBfaGVhdmlseV8gY3V0cyBkb3duIG9uIG5lc3RpbmcgYW5kIHJlYWRhYmlsaXR5XG4gICAgICAgIGNvbnN0IHJlbGF0aXZlVG9XaW5kb3cgPSBwb3NpdGlvbmluZyA9PT0gJ2ZpeGVkJyB8fCBwb3NpdGlvbmluZyA9PT0gJ2RvY3VtZW50JyA/IDEgOiAwO1xuICAgICAgICBjb25zdCByZWxhdGl2ZVRvRG9jdW1lbnQgPSBwb3NpdGlvbmluZyA9PT0gJ2RvY3VtZW50JyA/IDEgOiAwO1xuICAgICAgICBjb25zdCBpc0xUUiA9IGlzTFRSQm9vbCA/IDEgOiAwO1xuICAgICAgICBjb25zdCBpc1JUTCA9IGlzTFRSQm9vbCA/IDAgOiAxO1xuICAgICAgICBjb25zdCBpc1N1cmZhY2VJbmxpbmVTdGFydCA9IHN1cmZhY2VJbmxpbmUgPT09ICdzdGFydCcgPyAxIDogMDtcbiAgICAgICAgY29uc3QgaXNTdXJmYWNlSW5saW5lRW5kID0gc3VyZmFjZUlubGluZSA9PT0gJ2VuZCcgPyAxIDogMDtcbiAgICAgICAgY29uc3QgaXNPbmVJbmxpbmVFbmQgPSBhbmNob3JJbmxpbmUgIT09IHN1cmZhY2VJbmxpbmUgPyAxIDogMDtcbiAgICAgICAgLy8gV2hldGhlciBvciBub3QgdG8gYXBwbHkgdGhlIHdpZHRoIG9mIHRoZSBhbmNob3JcbiAgICAgICAgY29uc3QgaW5saW5lQW5jaG9yT2Zmc2V0ID0gaXNPbmVJbmxpbmVFbmQgKiBhbmNob3JSZWN0LndpZHRoICsgeE9mZnNldDtcbiAgICAgICAgLy8gVGhlIGlubGluZSBwb3NpdGlvbiBvZiB0aGUgYW5jaG9yIHJlbGF0aXZlIHRvIHdpbmRvdyBpbiBMVFJcbiAgICAgICAgY29uc3QgaW5saW5lVG9wTGF5ZXJPZmZzZXRMVFIgPSBpc1N1cmZhY2VJbmxpbmVTdGFydCAqIGFuY2hvclJlY3QubGVmdCArXG4gICAgICAgICAgICBpc1N1cmZhY2VJbmxpbmVFbmQgKlxuICAgICAgICAgICAgICAgICh3aW5kb3dJbm5lcldpZHRoIC0gYW5jaG9yUmVjdC5yaWdodCAtIGlubGluZVNjcm9sbGJhcldpZHRoKTtcbiAgICAgICAgLy8gVGhlIGlubGluZSBwb3NpdGlvbiBvZiB0aGUgYW5jaG9yIHJlbGF0aXZlIHRvIHdpbmRvdyBpbiBSVExcbiAgICAgICAgY29uc3QgaW5saW5lVG9wTGF5ZXJPZmZzZXRSVEwgPSBpc1N1cmZhY2VJbmxpbmVTdGFydCAqXG4gICAgICAgICAgICAod2luZG93SW5uZXJXaWR0aCAtIGFuY2hvclJlY3QucmlnaHQgLSBpbmxpbmVTY3JvbGxiYXJXaWR0aCkgK1xuICAgICAgICAgICAgaXNTdXJmYWNlSW5saW5lRW5kICogYW5jaG9yUmVjdC5sZWZ0O1xuICAgICAgICAvLyBUaGUgaW5saW5lIHBvc2l0aW9uIG9mIHRoZSBhbmNob3IgcmVsYXRpdmUgdG8gd2luZG93XG4gICAgICAgIGNvbnN0IGlubGluZVRvcExheWVyT2Zmc2V0ID0gaXNMVFIgKiBpbmxpbmVUb3BMYXllck9mZnNldExUUiArIGlzUlRMICogaW5saW5lVG9wTGF5ZXJPZmZzZXRSVEw7XG4gICAgICAgIC8vIFRoZSBpbmxpbmUgcG9zaXRpb24gb2YgdGhlIGFuY2hvciByZWxhdGl2ZSB0byB3aW5kb3cgaW4gTFRSXG4gICAgICAgIGNvbnN0IGlubGluZURvY3VtZW50T2Zmc2V0TFRSID0gaXNTdXJmYWNlSW5saW5lU3RhcnQgKiB3aW5kb3cuc2Nyb2xsWCAtXG4gICAgICAgICAgICBpc1N1cmZhY2VJbmxpbmVFbmQgKiB3aW5kb3cuc2Nyb2xsWDtcbiAgICAgICAgLy8gVGhlIGlubGluZSBwb3NpdGlvbiBvZiB0aGUgYW5jaG9yIHJlbGF0aXZlIHRvIHdpbmRvdyBpbiBSVExcbiAgICAgICAgY29uc3QgaW5saW5lRG9jdW1lbnRPZmZzZXRSVEwgPSBpc1N1cmZhY2VJbmxpbmVFbmQgKiB3aW5kb3cuc2Nyb2xsWCAtXG4gICAgICAgICAgICBpc1N1cmZhY2VJbmxpbmVTdGFydCAqIHdpbmRvdy5zY3JvbGxYO1xuICAgICAgICAvLyBUaGUgaW5saW5lIHBvc2l0aW9uIG9mIHRoZSBhbmNob3IgcmVsYXRpdmUgdG8gd2luZG93XG4gICAgICAgIGNvbnN0IGlubGluZURvY3VtZW50T2Zmc2V0ID0gaXNMVFIgKiBpbmxpbmVEb2N1bWVudE9mZnNldExUUiArIGlzUlRMICogaW5saW5lRG9jdW1lbnRPZmZzZXRSVEw7XG4gICAgICAgIC8vIElmIHRoZSBzdXJmYWNlJ3MgaW5saW5lIHdvdWxkIGJlIG91dCBvZiBib3VuZHMgb2YgdGhlIHdpbmRvdywgbW92ZSBpdFxuICAgICAgICAvLyBiYWNrIGluXG4gICAgICAgIGNvbnN0IGlubGluZU91dE9mQm91bmRzQ29ycmVjdGlvbiA9IE1hdGguYWJzKE1hdGgubWluKDAsIHdpbmRvd0lubmVyV2lkdGggLVxuICAgICAgICAgICAgaW5saW5lVG9wTGF5ZXJPZmZzZXQgLVxuICAgICAgICAgICAgaW5saW5lQW5jaG9yT2Zmc2V0IC1cbiAgICAgICAgICAgIHN1cmZhY2VSZWN0LndpZHRoKSk7XG4gICAgICAgIC8vIFRoZSBpbmxpbmUgbG9naWNhbCB2YWx1ZSBvZiB0aGUgc3VyZmFjZVxuICAgICAgICBjb25zdCBpbmxpbmVJbnNldCA9IHJlbGF0aXZlVG9XaW5kb3cgKiBpbmxpbmVUb3BMYXllck9mZnNldCArXG4gICAgICAgICAgICBpbmxpbmVBbmNob3JPZmZzZXQgK1xuICAgICAgICAgICAgcmVsYXRpdmVUb0RvY3VtZW50ICogaW5saW5lRG9jdW1lbnRPZmZzZXQ7XG4gICAgICAgIGxldCBzdXJmYWNlSW5saW5lUHJvcGVydHkgPSBzdXJmYWNlSW5saW5lID09PSAnc3RhcnQnID8gJ2luc2V0LWlubGluZS1zdGFydCcgOiAnaW5zZXQtaW5saW5lLWVuZCc7XG4gICAgICAgIC8vIFRoZXJlIGFyZSBjYXNlcyB3aGVyZSB0aGUgZWxlbWVudCBpcyBSVEwgYnV0IHRoZSByb290IG9mIHRoZSBwYWdlIGlzIG5vdC5cbiAgICAgICAgLy8gSW4gdGhlc2UgY2FzZXMgd2Ugd2FudCB0byBub3QgdXNlIGxvZ2ljYWwgcHJvcGVydGllcy5cbiAgICAgICAgaWYgKHBvc2l0aW9uaW5nID09PSAnZG9jdW1lbnQnIHx8IHBvc2l0aW9uaW5nID09PSAnZml4ZWQnKSB7XG4gICAgICAgICAgICBpZiAoKHN1cmZhY2VJbmxpbmUgPT09ICdzdGFydCcgJiYgaXNMVFJCb29sKSB8fFxuICAgICAgICAgICAgICAgIChzdXJmYWNlSW5saW5lID09PSAnZW5kJyAmJiAhaXNMVFJCb29sKSkge1xuICAgICAgICAgICAgICAgIHN1cmZhY2VJbmxpbmVQcm9wZXJ0eSA9ICdsZWZ0JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHN1cmZhY2VJbmxpbmVQcm9wZXJ0eSA9ICdyaWdodCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGlubGluZUluc2V0LFxuICAgICAgICAgICAgaW5saW5lT3V0T2ZCb3VuZHNDb3JyZWN0aW9uLFxuICAgICAgICAgICAgc3VyZmFjZUlubGluZVByb3BlcnR5LFxuICAgICAgICB9O1xuICAgIH1cbiAgICBob3N0VXBkYXRlKCkge1xuICAgICAgICB0aGlzLm9uVXBkYXRlKCk7XG4gICAgfVxuICAgIGhvc3RVcGRhdGVkKCkge1xuICAgICAgICB0aGlzLm9uVXBkYXRlKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENoZWNrcyB3aGV0aGVyIHRoZSBwcm9wZXJ0aWVzIHBhc3NlZCBpbnRvIHRoZSBjb250cm9sbGVyIGhhdmUgY2hhbmdlZCBzaW5jZVxuICAgICAqIHRoZSBsYXN0IHBvc2l0aW9uaW5nLiBJZiBzbywgaXQgd2lsbCByZXBvc2l0aW9uIGlmIHRoZSBzdXJmYWNlIGlzIG9wZW4gb3JcbiAgICAgKiBjbG9zZSBpdCBpZiB0aGUgc3VyZmFjZSBzaG91bGQgY2xvc2UuXG4gICAgICovXG4gICAgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgICAgIGNvbnN0IHByb3BzID0gdGhpcy5nZXRQcm9wZXJ0aWVzKCk7XG4gICAgICAgIGxldCBoYXNDaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHByb3BzKSkge1xuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBoYXNDaGFuZ2VkID0gaGFzQ2hhbmdlZCB8fCB2YWx1ZSAhPT0gdGhpcy5sYXN0VmFsdWVzW2tleV07XG4gICAgICAgICAgICBpZiAoaGFzQ2hhbmdlZClcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBvcGVuQ2hhbmdlZCA9IHRoaXMubGFzdFZhbHVlcy5pc09wZW4gIT09IHByb3BzLmlzT3BlbjtcbiAgICAgICAgY29uc3QgaGFzQW5jaG9yID0gISFwcm9wcy5hbmNob3JFbDtcbiAgICAgICAgY29uc3QgaGFzU3VyZmFjZSA9ICEhcHJvcHMuc3VyZmFjZUVsO1xuICAgICAgICBpZiAoaGFzQ2hhbmdlZCAmJiBoYXNBbmNob3IgJiYgaGFzU3VyZmFjZSkge1xuICAgICAgICAgICAgLy8gT25seSB1cGRhdGUgaXNPcGVuLCBiZWNhdXNlIGlmIGl0J3MgY2xvc2VkLCB3ZSBkbyBub3Qgd2FudCB0byB3YXN0ZVxuICAgICAgICAgICAgLy8gdGltZSBvbiBhIHVzZWxlc3MgcmVwb3NpdGlvbiBjYWxjdWxhdGlvbi4gU28gc2F2ZSB0aGUgb3RoZXIgXCJkaXJ0eVwiXG4gICAgICAgICAgICAvLyB2YWx1ZXMgdW50aWwgbmV4dCB0aW1lIGl0IG9wZW5zLlxuICAgICAgICAgICAgdGhpcy5sYXN0VmFsdWVzLmlzT3BlbiA9IHByb3BzLmlzT3BlbjtcbiAgICAgICAgICAgIGlmIChwcm9wcy5pc09wZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBXZSBhcmUgZ29pbmcgdG8gZG8gYSByZXBvc2l0aW9uLCBzbyBzYXZlIHRoZSBwcm9wIHZhbHVlcyBmb3IgZnV0dXJlXG4gICAgICAgICAgICAgICAgLy8gZGlydHkgY2hlY2tpbmcuXG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0VmFsdWVzID0gcHJvcHM7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgIHByb3BzLm9uT3BlbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAob3BlbkNoYW5nZWQpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBwcm9wcy5iZWZvcmVDbG9zZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICBwcm9wcy5vbkNsb3NlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogSGlkZXMgdGhlIHN1cmZhY2UuXG4gICAgICovXG4gICAgY2xvc2UoKSB7XG4gICAgICAgIHRoaXMuc3VyZmFjZVN0eWxlc0ludGVybmFsID0ge1xuICAgICAgICAgICAgJ2Rpc3BsYXknOiAnbm9uZScsXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuaG9zdC5yZXF1ZXN0VXBkYXRlKCk7XG4gICAgICAgIGNvbnN0IHN1cmZhY2VFbCA9IHRoaXMuZ2V0UHJvcGVydGllcygpLnN1cmZhY2VFbDtcbiAgICAgICAgLy8gVGhlIGZvbGxvd2luZyB0eXBlIGNhc3RzIGFyZSByZXF1aXJlZCBkdWUgdG8gZGlmZmVyaW5nIFRTIHR5cGVzIGluIEdvb2dsZVxuICAgICAgICAvLyBhbmQgb3BlbiBzb3VyY2UuXG4gICAgICAgIGlmIChzdXJmYWNlRWw/LnBvcG92ZXIgJiZcbiAgICAgICAgICAgIHN1cmZhY2VFbD8uaXNDb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIHN1cmZhY2VFbC5oaWRlUG9wb3ZlcigpO1xuICAgICAgICB9XG4gICAgfVxufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c3VyZmFjZVBvc2l0aW9uQ29udHJvbGxlci5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG4vKipcbiAqIEluZGljaWVzIHRvIGFjY2VzcyB0aGUgVHlwZWFoZWFkUmVjb3JkIHR1cGxlIHR5cGUuXG4gKi9cbmV4cG9ydCBjb25zdCBUWVBFQUhFQURfUkVDT1JEID0ge1xuICAgIElOREVYOiAwLFxuICAgIElURU06IDEsXG4gICAgVEVYVDogMixcbn07XG4vKipcbiAqIFRoaXMgY29udHJvbGxlciBsaXN0ZW5zIHRvIGBrZXlkb3duYCBldmVudHMgYW5kIHNlYXJjaGVzIHRoZSBoZWFkZXIgdGV4dCBvZlxuICogYW4gYXJyYXkgb2YgYE1lbnVJdGVtYHMgd2l0aCB0aGUgY29ycmVzcG9uZGluZyBlbnRlcmVkIGtleXMgd2l0aGluIHRoZSBidWZmZXJcbiAqIHRpbWUgYW5kIGFjdGl2YXRlcyB0aGUgaXRlbS5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIGNvbnN0IHR5cGVhaGVhZENvbnRyb2xsZXIgPSBuZXcgVHlwZWFoZWFkQ29udHJvbGxlcigoKSA9PiAoe1xuICogICB0eXBlYWhlYWRCdWZmZXJUaW1lOiA1MCxcbiAqICAgZ2V0SXRlbXM6ICgpID0+IEFycmF5LmZyb20oZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnbWQtbWVudS1pdGVtJykpXG4gKiB9KSk7XG4gKiBodG1sYFxuICogICA8ZGl2XG4gKiAgICAgICBAa2V5ZG93bj0ke3R5cGVhaGVhZENvbnRyb2xsZXIub25LZXlkb3dufVxuICogICAgICAgdGFiaW5kZXg9XCIwXCJcbiAqICAgICAgIGNsYXNzPVwiYWN0aXZlSXRlbVRleHRcIj5cbiAqICAgICA8IS0tIGZvY3VzYWJsZSBlbGVtZW50IHRoYXQgd2lsbCByZWNlaXZlIGtleWRvd24gZXZlbnRzIC0tPlxuICogICAgIEFwcGxlXG4gKiAgIDwvZGl2PlxuICogICA8ZGl2PlxuICogICAgIDxtZC1tZW51LWl0ZW0gYWN0aXZlIGhlYWRlcj1cIkFwcGxlXCI+PC9tZC1tZW51LWl0ZW0+XG4gKiAgICAgPG1kLW1lbnUtaXRlbSBoZWFkZXI9XCJBcHJpY290XCI+PC9tZC1tZW51LWl0ZW0+XG4gKiAgICAgPG1kLW1lbnUtaXRlbSBoZWFkZXI9XCJCYW5hbmFcIj48L21kLW1lbnUtaXRlbT5cbiAqICAgICA8bWQtbWVudS1pdGVtIGhlYWRlcj1cIk9saXZlXCI+PC9tZC1tZW51LWl0ZW0+XG4gKiAgICAgPG1kLW1lbnUtaXRlbSBoZWFkZXI9XCJPcmFuZ2VcIj48L21kLW1lbnUtaXRlbT5cbiAqICAgPC9kaXY+XG4gKiBgO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBUeXBlYWhlYWRDb250cm9sbGVyIHtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZ2V0UHJvcGVydGllcyBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgb3B0aW9ucyBvZiB0aGUgdHlwZWFoZWFkXG4gICAgICogY29udHJvbGxlcjpcbiAgICAgKlxuICAgICAqIHtcbiAgICAgKiAgIGdldEl0ZW1zOiBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhbiBhcnJheSBvZiBtZW51IGl0ZW1zIHRvIGJlIHNlYXJjaGVkLlxuICAgICAqICAgdHlwZWFoZWFkQnVmZmVyVGltZTogVGhlIG1heGltdW0gdGltZSBiZXR3ZWVuIGVhY2gga2V5c3Ryb2tlIHRvIGtlZXAgdGhlXG4gICAgICogICAgICAgY3VycmVudCB0eXBlIGJ1ZmZlciBhbGl2ZS5cbiAgICAgKiB9XG4gICAgICovXG4gICAgY29uc3RydWN0b3IoZ2V0UHJvcGVydGllcykge1xuICAgICAgICB0aGlzLmdldFByb3BlcnRpZXMgPSBnZXRQcm9wZXJ0aWVzO1xuICAgICAgICAvKipcbiAgICAgICAgICogQXJyYXkgb2YgdHVwbGVzIHRoYXQgaGVscHMgd2l0aCBpbmRleGluZy5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMudHlwZWFoZWFkUmVjb3JkcyA9IFtdO1xuICAgICAgICAvKipcbiAgICAgICAgICogQ3VycmVudGx5LXR5cGVkIHRleHQgc2luY2UgbGFzdCBidWZmZXIgdGltZW91dFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy50eXBhaGVhZEJ1ZmZlciA9ICcnO1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIHRpbWVvdXQgaWQgZnJvbSB0aGUgY3VycmVudCBidWZmZXIncyBzZXRUaW1lb3V0XG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmNhbmNlbFR5cGVhaGVhZFRpbWVvdXQgPSAwO1xuICAgICAgICAvKipcbiAgICAgICAgICogSWYgd2UgYXJlIGN1cnJlbnRseSBcInR5cGluZ1wiXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmlzVHlwaW5nQWhlYWQgPSBmYWxzZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSByZWNvcmQgb2YgdGhlIGxhc3QgYWN0aXZlIGl0ZW0uXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmxhc3RBY3RpdmVSZWNvcmQgPSBudWxsO1xuICAgICAgICAvKipcbiAgICAgICAgICogQXBwbHkgdGhpcyBsaXN0ZW5lciB0byB0aGUgZWxlbWVudCB0aGF0IHdpbGwgcmVjZWl2ZSBga2V5ZG93bmAgZXZlbnRzIHRoYXRcbiAgICAgICAgICogc2hvdWxkIHRyaWdnZXIgdGhpcyBjb250cm9sbGVyLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gZXZlbnQgVGhlIG5hdGl2ZSBicm93c2VyIGBLZXlib2FyZEV2ZW50YCBmcm9tIHRoZSBga2V5ZG93bmAgZXZlbnQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLm9uS2V5ZG93biA9IChldmVudCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNUeXBpbmdBaGVhZCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZWFoZWFkKGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuYmVnaW5UeXBlYWhlYWQoZXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogRW5kcyB0aGUgY3VycmVudCB0eXBlYWhlYWQgYW5kIGNsZWFycyB0aGUgYnVmZmVyLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5lbmRUeXBlYWhlYWQgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmlzVHlwaW5nQWhlYWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMudHlwYWhlYWRCdWZmZXIgPSAnJztcbiAgICAgICAgICAgIHRoaXMudHlwZWFoZWFkUmVjb3JkcyA9IFtdO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXQgaXRlbXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldFByb3BlcnRpZXMoKS5nZXRJdGVtcygpO1xuICAgIH1cbiAgICBnZXQgYWN0aXZlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRQcm9wZXJ0aWVzKCkuYWN0aXZlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZXRzIHVwIHR5cGluZ2FoZWFkXG4gICAgICovXG4gICAgYmVnaW5UeXBlYWhlYWQoZXZlbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLmFjdGl2ZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gdHlwZWFoZWFkIGlmIHRoZSBfYmVnaW5uaW5nXyBvZiB0aGUgdHlwZWFoZWFkIGlzIGEgbWVudVxuICAgICAgICAvLyBuYXZpZ2F0aW9uLCBvciBhIHNlbGVjdGlvbi4gV2Ugd2lsbCBoYW5kbGUgXCJTcGFjZVwiIG9ubHkgaWYgaXQncyBpbiB0aGVcbiAgICAgICAgLy8gbWlkZGxlIG9mIGEgdHlwZWFoZWFkXG4gICAgICAgIGlmIChldmVudC5jb2RlID09PSAnU3BhY2UnIHx8XG4gICAgICAgICAgICBldmVudC5jb2RlID09PSAnRW50ZXInIHx8XG4gICAgICAgICAgICBldmVudC5jb2RlLnN0YXJ0c1dpdGgoJ0Fycm93JykgfHxcbiAgICAgICAgICAgIGV2ZW50LmNvZGUgPT09ICdFc2NhcGUnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pc1R5cGluZ0FoZWFkID0gdHJ1ZTtcbiAgICAgICAgLy8gR2VuZXJhdGVzIHRoZSByZWNvcmQgYXJyYXkgZGF0YSBzdHJ1Y3R1cmUgd2hpY2ggaXMgdGhlIGluZGV4LCB0aGUgZWxlbWVudFxuICAgICAgICAvLyBhbmQgYSBub3JtYWxpemVkIGhlYWRlci5cbiAgICAgICAgdGhpcy50eXBlYWhlYWRSZWNvcmRzID0gdGhpcy5pdGVtcy5tYXAoKGVsLCBpbmRleCkgPT4gW1xuICAgICAgICAgICAgaW5kZXgsXG4gICAgICAgICAgICBlbCxcbiAgICAgICAgICAgIGVsLnR5cGVhaGVhZFRleHQudHJpbSgpLnRvTG93ZXJDYXNlKCksXG4gICAgICAgIF0pO1xuICAgICAgICB0aGlzLmxhc3RBY3RpdmVSZWNvcmQgPVxuICAgICAgICAgICAgdGhpcy50eXBlYWhlYWRSZWNvcmRzLmZpbmQoKHJlY29yZCkgPT4gcmVjb3JkW1RZUEVBSEVBRF9SRUNPUkQuSVRFTV0udGFiSW5kZXggPT09IDApID8/IG51bGw7XG4gICAgICAgIGlmICh0aGlzLmxhc3RBY3RpdmVSZWNvcmQpIHtcbiAgICAgICAgICAgIHRoaXMubGFzdEFjdGl2ZVJlY29yZFtUWVBFQUhFQURfUkVDT1JELklURU1dLnRhYkluZGV4ID0gLTE7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50eXBlYWhlYWQoZXZlbnQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyB0aGUgdHlwZWFoZWFkLiBCYXNlZCBvbiB0aGUgbm9ybWFsaXplZCBpdGVtcyBhbmQgdGhlIGN1cnJlbnQgdGV4dFxuICAgICAqIGJ1ZmZlciwgZmluZHMgdGhlIF9uZXh0XyBpdGVtIHdpdGggbWF0Y2hpbmcgdGV4dCBhbmQgYWN0aXZhdGVzIGl0LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGl0ZW1zOiBBcHBsZSwgQmFuYW5hLCBPbGl2ZSwgT3JhbmdlLCBDdWN1bWJlclxuICAgICAqIGJ1ZmZlcjogJydcbiAgICAgKiB1c2VyIHR5cGVzOiBvXG4gICAgICpcbiAgICAgKiBhY3RpdmF0ZXMgT2xpdmVcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBpdGVtczogQXBwbGUsIEJhbmFuYSwgT2xpdmUgKGFjdGl2ZSksIE9yYW5nZSwgQ3VjdW1iZXJcbiAgICAgKiBidWZmZXI6ICdvJ1xuICAgICAqIHVzZXIgdHlwZXM6IGxcbiAgICAgKlxuICAgICAqIGFjdGl2YXRlcyBPbGl2ZVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGl0ZW1zOiBBcHBsZSwgQmFuYW5hLCBPbGl2ZSAoYWN0aXZlKSwgT3JhbmdlLCBDdWN1bWJlclxuICAgICAqIGJ1ZmZlcjogJydcbiAgICAgKiB1c2VyIHR5cGVzOiBvXG4gICAgICpcbiAgICAgKiBhY3RpdmF0ZXMgT3JhbmdlXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogaXRlbXM6IEFwcGxlLCBCYW5hbmEsIE9saXZlLCBPcmFuZ2UgKGFjdGl2ZSksIEN1Y3VtYmVyXG4gICAgICogYnVmZmVyOiAnJ1xuICAgICAqIHVzZXIgdHlwZXM6IG9cbiAgICAgKlxuICAgICAqIGFjdGl2YXRlcyBPbGl2ZVxuICAgICAqL1xuICAgIHR5cGVhaGVhZChldmVudCkge1xuICAgICAgICBpZiAoZXZlbnQuZGVmYXVsdFByZXZlbnRlZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuY2FuY2VsVHlwZWFoZWFkVGltZW91dCk7XG4gICAgICAgIC8vIFN0b3AgdHlwaW5nYWhlYWQgaWYgb25lIG9mIHRoZSBuYXZpZ2F0aW9uIG9yIHNlbGVjdGlvbiBrZXlzIChleGNlcHQgZm9yXG4gICAgICAgIC8vIFNwYWNlKSBhcmUgcHJlc3NlZFxuICAgICAgICBpZiAoZXZlbnQuY29kZSA9PT0gJ0VudGVyJyB8fFxuICAgICAgICAgICAgZXZlbnQuY29kZS5zdGFydHNXaXRoKCdBcnJvdycpIHx8XG4gICAgICAgICAgICBldmVudC5jb2RlID09PSAnRXNjYXBlJykge1xuICAgICAgICAgICAgdGhpcy5lbmRUeXBlYWhlYWQoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmxhc3RBY3RpdmVSZWNvcmQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RBY3RpdmVSZWNvcmRbVFlQRUFIRUFEX1JFQ09SRC5JVEVNXS50YWJJbmRleCA9IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIElmIFNwYWNlIGlzIHByZXNzZWQsIHByZXZlbnQgaXQgZnJvbSBzZWxlY3RpbmcgYW5kIGNsb3NpbmcgdGhlIG1lbnVcbiAgICAgICAgaWYgKGV2ZW50LmNvZGUgPT09ICdTcGFjZScpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gU3RhcnQgdXAgYSBuZXcga2V5c3Ryb2tlIGJ1ZmZlciB0aW1lb3V0XG4gICAgICAgIHRoaXMuY2FuY2VsVHlwZWFoZWFkVGltZW91dCA9IHNldFRpbWVvdXQodGhpcy5lbmRUeXBlYWhlYWQsIHRoaXMuZ2V0UHJvcGVydGllcygpLnR5cGVhaGVhZEJ1ZmZlclRpbWUpO1xuICAgICAgICB0aGlzLnR5cGFoZWFkQnVmZmVyICs9IGV2ZW50LmtleS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICBjb25zdCBsYXN0QWN0aXZlSW5kZXggPSB0aGlzLmxhc3RBY3RpdmVSZWNvcmRcbiAgICAgICAgICAgID8gdGhpcy5sYXN0QWN0aXZlUmVjb3JkW1RZUEVBSEVBRF9SRUNPUkQuSU5ERVhdXG4gICAgICAgICAgICA6IC0xO1xuICAgICAgICBjb25zdCBudW1SZWNvcmRzID0gdGhpcy50eXBlYWhlYWRSZWNvcmRzLmxlbmd0aDtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNvcnRpbmcgZnVuY3Rpb24gdGhhdCB3aWxsIHJlc29ydCB0aGUgaXRlbXMgc3RhcnRpbmcgd2l0aCB0aGUgZ2l2ZW4gaW5kZXhcbiAgICAgICAgICpcbiAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICpcbiAgICAgICAgICogdGhpcy50eXBlYWhlYWRSZWNvcmRzID1cbiAgICAgICAgICogMDogWzAsIDxyZWZlcmVuY2U+LCAnYXBwbGUnXVxuICAgICAgICAgKiAxOiBbMSwgPHJlZmVyZW5jZT4sICdhcHJpY290J11cbiAgICAgICAgICogMjogWzIsIDxyZWZlcmVuY2U+LCAnYmFuYW5hJ11cbiAgICAgICAgICogMzogWzMsIDxyZWZlcmVuY2U+LCAnb2xpdmUnXSA8LS0gbGFzdEFjdGl2ZUluZGV4XG4gICAgICAgICAqIDQ6IFs0LCA8cmVmZXJlbmNlPiwgJ29yYW5nZSddXG4gICAgICAgICAqIDU6IFs1LCA8cmVmZXJlbmNlPiwgJ3N0cmF3YmVycnknXVxuICAgICAgICAgKlxuICAgICAgICAgKiB0aGlzLnR5cGVhaGVhZFJlY29yZHMuc29ydCgoYSxiKSA9PiByZWJhc2VJbmRleE9uQWN0aXZlKGEpXG4gICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLSByZWJhc2VJbmRleE9uQWN0aXZlKGIpKSA9PT1cbiAgICAgICAgICogMDogWzMsIDxyZWZlcmVuY2U+LCAnb2xpdmUnXSA8LS0gbGFzdEFjdGl2ZUluZGV4XG4gICAgICAgICAqIDE6IFs0LCA8cmVmZXJlbmNlPiwgJ29yYW5nZSddXG4gICAgICAgICAqIDI6IFs1LCA8cmVmZXJlbmNlPiwgJ3N0cmF3YmVycnknXVxuICAgICAgICAgKiAzOiBbMCwgPHJlZmVyZW5jZT4sICdhcHBsZSddXG4gICAgICAgICAqIDQ6IFsxLCA8cmVmZXJlbmNlPiwgJ2Fwcmljb3QnXVxuICAgICAgICAgKiA1OiBbMiwgPHJlZmVyZW5jZT4sICdiYW5hbmEnXVxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3QgcmViYXNlSW5kZXhPbkFjdGl2ZSA9IChyZWNvcmQpID0+IHtcbiAgICAgICAgICAgIHJldHVybiAoKHJlY29yZFtUWVBFQUhFQURfUkVDT1JELklOREVYXSArIG51bVJlY29yZHMgLSBsYXN0QWN0aXZlSW5kZXgpICVcbiAgICAgICAgICAgICAgICBudW1SZWNvcmRzKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gcmVjb3JkcyBmaWx0ZXJlZCBhbmQgc29ydGVkIC8gcmViYXNlZCBhcm91bmQgdGhlIGxhc3QgYWN0aXZlIGluZGV4XG4gICAgICAgIGNvbnN0IG1hdGNoaW5nUmVjb3JkcyA9IHRoaXMudHlwZWFoZWFkUmVjb3Jkc1xuICAgICAgICAgICAgLmZpbHRlcigocmVjb3JkKSA9PiAhcmVjb3JkW1RZUEVBSEVBRF9SRUNPUkQuSVRFTV0uZGlzYWJsZWQgJiZcbiAgICAgICAgICAgIHJlY29yZFtUWVBFQUhFQURfUkVDT1JELlRFWFRdLnN0YXJ0c1dpdGgodGhpcy50eXBhaGVhZEJ1ZmZlcikpXG4gICAgICAgICAgICAuc29ydCgoYSwgYikgPT4gcmViYXNlSW5kZXhPbkFjdGl2ZShhKSAtIHJlYmFzZUluZGV4T25BY3RpdmUoYikpO1xuICAgICAgICAvLyBKdXN0IGxlYXZlIGlmIHRoZXJlJ3Mgbm90aGluZyB0aGF0IG1hdGNoZXMuIE5hdGl2ZSBzZWxlY3Qgd2lsbCBqdXN0XG4gICAgICAgIC8vIGNob29zZSB0aGUgZmlyc3QgdGhpbmcgdGhhdCBzdGFydHMgd2l0aCB0aGUgbmV4dCBsZXR0ZXIgaW4gdGhlIGFscGhhYmV0XG4gICAgICAgIC8vIGJ1dCB0aGF0J3Mgb3V0IG9mIHNjb3BlIGFuZCBoYXJkIHRvIGxvY2FsaXplXG4gICAgICAgIGlmIChtYXRjaGluZ1JlY29yZHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5jYW5jZWxUeXBlYWhlYWRUaW1lb3V0KTtcbiAgICAgICAgICAgIGlmICh0aGlzLmxhc3RBY3RpdmVSZWNvcmQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RBY3RpdmVSZWNvcmRbVFlQRUFIRUFEX1JFQ09SRC5JVEVNXS50YWJJbmRleCA9IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5lbmRUeXBlYWhlYWQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpc05ld1F1ZXJ5ID0gdGhpcy50eXBhaGVhZEJ1ZmZlci5sZW5ndGggPT09IDE7XG4gICAgICAgIGxldCBuZXh0UmVjb3JkO1xuICAgICAgICAvLyBUaGlzIGlzIGxpa2VseSB0aGUgY2FzZSB0aGF0IHNvbWVvbmUgaXMgdHJ5aW5nIHRvIFwidGFiXCIgdGhyb3VnaCBkaWZmZXJlbnRcbiAgICAgICAgLy8gZW50cmllcyB0aGF0IHN0YXJ0IHdpdGggdGhlIHNhbWUgbGV0dGVyXG4gICAgICAgIGlmICh0aGlzLmxhc3RBY3RpdmVSZWNvcmQgPT09IG1hdGNoaW5nUmVjb3Jkc1swXSAmJiBpc05ld1F1ZXJ5KSB7XG4gICAgICAgICAgICBuZXh0UmVjb3JkID0gbWF0Y2hpbmdSZWNvcmRzWzFdID8/IG1hdGNoaW5nUmVjb3Jkc1swXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5leHRSZWNvcmQgPSBtYXRjaGluZ1JlY29yZHNbMF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMubGFzdEFjdGl2ZVJlY29yZCkge1xuICAgICAgICAgICAgdGhpcy5sYXN0QWN0aXZlUmVjb3JkW1RZUEVBSEVBRF9SRUNPUkQuSVRFTV0udGFiSW5kZXggPSAtMTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxhc3RBY3RpdmVSZWNvcmQgPSBuZXh0UmVjb3JkO1xuICAgICAgICBuZXh0UmVjb3JkW1RZUEVBSEVBRF9SRUNPUkQuSVRFTV0udGFiSW5kZXggPSAwO1xuICAgICAgICBuZXh0UmVjb3JkW1RZUEVBSEVBRF9SRUNPUkQuSVRFTV0uZm9jdXMoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXR5cGVhaGVhZENvbnRyb2xsZXIuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjQgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuLy8gR2VuZXJhdGVkIHN0eWxlc2hlZXQgZm9yIC4vbWVudS9pbnRlcm5hbC9tZW51LXN0eWxlcy5jc3MuXG5pbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuZXhwb3J0IGNvbnN0IHN0eWxlcyA9IGNzcyBgOmhvc3R7LS1tZC1lbGV2YXRpb24tbGV2ZWw6IHZhcigtLW1kLW1lbnUtY29udGFpbmVyLWVsZXZhdGlvbiwgMik7LS1tZC1lbGV2YXRpb24tc2hhZG93LWNvbG9yOiB2YXIoLS1tZC1tZW51LWNvbnRhaW5lci1zaGFkb3ctY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1zaGFkb3csICMwMDApKTttaW4td2lkdGg6MTEycHg7Y29sb3I6dW5zZXQ7ZGlzcGxheTpjb250ZW50c31tZC1mb2N1cy1yaW5ney0tbWQtZm9jdXMtcmluZy1zaGFwZTogdmFyKC0tbWQtbWVudS1jb250YWluZXItc2hhcGUsIHZhcigtLW1kLXN5cy1zaGFwZS1jb3JuZXItZXh0cmEtc21hbGwsIDRweCkpfS5tZW51e2JvcmRlci1yYWRpdXM6dmFyKC0tbWQtbWVudS1jb250YWluZXItc2hhcGUsIHZhcigtLW1kLXN5cy1zaGFwZS1jb3JuZXItZXh0cmEtc21hbGwsIDRweCkpO2Rpc3BsYXk6bm9uZTtpbnNldDphdXRvO2JvcmRlcjpub25lO3BhZGRpbmc6MHB4O292ZXJmbG93OnZpc2libGU7YmFja2dyb3VuZC1jb2xvcjpyZ2JhKDAsMCwwLDApO2NvbG9yOmluaGVyaXQ7b3BhY2l0eTowO3otaW5kZXg6MjA7cG9zaXRpb246YWJzb2x1dGU7dXNlci1zZWxlY3Q6bm9uZTttYXgtaGVpZ2h0OmluaGVyaXQ7aGVpZ2h0OmluaGVyaXQ7bWluLXdpZHRoOmluaGVyaXQ7bWF4LXdpZHRoOmluaGVyaXQ7c2Nyb2xsYmFyLXdpZHRoOmluaGVyaXR9Lm1lbnU6OmJhY2tkcm9we2Rpc3BsYXk6bm9uZX0uZml4ZWR7cG9zaXRpb246Zml4ZWR9Lml0ZW1ze2Rpc3BsYXk6YmxvY2s7bGlzdC1zdHlsZS10eXBlOm5vbmU7bWFyZ2luOjA7b3V0bGluZTpub25lO2JveC1zaXppbmc6Ym9yZGVyLWJveDtiYWNrZ3JvdW5kLWNvbG9yOnZhcigtLW1kLW1lbnUtY29udGFpbmVyLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itc3VyZmFjZS1jb250YWluZXIsICNmM2VkZjcpKTtoZWlnaHQ6aW5oZXJpdDttYXgtaGVpZ2h0OmluaGVyaXQ7b3ZlcmZsb3c6YXV0bzttaW4td2lkdGg6aW5oZXJpdDttYXgtd2lkdGg6aW5oZXJpdDtib3JkZXItcmFkaXVzOmluaGVyaXQ7c2Nyb2xsYmFyLXdpZHRoOmluaGVyaXR9Lml0ZW0tcGFkZGluZ3twYWRkaW5nLWJsb2NrOnZhcigtLW1kLW1lbnUtdG9wLXNwYWNlLCA4cHgpIHZhcigtLW1kLW1lbnUtYm90dG9tLXNwYWNlLCA4cHgpfS5oYXMtb3ZlcmZsb3c6bm90KFtwb3BvdmVyXSkgLml0ZW1ze292ZXJmbG93OnZpc2libGV9Lmhhcy1vdmVyZmxvdy5hbmltYXRpbmcgLml0ZW1zLC5hbmltYXRpbmcgLml0ZW1ze292ZXJmbG93OmhpZGRlbn0uaGFzLW92ZXJmbG93LmFuaW1hdGluZyAuaXRlbXN7cG9pbnRlci1ldmVudHM6bm9uZX0uYW5pbWF0aW5nIDo6c2xvdHRlZCgubWQtbWVudS1oaWRkZW4pe29wYWNpdHk6MH1zbG90e2Rpc3BsYXk6YmxvY2s7aGVpZ2h0OmluaGVyaXQ7bWF4LWhlaWdodDppbmhlcml0fTo6c2xvdHRlZCg6aXMobWQtZGl2aWRlcixbcm9sZT1zZXBhcmF0b3JdKSl7bWFyZ2luOjhweCAwfUBtZWRpYShmb3JjZWQtY29sb3JzOiBhY3RpdmUpey5tZW51e2JvcmRlci1zdHlsZTpzb2xpZDtib3JkZXItY29sb3I6Q2FudmFzVGV4dDtib3JkZXItd2lkdGg6MXB4fX1cbmA7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1tZW51LXN0eWxlcy5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBfX2RlY29yYXRlIH0gZnJvbSBcInRzbGliXCI7XG5pbXBvcnQgJy4uLy4uL2VsZXZhdGlvbi9lbGV2YXRpb24uanMnO1xuaW1wb3J0ICcuLi8uLi9mb2N1cy9tZC1mb2N1cy1yaW5nLmpzJztcbmltcG9ydCB7IExpdEVsZW1lbnQsIGh0bWwsIGlzU2VydmVyLCBub3RoaW5nIH0gZnJvbSAnbGl0JztcbmltcG9ydCB7IHByb3BlcnR5LCBxdWVyeSwgcXVlcnlBc3NpZ25lZEVsZW1lbnRzLCBzdGF0ZSB9IGZyb20gJ2xpdC9kZWNvcmF0b3JzLmpzJztcbmltcG9ydCB7IGNsYXNzTWFwIH0gZnJvbSAnbGl0L2RpcmVjdGl2ZXMvY2xhc3MtbWFwLmpzJztcbmltcG9ydCB7IHN0eWxlTWFwIH0gZnJvbSAnbGl0L2RpcmVjdGl2ZXMvc3R5bGUtbWFwLmpzJztcbmltcG9ydCB7IEVBU0lORywgY3JlYXRlQW5pbWF0aW9uU2lnbmFsIH0gZnJvbSAnLi4vLi4vaW50ZXJuYWwvbW90aW9uL2FuaW1hdGlvbi5qcyc7XG5pbXBvcnQgeyBMaXN0Q29udHJvbGxlciwgTmF2aWdhYmxlS2V5cywgfSBmcm9tICcuLi8uLi9saXN0L2ludGVybmFsL2xpc3QtY29udHJvbGxlci5qcyc7XG5pbXBvcnQgeyBnZXRBY3RpdmVJdGVtLCBnZXRGaXJzdEFjdGl2YXRhYmxlSXRlbSwgZ2V0TGFzdEFjdGl2YXRhYmxlSXRlbSwgfSBmcm9tICcuLi8uLi9saXN0L2ludGVybmFsL2xpc3QtbmF2aWdhdGlvbi1oZWxwZXJzLmpzJztcbmltcG9ydCB7IEZvY3VzU3RhdGUsIGlzQ2xvc2FibGVLZXksIGlzRWxlbWVudEluU3VidHJlZSwgfSBmcm9tICcuL2NvbnRyb2xsZXJzL3NoYXJlZC5qcyc7XG5pbXBvcnQgeyBDb3JuZXIsIFN1cmZhY2VQb3NpdGlvbkNvbnRyb2xsZXIsIH0gZnJvbSAnLi9jb250cm9sbGVycy9zdXJmYWNlUG9zaXRpb25Db250cm9sbGVyLmpzJztcbmltcG9ydCB7IFR5cGVhaGVhZENvbnRyb2xsZXIgfSBmcm9tICcuL2NvbnRyb2xsZXJzL3R5cGVhaGVhZENvbnRyb2xsZXIuanMnO1xuZXhwb3J0IHsgQ29ybmVyIH0gZnJvbSAnLi9jb250cm9sbGVycy9zdXJmYWNlUG9zaXRpb25Db250cm9sbGVyLmpzJztcbi8qKlxuICogVGhlIGRlZmF1bHQgdmFsdWUgZm9yIHRoZSB0eXBlYWhlYWQgYnVmZmVyIHRpbWUgaW4gTWlsbGlzZWNvbmRzLlxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9UWVBFQUhFQURfQlVGRkVSX1RJTUUgPSAyMDA7XG5jb25zdCBzdWJtZW51TmF2S2V5cyA9IG5ldyBTZXQoW1xuICAgIE5hdmlnYWJsZUtleXMuQXJyb3dEb3duLFxuICAgIE5hdmlnYWJsZUtleXMuQXJyb3dVcCxcbiAgICBOYXZpZ2FibGVLZXlzLkhvbWUsXG4gICAgTmF2aWdhYmxlS2V5cy5FbmQsXG5dKTtcbmNvbnN0IG1lbnVOYXZLZXlzID0gbmV3IFNldChbXG4gICAgTmF2aWdhYmxlS2V5cy5BcnJvd0xlZnQsXG4gICAgTmF2aWdhYmxlS2V5cy5BcnJvd1JpZ2h0LFxuICAgIC4uLnN1Ym1lbnVOYXZLZXlzLFxuXSk7XG4vKipcbiAqIEdldHMgdGhlIGN1cnJlbnRseSBmb2N1c2VkIGVsZW1lbnQgb24gdGhlIHBhZ2UuXG4gKlxuICogQHBhcmFtIGFjdGl2ZURvYyBUaGUgZG9jdW1lbnQgb3Igc2hhZG93cm9vdCBmcm9tIHdoaWNoIHRvIHN0YXJ0IHRoZSBzZWFyY2guXG4gKiAgICBEZWZhdWx0cyB0byBgd2luZG93LmRvY3VtZW50YFxuICogQHJldHVybiBSZXR1cm5zIHRoZSBjdXJyZW50bHkgZGVlcGx5IGZvY3VzZWQgZWxlbWVudCBvciBgbnVsbGAgaWYgbm9uZS5cbiAqL1xuZnVuY3Rpb24gZ2V0Rm9jdXNlZEVsZW1lbnQoYWN0aXZlRG9jID0gZG9jdW1lbnQpIHtcbiAgICBsZXQgYWN0aXZlRWwgPSBhY3RpdmVEb2MuYWN0aXZlRWxlbWVudDtcbiAgICAvLyBDaGVjayBmb3IgYWN0aXZlRWxlbWVudCBpbiB0aGUgY2FzZSB0aGF0IGFuIGVsZW1lbnQgd2l0aCBhIHNoYWRvdyByb290IGhvc3RcbiAgICAvLyBpcyBjdXJyZW50bHkgZm9jdXNlZC5cbiAgICB3aGlsZSAoYWN0aXZlRWwgJiYgYWN0aXZlRWw/LnNoYWRvd1Jvb3Q/LmFjdGl2ZUVsZW1lbnQpIHtcbiAgICAgICAgYWN0aXZlRWwgPSBhY3RpdmVFbC5zaGFkb3dSb290LmFjdGl2ZUVsZW1lbnQ7XG4gICAgfVxuICAgIHJldHVybiBhY3RpdmVFbDtcbn1cbi8qKlxuICogQGZpcmVzIG9wZW5pbmcge0V2ZW50fSBGaXJlZCBiZWZvcmUgdGhlIG9wZW5pbmcgYW5pbWF0aW9uIGJlZ2luc1xuICogQGZpcmVzIG9wZW5lZCB7RXZlbnR9IEZpcmVkIG9uY2UgdGhlIG1lbnUgaXMgb3BlbiwgYWZ0ZXIgYW55IGFuaW1hdGlvbnNcbiAqIEBmaXJlcyBjbG9zaW5nIHtFdmVudH0gRmlyZWQgYmVmb3JlIHRoZSBjbG9zaW5nIGFuaW1hdGlvbiBiZWdpbnNcbiAqIEBmaXJlcyBjbG9zZWQge0V2ZW50fSBGaXJlZCBvbmNlIHRoZSBtZW51IGlzIGNsb3NlZCwgYWZ0ZXIgYW55IGFuaW1hdGlvbnNcbiAqL1xuZXhwb3J0IGNsYXNzIE1lbnUgZXh0ZW5kcyBMaXRFbGVtZW50IHtcbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoZSBtZW51IGlzIGFuaW1hdGluZyB1cHdhcmRzIG9yIGRvd253YXJkcyB3aGVuIG9wZW5pbmcuIFRoaXMgaXNcbiAgICAgKiBoZWxwZnVsIGZvciBjYWxjdWxhdGluZyBzb21lIGFuaW1hdGlvbiBjYWxjdWxhdGlvbnMuXG4gICAgICovXG4gICAgZ2V0IG9wZW5EaXJlY3Rpb24oKSB7XG4gICAgICAgIGNvbnN0IG1lbnVDb3JuZXJCbG9jayA9IHRoaXMubWVudUNvcm5lci5zcGxpdCgnLScpWzBdO1xuICAgICAgICByZXR1cm4gbWVudUNvcm5lckJsb2NrID09PSAnc3RhcnQnID8gJ0RPV04nIDogJ1VQJztcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhlIGVsZW1lbnQgd2hpY2ggdGhlIG1lbnUgc2hvdWxkIGFsaWduIHRvLiBJZiBgYW5jaG9yYCBpcyBzZXQgdG8gYVxuICAgICAqIG5vbi1lbXB0eSBpZHJlZiBzdHJpbmcsIHRoZW4gYGFuY2hvckVsYCB3aWxsIHJlc29sdmUgdG8gdGhlIGVsZW1lbnQgd2l0aFxuICAgICAqIHRoZSBnaXZlbiBpZCBpbiB0aGUgc2FtZSByb290IG5vZGUuIE90aGVyd2lzZSwgYG51bGxgLlxuICAgICAqL1xuICAgIGdldCBhbmNob3JFbGVtZW50KCkge1xuICAgICAgICBpZiAodGhpcy5hbmNob3IpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldFJvb3ROb2RlKCkucXVlcnlTZWxlY3RvcihgIyR7dGhpcy5hbmNob3J9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudEFuY2hvckVsZW1lbnQ7XG4gICAgfVxuICAgIHNldCBhbmNob3JFbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50QW5jaG9yRWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHRoaXMucmVxdWVzdFVwZGF0ZSgnYW5jaG9yRWxlbWVudCcpO1xuICAgIH1cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBJRCBvZiB0aGUgZWxlbWVudCBpbiB0aGUgc2FtZSByb290IG5vZGUgaW4gd2hpY2ggdGhlIG1lbnUgc2hvdWxkIGFsaWduXG4gICAgICAgICAqIHRvLiBPdmVycmlkZXMgc2V0dGluZyBgYW5jaG9yRWxlbWVudCA9IGVsZW1lbnRSZWZlcmVuY2VgLlxuICAgICAgICAgKlxuICAgICAgICAgKiBfX05PVEVfXzogYW5jaG9yIG9yIGFuY2hvckVsZW1lbnQgbXVzdCBlaXRoZXIgYmUgYW4gSFRNTEVsZW1lbnQgb3IgcmVzb2x2ZVxuICAgICAgICAgKiB0byBhbiBIVE1MRWxlbWVudCBpbiBvcmRlciBmb3IgbWVudSB0byBvcGVuLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5hbmNob3IgPSAnJztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdoZXRoZXIgdGhlIHBvc2l0aW9uaW5nIGFsZ29yaXRobSBzaG91bGQgY2FsY3VsYXRlIHJlbGF0aXZlIHRvIHRoZSBwYXJlbnRcbiAgICAgICAgICogb2YgdGhlIGFuY2hvciBlbGVtZW50IChgYWJzb2x1dGVgKSwgcmVsYXRpdmUgdG8gdGhlIHdpbmRvdyAoYGZpeGVkYCksIG9yXG4gICAgICAgICAqIHJlbGF0aXZlIHRvIHRoZSBkb2N1bWVudCAoYGRvY3VtZW50YCkuIGBwb3BvdmVyYCB3aWxsIHVzZSB0aGUgcG9wb3ZlciBBUElcbiAgICAgICAgICogdG8gcmVuZGVyIHRoZSBtZW51IGluIHRoZSB0b3AtbGF5ZXIuIElmIHlvdXIgYnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IHRoZVxuICAgICAgICAgKiBwb3BvdmVyIEFQSSwgaXQgd2lsbCBmYWxsIGJhY2sgdG8gYGZpeGVkYC5cbiAgICAgICAgICpcbiAgICAgICAgICogX19FeGFtcGxlcyBmb3IgYHBvc2l0aW9uID0gJ2ZpeGVkJ2A6X19cbiAgICAgICAgICpcbiAgICAgICAgICogLSBJZiB0aGVyZSBpcyBubyBgcG9zaXRpb246cmVsYXRpdmVgIGluIHRoZSBnaXZlbiBwYXJlbnQgdHJlZSBhbmQgdGhlXG4gICAgICAgICAqICAgc3VyZmFjZSBpcyBgcG9zaXRpb246YWJzb2x1dGVgXG4gICAgICAgICAqIC0gSWYgdGhlIHN1cmZhY2UgaXMgYHBvc2l0aW9uOmZpeGVkYFxuICAgICAgICAgKiAtIElmIHRoZSBzdXJmYWNlIGlzIGluIHRoZSBcInRvcCBsYXllclwiXG4gICAgICAgICAqIC0gVGhlIGFuY2hvciBhbmQgdGhlIHN1cmZhY2UgZG8gbm90IHNoYXJlIGEgY29tbW9uIGBwb3NpdGlvbjpyZWxhdGl2ZWBcbiAgICAgICAgICogICBhbmNlc3RvclxuICAgICAgICAgKlxuICAgICAgICAgKiBXaGVuIHVzaW5nIGBwb3NpdGlvbmluZz1maXhlZGAsIGluIG1vc3QgY2FzZXMsIHRoZSBtZW51IHNob3VsZCBwb3NpdGlvblxuICAgICAgICAgKiBpdHNlbGYgYWJvdmUgbW9zdCBvdGhlciBgcG9zaXRpb246YWJzb2x1dGVgIG9yIGBwb3NpdGlvbjpmaXhlZGAgZWxlbWVudHNcbiAgICAgICAgICogd2hlbiBwbGFjZWQgaW5zaWRlIG9mIHRoZW0uIGUuZy4gdXNpbmcgYSBtZW51IGluc2lkZSBvZiBhbiBgbWQtZGlhbG9nYC5cbiAgICAgICAgICpcbiAgICAgICAgICogX19OT1RFX186IEZpeGVkIG1lbnVzIHdpbGwgbm90IHNjcm9sbCB3aXRoIHRoZSBwYWdlIGFuZCB3aWxsIGJlIGZpeGVkIHRvXG4gICAgICAgICAqIHRoZSB3aW5kb3cgaW5zdGVhZC5cbiAgICAgICAgICpcbiAgICAgICAgICogX19FeGFtcGxlcyBmb3IgYHBvc2l0aW9uID0gJ2RvY3VtZW50J2A6X19cbiAgICAgICAgICpcbiAgICAgICAgICogLSBUaGVyZSBpcyBubyBwYXJlbnQgdGhhdCBjcmVhdGVzIGEgcmVsYXRpdmUgcG9zaXRpb25pbmcgY29udGV4dCBlLmcuXG4gICAgICAgICAqICAgYHBvc2l0aW9uOiByZWxhdGl2ZWAsIGBwb3NpdGlvbjogYWJzb2x1dGVgLCBgdHJhbnNmb3JtOiB0cmFuc2xhdGUoeCwgeSlgLFxuICAgICAgICAgKiAgIGV0Yy5cbiAgICAgICAgICogLSBZb3UgcHV0IHRoZSBlZmZvcnQgaW50byBob2lzdGluZyB0aGUgbWVudSB0byB0aGUgdG9wIG9mIHRoZSBET00gbGlrZSB0aGVcbiAgICAgICAgICogICBlbmQgb2YgdGhlIGA8Ym9keT5gIHRvIHJlbmRlciBvdmVyIGV2ZXJ5dGhpbmcgb3IgaW4gYSB0b3AtbGF5ZXIuXG4gICAgICAgICAqIC0gWW91IGFyZSByZXVzaW5nIGEgc2luZ2xlIGBtZC1tZW51YCBlbGVtZW50IHRoYXQgZHluYW1pY2FsbHkgcmVuZGVyc1xuICAgICAgICAgKiAgIGNvbnRlbnQuXG4gICAgICAgICAqXG4gICAgICAgICAqIF9fRXhhbXBsZXMgZm9yIGBwb3NpdGlvbiA9ICdwb3BvdmVyJ2A6X19cbiAgICAgICAgICpcbiAgICAgICAgICogLSBZb3VyIGJyb3dzZXIgc3VwcG9ydHMgYHBvcG92ZXJgLlxuICAgICAgICAgKiAtIE1vc3QgY2FzZXMuIE9uY2UgcG9wb3ZlciBpcyBpbiBicm93c2VycywgdGhpcyB3aWxsIGJlY29tZSB0aGUgZGVmYXVsdC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMucG9zaXRpb25pbmcgPSAnYWJzb2x1dGUnO1xuICAgICAgICAvKipcbiAgICAgICAgICogU2tpcHMgdGhlIG9wZW5pbmcgYW5kIGNsb3NpbmcgYW5pbWF0aW9ucy5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMucXVpY2sgPSBmYWxzZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIERpc3BsYXlzIG92ZXJmbG93IGNvbnRlbnQgbGlrZSBhIHN1Ym1lbnUuIE5vdCByZXF1aXJlZCBpbiBtb3N0IGNhc2VzIHdoZW5cbiAgICAgICAgICogdXNpbmcgYHBvc2l0aW9uaW5nPVwicG9wb3ZlclwiYC5cbiAgICAgICAgICpcbiAgICAgICAgICogX19OT1RFX186IFRoaXMgbWF5IGNhdXNlIGFkdmVyc2UgZWZmZWN0cyBpZiB5b3Ugc2V0XG4gICAgICAgICAqIGBtZC1tZW51IHttYXgtaGVpZ2h0Oi4uLn1gXG4gICAgICAgICAqIGFuZCBoYXZlIGl0ZW1zIG92ZXJmbG93aW5nIGl0ZW1zIGluIHRoZSBcInlcIiBkaXJlY3Rpb24uXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmhhc092ZXJmbG93ID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBPcGVucyB0aGUgbWVudSBhbmQgbWFrZXMgaXQgdmlzaWJsZS4gQWx0ZXJuYXRpdmUgdG8gdGhlIGAuc2hvdygpYCBhbmRcbiAgICAgICAgICogYC5jbG9zZSgpYCBtZXRob2RzXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLm9wZW4gPSBmYWxzZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIE9mZnNldHMgdGhlIG1lbnUncyBpbmxpbmUgYWxpZ25tZW50IGZyb20gdGhlIGFuY2hvciBieSB0aGUgZ2l2ZW4gbnVtYmVyIGluXG4gICAgICAgICAqIHBpeGVscy4gVGhpcyB2YWx1ZSBpcyBkaXJlY3Rpb24gYXdhcmUgYW5kIHdpbGwgZm9sbG93IHRoZSBMVFIgLyBSVExcbiAgICAgICAgICogZGlyZWN0aW9uLlxuICAgICAgICAgKlxuICAgICAgICAgKiBlLmcuIExUUjogcG9zaXRpdmUgLT4gcmlnaHQsIG5lZ2F0aXZlIC0+IGxlZnRcbiAgICAgICAgICogICAgICBSVEw6IHBvc2l0aXZlIC0+IGxlZnQsIG5lZ2F0aXZlIC0+IHJpZ2h0XG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnhPZmZzZXQgPSAwO1xuICAgICAgICAvKipcbiAgICAgICAgICogT2Zmc2V0cyB0aGUgbWVudSdzIGJsb2NrIGFsaWdubWVudCBmcm9tIHRoZSBhbmNob3IgYnkgdGhlIGdpdmVuIG51bWJlciBpblxuICAgICAgICAgKiBwaXhlbHMuXG4gICAgICAgICAqXG4gICAgICAgICAqIGUuZy4gcG9zaXRpdmUgLT4gZG93biwgbmVnYXRpdmUgLT4gdXBcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMueU9mZnNldCA9IDA7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEaXNhYmxlIHRoZSBgZmxpcGAgYmVoYXZpb3IgdGhhdCB1c3VhbGx5IGhhcHBlbnMgb24gdGhlIGhvcml6b250YWwgYXhpc1xuICAgICAgICAgKiB3aGVuIHRoZSBzdXJmYWNlIHdvdWxkIHJlbmRlciBvdXRzaWRlIHRoZSB2aWV3cG9ydC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMubm9Ib3Jpem9udGFsRmxpcCA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogRGlzYWJsZSB0aGUgYGZsaXBgIGJlaGF2aW9yIHRoYXQgdXN1YWxseSBoYXBwZW5zIG9uIHRoZSB2ZXJ0aWNhbCBheGlzIHdoZW5cbiAgICAgICAgICogdGhlIHN1cmZhY2Ugd291bGQgcmVuZGVyIG91dHNpZGUgdGhlIHZpZXdwb3J0LlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5ub1ZlcnRpY2FsRmxpcCA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIG1heCB0aW1lIGJldHdlZW4gdGhlIGtleXN0cm9rZXMgb2YgdGhlIHR5cGVhaGVhZCBtZW51IGJlaGF2aW9yIGJlZm9yZVxuICAgICAgICAgKiBpdCBjbGVhcnMgdGhlIHR5cGVhaGVhZCBidWZmZXIuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnR5cGVhaGVhZERlbGF5ID0gREVGQVVMVF9UWVBFQUhFQURfQlVGRkVSX1RJTUU7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgY29ybmVyIG9mIHRoZSBhbmNob3Igd2hpY2ggdG8gYWxpZ24gdGhlIG1lbnUgaW4gdGhlIHN0YW5kYXJkIGxvZ2ljYWxcbiAgICAgICAgICogcHJvcGVydHkgc3R5bGUgb2YgPGJsb2NrPi08aW5saW5lPiBlLmcuIGAnZW5kLXN0YXJ0J2AuXG4gICAgICAgICAqXG4gICAgICAgICAqIE5PVEU6IFRoaXMgdmFsdWUgbWF5IG5vdCBiZSByZXNwZWN0ZWQgYnkgdGhlIG1lbnUgcG9zaXRpb25pbmcgYWxnb3JpdGhtXG4gICAgICAgICAqIGlmIHRoZSBtZW51IHdvdWxkIHJlbmRlciBvdXRpc2RlIHRoZSB2aWV3cG9ydC5cbiAgICAgICAgICogVXNlIGBuby1ob3Jpem9udGFsLWZsaXBgIG9yIGBuby12ZXJ0aWNhbC1mbGlwYCB0byBmb3JjZSB0aGUgdXNhZ2Ugb2YgdGhlIHZhbHVlXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmFuY2hvckNvcm5lciA9IENvcm5lci5FTkRfU1RBUlQ7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgY29ybmVyIG9mIHRoZSBtZW51IHdoaWNoIHRvIGFsaWduIHRoZSBhbmNob3IgaW4gdGhlIHN0YW5kYXJkIGxvZ2ljYWxcbiAgICAgICAgICogcHJvcGVydHkgc3R5bGUgb2YgPGJsb2NrPi08aW5saW5lPiBlLmcuIGAnc3RhcnQtc3RhcnQnYC5cbiAgICAgICAgICpcbiAgICAgICAgICogTk9URTogVGhpcyB2YWx1ZSBtYXkgbm90IGJlIHJlc3BlY3RlZCBieSB0aGUgbWVudSBwb3NpdGlvbmluZyBhbGdvcml0aG1cbiAgICAgICAgICogaWYgdGhlIG1lbnUgd291bGQgcmVuZGVyIG91dGlzZGUgdGhlIHZpZXdwb3J0LlxuICAgICAgICAgKiBVc2UgYG5vLWhvcml6b250YWwtZmxpcGAgb3IgYG5vLXZlcnRpY2FsLWZsaXBgIHRvIGZvcmNlIHRoZSB1c2FnZSBvZiB0aGUgdmFsdWVcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMubWVudUNvcm5lciA9IENvcm5lci5TVEFSVF9TVEFSVDtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEtlZXBzIHRoZSB1c2VyIGNsaWNrcyBvdXRzaWRlIHRoZSBtZW51LlxuICAgICAgICAgKlxuICAgICAgICAgKiBOT1RFOiBjbGlja2luZyBvdXRzaWRlIG1heSBzdGlsbCBjYXVzZSBmb2N1c291dCB0byBjbG9zZSB0aGUgbWVudSBzbyBzZWVcbiAgICAgICAgICogYHN0YXlPcGVuT25Gb2N1c291dGAuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnN0YXlPcGVuT25PdXRzaWRlQ2xpY2sgPSBmYWxzZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEtlZXBzIHRoZSBtZW51IG9wZW4gd2hlbiBmb2N1cyBsZWF2ZXMgdGhlIG1lbnUncyBjb21wb3NlZCBzdWJ0cmVlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBOT1RFOiBGb2N1c291dCBiZWhhdmlvciB3aWxsIHN0b3AgcHJvcGFnYXRpb24gb2YgdGhlIGZvY3Vzb3V0IGV2ZW50LiBTZXRcbiAgICAgICAgICogdGhpcyBwcm9wZXJ0eSB0byB0cnVlIHRvIG9wdC1vdXQgb2YgbWVudSdzIGZvY3Vzb3V0IGhhbmRsaW5nIGFsdG9nZXRoZXIuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnN0YXlPcGVuT25Gb2N1c291dCA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogQWZ0ZXIgY2xvc2luZywgZG9lcyBub3QgcmVzdG9yZSBmb2N1cyB0byB0aGUgbGFzdCBmb2N1c2VkIGVsZW1lbnQgYmVmb3JlXG4gICAgICAgICAqIHRoZSBtZW51IHdhcyBvcGVuZWQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnNraXBSZXN0b3JlRm9jdXMgPSBmYWxzZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBlbGVtZW50IHRoYXQgc2hvdWxkIGJlIGZvY3VzZWQgYnkgZGVmYXVsdCBvbmNlIG9wZW5lZC5cbiAgICAgICAgICpcbiAgICAgICAgICogTk9URTogV2hlbiBzZXR0aW5nIGRlZmF1bHQgZm9jdXMgdG8gJ0xJU1RfUk9PVCcsIHJlbWVtYmVyIHRvIGNoYW5nZVxuICAgICAgICAgKiBgdGFiaW5kZXhgIHRvIGAwYCBhbmQgY2hhbmdlIG1kLW1lbnUncyBkaXNwbGF5IHRvIHNvbWV0aGluZyBvdGhlciB0aGFuXG4gICAgICAgICAqIGBkaXNwbGF5OiBjb250ZW50c2Agd2hlbiBuZWNlc3NhcnkuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmRlZmF1bHRGb2N1cyA9IEZvY3VzU3RhdGUuRklSU1RfSVRFTTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFR1cm5zIG9mZiBuYXZpZ2F0aW9uIHdyYXBwaW5nLiBCeSBkZWZhdWx0LCBuYXZpZ2F0aW5nIHBhc3QgdGhlIGVuZCBvZiB0aGVcbiAgICAgICAgICogbWVudSBpdGVtcyB3aWxsIHdyYXAgZm9jdXMgYmFjayB0byB0aGUgYmVnaW5uaW5nIGFuZCB2aWNlIHZlcnNhLiBVc2UgdGhpc1xuICAgICAgICAgKiBmb3IgQVJJQSBwYXR0ZXJucyB0aGF0IGRvIG5vdCB3cmFwIGZvY3VzLCBsaWtlIGNvbWJvYm94LlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5ub05hdmlnYXRpb25XcmFwID0gZmFsc2U7XG4gICAgICAgIHRoaXMudHlwZWFoZWFkQWN0aXZlID0gdHJ1ZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdoZXRoZXIgb3Igbm90IHRoZSBjdXJyZW50IG1lbnUgaXMgYSBzdWJtZW51IGFuZCBzaG91bGQgbm90IGhhbmRsZSBzcGVjaWZpY1xuICAgICAgICAgKiBuYXZpZ2F0aW9uIGtleXMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBleHBvcnRcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaXNTdWJtZW51ID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgZXZlbnQgcGF0aCBvZiB0aGUgbGFzdCB3aW5kb3cgcG9pbnRlcmRvd24gZXZlbnQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnBvaW50ZXJQYXRoID0gW107XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXaGV0aGVyIG9yIG5vdCB0aGUgbWVudSBpcyByZXBvc2l0b2luaW5nIGR1ZSB0byB3aW5kb3cgLyBkb2N1bWVudCByZXNpemVcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaXNSZXBvc2l0aW9uaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMub3BlbkNsb3NlQW5pbWF0aW9uU2lnbmFsID0gY3JlYXRlQW5pbWF0aW9uU2lnbmFsKCk7XG4gICAgICAgIHRoaXMubGlzdENvbnRyb2xsZXIgPSBuZXcgTGlzdENvbnRyb2xsZXIoe1xuICAgICAgICAgICAgaXNJdGVtOiAobWF5YmVJdGVtKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1heWJlSXRlbS5oYXNBdHRyaWJ1dGUoJ21kLW1lbnUtaXRlbScpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldFBvc3NpYmxlSXRlbXM6ICgpID0+IHRoaXMuc2xvdEl0ZW1zLFxuICAgICAgICAgICAgaXNSdGw6ICgpID0+IGdldENvbXB1dGVkU3R5bGUodGhpcykuZGlyZWN0aW9uID09PSAncnRsJyxcbiAgICAgICAgICAgIGRlYWN0aXZhdGVJdGVtOiAoaXRlbSkgPT4ge1xuICAgICAgICAgICAgICAgIGl0ZW0uc2VsZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBpdGVtLnRhYkluZGV4ID0gLTE7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYWN0aXZhdGVJdGVtOiAoaXRlbSkgPT4ge1xuICAgICAgICAgICAgICAgIGl0ZW0uc2VsZWN0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGl0ZW0udGFiSW5kZXggPSAwO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzTmF2aWdhYmxlS2V5OiAoa2V5KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzU3VibWVudSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWVudU5hdktleXMuaGFzKGtleSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGlzUnRsID0gZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzKS5kaXJlY3Rpb24gPT09ICdydGwnO1xuICAgICAgICAgICAgICAgIC8vIHdlIHdhbnQgbWQtc3VibWVudSB0byBoYW5kbGUgdGhlIHN1Ym1lbnUncyBsZWZ0L3JpZ2h0IGFycm93IGV4aXRcbiAgICAgICAgICAgICAgICAvLyBrZXkgc28gaXQgY2FuIGNsb3NlIHRoZSBtZW51IGluc3RlYWQgb2YgbmF2aWdhdGUgdGhlIGxpc3QuXG4gICAgICAgICAgICAgICAgLy8gVGhlcmVmb3JlIHdlIG5lZWQgdG8gaW5jbHVkZSBhbGwga2V5cyBidXQgbGVmdC9yaWdodCBhcnJvdyBjbG9zZVxuICAgICAgICAgICAgICAgIC8vIGtleVxuICAgICAgICAgICAgICAgIGNvbnN0IGFycm93T3BlbiA9IGlzUnRsXG4gICAgICAgICAgICAgICAgICAgID8gTmF2aWdhYmxlS2V5cy5BcnJvd0xlZnRcbiAgICAgICAgICAgICAgICAgICAgOiBOYXZpZ2FibGVLZXlzLkFycm93UmlnaHQ7XG4gICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gYXJyb3dPcGVuKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gc3VibWVudU5hdktleXMuaGFzKGtleSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgd3JhcE5hdmlnYXRpb246ICgpID0+ICF0aGlzLm5vTmF2aWdhdGlvbldyYXAsXG4gICAgICAgIH0pO1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIGVsZW1lbnQgdGhhdCB3YXMgZm9jdXNlZCBiZWZvcmUgdGhlIG1lbnUgb3BlbmVkLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5sYXN0Rm9jdXNlZEVsZW1lbnQgPSBudWxsO1xuICAgICAgICAvKipcbiAgICAgICAgICogSGFuZGxlcyB0eXBlYWhlYWQgbmF2aWdhdGlvbiB0aHJvdWdoIHRoZSBtZW51LlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy50eXBlYWhlYWRDb250cm9sbGVyID0gbmV3IFR5cGVhaGVhZENvbnRyb2xsZXIoKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBnZXRJdGVtczogKCkgPT4gdGhpcy5pdGVtcyxcbiAgICAgICAgICAgICAgICB0eXBlYWhlYWRCdWZmZXJUaW1lOiB0aGlzLnR5cGVhaGVhZERlbGF5LFxuICAgICAgICAgICAgICAgIGFjdGl2ZTogdGhpcy50eXBlYWhlYWRBY3RpdmUsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5jdXJyZW50QW5jaG9yRWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuaW50ZXJuYWxzID0gXG4gICAgICAgIC8vIENhc3QgbmVlZGVkIGZvciBjbG9zdXJlXG4gICAgICAgIHRoaXMuYXR0YWNoSW50ZXJuYWxzKCk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIYW5kbGVzIHBvc2l0aW9uaW5nIHRoZSBzdXJmYWNlIGFuZCBhbGlnbmluZyBpdCB0byB0aGUgYW5jaG9yIGFzIHdlbGwgYXNcbiAgICAgICAgICoga2VlcGluZyBpdCBpbiB0aGUgdmlld3BvcnQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLm1lbnVQb3NpdGlvbkNvbnRyb2xsZXIgPSBuZXcgU3VyZmFjZVBvc2l0aW9uQ29udHJvbGxlcih0aGlzLCAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGFuY2hvckNvcm5lcjogdGhpcy5hbmNob3JDb3JuZXIsXG4gICAgICAgICAgICAgICAgc3VyZmFjZUNvcm5lcjogdGhpcy5tZW51Q29ybmVyLFxuICAgICAgICAgICAgICAgIHN1cmZhY2VFbDogdGhpcy5zdXJmYWNlRWwsXG4gICAgICAgICAgICAgICAgYW5jaG9yRWw6IHRoaXMuYW5jaG9yRWxlbWVudCxcbiAgICAgICAgICAgICAgICBwb3NpdGlvbmluZzogdGhpcy5wb3NpdGlvbmluZyA9PT0gJ3BvcG92ZXInID8gJ2RvY3VtZW50JyA6IHRoaXMucG9zaXRpb25pbmcsXG4gICAgICAgICAgICAgICAgaXNPcGVuOiB0aGlzLm9wZW4sXG4gICAgICAgICAgICAgICAgeE9mZnNldDogdGhpcy54T2Zmc2V0LFxuICAgICAgICAgICAgICAgIHlPZmZzZXQ6IHRoaXMueU9mZnNldCxcbiAgICAgICAgICAgICAgICBkaXNhYmxlQmxvY2tGbGlwOiB0aGlzLm5vVmVydGljYWxGbGlwLFxuICAgICAgICAgICAgICAgIGRpc2FibGVJbmxpbmVGbGlwOiB0aGlzLm5vSG9yaXpvbnRhbEZsaXAsXG4gICAgICAgICAgICAgICAgb25PcGVuOiB0aGlzLm9uT3BlbmVkLFxuICAgICAgICAgICAgICAgIGJlZm9yZUNsb3NlOiB0aGlzLmJlZm9yZUNsb3NlLFxuICAgICAgICAgICAgICAgIG9uQ2xvc2U6IHRoaXMub25DbG9zZWQsXG4gICAgICAgICAgICAgICAgLy8gV2UgY2FuJ3QgcmVzaXplIGNvbXBvbmVudHMgdGhhdCBoYXZlIG92ZXJmbG93IGxpa2UgbWVudXMgd2l0aFxuICAgICAgICAgICAgICAgIC8vIHN1Ym1lbnVzIGJlY2F1c2UgdGhlIG92ZXJmbG93LXkgd2lsbCBzaG93IG1lbnUgaXRlbXMgLyBjb250ZW50XG4gICAgICAgICAgICAgICAgLy8gb3V0c2lkZSB0aGUgYm91bmRzIG9mIHRoZSBtZW51LiBQb3BvdmVyIEFQSSBmaXhlcyB0aGlzIGJlY2F1c2UgZWFjaFxuICAgICAgICAgICAgICAgIC8vIHN1Ym1lbnUgaXMgaG9pc3RlZCB0byB0aGUgdG9wLWxheWVyIGFuZCBhcmUgbm90IGNvbnNpZGVyZWQgb3ZlcmZsb3dcbiAgICAgICAgICAgICAgICAvLyBjb250ZW50LlxuICAgICAgICAgICAgICAgIHJlcG9zaXRpb25TdHJhdGVneTogdGhpcy5oYXNPdmVyZmxvdyAmJiB0aGlzLnBvc2l0aW9uaW5nICE9PSAncG9wb3ZlcidcbiAgICAgICAgICAgICAgICAgICAgPyAnbW92ZSdcbiAgICAgICAgICAgICAgICAgICAgOiAncmVzaXplJyxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLm9uV2luZG93UmVzaXplID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaXNSZXBvc2l0aW9uaW5nIHx8XG4gICAgICAgICAgICAgICAgKHRoaXMucG9zaXRpb25pbmcgIT09ICdkb2N1bWVudCcgJiZcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wb3NpdGlvbmluZyAhPT0gJ2ZpeGVkJyAmJlxuICAgICAgICAgICAgICAgICAgICB0aGlzLnBvc2l0aW9uaW5nICE9PSAncG9wb3ZlcicpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5pc1JlcG9zaXRpb25pbmcgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5yZXBvc2l0aW9uKCk7XG4gICAgICAgICAgICB0aGlzLmlzUmVwb3NpdGlvbmluZyA9IGZhbHNlO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZUZvY3Vzb3V0ID0gYXN5bmMgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBhbmNob3JFbCA9IHRoaXMuYW5jaG9yRWxlbWVudDtcbiAgICAgICAgICAgIC8vIERvIG5vdCBjbG9zZSBpZiB3ZSBmb2N1c2VkIG91dCBieSBjbGlja2luZyBvbiB0aGUgYW5jaG9yIGVsZW1lbnQuIFdlXG4gICAgICAgICAgICAvLyBjYW4ndCBhc3N1bWUgYW5jaG9yIGJ1dHRvbnMgY2FuIGJlIHRoZSByZWxhdGVkIHRhcmdldCBiZWNhdXNlIG9mIGlPUyBkb2VzXG4gICAgICAgICAgICAvLyBub3QgZm9jdXMgYnV0dG9ucy5cbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXlPcGVuT25Gb2N1c291dCB8fFxuICAgICAgICAgICAgICAgICF0aGlzLm9wZW4gfHxcbiAgICAgICAgICAgICAgICB0aGlzLnBvaW50ZXJQYXRoLmluY2x1ZGVzKGFuY2hvckVsKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChldmVudC5yZWxhdGVkVGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgLy8gRG9uJ3QgY2xvc2UgdGhlIG1lbnUgaWYgd2UgYXJlIHN3aXRjaGluZyBmb2N1cyBiZXR3ZWVuIG1lbnUsXG4gICAgICAgICAgICAgICAgLy8gbWQtbWVudS1pdGVtLCBhbmQgbWQtbGlzdCBvciBpZiB0aGUgYW5jaG9yIHdhcyBjbGljayBmb2N1c2VkLCBidXQgY2hlY2tcbiAgICAgICAgICAgICAgICAvLyBpZiBsZW5ndGggb2YgcG9pbnRlclBhdGggaXMgMCBiZWNhdXNlIHRoYXQgbWVhbnMgc29tZXRoaW5nIHdhcyBhdCBsZWFzdFxuICAgICAgICAgICAgICAgIC8vIGNsaWNrZWQgKHNoaWZ0K3RhYiBjYXNlKS5cbiAgICAgICAgICAgICAgICBpZiAoaXNFbGVtZW50SW5TdWJ0cmVlKGV2ZW50LnJlbGF0ZWRUYXJnZXQsIHRoaXMpIHx8XG4gICAgICAgICAgICAgICAgICAgICh0aGlzLnBvaW50ZXJQYXRoLmxlbmd0aCAhPT0gMCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgaXNFbGVtZW50SW5TdWJ0cmVlKGV2ZW50LnJlbGF0ZWRUYXJnZXQsIGFuY2hvckVsKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMucG9pbnRlclBhdGguaW5jbHVkZXModGhpcykpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBtZW51IHRhYmluZGV4ID09IC0xIGFuZCB0aGUgdXNlciBjbGlja3Mgb24gdGhlIG1lbnUgb3IgYSBkaXZpZGVyLCB3ZVxuICAgICAgICAgICAgICAgIC8vIHdhbnQgdG8ga2VlcCB0aGUgbWVudSBvcGVuLlxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG9sZFJlc3RvcmVGb2N1cyA9IHRoaXMuc2tpcFJlc3RvcmVGb2N1cztcbiAgICAgICAgICAgIC8vIGFsbG93IGZvY3VzIHRvIGNvbnRpbnVlIHRvIHRoZSBuZXh0IGZvY3VzZWQgb2JqZWN0IHJhdGhlciB0aGFuIHJldHVybmluZ1xuICAgICAgICAgICAgdGhpcy5za2lwUmVzdG9yZUZvY3VzID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICAgICAgICAgIC8vIGF3YWl0IGZvciBjbG9zZVxuICAgICAgICAgICAgYXdhaXQgdGhpcy51cGRhdGVDb21wbGV0ZTtcbiAgICAgICAgICAgIC8vIHJldHVybiB0byBwcmV2aW91cyBiZWhhdmlvclxuICAgICAgICAgICAgdGhpcy5za2lwUmVzdG9yZUZvY3VzID0gb2xkUmVzdG9yZUZvY3VzO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogU2F2ZXMgdGhlIGxhc3QgZm9jdXNlZCBlbGVtZW50IGZvY3VzZXMgdGhlIG5ldyBlbGVtZW50IGJhc2VkIG9uXG4gICAgICAgICAqIGBkZWZhdWx0Rm9jdXNgLCBhbmQgYW5pbWF0ZXMgb3Blbi5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMub25PcGVuZWQgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmxhc3RGb2N1c2VkRWxlbWVudCA9IGdldEZvY3VzZWRFbGVtZW50KCk7XG4gICAgICAgICAgICBjb25zdCBpdGVtcyA9IHRoaXMuaXRlbXM7XG4gICAgICAgICAgICBjb25zdCBhY3RpdmVJdGVtUmVjb3JkID0gZ2V0QWN0aXZlSXRlbShpdGVtcyk7XG4gICAgICAgICAgICBpZiAoYWN0aXZlSXRlbVJlY29yZCAmJiB0aGlzLmRlZmF1bHRGb2N1cyAhPT0gRm9jdXNTdGF0ZS5OT05FKSB7XG4gICAgICAgICAgICAgICAgYWN0aXZlSXRlbVJlY29yZC5pdGVtLnRhYkluZGV4ID0gLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgYW5pbWF0aW9uQWJvcnRlZCA9ICF0aGlzLnF1aWNrO1xuICAgICAgICAgICAgaWYgKHRoaXMucXVpY2spIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdvcGVuaW5nJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYW5pbWF0aW9uQWJvcnRlZCA9ICEhKGF3YWl0IHRoaXMuYW5pbWF0ZU9wZW4oKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBUaGlzIG11c3QgY29tZSBhZnRlciB0aGUgb3BlbmluZyBhbmltYXRpb24gb3IgZWxzZSBpdCBtYXkgZm9jdXMgb25lIG9mXG4gICAgICAgICAgICAvLyB0aGUgaXRlbXMgYmVmb3JlIHRoZSBhbmltYXRpb24gaGFzIGJlZ3VuIGFuZCBjYXVzZXMgdGhlIGxpc3QgdG8gc2xpZGVcbiAgICAgICAgICAgIC8vIChibG9jay1wYWRkaW5nLW9mLXRoZS1tZW51KXB4IGF0IHRoZSBlbmQgb2YgdGhlIGFuaW1hdGlvblxuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRlZmF1bHRGb2N1cykge1xuICAgICAgICAgICAgICAgIGNhc2UgRm9jdXNTdGF0ZS5GSVJTVF9JVEVNOlxuICAgICAgICAgICAgICAgICAgICBjb25zdCBmaXJzdCA9IGdldEZpcnN0QWN0aXZhdGFibGVJdGVtKGl0ZW1zKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZpcnN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaXJzdC50YWJJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaXJzdC5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgZmlyc3QudXBkYXRlQ29tcGxldGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBGb2N1c1N0YXRlLkxBU1RfSVRFTTpcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGFzdCA9IGdldExhc3RBY3RpdmF0YWJsZUl0ZW0oaXRlbXMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAobGFzdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdC50YWJJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0LmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBsYXN0LnVwZGF0ZUNvbXBsZXRlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgRm9jdXNTdGF0ZS5MSVNUX1JPT1Q6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBjYXNlIEZvY3VzU3RhdGUuTk9ORTpcbiAgICAgICAgICAgICAgICAgICAgLy8gRG8gbm90aGluZy5cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWFuaW1hdGlvbkFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdvcGVuZWQnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBbmltYXRlcyBjbG9zZWQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmJlZm9yZUNsb3NlID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5vcGVuID0gZmFsc2U7XG4gICAgICAgICAgICBpZiAoIXRoaXMuc2tpcFJlc3RvcmVGb2N1cykge1xuICAgICAgICAgICAgICAgIHRoaXMubGFzdEZvY3VzZWRFbGVtZW50Py5mb2N1cz8uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMucXVpY2spIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmFuaW1hdGVDbG9zZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogRm9jdXNlcyB0aGUgbGFzdCBmb2N1c2VkIGVsZW1lbnQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLm9uQ2xvc2VkID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucXVpY2spIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdjbG9zaW5nJykpO1xuICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2Nsb3NlZCcpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5vbldpbmRvd1BvaW50ZXJkb3duID0gKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICB0aGlzLnBvaW50ZXJQYXRoID0gZXZlbnQuY29tcG9zZWRQYXRoKCk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXZSBjYW5ub3QgbGlzdGVuIHRvIHdpbmRvdyBjbGljayBiZWNhdXNlIFNhZmFyaSBvbiBpT1Mgd2lsbCBub3QgYnViYmxlIGFcbiAgICAgICAgICogY2xpY2sgZXZlbnQgb24gd2luZG93IGlmIHRoZSBpdGVtIGNsaWNrZWQgaXMgbm90IGEgXCJjbGlja2FibGVcIiBpdGVtIHN1Y2ggYXNcbiAgICAgICAgICogPGJvZHk+XG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLm9uRG9jdW1lbnRDbGljayA9IChldmVudCkgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLm9wZW4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBwYXRoID0gZXZlbnQuY29tcG9zZWRQYXRoKCk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuc3RheU9wZW5Pbk91dHNpZGVDbGljayAmJlxuICAgICAgICAgICAgICAgICFwYXRoLmluY2x1ZGVzKHRoaXMpICYmXG4gICAgICAgICAgICAgICAgIXBhdGguaW5jbHVkZXModGhpcy5hbmNob3JFbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIHRoaXMub3BlbiA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpZiAoIWlzU2VydmVyKSB7XG4gICAgICAgICAgICB0aGlzLmludGVybmFscy5yb2xlID0gJ21lbnUnO1xuICAgICAgICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5oYW5kbGVLZXlkb3duKTtcbiAgICAgICAgICAgIC8vIENhcHR1cmUgc28gdGhhdCB3ZSBjYW4gZ3JhYiB0aGUgZXZlbnQgYmVmb3JlIGl0IHJlYWNoZXMgdGhlIG1lbnUgaXRlbVxuICAgICAgICAgICAgLy8gaXN0ZWxmLiBTcGVjaWZpY2FsbHkgdXNlZnVsIGZvciB0aGUgY2FzZSB3aGVyZSB0eXBlYWhlYWQgZW5jb3VudGVycyBhXG4gICAgICAgICAgICAvLyBzcGFjZSBhbmQgd2UgZG9uJ3Qgd2FudCB0aGUgbWVudSBpdGVtIHRvIGNsb3NlIHRoZSBtZW51LlxuICAgICAgICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5jYXB0dXJlS2V5ZG93biwgeyBjYXB0dXJlOiB0cnVlIH0pO1xuICAgICAgICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdmb2N1c291dCcsIHRoaXMuaGFuZGxlRm9jdXNvdXQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoZSBtZW51IGl0ZW1zIGFzc29jaWF0ZWQgd2l0aCB0aGlzIG1lbnUuIFRoZSBpdGVtcyBtdXN0IGJlIGBNZW51SXRlbWBzIGFuZFxuICAgICAqIGhhdmUgYm90aCB0aGUgYG1kLW1lbnUtaXRlbWAgYW5kIGBtZC1saXN0LWl0ZW1gIGF0dHJpYnV0ZXMuXG4gICAgICovXG4gICAgZ2V0IGl0ZW1zKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5saXN0Q29udHJvbGxlci5pdGVtcztcbiAgICB9XG4gICAgd2lsbFVwZGF0ZShjaGFuZ2VkKSB7XG4gICAgICAgIGlmICghY2hhbmdlZC5oYXMoJ29wZW4nKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLm9wZW4pIHtcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKCdhcmlhLWhpZGRlbicpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsICd0cnVlJyk7XG4gICAgfVxuICAgIHVwZGF0ZShjaGFuZ2VkKSB7XG4gICAgICAgIGlmIChjaGFuZ2VkLmhhcygnb3BlbicpKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5vcGVuKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRVcEdsb2JhbEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsZWFuVXBHbG9iYWxFdmVudExpc3RlbmVycygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIEZpcmVmb3ggZG9lcyBub3Qgc3VwcG9ydCBwb3BvdmVyLiBGYWxsLWJhY2sgdG8gdXNpbmcgZml4ZWQuXG4gICAgICAgIGlmIChjaGFuZ2VkLmhhcygncG9zaXRpb25pbmcnKSAmJlxuICAgICAgICAgICAgdGhpcy5wb3NpdGlvbmluZyA9PT0gJ3BvcG92ZXInICYmXG4gICAgICAgICAgICAvLyB0eXBlIHJlcXVpcmVkIGZvciBHb29nbGUgSlMgY29uZm9ybWFuY2VcbiAgICAgICAgICAgICF0aGlzLnNob3dQb3BvdmVyKSB7XG4gICAgICAgICAgICB0aGlzLnBvc2l0aW9uaW5nID0gJ2ZpeGVkJztcbiAgICAgICAgfVxuICAgICAgICBzdXBlci51cGRhdGUoY2hhbmdlZCk7XG4gICAgfVxuICAgIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgICAgICBzdXBlci5jb25uZWN0ZWRDYWxsYmFjaygpO1xuICAgICAgICBpZiAodGhpcy5vcGVuKSB7XG4gICAgICAgICAgICB0aGlzLnNldFVwR2xvYmFsRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICAgICAgc3VwZXIuZGlzY29ubmVjdGVkQ2FsbGJhY2soKTtcbiAgICAgICAgdGhpcy5jbGVhblVwR2xvYmFsRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICB9XG4gICAgZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkge1xuICAgICAgICBpZiAoIXRoaXMuc3VyZmFjZUVsKSB7XG4gICAgICAgICAgICByZXR1cm4gc3VwZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuc3VyZmFjZUVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIH1cbiAgICBnZXRDbGllbnRSZWN0cygpIHtcbiAgICAgICAgaWYgKCF0aGlzLnN1cmZhY2VFbCkge1xuICAgICAgICAgICAgcmV0dXJuIHN1cGVyLmdldENsaWVudFJlY3RzKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuc3VyZmFjZUVsLmdldENsaWVudFJlY3RzKCk7XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVuZGVyU3VyZmFjZSgpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBwb3NpdGlvbmFibGUgc3VyZmFjZSBlbGVtZW50IGFuZCBpdHMgY29udGVudHMuXG4gICAgICovXG4gICAgcmVuZGVyU3VyZmFjZSgpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYFxuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cIm1lbnUgJHtjbGFzc01hcCh0aGlzLmdldFN1cmZhY2VDbGFzc2VzKCkpfVwiXG4gICAgICAgIHN0eWxlPSR7c3R5bGVNYXAodGhpcy5tZW51UG9zaXRpb25Db250cm9sbGVyLnN1cmZhY2VTdHlsZXMpfVxuICAgICAgICBwb3BvdmVyPSR7dGhpcy5wb3NpdGlvbmluZyA9PT0gJ3BvcG92ZXInID8gJ21hbnVhbCcgOiBub3RoaW5nfT5cbiAgICAgICAgJHt0aGlzLnJlbmRlckVsZXZhdGlvbigpfVxuICAgICAgICA8ZGl2IGNsYXNzPVwiaXRlbXNcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiaXRlbS1wYWRkaW5nXCI+ICR7dGhpcy5yZW5kZXJNZW51SXRlbXMoKX0gPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgYDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgbWVudSBpdGVtcycgc2xvdFxuICAgICAqL1xuICAgIHJlbmRlck1lbnVJdGVtcygpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYDxzbG90XG4gICAgICBAY2xvc2UtbWVudT0ke3RoaXMub25DbG9zZU1lbnV9XG4gICAgICBAZGVhY3RpdmF0ZS1pdGVtcz0ke3RoaXMub25EZWFjdGl2YXRlSXRlbXN9XG4gICAgICBAcmVxdWVzdC1hY3RpdmF0aW9uPSR7dGhpcy5vblJlcXVlc3RBY3RpdmF0aW9ufVxuICAgICAgQGRlYWN0aXZhdGUtdHlwZWFoZWFkPSR7dGhpcy5oYW5kbGVEZWFjdGl2YXRlVHlwZWFoZWFkfVxuICAgICAgQGFjdGl2YXRlLXR5cGVhaGVhZD0ke3RoaXMuaGFuZGxlQWN0aXZhdGVUeXBlYWhlYWR9XG4gICAgICBAc3RheS1vcGVuLW9uLWZvY3Vzb3V0PSR7dGhpcy5oYW5kbGVTdGF5T3Blbk9uRm9jdXNvdXR9XG4gICAgICBAY2xvc2Utb24tZm9jdXNvdXQ9JHt0aGlzLmhhbmRsZUNsb3NlT25Gb2N1c291dH1cbiAgICAgIEBzbG90Y2hhbmdlPSR7dGhpcy5saXN0Q29udHJvbGxlci5vblNsb3RjaGFuZ2V9Pjwvc2xvdD5gO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZW5kZXJzIHRoZSBlbGV2YXRpb24gY29tcG9uZW50LlxuICAgICAqL1xuICAgIHJlbmRlckVsZXZhdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYDxtZC1lbGV2YXRpb24gcGFydD1cImVsZXZhdGlvblwiPjwvbWQtZWxldmF0aW9uPmA7XG4gICAgfVxuICAgIGdldFN1cmZhY2VDbGFzc2VzKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgb3BlbjogdGhpcy5vcGVuLFxuICAgICAgICAgICAgZml4ZWQ6IHRoaXMucG9zaXRpb25pbmcgPT09ICdmaXhlZCcsXG4gICAgICAgICAgICAnaGFzLW92ZXJmbG93JzogdGhpcy5oYXNPdmVyZmxvdyxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgY2FwdHVyZUtleWRvd24oZXZlbnQpIHtcbiAgICAgICAgaWYgKGV2ZW50LnRhcmdldCA9PT0gdGhpcyAmJlxuICAgICAgICAgICAgIWV2ZW50LmRlZmF1bHRQcmV2ZW50ZWQgJiZcbiAgICAgICAgICAgIGlzQ2xvc2FibGVLZXkoZXZlbnQuY29kZSkpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB0aGlzLmNsb3NlKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy50eXBlYWhlYWRDb250cm9sbGVyLm9uS2V5ZG93bihldmVudCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFBlcmZvcm1zIHRoZSBvcGVuaW5nIGFuaW1hdGlvbjpcbiAgICAgKlxuICAgICAqIGh0dHBzOi8vZGlyZWN0Lmdvb2dsZXBsZXguY29tLyMvc3BlYy8yOTUwMDAwMDMrMjcxMDYwMDAzXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIEEgcHJvbWlzZSB0aGF0IHJlc29sdmUgdG8gYHRydWVgIGlmIHRoZSBhbmltYXRpb24gd2FzIGFib3J0ZWQsXG4gICAgICogICAgIGBmYWxzZWAgaWYgaXQgd2FzIG5vdCBhYm9ydGVkLlxuICAgICAqL1xuICAgIGFzeW5jIGFuaW1hdGVPcGVuKCkge1xuICAgICAgICBjb25zdCBzdXJmYWNlRWwgPSB0aGlzLnN1cmZhY2VFbDtcbiAgICAgICAgY29uc3Qgc2xvdEVsID0gdGhpcy5zbG90RWw7XG4gICAgICAgIGlmICghc3VyZmFjZUVsIHx8ICFzbG90RWwpXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgY29uc3Qgb3BlbkRpcmVjdGlvbiA9IHRoaXMub3BlbkRpcmVjdGlvbjtcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudCgnb3BlbmluZycpKTtcbiAgICAgICAgLy8gbmVlZHMgdG8gYmUgaW1wZXJhdGl2ZSBiZWNhdXNlIHdlIGRvbid0IHdhbnQgdG8gbWl4IGFuaW1hdGlvbiBhbmQgTGl0XG4gICAgICAgIC8vIHJlbmRlciB0aW1pbmdcbiAgICAgICAgc3VyZmFjZUVsLmNsYXNzTGlzdC50b2dnbGUoJ2FuaW1hdGluZycsIHRydWUpO1xuICAgICAgICBjb25zdCBzaWduYWwgPSB0aGlzLm9wZW5DbG9zZUFuaW1hdGlvblNpZ25hbC5zdGFydCgpO1xuICAgICAgICBjb25zdCBoZWlnaHQgPSBzdXJmYWNlRWwub2Zmc2V0SGVpZ2h0O1xuICAgICAgICBjb25zdCBvcGVuaW5nVXB3YXJkcyA9IG9wZW5EaXJlY3Rpb24gPT09ICdVUCc7XG4gICAgICAgIGNvbnN0IGNoaWxkcmVuID0gdGhpcy5pdGVtcztcbiAgICAgICAgY29uc3QgRlVMTF9EVVJBVElPTiA9IDUwMDtcbiAgICAgICAgY29uc3QgU1VSRkFDRV9PUEFDSVRZX0RVUkFUSU9OID0gNTA7XG4gICAgICAgIGNvbnN0IElURU1fT1BBQ0lUWV9EVVJBVElPTiA9IDI1MDtcbiAgICAgICAgLy8gV2Ugd2FudCB0byBmaXQgZXZlcnkgY2hpbGQgZmFkZS1pbiBhbmltYXRpb24gd2l0aGluIHRoZSBmdWxsIGR1cmF0aW9uIG9mXG4gICAgICAgIC8vIHRoZSBhbmltYXRpb24uXG4gICAgICAgIGNvbnN0IERFTEFZX0JFVFdFRU5fSVRFTVMgPSAoRlVMTF9EVVJBVElPTiAtIElURU1fT1BBQ0lUWV9EVVJBVElPTikgLyBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgIGNvbnN0IHN1cmZhY2VIZWlnaHRBbmltYXRpb24gPSBzdXJmYWNlRWwuYW5pbWF0ZShbeyBoZWlnaHQ6ICcwcHgnIH0sIHsgaGVpZ2h0OiBgJHtoZWlnaHR9cHhgIH1dLCB7XG4gICAgICAgICAgICBkdXJhdGlvbjogRlVMTF9EVVJBVElPTixcbiAgICAgICAgICAgIGVhc2luZzogRUFTSU5HLkVNUEhBU0laRUQsXG4gICAgICAgIH0pO1xuICAgICAgICAvLyBXaGVuIHdlIGFyZSBvcGVuaW5nIHVwd2FyZHMsIHdlIHdhbnQgdG8gbWFrZSBzdXJlIHRoZSBsYXN0IGl0ZW0gaXMgYWx3YXlzXG4gICAgICAgIC8vIGluIHZpZXcsIHNvIHdlIG5lZWQgdG8gdHJhbnNsYXRlIGl0IHVwd2FyZHMgdGhlIG9wcG9zaXRlIGRpcmVjdGlvbiBvZiB0aGVcbiAgICAgICAgLy8gaGVpZ2h0IGFuaW1hdGlvblxuICAgICAgICBjb25zdCB1cFBvc2l0aW9uQ29ycmVjdGlvbkFuaW1hdGlvbiA9IHNsb3RFbC5hbmltYXRlKFtcbiAgICAgICAgICAgIHsgdHJhbnNmb3JtOiBvcGVuaW5nVXB3YXJkcyA/IGB0cmFuc2xhdGVZKC0ke2hlaWdodH1weClgIDogJycgfSxcbiAgICAgICAgICAgIHsgdHJhbnNmb3JtOiAnJyB9LFxuICAgICAgICBdLCB7IGR1cmF0aW9uOiBGVUxMX0RVUkFUSU9OLCBlYXNpbmc6IEVBU0lORy5FTVBIQVNJWkVEIH0pO1xuICAgICAgICBjb25zdCBzdXJmYWNlT3BhY2l0eUFuaW1hdGlvbiA9IHN1cmZhY2VFbC5hbmltYXRlKFt7IG9wYWNpdHk6IDAgfSwgeyBvcGFjaXR5OiAxIH1dLCBTVVJGQUNFX09QQUNJVFlfRFVSQVRJT04pO1xuICAgICAgICBjb25zdCBjaGlsZHJlbkFuaW1hdGlvbnMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgLy8gSWYgd2UgYXJlIGFuaW1hdGluZyB1cHdhcmRzLCB0aGVuIHJldmVyc2UgdGhlIGNoaWxkcmVuIGxpc3QuXG4gICAgICAgICAgICBjb25zdCBkaXJlY3Rpb25hbEluZGV4ID0gb3BlbmluZ1Vwd2FyZHMgPyBjaGlsZHJlbi5sZW5ndGggLSAxIC0gaSA6IGk7XG4gICAgICAgICAgICBjb25zdCBjaGlsZCA9IGNoaWxkcmVuW2RpcmVjdGlvbmFsSW5kZXhdO1xuICAgICAgICAgICAgY29uc3QgYW5pbWF0aW9uID0gY2hpbGQuYW5pbWF0ZShbeyBvcGFjaXR5OiAwIH0sIHsgb3BhY2l0eTogMSB9XSwge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiBJVEVNX09QQUNJVFlfRFVSQVRJT04sXG4gICAgICAgICAgICAgICAgZGVsYXk6IERFTEFZX0JFVFdFRU5fSVRFTVMgKiBpLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAvLyBNYWtlIHRoZW0gYWxsIGluaXRpYWxseSBoaWRkZW4gYW5kIHRoZW4gY2xlYW4gdXAgYXQgdGhlIGVuZCBvZiBlYWNoXG4gICAgICAgICAgICAvLyBhbmltYXRpb24uXG4gICAgICAgICAgICBjaGlsZC5jbGFzc0xpc3QudG9nZ2xlKCdtZC1tZW51LWhpZGRlbicsIHRydWUpO1xuICAgICAgICAgICAgYW5pbWF0aW9uLmFkZEV2ZW50TGlzdGVuZXIoJ2ZpbmlzaCcsICgpID0+IHtcbiAgICAgICAgICAgICAgICBjaGlsZC5jbGFzc0xpc3QudG9nZ2xlKCdtZC1tZW51LWhpZGRlbicsIGZhbHNlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY2hpbGRyZW5BbmltYXRpb25zLnB1c2goW2NoaWxkLCBhbmltYXRpb25dKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcmVzb2x2ZUFuaW1hdGlvbiA9ICh2YWx1ZSkgPT4geyB9O1xuICAgICAgICBjb25zdCBhbmltYXRpb25GaW5pc2hlZCA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlQW5pbWF0aW9uID0gcmVzb2x2ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKCdhYm9ydCcsICgpID0+IHtcbiAgICAgICAgICAgIHN1cmZhY2VIZWlnaHRBbmltYXRpb24uY2FuY2VsKCk7XG4gICAgICAgICAgICB1cFBvc2l0aW9uQ29ycmVjdGlvbkFuaW1hdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgIHN1cmZhY2VPcGFjaXR5QW5pbWF0aW9uLmNhbmNlbCgpO1xuICAgICAgICAgICAgY2hpbGRyZW5BbmltYXRpb25zLmZvckVhY2goKFtjaGlsZCwgYW5pbWF0aW9uXSkgPT4ge1xuICAgICAgICAgICAgICAgIGNoaWxkLmNsYXNzTGlzdC50b2dnbGUoJ21kLW1lbnUtaGlkZGVuJywgZmFsc2UpO1xuICAgICAgICAgICAgICAgIGFuaW1hdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmVzb2x2ZUFuaW1hdGlvbih0cnVlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHN1cmZhY2VIZWlnaHRBbmltYXRpb24uYWRkRXZlbnRMaXN0ZW5lcignZmluaXNoJywgKCkgPT4ge1xuICAgICAgICAgICAgc3VyZmFjZUVsLmNsYXNzTGlzdC50b2dnbGUoJ2FuaW1hdGluZycsIGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMub3BlbkNsb3NlQW5pbWF0aW9uU2lnbmFsLmZpbmlzaCgpO1xuICAgICAgICAgICAgcmVzb2x2ZUFuaW1hdGlvbihmYWxzZSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gYXdhaXQgYW5pbWF0aW9uRmluaXNoZWQ7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFBlcmZvcm1zIHRoZSBjbG9zaW5nIGFuaW1hdGlvbjpcbiAgICAgKlxuICAgICAqIGh0dHBzOi8vZGlyZWN0Lmdvb2dsZXBsZXguY29tLyMvc3BlYy8yOTUwMDAwMDMrMjcxMDYwMDAzXG4gICAgICovXG4gICAgYW5pbWF0ZUNsb3NlKCkge1xuICAgICAgICBsZXQgcmVzb2x2ZTtcbiAgICAgICAgLy8gVGhpcyBwcm9taXNlIGJsb2NrcyB0aGUgc3VyZmFjZSBwb3NpdGlvbiBjb250cm9sbGVyIGZyb20gc2V0dGluZ1xuICAgICAgICAvLyBkaXNwbGF5OiBub25lIG9uIHRoZSBzdXJmYWNlIHdoaWNoIHdpbGwgaW50ZXJmZXJlIHdpdGggdGhpcyBhbmltYXRpb24uXG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbkVuZGVkID0gbmV3IFByb21pc2UoKHJlcykgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZSA9IHJlcztcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHN1cmZhY2VFbCA9IHRoaXMuc3VyZmFjZUVsO1xuICAgICAgICBjb25zdCBzbG90RWwgPSB0aGlzLnNsb3RFbDtcbiAgICAgICAgaWYgKCFzdXJmYWNlRWwgfHwgIXNsb3RFbCkge1xuICAgICAgICAgICAgcmVzb2x2ZShmYWxzZSk7XG4gICAgICAgICAgICByZXR1cm4gYW5pbWF0aW9uRW5kZWQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgb3BlbkRpcmVjdGlvbiA9IHRoaXMub3BlbkRpcmVjdGlvbjtcbiAgICAgICAgY29uc3QgY2xvc2luZ0Rvd253YXJkcyA9IG9wZW5EaXJlY3Rpb24gPT09ICdVUCc7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2Nsb3NpbmcnKSk7XG4gICAgICAgIC8vIG5lZWRzIHRvIGJlIGltcGVyYXRpdmUgYmVjYXVzZSB3ZSBkb24ndCB3YW50IHRvIG1peCBhbmltYXRpb24gYW5kIExpdFxuICAgICAgICAvLyByZW5kZXIgdGltaW5nXG4gICAgICAgIHN1cmZhY2VFbC5jbGFzc0xpc3QudG9nZ2xlKCdhbmltYXRpbmcnLCB0cnVlKTtcbiAgICAgICAgY29uc3Qgc2lnbmFsID0gdGhpcy5vcGVuQ2xvc2VBbmltYXRpb25TaWduYWwuc3RhcnQoKTtcbiAgICAgICAgY29uc3QgaGVpZ2h0ID0gc3VyZmFjZUVsLm9mZnNldEhlaWdodDtcbiAgICAgICAgY29uc3QgY2hpbGRyZW4gPSB0aGlzLml0ZW1zO1xuICAgICAgICBjb25zdCBGVUxMX0RVUkFUSU9OID0gMTUwO1xuICAgICAgICBjb25zdCBTVVJGQUNFX09QQUNJVFlfRFVSQVRJT04gPSA1MDtcbiAgICAgICAgLy8gVGhlIHN1cmZhY2UgZmFkZXMgYXdheSBhdCB0aGUgdmVyeSBlbmRcbiAgICAgICAgY29uc3QgU1VSRkFDRV9PUEFDSVRZX0RFTEFZID0gRlVMTF9EVVJBVElPTiAtIFNVUkZBQ0VfT1BBQ0lUWV9EVVJBVElPTjtcbiAgICAgICAgY29uc3QgSVRFTV9PUEFDSVRZX0RVUkFUSU9OID0gNTA7XG4gICAgICAgIGNvbnN0IElURU1fT1BBQ0lUWV9JTklUSUFMX0RFTEFZID0gNTA7XG4gICAgICAgIGNvbnN0IEVORF9IRUlHSFRfUEVSQ0VOVEFHRSA9IDAuMzU7XG4gICAgICAgIC8vIFdlIHdhbnQgdG8gZml0IGV2ZXJ5IGNoaWxkIGZhZGUtb3V0IGFuaW1hdGlvbiB3aXRoaW4gdGhlIGZ1bGwgZHVyYXRpb24gb2ZcbiAgICAgICAgLy8gdGhlIGFuaW1hdGlvbi5cbiAgICAgICAgY29uc3QgREVMQVlfQkVUV0VFTl9JVEVNUyA9IChGVUxMX0RVUkFUSU9OIC0gSVRFTV9PUEFDSVRZX0lOSVRJQUxfREVMQVkgLSBJVEVNX09QQUNJVFlfRFVSQVRJT04pIC9cbiAgICAgICAgICAgIGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgLy8gVGhlIG1vY2sgaGFzIHRoZSBhbmltYXRpb24gc2hyaW5rIHRvIDM1JVxuICAgICAgICBjb25zdCBzdXJmYWNlSGVpZ2h0QW5pbWF0aW9uID0gc3VyZmFjZUVsLmFuaW1hdGUoW1xuICAgICAgICAgICAgeyBoZWlnaHQ6IGAke2hlaWdodH1weGAgfSxcbiAgICAgICAgICAgIHsgaGVpZ2h0OiBgJHtoZWlnaHQgKiBFTkRfSEVJR0hUX1BFUkNFTlRBR0V9cHhgIH0sXG4gICAgICAgIF0sIHtcbiAgICAgICAgICAgIGR1cmF0aW9uOiBGVUxMX0RVUkFUSU9OLFxuICAgICAgICAgICAgZWFzaW5nOiBFQVNJTkcuRU1QSEFTSVpFRF9BQ0NFTEVSQVRFLFxuICAgICAgICB9KTtcbiAgICAgICAgLy8gV2hlbiB3ZSBhcmUgY2xvc2luZyBkb3dud2FyZHMsIHdlIHdhbnQgdG8gbWFrZSBzdXJlIHRoZSBsYXN0IGl0ZW0gaXNcbiAgICAgICAgLy8gYWx3YXlzIGluIHZpZXcsIHNvIHdlIG5lZWQgdG8gdHJhbnNsYXRlIGl0IHVwd2FyZHMgdGhlIG9wcG9zaXRlIGRpcmVjdGlvblxuICAgICAgICAvLyBvZiB0aGUgaGVpZ2h0IGFuaW1hdGlvblxuICAgICAgICBjb25zdCBkb3duUG9zaXRpb25Db3JyZWN0aW9uQW5pbWF0aW9uID0gc2xvdEVsLmFuaW1hdGUoW1xuICAgICAgICAgICAgeyB0cmFuc2Zvcm06ICcnIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiBjbG9zaW5nRG93bndhcmRzXG4gICAgICAgICAgICAgICAgICAgID8gYHRyYW5zbGF0ZVkoLSR7aGVpZ2h0ICogKDEgLSBFTkRfSEVJR0hUX1BFUkNFTlRBR0UpfXB4KWBcbiAgICAgICAgICAgICAgICAgICAgOiAnJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIF0sIHsgZHVyYXRpb246IEZVTExfRFVSQVRJT04sIGVhc2luZzogRUFTSU5HLkVNUEhBU0laRURfQUNDRUxFUkFURSB9KTtcbiAgICAgICAgY29uc3Qgc3VyZmFjZU9wYWNpdHlBbmltYXRpb24gPSBzdXJmYWNlRWwuYW5pbWF0ZShbeyBvcGFjaXR5OiAxIH0sIHsgb3BhY2l0eTogMCB9XSwgeyBkdXJhdGlvbjogU1VSRkFDRV9PUEFDSVRZX0RVUkFUSU9OLCBkZWxheTogU1VSRkFDRV9PUEFDSVRZX0RFTEFZIH0pO1xuICAgICAgICBjb25zdCBjaGlsZHJlbkFuaW1hdGlvbnMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgLy8gSWYgdGhlIGFuaW1hdGlvbiBpcyBjbG9zaW5nIHVwd2FyZHMsIHRoZW4gcmV2ZXJzZSB0aGUgbGlzdCBvZlxuICAgICAgICAgICAgLy8gY2hpbGRyZW4gc28gdGhhdCB3ZSBhbmltYXRlIGluIHRoZSBvcHBvc2l0ZSBkaXJlY3Rpb24uXG4gICAgICAgICAgICBjb25zdCBkaXJlY3Rpb25hbEluZGV4ID0gY2xvc2luZ0Rvd253YXJkcyA/IGkgOiBjaGlsZHJlbi5sZW5ndGggLSAxIC0gaTtcbiAgICAgICAgICAgIGNvbnN0IGNoaWxkID0gY2hpbGRyZW5bZGlyZWN0aW9uYWxJbmRleF07XG4gICAgICAgICAgICBjb25zdCBhbmltYXRpb24gPSBjaGlsZC5hbmltYXRlKFt7IG9wYWNpdHk6IDEgfSwgeyBvcGFjaXR5OiAwIH1dLCB7XG4gICAgICAgICAgICAgICAgZHVyYXRpb246IElURU1fT1BBQ0lUWV9EVVJBVElPTixcbiAgICAgICAgICAgICAgICBkZWxheTogSVRFTV9PUEFDSVRZX0lOSVRJQUxfREVMQVkgKyBERUxBWV9CRVRXRUVOX0lURU1TICogaSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHRoZSBpdGVtcyBzdGF5IGhpZGRlbiBhdCB0aGUgZW5kIG9mIGVhY2ggY2hpbGQgYW5pbWF0aW9uLlxuICAgICAgICAgICAgLy8gV2UgY2xlYW4gdGhpcyB1cCBhdCB0aGUgZW5kIG9mIHRoZSBvdmVyYWxsIGFuaW1hdGlvbi5cbiAgICAgICAgICAgIGFuaW1hdGlvbi5hZGRFdmVudExpc3RlbmVyKCdmaW5pc2gnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY2hpbGQuY2xhc3NMaXN0LnRvZ2dsZSgnbWQtbWVudS1oaWRkZW4nLCB0cnVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY2hpbGRyZW5BbmltYXRpb25zLnB1c2goW2NoaWxkLCBhbmltYXRpb25dKTtcbiAgICAgICAgfVxuICAgICAgICBzaWduYWwuYWRkRXZlbnRMaXN0ZW5lcignYWJvcnQnLCAoKSA9PiB7XG4gICAgICAgICAgICBzdXJmYWNlSGVpZ2h0QW5pbWF0aW9uLmNhbmNlbCgpO1xuICAgICAgICAgICAgZG93blBvc2l0aW9uQ29ycmVjdGlvbkFuaW1hdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgIHN1cmZhY2VPcGFjaXR5QW5pbWF0aW9uLmNhbmNlbCgpO1xuICAgICAgICAgICAgY2hpbGRyZW5BbmltYXRpb25zLmZvckVhY2goKFtjaGlsZCwgYW5pbWF0aW9uXSkgPT4ge1xuICAgICAgICAgICAgICAgIGFuaW1hdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICBjaGlsZC5jbGFzc0xpc3QudG9nZ2xlKCdtZC1tZW51LWhpZGRlbicsIGZhbHNlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmVzb2x2ZShmYWxzZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBzdXJmYWNlSGVpZ2h0QW5pbWF0aW9uLmFkZEV2ZW50TGlzdGVuZXIoJ2ZpbmlzaCcsICgpID0+IHtcbiAgICAgICAgICAgIHN1cmZhY2VFbC5jbGFzc0xpc3QudG9nZ2xlKCdhbmltYXRpbmcnLCBmYWxzZSk7XG4gICAgICAgICAgICBjaGlsZHJlbkFuaW1hdGlvbnMuZm9yRWFjaCgoW2NoaWxkXSkgPT4ge1xuICAgICAgICAgICAgICAgIGNoaWxkLmNsYXNzTGlzdC50b2dnbGUoJ21kLW1lbnUtaGlkZGVuJywgZmFsc2UpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLm9wZW5DbG9zZUFuaW1hdGlvblNpZ25hbC5maW5pc2goKTtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2Nsb3NlZCcpKTtcbiAgICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gYW5pbWF0aW9uRW5kZWQ7XG4gICAgfVxuICAgIGhhbmRsZUtleWRvd24oZXZlbnQpIHtcbiAgICAgICAgLy8gQXQgYW55IGtleSBldmVudCwgdGhlIHBvaW50ZXIgaW50ZXJhY3Rpb24gaXMgZG9uZSBzbyB3ZSBuZWVkIHRvIGNsZWFyIG91clxuICAgICAgICAvLyBjYWNoZWQgcG9pbnRlcnBhdGguIFRoaXMgaGFuZGxlcyB0aGUgY2FzZSB3aGVyZSB0aGUgdXNlciBjbGlja3Mgb24gdGhlXG4gICAgICAgIC8vIGFuY2hvciwgYW5kIHRoZW4gaGl0cyBzaGlmdCt0YWJcbiAgICAgICAgdGhpcy5wb2ludGVyUGF0aCA9IFtdO1xuICAgICAgICB0aGlzLmxpc3RDb250cm9sbGVyLmhhbmRsZUtleWRvd24oZXZlbnQpO1xuICAgIH1cbiAgICBzZXRVcEdsb2JhbEV2ZW50TGlzdGVuZXJzKCkge1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMub25Eb2N1bWVudENsaWNrLCB7IGNhcHR1cmU6IHRydWUgfSk7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVyZG93bicsIHRoaXMub25XaW5kb3dQb2ludGVyZG93bik7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMub25XaW5kb3dSZXNpemUsIHsgcGFzc2l2ZTogdHJ1ZSB9KTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMub25XaW5kb3dSZXNpemUsIHsgcGFzc2l2ZTogdHJ1ZSB9KTtcbiAgICB9XG4gICAgY2xlYW5VcEdsb2JhbEV2ZW50TGlzdGVuZXJzKCkge1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMub25Eb2N1bWVudENsaWNrLCB7XG4gICAgICAgICAgICBjYXB0dXJlOiB0cnVlLFxuICAgICAgICB9KTtcbiAgICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJkb3duJywgdGhpcy5vbldpbmRvd1BvaW50ZXJkb3duKTtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5vbldpbmRvd1Jlc2l6ZSk7XG4gICAgICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNpemUnLCB0aGlzLm9uV2luZG93UmVzaXplKTtcbiAgICB9XG4gICAgb25DbG9zZU1lbnUoKSB7XG4gICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICB9XG4gICAgb25EZWFjdGl2YXRlSXRlbXMoZXZlbnQpIHtcbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIHRoaXMubGlzdENvbnRyb2xsZXIub25EZWFjdGl2YXRlSXRlbXMoKTtcbiAgICB9XG4gICAgb25SZXF1ZXN0QWN0aXZhdGlvbihldmVudCkge1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgdGhpcy5saXN0Q29udHJvbGxlci5vblJlcXVlc3RBY3RpdmF0aW9uKGV2ZW50KTtcbiAgICB9XG4gICAgaGFuZGxlRGVhY3RpdmF0ZVR5cGVhaGVhZChldmVudCkge1xuICAgICAgICAvLyBzdG9wUHJvcGFnYXRpb24gc28gdGhhdCB0aGlzIGRvZXMgbm90IGRlYWN0aXZhdGUgYW55IHR5cGVhaGVhZHMgaW4gbWVudXNcbiAgICAgICAgLy8gbmVzdGVkIGFib3ZlIGl0IGUuZy4gbWQtc3ViLW1lbnVcbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIHRoaXMudHlwZWFoZWFkQWN0aXZlID0gZmFsc2U7XG4gICAgfVxuICAgIGhhbmRsZUFjdGl2YXRlVHlwZWFoZWFkKGV2ZW50KSB7XG4gICAgICAgIC8vIHN0b3BQcm9wYWdhdGlvbiBzbyB0aGF0IHRoaXMgZG9lcyBub3QgYWN0aXZhdGUgYW55IHR5cGVhaGVhZHMgaW4gbWVudXNcbiAgICAgICAgLy8gbmVzdGVkIGFib3ZlIGl0IGUuZy4gbWQtc3ViLW1lbnVcbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIHRoaXMudHlwZWFoZWFkQWN0aXZlID0gdHJ1ZTtcbiAgICB9XG4gICAgaGFuZGxlU3RheU9wZW5PbkZvY3Vzb3V0KGV2ZW50KSB7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICB0aGlzLnN0YXlPcGVuT25Gb2N1c291dCA9IHRydWU7XG4gICAgfVxuICAgIGhhbmRsZUNsb3NlT25Gb2N1c291dChldmVudCkge1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgdGhpcy5zdGF5T3Blbk9uRm9jdXNvdXQgPSBmYWxzZTtcbiAgICB9XG4gICAgY2xvc2UoKSB7XG4gICAgICAgIHRoaXMub3BlbiA9IGZhbHNlO1xuICAgICAgICBjb25zdCBtYXliZVN1Ym1lbnUgPSB0aGlzLnNsb3RJdGVtcztcbiAgICAgICAgbWF5YmVTdWJtZW51LmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgICAgICAgIGl0ZW0uY2xvc2U/LigpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgc2hvdygpIHtcbiAgICAgICAgdGhpcy5vcGVuID0gdHJ1ZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQWN0aXZhdGVzIHRoZSBuZXh0IGl0ZW0gaW4gdGhlIG1lbnUuIElmIGF0IHRoZSBlbmQgb2YgdGhlIG1lbnUsIHRoZSBmaXJzdFxuICAgICAqIGl0ZW0gd2lsbCBiZSBhY3RpdmF0ZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIFRoZSBhY3RpdmF0ZWQgbWVudSBpdGVtIG9yIGBudWxsYCBpZiB0aGVyZSBhcmUgbm8gaXRlbXMuXG4gICAgICovXG4gICAgYWN0aXZhdGVOZXh0SXRlbSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGlzdENvbnRyb2xsZXIuYWN0aXZhdGVOZXh0SXRlbSgpID8/IG51bGw7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFjdGl2YXRlcyB0aGUgcHJldmlvdXMgaXRlbSBpbiB0aGUgbWVudS4gSWYgYXQgdGhlIHN0YXJ0IG9mIHRoZSBtZW51LCB0aGVcbiAgICAgKiBsYXN0IGl0ZW0gd2lsbCBiZSBhY3RpdmF0ZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIFRoZSBhY3RpdmF0ZWQgbWVudSBpdGVtIG9yIGBudWxsYCBpZiB0aGVyZSBhcmUgbm8gaXRlbXMuXG4gICAgICovXG4gICAgYWN0aXZhdGVQcmV2aW91c0l0ZW0oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RDb250cm9sbGVyLmFjdGl2YXRlUHJldmlvdXNJdGVtKCkgPz8gbnVsbDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVwb3NpdGlvbnMgdGhlIG1lbnUgaWYgaXQgaXMgb3Blbi5cbiAgICAgKlxuICAgICAqIFVzZWZ1bCBmb3IgdGhlIGNhc2Ugd2hlcmUgZG9jdW1lbnQgb3Igd2luZG93LXBvc2l0aW9uZWQgbWVudXMgaGF2ZSB0aGVpclxuICAgICAqIGFuY2hvcnMgbW92ZWQgd2hpbGUgb3Blbi5cbiAgICAgKi9cbiAgICByZXBvc2l0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5vcGVuKSB7XG4gICAgICAgICAgICB0aGlzLm1lbnVQb3NpdGlvbkNvbnRyb2xsZXIucG9zaXRpb24oKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbl9fZGVjb3JhdGUoW1xuICAgIHF1ZXJ5KCcubWVudScpXG5dLCBNZW51LnByb3RvdHlwZSwgXCJzdXJmYWNlRWxcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHF1ZXJ5KCdzbG90Jylcbl0sIE1lbnUucHJvdG90eXBlLCBcInNsb3RFbFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoKVxuXSwgTWVudS5wcm90b3R5cGUsIFwiYW5jaG9yXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSgpXG5dLCBNZW51LnByb3RvdHlwZSwgXCJwb3NpdGlvbmluZ1wiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuIH0pXG5dLCBNZW51LnByb3RvdHlwZSwgXCJxdWlja1wiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCBhdHRyaWJ1dGU6ICdoYXMtb3ZlcmZsb3cnIH0pXG5dLCBNZW51LnByb3RvdHlwZSwgXCJoYXNPdmVyZmxvd1wiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCByZWZsZWN0OiB0cnVlIH0pXG5dLCBNZW51LnByb3RvdHlwZSwgXCJvcGVuXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IE51bWJlciwgYXR0cmlidXRlOiAneC1vZmZzZXQnIH0pXG5dLCBNZW51LnByb3RvdHlwZSwgXCJ4T2Zmc2V0XCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IE51bWJlciwgYXR0cmlidXRlOiAneS1vZmZzZXQnIH0pXG5dLCBNZW51LnByb3RvdHlwZSwgXCJ5T2Zmc2V0XCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IEJvb2xlYW4sIGF0dHJpYnV0ZTogJ25vLWhvcml6b250YWwtZmxpcCcgfSlcbl0sIE1lbnUucHJvdG90eXBlLCBcIm5vSG9yaXpvbnRhbEZsaXBcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgYXR0cmlidXRlOiAnbm8tdmVydGljYWwtZmxpcCcgfSlcbl0sIE1lbnUucHJvdG90eXBlLCBcIm5vVmVydGljYWxGbGlwXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IE51bWJlciwgYXR0cmlidXRlOiAndHlwZWFoZWFkLWRlbGF5JyB9KVxuXSwgTWVudS5wcm90b3R5cGUsIFwidHlwZWFoZWFkRGVsYXlcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgYXR0cmlidXRlOiAnYW5jaG9yLWNvcm5lcicgfSlcbl0sIE1lbnUucHJvdG90eXBlLCBcImFuY2hvckNvcm5lclwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyBhdHRyaWJ1dGU6ICdtZW51LWNvcm5lcicgfSlcbl0sIE1lbnUucHJvdG90eXBlLCBcIm1lbnVDb3JuZXJcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgYXR0cmlidXRlOiAnc3RheS1vcGVuLW9uLW91dHNpZGUtY2xpY2snIH0pXG5dLCBNZW51LnByb3RvdHlwZSwgXCJzdGF5T3Blbk9uT3V0c2lkZUNsaWNrXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IEJvb2xlYW4sIGF0dHJpYnV0ZTogJ3N0YXktb3Blbi1vbi1mb2N1c291dCcgfSlcbl0sIE1lbnUucHJvdG90eXBlLCBcInN0YXlPcGVuT25Gb2N1c291dFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCBhdHRyaWJ1dGU6ICdza2lwLXJlc3RvcmUtZm9jdXMnIH0pXG5dLCBNZW51LnByb3RvdHlwZSwgXCJza2lwUmVzdG9yZUZvY3VzXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ2RlZmF1bHQtZm9jdXMnIH0pXG5dLCBNZW51LnByb3RvdHlwZSwgXCJkZWZhdWx0Rm9jdXNcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgYXR0cmlidXRlOiAnbm8tbmF2aWdhdGlvbi13cmFwJyB9KVxuXSwgTWVudS5wcm90b3R5cGUsIFwibm9OYXZpZ2F0aW9uV3JhcFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcXVlcnlBc3NpZ25lZEVsZW1lbnRzKHsgZmxhdHRlbjogdHJ1ZSB9KVxuXSwgTWVudS5wcm90b3R5cGUsIFwic2xvdEl0ZW1zXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBzdGF0ZSgpXG5dLCBNZW51LnByb3RvdHlwZSwgXCJ0eXBlYWhlYWRBY3RpdmVcIiwgdm9pZCAwKTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPW1lbnUuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjQgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuLy8gR2VuZXJhdGVkIHN0eWxlc2hlZXQgZm9yIC4vbWVudS9pbnRlcm5hbC9tZW51aXRlbS9tZW51LWl0ZW0tc3R5bGVzLmNzcy5cbmltcG9ydCB7IGNzcyB9IGZyb20gJ2xpdCc7XG5leHBvcnQgY29uc3Qgc3R5bGVzID0gY3NzIGA6aG9zdHtkaXNwbGF5OmZsZXg7LS1tZC1yaXBwbGUtaG92ZXItY29sb3I6IHZhcigtLW1kLW1lbnUtaXRlbS1ob3Zlci1zdGF0ZS1sYXllci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLW1kLXJpcHBsZS1ob3Zlci1vcGFjaXR5OiB2YXIoLS1tZC1tZW51LWl0ZW0taG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eSwgMC4wOCk7LS1tZC1yaXBwbGUtcHJlc3NlZC1jb2xvcjogdmFyKC0tbWQtbWVudS1pdGVtLXByZXNzZWQtc3RhdGUtbGF5ZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1tZC1yaXBwbGUtcHJlc3NlZC1vcGFjaXR5OiB2YXIoLS1tZC1tZW51LWl0ZW0tcHJlc3NlZC1zdGF0ZS1sYXllci1vcGFjaXR5LCAwLjEyKX06aG9zdChbZGlzYWJsZWRdKXtvcGFjaXR5OnZhcigtLW1kLW1lbnUtaXRlbS1kaXNhYmxlZC1vcGFjaXR5LCAwLjMpO3BvaW50ZXItZXZlbnRzOm5vbmV9bWQtZm9jdXMtcmluZ3t6LWluZGV4OjE7LS1tZC1mb2N1cy1yaW5nLXNoYXBlOiA4cHh9YSxidXR0b24sbGl7YmFja2dyb3VuZDpub25lO2JvcmRlcjpub25lO3BhZGRpbmc6MDttYXJnaW46MDt0ZXh0LWFsaWduOnVuc2V0O3RleHQtZGVjb3JhdGlvbjpub25lfS5saXN0LWl0ZW17Ym9yZGVyLXJhZGl1czppbmhlcml0O2Rpc3BsYXk6ZmxleDtmbGV4OjE7bWF4LXdpZHRoOmluaGVyaXQ7bWluLXdpZHRoOmluaGVyaXQ7b3V0bGluZTpub25lOy13ZWJraXQtdGFwLWhpZ2hsaWdodC1jb2xvcjpyZ2JhKDAsMCwwLDApfS5saXN0LWl0ZW06bm90KC5kaXNhYmxlZCl7Y3Vyc29yOnBvaW50ZXJ9W3Nsb3Q9Y29udGFpbmVyXXtwb2ludGVyLWV2ZW50czpub25lfW1kLXJpcHBsZXtib3JkZXItcmFkaXVzOmluaGVyaXR9bWQtaXRlbXtib3JkZXItcmFkaXVzOmluaGVyaXQ7ZmxleDoxO2NvbG9yOnZhcigtLW1kLW1lbnUtaXRlbS1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpO2ZvbnQtZmFtaWx5OnZhcigtLW1kLW1lbnUtaXRlbS1sYWJlbC10ZXh0LWZvbnQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS1mb250LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2UtcGxhaW4sIFJvYm90bykpKTtmb250LXNpemU6dmFyKC0tbWQtbWVudS1pdGVtLWxhYmVsLXRleHQtc2l6ZSwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LWxhcmdlLXNpemUsIDFyZW0pKTtsaW5lLWhlaWdodDp2YXIoLS1tZC1tZW51LWl0ZW0tbGFiZWwtdGV4dC1saW5lLWhlaWdodCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LWxhcmdlLWxpbmUtaGVpZ2h0LCAxLjVyZW0pKTtmb250LXdlaWdodDp2YXIoLS1tZC1tZW51LWl0ZW0tbGFiZWwtdGV4dC13ZWlnaHQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS13ZWlnaHQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS13ZWlnaHQtcmVndWxhciwgNDAwKSkpO21pbi1oZWlnaHQ6dmFyKC0tbWQtbWVudS1pdGVtLW9uZS1saW5lLWNvbnRhaW5lci1oZWlnaHQsIDU2cHgpO3BhZGRpbmctdG9wOnZhcigtLW1kLW1lbnUtaXRlbS10b3Atc3BhY2UsIDEycHgpO3BhZGRpbmctYm90dG9tOnZhcigtLW1kLW1lbnUtaXRlbS1ib3R0b20tc3BhY2UsIDEycHgpO3BhZGRpbmctaW5saW5lLXN0YXJ0OnZhcigtLW1kLW1lbnUtaXRlbS1sZWFkaW5nLXNwYWNlLCAxNnB4KTtwYWRkaW5nLWlubGluZS1lbmQ6dmFyKC0tbWQtbWVudS1pdGVtLXRyYWlsaW5nLXNwYWNlLCAxNnB4KX1tZC1pdGVtW211bHRpbGluZV17bWluLWhlaWdodDp2YXIoLS1tZC1tZW51LWl0ZW0tdHdvLWxpbmUtY29udGFpbmVyLWhlaWdodCwgNzJweCl9W3Nsb3Q9c3VwcG9ydGluZy10ZXh0XXtjb2xvcjp2YXIoLS1tZC1tZW51LWl0ZW0tc3VwcG9ydGluZy10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7Zm9udC1mYW1pbHk6dmFyKC0tbWQtbWVudS1pdGVtLXN1cHBvcnRpbmctdGV4dC1mb250LCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbWVkaXVtLWZvbnQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS1wbGFpbiwgUm9ib3RvKSkpO2ZvbnQtc2l6ZTp2YXIoLS1tZC1tZW51LWl0ZW0tc3VwcG9ydGluZy10ZXh0LXNpemUsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1tZWRpdW0tc2l6ZSwgMC44NzVyZW0pKTtsaW5lLWhlaWdodDp2YXIoLS1tZC1tZW51LWl0ZW0tc3VwcG9ydGluZy10ZXh0LWxpbmUtaGVpZ2h0LCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbWVkaXVtLWxpbmUtaGVpZ2h0LCAxLjI1cmVtKSk7Zm9udC13ZWlnaHQ6dmFyKC0tbWQtbWVudS1pdGVtLXN1cHBvcnRpbmctdGV4dC13ZWlnaHQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1tZWRpdW0td2VpZ2h0LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2Utd2VpZ2h0LXJlZ3VsYXIsIDQwMCkpKX1bc2xvdD10cmFpbGluZy1zdXBwb3J0aW5nLXRleHRde2NvbG9yOnZhcigtLW1kLW1lbnUtaXRlbS10cmFpbGluZy1zdXBwb3J0aW5nLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTtmb250LWZhbWlseTp2YXIoLS1tZC1tZW51LWl0ZW0tdHJhaWxpbmctc3VwcG9ydGluZy10ZXh0LWZvbnQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtbGFiZWwtc21hbGwtZm9udCwgdmFyKC0tbWQtcmVmLXR5cGVmYWNlLXBsYWluLCBSb2JvdG8pKSk7Zm9udC1zaXplOnZhcigtLW1kLW1lbnUtaXRlbS10cmFpbGluZy1zdXBwb3J0aW5nLXRleHQtc2l6ZSwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1sYWJlbC1zbWFsbC1zaXplLCAwLjY4NzVyZW0pKTtsaW5lLWhlaWdodDp2YXIoLS1tZC1tZW51LWl0ZW0tdHJhaWxpbmctc3VwcG9ydGluZy10ZXh0LWxpbmUtaGVpZ2h0LCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWxhYmVsLXNtYWxsLWxpbmUtaGVpZ2h0LCAxcmVtKSk7Zm9udC13ZWlnaHQ6dmFyKC0tbWQtbWVudS1pdGVtLXRyYWlsaW5nLXN1cHBvcnRpbmctdGV4dC13ZWlnaHQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtbGFiZWwtc21hbGwtd2VpZ2h0LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2Utd2VpZ2h0LW1lZGl1bSwgNTAwKSkpfTppcyhbc2xvdD1zdGFydF0sW3Nsb3Q9ZW5kXSk6OnNsb3R0ZWQoKil7ZmlsbDpjdXJyZW50Q29sb3J9W3Nsb3Q9c3RhcnRde2NvbG9yOnZhcigtLW1kLW1lbnUtaXRlbS1sZWFkaW5nLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKX1bc2xvdD1lbmRde2NvbG9yOnZhcigtLW1kLW1lbnUtaXRlbS10cmFpbGluZy1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSl9Lmxpc3QtaXRlbXtiYWNrZ3JvdW5kLWNvbG9yOnZhcigtLW1kLW1lbnUtaXRlbS1jb250YWluZXItY29sb3IsIHRyYW5zcGFyZW50KX0ubGlzdC1pdGVtLnNlbGVjdGVke2JhY2tncm91bmQtY29sb3I6dmFyKC0tbWQtbWVudS1pdGVtLXNlbGVjdGVkLWNvbnRhaW5lci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXNlY29uZGFyeS1jb250YWluZXIsICNlOGRlZjgpKX0uc2VsZWN0ZWQ6bm90KC5kaXNhYmxlZCkgOjpzbG90dGVkKCope2NvbG9yOnZhcigtLW1kLW1lbnUtaXRlbS1zZWxlY3RlZC1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc2Vjb25kYXJ5LWNvbnRhaW5lciwgIzFkMTkyYikpfUBtZWRpYShmb3JjZWQtY29sb3JzOiBhY3RpdmUpezpob3N0KFtkaXNhYmxlZF0pLDpob3N0KFtkaXNhYmxlZF0pIHNsb3R7Y29sb3I6R3JheVRleHQ7b3BhY2l0eToxfS5saXN0LWl0ZW17cG9zaXRpb246cmVsYXRpdmV9Lmxpc3QtaXRlbS5zZWxlY3RlZDo6YmVmb3Jle2NvbnRlbnQ6XCJcIjtwb3NpdGlvbjphYnNvbHV0ZTtpbnNldDowO2JveC1zaXppbmc6Ym9yZGVyLWJveDtib3JkZXItcmFkaXVzOmluaGVyaXQ7cG9pbnRlci1ldmVudHM6bm9uZTtib3JkZXI6M3B4IGRvdWJsZSBDYW52YXNUZXh0fX1cbmA7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1tZW51LWl0ZW0tc3R5bGVzLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIyIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbmltcG9ydCB7IF9fZGVjb3JhdGUgfSBmcm9tIFwidHNsaWJcIjtcbmltcG9ydCB7IGN1c3RvbUVsZW1lbnQgfSBmcm9tICdsaXQvZGVjb3JhdG9ycy5qcyc7XG5pbXBvcnQgeyBNZW51IH0gZnJvbSAnLi9pbnRlcm5hbC9tZW51LmpzJztcbmltcG9ydCB7IHN0eWxlcyB9IGZyb20gJy4vaW50ZXJuYWwvbWVudS1zdHlsZXMuanMnO1xuZXhwb3J0IHsgQ2xvc2VSZWFzb24sIEZvY3VzU3RhdGUsIH0gZnJvbSAnLi9pbnRlcm5hbC9jb250cm9sbGVycy9zaGFyZWQuanMnO1xuZXhwb3J0IHsgQ29ybmVyIH0gZnJvbSAnLi9pbnRlcm5hbC9tZW51LmpzJztcbi8qKlxuICogQHN1bW1hcnkgTWVudXMgZGlzcGxheSBhIGxpc3Qgb2YgY2hvaWNlcyBvbiBhIHRlbXBvcmFyeSBzdXJmYWNlLlxuICpcbiAqIEBkZXNjcmlwdGlvblxuICogTWVudXMgYXBwZWFyIHdoZW4gdXNlcnMgaW50ZXJhY3Qgd2l0aCBhIGJ1dHRvbiwgYWN0aW9uLCBvciBvdGhlciBjb250cm9sLlxuICpcbiAqIFRoZXkgY2FuIGJlIG9wZW5lZCBmcm9tIGEgdmFyaWV0eSBvZiBlbGVtZW50cywgbW9zdCBjb21tb25seSBpY29uIGJ1dHRvbnMsXG4gKiBidXR0b25zLCBhbmQgdGV4dCBmaWVsZHMuXG4gKlxuICogbWQtbWVudSBsaXN0ZW5zIGZvciB0aGUgYGNsb3NlLW1lbnVgIGFuZCBgZGVzZWxlY3QtaXRlbXNgIGV2ZW50cy5cbiAqXG4gKiAtIGBjbG9zZS1tZW51YCBjbG9zZXMgdGhlIG1lbnUgd2hlbiBkaXNwYXRjaGVkIGZyb20gYSBjaGlsZCBlbGVtZW50LlxuICogLSBgZGVzZWxlY3QtaXRlbXNgIGRlc2VsZWN0cyBhbGwgb2YgaXRzIGltbWVkaWF0ZSBtZW51LWl0ZW0gY2hpbGRyZW4uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGh0bWxcbiAqIDxkaXYgc3R5bGU9XCJwb3NpdGlvbjpyZWxhdGl2ZTtcIj5cbiAqICAgPGJ1dHRvblxuICogICAgICAgaWQ9XCJhbmNob3JcIlxuICogICAgICAgQGNsaWNrPSR7KCkgPT4gdGhpcy5tZW51UmVmLnZhbHVlLnNob3coKX0+XG4gKiAgICAgQ2xpY2sgdG8gb3BlbiBtZW51XG4gKiAgIDwvYnV0dG9uPlxuICogICA8IS0tXG4gKiAgICAgYGhhcy1vdmVyZmxvd2AgaXMgcmVxdWlyZWQgd2hlbiB1c2luZyBhIHN1Ym1lbnUgd2hpY2ggb3ZlcmZsb3dzIHRoZVxuICogICAgIG1lbnUncyBjb250ZW50cy5cbiAqXG4gKiAgICAgQWRkaXRpb25hbGx5LCBgYW5jaG9yYCBpbmdlc3RzIGFuIGlkcmVmIHdoaWNoIGRvIG5vdCBwYXNzIHRocm91Z2ggc2hhZG93XG4gKiAgICAgcm9vdHMuIFlvdSBjYW4gYWxzbyBzZXQgYC5hbmNob3JFbGVtZW50YCB0byBhbiBlbGVtZW50IHJlZmVyZW5jZSBpZlxuICogICAgIG5lY2Vzc2FyeS5cbiAqICAgLS0+XG4gKiAgIDxtZC1tZW51IGFuY2hvcj1cImFuY2hvclwiIGhhcy1vdmVyZmxvdyAke3JlZihtZW51UmVmKX0+XG4gKiAgICAgPG1kLW1lbnUtaXRlbSBoZWFkbGluZT1cIlRoaXMgaXMgYSBoZWFkbGluZVwiPjwvbWQtbWVudS1pdGVtPlxuICogICAgIDxtZC1zdWItbWVudT5cbiAqICAgICAgIDxtZC1tZW51LWl0ZW1cbiAqICAgICAgICAgICBzbG90PVwiaXRlbVwiXG4gKiAgICAgICAgICAgaGVhZGxpbmU9XCJ0aGlzIGlzIGEgc3VibWVudSBpdGVtXCI+XG4gKiAgICAgICA8L21kLW1lbnUtaXRlbT5cbiAqICAgICAgIDxtZC1tZW51IHNsb3Q9XCJtZW51XCI+XG4gKiAgICAgICAgIDxtZC1tZW51LWl0ZW0gaGVhZGxpbmU9XCJUaGlzIGlzIGFuIGl0ZW0gaW5zaWRlIGEgc3VibWVudVwiPlxuICogICAgICAgICA8L21kLW1lbnUtaXRlbT5cbiAqICAgICAgIDwvbWQtbWVudT5cbiAqICAgICA8L21kLXN1Yi1tZW51PlxuICogICA8L21kLW1lbnU+XG4gKiA8L2Rpdj5cbiAqIGBgYFxuICpcbiAqIEBmaW5hbFxuICogQHN1cHByZXNzIHt2aXNpYmlsaXR5fVxuICovXG5sZXQgTWRNZW51ID0gY2xhc3MgTWRNZW51IGV4dGVuZHMgTWVudSB7XG59O1xuTWRNZW51LnN0eWxlcyA9IFtzdHlsZXNdO1xuTWRNZW51ID0gX19kZWNvcmF0ZShbXG4gICAgY3VzdG9tRWxlbWVudCgnbWQtbWVudScpXG5dLCBNZE1lbnUpO1xuZXhwb3J0IHsgTWRNZW51IH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1tZW51LmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDI0IEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbi8vIEdlbmVyYXRlZCBzdHlsZXNoZWV0IGZvciAuL3Byb2dyZXNzL2ludGVybmFsL2NpcmN1bGFyLXByb2dyZXNzLXN0eWxlcy5jc3MuXG5pbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuZXhwb3J0IGNvbnN0IHN0eWxlcyA9IGNzcyBgOmhvc3R7LS1fYWN0aXZlLWluZGljYXRvci1jb2xvcjogdmFyKC0tbWQtY2lyY3VsYXItcHJvZ3Jlc3MtYWN0aXZlLWluZGljYXRvci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKTstLV9hY3RpdmUtaW5kaWNhdG9yLXdpZHRoOiB2YXIoLS1tZC1jaXJjdWxhci1wcm9ncmVzcy1hY3RpdmUtaW5kaWNhdG9yLXdpZHRoLCAxMCk7LS1fZm91ci1jb2xvci1hY3RpdmUtaW5kaWNhdG9yLWZvdXItY29sb3I6IHZhcigtLW1kLWNpcmN1bGFyLXByb2dyZXNzLWZvdXItY29sb3ItYWN0aXZlLWluZGljYXRvci1mb3VyLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItdGVydGlhcnktY29udGFpbmVyLCAjZmZkOGU0KSk7LS1fZm91ci1jb2xvci1hY3RpdmUtaW5kaWNhdG9yLW9uZS1jb2xvcjogdmFyKC0tbWQtY2lyY3VsYXItcHJvZ3Jlc3MtZm91ci1jb2xvci1hY3RpdmUtaW5kaWNhdG9yLW9uZS1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKTstLV9mb3VyLWNvbG9yLWFjdGl2ZS1pbmRpY2F0b3ItdGhyZWUtY29sb3I6IHZhcigtLW1kLWNpcmN1bGFyLXByb2dyZXNzLWZvdXItY29sb3ItYWN0aXZlLWluZGljYXRvci10aHJlZS1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXRlcnRpYXJ5LCAjN2Q1MjYwKSk7LS1fZm91ci1jb2xvci1hY3RpdmUtaW5kaWNhdG9yLXR3by1jb2xvcjogdmFyKC0tbWQtY2lyY3VsYXItcHJvZ3Jlc3MtZm91ci1jb2xvci1hY3RpdmUtaW5kaWNhdG9yLXR3by1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnktY29udGFpbmVyLCAjZWFkZGZmKSk7LS1fc2l6ZTogdmFyKC0tbWQtY2lyY3VsYXItcHJvZ3Jlc3Mtc2l6ZSwgNDhweCk7ZGlzcGxheTppbmxpbmUtZmxleDt2ZXJ0aWNhbC1hbGlnbjptaWRkbGU7d2lkdGg6dmFyKC0tX3NpemUpO2hlaWdodDp2YXIoLS1fc2l6ZSk7cG9zaXRpb246cmVsYXRpdmU7YWxpZ24taXRlbXM6Y2VudGVyO2p1c3RpZnktY29udGVudDpjZW50ZXI7Y29udGFpbjpzdHJpY3Q7Y29udGVudC12aXNpYmlsaXR5OmF1dG99LnByb2dyZXNze2ZsZXg6MTthbGlnbi1zZWxmOnN0cmV0Y2g7bWFyZ2luOjRweH0ucHJvZ3Jlc3MsLnNwaW5uZXIsLmxlZnQsLnJpZ2h0LC5jaXJjbGUsc3ZnLC50cmFjaywuYWN0aXZlLXRyYWNre3Bvc2l0aW9uOmFic29sdXRlO2luc2V0OjB9c3Zne3RyYW5zZm9ybTpyb3RhdGUoLTkwZGVnKX1jaXJjbGV7Y3g6NTAlO2N5OjUwJTtyOmNhbGMoNTAlKigxIC0gdmFyKC0tX2FjdGl2ZS1pbmRpY2F0b3Itd2lkdGgpLzEwMCkpO3N0cm9rZS13aWR0aDpjYWxjKHZhcigtLV9hY3RpdmUtaW5kaWNhdG9yLXdpZHRoKSoxJSk7c3Ryb2tlLWRhc2hhcnJheToxMDA7ZmlsbDpyZ2JhKDAsMCwwLDApfS5hY3RpdmUtdHJhY2t7dHJhbnNpdGlvbjpzdHJva2UtZGFzaG9mZnNldCA1MDBtcyBjdWJpYy1iZXppZXIoMCwgMCwgMC4yLCAxKTtzdHJva2U6dmFyKC0tX2FjdGl2ZS1pbmRpY2F0b3ItY29sb3IpfS50cmFja3tzdHJva2U6cmdiYSgwLDAsMCwwKX0ucHJvZ3Jlc3MuaW5kZXRlcm1pbmF0ZXthbmltYXRpb246bGluZWFyIGluZmluaXRlIGxpbmVhci1yb3RhdGU7YW5pbWF0aW9uLWR1cmF0aW9uOjE1NjguMjM1Mjk0MTE3Nm1zfS5zcGlubmVye2FuaW1hdGlvbjppbmZpbml0ZSBib3RoIHJvdGF0ZS1hcmM7YW5pbWF0aW9uLWR1cmF0aW9uOjUzMzJtczthbmltYXRpb24tdGltaW5nLWZ1bmN0aW9uOmN1YmljLWJlemllcigwLjQsIDAsIDAuMiwgMSl9LmxlZnR7b3ZlcmZsb3c6aGlkZGVuO2luc2V0OjAgNTAlIDAgMH0ucmlnaHR7b3ZlcmZsb3c6aGlkZGVuO2luc2V0OjAgMCAwIDUwJX0uY2lyY2xle2JveC1zaXppbmc6Ym9yZGVyLWJveDtib3JkZXItcmFkaXVzOjUwJTtib3JkZXI6c29saWQgY2FsYyh2YXIoLS1fYWN0aXZlLWluZGljYXRvci13aWR0aCkvMTAwKih2YXIoLS1fc2l6ZSkgLSA4cHgpKTtib3JkZXItY29sb3I6dmFyKC0tX2FjdGl2ZS1pbmRpY2F0b3ItY29sb3IpIHZhcigtLV9hY3RpdmUtaW5kaWNhdG9yLWNvbG9yKSByZ2JhKDAsMCwwLDApIHJnYmEoMCwwLDAsMCk7YW5pbWF0aW9uOmV4cGFuZC1hcmM7YW5pbWF0aW9uLWl0ZXJhdGlvbi1jb3VudDppbmZpbml0ZTthbmltYXRpb24tZmlsbC1tb2RlOmJvdGg7YW5pbWF0aW9uLWR1cmF0aW9uOjEzMzNtcyw1MzMybXM7YW5pbWF0aW9uLXRpbWluZy1mdW5jdGlvbjpjdWJpYy1iZXppZXIoMC40LCAwLCAwLjIsIDEpfS5mb3VyLWNvbG9yIC5jaXJjbGV7YW5pbWF0aW9uLW5hbWU6ZXhwYW5kLWFyYyxmb3VyLWNvbG9yfS5sZWZ0IC5jaXJjbGV7cm90YXRlOjEzNWRlZztpbnNldDowIC0xMDAlIDAgMH0ucmlnaHQgLmNpcmNsZXtyb3RhdGU6MTAwZGVnO2luc2V0OjAgMCAwIC0xMDAlO2FuaW1hdGlvbi1kZWxheTotNjY2LjVtcywwbXN9QG1lZGlhKGZvcmNlZC1jb2xvcnM6IGFjdGl2ZSl7LmFjdGl2ZS10cmFja3tzdHJva2U6Q2FudmFzVGV4dH0uY2lyY2xle2JvcmRlci1jb2xvcjpDYW52YXNUZXh0IENhbnZhc1RleHQgQ2FudmFzIENhbnZhc319QGtleWZyYW1lcyBleHBhbmQtYXJjezAle3RyYW5zZm9ybTpyb3RhdGUoMjY1ZGVnKX01MCV7dHJhbnNmb3JtOnJvdGF0ZSgxMzBkZWcpfTEwMCV7dHJhbnNmb3JtOnJvdGF0ZSgyNjVkZWcpfX1Aa2V5ZnJhbWVzIHJvdGF0ZS1hcmN7MTIuNSV7dHJhbnNmb3JtOnJvdGF0ZSgxMzVkZWcpfTI1JXt0cmFuc2Zvcm06cm90YXRlKDI3MGRlZyl9MzcuNSV7dHJhbnNmb3JtOnJvdGF0ZSg0MDVkZWcpfTUwJXt0cmFuc2Zvcm06cm90YXRlKDU0MGRlZyl9NjIuNSV7dHJhbnNmb3JtOnJvdGF0ZSg2NzVkZWcpfTc1JXt0cmFuc2Zvcm06cm90YXRlKDgxMGRlZyl9ODcuNSV7dHJhbnNmb3JtOnJvdGF0ZSg5NDVkZWcpfTEwMCV7dHJhbnNmb3JtOnJvdGF0ZSgxMDgwZGVnKX19QGtleWZyYW1lcyBsaW5lYXItcm90YXRle3Rve3RyYW5zZm9ybTpyb3RhdGUoMzYwZGVnKX19QGtleWZyYW1lcyBmb3VyLWNvbG9yezAle2JvcmRlci10b3AtY29sb3I6dmFyKC0tX2ZvdXItY29sb3ItYWN0aXZlLWluZGljYXRvci1vbmUtY29sb3IpO2JvcmRlci1yaWdodC1jb2xvcjp2YXIoLS1fZm91ci1jb2xvci1hY3RpdmUtaW5kaWNhdG9yLW9uZS1jb2xvcil9MTUle2JvcmRlci10b3AtY29sb3I6dmFyKC0tX2ZvdXItY29sb3ItYWN0aXZlLWluZGljYXRvci1vbmUtY29sb3IpO2JvcmRlci1yaWdodC1jb2xvcjp2YXIoLS1fZm91ci1jb2xvci1hY3RpdmUtaW5kaWNhdG9yLW9uZS1jb2xvcil9MjUle2JvcmRlci10b3AtY29sb3I6dmFyKC0tX2ZvdXItY29sb3ItYWN0aXZlLWluZGljYXRvci10d28tY29sb3IpO2JvcmRlci1yaWdodC1jb2xvcjp2YXIoLS1fZm91ci1jb2xvci1hY3RpdmUtaW5kaWNhdG9yLXR3by1jb2xvcil9NDAle2JvcmRlci10b3AtY29sb3I6dmFyKC0tX2ZvdXItY29sb3ItYWN0aXZlLWluZGljYXRvci10d28tY29sb3IpO2JvcmRlci1yaWdodC1jb2xvcjp2YXIoLS1fZm91ci1jb2xvci1hY3RpdmUtaW5kaWNhdG9yLXR3by1jb2xvcil9NTAle2JvcmRlci10b3AtY29sb3I6dmFyKC0tX2ZvdXItY29sb3ItYWN0aXZlLWluZGljYXRvci10aHJlZS1jb2xvcik7Ym9yZGVyLXJpZ2h0LWNvbG9yOnZhcigtLV9mb3VyLWNvbG9yLWFjdGl2ZS1pbmRpY2F0b3ItdGhyZWUtY29sb3IpfTY1JXtib3JkZXItdG9wLWNvbG9yOnZhcigtLV9mb3VyLWNvbG9yLWFjdGl2ZS1pbmRpY2F0b3ItdGhyZWUtY29sb3IpO2JvcmRlci1yaWdodC1jb2xvcjp2YXIoLS1fZm91ci1jb2xvci1hY3RpdmUtaW5kaWNhdG9yLXRocmVlLWNvbG9yKX03NSV7Ym9yZGVyLXRvcC1jb2xvcjp2YXIoLS1fZm91ci1jb2xvci1hY3RpdmUtaW5kaWNhdG9yLWZvdXItY29sb3IpO2JvcmRlci1yaWdodC1jb2xvcjp2YXIoLS1fZm91ci1jb2xvci1hY3RpdmUtaW5kaWNhdG9yLWZvdXItY29sb3IpfTkwJXtib3JkZXItdG9wLWNvbG9yOnZhcigtLV9mb3VyLWNvbG9yLWFjdGl2ZS1pbmRpY2F0b3ItZm91ci1jb2xvcik7Ym9yZGVyLXJpZ2h0LWNvbG9yOnZhcigtLV9mb3VyLWNvbG9yLWFjdGl2ZS1pbmRpY2F0b3ItZm91ci1jb2xvcil9MTAwJXtib3JkZXItdG9wLWNvbG9yOnZhcigtLV9mb3VyLWNvbG9yLWFjdGl2ZS1pbmRpY2F0b3Itb25lLWNvbG9yKTtib3JkZXItcmlnaHQtY29sb3I6dmFyKC0tX2ZvdXItY29sb3ItYWN0aXZlLWluZGljYXRvci1vbmUtY29sb3IpfX1cbmA7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jaXJjdWxhci1wcm9ncmVzcy1zdHlsZXMuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjMgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuaW1wb3J0IHsgaHRtbCB9IGZyb20gJ2xpdCc7XG5pbXBvcnQgeyBQcm9ncmVzcyB9IGZyb20gJy4vcHJvZ3Jlc3MuanMnO1xuLyoqXG4gKiBBIGNpcmN1bGFyIHByb2dyZXNzIGNvbXBvbmVudC5cbiAqL1xuZXhwb3J0IGNsYXNzIENpcmN1bGFyUHJvZ3Jlc3MgZXh0ZW5kcyBQcm9ncmVzcyB7XG4gICAgcmVuZGVySW5kaWNhdG9yKCkge1xuICAgICAgICBpZiAodGhpcy5pbmRldGVybWluYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZW5kZXJJbmRldGVybWluYXRlQ29udGFpbmVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMucmVuZGVyRGV0ZXJtaW5hdGVDb250YWluZXIoKTtcbiAgICB9XG4gICAgLy8gRGV0ZXJtaW5hdGUgbW9kZSBpcyByZW5kZXJlZCB3aXRoIGFuIHN2ZyBzbyB0aGUgcHJvZ3Jlc3MgYXJjIGNhbiBiZVxuICAgIC8vIGVhc2lseSBhbmltYXRlZCB2aWEgc3Ryb2tlLWRhc2hvZmZzZXQuXG4gICAgcmVuZGVyRGV0ZXJtaW5hdGVDb250YWluZXIoKSB7XG4gICAgICAgIGNvbnN0IGRhc2hPZmZzZXQgPSAoMSAtIHRoaXMudmFsdWUgLyB0aGlzLm1heCkgKiAxMDA7XG4gICAgICAgIC8vIG5vdGUsIGRhc2gtYXJyYXkvb2Zmc2V0IGFyZSByZWxhdGl2ZSB0byBTZXR0aW5nIGBwYXRoTGVuZ3RoYCBidXRcbiAgICAgICAgLy8gQ2hyb21lIHNlZW1zIHRvIHJlbmRlciB0aGlzIGluYWNjdXJhdGVseSBhbmQgdXNpbmcgYSBsYXJnZSB2aWV3Ym94IGhlbHBzLlxuICAgICAgICByZXR1cm4gaHRtbCBgXG4gICAgICA8c3ZnIHZpZXdCb3g9XCIwIDAgNDgwMCA0ODAwXCI+XG4gICAgICAgIDxjaXJjbGUgY2xhc3M9XCJ0cmFja1wiIHBhdGhMZW5ndGg9XCIxMDBcIj48L2NpcmNsZT5cbiAgICAgICAgPGNpcmNsZVxuICAgICAgICAgIGNsYXNzPVwiYWN0aXZlLXRyYWNrXCJcbiAgICAgICAgICBwYXRoTGVuZ3RoPVwiMTAwXCJcbiAgICAgICAgICBzdHJva2UtZGFzaG9mZnNldD0ke2Rhc2hPZmZzZXR9PjwvY2lyY2xlPlxuICAgICAgPC9zdmc+XG4gICAgYDtcbiAgICB9XG4gICAgLy8gSW5kZXRlcm1pbmF0ZSBtb2RlIHJlbmRlcmVkIHdpdGggMiBib3JkZXJlZC1kaXZzLiBUaGUgYm9yZGVycyBhcmVcbiAgICAvLyBjbGlwcGVkIGludG8gaGFsZiBjaXJjbGVzIGJ5IHRoZWlyIGNvbnRhaW5lcnMuIFRoZSBkaXZzIGFyZSB0aGVuIGNhcmVmdWxseVxuICAgIC8vIGFuaW1hdGVkIHRvIHByb2R1Y2UgY2hhbmdlcyB0byB0aGUgc3Bpbm5lciBhcmMgc2l6ZS5cbiAgICAvLyBUaGlzIGFwcHJvYWNoIGhhcyA0LjV4IHRoZSBGUFMgb2YgcmVuZGVyaW5nIHZpYSBzdmcgb24gQ2hyb21lIDExMS5cbiAgICAvLyBTZWUgaHR0cHM6Ly9saXQuZGV2L3BsYXlncm91bmQvI2dpc3Q9ZmViYjc3MzU2NTI3MmY3NTQwOGFiMDZhMGViNDk3NDYuXG4gICAgcmVuZGVySW5kZXRlcm1pbmF0ZUNvbnRhaW5lcigpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYCA8ZGl2IGNsYXNzPVwic3Bpbm5lclwiPlxuICAgICAgPGRpdiBjbGFzcz1cImxlZnRcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNpcmNsZVwiPjwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwicmlnaHRcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNpcmNsZVwiPjwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+YDtcbiAgICB9XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jaXJjdWxhci1wcm9ncmVzcy5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBfX2RlY29yYXRlIH0gZnJvbSBcInRzbGliXCI7XG5pbXBvcnQgeyBodG1sLCBMaXRFbGVtZW50LCBub3RoaW5nIH0gZnJvbSAnbGl0JztcbmltcG9ydCB7IHByb3BlcnR5IH0gZnJvbSAnbGl0L2RlY29yYXRvcnMuanMnO1xuaW1wb3J0IHsgY2xhc3NNYXAgfSBmcm9tICdsaXQvZGlyZWN0aXZlcy9jbGFzcy1tYXAuanMnO1xuaW1wb3J0IHsgbWl4aW5EZWxlZ2F0ZXNBcmlhIH0gZnJvbSAnLi4vLi4vaW50ZXJuYWwvYXJpYS9kZWxlZ2F0ZS5qcyc7XG4vLyBTZXBhcmF0ZSB2YXJpYWJsZSBuZWVkZWQgZm9yIGNsb3N1cmUuXG5jb25zdCBwcm9ncmVzc0Jhc2VDbGFzcyA9IG1peGluRGVsZWdhdGVzQXJpYShMaXRFbGVtZW50KTtcbi8qKlxuICogQSBwcm9ncmVzcyBjb21wb25lbnQuXG4gKi9cbmV4cG9ydCBjbGFzcyBQcm9ncmVzcyBleHRlbmRzIHByb2dyZXNzQmFzZUNsYXNzIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFByb2dyZXNzIHRvIGRpc3BsYXksIGEgZnJhY3Rpb24gYmV0d2VlbiAwIGFuZCBgbWF4YC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMudmFsdWUgPSAwO1xuICAgICAgICAvKipcbiAgICAgICAgICogTWF4aW11bSBwcm9ncmVzcyB0byBkaXNwbGF5LCBkZWZhdWx0cyB0byAxLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5tYXggPSAxO1xuICAgICAgICAvKipcbiAgICAgICAgICogV2hldGhlciBvciBub3QgdG8gZGlzcGxheSBpbmRldGVybWluYXRlIHByb2dyZXNzLCB3aGljaCBnaXZlcyBubyBpbmRpY2F0aW9uXG4gICAgICAgICAqIHRvIGhvdyBsb25nIGFuIGFjdGl2aXR5IHdpbGwgdGFrZS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaW5kZXRlcm1pbmF0ZSA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogV2hldGhlciBvciBub3QgdG8gcmVuZGVyIGluZGV0ZXJtaW5hdGUgbW9kZSB1c2luZyA0IGNvbG9ycyBpbnN0ZWFkIG9mIG9uZS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZm91ckNvbG9yID0gZmFsc2U7XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgLy8gTmVlZGVkIGZvciBjbG9zdXJlIGNvbmZvcm1hbmNlXG4gICAgICAgIGNvbnN0IHsgYXJpYUxhYmVsIH0gPSB0aGlzO1xuICAgICAgICByZXR1cm4gaHRtbCBgXG4gICAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwicHJvZ3Jlc3MgJHtjbGFzc01hcCh0aGlzLmdldFJlbmRlckNsYXNzZXMoKSl9XCJcbiAgICAgICAgcm9sZT1cInByb2dyZXNzYmFyXCJcbiAgICAgICAgYXJpYS1sYWJlbD1cIiR7YXJpYUxhYmVsIHx8IG5vdGhpbmd9XCJcbiAgICAgICAgYXJpYS12YWx1ZW1pbj1cIjBcIlxuICAgICAgICBhcmlhLXZhbHVlbWF4PSR7dGhpcy5tYXh9XG4gICAgICAgIGFyaWEtdmFsdWVub3c9JHt0aGlzLmluZGV0ZXJtaW5hdGUgPyBub3RoaW5nIDogdGhpcy52YWx1ZX1cbiAgICAgICAgPiR7dGhpcy5yZW5kZXJJbmRpY2F0b3IoKX08L2RpdlxuICAgICAgPlxuICAgIGA7XG4gICAgfVxuICAgIGdldFJlbmRlckNsYXNzZXMoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAnaW5kZXRlcm1pbmF0ZSc6IHRoaXMuaW5kZXRlcm1pbmF0ZSxcbiAgICAgICAgICAgICdmb3VyLWNvbG9yJzogdGhpcy5mb3VyQ29sb3IsXG4gICAgICAgIH07XG4gICAgfVxufVxuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBOdW1iZXIgfSlcbl0sIFByb2dyZXNzLnByb3RvdHlwZSwgXCJ2YWx1ZVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBOdW1iZXIgfSlcbl0sIFByb2dyZXNzLnByb3RvdHlwZSwgXCJtYXhcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiB9KVxuXSwgUHJvZ3Jlc3MucHJvdG90eXBlLCBcImluZGV0ZXJtaW5hdGVcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgYXR0cmlidXRlOiAnZm91ci1jb2xvcicgfSlcbl0sIFByb2dyZXNzLnByb3RvdHlwZSwgXCJmb3VyQ29sb3JcIiwgdm9pZCAwKTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXByb2dyZXNzLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDI0IEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbi8vIEdlbmVyYXRlZCBzdHlsZXNoZWV0IGZvciAuL3NlbGVjdC9pbnRlcm5hbC9maWxsZWQtc2VsZWN0LXN0eWxlcy5jc3MuXG5pbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuZXhwb3J0IGNvbnN0IHN0eWxlcyA9IGNzcyBgOmhvc3R7LS1fdGV4dC1maWVsZC1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtYWN0aXZlLWluZGljYXRvci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX3RleHQtZmllbGQtYWN0aXZlLWluZGljYXRvci1oZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodCwgMXB4KTstLV90ZXh0LWZpZWxkLWNvbnRhaW5lci1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWNvbnRhaW5lci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXN1cmZhY2UtY29udGFpbmVyLWhpZ2hlc3QsICNlNmUwZTkpKTstLV90ZXh0LWZpZWxkLWRpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX3RleHQtZmllbGQtZGlzYWJsZWQtYWN0aXZlLWluZGljYXRvci1oZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodCwgMXB4KTstLV90ZXh0LWZpZWxkLWRpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3Itb3BhY2l0eTogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWRpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3Itb3BhY2l0eSwgMC4zOCk7LS1fdGV4dC1maWVsZC1kaXNhYmxlZC1jb250YWluZXItY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1kaXNhYmxlZC1jb250YWluZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1fdGV4dC1maWVsZC1kaXNhYmxlZC1jb250YWluZXItb3BhY2l0eTogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWRpc2FibGVkLWNvbnRhaW5lci1vcGFjaXR5LCAwLjA0KTstLV90ZXh0LWZpZWxkLWRpc2FibGVkLWlucHV0LXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1kaXNhYmxlZC1pbnB1dC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX3RleHQtZmllbGQtZGlzYWJsZWQtaW5wdXQtdGV4dC1vcGFjaXR5OiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZGlzYWJsZWQtaW5wdXQtdGV4dC1vcGFjaXR5LCAwLjM4KTstLV90ZXh0LWZpZWxkLWRpc2FibGVkLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1kaXNhYmxlZC1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX3RleHQtZmllbGQtZGlzYWJsZWQtbGFiZWwtdGV4dC1vcGFjaXR5OiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZGlzYWJsZWQtbGFiZWwtdGV4dC1vcGFjaXR5LCAwLjM4KTstLV90ZXh0LWZpZWxkLWRpc2FibGVkLWxlYWRpbmctaWNvbi1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWRpc2FibGVkLWxlYWRpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV90ZXh0LWZpZWxkLWRpc2FibGVkLWxlYWRpbmctaWNvbi1vcGFjaXR5OiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZGlzYWJsZWQtbGVhZGluZy1pY29uLW9wYWNpdHksIDAuMzgpOy0tX3RleHQtZmllbGQtZGlzYWJsZWQtc3VwcG9ydGluZy10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZGlzYWJsZWQtc3VwcG9ydGluZy10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX3RleHQtZmllbGQtZGlzYWJsZWQtc3VwcG9ydGluZy10ZXh0LW9wYWNpdHk6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1kaXNhYmxlZC1zdXBwb3J0aW5nLXRleHQtb3BhY2l0eSwgMC4zOCk7LS1fdGV4dC1maWVsZC1kaXNhYmxlZC10cmFpbGluZy1pY29uLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZGlzYWJsZWQtdHJhaWxpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV90ZXh0LWZpZWxkLWRpc2FibGVkLXRyYWlsaW5nLWljb24tb3BhY2l0eTogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWRpc2FibGVkLXRyYWlsaW5nLWljb24tb3BhY2l0eSwgMC4zOCk7LS1fdGV4dC1maWVsZC1lcnJvci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZXJyb3ItYWN0aXZlLWluZGljYXRvci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLWVycm9yLCAjYjMyNjFlKSk7LS1fdGV4dC1maWVsZC1lcnJvci1mb2N1cy1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZXJyb3ItZm9jdXMtYWN0aXZlLWluZGljYXRvci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLWVycm9yLCAjYjMyNjFlKSk7LS1fdGV4dC1maWVsZC1lcnJvci1mb2N1cy1pbnB1dC10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZXJyb3ItZm9jdXMtaW5wdXQtdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV90ZXh0LWZpZWxkLWVycm9yLWZvY3VzLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1lcnJvci1mb2N1cy1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItZXJyb3IsICNiMzI2MWUpKTstLV90ZXh0LWZpZWxkLWVycm9yLWZvY3VzLWxlYWRpbmctaWNvbi1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWVycm9yLWZvY3VzLWxlYWRpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX3RleHQtZmllbGQtZXJyb3ItZm9jdXMtc3VwcG9ydGluZy10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZXJyb3ItZm9jdXMtc3VwcG9ydGluZy10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItZXJyb3IsICNiMzI2MWUpKTstLV90ZXh0LWZpZWxkLWVycm9yLWZvY3VzLXRyYWlsaW5nLWljb24tY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1lcnJvci1mb2N1cy10cmFpbGluZy1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItZXJyb3IsICNiMzI2MWUpKTstLV90ZXh0LWZpZWxkLWVycm9yLWhvdmVyLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1lcnJvci1ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tZXJyb3ItY29udGFpbmVyLCAjNDEwZTBiKSk7LS1fdGV4dC1maWVsZC1lcnJvci1ob3Zlci1pbnB1dC10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZXJyb3ItaG92ZXItaW5wdXQtdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV90ZXh0LWZpZWxkLWVycm9yLWhvdmVyLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1lcnJvci1ob3Zlci1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tZXJyb3ItY29udGFpbmVyLCAjNDEwZTBiKSk7LS1fdGV4dC1maWVsZC1lcnJvci1ob3Zlci1sZWFkaW5nLWljb24tY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1lcnJvci1ob3Zlci1sZWFkaW5nLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV90ZXh0LWZpZWxkLWVycm9yLWhvdmVyLXN0YXRlLWxheWVyLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZXJyb3ItaG92ZXItc3RhdGUtbGF5ZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1fdGV4dC1maWVsZC1lcnJvci1ob3Zlci1zdGF0ZS1sYXllci1vcGFjaXR5OiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZXJyb3ItaG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eSwgMC4wOCk7LS1fdGV4dC1maWVsZC1lcnJvci1ob3Zlci1zdXBwb3J0aW5nLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1lcnJvci1ob3Zlci1zdXBwb3J0aW5nLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1lcnJvciwgI2IzMjYxZSkpOy0tX3RleHQtZmllbGQtZXJyb3ItaG92ZXItdHJhaWxpbmctaWNvbi1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWVycm9yLWhvdmVyLXRyYWlsaW5nLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1lcnJvci1jb250YWluZXIsICM0MTBlMGIpKTstLV90ZXh0LWZpZWxkLWVycm9yLWlucHV0LXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1lcnJvci1pbnB1dC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX3RleHQtZmllbGQtZXJyb3ItbGFiZWwtdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWVycm9yLWxhYmVsLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1lcnJvciwgI2IzMjYxZSkpOy0tX3RleHQtZmllbGQtZXJyb3ItbGVhZGluZy1pY29uLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZXJyb3ItbGVhZGluZy1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fdGV4dC1maWVsZC1lcnJvci1zdXBwb3J0aW5nLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1lcnJvci1zdXBwb3J0aW5nLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1lcnJvciwgI2IzMjYxZSkpOy0tX3RleHQtZmllbGQtZXJyb3ItdHJhaWxpbmctaWNvbi1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWVycm9yLXRyYWlsaW5nLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1lcnJvciwgI2IzMjYxZSkpOy0tX3RleHQtZmllbGQtZm9jdXMtYWN0aXZlLWluZGljYXRvci1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWZvY3VzLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1wcmltYXJ5LCAjNjc1MGE0KSk7LS1fdGV4dC1maWVsZC1mb2N1cy1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodDogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWZvY3VzLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0LCAzcHgpOy0tX3RleHQtZmllbGQtZm9jdXMtaW5wdXQtdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWZvY3VzLWlucHV0LXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1fdGV4dC1maWVsZC1mb2N1cy1sYWJlbC10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZm9jdXMtbGFiZWwtdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKTstLV90ZXh0LWZpZWxkLWZvY3VzLWxlYWRpbmctaWNvbi1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWZvY3VzLWxlYWRpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX3RleHQtZmllbGQtZm9jdXMtc3VwcG9ydGluZy10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZm9jdXMtc3VwcG9ydGluZy10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fdGV4dC1maWVsZC1mb2N1cy10cmFpbGluZy1pY29uLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtZm9jdXMtdHJhaWxpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKTstLV90ZXh0LWZpZWxkLWhvdmVyLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX3RleHQtZmllbGQtaG92ZXItYWN0aXZlLWluZGljYXRvci1oZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodCwgMXB4KTstLV90ZXh0LWZpZWxkLWhvdmVyLWlucHV0LXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1ob3Zlci1pbnB1dC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX3RleHQtZmllbGQtaG92ZXItbGFiZWwtdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWhvdmVyLWxhYmVsLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1fdGV4dC1maWVsZC1ob3Zlci1sZWFkaW5nLWljb24tY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1ob3Zlci1sZWFkaW5nLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV90ZXh0LWZpZWxkLWhvdmVyLXN0YXRlLWxheWVyLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtaG92ZXItc3RhdGUtbGF5ZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1fdGV4dC1maWVsZC1ob3Zlci1zdGF0ZS1sYXllci1vcGFjaXR5OiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtaG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eSwgMC4wOCk7LS1fdGV4dC1maWVsZC1ob3Zlci1zdXBwb3J0aW5nLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1ob3Zlci1zdXBwb3J0aW5nLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV90ZXh0LWZpZWxkLWhvdmVyLXRyYWlsaW5nLWljb24tY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1ob3Zlci10cmFpbGluZy1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fdGV4dC1maWVsZC1pbnB1dC10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtaW5wdXQtdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV90ZXh0LWZpZWxkLWlucHV0LXRleHQtZm9udDogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWlucHV0LXRleHQtZm9udCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LWxhcmdlLWZvbnQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS1wbGFpbiwgUm9ib3RvKSkpOy0tX3RleHQtZmllbGQtaW5wdXQtdGV4dC1saW5lLWhlaWdodDogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWlucHV0LXRleHQtbGluZS1oZWlnaHQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS1saW5lLWhlaWdodCwgMS41cmVtKSk7LS1fdGV4dC1maWVsZC1pbnB1dC10ZXh0LXNpemU6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1pbnB1dC10ZXh0LXNpemUsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS1zaXplLCAxcmVtKSk7LS1fdGV4dC1maWVsZC1pbnB1dC10ZXh0LXdlaWdodDogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWlucHV0LXRleHQtd2VpZ2h0LCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbGFyZ2Utd2VpZ2h0LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2Utd2VpZ2h0LXJlZ3VsYXIsIDQwMCkpKTstLV90ZXh0LWZpZWxkLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fdGV4dC1maWVsZC1sYWJlbC10ZXh0LWZvbnQ6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1sYWJlbC10ZXh0LWZvbnQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS1mb250LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2UtcGxhaW4sIFJvYm90bykpKTstLV90ZXh0LWZpZWxkLWxhYmVsLXRleHQtbGluZS1oZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1sYWJlbC10ZXh0LWxpbmUtaGVpZ2h0LCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbGFyZ2UtbGluZS1oZWlnaHQsIDEuNXJlbSkpOy0tX3RleHQtZmllbGQtbGFiZWwtdGV4dC1wb3B1bGF0ZWQtbGluZS1oZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1sYWJlbC10ZXh0LXBvcHVsYXRlZC1saW5lLWhlaWdodCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LXNtYWxsLWxpbmUtaGVpZ2h0LCAxcmVtKSk7LS1fdGV4dC1maWVsZC1sYWJlbC10ZXh0LXBvcHVsYXRlZC1zaXplOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtbGFiZWwtdGV4dC1wb3B1bGF0ZWQtc2l6ZSwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LXNtYWxsLXNpemUsIDAuNzVyZW0pKTstLV90ZXh0LWZpZWxkLWxhYmVsLXRleHQtc2l6ZTogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWxhYmVsLXRleHQtc2l6ZSwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LWxhcmdlLXNpemUsIDFyZW0pKTstLV90ZXh0LWZpZWxkLWxhYmVsLXRleHQtd2VpZ2h0OiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtbGFiZWwtdGV4dC13ZWlnaHQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS13ZWlnaHQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS13ZWlnaHQtcmVndWxhciwgNDAwKSkpOy0tX3RleHQtZmllbGQtbGVhZGluZy1pY29uLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtbGVhZGluZy1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fdGV4dC1maWVsZC1sZWFkaW5nLWljb24tc2l6ZTogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWxlYWRpbmctaWNvbi1zaXplLCAyNHB4KTstLV90ZXh0LWZpZWxkLXN1cHBvcnRpbmctdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLXN1cHBvcnRpbmctdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX3RleHQtZmllbGQtc3VwcG9ydGluZy10ZXh0LWZvbnQ6IHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1zdXBwb3J0aW5nLXRleHQtZm9udCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LXNtYWxsLWZvbnQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS1wbGFpbiwgUm9ib3RvKSkpOy0tX3RleHQtZmllbGQtc3VwcG9ydGluZy10ZXh0LWxpbmUtaGVpZ2h0OiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtc3VwcG9ydGluZy10ZXh0LWxpbmUtaGVpZ2h0LCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktc21hbGwtbGluZS1oZWlnaHQsIDFyZW0pKTstLV90ZXh0LWZpZWxkLXN1cHBvcnRpbmctdGV4dC1zaXplOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtc3VwcG9ydGluZy10ZXh0LXNpemUsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1zbWFsbC1zaXplLCAwLjc1cmVtKSk7LS1fdGV4dC1maWVsZC1zdXBwb3J0aW5nLXRleHQtd2VpZ2h0OiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtc3VwcG9ydGluZy10ZXh0LXdlaWdodCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LXNtYWxsLXdlaWdodCwgdmFyKC0tbWQtcmVmLXR5cGVmYWNlLXdlaWdodC1yZWd1bGFyLCA0MDApKSk7LS1fdGV4dC1maWVsZC10cmFpbGluZy1pY29uLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtdHJhaWxpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX3RleHQtZmllbGQtdHJhaWxpbmctaWNvbi1zaXplOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtdHJhaWxpbmctaWNvbi1zaXplLCAyNHB4KTstLV90ZXh0LWZpZWxkLWNvbnRhaW5lci1zaGFwZS1zdGFydC1zdGFydDogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWNvbnRhaW5lci1zaGFwZS1zdGFydC1zdGFydCwgdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWNvbnRhaW5lci1zaGFwZSwgdmFyKC0tbWQtc3lzLXNoYXBlLWNvcm5lci1leHRyYS1zbWFsbCwgNHB4KSkpOy0tX3RleHQtZmllbGQtY29udGFpbmVyLXNoYXBlLXN0YXJ0LWVuZDogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWNvbnRhaW5lci1zaGFwZS1zdGFydC1lbmQsIHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1jb250YWluZXItc2hhcGUsIHZhcigtLW1kLXN5cy1zaGFwZS1jb3JuZXItZXh0cmEtc21hbGwsIDRweCkpKTstLV90ZXh0LWZpZWxkLWNvbnRhaW5lci1zaGFwZS1lbmQtZW5kOiB2YXIoLS1tZC1maWxsZWQtc2VsZWN0LXRleHQtZmllbGQtY29udGFpbmVyLXNoYXBlLWVuZC1lbmQsIHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1jb250YWluZXItc2hhcGUsIHZhcigtLW1kLXN5cy1zaGFwZS1jb3JuZXItbm9uZSwgMHB4KSkpOy0tX3RleHQtZmllbGQtY29udGFpbmVyLXNoYXBlLWVuZC1zdGFydDogdmFyKC0tbWQtZmlsbGVkLXNlbGVjdC10ZXh0LWZpZWxkLWNvbnRhaW5lci1zaGFwZS1lbmQtc3RhcnQsIHZhcigtLW1kLWZpbGxlZC1zZWxlY3QtdGV4dC1maWVsZC1jb250YWluZXItc2hhcGUsIHZhcigtLW1kLXN5cy1zaGFwZS1jb3JuZXItbm9uZSwgMHB4KSkpOy0tbWQtZmlsbGVkLWZpZWxkLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0OiB2YXIoLS1fdGV4dC1maWVsZC1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodCk7LS1tZC1maWxsZWQtZmllbGQtY29udGFpbmVyLWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1jb250YWluZXItY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWNvbnRhaW5lci1zaGFwZS1lbmQtZW5kOiB2YXIoLS1fdGV4dC1maWVsZC1jb250YWluZXItc2hhcGUtZW5kLWVuZCk7LS1tZC1maWxsZWQtZmllbGQtY29udGFpbmVyLXNoYXBlLWVuZC1zdGFydDogdmFyKC0tX3RleHQtZmllbGQtY29udGFpbmVyLXNoYXBlLWVuZC1zdGFydCk7LS1tZC1maWxsZWQtZmllbGQtY29udGFpbmVyLXNoYXBlLXN0YXJ0LWVuZDogdmFyKC0tX3RleHQtZmllbGQtY29udGFpbmVyLXNoYXBlLXN0YXJ0LWVuZCk7LS1tZC1maWxsZWQtZmllbGQtY29udGFpbmVyLXNoYXBlLXN0YXJ0LXN0YXJ0OiB2YXIoLS1fdGV4dC1maWVsZC1jb250YWluZXItc2hhcGUtc3RhcnQtc3RhcnQpOy0tbWQtZmlsbGVkLWZpZWxkLWNvbnRlbnQtY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWlucHV0LXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWNvbnRlbnQtZm9udDogdmFyKC0tX3RleHQtZmllbGQtaW5wdXQtdGV4dC1mb250KTstLW1kLWZpbGxlZC1maWVsZC1jb250ZW50LWxpbmUtaGVpZ2h0OiB2YXIoLS1fdGV4dC1maWVsZC1pbnB1dC10ZXh0LWxpbmUtaGVpZ2h0KTstLW1kLWZpbGxlZC1maWVsZC1jb250ZW50LXNpemU6IHZhcigtLV90ZXh0LWZpZWxkLWlucHV0LXRleHQtc2l6ZSk7LS1tZC1maWxsZWQtZmllbGQtY29udGVudC13ZWlnaHQ6IHZhcigtLV90ZXh0LWZpZWxkLWlucHV0LXRleHQtd2VpZ2h0KTstLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodDogdmFyKC0tX3RleHQtZmllbGQtZGlzYWJsZWQtYWN0aXZlLWluZGljYXRvci1oZWlnaHQpOy0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3Itb3BhY2l0eTogdmFyKC0tX3RleHQtZmllbGQtZGlzYWJsZWQtYWN0aXZlLWluZGljYXRvci1vcGFjaXR5KTstLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1jb250YWluZXItY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWRpc2FibGVkLWNvbnRhaW5lci1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtY29udGFpbmVyLW9wYWNpdHk6IHZhcigtLV90ZXh0LWZpZWxkLWRpc2FibGVkLWNvbnRhaW5lci1vcGFjaXR5KTstLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1jb250ZW50LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1kaXNhYmxlZC1pbnB1dC10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1jb250ZW50LW9wYWNpdHk6IHZhcigtLV90ZXh0LWZpZWxkLWRpc2FibGVkLWlucHV0LXRleHQtb3BhY2l0eSk7LS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtbGFiZWwtdGV4dC1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtZGlzYWJsZWQtbGFiZWwtdGV4dC1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtbGFiZWwtdGV4dC1vcGFjaXR5OiB2YXIoLS1fdGV4dC1maWVsZC1kaXNhYmxlZC1sYWJlbC10ZXh0LW9wYWNpdHkpOy0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLWxlYWRpbmctY29udGVudC1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtZGlzYWJsZWQtbGVhZGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1sZWFkaW5nLWNvbnRlbnQtb3BhY2l0eTogdmFyKC0tX3RleHQtZmllbGQtZGlzYWJsZWQtbGVhZGluZy1pY29uLW9wYWNpdHkpOy0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLXN1cHBvcnRpbmctdGV4dC1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtZGlzYWJsZWQtc3VwcG9ydGluZy10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1zdXBwb3J0aW5nLXRleHQtb3BhY2l0eTogdmFyKC0tX3RleHQtZmllbGQtZGlzYWJsZWQtc3VwcG9ydGluZy10ZXh0LW9wYWNpdHkpOy0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLXRyYWlsaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWRpc2FibGVkLXRyYWlsaW5nLWljb24tY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLXRyYWlsaW5nLWNvbnRlbnQtb3BhY2l0eTogdmFyKC0tX3RleHQtZmllbGQtZGlzYWJsZWQtdHJhaWxpbmctaWNvbi1vcGFjaXR5KTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1lcnJvci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1jb250ZW50LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1lcnJvci1pbnB1dC10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1mb2N1cy1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1lcnJvci1mb2N1cy1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1mb2N1cy1jb250ZW50LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1lcnJvci1mb2N1cy1pbnB1dC10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1mb2N1cy1sYWJlbC10ZXh0LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1lcnJvci1mb2N1cy1sYWJlbC10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1mb2N1cy1sZWFkaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWVycm9yLWZvY3VzLWxlYWRpbmctaWNvbi1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZXJyb3ItZm9jdXMtc3VwcG9ydGluZy10ZXh0LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1lcnJvci1mb2N1cy1zdXBwb3J0aW5nLXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWZvY3VzLXRyYWlsaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWVycm9yLWZvY3VzLXRyYWlsaW5nLWljb24tY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWhvdmVyLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWVycm9yLWhvdmVyLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWhvdmVyLWNvbnRlbnQtY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWVycm9yLWhvdmVyLWlucHV0LXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWhvdmVyLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWVycm9yLWhvdmVyLWxhYmVsLXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWhvdmVyLWxlYWRpbmctY29udGVudC1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtZXJyb3ItaG92ZXItbGVhZGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1ob3Zlci1zdGF0ZS1sYXllci1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtZXJyb3ItaG92ZXItc3RhdGUtbGF5ZXItY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWhvdmVyLXN0YXRlLWxheWVyLW9wYWNpdHk6IHZhcigtLV90ZXh0LWZpZWxkLWVycm9yLWhvdmVyLXN0YXRlLWxheWVyLW9wYWNpdHkpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWhvdmVyLXN1cHBvcnRpbmctdGV4dC1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtZXJyb3ItaG92ZXItc3VwcG9ydGluZy10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1ob3Zlci10cmFpbGluZy1jb250ZW50LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1lcnJvci1ob3Zlci10cmFpbGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1sYWJlbC10ZXh0LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1lcnJvci1sYWJlbC10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1sZWFkaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWVycm9yLWxlYWRpbmctaWNvbi1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZXJyb3Itc3VwcG9ydGluZy10ZXh0LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1lcnJvci1zdXBwb3J0aW5nLXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLXRyYWlsaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWVycm9yLXRyYWlsaW5nLWljb24tY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWZvY3VzLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWZvY3VzLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWZvY3VzLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0OiB2YXIoLS1fdGV4dC1maWVsZC1mb2N1cy1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodCk7LS1tZC1maWxsZWQtZmllbGQtZm9jdXMtY29udGVudC1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtZm9jdXMtaW5wdXQtdGV4dC1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZm9jdXMtbGFiZWwtdGV4dC1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtZm9jdXMtbGFiZWwtdGV4dC1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZm9jdXMtbGVhZGluZy1jb250ZW50LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1mb2N1cy1sZWFkaW5nLWljb24tY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWZvY3VzLXN1cHBvcnRpbmctdGV4dC1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtZm9jdXMtc3VwcG9ydGluZy10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1mb2N1cy10cmFpbGluZy1jb250ZW50LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1mb2N1cy10cmFpbGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodDogdmFyKC0tX3RleHQtZmllbGQtaG92ZXItYWN0aXZlLWluZGljYXRvci1oZWlnaHQpOy0tbWQtZmlsbGVkLWZpZWxkLWhvdmVyLWNvbnRlbnQtY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWhvdmVyLWlucHV0LXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWhvdmVyLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWhvdmVyLWxhYmVsLXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWhvdmVyLWxlYWRpbmctY29udGVudC1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtaG92ZXItbGVhZGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1ob3Zlci1zdGF0ZS1sYXllci1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtaG92ZXItc3RhdGUtbGF5ZXItY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWhvdmVyLXN0YXRlLWxheWVyLW9wYWNpdHk6IHZhcigtLV90ZXh0LWZpZWxkLWhvdmVyLXN0YXRlLWxheWVyLW9wYWNpdHkpOy0tbWQtZmlsbGVkLWZpZWxkLWhvdmVyLXN1cHBvcnRpbmctdGV4dC1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtaG92ZXItc3VwcG9ydGluZy10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1ob3Zlci10cmFpbGluZy1jb250ZW50LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1ob3Zlci10cmFpbGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1sYWJlbC10ZXh0LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1sYWJlbC10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1sYWJlbC10ZXh0LWZvbnQ6IHZhcigtLV90ZXh0LWZpZWxkLWxhYmVsLXRleHQtZm9udCk7LS1tZC1maWxsZWQtZmllbGQtbGFiZWwtdGV4dC1saW5lLWhlaWdodDogdmFyKC0tX3RleHQtZmllbGQtbGFiZWwtdGV4dC1saW5lLWhlaWdodCk7LS1tZC1maWxsZWQtZmllbGQtbGFiZWwtdGV4dC1wb3B1bGF0ZWQtbGluZS1oZWlnaHQ6IHZhcigtLV90ZXh0LWZpZWxkLWxhYmVsLXRleHQtcG9wdWxhdGVkLWxpbmUtaGVpZ2h0KTstLW1kLWZpbGxlZC1maWVsZC1sYWJlbC10ZXh0LXBvcHVsYXRlZC1zaXplOiB2YXIoLS1fdGV4dC1maWVsZC1sYWJlbC10ZXh0LXBvcHVsYXRlZC1zaXplKTstLW1kLWZpbGxlZC1maWVsZC1sYWJlbC10ZXh0LXNpemU6IHZhcigtLV90ZXh0LWZpZWxkLWxhYmVsLXRleHQtc2l6ZSk7LS1tZC1maWxsZWQtZmllbGQtbGFiZWwtdGV4dC13ZWlnaHQ6IHZhcigtLV90ZXh0LWZpZWxkLWxhYmVsLXRleHQtd2VpZ2h0KTstLW1kLWZpbGxlZC1maWVsZC1sZWFkaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV90ZXh0LWZpZWxkLWxlYWRpbmctaWNvbi1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtc3VwcG9ydGluZy10ZXh0LWNvbG9yOiB2YXIoLS1fdGV4dC1maWVsZC1zdXBwb3J0aW5nLXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLXN1cHBvcnRpbmctdGV4dC1mb250OiB2YXIoLS1fdGV4dC1maWVsZC1zdXBwb3J0aW5nLXRleHQtZm9udCk7LS1tZC1maWxsZWQtZmllbGQtc3VwcG9ydGluZy10ZXh0LWxpbmUtaGVpZ2h0OiB2YXIoLS1fdGV4dC1maWVsZC1zdXBwb3J0aW5nLXRleHQtbGluZS1oZWlnaHQpOy0tbWQtZmlsbGVkLWZpZWxkLXN1cHBvcnRpbmctdGV4dC1zaXplOiB2YXIoLS1fdGV4dC1maWVsZC1zdXBwb3J0aW5nLXRleHQtc2l6ZSk7LS1tZC1maWxsZWQtZmllbGQtc3VwcG9ydGluZy10ZXh0LXdlaWdodDogdmFyKC0tX3RleHQtZmllbGQtc3VwcG9ydGluZy10ZXh0LXdlaWdodCk7LS1tZC1maWxsZWQtZmllbGQtdHJhaWxpbmctY29udGVudC1jb2xvcjogdmFyKC0tX3RleHQtZmllbGQtdHJhaWxpbmctaWNvbi1jb2xvcil9W2hhcy1zdGFydF0gLmljb24ubGVhZGluZ3tmb250LXNpemU6dmFyKC0tX3RleHQtZmllbGQtbGVhZGluZy1pY29uLXNpemUpO2hlaWdodDp2YXIoLS1fdGV4dC1maWVsZC1sZWFkaW5nLWljb24tc2l6ZSk7d2lkdGg6dmFyKC0tX3RleHQtZmllbGQtbGVhZGluZy1pY29uLXNpemUpfS5pY29uLnRyYWlsaW5ne2ZvbnQtc2l6ZTp2YXIoLS1fdGV4dC1maWVsZC10cmFpbGluZy1pY29uLXNpemUpO2hlaWdodDp2YXIoLS1fdGV4dC1maWVsZC10cmFpbGluZy1pY29uLXNpemUpO3dpZHRoOnZhcigtLV90ZXh0LWZpZWxkLXRyYWlsaW5nLWljb24tc2l6ZSl9XG5gO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZmlsbGVkLXNlbGVjdC1zdHlsZXMuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjMgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuaW1wb3J0ICcuLi8uLi9maWVsZC9maWxsZWQtZmllbGQuanMnO1xuaW1wb3J0IHsgbGl0ZXJhbCB9IGZyb20gJ2xpdC9zdGF0aWMtaHRtbC5qcyc7XG5pbXBvcnQgeyBTZWxlY3QgfSBmcm9tICcuL3NlbGVjdC5qcyc7XG4vLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6ZW5mb3JjZS1jb21tZW50cy1vbi1leHBvcnRlZC1zeW1ib2xzXG5leHBvcnQgY2xhc3MgRmlsbGVkU2VsZWN0IGV4dGVuZHMgU2VsZWN0IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgdGhpcy5maWVsZFRhZyA9IGxpdGVyYWwgYG1kLWZpbGxlZC1maWVsZGA7XG4gICAgfVxufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZmlsbGVkLXNlbGVjdC5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG52YXIgX2E7XG5pbXBvcnQgeyBfX2RlY29yYXRlIH0gZnJvbSBcInRzbGliXCI7XG5pbXBvcnQgJy4uLy4uL21lbnUvbWVudS5qcyc7XG5pbXBvcnQgeyBodG1sLCBpc1NlcnZlciwgTGl0RWxlbWVudCwgbm90aGluZyB9IGZyb20gJ2xpdCc7XG5pbXBvcnQgeyBwcm9wZXJ0eSwgcXVlcnksIHF1ZXJ5QXNzaWduZWRFbGVtZW50cywgc3RhdGUgfSBmcm9tICdsaXQvZGVjb3JhdG9ycy5qcyc7XG5pbXBvcnQgeyBjbGFzc01hcCB9IGZyb20gJ2xpdC9kaXJlY3RpdmVzL2NsYXNzLW1hcC5qcyc7XG5pbXBvcnQgeyBzdHlsZU1hcCB9IGZyb20gJ2xpdC9kaXJlY3RpdmVzL3N0eWxlLW1hcC5qcyc7XG5pbXBvcnQgeyBodG1sIGFzIHN0YXRpY0h0bWwgfSBmcm9tICdsaXQvc3RhdGljLWh0bWwuanMnO1xuaW1wb3J0IHsgbWl4aW5EZWxlZ2F0ZXNBcmlhIH0gZnJvbSAnLi4vLi4vaW50ZXJuYWwvYXJpYS9kZWxlZ2F0ZS5qcyc7XG5pbXBvcnQgeyByZWRpc3BhdGNoRXZlbnQgfSBmcm9tICcuLi8uLi9pbnRlcm5hbC9ldmVudHMvcmVkaXNwYXRjaC1ldmVudC5qcyc7XG5pbXBvcnQgeyBjcmVhdGVWYWxpZGF0b3IsIGdldFZhbGlkaXR5QW5jaG9yLCBtaXhpbkNvbnN0cmFpbnRWYWxpZGF0aW9uLCB9IGZyb20gJy4uLy4uL2xhYnMvYmVoYXZpb3JzL2NvbnN0cmFpbnQtdmFsaWRhdGlvbi5qcyc7XG5pbXBvcnQgeyBtaXhpbkVsZW1lbnRJbnRlcm5hbHMgfSBmcm9tICcuLi8uLi9sYWJzL2JlaGF2aW9ycy9lbGVtZW50LWludGVybmFscy5qcyc7XG5pbXBvcnQgeyBnZXRGb3JtVmFsdWUsIG1peGluRm9ybUFzc29jaWF0ZWQsIH0gZnJvbSAnLi4vLi4vbGFicy9iZWhhdmlvcnMvZm9ybS1hc3NvY2lhdGVkLmpzJztcbmltcG9ydCB7IG1peGluT25SZXBvcnRWYWxpZGl0eSwgb25SZXBvcnRWYWxpZGl0eSwgfSBmcm9tICcuLi8uLi9sYWJzL2JlaGF2aW9ycy9vbi1yZXBvcnQtdmFsaWRpdHkuanMnO1xuaW1wb3J0IHsgU2VsZWN0VmFsaWRhdG9yIH0gZnJvbSAnLi4vLi4vbGFicy9iZWhhdmlvcnMvdmFsaWRhdG9ycy9zZWxlY3QtdmFsaWRhdG9yLmpzJztcbmltcG9ydCB7IGdldEFjdGl2ZUl0ZW0gfSBmcm9tICcuLi8uLi9saXN0L2ludGVybmFsL2xpc3QtbmF2aWdhdGlvbi1oZWxwZXJzLmpzJztcbmltcG9ydCB7IEZvY3VzU3RhdGUsIGlzRWxlbWVudEluU3VidHJlZSwgaXNTZWxlY3RhYmxlS2V5LCB9IGZyb20gJy4uLy4uL21lbnUvaW50ZXJuYWwvY29udHJvbGxlcnMvc2hhcmVkLmpzJztcbmltcG9ydCB7IFRZUEVBSEVBRF9SRUNPUkQgfSBmcm9tICcuLi8uLi9tZW51L2ludGVybmFsL2NvbnRyb2xsZXJzL3R5cGVhaGVhZENvbnRyb2xsZXIuanMnO1xuaW1wb3J0IHsgREVGQVVMVF9UWVBFQUhFQURfQlVGRkVSX1RJTUUgfSBmcm9tICcuLi8uLi9tZW51L2ludGVybmFsL21lbnUuanMnO1xuaW1wb3J0IHsgZ2V0U2VsZWN0ZWRJdGVtcyB9IGZyb20gJy4vc2hhcmVkLmpzJztcbmNvbnN0IFZBTFVFID0gU3ltYm9sKCd2YWx1ZScpO1xuLy8gU2VwYXJhdGUgdmFyaWFibGUgbmVlZGVkIGZvciBjbG9zdXJlLlxuY29uc3Qgc2VsZWN0QmFzZUNsYXNzID0gbWl4aW5EZWxlZ2F0ZXNBcmlhKG1peGluT25SZXBvcnRWYWxpZGl0eShtaXhpbkNvbnN0cmFpbnRWYWxpZGF0aW9uKG1peGluRm9ybUFzc29jaWF0ZWQobWl4aW5FbGVtZW50SW50ZXJuYWxzKExpdEVsZW1lbnQpKSkpKTtcbi8qKlxuICogQGZpcmVzIGNoYW5nZSB7RXZlbnR9IFRoZSBuYXRpdmUgYGNoYW5nZWAgZXZlbnQgb25cbiAqIFtgPGlucHV0PmBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9IVE1MRWxlbWVudC9jaGFuZ2VfZXZlbnQpXG4gKiAtLWJ1YmJsZXNcbiAqIEBmaXJlcyBpbnB1dCB7SW5wdXRFdmVudH0gVGhlIG5hdGl2ZSBgaW5wdXRgIGV2ZW50IG9uXG4gKiBbYDxpbnB1dD5gXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvSFRNTEVsZW1lbnQvaW5wdXRfZXZlbnQpXG4gKiAtLWJ1YmJsZXMgLS1jb21wb3NlZFxuICogQGZpcmVzIG9wZW5pbmcge0V2ZW50fSBGaXJlZCB3aGVuIHRoZSBzZWxlY3QncyBtZW51IGlzIGFib3V0IHRvIG9wZW4uXG4gKiBAZmlyZXMgb3BlbmVkIHtFdmVudH0gRmlyZWQgd2hlbiB0aGUgc2VsZWN0J3MgbWVudSBoYXMgZmluaXNoZWQgYW5pbWF0aW9uc1xuICogYW5kIG9wZW5lZC5cbiAqIEBmaXJlcyBjbG9zaW5nIHtFdmVudH0gRmlyZWQgd2hlbiB0aGUgc2VsZWN0J3MgbWVudSBpcyBhYm91dCB0byBjbG9zZS5cbiAqIEBmaXJlcyBjbG9zZWQge0V2ZW50fSBGaXJlZCB3aGVuIHRoZSBzZWxlY3QncyBtZW51IGhhcyBmaW5pc2hlZCBhbmltYXRpb25zXG4gKiBhbmQgY2xvc2VkLlxuICovXG5leHBvcnQgY2xhc3MgU2VsZWN0IGV4dGVuZHMgc2VsZWN0QmFzZUNsYXNzIHtcbiAgICAvKipcbiAgICAgKiBUaGUgdmFsdWUgb2YgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBvcHRpb24uXG4gICAgICpcbiAgICAgKiBOb3RlOiBGb3IgU1NSLCBzZXQgYFtzZWxlY3RlZF1gIG9uIHRoZSByZXF1ZXN0ZWQgb3B0aW9uIGFuZCBgZGlzcGxheVRleHRgXG4gICAgICogcmF0aGVyIHRoYW4gc2V0dGluZyBgdmFsdWVgIHNldHRpbmcgYHZhbHVlYCB3aWxsIGluY3VyIGEgRE9NIHF1ZXJ5LlxuICAgICAqL1xuICAgIGdldCB2YWx1ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbVkFMVUVdO1xuICAgIH1cbiAgICBzZXQgdmFsdWUodmFsdWUpIHtcbiAgICAgICAgaWYgKGlzU2VydmVyKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB0aGlzLmxhc3RVc2VyU2V0VmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgdGhpcy5zZWxlY3QodmFsdWUpO1xuICAgIH1cbiAgICBnZXQgb3B0aW9ucygpIHtcbiAgICAgICAgLy8gTk9URTogdGhpcyBkb2VzIGEgRE9NIHF1ZXJ5LlxuICAgICAgICByZXR1cm4gKHRoaXMubWVudT8uaXRlbXMgPz8gW10pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBUaGUgaW5kZXggb2YgdGhlIGN1cnJlbnRseSBzZWxlY3RlZCBvcHRpb24uXG4gICAgICpcbiAgICAgKiBOb3RlOiBGb3IgU1NSLCBzZXQgYFtzZWxlY3RlZF1gIG9uIHRoZSByZXF1ZXN0ZWQgb3B0aW9uIGFuZCBgZGlzcGxheVRleHRgXG4gICAgICogcmF0aGVyIHRoYW4gc2V0dGluZyBgc2VsZWN0ZWRJbmRleGAgc2V0dGluZyBgc2VsZWN0ZWRJbmRleGAgd2lsbCBpbmN1ciBhXG4gICAgICogRE9NIHF1ZXJ5LlxuICAgICAqL1xuICAgIGdldCBzZWxlY3RlZEluZGV4KCkge1xuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6ZW5mb3JjZS1uYW1lLWNhc2luZ1xuICAgICAgICBjb25zdCBbX29wdGlvbiwgaW5kZXhdID0gKHRoaXMuZ2V0U2VsZWN0ZWRPcHRpb25zKCkgPz8gW10pWzBdID8/IFtdO1xuICAgICAgICByZXR1cm4gaW5kZXggPz8gLTE7XG4gICAgfVxuICAgIHNldCBzZWxlY3RlZEluZGV4KGluZGV4KSB7XG4gICAgICAgIHRoaXMubGFzdFVzZXJTZXRTZWxlY3RlZEluZGV4ID0gaW5kZXg7XG4gICAgICAgIHRoaXMuc2VsZWN0SW5kZXgoaW5kZXgpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIGFycmF5IG9mIHNlbGVjdGVkIG9wdGlvbnMuXG4gICAgICpcbiAgICAgKiBOT1RFOiBtZC1zZWxlY3Qgb25seSBzdXBwb3J0cyBzaW5nbGUgc2VsZWN0aW9uLlxuICAgICAqL1xuICAgIGdldCBzZWxlY3RlZE9wdGlvbnMoKSB7XG4gICAgICAgIHJldHVybiAodGhpcy5nZXRTZWxlY3RlZE9wdGlvbnMoKSA/PyBbXSkubWFwKChbb3B0aW9uXSkgPT4gb3B0aW9uKTtcbiAgICB9XG4gICAgZ2V0IGhhc0Vycm9yKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lcnJvciB8fCB0aGlzLm5hdGl2ZUVycm9yO1xuICAgIH1cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIE9wZW5zIHRoZSBtZW51IHN5bmNocm9ub3VzbHkgd2l0aCBubyBhbmltYXRpb24uXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnF1aWNrID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXaGV0aGVyIG9yIG5vdCB0aGUgc2VsZWN0IGlzIHJlcXVpcmVkLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5yZXF1aXJlZCA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIGVycm9yIG1lc3NhZ2UgdGhhdCByZXBsYWNlcyBzdXBwb3J0aW5nIHRleHQgd2hlbiBgZXJyb3JgIGlzIHRydWUuIElmXG4gICAgICAgICAqIGBlcnJvclRleHRgIGlzIGFuIGVtcHR5IHN0cmluZywgdGhlbiB0aGUgc3VwcG9ydGluZyB0ZXh0IHdpbGwgY29udGludWUgdG9cbiAgICAgICAgICogc2hvdy5cbiAgICAgICAgICpcbiAgICAgICAgICogVGhpcyBlcnJvciBtZXNzYWdlIG92ZXJyaWRlcyB0aGUgZXJyb3IgbWVzc2FnZSBkaXNwbGF5ZWQgYnlcbiAgICAgICAgICogYHJlcG9ydFZhbGlkaXR5KClgLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5lcnJvclRleHQgPSAnJztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBmbG9hdGluZyBsYWJlbCBmb3IgdGhlIGZpZWxkLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5sYWJlbCA9ICcnO1xuICAgICAgICAvKipcbiAgICAgICAgICogRGlzYWJsZXMgdGhlIGFzdGVyaXNrIG9uIHRoZSBmbG9hdGluZyBsYWJlbCwgd2hlbiB0aGUgc2VsZWN0IGlzXG4gICAgICAgICAqIHJlcXVpcmVkLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5ub0FzdGVyaXNrID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb252ZXlzIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gYmVsb3cgdGhlIHNlbGVjdCwgc3VjaCBhcyBob3cgaXQgc2hvdWxkXG4gICAgICAgICAqIGJlIHVzZWQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnN1cHBvcnRpbmdUZXh0ID0gJyc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHZXRzIG9yIHNldHMgd2hldGhlciBvciBub3QgdGhlIHNlbGVjdCBpcyBpbiBhIHZpc3VhbGx5IGludmFsaWQgc3RhdGUuXG4gICAgICAgICAqXG4gICAgICAgICAqIFRoaXMgZXJyb3Igc3RhdGUgb3ZlcnJpZGVzIHRoZSBlcnJvciBzdGF0ZSBjb250cm9sbGVkIGJ5XG4gICAgICAgICAqIGByZXBvcnRWYWxpZGl0eSgpYC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZXJyb3IgPSBmYWxzZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdoZXRoZXIgb3Igbm90IHRoZSB1bmRlcmx5aW5nIG1kLW1lbnUgc2hvdWxkIGJlIHBvc2l0aW9uOiBmaXhlZCB0byBkaXNwbGF5XG4gICAgICAgICAqIGluIGEgdG9wLWxldmVsIG1hbm5lciwgb3IgcG9zaXRpb246IGFic29sdXRlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBwb3NpdGlvbjpmaXhlZCBpcyB1c2VmdWwgZm9yIGNhc2VzIHdoZXJlIHNlbGVjdCBpcyBpbnNpZGUgb2YgYW5vdGhlclxuICAgICAgICAgKiBlbGVtZW50IHdpdGggc3RhY2tpbmcgY29udGV4dCBhbmQgaGlkZGVuIG92ZXJmbG93cyBzdWNoIGFzIGBtZC1kaWFsb2dgLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5tZW51UG9zaXRpb25pbmcgPSAncG9wb3Zlcic7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDbGFtcHMgdGhlIG1lbnUtd2lkdGggdG8gdGhlIHdpZHRoIG9mIHRoZSBzZWxlY3QuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmNsYW1wTWVudVdpZHRoID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgbWF4IHRpbWUgYmV0d2VlbiB0aGUga2V5c3Ryb2tlcyBvZiB0aGUgdHlwZWFoZWFkIHNlbGVjdCAvIG1lbnUgYmVoYXZpb3JcbiAgICAgICAgICogYmVmb3JlIGl0IGNsZWFycyB0aGUgdHlwZWFoZWFkIGJ1ZmZlci5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMudHlwZWFoZWFkRGVsYXkgPSBERUZBVUxUX1RZUEVBSEVBRF9CVUZGRVJfVElNRTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdoZXRoZXIgb3Igbm90IHRoZSB0ZXh0IGZpZWxkIGhhcyBhIGxlYWRpbmcgaWNvbi4gVXNlZCBmb3IgU1NSLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5oYXNMZWFkaW5nSWNvbiA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogVGV4dCB0byBkaXNwbGF5IGluIHRoZSBmaWVsZC4gT25seSBzZXQgZm9yIFNTUi5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZGlzcGxheVRleHQgPSAnJztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdoZXRoZXIgdGhlIG1lbnUgc2hvdWxkIGJlIGFsaWduZWQgdG8gdGhlIHN0YXJ0IG9yIHRoZSBlbmQgb2YgdGhlIHNlbGVjdCdzXG4gICAgICAgICAqIHRleHRib3guXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLm1lbnVBbGlnbiA9ICdzdGFydCc7XG4gICAgICAgIHRoaXNbX2FdID0gJyc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBVc2VkIGZvciBpbml0aWFsaXppbmcgc2VsZWN0IHdoZW4gdGhlIHVzZXIgc2V0cyB0aGUgYHZhbHVlYCBkaXJlY3RseS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMubGFzdFVzZXJTZXRWYWx1ZSA9IG51bGw7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBVc2VkIGZvciBpbml0aWFsaXppbmcgc2VsZWN0IHdoZW4gdGhlIHVzZXIgc2V0cyB0aGUgYHNlbGVjdGVkSW5kZXhgXG4gICAgICAgICAqIGRpcmVjdGx5LlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5sYXN0VXNlclNldFNlbGVjdGVkSW5kZXggPSBudWxsO1xuICAgICAgICAvKipcbiAgICAgICAgICogVXNlZCBmb3IgYGlucHV0YCBhbmQgYGNoYW5nZWAgZXZlbnQgY2hhbmdlIGRldGVjdGlvbi5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMubGFzdFNlbGVjdGVkT3B0aW9uID0gbnVsbDtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmVuZm9yY2UtbmFtZS1jYXNpbmdcbiAgICAgICAgdGhpcy5sYXN0U2VsZWN0ZWRPcHRpb25SZWNvcmRzID0gW107XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXaGV0aGVyIG9yIG5vdCBhIG5hdGl2ZSBlcnJvciBoYXMgYmVlbiByZXBvcnRlZCB2aWEgYHJlcG9ydFZhbGlkaXR5KClgLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5uYXRpdmVFcnJvciA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIHZhbGlkYXRpb24gbWVzc2FnZSBkaXNwbGF5ZWQgZnJvbSBhIG5hdGl2ZSBlcnJvciB2aWFcbiAgICAgICAgICogYHJlcG9ydFZhbGlkaXR5KClgLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5uYXRpdmVFcnJvclRleHQgPSAnJztcbiAgICAgICAgdGhpcy5mb2N1c2VkID0gZmFsc2U7XG4gICAgICAgIHRoaXMub3BlbiA9IGZhbHNlO1xuICAgICAgICB0aGlzLmRlZmF1bHRGb2N1cyA9IEZvY3VzU3RhdGUuTk9ORTtcbiAgICAgICAgLy8gSGF2ZSB0byBrZWVwIHRyYWNrIG9mIHByZXZpb3VzIG9wZW4gYmVjYXVzZSBpdCdzIHN0YXRlIGFuZCBwcml2YXRlIGFuZCB0aHVzXG4gICAgICAgIC8vIGNhbm5vdCBiZSB0cmFja2VkIGluIFByb3BlcnR5VmFsdWVzPHRoaXM+IG1hcC5cbiAgICAgICAgdGhpcy5wcmV2T3BlbiA9IHRoaXMub3BlbjtcbiAgICAgICAgdGhpcy5zZWxlY3RXaWR0aCA9IDA7XG4gICAgICAgIGlmIChpc1NlcnZlcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLmhhbmRsZUZvY3VzLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLCB0aGlzLmhhbmRsZUJsdXIuYmluZCh0aGlzKSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNlbGVjdHMgYW4gb3B0aW9uIGdpdmVuIHRoZSB2YWx1ZSBvZiB0aGUgb3B0aW9uLCBhbmQgdXBkYXRlcyBNZFNlbGVjdCdzXG4gICAgICogdmFsdWUuXG4gICAgICovXG4gICAgc2VsZWN0KHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvblRvU2VsZWN0ID0gdGhpcy5vcHRpb25zLmZpbmQoKG9wdGlvbikgPT4gb3B0aW9uLnZhbHVlID09PSB2YWx1ZSk7XG4gICAgICAgIGlmIChvcHRpb25Ub1NlbGVjdCkge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RJdGVtKG9wdGlvblRvU2VsZWN0KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZWxlY3RzIGFuIG9wdGlvbiBnaXZlbiB0aGUgaW5kZXggb2YgdGhlIG9wdGlvbiwgYW5kIHVwZGF0ZXMgTWRTZWxlY3Qnc1xuICAgICAqIHZhbHVlLlxuICAgICAqL1xuICAgIHNlbGVjdEluZGV4KGluZGV4KSB7XG4gICAgICAgIGNvbnN0IG9wdGlvblRvU2VsZWN0ID0gdGhpcy5vcHRpb25zW2luZGV4XTtcbiAgICAgICAgaWYgKG9wdGlvblRvU2VsZWN0KSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdEl0ZW0ob3B0aW9uVG9TZWxlY3QpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlc2V0IHRoZSBzZWxlY3QgdG8gaXRzIGRlZmF1bHQgdmFsdWUuXG4gICAgICovXG4gICAgcmVzZXQoKSB7XG4gICAgICAgIGZvciAoY29uc3Qgb3B0aW9uIG9mIHRoaXMub3B0aW9ucykge1xuICAgICAgICAgICAgb3B0aW9uLnNlbGVjdGVkID0gb3B0aW9uLmhhc0F0dHJpYnV0ZSgnc2VsZWN0ZWQnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlQW5kRGlzcGxheVRleHQoKTtcbiAgICAgICAgdGhpcy5uYXRpdmVFcnJvciA9IGZhbHNlO1xuICAgICAgICB0aGlzLm5hdGl2ZUVycm9yVGV4dCA9ICcnO1xuICAgIH1cbiAgICBbKF9hID0gVkFMVUUsIG9uUmVwb3J0VmFsaWRpdHkpXShpbnZhbGlkRXZlbnQpIHtcbiAgICAgICAgLy8gUHJldmVudCBkZWZhdWx0IHBvcC11cCBiZWhhdmlvci5cbiAgICAgICAgaW52YWxpZEV2ZW50Py5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBjb25zdCBwcmV2TWVzc2FnZSA9IHRoaXMuZ2V0RXJyb3JUZXh0KCk7XG4gICAgICAgIHRoaXMubmF0aXZlRXJyb3IgPSAhIWludmFsaWRFdmVudDtcbiAgICAgICAgdGhpcy5uYXRpdmVFcnJvclRleHQgPSB0aGlzLnZhbGlkYXRpb25NZXNzYWdlO1xuICAgICAgICBpZiAocHJldk1lc3NhZ2UgPT09IHRoaXMuZ2V0RXJyb3JUZXh0KCkpIHtcbiAgICAgICAgICAgIHRoaXMuZmllbGQ/LnJlYW5ub3VuY2VFcnJvcigpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHVwZGF0ZShjaGFuZ2VkKSB7XG4gICAgICAgIC8vIEluIFNTUiB0aGUgb3B0aW9ucyB3aWxsIGJlIHJlYWR5IHRvIHF1ZXJ5LCBzbyB0cnkgdG8gZmlndXJlIG91dCB3aGF0XG4gICAgICAgIC8vIHRoZSB2YWx1ZSBhbmQgZGlzcGxheSB0ZXh0IHNob3VsZCBiZS5cbiAgICAgICAgaWYgKCF0aGlzLmhhc1VwZGF0ZWQpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFVzZXJTZWxlY3Rpb24oKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBXZSBoYXZlIGp1c3Qgb3BlbmVkIHRoZSBtZW51LlxuICAgICAgICAvLyBXZSBhcmUgb25seSBhYmxlIHRvIGNoZWNrIGZvciB0aGUgc2VsZWN0J3MgcmVjdCBpbiBgdXBkYXRlKClgIGluc3RlYWQgb2ZcbiAgICAgICAgLy8gaGF2aW5nIHRvIHdhaXQgZm9yIGB1cGRhdGVkKClgIGJlY2F1c2UgdGhlIG1lbnUgY2FuIG5ldmVyIGJlIG9wZW4gb25cbiAgICAgICAgLy8gZmlyc3QgcmVuZGVyIHNpbmNlIGl0IGlzIG5vdCBzZXR0YWJsZSBhbmQgTGl0IFNTUiBkb2VzIG5vdCBzdXBwb3J0IGNsaWNrXG4gICAgICAgIC8vIGV2ZW50cyB3aGljaCB3b3VsZCBvcGVuIHRoZSBtZW51LlxuICAgICAgICBpZiAodGhpcy5wcmV2T3BlbiAhPT0gdGhpcy5vcGVuICYmIHRoaXMub3Blbikge1xuICAgICAgICAgICAgY29uc3Qgc2VsZWN0UmVjdCA9IHRoaXMuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdFdpZHRoID0gc2VsZWN0UmVjdC53aWR0aDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnByZXZPcGVuID0gdGhpcy5vcGVuO1xuICAgICAgICBzdXBlci51cGRhdGUoY2hhbmdlZCk7XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYFxuICAgICAgPHNwYW5cbiAgICAgICAgY2xhc3M9XCJzZWxlY3QgJHtjbGFzc01hcCh0aGlzLmdldFJlbmRlckNsYXNzZXMoKSl9XCJcbiAgICAgICAgQGZvY3Vzb3V0PSR7dGhpcy5oYW5kbGVGb2N1c291dH0+XG4gICAgICAgICR7dGhpcy5yZW5kZXJGaWVsZCgpfSAke3RoaXMucmVuZGVyTWVudSgpfVxuICAgICAgPC9zcGFuPlxuICAgIGA7XG4gICAgfVxuICAgIGFzeW5jIGZpcnN0VXBkYXRlZChjaGFuZ2VkKSB7XG4gICAgICAgIGF3YWl0IHRoaXMubWVudT8udXBkYXRlQ29tcGxldGU7XG4gICAgICAgIC8vIElmIHRoaXMgaGFzIGJlZW4gaGFuZGxlZCBvbiB1cGRhdGUgYWxyZWFkeSBkdWUgdG8gU1NSLCB0cnkgYWdhaW4uXG4gICAgICAgIGlmICghdGhpcy5sYXN0U2VsZWN0ZWRPcHRpb25SZWNvcmRzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhpcy5pbml0VXNlclNlbGVjdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIC8vIENhc2UgZm9yIHdoZW4gdGhlIERPTSBpcyBzdHJlYW1pbmcsIHRoZXJlIGFyZSBubyBjaGlsZHJlbiwgYW5kIGEgY2hpbGRcbiAgICAgICAgLy8gaGFzIFtzZWxlY3RlZF0gc2V0IG9uIGl0LCB3ZSBuZWVkIHRvIHdhaXQgZm9yIERPTSB0byByZW5kZXIgc29tZXRoaW5nLlxuICAgICAgICBpZiAoIXRoaXMubGFzdFNlbGVjdGVkT3B0aW9uUmVjb3Jkcy5sZW5ndGggJiZcbiAgICAgICAgICAgICFpc1NlcnZlciAmJlxuICAgICAgICAgICAgIXRoaXMub3B0aW9ucy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlVmFsdWVBbmREaXNwbGF5VGV4dCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgc3VwZXIuZmlyc3RVcGRhdGVkKGNoYW5nZWQpO1xuICAgIH1cbiAgICBnZXRSZW5kZXJDbGFzc2VzKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgJ2Rpc2FibGVkJzogdGhpcy5kaXNhYmxlZCxcbiAgICAgICAgICAgICdlcnJvcic6IHRoaXMuZXJyb3IsXG4gICAgICAgICAgICAnb3Blbic6IHRoaXMub3BlbixcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmVuZGVyRmllbGQoKSB7XG4gICAgICAgIGNvbnN0IGFyaWFMYWJlbCA9IHRoaXMuYXJpYUxhYmVsIHx8IHRoaXMubGFiZWw7XG4gICAgICAgIHJldHVybiBzdGF0aWNIdG1sIGBcbiAgICAgIDwke3RoaXMuZmllbGRUYWd9XG4gICAgICAgICAgYXJpYS1oYXNwb3B1cD1cImxpc3Rib3hcIlxuICAgICAgICAgIHJvbGU9XCJjb21ib2JveFwiXG4gICAgICAgICAgcGFydD1cImZpZWxkXCJcbiAgICAgICAgICBpZD1cImZpZWxkXCJcbiAgICAgICAgICB0YWJpbmRleD0ke3RoaXMuZGlzYWJsZWQgPyAnLTEnIDogJzAnfVxuICAgICAgICAgIGFyaWEtbGFiZWw9JHthcmlhTGFiZWwgfHwgbm90aGluZ31cbiAgICAgICAgICBhcmlhLWRlc2NyaWJlZGJ5PVwiZGVzY3JpcHRpb25cIlxuICAgICAgICAgIGFyaWEtZXhwYW5kZWQ9JHt0aGlzLm9wZW4gPyAndHJ1ZScgOiAnZmFsc2UnfVxuICAgICAgICAgIGFyaWEtY29udHJvbHM9XCJsaXN0Ym94XCJcbiAgICAgICAgICBjbGFzcz1cImZpZWxkXCJcbiAgICAgICAgICBsYWJlbD0ke3RoaXMubGFiZWx9XG4gICAgICAgICAgP25vLWFzdGVyaXNrPSR7dGhpcy5ub0FzdGVyaXNrfVxuICAgICAgICAgIC5mb2N1c2VkPSR7dGhpcy5mb2N1c2VkIHx8IHRoaXMub3Blbn1cbiAgICAgICAgICAucG9wdWxhdGVkPSR7ISF0aGlzLmRpc3BsYXlUZXh0fVxuICAgICAgICAgIC5kaXNhYmxlZD0ke3RoaXMuZGlzYWJsZWR9XG4gICAgICAgICAgLnJlcXVpcmVkPSR7dGhpcy5yZXF1aXJlZH1cbiAgICAgICAgICAuZXJyb3I9JHt0aGlzLmhhc0Vycm9yfVxuICAgICAgICAgID9oYXMtc3RhcnQ9JHt0aGlzLmhhc0xlYWRpbmdJY29ufVxuICAgICAgICAgIGhhcy1lbmRcbiAgICAgICAgICBzdXBwb3J0aW5nLXRleHQ9JHt0aGlzLnN1cHBvcnRpbmdUZXh0fVxuICAgICAgICAgIGVycm9yLXRleHQ9JHt0aGlzLmdldEVycm9yVGV4dCgpfVxuICAgICAgICAgIEBrZXlkb3duPSR7dGhpcy5oYW5kbGVLZXlkb3dufVxuICAgICAgICAgIEBjbGljaz0ke3RoaXMuaGFuZGxlQ2xpY2t9PlxuICAgICAgICAgJHt0aGlzLnJlbmRlckZpZWxkQ29udGVudCgpfVxuICAgICAgICAgPGRpdiBpZD1cImRlc2NyaXB0aW9uXCIgc2xvdD1cImFyaWEtZGVzY3JpYmVkYnlcIj48L2Rpdj5cbiAgICAgIDwvJHt0aGlzLmZpZWxkVGFnfT5gO1xuICAgIH1cbiAgICByZW5kZXJGaWVsZENvbnRlbnQoKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICB0aGlzLnJlbmRlckxlYWRpbmdJY29uKCksXG4gICAgICAgICAgICB0aGlzLnJlbmRlckxhYmVsKCksXG4gICAgICAgICAgICB0aGlzLnJlbmRlclRyYWlsaW5nSWNvbigpLFxuICAgICAgICBdO1xuICAgIH1cbiAgICByZW5kZXJMZWFkaW5nSWNvbigpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYFxuICAgICAgPHNwYW4gY2xhc3M9XCJpY29uIGxlYWRpbmdcIiBzbG90PVwic3RhcnRcIj5cbiAgICAgICAgPHNsb3QgbmFtZT1cImxlYWRpbmctaWNvblwiIEBzbG90Y2hhbmdlPSR7dGhpcy5oYW5kbGVJY29uQ2hhbmdlfT48L3Nsb3Q+XG4gICAgICA8L3NwYW4+XG4gICAgYDtcbiAgICB9XG4gICAgcmVuZGVyVHJhaWxpbmdJY29uKCkge1xuICAgICAgICByZXR1cm4gaHRtbCBgXG4gICAgICA8c3BhbiBjbGFzcz1cImljb24gdHJhaWxpbmdcIiBzbG90PVwiZW5kXCI+XG4gICAgICAgIDxzbG90IG5hbWU9XCJ0cmFpbGluZy1pY29uXCIgQHNsb3RjaGFuZ2U9JHt0aGlzLmhhbmRsZUljb25DaGFuZ2V9PlxuICAgICAgICAgIDxzdmcgaGVpZ2h0PVwiNVwiIHZpZXdCb3g9XCI3IDEwIDEwIDVcIiBmb2N1c2FibGU9XCJmYWxzZVwiPlxuICAgICAgICAgICAgPHBvbHlnb25cbiAgICAgICAgICAgICAgY2xhc3M9XCJkb3duXCJcbiAgICAgICAgICAgICAgc3Ryb2tlPVwibm9uZVwiXG4gICAgICAgICAgICAgIGZpbGwtcnVsZT1cImV2ZW5vZGRcIlxuICAgICAgICAgICAgICBwb2ludHM9XCI3IDEwIDEyIDE1IDE3IDEwXCI+PC9wb2x5Z29uPlxuICAgICAgICAgICAgPHBvbHlnb25cbiAgICAgICAgICAgICAgY2xhc3M9XCJ1cFwiXG4gICAgICAgICAgICAgIHN0cm9rZT1cIm5vbmVcIlxuICAgICAgICAgICAgICBmaWxsLXJ1bGU9XCJldmVub2RkXCJcbiAgICAgICAgICAgICAgcG9pbnRzPVwiNyAxNSAxMiAxMCAxNyAxNVwiPjwvcG9seWdvbj5cbiAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgPC9zbG90PlxuICAgICAgPC9zcGFuPlxuICAgIGA7XG4gICAgfVxuICAgIHJlbmRlckxhYmVsKCkge1xuICAgICAgICAvLyBuZWVkIHRvIHJlbmRlciAmbmJzcDsgc28gdGhhdCBsaW5lLWhlaWdodCBjYW4gYXBwbHkgYW5kIGdpdmUgaXQgYVxuICAgICAgICAvLyBub24temVybyBoZWlnaHRcbiAgICAgICAgcmV0dXJuIGh0bWwgYDxkaXYgaWQ9XCJsYWJlbFwiPiR7dGhpcy5kaXNwbGF5VGV4dCB8fCBodG1sIGAmbmJzcDtgfTwvZGl2PmA7XG4gICAgfVxuICAgIHJlbmRlck1lbnUoKSB7XG4gICAgICAgIGNvbnN0IGFyaWFMYWJlbCA9IHRoaXMubGFiZWwgfHwgdGhpcy5hcmlhTGFiZWw7XG4gICAgICAgIHJldHVybiBodG1sIGA8ZGl2IGNsYXNzPVwibWVudS13cmFwcGVyXCI+XG4gICAgICA8bWQtbWVudVxuICAgICAgICBpZD1cImxpc3Rib3hcIlxuICAgICAgICAuZGVmYXVsdEZvY3VzPSR7dGhpcy5kZWZhdWx0Rm9jdXN9XG4gICAgICAgIHJvbGU9XCJsaXN0Ym94XCJcbiAgICAgICAgdGFiaW5kZXg9XCItMVwiXG4gICAgICAgIGFyaWEtbGFiZWw9JHthcmlhTGFiZWwgfHwgbm90aGluZ31cbiAgICAgICAgc3RheS1vcGVuLW9uLWZvY3Vzb3V0XG4gICAgICAgIHBhcnQ9XCJtZW51XCJcbiAgICAgICAgZXhwb3J0cGFydHM9XCJmb2N1cy1yaW5nOiBtZW51LWZvY3VzLXJpbmdcIlxuICAgICAgICBhbmNob3I9XCJmaWVsZFwiXG4gICAgICAgIHN0eWxlPSR7c3R5bGVNYXAoe1xuICAgICAgICAgICAgJy0tX19tZW51LW1pbi13aWR0aCc6IGAke3RoaXMuc2VsZWN0V2lkdGh9cHhgLFxuICAgICAgICAgICAgJy0tX19tZW51LW1heC13aWR0aCc6IHRoaXMuY2xhbXBNZW51V2lkdGhcbiAgICAgICAgICAgICAgICA/IGAke3RoaXMuc2VsZWN0V2lkdGh9cHhgXG4gICAgICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgIH0pfVxuICAgICAgICBuby1uYXZpZ2F0aW9uLXdyYXBcbiAgICAgICAgLm9wZW49JHt0aGlzLm9wZW59XG4gICAgICAgIC5xdWljaz0ke3RoaXMucXVpY2t9XG4gICAgICAgIC5wb3NpdGlvbmluZz0ke3RoaXMubWVudVBvc2l0aW9uaW5nfVxuICAgICAgICAudHlwZWFoZWFkRGVsYXk9JHt0aGlzLnR5cGVhaGVhZERlbGF5fVxuICAgICAgICAuYW5jaG9yQ29ybmVyPSR7dGhpcy5tZW51QWxpZ24gPT09ICdzdGFydCcgPyAnZW5kLXN0YXJ0JyA6ICdlbmQtZW5kJ31cbiAgICAgICAgLm1lbnVDb3JuZXI9JHt0aGlzLm1lbnVBbGlnbiA9PT0gJ3N0YXJ0JyA/ICdzdGFydC1zdGFydCcgOiAnc3RhcnQtZW5kJ31cbiAgICAgICAgQG9wZW5pbmc9JHt0aGlzLmhhbmRsZU9wZW5pbmd9XG4gICAgICAgIEBvcGVuZWQ9JHt0aGlzLnJlZGlzcGF0Y2hFdmVudH1cbiAgICAgICAgQGNsb3Npbmc9JHt0aGlzLnJlZGlzcGF0Y2hFdmVudH1cbiAgICAgICAgQGNsb3NlZD0ke3RoaXMuaGFuZGxlQ2xvc2VkfVxuICAgICAgICBAY2xvc2UtbWVudT0ke3RoaXMuaGFuZGxlQ2xvc2VNZW51fVxuICAgICAgICBAcmVxdWVzdC1zZWxlY3Rpb249JHt0aGlzLmhhbmRsZVJlcXVlc3RTZWxlY3Rpb259XG4gICAgICAgIEByZXF1ZXN0LWRlc2VsZWN0aW9uPSR7dGhpcy5oYW5kbGVSZXF1ZXN0RGVzZWxlY3Rpb259PlxuICAgICAgICAke3RoaXMucmVuZGVyTWVudUNvbnRlbnQoKX1cbiAgICAgIDwvbWQtbWVudT5cbiAgICA8L2Rpdj5gO1xuICAgIH1cbiAgICByZW5kZXJNZW51Q29udGVudCgpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYDxzbG90Pjwvc2xvdD5gO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIG9wZW5pbmcgdGhlIHNlbGVjdCBvbiBrZXlkb3duIGFuZCB0eXBhaGVhZCBzZWxlY3Rpb24gd2hlbiB0aGUgbWVudVxuICAgICAqIGlzIGNsb3NlZC5cbiAgICAgKi9cbiAgICBoYW5kbGVLZXlkb3duKGV2ZW50KSB7XG4gICAgICAgIGlmICh0aGlzLm9wZW4gfHwgdGhpcy5kaXNhYmxlZCB8fCAhdGhpcy5tZW51KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdHlwZWFoZWFkQ29udHJvbGxlciA9IHRoaXMubWVudS50eXBlYWhlYWRDb250cm9sbGVyO1xuICAgICAgICBjb25zdCBpc09wZW5LZXkgPSBldmVudC5jb2RlID09PSAnU3BhY2UnIHx8XG4gICAgICAgICAgICBldmVudC5jb2RlID09PSAnQXJyb3dEb3duJyB8fFxuICAgICAgICAgICAgZXZlbnQuY29kZSA9PT0gJ0Fycm93VXAnIHx8XG4gICAgICAgICAgICBldmVudC5jb2RlID09PSAnRW5kJyB8fFxuICAgICAgICAgICAgZXZlbnQuY29kZSA9PT0gJ0hvbWUnIHx8XG4gICAgICAgICAgICBldmVudC5jb2RlID09PSAnRW50ZXInO1xuICAgICAgICAvLyBEbyBub3Qgb3BlbiBpZiBjdXJyZW50bHkgdHlwaW5nIGFoZWFkIGJlY2F1c2UgdGhlIHVzZXIgbWF5IGJlIHR5cGluZyB0aGVcbiAgICAgICAgLy8gc3BhY2ViYXIgdG8gbWF0Y2ggYSB3b3JkIHdpdGggYSBzcGFjZVxuICAgICAgICBpZiAoIXR5cGVhaGVhZENvbnRyb2xsZXIuaXNUeXBpbmdBaGVhZCAmJiBpc09wZW5LZXkpIHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB0aGlzLm9wZW4gPSB0cnVlO1xuICAgICAgICAgICAgLy8gaHR0cHM6Ly93d3cudzMub3JnL1dBSS9BUklBL2FwZy9wYXR0ZXJucy9jb21ib2JveC9leGFtcGxlcy9jb21ib2JveC1zZWxlY3Qtb25seS8ja2JkX2xhYmVsXG4gICAgICAgICAgICBzd2l0Y2ggKGV2ZW50LmNvZGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdTcGFjZSc6XG4gICAgICAgICAgICAgICAgY2FzZSAnQXJyb3dEb3duJzpcbiAgICAgICAgICAgICAgICBjYXNlICdFbnRlcic6XG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIHdpbGwgaGFuZGxlIGZvY3VzaW5nIGxhc3Qgc2VsZWN0ZWQgaXRlbSBpbiB0aGlzLmhhbmRsZU9wZW5pbmcoKVxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRlZmF1bHRGb2N1cyA9IEZvY3VzU3RhdGUuTk9ORTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnRW5kJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWZhdWx0Rm9jdXMgPSBGb2N1c1N0YXRlLkxBU1RfSVRFTTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnQXJyb3dVcCc6XG4gICAgICAgICAgICAgICAgY2FzZSAnSG9tZSc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGVmYXVsdEZvY3VzID0gRm9jdXNTdGF0ZS5GSVJTVF9JVEVNO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpc1ByaW50YWJsZUtleSA9IGV2ZW50LmtleS5sZW5ndGggPT09IDE7XG4gICAgICAgIC8vIEhhbmRsZXMgdHlwaW5nIGFoZWFkIHdoZW4gdGhlIG1lbnUgaXMgY2xvc2VkIGJ5IGRlbGVnYXRpbmcgdGhlIGV2ZW50IHRvXG4gICAgICAgIC8vIHRoZSB1bmRlcmx5aW5nIG1lbnUncyB0eXBlYWhlYWRDb250cm9sbGVyXG4gICAgICAgIGlmIChpc1ByaW50YWJsZUtleSkge1xuICAgICAgICAgICAgdHlwZWFoZWFkQ29udHJvbGxlci5vbktleWRvd24oZXZlbnQpO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIGNvbnN0IHsgbGFzdEFjdGl2ZVJlY29yZCB9ID0gdHlwZWFoZWFkQ29udHJvbGxlcjtcbiAgICAgICAgICAgIGlmICghbGFzdEFjdGl2ZVJlY29yZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMubGFiZWxFbD8uc2V0QXR0cmlidXRlPy4oJ2FyaWEtbGl2ZScsICdwb2xpdGUnKTtcbiAgICAgICAgICAgIGNvbnN0IGhhc0NoYW5nZWQgPSB0aGlzLnNlbGVjdEl0ZW0obGFzdEFjdGl2ZVJlY29yZFtUWVBFQUhFQURfUkVDT1JELklURU1dKTtcbiAgICAgICAgICAgIGlmIChoYXNDaGFuZ2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kaXNwYXRjaEludGVyYWN0aW9uRXZlbnRzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgaGFuZGxlQ2xpY2soKSB7XG4gICAgICAgIHRoaXMub3BlbiA9ICF0aGlzLm9wZW47XG4gICAgfVxuICAgIGhhbmRsZUZvY3VzKCkge1xuICAgICAgICB0aGlzLmZvY3VzZWQgPSB0cnVlO1xuICAgIH1cbiAgICBoYW5kbGVCbHVyKCkge1xuICAgICAgICB0aGlzLmZvY3VzZWQgPSBmYWxzZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlcyBjbG9zaW5nIHRoZSBtZW51IHdoZW4gdGhlIGZvY3VzIGxlYXZlcyB0aGUgc2VsZWN0J3Mgc3VidHJlZS5cbiAgICAgKi9cbiAgICBoYW5kbGVGb2N1c291dChldmVudCkge1xuICAgICAgICAvLyBEb24ndCBjbG9zZSB0aGUgbWVudSBpZiB3ZSBhcmUgc3dpdGNoaW5nIGZvY3VzIGJldHdlZW4gbWVudSxcbiAgICAgICAgLy8gc2VsZWN0LW9wdGlvbiwgYW5kIGZpZWxkXG4gICAgICAgIGlmIChldmVudC5yZWxhdGVkVGFyZ2V0ICYmIGlzRWxlbWVudEluU3VidHJlZShldmVudC5yZWxhdGVkVGFyZ2V0LCB0aGlzKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub3BlbiA9IGZhbHNlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXRzIGEgbGlzdCBvZiBhbGwgc2VsZWN0ZWQgc2VsZWN0IG9wdGlvbnMgYXMgYSBsaXN0IGl0ZW0gcmVjb3JkIGFycmF5LlxuICAgICAqXG4gICAgICogQHJldHVybiBBbiBhcnJheSBvZiBzZWxlY3RlZCBsaXN0IG9wdGlvbiByZWNvcmRzLlxuICAgICAqL1xuICAgIGdldFNlbGVjdGVkT3B0aW9ucygpIHtcbiAgICAgICAgaWYgKCF0aGlzLm1lbnUpIHtcbiAgICAgICAgICAgIHRoaXMubGFzdFNlbGVjdGVkT3B0aW9uUmVjb3JkcyA9IFtdO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLm1lbnUuaXRlbXM7XG4gICAgICAgIHRoaXMubGFzdFNlbGVjdGVkT3B0aW9uUmVjb3JkcyA9IGdldFNlbGVjdGVkSXRlbXMoaXRlbXMpO1xuICAgICAgICByZXR1cm4gdGhpcy5sYXN0U2VsZWN0ZWRPcHRpb25SZWNvcmRzO1xuICAgIH1cbiAgICBhc3luYyBnZXRVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5tZW51Py51cGRhdGVDb21wbGV0ZTtcbiAgICAgICAgcmV0dXJuIHN1cGVyLmdldFVwZGF0ZUNvbXBsZXRlKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHNlbGVjdGVkIG9wdGlvbnMgZnJvbSB0aGUgRE9NLCBhbmQgdXBkYXRlcyB0aGUgdmFsdWUgYW5kIGRpc3BsYXlcbiAgICAgKiB0ZXh0IHRvIHRoZSBmaXJzdCBzZWxlY3RlZCBvcHRpb24ncyB2YWx1ZSBhbmQgaGVhZGxpbmUgcmVzcGVjdGl2ZWx5LlxuICAgICAqXG4gICAgICogQHJldHVybiBXaGV0aGVyIG9yIG5vdCB0aGUgc2VsZWN0ZWQgb3B0aW9uIGhhcyBjaGFuZ2VkIHNpbmNlIGxhc3QgdXBkYXRlLlxuICAgICAqL1xuICAgIHVwZGF0ZVZhbHVlQW5kRGlzcGxheVRleHQoKSB7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkT3B0aW9ucyA9IHRoaXMuZ2V0U2VsZWN0ZWRPcHRpb25zKCkgPz8gW107XG4gICAgICAgIC8vIFVzZWQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgb3Igbm90IHdlIG5lZWQgdG8gZmlyZSBhbiBpbnB1dCAvIGNoYW5nZSBldmVudFxuICAgICAgICAvLyB3aGljaCBmaXJlIHdoZW5ldmVyIHRoZSBvcHRpb24gZWxlbWVudCBjaGFuZ2VzICh2YWx1ZSBvciBzZWxlY3RlZEluZGV4KVxuICAgICAgICAvLyBvbiB1c2VyIGludGVyYWN0aW9uLlxuICAgICAgICBsZXQgaGFzU2VsZWN0ZWRPcHRpb25DaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgIGlmIChzZWxlY3RlZE9wdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCBbZmlyc3RTZWxlY3RlZE9wdGlvbl0gPSBzZWxlY3RlZE9wdGlvbnNbMF07XG4gICAgICAgICAgICBoYXNTZWxlY3RlZE9wdGlvbkNoYW5nZWQgPVxuICAgICAgICAgICAgICAgIHRoaXMubGFzdFNlbGVjdGVkT3B0aW9uICE9PSBmaXJzdFNlbGVjdGVkT3B0aW9uO1xuICAgICAgICAgICAgdGhpcy5sYXN0U2VsZWN0ZWRPcHRpb24gPSBmaXJzdFNlbGVjdGVkT3B0aW9uO1xuICAgICAgICAgICAgdGhpc1tWQUxVRV0gPSBmaXJzdFNlbGVjdGVkT3B0aW9uLnZhbHVlO1xuICAgICAgICAgICAgdGhpcy5kaXNwbGF5VGV4dCA9IGZpcnN0U2VsZWN0ZWRPcHRpb24uZGlzcGxheVRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBoYXNTZWxlY3RlZE9wdGlvbkNoYW5nZWQgPSB0aGlzLmxhc3RTZWxlY3RlZE9wdGlvbiAhPT0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMubGFzdFNlbGVjdGVkT3B0aW9uID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXNbVkFMVUVdID0gJyc7XG4gICAgICAgICAgICB0aGlzLmRpc3BsYXlUZXh0ID0gJyc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGhhc1NlbGVjdGVkT3B0aW9uQ2hhbmdlZDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRm9jdXNlcyBhbmQgYWN0aXZhdGVzIHRoZSBsYXN0IHNlbGVjdGVkIGl0ZW0gdXBvbiBvcGVuaW5nLCBhbmQgcmVzZXRzIG90aGVyXG4gICAgICogYWN0aXZlIGl0ZW1zLlxuICAgICAqL1xuICAgIGFzeW5jIGhhbmRsZU9wZW5pbmcoZSkge1xuICAgICAgICB0aGlzLmxhYmVsRWw/LnJlbW92ZUF0dHJpYnV0ZT8uKCdhcmlhLWxpdmUnKTtcbiAgICAgICAgdGhpcy5yZWRpc3BhdGNoRXZlbnQoZSk7XG4gICAgICAgIC8vIEZvY3VzU3RhdGUuTk9ORSBtZWFucyB3ZSB3YW50IHRvIGhhbmRsZSBmb2N1cyBvdXJzZWx2ZXMgYW5kIGZvY3VzIHRoZVxuICAgICAgICAvLyBsYXN0IHNlbGVjdGVkIGl0ZW0uXG4gICAgICAgIGlmICh0aGlzLmRlZmF1bHRGb2N1cyAhPT0gRm9jdXNTdGF0ZS5OT05FKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLm1lbnUuaXRlbXM7XG4gICAgICAgIGNvbnN0IGFjdGl2ZUl0ZW0gPSBnZXRBY3RpdmVJdGVtKGl0ZW1zKT8uaXRlbTtcbiAgICAgICAgbGV0IFtzZWxlY3RlZEl0ZW1dID0gdGhpcy5sYXN0U2VsZWN0ZWRPcHRpb25SZWNvcmRzWzBdID8/IFtudWxsXTtcbiAgICAgICAgLy8gVGhpcyBpcyB0cnVlIGlmIHRoZSB1c2VyIGtleXMgdGhyb3VnaCB0aGUgbGlzdCBidXQgY2xpY2tzIG91dCBvZiB0aGUgbWVudVxuICAgICAgICAvLyB0aHVzIG5vIGNsb3NlLW1lbnUgZXZlbnQgaXMgZmlyZWQgYnkgYW4gaXRlbSBhbmQgd2UgY2FuJ3QgY2xlYW4gdXAgaW5cbiAgICAgICAgLy8gaGFuZGxlQ2xvc2VNZW51LlxuICAgICAgICBpZiAoYWN0aXZlSXRlbSAmJiBhY3RpdmVJdGVtICE9PSBzZWxlY3RlZEl0ZW0pIHtcbiAgICAgICAgICAgIGFjdGl2ZUl0ZW0udGFiSW5kZXggPSAtMTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpbiB0aGUgY2FzZSB0aGF0IG5vdGhpbmcgaXMgc2VsZWN0ZWQsIGZvY3VzIHRoZSBmaXJzdCBpdGVtXG4gICAgICAgIHNlbGVjdGVkSXRlbSA9IHNlbGVjdGVkSXRlbSA/PyBpdGVtc1swXTtcbiAgICAgICAgaWYgKHNlbGVjdGVkSXRlbSkge1xuICAgICAgICAgICAgc2VsZWN0ZWRJdGVtLnRhYkluZGV4ID0gMDtcbiAgICAgICAgICAgIHNlbGVjdGVkSXRlbS5mb2N1cygpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJlZGlzcGF0Y2hFdmVudChlKSB7XG4gICAgICAgIHJlZGlzcGF0Y2hFdmVudCh0aGlzLCBlKTtcbiAgICB9XG4gICAgaGFuZGxlQ2xvc2VkKGUpIHtcbiAgICAgICAgdGhpcy5vcGVuID0gZmFsc2U7XG4gICAgICAgIHRoaXMucmVkaXNwYXRjaEV2ZW50KGUpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBEZXRlcm1pbmVzIHRoZSByZWFzb24gZm9yIGNsb3NpbmcsIGFuZCB1cGRhdGVzIHRoZSBVSSBhY2NvcmRpbmdseS5cbiAgICAgKi9cbiAgICBoYW5kbGVDbG9zZU1lbnUoZXZlbnQpIHtcbiAgICAgICAgY29uc3QgcmVhc29uID0gZXZlbnQuZGV0YWlsLnJlYXNvbjtcbiAgICAgICAgY29uc3QgaXRlbSA9IGV2ZW50LmRldGFpbC5pdGVtUGF0aFswXTtcbiAgICAgICAgdGhpcy5vcGVuID0gZmFsc2U7XG4gICAgICAgIGxldCBoYXNDaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgIGlmIChyZWFzb24ua2luZCA9PT0gJ2NsaWNrLXNlbGVjdGlvbicpIHtcbiAgICAgICAgICAgIGhhc0NoYW5nZWQgPSB0aGlzLnNlbGVjdEl0ZW0oaXRlbSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAocmVhc29uLmtpbmQgPT09ICdrZXlkb3duJyAmJiBpc1NlbGVjdGFibGVLZXkocmVhc29uLmtleSkpIHtcbiAgICAgICAgICAgIGhhc0NoYW5nZWQgPSB0aGlzLnNlbGVjdEl0ZW0oaXRlbSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBUaGlzIGNhbiBoYXBwZW4gb24gRVNDIGJlaW5nIHByZXNzZWRcbiAgICAgICAgICAgIGl0ZW0udGFiSW5kZXggPSAtMTtcbiAgICAgICAgICAgIGl0ZW0uYmx1cigpO1xuICAgICAgICB9XG4gICAgICAgIC8vIERpc3BhdGNoIGludGVyYWN0aW9uIGV2ZW50cyBzaW5jZSBzZWxlY3Rpb24gaGFzIGJlZW4gbWFkZSB2aWEga2V5Ym9hcmRcbiAgICAgICAgLy8gb3IgbW91c2UuXG4gICAgICAgIGlmIChoYXNDaGFuZ2VkKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BhdGNoSW50ZXJhY3Rpb25FdmVudHMoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZWxlY3RzIGEgZ2l2ZW4gb3B0aW9uLCBkZXNlbGVjdHMgb3RoZXIgb3B0aW9ucywgYW5kIHVwZGF0ZXMgdGhlIFVJLlxuICAgICAqXG4gICAgICogQHJldHVybiBXaGV0aGVyIHRoZSBsYXN0IHNlbGVjdGVkIG9wdGlvbiBoYXMgY2hhbmdlZC5cbiAgICAgKi9cbiAgICBzZWxlY3RJdGVtKGl0ZW0pIHtcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRPcHRpb25zID0gdGhpcy5nZXRTZWxlY3RlZE9wdGlvbnMoKSA/PyBbXTtcbiAgICAgICAgc2VsZWN0ZWRPcHRpb25zLmZvckVhY2goKFtvcHRpb25dKSA9PiB7XG4gICAgICAgICAgICBpZiAoaXRlbSAhPT0gb3B0aW9uKSB7XG4gICAgICAgICAgICAgICAgb3B0aW9uLnNlbGVjdGVkID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpdGVtLnNlbGVjdGVkID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXMudXBkYXRlVmFsdWVBbmREaXNwbGF5VGV4dCgpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHVwZGF0aW5nIHNlbGVjdGlvbiB3aGVuIGFuIG9wdGlvbiBlbGVtZW50IHJlcXVlc3RzIHNlbGVjdGlvbiB2aWFcbiAgICAgKiBwcm9wZXJ0eSAvIGF0dHJpYnV0ZSBjaGFuZ2UuXG4gICAgICovXG4gICAgaGFuZGxlUmVxdWVzdFNlbGVjdGlvbihldmVudCkge1xuICAgICAgICBjb25zdCByZXF1ZXN0aW5nT3B0aW9uRWwgPSBldmVudC50YXJnZXQ7XG4gICAgICAgIC8vIE5vLW9wIGlmIHRoaXMgaXRlbSBpcyBhbHJlYWR5IHNlbGVjdGVkLlxuICAgICAgICBpZiAodGhpcy5sYXN0U2VsZWN0ZWRPcHRpb25SZWNvcmRzLnNvbWUoKFtvcHRpb25dKSA9PiBvcHRpb24gPT09IHJlcXVlc3RpbmdPcHRpb25FbCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNlbGVjdEl0ZW0ocmVxdWVzdGluZ09wdGlvbkVsKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB1cGRhdGluZyBzZWxlY3Rpb24gd2hlbiBhbiBvcHRpb24gZWxlbWVudCByZXF1ZXN0cyBkZXNlbGVjdGlvbiB2aWFcbiAgICAgKiBwcm9wZXJ0eSAvIGF0dHJpYnV0ZSBjaGFuZ2UuXG4gICAgICovXG4gICAgaGFuZGxlUmVxdWVzdERlc2VsZWN0aW9uKGV2ZW50KSB7XG4gICAgICAgIGNvbnN0IHJlcXVlc3RpbmdPcHRpb25FbCA9IGV2ZW50LnRhcmdldDtcbiAgICAgICAgLy8gTm8tb3AgaWYgdGhpcyBpdGVtIGlzIG5vdCBldmVuIGluIHRoZSBsaXN0IG9mIHRyYWNrZWQgc2VsZWN0ZWQgaXRlbXMuXG4gICAgICAgIGlmICghdGhpcy5sYXN0U2VsZWN0ZWRPcHRpb25SZWNvcmRzLnNvbWUoKFtvcHRpb25dKSA9PiBvcHRpb24gPT09IHJlcXVlc3RpbmdPcHRpb25FbCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlQW5kRGlzcGxheVRleHQoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQXR0ZW1wdHMgdG8gaW5pdGlhbGl6ZSB0aGUgc2VsZWN0ZWQgb3B0aW9uIGZyb20gdXNlci1zZXR0YWJsZSB2YWx1ZXMgbGlrZVxuICAgICAqIFNTUiwgc2V0dGluZyBgdmFsdWVgLCBvciBgc2VsZWN0ZWRJbmRleGAgYXQgc3RhcnR1cC5cbiAgICAgKi9cbiAgICBpbml0VXNlclNlbGVjdGlvbigpIHtcbiAgICAgICAgLy8gVXNlciBoYXMgc2V0IGAudmFsdWVgIGRpcmVjdGx5LCBidXQgaW50ZXJuYWxzIGhhdmUgbm90IHlldCBib290ZWQgdXAuXG4gICAgICAgIGlmICh0aGlzLmxhc3RVc2VyU2V0VmFsdWUgJiYgIXRoaXMubGFzdFNlbGVjdGVkT3B0aW9uUmVjb3Jkcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0KHRoaXMubGFzdFVzZXJTZXRWYWx1ZSk7XG4gICAgICAgICAgICAvLyBVc2VyIGhhcyBzZXQgYC5zZWxlY3RlZEluZGV4YCBkaXJlY3RseSwgYnV0IGludGVybmFscyBoYXZlIG5vdCB5ZXRcbiAgICAgICAgICAgIC8vIGJvb3RlZCB1cC5cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLmxhc3RVc2VyU2V0U2VsZWN0ZWRJbmRleCAhPT0gbnVsbCAmJlxuICAgICAgICAgICAgIXRoaXMubGFzdFNlbGVjdGVkT3B0aW9uUmVjb3Jkcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0SW5kZXgodGhpcy5sYXN0VXNlclNldFNlbGVjdGVkSW5kZXgpO1xuICAgICAgICAgICAgLy8gUmVndWxhciBib290IHVwIVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVWYWx1ZUFuZERpc3BsYXlUZXh0KCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaGFuZGxlSWNvbkNoYW5nZSgpIHtcbiAgICAgICAgdGhpcy5oYXNMZWFkaW5nSWNvbiA9IHRoaXMubGVhZGluZ0ljb25zLmxlbmd0aCA+IDA7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERpc3BhdGNoZXMgdGhlIGBpbnB1dGAgYW5kIGBjaGFuZ2VgIGV2ZW50cy5cbiAgICAgKi9cbiAgICBkaXNwYXRjaEludGVyYWN0aW9uRXZlbnRzKCkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdpbnB1dCcsIHsgYnViYmxlczogdHJ1ZSwgY29tcG9zZWQ6IHRydWUgfSkpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdjaGFuZ2UnLCB7IGJ1YmJsZXM6IHRydWUgfSkpO1xuICAgIH1cbiAgICBnZXRFcnJvclRleHQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVycm9yID8gdGhpcy5lcnJvclRleHQgOiB0aGlzLm5hdGl2ZUVycm9yVGV4dDtcbiAgICB9XG4gICAgW2dldEZvcm1WYWx1ZV0oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICAgIH1cbiAgICBmb3JtUmVzZXRDYWxsYmFjaygpIHtcbiAgICAgICAgdGhpcy5yZXNldCgpO1xuICAgIH1cbiAgICBmb3JtU3RhdGVSZXN0b3JlQ2FsbGJhY2soc3RhdGUpIHtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHN0YXRlO1xuICAgIH1cbiAgICBjbGljaygpIHtcbiAgICAgICAgdGhpcy5maWVsZD8uY2xpY2soKTtcbiAgICB9XG4gICAgW2NyZWF0ZVZhbGlkYXRvcl0oKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2VsZWN0VmFsaWRhdG9yKCgpID0+IHRoaXMpO1xuICAgIH1cbiAgICBbZ2V0VmFsaWRpdHlBbmNob3JdKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5maWVsZDtcbiAgICB9XG59XG4vKiogQG5vY29sbGFwc2UgKi9cblNlbGVjdC5zaGFkb3dSb290T3B0aW9ucyA9IHtcbiAgICAuLi5MaXRFbGVtZW50LnNoYWRvd1Jvb3RPcHRpb25zLFxuICAgIGRlbGVnYXRlc0ZvY3VzOiB0cnVlLFxufTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiB9KVxuXSwgU2VsZWN0LnByb3RvdHlwZSwgXCJxdWlja1wiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuIH0pXG5dLCBTZWxlY3QucHJvdG90eXBlLCBcInJlcXVpcmVkXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IFN0cmluZywgYXR0cmlidXRlOiAnZXJyb3ItdGV4dCcgfSlcbl0sIFNlbGVjdC5wcm90b3R5cGUsIFwiZXJyb3JUZXh0XCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSgpXG5dLCBTZWxlY3QucHJvdG90eXBlLCBcImxhYmVsXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IEJvb2xlYW4sIGF0dHJpYnV0ZTogJ25vLWFzdGVyaXNrJyB9KVxuXSwgU2VsZWN0LnByb3RvdHlwZSwgXCJub0FzdGVyaXNrXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IFN0cmluZywgYXR0cmlidXRlOiAnc3VwcG9ydGluZy10ZXh0JyB9KVxuXSwgU2VsZWN0LnByb3RvdHlwZSwgXCJzdXBwb3J0aW5nVGV4dFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCByZWZsZWN0OiB0cnVlIH0pXG5dLCBTZWxlY3QucHJvdG90eXBlLCBcImVycm9yXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ21lbnUtcG9zaXRpb25pbmcnIH0pXG5dLCBTZWxlY3QucHJvdG90eXBlLCBcIm1lbnVQb3NpdGlvbmluZ1wiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCBhdHRyaWJ1dGU6ICdjbGFtcC1tZW51LXdpZHRoJyB9KVxuXSwgU2VsZWN0LnByb3RvdHlwZSwgXCJjbGFtcE1lbnVXaWR0aFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBOdW1iZXIsIGF0dHJpYnV0ZTogJ3R5cGVhaGVhZC1kZWxheScgfSlcbl0sIFNlbGVjdC5wcm90b3R5cGUsIFwidHlwZWFoZWFkRGVsYXlcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgYXR0cmlidXRlOiAnaGFzLWxlYWRpbmctaWNvbicgfSlcbl0sIFNlbGVjdC5wcm90b3R5cGUsIFwiaGFzTGVhZGluZ0ljb25cIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgYXR0cmlidXRlOiAnZGlzcGxheS10ZXh0JyB9KVxuXSwgU2VsZWN0LnByb3RvdHlwZSwgXCJkaXNwbGF5VGV4dFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyBhdHRyaWJ1dGU6ICdtZW51LWFsaWduJyB9KVxuXSwgU2VsZWN0LnByb3RvdHlwZSwgXCJtZW51QWxpZ25cIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KClcbl0sIFNlbGVjdC5wcm90b3R5cGUsIFwidmFsdWVcIiwgbnVsbCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IE51bWJlciwgYXR0cmlidXRlOiAnc2VsZWN0ZWQtaW5kZXgnIH0pXG5dLCBTZWxlY3QucHJvdG90eXBlLCBcInNlbGVjdGVkSW5kZXhcIiwgbnVsbCk7XG5fX2RlY29yYXRlKFtcbiAgICBzdGF0ZSgpXG5dLCBTZWxlY3QucHJvdG90eXBlLCBcIm5hdGl2ZUVycm9yXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBzdGF0ZSgpXG5dLCBTZWxlY3QucHJvdG90eXBlLCBcIm5hdGl2ZUVycm9yVGV4dFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgc3RhdGUoKVxuXSwgU2VsZWN0LnByb3RvdHlwZSwgXCJmb2N1c2VkXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBzdGF0ZSgpXG5dLCBTZWxlY3QucHJvdG90eXBlLCBcIm9wZW5cIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHN0YXRlKClcbl0sIFNlbGVjdC5wcm90b3R5cGUsIFwiZGVmYXVsdEZvY3VzXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBxdWVyeSgnLmZpZWxkJylcbl0sIFNlbGVjdC5wcm90b3R5cGUsIFwiZmllbGRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHF1ZXJ5KCdtZC1tZW51Jylcbl0sIFNlbGVjdC5wcm90b3R5cGUsIFwibWVudVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcXVlcnkoJyNsYWJlbCcpXG5dLCBTZWxlY3QucHJvdG90eXBlLCBcImxhYmVsRWxcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHF1ZXJ5QXNzaWduZWRFbGVtZW50cyh7IHNsb3Q6ICdsZWFkaW5nLWljb24nLCBmbGF0dGVuOiB0cnVlIH0pXG5dLCBTZWxlY3QucHJvdG90eXBlLCBcImxlYWRpbmdJY29uc1wiLCB2b2lkIDApO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2VsZWN0LmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIzIEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbmltcG9ydCB7IF9fZGVjb3JhdGUgfSBmcm9tIFwidHNsaWJcIjtcbmltcG9ydCAnLi4vLi4vLi4vZm9jdXMvbWQtZm9jdXMtcmluZy5qcyc7XG5pbXBvcnQgJy4uLy4uLy4uL2xhYnMvaXRlbS9pdGVtLmpzJztcbmltcG9ydCAnLi4vLi4vLi4vcmlwcGxlL3JpcHBsZS5qcyc7XG5pbXBvcnQgeyBodG1sLCBMaXRFbGVtZW50LCBub3RoaW5nIH0gZnJvbSAnbGl0JztcbmltcG9ydCB7IHByb3BlcnR5LCBxdWVyeSwgcXVlcnlBc3NpZ25lZEVsZW1lbnRzLCBxdWVyeUFzc2lnbmVkTm9kZXMsIH0gZnJvbSAnbGl0L2RlY29yYXRvcnMuanMnO1xuaW1wb3J0IHsgY2xhc3NNYXAgfSBmcm9tICdsaXQvZGlyZWN0aXZlcy9jbGFzcy1tYXAuanMnO1xuaW1wb3J0IHsgbWl4aW5EZWxlZ2F0ZXNBcmlhIH0gZnJvbSAnLi4vLi4vLi4vaW50ZXJuYWwvYXJpYS9kZWxlZ2F0ZS5qcyc7XG5pbXBvcnQgeyBTZWxlY3RPcHRpb25Db250cm9sbGVyIH0gZnJvbSAnLi9zZWxlY3RPcHRpb25Db250cm9sbGVyLmpzJztcbi8vIFNlcGFyYXRlIHZhcmlhYmxlIG5lZWRlZCBmb3IgY2xvc3VyZS5cbmNvbnN0IHNlbGVjdE9wdGlvbkJhc2VDbGFzcyA9IG1peGluRGVsZWdhdGVzQXJpYShMaXRFbGVtZW50KTtcbi8qKlxuICogQGZpcmVzIGNsb3NlLW1lbnUge0N1c3RvbUV2ZW50PHtpbml0aWF0b3I6IFNlbGVjdE9wdGlvbiwgcmVhc29uOiBSZWFzb24sIGl0ZW1QYXRoOiBTZWxlY3RPcHRpb25bXX0+fVxuICogQ2xvc2VzIHRoZSBlbmNhcHN1bGF0aW5nIG1lbnUgb24gY2xvc2FibGUgaW50ZXJhY3Rpb24uIC0tYnViYmxlcyAtLWNvbXBvc2VkXG4gKiBAZmlyZXMgcmVxdWVzdC1zZWxlY3Rpb24ge0V2ZW50fSBSZXF1ZXN0cyB0aGUgcGFyZW50IG1kLXNlbGVjdCB0byBzZWxlY3QgdGhpc1xuICogZWxlbWVudCAoYW5kIGRlc2VsZWN0IG90aGVycyBpZiBzaW5nbGUtc2VsZWN0aW9uKSB3aGVuIGBzZWxlY3RlZGAgY2hhbmdlZCB0b1xuICogYHRydWVgLiAtLWJ1YmJsZXMgLS1jb21wb3NlZFxuICogQGZpcmVzIHJlcXVlc3QtZGVzZWxlY3Rpb24ge0V2ZW50fSBSZXF1ZXN0cyB0aGUgcGFyZW50IG1kLXNlbGVjdCB0byBkZXNlbGVjdFxuICogdGhpcyBlbGVtZW50IHdoZW4gYHNlbGVjdGVkYCBjaGFuZ2VkIHRvIGBmYWxzZWAuIC0tYnViYmxlcyAtLWNvbXBvc2VkXG4gKi9cbmV4cG9ydCBjbGFzcyBTZWxlY3RPcHRpb25FbCBleHRlbmRzIHNlbGVjdE9wdGlvbkJhc2VDbGFzcyB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEaXNhYmxlcyB0aGUgaXRlbSBhbmQgbWFrZXMgaXQgbm9uLXNlbGVjdGFibGUgYW5kIG5vbi1pbnRlcmFjdGl2ZS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJFQURPTkxZOiBzZWxmLWlkZW50aWZpZXMgYXMgYSBtZW51IGl0ZW0gYW5kIHNldHMgaXRzIGlkZW50aWZ5aW5nIGF0dHJpYnV0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5pc01lbnVJdGVtID0gdHJ1ZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNldHMgdGhlIGl0ZW0gaW4gdGhlIHNlbGVjdGVkIHZpc3VhbCBzdGF0ZSB3aGVuIGEgc3VibWVudSBpcyBvcGVuZWQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnNlbGVjdGVkID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGb3JtIHZhbHVlIG9mIHRoZSBvcHRpb24uXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnZhbHVlID0gJyc7XG4gICAgICAgIHRoaXMudHlwZSA9ICdvcHRpb24nO1xuICAgICAgICB0aGlzLnNlbGVjdE9wdGlvbkNvbnRyb2xsZXIgPSBuZXcgU2VsZWN0T3B0aW9uQ29udHJvbGxlcih0aGlzLCB7XG4gICAgICAgICAgICBnZXRIZWFkbGluZUVsZW1lbnRzOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGVhZGxpbmVFbGVtZW50cztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXRTdXBwb3J0aW5nVGV4dEVsZW1lbnRzOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3VwcG9ydGluZ1RleHRFbGVtZW50cztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXREZWZhdWx0RWxlbWVudHM6ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kZWZhdWx0RWxlbWVudHM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0SW50ZXJhY3RpdmVFbGVtZW50OiAoKSA9PiB0aGlzLmxpc3RJdGVtUm9vdCxcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoZSB0ZXh0IHRoYXQgaXMgc2VsZWN0YWJsZSB2aWEgdHlwZWFoZWFkLiBJZiBub3Qgc2V0LCBkZWZhdWx0cyB0byB0aGVcbiAgICAgKiBpbm5lclRleHQgb2YgdGhlIGl0ZW0gc2xvdHRlZCBpbnRvIHRoZSBgXCJoZWFkbGluZVwiYCBzbG90LlxuICAgICAqL1xuICAgIGdldCB0eXBlYWhlYWRUZXh0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZWxlY3RPcHRpb25Db250cm9sbGVyLnR5cGVhaGVhZFRleHQ7XG4gICAgfVxuICAgIHNldCB0eXBlYWhlYWRUZXh0KHRleHQpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RPcHRpb25Db250cm9sbGVyLnNldFR5cGVhaGVhZFRleHQodGV4dCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoZSB0ZXh0IHRoYXQgaXMgZGlzcGxheWVkIGluIHRoZSBzZWxlY3QgZmllbGQgd2hlbiBzZWxlY3RlZC4gSWYgbm90IHNldCxcbiAgICAgKiBkZWZhdWx0cyB0byB0aGUgdGV4dENvbnRlbnQgb2YgdGhlIGl0ZW0gc2xvdHRlZCBpbnRvIHRoZSBgXCJoZWFkbGluZVwiYCBzbG90LlxuICAgICAqL1xuICAgIGdldCBkaXNwbGF5VGV4dCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0T3B0aW9uQ29udHJvbGxlci5kaXNwbGF5VGV4dDtcbiAgICB9XG4gICAgc2V0IGRpc3BsYXlUZXh0KHRleHQpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RPcHRpb25Db250cm9sbGVyLnNldERpc3BsYXlUZXh0KHRleHQpO1xuICAgIH1cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJlbmRlckxpc3RJdGVtKGh0bWwgYFxuICAgICAgPG1kLWl0ZW0+XG4gICAgICAgIDxkaXYgc2xvdD1cImNvbnRhaW5lclwiPlxuICAgICAgICAgICR7dGhpcy5yZW5kZXJSaXBwbGUoKX0gJHt0aGlzLnJlbmRlckZvY3VzUmluZygpfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPHNsb3QgbmFtZT1cInN0YXJ0XCIgc2xvdD1cInN0YXJ0XCI+PC9zbG90PlxuICAgICAgICA8c2xvdCBuYW1lPVwiZW5kXCIgc2xvdD1cImVuZFwiPjwvc2xvdD5cbiAgICAgICAgJHt0aGlzLnJlbmRlckJvZHkoKX1cbiAgICAgIDwvbWQtaXRlbT5cbiAgICBgKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVuZGVycyB0aGUgcm9vdCBsaXN0IGl0ZW0uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gY29udGVudCB0aGUgY2hpbGQgY29udGVudCBvZiB0aGUgbGlzdCBpdGVtLlxuICAgICAqL1xuICAgIHJlbmRlckxpc3RJdGVtKGNvbnRlbnQpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYFxuICAgICAgPGxpXG4gICAgICAgIGlkPVwiaXRlbVwiXG4gICAgICAgIHRhYmluZGV4PSR7dGhpcy5kaXNhYmxlZCA/IC0xIDogMH1cbiAgICAgICAgcm9sZT0ke3RoaXMuc2VsZWN0T3B0aW9uQ29udHJvbGxlci5yb2xlfVxuICAgICAgICBhcmlhLWxhYmVsPSR7dGhpcy5hcmlhTGFiZWwgfHwgbm90aGluZ31cbiAgICAgICAgYXJpYS1zZWxlY3RlZD0ke3RoaXMuYXJpYVNlbGVjdGVkIHx8IG5vdGhpbmd9XG4gICAgICAgIGFyaWEtY2hlY2tlZD0ke3RoaXMuYXJpYUNoZWNrZWQgfHwgbm90aGluZ31cbiAgICAgICAgYXJpYS1leHBhbmRlZD0ke3RoaXMuYXJpYUV4cGFuZGVkIHx8IG5vdGhpbmd9XG4gICAgICAgIGFyaWEtaGFzcG9wdXA9JHt0aGlzLmFyaWFIYXNQb3B1cCB8fCBub3RoaW5nfVxuICAgICAgICBjbGFzcz1cImxpc3QtaXRlbSAke2NsYXNzTWFwKHRoaXMuZ2V0UmVuZGVyQ2xhc3NlcygpKX1cIlxuICAgICAgICBAY2xpY2s9JHt0aGlzLnNlbGVjdE9wdGlvbkNvbnRyb2xsZXIub25DbGlja31cbiAgICAgICAgQGtleWRvd249JHt0aGlzLnNlbGVjdE9wdGlvbkNvbnRyb2xsZXIub25LZXlkb3dufVxuICAgICAgICA+JHtjb250ZW50fTwvbGlcbiAgICAgID5cbiAgICBgO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHJlbmRlcmluZyBvZiB0aGUgcmlwcGxlIGVsZW1lbnQuXG4gICAgICovXG4gICAgcmVuZGVyUmlwcGxlKCkge1xuICAgICAgICByZXR1cm4gaHRtbCBgIDxtZC1yaXBwbGVcbiAgICAgIHBhcnQ9XCJyaXBwbGVcIlxuICAgICAgZm9yPVwiaXRlbVwiXG4gICAgICA/ZGlzYWJsZWQ9JHt0aGlzLmRpc2FibGVkfT48L21kLXJpcHBsZT5gO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHJlbmRlcmluZyBvZiB0aGUgZm9jdXMgcmluZy5cbiAgICAgKi9cbiAgICByZW5kZXJGb2N1c1JpbmcoKSB7XG4gICAgICAgIHJldHVybiBodG1sIGAgPG1kLWZvY3VzLXJpbmdcbiAgICAgIHBhcnQ9XCJmb2N1cy1yaW5nXCJcbiAgICAgIGZvcj1cIml0ZW1cIlxuICAgICAgaW53YXJkPjwvbWQtZm9jdXMtcmluZz5gO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDbGFzc2VzIGFwcGxpZWQgdG8gdGhlIGxpc3QgaXRlbSByb290LlxuICAgICAqL1xuICAgIGdldFJlbmRlckNsYXNzZXMoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAnZGlzYWJsZWQnOiB0aGlzLmRpc2FibGVkLFxuICAgICAgICAgICAgJ3NlbGVjdGVkJzogdGhpcy5zZWxlY3RlZCxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSGFuZGxlcyByZW5kZXJpbmcgdGhlIGhlYWRsaW5lIGFuZCBzdXBwb3J0aW5nIHRleHQuXG4gICAgICovXG4gICAgcmVuZGVyQm9keSgpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYFxuICAgICAgPHNsb3Q+PC9zbG90PlxuICAgICAgPHNsb3QgbmFtZT1cIm92ZXJsaW5lXCIgc2xvdD1cIm92ZXJsaW5lXCI+PC9zbG90PlxuICAgICAgPHNsb3QgbmFtZT1cImhlYWRsaW5lXCIgc2xvdD1cImhlYWRsaW5lXCI+PC9zbG90PlxuICAgICAgPHNsb3QgbmFtZT1cInN1cHBvcnRpbmctdGV4dFwiIHNsb3Q9XCJzdXBwb3J0aW5nLXRleHRcIj48L3Nsb3Q+XG4gICAgICA8c2xvdFxuICAgICAgICBuYW1lPVwidHJhaWxpbmctc3VwcG9ydGluZy10ZXh0XCJcbiAgICAgICAgc2xvdD1cInRyYWlsaW5nLXN1cHBvcnRpbmctdGV4dFwiPjwvc2xvdD5cbiAgICBgO1xuICAgIH1cbiAgICBmb2N1cygpIHtcbiAgICAgICAgLy8gVE9ETyhiLzMwMDMzNDUwOSk6IG5lZWRlZCBmb3Igc29tZSBjYXNlcyB3aGVyZSBkZWxlZ2F0ZXNGb2N1cyBkb2Vzbid0XG4gICAgICAgIC8vIHdvcmsgcHJvZ3JhbW1hdGljYWxseSBsaWtlIGluIEZGIGFuZCBzZWxlY3Qtb3B0aW9uXG4gICAgICAgIHRoaXMubGlzdEl0ZW1Sb290Py5mb2N1cygpO1xuICAgIH1cbn1cbi8qKiBAbm9jb2xsYXBzZSAqL1xuU2VsZWN0T3B0aW9uRWwuc2hhZG93Um9vdE9wdGlvbnMgPSB7XG4gICAgLi4uTGl0RWxlbWVudC5zaGFkb3dSb290T3B0aW9ucyxcbiAgICBkZWxlZ2F0ZXNGb2N1czogdHJ1ZSxcbn07XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IEJvb2xlYW4sIHJlZmxlY3Q6IHRydWUgfSlcbl0sIFNlbGVjdE9wdGlvbkVsLnByb3RvdHlwZSwgXCJkaXNhYmxlZFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCBhdHRyaWJ1dGU6ICdtZC1tZW51LWl0ZW0nLCByZWZsZWN0OiB0cnVlIH0pXG5dLCBTZWxlY3RPcHRpb25FbC5wcm90b3R5cGUsIFwiaXNNZW51SXRlbVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuIH0pXG5dLCBTZWxlY3RPcHRpb25FbC5wcm90b3R5cGUsIFwic2VsZWN0ZWRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KClcbl0sIFNlbGVjdE9wdGlvbkVsLnByb3RvdHlwZSwgXCJ2YWx1ZVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcXVlcnkoJy5saXN0LWl0ZW0nKVxuXSwgU2VsZWN0T3B0aW9uRWwucHJvdG90eXBlLCBcImxpc3RJdGVtUm9vdFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcXVlcnlBc3NpZ25lZEVsZW1lbnRzKHsgc2xvdDogJ2hlYWRsaW5lJyB9KVxuXSwgU2VsZWN0T3B0aW9uRWwucHJvdG90eXBlLCBcImhlYWRsaW5lRWxlbWVudHNcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHF1ZXJ5QXNzaWduZWRFbGVtZW50cyh7IHNsb3Q6ICdzdXBwb3J0aW5nLXRleHQnIH0pXG5dLCBTZWxlY3RPcHRpb25FbC5wcm90b3R5cGUsIFwic3VwcG9ydGluZ1RleHRFbGVtZW50c1wiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcXVlcnlBc3NpZ25lZE5vZGVzKHsgc2xvdDogJycgfSlcbl0sIFNlbGVjdE9wdGlvbkVsLnByb3RvdHlwZSwgXCJkZWZhdWx0RWxlbWVudHNcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgYXR0cmlidXRlOiAndHlwZWFoZWFkLXRleHQnIH0pXG5dLCBTZWxlY3RPcHRpb25FbC5wcm90b3R5cGUsIFwidHlwZWFoZWFkVGV4dFwiLCBudWxsKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgYXR0cmlidXRlOiAnZGlzcGxheS10ZXh0JyB9KVxuXSwgU2VsZWN0T3B0aW9uRWwucHJvdG90eXBlLCBcImRpc3BsYXlUZXh0XCIsIG51bGwpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2VsZWN0LW9wdGlvbi5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMyBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBNZW51SXRlbUNvbnRyb2xsZXIsIH0gZnJvbSAnLi4vLi4vLi4vbWVudS9pbnRlcm5hbC9jb250cm9sbGVycy9tZW51SXRlbUNvbnRyb2xsZXIuanMnO1xuLyoqXG4gKiBDcmVhdGVzIGFuIGV2ZW50IGZpcmVkIGJ5IGEgU2VsZWN0T3B0aW9uIHRvIHJlcXVlc3Qgc2VsZWN0aW9uIGZyb20gbWQtc2VsZWN0LlxuICogVHlwaWNhbGx5IGZpcmVkIGFmdGVyIGBzZWxlY3RlZGAgY2hhbmdlcyBmcm9tIGBmYWxzZWAgdG8gYHRydWVgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVxdWVzdFNlbGVjdGlvbkV2ZW50KCkge1xuICAgIHJldHVybiBuZXcgRXZlbnQoJ3JlcXVlc3Qtc2VsZWN0aW9uJywge1xuICAgICAgICBidWJibGVzOiB0cnVlLFxuICAgICAgICBjb21wb3NlZDogdHJ1ZSxcbiAgICB9KTtcbn1cbi8qKlxuICogQ3JlYXRlcyBhbiBldmVudCBmaXJlZCBieSBhIFNlbGVjdE9wdGlvbiB0byByZXF1ZXN0IGRlc2VsZWN0aW9uIGZyb21cbiAqIG1kLXNlbGVjdC4gVHlwaWNhbGx5IGZpcmVkIGFmdGVyIGBzZWxlY3RlZGAgY2hhbmdlcyBmcm9tIGB0cnVlYCB0byBgZmFsc2VgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVxdWVzdERlc2VsZWN0aW9uRXZlbnQoKSB7XG4gICAgcmV0dXJuIG5ldyBFdmVudCgncmVxdWVzdC1kZXNlbGVjdGlvbicsIHtcbiAgICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgICAgY29tcG9zZWQ6IHRydWUsXG4gICAgfSk7XG59XG4vKipcbiAqIEEgY29udHJvbGxlciB0aGF0IHByb3ZpZGVzIG1vc3QgZnVuY3Rpb25hbGl0eSBhbmQgbWQtc2VsZWN0IGNvbXBhdGliaWxpdHkgZm9yXG4gKiBhbiBlbGVtZW50IHRoYXQgaW1wbGVtZW50cyB0aGUgU2VsZWN0T3B0aW9uIGludGVyZmFjZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFNlbGVjdE9wdGlvbkNvbnRyb2xsZXIge1xuICAgIC8qKlxuICAgICAqIFRoZSByZWNvbW1lbmRlZCByb2xlIG9mIHRoZSBzZWxlY3Qgb3B0aW9uLlxuICAgICAqL1xuICAgIGdldCByb2xlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tZW51SXRlbUNvbnRyb2xsZXIucm9sZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhlIHRleHQgdGhhdCBpcyBzZWxlY3RhYmxlIHZpYSB0eXBlYWhlYWQuIElmIG5vdCBzZXQsIGRlZmF1bHRzIHRvIHRoZVxuICAgICAqIGlubmVyVGV4dCBvZiB0aGUgaXRlbSBzbG90dGVkIGludG8gdGhlIGBcImhlYWRsaW5lXCJgIHNsb3QsIGFuZCBpZiB0aGVyZSBhcmVcbiAgICAgKiBubyBzbG90dGVkIGVsZW1lbnRzIGludG8gaGVhZGxpbmUsIHRoZW4gaXQgY2hlY2tzIHRoZSBfZGVmYXVsdF8gc2xvdCwgYW5kXG4gICAgICogdGhlbiB0aGUgYFwic3VwcG9ydGluZy10ZXh0XCJgIHNsb3QgaWYgbm90aGluZyBpcyBpbiBfZGVmYXVsdF8uXG4gICAgICovXG4gICAgZ2V0IHR5cGVhaGVhZFRleHQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lbnVJdGVtQ29udHJvbGxlci50eXBlYWhlYWRUZXh0O1xuICAgIH1cbiAgICBzZXRUeXBlYWhlYWRUZXh0KHRleHQpIHtcbiAgICAgICAgdGhpcy5tZW51SXRlbUNvbnRyb2xsZXIuc2V0VHlwZWFoZWFkVGV4dCh0ZXh0KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhlIHRleHQgdGhhdCBpcyBkaXNwbGF5ZWQgaW4gdGhlIHNlbGVjdCBmaWVsZCB3aGVuIHNlbGVjdGVkLiBJZiBub3Qgc2V0LFxuICAgICAqIGRlZmF1bHRzIHRvIHRoZSB0ZXh0Q29udGVudCBvZiB0aGUgaXRlbSBzbG90dGVkIGludG8gdGhlIGBcImhlYWRsaW5lXCJgIHNsb3QsXG4gICAgICogYW5kIGlmIHRoZXJlIGFyZSBubyBzbG90dGVkIGVsZW1lbnRzIGludG8gaGVhZGxpbmUsIHRoZW4gaXQgY2hlY2tzIHRoZVxuICAgICAqIF9kZWZhdWx0XyBzbG90LCBhbmQgdGhlbiB0aGUgYFwic3VwcG9ydGluZy10ZXh0XCJgIHNsb3QgaWYgbm90aGluZyBpcyBpblxuICAgICAqIF9kZWZhdWx0Xy5cbiAgICAgKi9cbiAgICBnZXQgZGlzcGxheVRleHQoKSB7XG4gICAgICAgIGlmICh0aGlzLmludGVybmFsRGlzcGxheVRleHQgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmludGVybmFsRGlzcGxheVRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMubWVudUl0ZW1Db250cm9sbGVyLnR5cGVhaGVhZFRleHQ7XG4gICAgfVxuICAgIHNldERpc3BsYXlUZXh0KHRleHQpIHtcbiAgICAgICAgdGhpcy5pbnRlcm5hbERpc3BsYXlUZXh0ID0gdGV4dDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQHBhcmFtIGhvc3QgVGhlIFNlbGVjdE9wdGlvbiBpbiB3aGljaCB0byBhdHRhY2ggdGhpcyBjb250cm9sbGVyIHRvLlxuICAgICAqIEBwYXJhbSBjb25maWcgVGhlIG9iamVjdCB0aGF0IGNvbmZpZ3VyZXMgdGhpcyBjb250cm9sbGVyJ3MgYmVoYXZpb3IuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoaG9zdCwgY29uZmlnKSB7XG4gICAgICAgIHRoaXMuaG9zdCA9IGhvc3Q7XG4gICAgICAgIHRoaXMuaW50ZXJuYWxEaXNwbGF5VGV4dCA9IG51bGw7XG4gICAgICAgIHRoaXMuZmlyc3RVcGRhdGUgPSB0cnVlO1xuICAgICAgICAvKipcbiAgICAgICAgICogQmluZCB0aGlzIGNsaWNrIGxpc3RlbmVyIHRvIHRoZSBpbnRlcmFjdGl2ZSBlbGVtZW50LiBIYW5kbGVzIGNsb3NpbmcgdGhlXG4gICAgICAgICAqIG1lbnUuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLm9uQ2xpY2sgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLm1lbnVJdGVtQ29udHJvbGxlci5vbkNsaWNrKCk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBCaW5kIHRoaXMgY2xpY2sgbGlzdGVuZXIgdG8gdGhlIGludGVyYWN0aXZlIGVsZW1lbnQuIEhhbmRsZXMgY2xvc2luZyB0aGVcbiAgICAgICAgICogbWVudS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMub25LZXlkb3duID0gKGUpID0+IHtcbiAgICAgICAgICAgIHRoaXMubWVudUl0ZW1Db250cm9sbGVyLm9uS2V5ZG93bihlKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5sYXN0U2VsZWN0ZWQgPSB0aGlzLmhvc3Quc2VsZWN0ZWQ7XG4gICAgICAgIHRoaXMubWVudUl0ZW1Db250cm9sbGVyID0gbmV3IE1lbnVJdGVtQ29udHJvbGxlcihob3N0LCBjb25maWcpO1xuICAgICAgICBob3N0LmFkZENvbnRyb2xsZXIodGhpcyk7XG4gICAgfVxuICAgIGhvc3RVcGRhdGUoKSB7XG4gICAgICAgIGlmICh0aGlzLmxhc3RTZWxlY3RlZCAhPT0gdGhpcy5ob3N0LnNlbGVjdGVkKSB7XG4gICAgICAgICAgICB0aGlzLmhvc3QuYXJpYVNlbGVjdGVkID0gdGhpcy5ob3N0LnNlbGVjdGVkID8gJ3RydWUnIDogJ2ZhbHNlJztcbiAgICAgICAgfVxuICAgIH1cbiAgICBob3N0VXBkYXRlZCgpIHtcbiAgICAgICAgLy8gRG8gbm90IGRpc3BhdGNoIGV2ZW50IG9uIGZpcnN0IHVwZGF0ZSAvIGJvb3QtdXAuXG4gICAgICAgIGlmICh0aGlzLmxhc3RTZWxlY3RlZCAhPT0gdGhpcy5ob3N0LnNlbGVjdGVkICYmICF0aGlzLmZpcnN0VXBkYXRlKSB7XG4gICAgICAgICAgICAvLyBUaGlzIHNlY3Rpb24gaXMgcmVhbGx5IHVzZWZ1bCBmb3Igd2hlbiB0aGUgdXNlciBzZXRzIHNlbGVjdGVkIG9uIHRoZVxuICAgICAgICAgICAgLy8gb3B0aW9uIHByb2dyYW1tYXRpY2FsbHkuIE1vc3Qgb3RoZXIgY2FzZXMgKGNsaWNrIGFuZCBrZXlib2FyZCkgYXJlXG4gICAgICAgICAgICAvLyBoYW5kbGVkIGJ5IG1kLXNlbGVjdCBiZWNhdXNlIGl0IG5lZWRzIHRvIGNvb3JkaW5hdGUgdGhlXG4gICAgICAgICAgICAvLyBzaW5nbGUtc2VsZWN0aW9uIGJlaGF2aW9yLlxuICAgICAgICAgICAgaWYgKHRoaXMuaG9zdC5zZWxlY3RlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaG9zdC5kaXNwYXRjaEV2ZW50KGNyZWF0ZVJlcXVlc3RTZWxlY3Rpb25FdmVudCgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuaG9zdC5kaXNwYXRjaEV2ZW50KGNyZWF0ZVJlcXVlc3REZXNlbGVjdGlvbkV2ZW50KCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMubGFzdFNlbGVjdGVkID0gdGhpcy5ob3N0LnNlbGVjdGVkO1xuICAgICAgICB0aGlzLmZpcnN0VXBkYXRlID0gZmFsc2U7XG4gICAgfVxufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2VsZWN0T3B0aW9uQ29udHJvbGxlci5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyNCBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG4vLyBHZW5lcmF0ZWQgc3R5bGVzaGVldCBmb3IgLi9zZWxlY3QvaW50ZXJuYWwvc2hhcmVkLXN0eWxlcy5jc3MuXG5pbXBvcnQgeyBjc3MgfSBmcm9tICdsaXQnO1xuZXhwb3J0IGNvbnN0IHN0eWxlcyA9IGNzcyBgOmhvc3R7Y29sb3I6dW5zZXQ7bWluLXdpZHRoOjIxMHB4O2Rpc3BsYXk6ZmxleH0uZmllbGR7Y3Vyc29yOmRlZmF1bHQ7b3V0bGluZTpub25lfS5zZWxlY3R7cG9zaXRpb246cmVsYXRpdmU7ZmxleC1kaXJlY3Rpb246Y29sdW1ufS5pY29uLnRyYWlsaW5nIHN2ZywuaWNvbiA6OnNsb3R0ZWQoKil7ZmlsbDpjdXJyZW50Q29sb3J9Lmljb24gOjpzbG90dGVkKCope3dpZHRoOmluaGVyaXQ7aGVpZ2h0OmluaGVyaXQ7Zm9udC1zaXplOmluaGVyaXR9Lmljb24gc2xvdHtkaXNwbGF5OmZsZXg7aGVpZ2h0OjEwMCU7d2lkdGg6MTAwJTthbGlnbi1pdGVtczpjZW50ZXI7anVzdGlmeS1jb250ZW50OmNlbnRlcn0uaWNvbi50cmFpbGluZyA6aXMoLnVwLC5kb3duKXtvcGFjaXR5OjA7dHJhbnNpdGlvbjpvcGFjaXR5IDc1bXMgbGluZWFyIDc1bXN9LnNlbGVjdDpub3QoLm9wZW4pIC5kb3duLC5zZWxlY3Qub3BlbiAudXB7b3BhY2l0eToxfS5maWVsZCwuc2VsZWN0LG1kLW1lbnV7bWluLXdpZHRoOmluaGVyaXQ7d2lkdGg6aW5oZXJpdDttYXgtd2lkdGg6aW5oZXJpdDtkaXNwbGF5OmZsZXh9bWQtbWVudXttaW4td2lkdGg6dmFyKC0tX19tZW51LW1pbi13aWR0aCk7bWF4LXdpZHRoOnZhcigtLV9fbWVudS1tYXgtd2lkdGgsIGluaGVyaXQpfS5tZW51LXdyYXBwZXJ7d2lkdGg6MHB4O2hlaWdodDowcHg7bWF4LXdpZHRoOmluaGVyaXR9bWQtbWVudSA6OnNsb3R0ZWQoOm5vdFtkaXNhYmxlZF0pe2N1cnNvcjpwb2ludGVyfS5maWVsZCwuc2VsZWN0e3dpZHRoOjEwMCV9Omhvc3R7ZGlzcGxheTppbmxpbmUtZmxleH06aG9zdChbZGlzYWJsZWRdKXtwb2ludGVyLWV2ZW50czpub25lfVxuYDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXNoYXJlZC1zdHlsZXMuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjMgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuLyoqXG4gKiBHaXZlbiBhIGxpc3Qgb2Ygc2VsZWN0IG9wdGlvbnMsIHRoaXMgZnVuY3Rpb24gd2lsbCByZXR1cm4gYW4gYXJyYXkgb2ZcbiAqIFNlbGVjdE9wdGlvblJlY29yZHMgdGhhdCBhcmUgc2VsZWN0ZWQuXG4gKlxuICogQHJldHVybiBBbiBhcnJheSBvZiBTZWxlY3RPcHRpb25SZWNvcmRzIGRlc2NyaWJpbmcgdGhlIG9wdGlvbnMgdGhhdCBhcmVcbiAqIHNlbGVjdGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2VsZWN0ZWRJdGVtcyhpdGVtcykge1xuICAgIGNvbnN0IHNlbGVjdGVkSXRlbVJlY29yZHMgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGl0ZW0gPSBpdGVtc1tpXTtcbiAgICAgICAgaWYgKGl0ZW0uc2VsZWN0ZWQpIHtcbiAgICAgICAgICAgIHNlbGVjdGVkSXRlbVJlY29yZHMucHVzaChbaXRlbSwgaV0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBzZWxlY3RlZEl0ZW1SZWNvcmRzO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2hhcmVkLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDI0IEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbi8vIEdlbmVyYXRlZCBzdHlsZXNoZWV0IGZvciAuL3RleHRmaWVsZC9pbnRlcm5hbC9maWxsZWQtc3R5bGVzLmNzcy5cbmltcG9ydCB7IGNzcyB9IGZyb20gJ2xpdCc7XG5leHBvcnQgY29uc3Qgc3R5bGVzID0gY3NzIGA6aG9zdHstLV9hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fYWN0aXZlLWluZGljYXRvci1oZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0LCAxcHgpOy0tX2NhcmV0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1jYXJldC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKTstLV9jb250YWluZXItY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWNvbnRhaW5lci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXN1cmZhY2UtY29udGFpbmVyLWhpZ2hlc3QsICNlNmUwZTkpKTstLV9kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2Rpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0OiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodCwgMXB4KTstLV9kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLW9wYWNpdHk6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWRpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3Itb3BhY2l0eSwgMC4zOCk7LS1fZGlzYWJsZWQtY29udGFpbmVyLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1kaXNhYmxlZC1jb250YWluZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1fZGlzYWJsZWQtY29udGFpbmVyLW9wYWNpdHk6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWRpc2FibGVkLWNvbnRhaW5lci1vcGFjaXR5LCAwLjA0KTstLV9kaXNhYmxlZC1pbnB1dC10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1kaXNhYmxlZC1pbnB1dC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2Rpc2FibGVkLWlucHV0LXRleHQtb3BhY2l0eTogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZGlzYWJsZWQtaW5wdXQtdGV4dC1vcGFjaXR5LCAwLjM4KTstLV9kaXNhYmxlZC1sYWJlbC10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1kaXNhYmxlZC1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2Rpc2FibGVkLWxhYmVsLXRleHQtb3BhY2l0eTogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZGlzYWJsZWQtbGFiZWwtdGV4dC1vcGFjaXR5LCAwLjM4KTstLV9kaXNhYmxlZC1sZWFkaW5nLWljb24tY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWRpc2FibGVkLWxlYWRpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV9kaXNhYmxlZC1sZWFkaW5nLWljb24tb3BhY2l0eTogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZGlzYWJsZWQtbGVhZGluZy1pY29uLW9wYWNpdHksIDAuMzgpOy0tX2Rpc2FibGVkLXN1cHBvcnRpbmctdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZGlzYWJsZWQtc3VwcG9ydGluZy10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2Rpc2FibGVkLXN1cHBvcnRpbmctdGV4dC1vcGFjaXR5OiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1kaXNhYmxlZC1zdXBwb3J0aW5nLXRleHQtb3BhY2l0eSwgMC4zOCk7LS1fZGlzYWJsZWQtdHJhaWxpbmctaWNvbi1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZGlzYWJsZWQtdHJhaWxpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV9kaXNhYmxlZC10cmFpbGluZy1pY29uLW9wYWNpdHk6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWRpc2FibGVkLXRyYWlsaW5nLWljb24tb3BhY2l0eSwgMC4zOCk7LS1fZXJyb3ItYWN0aXZlLWluZGljYXRvci1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZXJyb3ItYWN0aXZlLWluZGljYXRvci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLWVycm9yLCAjYjMyNjFlKSk7LS1fZXJyb3ItZm9jdXMtYWN0aXZlLWluZGljYXRvci1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZXJyb3ItZm9jdXMtYWN0aXZlLWluZGljYXRvci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLWVycm9yLCAjYjMyNjFlKSk7LS1fZXJyb3ItZm9jdXMtY2FyZXQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWVycm9yLWZvY3VzLWNhcmV0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItZXJyb3IsICNiMzI2MWUpKTstLV9lcnJvci1mb2N1cy1pbnB1dC10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1lcnJvci1mb2N1cy1pbnB1dC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2Vycm9yLWZvY3VzLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWVycm9yLWZvY3VzLWxhYmVsLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1lcnJvciwgI2IzMjYxZSkpOy0tX2Vycm9yLWZvY3VzLWxlYWRpbmctaWNvbi1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZXJyb3ItZm9jdXMtbGVhZGluZy1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fZXJyb3ItZm9jdXMtc3VwcG9ydGluZy10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1lcnJvci1mb2N1cy1zdXBwb3J0aW5nLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1lcnJvciwgI2IzMjYxZSkpOy0tX2Vycm9yLWZvY3VzLXRyYWlsaW5nLWljb24tY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWVycm9yLWZvY3VzLXRyYWlsaW5nLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1lcnJvciwgI2IzMjYxZSkpOy0tX2Vycm9yLWhvdmVyLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWVycm9yLWhvdmVyLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1lcnJvci1jb250YWluZXIsICM0MTBlMGIpKTstLV9lcnJvci1ob3Zlci1pbnB1dC10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1lcnJvci1ob3Zlci1pbnB1dC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZSwgIzFkMWIyMCkpOy0tX2Vycm9yLWhvdmVyLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWVycm9yLWhvdmVyLWxhYmVsLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1lcnJvci1jb250YWluZXIsICM0MTBlMGIpKTstLV9lcnJvci1ob3Zlci1sZWFkaW5nLWljb24tY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWVycm9yLWhvdmVyLWxlYWRpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2Vycm9yLWhvdmVyLXN0YXRlLWxheWVyLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1lcnJvci1ob3Zlci1zdGF0ZS1sYXllci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV9lcnJvci1ob3Zlci1zdGF0ZS1sYXllci1vcGFjaXR5OiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1lcnJvci1ob3Zlci1zdGF0ZS1sYXllci1vcGFjaXR5LCAwLjA4KTstLV9lcnJvci1ob3Zlci1zdXBwb3J0aW5nLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWVycm9yLWhvdmVyLXN1cHBvcnRpbmctdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLWVycm9yLCAjYjMyNjFlKSk7LS1fZXJyb3ItaG92ZXItdHJhaWxpbmctaWNvbi1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZXJyb3ItaG92ZXItdHJhaWxpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLWVycm9yLWNvbnRhaW5lciwgIzQxMGUwYikpOy0tX2Vycm9yLWlucHV0LXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWVycm9yLWlucHV0LXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1fZXJyb3ItbGFiZWwtdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZXJyb3ItbGFiZWwtdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLWVycm9yLCAjYjMyNjFlKSk7LS1fZXJyb3ItbGVhZGluZy1pY29uLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1lcnJvci1sZWFkaW5nLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV9lcnJvci1zdXBwb3J0aW5nLXRleHQtY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWVycm9yLXN1cHBvcnRpbmctdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLWVycm9yLCAjYjMyNjFlKSk7LS1fZXJyb3ItdHJhaWxpbmctaWNvbi1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZXJyb3ItdHJhaWxpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLWVycm9yLCAjYjMyNjFlKSk7LS1fZm9jdXMtYWN0aXZlLWluZGljYXRvci1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZm9jdXMtYWN0aXZlLWluZGljYXRvci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKTstLV9mb2N1cy1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodDogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZm9jdXMtYWN0aXZlLWluZGljYXRvci1oZWlnaHQsIDNweCk7LS1fZm9jdXMtaW5wdXQtdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZm9jdXMtaW5wdXQtdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV9mb2N1cy1sYWJlbC10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1mb2N1cy1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3ItcHJpbWFyeSwgIzY3NTBhNCkpOy0tX2ZvY3VzLWxlYWRpbmctaWNvbi1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtZm9jdXMtbGVhZGluZy1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1fZm9jdXMtc3VwcG9ydGluZy10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1mb2N1cy1zdXBwb3J0aW5nLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV9mb2N1cy10cmFpbGluZy1pY29uLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1mb2N1cy10cmFpbGluZy1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1faG92ZXItYWN0aXZlLWluZGljYXRvci1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtaG92ZXItYWN0aXZlLWluZGljYXRvci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV9ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodDogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtaG92ZXItYWN0aXZlLWluZGljYXRvci1oZWlnaHQsIDFweCk7LS1faG92ZXItaW5wdXQtdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtaG92ZXItaW5wdXQtdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV9ob3Zlci1sYWJlbC10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1ob3Zlci1sYWJlbC10ZXh0LWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1faG92ZXItbGVhZGluZy1pY29uLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1ob3Zlci1sZWFkaW5nLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV9ob3Zlci1zdGF0ZS1sYXllci1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtaG92ZXItc3RhdGUtbGF5ZXItY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLCAjMWQxYjIwKSk7LS1faG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eTogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtaG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eSwgMC4wOCk7LS1faG92ZXItc3VwcG9ydGluZy10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1ob3Zlci1zdXBwb3J0aW5nLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV9ob3Zlci10cmFpbGluZy1pY29uLWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1ob3Zlci10cmFpbGluZy1pY29uLWNvbG9yLCB2YXIoLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZS12YXJpYW50LCAjNDk0NTRmKSk7LS1faW5wdXQtdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtaW5wdXQtdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UsICMxZDFiMjApKTstLV9pbnB1dC10ZXh0LWZvbnQ6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWlucHV0LXRleHQtZm9udCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LWxhcmdlLWZvbnQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS1wbGFpbiwgUm9ib3RvKSkpOy0tX2lucHV0LXRleHQtbGluZS1oZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWlucHV0LXRleHQtbGluZS1oZWlnaHQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS1saW5lLWhlaWdodCwgMS41cmVtKSk7LS1faW5wdXQtdGV4dC1wbGFjZWhvbGRlci1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtaW5wdXQtdGV4dC1wbGFjZWhvbGRlci1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2lucHV0LXRleHQtcHJlZml4LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1pbnB1dC10ZXh0LXByZWZpeC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2lucHV0LXRleHQtc2l6ZTogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtaW5wdXQtdGV4dC1zaXplLCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbGFyZ2Utc2l6ZSwgMXJlbSkpOy0tX2lucHV0LXRleHQtc3VmZml4LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1pbnB1dC10ZXh0LXN1ZmZpeC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2lucHV0LXRleHQtd2VpZ2h0OiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1pbnB1dC10ZXh0LXdlaWdodCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LWxhcmdlLXdlaWdodCwgdmFyKC0tbWQtcmVmLXR5cGVmYWNlLXdlaWdodC1yZWd1bGFyLCA0MDApKSk7LS1fbGFiZWwtdGV4dC1jb2xvcjogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtbGFiZWwtdGV4dC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2xhYmVsLXRleHQtZm9udDogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtbGFiZWwtdGV4dC1mb250LCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbGFyZ2UtZm9udCwgdmFyKC0tbWQtcmVmLXR5cGVmYWNlLXBsYWluLCBSb2JvdG8pKSk7LS1fbGFiZWwtdGV4dC1saW5lLWhlaWdodDogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtbGFiZWwtdGV4dC1saW5lLWhlaWdodCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LWxhcmdlLWxpbmUtaGVpZ2h0LCAxLjVyZW0pKTstLV9sYWJlbC10ZXh0LXBvcHVsYXRlZC1saW5lLWhlaWdodDogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtbGFiZWwtdGV4dC1wb3B1bGF0ZWQtbGluZS1oZWlnaHQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1zbWFsbC1saW5lLWhlaWdodCwgMXJlbSkpOy0tX2xhYmVsLXRleHQtcG9wdWxhdGVkLXNpemU6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWxhYmVsLXRleHQtcG9wdWxhdGVkLXNpemUsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1zbWFsbC1zaXplLCAwLjc1cmVtKSk7LS1fbGFiZWwtdGV4dC1zaXplOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1sYWJlbC10ZXh0LXNpemUsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1sYXJnZS1zaXplLCAxcmVtKSk7LS1fbGFiZWwtdGV4dC13ZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWxhYmVsLXRleHQtd2VpZ2h0LCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktbGFyZ2Utd2VpZ2h0LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2Utd2VpZ2h0LXJlZ3VsYXIsIDQwMCkpKTstLV9sZWFkaW5nLWljb24tY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWxlYWRpbmctaWNvbi1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLW9uLXN1cmZhY2UtdmFyaWFudCwgIzQ5NDU0ZikpOy0tX2xlYWRpbmctaWNvbi1zaXplOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1sZWFkaW5nLWljb24tc2l6ZSwgMjRweCk7LS1fc3VwcG9ydGluZy10ZXh0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1zdXBwb3J0aW5nLXRleHQtY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV9zdXBwb3J0aW5nLXRleHQtZm9udDogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtc3VwcG9ydGluZy10ZXh0LWZvbnQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1zbWFsbC1mb250LCB2YXIoLS1tZC1yZWYtdHlwZWZhY2UtcGxhaW4sIFJvYm90bykpKTstLV9zdXBwb3J0aW5nLXRleHQtbGluZS1oZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLXN1cHBvcnRpbmctdGV4dC1saW5lLWhlaWdodCwgdmFyKC0tbWQtc3lzLXR5cGVzY2FsZS1ib2R5LXNtYWxsLWxpbmUtaGVpZ2h0LCAxcmVtKSk7LS1fc3VwcG9ydGluZy10ZXh0LXNpemU6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLXN1cHBvcnRpbmctdGV4dC1zaXplLCB2YXIoLS1tZC1zeXMtdHlwZXNjYWxlLWJvZHktc21hbGwtc2l6ZSwgMC43NXJlbSkpOy0tX3N1cHBvcnRpbmctdGV4dC13ZWlnaHQ6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLXN1cHBvcnRpbmctdGV4dC13ZWlnaHQsIHZhcigtLW1kLXN5cy10eXBlc2NhbGUtYm9keS1zbWFsbC13ZWlnaHQsIHZhcigtLW1kLXJlZi10eXBlZmFjZS13ZWlnaHQtcmVndWxhciwgNDAwKSkpOy0tX3RyYWlsaW5nLWljb24tY29sb3I6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLXRyYWlsaW5nLWljb24tY29sb3IsIHZhcigtLW1kLXN5cy1jb2xvci1vbi1zdXJmYWNlLXZhcmlhbnQsICM0OTQ1NGYpKTstLV90cmFpbGluZy1pY29uLXNpemU6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLXRyYWlsaW5nLWljb24tc2l6ZSwgMjRweCk7LS1fY29udGFpbmVyLXNoYXBlLXN0YXJ0LXN0YXJ0OiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1jb250YWluZXItc2hhcGUtc3RhcnQtc3RhcnQsIHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWNvbnRhaW5lci1zaGFwZSwgdmFyKC0tbWQtc3lzLXNoYXBlLWNvcm5lci1leHRyYS1zbWFsbCwgNHB4KSkpOy0tX2NvbnRhaW5lci1zaGFwZS1zdGFydC1lbmQ6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWNvbnRhaW5lci1zaGFwZS1zdGFydC1lbmQsIHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWNvbnRhaW5lci1zaGFwZSwgdmFyKC0tbWQtc3lzLXNoYXBlLWNvcm5lci1leHRyYS1zbWFsbCwgNHB4KSkpOy0tX2NvbnRhaW5lci1zaGFwZS1lbmQtZW5kOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1jb250YWluZXItc2hhcGUtZW5kLWVuZCwgdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtY29udGFpbmVyLXNoYXBlLCB2YXIoLS1tZC1zeXMtc2hhcGUtY29ybmVyLW5vbmUsIDBweCkpKTstLV9jb250YWluZXItc2hhcGUtZW5kLXN0YXJ0OiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1jb250YWluZXItc2hhcGUtZW5kLXN0YXJ0LCB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1jb250YWluZXItc2hhcGUsIHZhcigtLW1kLXN5cy1zaGFwZS1jb3JuZXItbm9uZSwgMHB4KSkpOy0tX2ljb24taW5wdXQtc3BhY2U6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWljb24taW5wdXQtc3BhY2UsIDE2cHgpOy0tX2xlYWRpbmctc3BhY2U6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLWxlYWRpbmctc3BhY2UsIDE2cHgpOy0tX3RyYWlsaW5nLXNwYWNlOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC10cmFpbGluZy1zcGFjZSwgMTZweCk7LS1fdG9wLXNwYWNlOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC10b3Atc3BhY2UsIDE2cHgpOy0tX2JvdHRvbS1zcGFjZTogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtYm90dG9tLXNwYWNlLCAxNnB4KTstLV9pbnB1dC10ZXh0LXByZWZpeC10cmFpbGluZy1zcGFjZTogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtaW5wdXQtdGV4dC1wcmVmaXgtdHJhaWxpbmctc3BhY2UsIDJweCk7LS1faW5wdXQtdGV4dC1zdWZmaXgtbGVhZGluZy1zcGFjZTogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtaW5wdXQtdGV4dC1zdWZmaXgtbGVhZGluZy1zcGFjZSwgMnB4KTstLV93aXRoLWxhYmVsLXRvcC1zcGFjZTogdmFyKC0tbWQtZmlsbGVkLXRleHQtZmllbGQtd2l0aC1sYWJlbC10b3Atc3BhY2UsIDhweCk7LS1fd2l0aC1sYWJlbC1ib3R0b20tc3BhY2U6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLXdpdGgtbGFiZWwtYm90dG9tLXNwYWNlLCA4cHgpOy0tX2ZvY3VzLWNhcmV0LWNvbG9yOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC1mb2N1cy1jYXJldC1jb2xvciwgdmFyKC0tbWQtc3lzLWNvbG9yLXByaW1hcnksICM2NzUwYTQpKTstLV93aXRoLWxlYWRpbmctaWNvbi1sZWFkaW5nLXNwYWNlOiB2YXIoLS1tZC1maWxsZWQtdGV4dC1maWVsZC13aXRoLWxlYWRpbmctaWNvbi1sZWFkaW5nLXNwYWNlLCAxMnB4KTstLV93aXRoLXRyYWlsaW5nLWljb24tdHJhaWxpbmctc3BhY2U6IHZhcigtLW1kLWZpbGxlZC10ZXh0LWZpZWxkLXdpdGgtdHJhaWxpbmctaWNvbi10cmFpbGluZy1zcGFjZSwgMTJweCk7LS1tZC1maWxsZWQtZmllbGQtYWN0aXZlLWluZGljYXRvci1jb2xvcjogdmFyKC0tX2FjdGl2ZS1pbmRpY2F0b3ItY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0OiB2YXIoLS1fYWN0aXZlLWluZGljYXRvci1oZWlnaHQpOy0tbWQtZmlsbGVkLWZpZWxkLWJvdHRvbS1zcGFjZTogdmFyKC0tX2JvdHRvbS1zcGFjZSk7LS1tZC1maWxsZWQtZmllbGQtY29udGFpbmVyLWNvbG9yOiB2YXIoLS1fY29udGFpbmVyLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1jb250YWluZXItc2hhcGUtZW5kLWVuZDogdmFyKC0tX2NvbnRhaW5lci1zaGFwZS1lbmQtZW5kKTstLW1kLWZpbGxlZC1maWVsZC1jb250YWluZXItc2hhcGUtZW5kLXN0YXJ0OiB2YXIoLS1fY29udGFpbmVyLXNoYXBlLWVuZC1zdGFydCk7LS1tZC1maWxsZWQtZmllbGQtY29udGFpbmVyLXNoYXBlLXN0YXJ0LWVuZDogdmFyKC0tX2NvbnRhaW5lci1zaGFwZS1zdGFydC1lbmQpOy0tbWQtZmlsbGVkLWZpZWxkLWNvbnRhaW5lci1zaGFwZS1zdGFydC1zdGFydDogdmFyKC0tX2NvbnRhaW5lci1zaGFwZS1zdGFydC1zdGFydCk7LS1tZC1maWxsZWQtZmllbGQtY29udGVudC1jb2xvcjogdmFyKC0tX2lucHV0LXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWNvbnRlbnQtZm9udDogdmFyKC0tX2lucHV0LXRleHQtZm9udCk7LS1tZC1maWxsZWQtZmllbGQtY29udGVudC1saW5lLWhlaWdodDogdmFyKC0tX2lucHV0LXRleHQtbGluZS1oZWlnaHQpOy0tbWQtZmlsbGVkLWZpZWxkLWNvbnRlbnQtc2l6ZTogdmFyKC0tX2lucHV0LXRleHQtc2l6ZSk7LS1tZC1maWxsZWQtZmllbGQtY29udGVudC1zcGFjZTogdmFyKC0tX2ljb24taW5wdXQtc3BhY2UpOy0tbWQtZmlsbGVkLWZpZWxkLWNvbnRlbnQtd2VpZ2h0OiB2YXIoLS1faW5wdXQtdGV4dC13ZWlnaHQpOy0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3I6IHZhcigtLV9kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodDogdmFyKC0tX2Rpc2FibGVkLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0KTstLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLW9wYWNpdHk6IHZhcigtLV9kaXNhYmxlZC1hY3RpdmUtaW5kaWNhdG9yLW9wYWNpdHkpOy0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLWNvbnRhaW5lci1jb2xvcjogdmFyKC0tX2Rpc2FibGVkLWNvbnRhaW5lci1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtY29udGFpbmVyLW9wYWNpdHk6IHZhcigtLV9kaXNhYmxlZC1jb250YWluZXItb3BhY2l0eSk7LS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtY29udGVudC1jb2xvcjogdmFyKC0tX2Rpc2FibGVkLWlucHV0LXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLWNvbnRlbnQtb3BhY2l0eTogdmFyKC0tX2Rpc2FibGVkLWlucHV0LXRleHQtb3BhY2l0eSk7LS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtbGFiZWwtdGV4dC1jb2xvcjogdmFyKC0tX2Rpc2FibGVkLWxhYmVsLXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLWxhYmVsLXRleHQtb3BhY2l0eTogdmFyKC0tX2Rpc2FibGVkLWxhYmVsLXRleHQtb3BhY2l0eSk7LS1tZC1maWxsZWQtZmllbGQtZGlzYWJsZWQtbGVhZGluZy1jb250ZW50LWNvbG9yOiB2YXIoLS1fZGlzYWJsZWQtbGVhZGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1sZWFkaW5nLWNvbnRlbnQtb3BhY2l0eTogdmFyKC0tX2Rpc2FibGVkLWxlYWRpbmctaWNvbi1vcGFjaXR5KTstLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC1zdXBwb3J0aW5nLXRleHQtY29sb3I6IHZhcigtLV9kaXNhYmxlZC1zdXBwb3J0aW5nLXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLXN1cHBvcnRpbmctdGV4dC1vcGFjaXR5OiB2YXIoLS1fZGlzYWJsZWQtc3VwcG9ydGluZy10ZXh0LW9wYWNpdHkpOy0tbWQtZmlsbGVkLWZpZWxkLWRpc2FibGVkLXRyYWlsaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV9kaXNhYmxlZC10cmFpbGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1kaXNhYmxlZC10cmFpbGluZy1jb250ZW50LW9wYWNpdHk6IHZhcigtLV9kaXNhYmxlZC10cmFpbGluZy1pY29uLW9wYWNpdHkpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3I6IHZhcigtLV9lcnJvci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1jb250ZW50LWNvbG9yOiB2YXIoLS1fZXJyb3ItaW5wdXQtdGV4dC1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZXJyb3ItZm9jdXMtYWN0aXZlLWluZGljYXRvci1jb2xvcjogdmFyKC0tX2Vycm9yLWZvY3VzLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWZvY3VzLWNvbnRlbnQtY29sb3I6IHZhcigtLV9lcnJvci1mb2N1cy1pbnB1dC10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1mb2N1cy1sYWJlbC10ZXh0LWNvbG9yOiB2YXIoLS1fZXJyb3ItZm9jdXMtbGFiZWwtdGV4dC1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZXJyb3ItZm9jdXMtbGVhZGluZy1jb250ZW50LWNvbG9yOiB2YXIoLS1fZXJyb3ItZm9jdXMtbGVhZGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1mb2N1cy1zdXBwb3J0aW5nLXRleHQtY29sb3I6IHZhcigtLV9lcnJvci1mb2N1cy1zdXBwb3J0aW5nLXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWZvY3VzLXRyYWlsaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV9lcnJvci1mb2N1cy10cmFpbGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1fZXJyb3ItaG92ZXItYWN0aXZlLWluZGljYXRvci1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZXJyb3ItaG92ZXItY29udGVudC1jb2xvcjogdmFyKC0tX2Vycm9yLWhvdmVyLWlucHV0LXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWhvdmVyLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLV9lcnJvci1ob3Zlci1sYWJlbC10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1ob3Zlci1sZWFkaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV9lcnJvci1ob3Zlci1sZWFkaW5nLWljb24tY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWhvdmVyLXN0YXRlLWxheWVyLWNvbG9yOiB2YXIoLS1fZXJyb3ItaG92ZXItc3RhdGUtbGF5ZXItY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWhvdmVyLXN0YXRlLWxheWVyLW9wYWNpdHk6IHZhcigtLV9lcnJvci1ob3Zlci1zdGF0ZS1sYXllci1vcGFjaXR5KTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1ob3Zlci1zdXBwb3J0aW5nLXRleHQtY29sb3I6IHZhcigtLV9lcnJvci1ob3Zlci1zdXBwb3J0aW5nLXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLWhvdmVyLXRyYWlsaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV9lcnJvci1ob3Zlci10cmFpbGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1sYWJlbC10ZXh0LWNvbG9yOiB2YXIoLS1fZXJyb3ItbGFiZWwtdGV4dC1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZXJyb3ItbGVhZGluZy1jb250ZW50LWNvbG9yOiB2YXIoLS1fZXJyb3ItbGVhZGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1lcnJvci1zdXBwb3J0aW5nLXRleHQtY29sb3I6IHZhcigtLV9lcnJvci1zdXBwb3J0aW5nLXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWVycm9yLXRyYWlsaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV9lcnJvci10cmFpbGluZy1pY29uLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1mb2N1cy1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yOiB2YXIoLS1fZm9jdXMtYWN0aXZlLWluZGljYXRvci1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZm9jdXMtYWN0aXZlLWluZGljYXRvci1oZWlnaHQ6IHZhcigtLV9mb2N1cy1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodCk7LS1tZC1maWxsZWQtZmllbGQtZm9jdXMtY29udGVudC1jb2xvcjogdmFyKC0tX2ZvY3VzLWlucHV0LXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWZvY3VzLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLV9mb2N1cy1sYWJlbC10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1mb2N1cy1sZWFkaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV9mb2N1cy1sZWFkaW5nLWljb24tY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWZvY3VzLXN1cHBvcnRpbmctdGV4dC1jb2xvcjogdmFyKC0tX2ZvY3VzLXN1cHBvcnRpbmctdGV4dC1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtZm9jdXMtdHJhaWxpbmctY29udGVudC1jb2xvcjogdmFyKC0tX2ZvY3VzLXRyYWlsaW5nLWljb24tY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWhvdmVyLWFjdGl2ZS1pbmRpY2F0b3ItY29sb3I6IHZhcigtLV9ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1ob3Zlci1hY3RpdmUtaW5kaWNhdG9yLWhlaWdodDogdmFyKC0tX2hvdmVyLWFjdGl2ZS1pbmRpY2F0b3ItaGVpZ2h0KTstLW1kLWZpbGxlZC1maWVsZC1ob3Zlci1jb250ZW50LWNvbG9yOiB2YXIoLS1faG92ZXItaW5wdXQtdGV4dC1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtaG92ZXItbGFiZWwtdGV4dC1jb2xvcjogdmFyKC0tX2hvdmVyLWxhYmVsLXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWhvdmVyLWxlYWRpbmctY29udGVudC1jb2xvcjogdmFyKC0tX2hvdmVyLWxlYWRpbmctaWNvbi1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtaG92ZXItc3RhdGUtbGF5ZXItY29sb3I6IHZhcigtLV9ob3Zlci1zdGF0ZS1sYXllci1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtaG92ZXItc3RhdGUtbGF5ZXItb3BhY2l0eTogdmFyKC0tX2hvdmVyLXN0YXRlLWxheWVyLW9wYWNpdHkpOy0tbWQtZmlsbGVkLWZpZWxkLWhvdmVyLXN1cHBvcnRpbmctdGV4dC1jb2xvcjogdmFyKC0tX2hvdmVyLXN1cHBvcnRpbmctdGV4dC1jb2xvcik7LS1tZC1maWxsZWQtZmllbGQtaG92ZXItdHJhaWxpbmctY29udGVudC1jb2xvcjogdmFyKC0tX2hvdmVyLXRyYWlsaW5nLWljb24tY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWxhYmVsLXRleHQtY29sb3I6IHZhcigtLV9sYWJlbC10ZXh0LWNvbG9yKTstLW1kLWZpbGxlZC1maWVsZC1sYWJlbC10ZXh0LWZvbnQ6IHZhcigtLV9sYWJlbC10ZXh0LWZvbnQpOy0tbWQtZmlsbGVkLWZpZWxkLWxhYmVsLXRleHQtbGluZS1oZWlnaHQ6IHZhcigtLV9sYWJlbC10ZXh0LWxpbmUtaGVpZ2h0KTstLW1kLWZpbGxlZC1maWVsZC1sYWJlbC10ZXh0LXBvcHVsYXRlZC1saW5lLWhlaWdodDogdmFyKC0tX2xhYmVsLXRleHQtcG9wdWxhdGVkLWxpbmUtaGVpZ2h0KTstLW1kLWZpbGxlZC1maWVsZC1sYWJlbC10ZXh0LXBvcHVsYXRlZC1zaXplOiB2YXIoLS1fbGFiZWwtdGV4dC1wb3B1bGF0ZWQtc2l6ZSk7LS1tZC1maWxsZWQtZmllbGQtbGFiZWwtdGV4dC1zaXplOiB2YXIoLS1fbGFiZWwtdGV4dC1zaXplKTstLW1kLWZpbGxlZC1maWVsZC1sYWJlbC10ZXh0LXdlaWdodDogdmFyKC0tX2xhYmVsLXRleHQtd2VpZ2h0KTstLW1kLWZpbGxlZC1maWVsZC1sZWFkaW5nLWNvbnRlbnQtY29sb3I6IHZhcigtLV9sZWFkaW5nLWljb24tY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLWxlYWRpbmctc3BhY2U6IHZhcigtLV9sZWFkaW5nLXNwYWNlKTstLW1kLWZpbGxlZC1maWVsZC1zdXBwb3J0aW5nLXRleHQtY29sb3I6IHZhcigtLV9zdXBwb3J0aW5nLXRleHQtY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLXN1cHBvcnRpbmctdGV4dC1mb250OiB2YXIoLS1fc3VwcG9ydGluZy10ZXh0LWZvbnQpOy0tbWQtZmlsbGVkLWZpZWxkLXN1cHBvcnRpbmctdGV4dC1saW5lLWhlaWdodDogdmFyKC0tX3N1cHBvcnRpbmctdGV4dC1saW5lLWhlaWdodCk7LS1tZC1maWxsZWQtZmllbGQtc3VwcG9ydGluZy10ZXh0LXNpemU6IHZhcigtLV9zdXBwb3J0aW5nLXRleHQtc2l6ZSk7LS1tZC1maWxsZWQtZmllbGQtc3VwcG9ydGluZy10ZXh0LXdlaWdodDogdmFyKC0tX3N1cHBvcnRpbmctdGV4dC13ZWlnaHQpOy0tbWQtZmlsbGVkLWZpZWxkLXRvcC1zcGFjZTogdmFyKC0tX3RvcC1zcGFjZSk7LS1tZC1maWxsZWQtZmllbGQtdHJhaWxpbmctY29udGVudC1jb2xvcjogdmFyKC0tX3RyYWlsaW5nLWljb24tY29sb3IpOy0tbWQtZmlsbGVkLWZpZWxkLXRyYWlsaW5nLXNwYWNlOiB2YXIoLS1fdHJhaWxpbmctc3BhY2UpOy0tbWQtZmlsbGVkLWZpZWxkLXdpdGgtbGFiZWwtYm90dG9tLXNwYWNlOiB2YXIoLS1fd2l0aC1sYWJlbC1ib3R0b20tc3BhY2UpOy0tbWQtZmlsbGVkLWZpZWxkLXdpdGgtbGFiZWwtdG9wLXNwYWNlOiB2YXIoLS1fd2l0aC1sYWJlbC10b3Atc3BhY2UpOy0tbWQtZmlsbGVkLWZpZWxkLXdpdGgtbGVhZGluZy1jb250ZW50LWxlYWRpbmctc3BhY2U6IHZhcigtLV93aXRoLWxlYWRpbmctaWNvbi1sZWFkaW5nLXNwYWNlKTstLW1kLWZpbGxlZC1maWVsZC13aXRoLXRyYWlsaW5nLWNvbnRlbnQtdHJhaWxpbmctc3BhY2U6IHZhcigtLV93aXRoLXRyYWlsaW5nLWljb24tdHJhaWxpbmctc3BhY2UpfVxuYDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWZpbGxlZC1zdHlsZXMuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjEgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuaW1wb3J0ICcuLi8uLi9maWVsZC9maWxsZWQtZmllbGQuanMnO1xuaW1wb3J0IHsgbGl0ZXJhbCB9IGZyb20gJ2xpdC9zdGF0aWMtaHRtbC5qcyc7XG5pbXBvcnQgeyBUZXh0RmllbGQgfSBmcm9tICcuL3RleHQtZmllbGQuanMnO1xuLyoqXG4gKiBBIGZpbGxlZCB0ZXh0IGZpZWxkIGNvbXBvbmVudC5cbiAqL1xuZXhwb3J0IGNsYXNzIEZpbGxlZFRleHRGaWVsZCBleHRlbmRzIFRleHRGaWVsZCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuZmllbGRUYWcgPSBsaXRlcmFsIGBtZC1maWxsZWQtZmllbGRgO1xuICAgIH1cbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWZpbGxlZC10ZXh0LWZpZWxkLmpzLm1hcCIsIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDI0IEdvb2dsZSBMTENcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cbi8vIEdlbmVyYXRlZCBzdHlsZXNoZWV0IGZvciAuL3RleHRmaWVsZC9pbnRlcm5hbC9zaGFyZWQtc3R5bGVzLmNzcy5cbmltcG9ydCB7IGNzcyB9IGZyb20gJ2xpdCc7XG5leHBvcnQgY29uc3Qgc3R5bGVzID0gY3NzIGA6aG9zdHtkaXNwbGF5OmlubGluZS1mbGV4O291dGxpbmU6bm9uZTtyZXNpemU6Ym90aDt0ZXh0LWFsaWduOnN0YXJ0Oy13ZWJraXQtdGFwLWhpZ2hsaWdodC1jb2xvcjpyZ2JhKDAsMCwwLDApfS50ZXh0LWZpZWxkLC5maWVsZHt3aWR0aDoxMDAlfS50ZXh0LWZpZWxke2Rpc3BsYXk6aW5saW5lLWZsZXh9LmZpZWxke2N1cnNvcjp0ZXh0fS5kaXNhYmxlZCAuZmllbGR7Y3Vyc29yOmRlZmF1bHR9LnRleHQtZmllbGQsLnRleHRhcmVhIC5maWVsZHtyZXNpemU6aW5oZXJpdH1zbG90W25hbWU9Y29udGFpbmVyXXtib3JkZXItcmFkaXVzOmluaGVyaXR9Lmljb257Y29sb3I6Y3VycmVudENvbG9yO2Rpc3BsYXk6ZmxleDthbGlnbi1pdGVtczpjZW50ZXI7anVzdGlmeS1jb250ZW50OmNlbnRlcjtmaWxsOmN1cnJlbnRDb2xvcjtwb3NpdGlvbjpyZWxhdGl2ZX0uaWNvbiA6OnNsb3R0ZWQoKil7ZGlzcGxheTpmbGV4O3Bvc2l0aW9uOmFic29sdXRlfVtoYXMtc3RhcnRdIC5pY29uLmxlYWRpbmd7Zm9udC1zaXplOnZhcigtLV9sZWFkaW5nLWljb24tc2l6ZSk7aGVpZ2h0OnZhcigtLV9sZWFkaW5nLWljb24tc2l6ZSk7d2lkdGg6dmFyKC0tX2xlYWRpbmctaWNvbi1zaXplKX1baGFzLWVuZF0gLmljb24udHJhaWxpbmd7Zm9udC1zaXplOnZhcigtLV90cmFpbGluZy1pY29uLXNpemUpO2hlaWdodDp2YXIoLS1fdHJhaWxpbmctaWNvbi1zaXplKTt3aWR0aDp2YXIoLS1fdHJhaWxpbmctaWNvbi1zaXplKX0uaW5wdXQtd3JhcHBlcntkaXNwbGF5OmZsZXh9LmlucHV0LXdyYXBwZXI+KnthbGw6aW5oZXJpdDtwYWRkaW5nOjB9LmlucHV0e2NhcmV0LWNvbG9yOnZhcigtLV9jYXJldC1jb2xvcik7b3ZlcmZsb3cteDpoaWRkZW47dGV4dC1hbGlnbjppbmhlcml0fS5pbnB1dDo6cGxhY2Vob2xkZXJ7Y29sb3I6Y3VycmVudENvbG9yO29wYWNpdHk6MX0uaW5wdXQ6Oi13ZWJraXQtY2FsZW5kYXItcGlja2VyLWluZGljYXRvcntkaXNwbGF5Om5vbmV9LmlucHV0Ojotd2Via2l0LXNlYXJjaC1kZWNvcmF0aW9uLC5pbnB1dDo6LXdlYmtpdC1zZWFyY2gtY2FuY2VsLWJ1dHRvbntkaXNwbGF5Om5vbmV9QG1lZGlhKGZvcmNlZC1jb2xvcnM6IGFjdGl2ZSl7LmlucHV0e2JhY2tncm91bmQ6bm9uZX19Lm5vLXNwaW5uZXIgLmlucHV0Ojotd2Via2l0LWlubmVyLXNwaW4tYnV0dG9uLC5uby1zcGlubmVyIC5pbnB1dDo6LXdlYmtpdC1vdXRlci1zcGluLWJ1dHRvbntkaXNwbGF5Om5vbmV9Lm5vLXNwaW5uZXIgLmlucHV0W3R5cGU9bnVtYmVyXXstbW96LWFwcGVhcmFuY2U6dGV4dGZpZWxkfTpmb2N1cy13aXRoaW4gLmlucHV0e2NhcmV0LWNvbG9yOnZhcigtLV9mb2N1cy1jYXJldC1jb2xvcil9LmVycm9yOmZvY3VzLXdpdGhpbiAuaW5wdXR7Y2FyZXQtY29sb3I6dmFyKC0tX2Vycm9yLWZvY3VzLWNhcmV0LWNvbG9yKX0udGV4dC1maWVsZDpub3QoLmRpc2FibGVkKSAucHJlZml4e2NvbG9yOnZhcigtLV9pbnB1dC10ZXh0LXByZWZpeC1jb2xvcil9LnRleHQtZmllbGQ6bm90KC5kaXNhYmxlZCkgLnN1ZmZpeHtjb2xvcjp2YXIoLS1faW5wdXQtdGV4dC1zdWZmaXgtY29sb3IpfS50ZXh0LWZpZWxkOm5vdCguZGlzYWJsZWQpIC5pbnB1dDo6cGxhY2Vob2xkZXJ7Y29sb3I6dmFyKC0tX2lucHV0LXRleHQtcGxhY2Vob2xkZXItY29sb3IpfS5wcmVmaXgsLnN1ZmZpeHt0ZXh0LXdyYXA6bm93cmFwO3dpZHRoOm1pbi1jb250ZW50fS5wcmVmaXh7cGFkZGluZy1pbmxpbmUtZW5kOnZhcigtLV9pbnB1dC10ZXh0LXByZWZpeC10cmFpbGluZy1zcGFjZSl9LnN1ZmZpeHtwYWRkaW5nLWlubGluZS1zdGFydDp2YXIoLS1faW5wdXQtdGV4dC1zdWZmaXgtbGVhZGluZy1zcGFjZSl9XG5gO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2hhcmVkLXN0eWxlcy5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5pbXBvcnQgeyBfX2RlY29yYXRlIH0gZnJvbSBcInRzbGliXCI7XG5pbXBvcnQgeyBMaXRFbGVtZW50LCBodG1sLCBub3RoaW5nIH0gZnJvbSAnbGl0JztcbmltcG9ydCB7IHByb3BlcnR5LCBxdWVyeSwgcXVlcnlBc3NpZ25lZEVsZW1lbnRzLCBzdGF0ZSB9IGZyb20gJ2xpdC9kZWNvcmF0b3JzLmpzJztcbmltcG9ydCB7IGNsYXNzTWFwIH0gZnJvbSAnbGl0L2RpcmVjdGl2ZXMvY2xhc3MtbWFwLmpzJztcbmltcG9ydCB7IGxpdmUgfSBmcm9tICdsaXQvZGlyZWN0aXZlcy9saXZlLmpzJztcbmltcG9ydCB7IHN0eWxlTWFwIH0gZnJvbSAnbGl0L2RpcmVjdGl2ZXMvc3R5bGUtbWFwLmpzJztcbmltcG9ydCB7IGh0bWwgYXMgc3RhdGljSHRtbCB9IGZyb20gJ2xpdC9zdGF0aWMtaHRtbC5qcyc7XG5pbXBvcnQgeyBtaXhpbkRlbGVnYXRlc0FyaWEgfSBmcm9tICcuLi8uLi9pbnRlcm5hbC9hcmlhL2RlbGVnYXRlLmpzJztcbmltcG9ydCB7IHN0cmluZ0NvbnZlcnRlciB9IGZyb20gJy4uLy4uL2ludGVybmFsL2NvbnRyb2xsZXIvc3RyaW5nLWNvbnZlcnRlci5qcyc7XG5pbXBvcnQgeyByZWRpc3BhdGNoRXZlbnQgfSBmcm9tICcuLi8uLi9pbnRlcm5hbC9ldmVudHMvcmVkaXNwYXRjaC1ldmVudC5qcyc7XG5pbXBvcnQgeyBjcmVhdGVWYWxpZGF0b3IsIGdldFZhbGlkaXR5QW5jaG9yLCBtaXhpbkNvbnN0cmFpbnRWYWxpZGF0aW9uLCB9IGZyb20gJy4uLy4uL2xhYnMvYmVoYXZpb3JzL2NvbnN0cmFpbnQtdmFsaWRhdGlvbi5qcyc7XG5pbXBvcnQgeyBtaXhpbkVsZW1lbnRJbnRlcm5hbHMgfSBmcm9tICcuLi8uLi9sYWJzL2JlaGF2aW9ycy9lbGVtZW50LWludGVybmFscy5qcyc7XG5pbXBvcnQgeyBnZXRGb3JtVmFsdWUsIG1peGluRm9ybUFzc29jaWF0ZWQsIH0gZnJvbSAnLi4vLi4vbGFicy9iZWhhdmlvcnMvZm9ybS1hc3NvY2lhdGVkLmpzJztcbmltcG9ydCB7IG1peGluT25SZXBvcnRWYWxpZGl0eSwgb25SZXBvcnRWYWxpZGl0eSwgfSBmcm9tICcuLi8uLi9sYWJzL2JlaGF2aW9ycy9vbi1yZXBvcnQtdmFsaWRpdHkuanMnO1xuaW1wb3J0IHsgVGV4dEZpZWxkVmFsaWRhdG9yIH0gZnJvbSAnLi4vLi4vbGFicy9iZWhhdmlvcnMvdmFsaWRhdG9ycy90ZXh0LWZpZWxkLXZhbGlkYXRvci5qcyc7XG4vLyBTZXBhcmF0ZSB2YXJpYWJsZSBuZWVkZWQgZm9yIGNsb3N1cmUuXG5jb25zdCB0ZXh0RmllbGRCYXNlQ2xhc3MgPSBtaXhpbkRlbGVnYXRlc0FyaWEobWl4aW5PblJlcG9ydFZhbGlkaXR5KG1peGluQ29uc3RyYWludFZhbGlkYXRpb24obWl4aW5Gb3JtQXNzb2NpYXRlZChtaXhpbkVsZW1lbnRJbnRlcm5hbHMoTGl0RWxlbWVudCkpKSkpO1xuLyoqXG4gKiBBIHRleHQgZmllbGQgY29tcG9uZW50LlxuICpcbiAqIEBmaXJlcyBzZWxlY3Qge0V2ZW50fSBUaGUgbmF0aXZlIGBzZWxlY3RgIGV2ZW50IG9uXG4gKiBbYDxpbnB1dD5gXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvSFRNTElucHV0RWxlbWVudC9zZWxlY3RfZXZlbnQpXG4gKiAtLWJ1YmJsZXNcbiAqIEBmaXJlcyBjaGFuZ2Uge0V2ZW50fSBUaGUgbmF0aXZlIGBjaGFuZ2VgIGV2ZW50IG9uXG4gKiBbYDxpbnB1dD5gXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvSFRNTEVsZW1lbnQvY2hhbmdlX2V2ZW50KVxuICogLS1idWJibGVzXG4gKiBAZmlyZXMgaW5wdXQge0lucHV0RXZlbnR9IFRoZSBuYXRpdmUgYGlucHV0YCBldmVudCBvblxuICogW2A8aW5wdXQ+YF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0hUTUxFbGVtZW50L2lucHV0X2V2ZW50KVxuICogLS1idWJibGVzIC0tY29tcG9zZWRcbiAqL1xuZXhwb3J0IGNsYXNzIFRleHRGaWVsZCBleHRlbmRzIHRleHRGaWVsZEJhc2VDbGFzcyB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHZXRzIG9yIHNldHMgd2hldGhlciBvciBub3QgdGhlIHRleHQgZmllbGQgaXMgaW4gYSB2aXN1YWxseSBpbnZhbGlkIHN0YXRlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBUaGlzIGVycm9yIHN0YXRlIG92ZXJyaWRlcyB0aGUgZXJyb3Igc3RhdGUgY29udHJvbGxlZCBieVxuICAgICAgICAgKiBgcmVwb3J0VmFsaWRpdHkoKWAuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmVycm9yID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgZXJyb3IgbWVzc2FnZSB0aGF0IHJlcGxhY2VzIHN1cHBvcnRpbmcgdGV4dCB3aGVuIGBlcnJvcmAgaXMgdHJ1ZS4gSWZcbiAgICAgICAgICogYGVycm9yVGV4dGAgaXMgYW4gZW1wdHkgc3RyaW5nLCB0aGVuIHRoZSBzdXBwb3J0aW5nIHRleHQgd2lsbCBjb250aW51ZSB0b1xuICAgICAgICAgKiBzaG93LlxuICAgICAgICAgKlxuICAgICAgICAgKiBUaGlzIGVycm9yIG1lc3NhZ2Ugb3ZlcnJpZGVzIHRoZSBlcnJvciBtZXNzYWdlIGRpc3BsYXllZCBieVxuICAgICAgICAgKiBgcmVwb3J0VmFsaWRpdHkoKWAuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmVycm9yVGV4dCA9ICcnO1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIGZsb2F0aW5nIE1hdGVyaWFsIGxhYmVsIG9mIHRoZSB0ZXh0ZmllbGQgY29tcG9uZW50LiBJdCBpbmZvcm1zIHRoZSB1c2VyXG4gICAgICAgICAqIGFib3V0IHdoYXQgaW5mb3JtYXRpb24gaXMgcmVxdWVzdGVkIGZvciBhIHRleHQgZmllbGQuIEl0IGlzIGFsaWduZWQgd2l0aFxuICAgICAgICAgKiB0aGUgaW5wdXQgdGV4dCwgaXMgYWx3YXlzIHZpc2libGUsIGFuZCBpdCBmbG9hdHMgd2hlbiBmb2N1c2VkIG9yIHdoZW4gdGV4dFxuICAgICAgICAgKiBpcyBlbnRlcmVkIGludG8gdGhlIHRleHRmaWVsZC4gVGhpcyBsYWJlbCBhbHNvIHNldHMgYWNjZXNzaWJpbHR5IGxhYmVscyxcbiAgICAgICAgICogYnV0IHRoZSBhY2Nlc3NpYmxlIGxhYmVsIGlzIG92ZXJyaWRlbiBieSBgYXJpYS1sYWJlbGAuXG4gICAgICAgICAqXG4gICAgICAgICAqIExlYXJuIG1vcmUgYWJvdXQgZmxvYXRpbmcgbGFiZWxzIGZyb20gdGhlIE1hdGVyaWFsIERlc2lnbiBndWlkZWxpbmVzOlxuICAgICAgICAgKiBodHRwczovL20zLm1hdGVyaWFsLmlvL2NvbXBvbmVudHMvdGV4dC1maWVsZHMvZ3VpZGVsaW5lc1xuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5sYWJlbCA9ICcnO1xuICAgICAgICAvKipcbiAgICAgICAgICogRGlzYWJsZXMgdGhlIGFzdGVyaXNrIG9uIHRoZSBmbG9hdGluZyBsYWJlbCwgd2hlbiB0aGUgdGV4dCBmaWVsZCBpc1xuICAgICAgICAgKiByZXF1aXJlZC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMubm9Bc3RlcmlzayA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogSW5kaWNhdGVzIHRoYXQgdGhlIHVzZXIgbXVzdCBzcGVjaWZ5IGEgdmFsdWUgZm9yIHRoZSBpbnB1dCBiZWZvcmUgdGhlXG4gICAgICAgICAqIG93bmluZyBmb3JtIGNhbiBiZSBzdWJtaXR0ZWQgYW5kIHdpbGwgcmVuZGVyIGFuIGVycm9yIHN0YXRlIHdoZW5cbiAgICAgICAgICogYHJlcG9ydFZhbGlkaXR5KClgIGlzIGludm9rZWQgd2hlbiB2YWx1ZSBpcyBlbXB0eS4gQWRkaXRpb25hbGx5IHRoZVxuICAgICAgICAgKiBmbG9hdGluZyBsYWJlbCB3aWxsIHJlbmRlciBhbiBhc3RlcmlzayBgXCIqXCJgIHdoZW4gdHJ1ZS5cbiAgICAgICAgICpcbiAgICAgICAgICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRNTC9BdHRyaWJ1dGVzL3JlcXVpcmVkXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnJlcXVpcmVkID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgdGV4dCBmaWVsZC4gSXQgaXMgYWx3YXlzIGEgc3RyaW5nLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy52YWx1ZSA9ICcnO1xuICAgICAgICAvKipcbiAgICAgICAgICogQW4gb3B0aW9uYWwgcHJlZml4IHRvIGRpc3BsYXkgYmVmb3JlIHRoZSBpbnB1dCB2YWx1ZS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMucHJlZml4VGV4dCA9ICcnO1xuICAgICAgICAvKipcbiAgICAgICAgICogQW4gb3B0aW9uYWwgc3VmZml4IHRvIGRpc3BsYXkgYWZ0ZXIgdGhlIGlucHV0IHZhbHVlLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5zdWZmaXhUZXh0ID0gJyc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXaGV0aGVyIG9yIG5vdCB0aGUgdGV4dCBmaWVsZCBoYXMgYSBsZWFkaW5nIGljb24uIFVzZWQgZm9yIFNTUi5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaGFzTGVhZGluZ0ljb24gPSBmYWxzZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdoZXRoZXIgb3Igbm90IHRoZSB0ZXh0IGZpZWxkIGhhcyBhIHRyYWlsaW5nIGljb24uIFVzZWQgZm9yIFNTUi5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaGFzVHJhaWxpbmdJY29uID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb252ZXlzIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gYmVsb3cgdGhlIHRleHQgZmllbGQsIHN1Y2ggYXMgaG93IGl0IHNob3VsZFxuICAgICAgICAgKiBiZSB1c2VkLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5zdXBwb3J0aW5nVGV4dCA9ICcnO1xuICAgICAgICAvKipcbiAgICAgICAgICogT3ZlcnJpZGUgdGhlIGlucHV0IHRleHQgQ1NTIGBkaXJlY3Rpb25gLiBVc2VmdWwgZm9yIFJUTCBsYW5ndWFnZXMgdGhhdCB1c2VcbiAgICAgICAgICogTFRSIG5vdGF0aW9uIGZvciBmcmFjdGlvbnMuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnRleHREaXJlY3Rpb24gPSAnJztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRoZSBudW1iZXIgb2Ygcm93cyB0byBkaXNwbGF5IGZvciBhIGB0eXBlPVwidGV4dGFyZWFcImAgdGV4dCBmaWVsZC5cbiAgICAgICAgICogRGVmYXVsdHMgdG8gMi5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMucm93cyA9IDI7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgbnVtYmVyIG9mIGNvbHMgdG8gZGlzcGxheSBmb3IgYSBgdHlwZT1cInRleHRhcmVhXCJgIHRleHQgZmllbGQuXG4gICAgICAgICAqIERlZmF1bHRzIHRvIDIwLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5jb2xzID0gMjA7XG4gICAgICAgIC8vIDxpbnB1dD4gcHJvcGVydGllc1xuICAgICAgICB0aGlzLmlucHV0TW9kZSA9ICcnO1xuICAgICAgICAvKipcbiAgICAgICAgICogRGVmaW5lcyB0aGUgZ3JlYXRlc3QgdmFsdWUgaW4gdGhlIHJhbmdlIG9mIHBlcm1pdHRlZCB2YWx1ZXMuXG4gICAgICAgICAqXG4gICAgICAgICAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0hUTUwvRWxlbWVudC9pbnB1dCNtYXhcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMubWF4ID0gJyc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgbWF4aW11bSBudW1iZXIgb2YgY2hhcmFjdGVycyBhIHVzZXIgY2FuIGVudGVyIGludG8gdGhlIHRleHQgZmllbGQuIFNldFxuICAgICAgICAgKiB0byAtMSBmb3Igbm9uZS5cbiAgICAgICAgICpcbiAgICAgICAgICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRNTC9FbGVtZW50L2lucHV0I21heGxlbmd0aFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5tYXhMZW5ndGggPSAtMTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlZmluZXMgdGhlIG1vc3QgbmVnYXRpdmUgdmFsdWUgaW4gdGhlIHJhbmdlIG9mIHBlcm1pdHRlZCB2YWx1ZXMuXG4gICAgICAgICAqXG4gICAgICAgICAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0hUTUwvRWxlbWVudC9pbnB1dCNtaW5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMubWluID0gJyc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGUgbWluaW11bSBudW1iZXIgb2YgY2hhcmFjdGVycyBhIHVzZXIgY2FuIGVudGVyIGludG8gdGhlIHRleHQgZmllbGQuIFNldFxuICAgICAgICAgKiB0byAtMSBmb3Igbm9uZS5cbiAgICAgICAgICpcbiAgICAgICAgICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRNTC9FbGVtZW50L2lucHV0I21pbmxlbmd0aFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5taW5MZW5ndGggPSAtMTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdoZW4gdHJ1ZSwgaGlkZSB0aGUgc3Bpbm5lciBmb3IgYHR5cGU9XCJudW1iZXJcImAgdGV4dCBmaWVsZHMuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLm5vU3Bpbm5lciA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogQSByZWd1bGFyIGV4cHJlc3Npb24gdGhhdCB0aGUgdGV4dCBmaWVsZCdzIHZhbHVlIG11c3QgbWF0Y2ggdG8gcGFzc1xuICAgICAgICAgKiBjb25zdHJhaW50IHZhbGlkYXRpb24uXG4gICAgICAgICAqXG4gICAgICAgICAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0hUTUwvRWxlbWVudC9pbnB1dCNwYXR0ZXJuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnBhdHRlcm4gPSAnJztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlZmluZXMgdGhlIHRleHQgZGlzcGxheWVkIGluIHRoZSB0ZXh0ZmllbGQgd2hlbiBpdCBoYXMgbm8gdmFsdWUuIFByb3ZpZGVzXG4gICAgICAgICAqIGEgYnJpZWYgaGludCB0byB0aGUgdXNlciBhcyB0byB0aGUgZXhwZWN0ZWQgdHlwZSBvZiBkYXRhIHRoYXQgc2hvdWxkIGJlXG4gICAgICAgICAqIGVudGVyZWQgaW50byB0aGUgY29udHJvbC4gVW5saWtlIGBsYWJlbGAsIHRoZSBwbGFjZWhvbGRlciBpcyBub3QgdmlzaWJsZVxuICAgICAgICAgKiBhbmQgZG9lcyBub3QgZmxvYXQgd2hlbiB0aGUgdGV4dGZpZWxkIGhhcyBhIHZhbHVlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVE1ML0F0dHJpYnV0ZXMvcGxhY2Vob2xkZXJcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMucGxhY2Vob2xkZXIgPSAnJztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEluZGljYXRlcyB3aGV0aGVyIG9yIG5vdCBhIHVzZXIgc2hvdWxkIGJlIGFibGUgdG8gZWRpdCB0aGUgdGV4dCBmaWVsZCdzXG4gICAgICAgICAqIHZhbHVlLlxuICAgICAgICAgKlxuICAgICAgICAgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVE1ML0VsZW1lbnQvaW5wdXQjcmVhZG9ubHlcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMucmVhZE9ubHkgPSBmYWxzZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEluZGljYXRlcyB0aGF0IGlucHV0IGFjY2VwdHMgbXVsdGlwbGUgZW1haWwgYWRkcmVzc2VzLlxuICAgICAgICAgKlxuICAgICAgICAgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVE1ML0VsZW1lbnQvaW5wdXQvZW1haWwjbXVsdGlwbGVcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMubXVsdGlwbGUgPSBmYWxzZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgb3Igc2V0cyB0aGUgZWxlbWVudCdzIHN0ZXAgYXR0cmlidXRlLCB3aGljaCB3b3JrcyB3aXRoIG1pbiBhbmQgbWF4XG4gICAgICAgICAqIHRvIGxpbWl0IHRoZSBpbmNyZW1lbnRzIGF0IHdoaWNoIGEgbnVtZXJpYyBvciBkYXRlLXRpbWUgdmFsdWUgY2FuIGJlIHNldC5cbiAgICAgICAgICpcbiAgICAgICAgICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRNTC9FbGVtZW50L2lucHV0I3N0ZXBcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuc3RlcCA9ICcnO1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIGA8aW5wdXQ+YCB0eXBlIHRvIHVzZSwgZGVmYXVsdHMgdG8gXCJ0ZXh0XCIuIFRoZSB0eXBlIGdyZWF0bHkgY2hhbmdlcyBob3dcbiAgICAgICAgICogdGhlIHRleHQgZmllbGQgYmVoYXZlcy5cbiAgICAgICAgICpcbiAgICAgICAgICogVGV4dCBmaWVsZHMgc3VwcG9ydCBhIGxpbWl0ZWQgbnVtYmVyIG9mIGA8aW5wdXQ+YCB0eXBlczpcbiAgICAgICAgICpcbiAgICAgICAgICogLSB0ZXh0XG4gICAgICAgICAqIC0gdGV4dGFyZWFcbiAgICAgICAgICogLSBlbWFpbFxuICAgICAgICAgKiAtIG51bWJlclxuICAgICAgICAgKiAtIHBhc3N3b3JkXG4gICAgICAgICAqIC0gc2VhcmNoXG4gICAgICAgICAqIC0gdGVsXG4gICAgICAgICAqIC0gdXJsXG4gICAgICAgICAqXG4gICAgICAgICAqIFNlZVxuICAgICAgICAgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVE1ML0VsZW1lbnQvaW5wdXQjaW5wdXRfdHlwZXNcbiAgICAgICAgICogZm9yIG1vcmUgZGV0YWlscyBvbiBlYWNoIGlucHV0IHR5cGUuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnR5cGUgPSAndGV4dCc7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZXNjcmliZXMgd2hhdCwgaWYgYW55LCB0eXBlIG9mIGF1dG9jb21wbGV0ZSBmdW5jdGlvbmFsaXR5IHRoZSBpbnB1dFxuICAgICAgICAgKiBzaG91bGQgcHJvdmlkZS5cbiAgICAgICAgICpcbiAgICAgICAgICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRNTC9BdHRyaWJ1dGVzL2F1dG9jb21wbGV0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5hdXRvY29tcGxldGUgPSAnJztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHVybnMgdHJ1ZSB3aGVuIHRoZSB0ZXh0IGZpZWxkIGhhcyBiZWVuIGludGVyYWN0ZWQgd2l0aC4gTmF0aXZlXG4gICAgICAgICAqIHZhbGlkYXRpb24gZXJyb3JzIG9ubHkgZGlzcGxheSBpbiByZXNwb25zZSB0byB1c2VyIGludGVyYWN0aW9ucy5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZGlydHkgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5mb2N1c2VkID0gZmFsc2U7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXaGV0aGVyIG9yIG5vdCBhIG5hdGl2ZSBlcnJvciBoYXMgYmVlbiByZXBvcnRlZCB2aWEgYHJlcG9ydFZhbGlkaXR5KClgLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5uYXRpdmVFcnJvciA9IGZhbHNlO1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhlIHZhbGlkYXRpb24gbWVzc2FnZSBkaXNwbGF5ZWQgZnJvbSBhIG5hdGl2ZSBlcnJvciB2aWFcbiAgICAgICAgICogYHJlcG9ydFZhbGlkaXR5KClgLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5uYXRpdmVFcnJvclRleHQgPSAnJztcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0cyBvciBzZXRzIHRoZSBkaXJlY3Rpb24gaW4gd2hpY2ggc2VsZWN0aW9uIG9jY3VycmVkLlxuICAgICAqL1xuICAgIGdldCBzZWxlY3Rpb25EaXJlY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldElucHV0T3JUZXh0YXJlYSgpLnNlbGVjdGlvbkRpcmVjdGlvbjtcbiAgICB9XG4gICAgc2V0IHNlbGVjdGlvbkRpcmVjdGlvbih2YWx1ZSkge1xuICAgICAgICB0aGlzLmdldElucHV0T3JUZXh0YXJlYSgpLnNlbGVjdGlvbkRpcmVjdGlvbiA9IHZhbHVlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXRzIG9yIHNldHMgdGhlIGVuZCBwb3NpdGlvbiBvciBvZmZzZXQgb2YgYSB0ZXh0IHNlbGVjdGlvbi5cbiAgICAgKi9cbiAgICBnZXQgc2VsZWN0aW9uRW5kKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRJbnB1dE9yVGV4dGFyZWEoKS5zZWxlY3Rpb25FbmQ7XG4gICAgfVxuICAgIHNldCBzZWxlY3Rpb25FbmQodmFsdWUpIHtcbiAgICAgICAgdGhpcy5nZXRJbnB1dE9yVGV4dGFyZWEoKS5zZWxlY3Rpb25FbmQgPSB2YWx1ZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0cyBvciBzZXRzIHRoZSBzdGFydGluZyBwb3NpdGlvbiBvciBvZmZzZXQgb2YgYSB0ZXh0IHNlbGVjdGlvbi5cbiAgICAgKi9cbiAgICBnZXQgc2VsZWN0aW9uU3RhcnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldElucHV0T3JUZXh0YXJlYSgpLnNlbGVjdGlvblN0YXJ0O1xuICAgIH1cbiAgICBzZXQgc2VsZWN0aW9uU3RhcnQodmFsdWUpIHtcbiAgICAgICAgdGhpcy5nZXRJbnB1dE9yVGV4dGFyZWEoKS5zZWxlY3Rpb25TdGFydCA9IHZhbHVlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBUaGUgdGV4dCBmaWVsZCdzIHZhbHVlIGFzIGEgbnVtYmVyLlxuICAgICAqL1xuICAgIGdldCB2YWx1ZUFzTnVtYmVyKCkge1xuICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuZ2V0SW5wdXQoKTtcbiAgICAgICAgaWYgKCFpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaW5wdXQudmFsdWVBc051bWJlcjtcbiAgICB9XG4gICAgc2V0IHZhbHVlQXNOdW1iZXIodmFsdWUpIHtcbiAgICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLmdldElucHV0KCk7XG4gICAgICAgIGlmICghaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpbnB1dC52YWx1ZUFzTnVtYmVyID0gdmFsdWU7XG4gICAgICAgIHRoaXMudmFsdWUgPSBpbnB1dC52YWx1ZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhlIHRleHQgZmllbGQncyB2YWx1ZSBhcyBhIERhdGUuXG4gICAgICovXG4gICAgZ2V0IHZhbHVlQXNEYXRlKCkge1xuICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuZ2V0SW5wdXQoKTtcbiAgICAgICAgaWYgKCFpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlucHV0LnZhbHVlQXNEYXRlO1xuICAgIH1cbiAgICBzZXQgdmFsdWVBc0RhdGUodmFsdWUpIHtcbiAgICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLmdldElucHV0KCk7XG4gICAgICAgIGlmICghaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpbnB1dC52YWx1ZUFzRGF0ZSA9IHZhbHVlO1xuICAgICAgICB0aGlzLnZhbHVlID0gaW5wdXQudmFsdWU7XG4gICAgfVxuICAgIGdldCBoYXNFcnJvcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZXJyb3IgfHwgdGhpcy5uYXRpdmVFcnJvcjtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2VsZWN0cyBhbGwgdGhlIHRleHQgaW4gdGhlIHRleHQgZmllbGQuXG4gICAgICpcbiAgICAgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvSFRNTElucHV0RWxlbWVudC9zZWxlY3RcbiAgICAgKi9cbiAgICBzZWxlY3QoKSB7XG4gICAgICAgIHRoaXMuZ2V0SW5wdXRPclRleHRhcmVhKCkuc2VsZWN0KCk7XG4gICAgfVxuICAgIHNldFJhbmdlVGV4dCguLi5hcmdzKSB7XG4gICAgICAgIC8vIENhbGxpbmcgc2V0UmFuZ2VUZXh0IHdpdGggMSB2cyAzLTQgYXJndW1lbnRzIGhhcyBkaWZmZXJlbnQgYmVoYXZpb3IuXG4gICAgICAgIC8vIFVzZSBzcHJlYWQgc3ludGF4IGFuZCB0eXBlIGNhc3RpbmcgdG8gZW5zdXJlIGNvcnJlY3QgdXNhZ2UuXG4gICAgICAgIHRoaXMuZ2V0SW5wdXRPclRleHRhcmVhKCkuc2V0UmFuZ2VUZXh0KC4uLmFyZ3MpO1xuICAgICAgICB0aGlzLnZhbHVlID0gdGhpcy5nZXRJbnB1dE9yVGV4dGFyZWEoKS52YWx1ZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc3RhcnQgYW5kIGVuZCBwb3NpdGlvbnMgb2YgYSBzZWxlY3Rpb24gaW4gdGhlIHRleHQgZmllbGQuXG4gICAgICpcbiAgICAgKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvSFRNTElucHV0RWxlbWVudC9zZXRTZWxlY3Rpb25SYW5nZVxuICAgICAqXG4gICAgICogQHBhcmFtIHN0YXJ0IFRoZSBvZmZzZXQgaW50byB0aGUgdGV4dCBmaWVsZCBmb3IgdGhlIHN0YXJ0IG9mIHRoZSBzZWxlY3Rpb24uXG4gICAgICogQHBhcmFtIGVuZCBUaGUgb2Zmc2V0IGludG8gdGhlIHRleHQgZmllbGQgZm9yIHRoZSBlbmQgb2YgdGhlIHNlbGVjdGlvbi5cbiAgICAgKiBAcGFyYW0gZGlyZWN0aW9uIFRoZSBkaXJlY3Rpb24gaW4gd2hpY2ggdGhlIHNlbGVjdGlvbiBpcyBwZXJmb3JtZWQuXG4gICAgICovXG4gICAgc2V0U2VsZWN0aW9uUmFuZ2Uoc3RhcnQsIGVuZCwgZGlyZWN0aW9uKSB7XG4gICAgICAgIHRoaXMuZ2V0SW5wdXRPclRleHRhcmVhKCkuc2V0U2VsZWN0aW9uUmFuZ2Uoc3RhcnQsIGVuZCwgZGlyZWN0aW9uKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2hvd3MgdGhlIGJyb3dzZXIgcGlja2VyIGZvciBhbiBpbnB1dCBlbGVtZW50IG9mIHR5cGUgXCJkYXRlXCIsIFwidGltZVwiLCBldGMuXG4gICAgICpcbiAgICAgKiBGb3IgYSBmdWxsIGxpc3Qgb2Ygc3VwcG9ydGVkIHR5cGVzLCBzZWU6XG4gICAgICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0hUTUxJbnB1dEVsZW1lbnQvc2hvd1BpY2tlciNicm93c2VyX2NvbXBhdGliaWxpdHlcbiAgICAgKlxuICAgICAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9IVE1MSW5wdXRFbGVtZW50L3Nob3dQaWNrZXJcbiAgICAgKi9cbiAgICBzaG93UGlja2VyKCkge1xuICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuZ2V0SW5wdXQoKTtcbiAgICAgICAgaWYgKCFpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlucHV0LnNob3dQaWNrZXIoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRGVjcmVtZW50cyB0aGUgdmFsdWUgb2YgYSBudW1lcmljIHR5cGUgdGV4dCBmaWVsZCBieSBgc3RlcGAgb3IgYG5gIGBzdGVwYFxuICAgICAqIG51bWJlciBvZiB0aW1lcy5cbiAgICAgKlxuICAgICAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9IVE1MSW5wdXRFbGVtZW50L3N0ZXBEb3duXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc3RlcERlY3JlbWVudCBUaGUgbnVtYmVyIG9mIHN0ZXBzIHRvIGRlY3JlbWVudCwgZGVmYXVsdHMgdG8gMS5cbiAgICAgKi9cbiAgICBzdGVwRG93bihzdGVwRGVjcmVtZW50KSB7XG4gICAgICAgIGNvbnN0IGlucHV0ID0gdGhpcy5nZXRJbnB1dCgpO1xuICAgICAgICBpZiAoIWlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaW5wdXQuc3RlcERvd24oc3RlcERlY3JlbWVudCk7XG4gICAgICAgIHRoaXMudmFsdWUgPSBpbnB1dC52YWx1ZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSW5jcmVtZW50cyB0aGUgdmFsdWUgb2YgYSBudW1lcmljIHR5cGUgdGV4dCBmaWVsZCBieSBgc3RlcGAgb3IgYG5gIGBzdGVwYFxuICAgICAqIG51bWJlciBvZiB0aW1lcy5cbiAgICAgKlxuICAgICAqIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9IVE1MSW5wdXRFbGVtZW50L3N0ZXBVcFxuICAgICAqXG4gICAgICogQHBhcmFtIHN0ZXBJbmNyZW1lbnQgVGhlIG51bWJlciBvZiBzdGVwcyB0byBpbmNyZW1lbnQsIGRlZmF1bHRzIHRvIDEuXG4gICAgICovXG4gICAgc3RlcFVwKHN0ZXBJbmNyZW1lbnQpIHtcbiAgICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLmdldElucHV0KCk7XG4gICAgICAgIGlmICghaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpbnB1dC5zdGVwVXAoc3RlcEluY3JlbWVudCk7XG4gICAgICAgIHRoaXMudmFsdWUgPSBpbnB1dC52YWx1ZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVzZXQgdGhlIHRleHQgZmllbGQgdG8gaXRzIGRlZmF1bHQgdmFsdWUuXG4gICAgICovXG4gICAgcmVzZXQoKSB7XG4gICAgICAgIHRoaXMuZGlydHkgPSBmYWxzZTtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHRoaXMuZ2V0QXR0cmlidXRlKCd2YWx1ZScpID8/ICcnO1xuICAgICAgICB0aGlzLm5hdGl2ZUVycm9yID0gZmFsc2U7XG4gICAgICAgIHRoaXMubmF0aXZlRXJyb3JUZXh0ID0gJyc7XG4gICAgfVxuICAgIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhhdHRyaWJ1dGUsIG5ld1ZhbHVlLCBvbGRWYWx1ZSkge1xuICAgICAgICBpZiAoYXR0cmlidXRlID09PSAndmFsdWUnICYmIHRoaXMuZGlydHkpIHtcbiAgICAgICAgICAgIC8vIEFmdGVyIHVzZXIgaW5wdXQsIGNoYW5naW5nIHRoZSB2YWx1ZSBhdHRyaWJ1dGUgbm8gbG9uZ2VyIHVwZGF0ZXMgdGhlXG4gICAgICAgICAgICAvLyB0ZXh0IGZpZWxkJ3MgdmFsdWUgKHVudGlsIHJlc2V0KS4gVGhpcyBtYXRjaGVzIG5hdGl2ZSA8aW5wdXQ+IGJlaGF2aW9yLlxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN1cGVyLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhhdHRyaWJ1dGUsIG5ld1ZhbHVlLCBvbGRWYWx1ZSk7XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgY29uc3QgY2xhc3NlcyA9IHtcbiAgICAgICAgICAgICdkaXNhYmxlZCc6IHRoaXMuZGlzYWJsZWQsXG4gICAgICAgICAgICAnZXJyb3InOiAhdGhpcy5kaXNhYmxlZCAmJiB0aGlzLmhhc0Vycm9yLFxuICAgICAgICAgICAgJ3RleHRhcmVhJzogdGhpcy50eXBlID09PSAndGV4dGFyZWEnLFxuICAgICAgICAgICAgJ25vLXNwaW5uZXInOiB0aGlzLm5vU3Bpbm5lcixcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIGh0bWwgYFxuICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LWZpZWxkICR7Y2xhc3NNYXAoY2xhc3Nlcyl9XCI+XG4gICAgICAgICR7dGhpcy5yZW5kZXJGaWVsZCgpfVxuICAgICAgPC9zcGFuPlxuICAgIGA7XG4gICAgfVxuICAgIHVwZGF0ZWQoY2hhbmdlZFByb3BlcnRpZXMpIHtcbiAgICAgICAgLy8gS2VlcCBjaGFuZ2VkUHJvcGVydGllcyBhcmcgc28gdGhhdCBzdWJjbGFzc2VzIG1heSBjYWxsIGl0XG4gICAgICAgIC8vIElmIGEgcHJvcGVydHkgc3VjaCBhcyBgdHlwZWAgY2hhbmdlcyBhbmQgY2F1c2VzIHRoZSBpbnRlcm5hbCA8aW5wdXQ+XG4gICAgICAgIC8vIHZhbHVlIHRvIGNoYW5nZSB3aXRob3V0IGRpc3BhdGNoaW5nIGFuIGV2ZW50LCByZS1zeW5jIGl0LlxuICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMuZ2V0SW5wdXRPclRleHRhcmVhKCkudmFsdWU7XG4gICAgICAgIGlmICh0aGlzLnZhbHVlICE9PSB2YWx1ZSkge1xuICAgICAgICAgICAgLy8gTm90ZSB0aGlzIGlzIHR5cGljYWxseSBpbmVmZmljaWVudCBpbiB1cGRhdGVkKCkgc2luY2UgaXQgc2NoZWR1bGVzXG4gICAgICAgICAgICAvLyBhbm90aGVyIHVwZGF0ZS4gSG93ZXZlciwgaXQgaXMgbmVlZGVkIGZvciB0aGUgPGlucHV0PiB0byBmdWxseSByZW5kZXJcbiAgICAgICAgICAgIC8vIGJlZm9yZSBjaGVja2luZyBpdHMgdmFsdWUuXG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmVuZGVyRmllbGQoKSB7XG4gICAgICAgIHJldHVybiBzdGF0aWNIdG1sIGA8JHt0aGlzLmZpZWxkVGFnfVxuICAgICAgY2xhc3M9XCJmaWVsZFwiXG4gICAgICBjb3VudD0ke3RoaXMudmFsdWUubGVuZ3RofVxuICAgICAgP2Rpc2FibGVkPSR7dGhpcy5kaXNhYmxlZH1cbiAgICAgID9lcnJvcj0ke3RoaXMuaGFzRXJyb3J9XG4gICAgICBlcnJvci10ZXh0PSR7dGhpcy5nZXRFcnJvclRleHQoKX1cbiAgICAgID9mb2N1c2VkPSR7dGhpcy5mb2N1c2VkfVxuICAgICAgP2hhcy1lbmQ9JHt0aGlzLmhhc1RyYWlsaW5nSWNvbn1cbiAgICAgID9oYXMtc3RhcnQ9JHt0aGlzLmhhc0xlYWRpbmdJY29ufVxuICAgICAgbGFiZWw9JHt0aGlzLmxhYmVsfVxuICAgICAgP25vLWFzdGVyaXNrPSR7dGhpcy5ub0FzdGVyaXNrfVxuICAgICAgbWF4PSR7dGhpcy5tYXhMZW5ndGh9XG4gICAgICA/cG9wdWxhdGVkPSR7ISF0aGlzLnZhbHVlfVxuICAgICAgP3JlcXVpcmVkPSR7dGhpcy5yZXF1aXJlZH1cbiAgICAgID9yZXNpemFibGU9JHt0aGlzLnR5cGUgPT09ICd0ZXh0YXJlYSd9XG4gICAgICBzdXBwb3J0aW5nLXRleHQ9JHt0aGlzLnN1cHBvcnRpbmdUZXh0fVxuICAgID5cbiAgICAgICR7dGhpcy5yZW5kZXJMZWFkaW5nSWNvbigpfVxuICAgICAgJHt0aGlzLnJlbmRlcklucHV0T3JUZXh0YXJlYSgpfVxuICAgICAgJHt0aGlzLnJlbmRlclRyYWlsaW5nSWNvbigpfVxuICAgICAgPGRpdiBpZD1cImRlc2NyaXB0aW9uXCIgc2xvdD1cImFyaWEtZGVzY3JpYmVkYnlcIj48L2Rpdj5cbiAgICAgIDxzbG90IG5hbWU9XCJjb250YWluZXJcIiBzbG90PVwiY29udGFpbmVyXCI+PC9zbG90PlxuICAgIDwvJHt0aGlzLmZpZWxkVGFnfT5gO1xuICAgIH1cbiAgICByZW5kZXJMZWFkaW5nSWNvbigpIHtcbiAgICAgICAgcmV0dXJuIGh0bWwgYFxuICAgICAgPHNwYW4gY2xhc3M9XCJpY29uIGxlYWRpbmdcIiBzbG90PVwic3RhcnRcIj5cbiAgICAgICAgPHNsb3QgbmFtZT1cImxlYWRpbmctaWNvblwiIEBzbG90Y2hhbmdlPSR7dGhpcy5oYW5kbGVJY29uQ2hhbmdlfT48L3Nsb3Q+XG4gICAgICA8L3NwYW4+XG4gICAgYDtcbiAgICB9XG4gICAgcmVuZGVyVHJhaWxpbmdJY29uKCkge1xuICAgICAgICByZXR1cm4gaHRtbCBgXG4gICAgICA8c3BhbiBjbGFzcz1cImljb24gdHJhaWxpbmdcIiBzbG90PVwiZW5kXCI+XG4gICAgICAgIDxzbG90IG5hbWU9XCJ0cmFpbGluZy1pY29uXCIgQHNsb3RjaGFuZ2U9JHt0aGlzLmhhbmRsZUljb25DaGFuZ2V9Pjwvc2xvdD5cbiAgICAgIDwvc3Bhbj5cbiAgICBgO1xuICAgIH1cbiAgICByZW5kZXJJbnB1dE9yVGV4dGFyZWEoKSB7XG4gICAgICAgIGNvbnN0IHN0eWxlID0geyAnZGlyZWN0aW9uJzogdGhpcy50ZXh0RGlyZWN0aW9uIH07XG4gICAgICAgIGNvbnN0IGFyaWFMYWJlbCA9IHRoaXMuYXJpYUxhYmVsIHx8IHRoaXMubGFiZWwgfHwgbm90aGluZztcbiAgICAgICAgLy8gbGl0LWFuYXlsemVyIGBhdXRvY29tcGxldGVgIHR5cGVzIGFyZSB0b28gc3RyaWN0XG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgICAgICAgY29uc3QgYXV0b2NvbXBsZXRlID0gdGhpcy5hdXRvY29tcGxldGU7XG4gICAgICAgIC8vIFRoZXNlIHByb3BlcnRpZXMgbWF5IGJlIHNldCB0byBudWxsIGlmIHRoZSBhdHRyaWJ1dGUgaXMgcmVtb3ZlZCwgYW5kXG4gICAgICAgIC8vIGBudWxsID4gLTFgIGlzIGluY29ycmVjdGx5IGB0cnVlYC5cbiAgICAgICAgY29uc3QgaGFzTWF4TGVuZ3RoID0gKHRoaXMubWF4TGVuZ3RoID8/IC0xKSA+IC0xO1xuICAgICAgICBjb25zdCBoYXNNaW5MZW5ndGggPSAodGhpcy5taW5MZW5ndGggPz8gLTEpID4gLTE7XG4gICAgICAgIGlmICh0aGlzLnR5cGUgPT09ICd0ZXh0YXJlYScpIHtcbiAgICAgICAgICAgIHJldHVybiBodG1sIGBcbiAgICAgICAgPHRleHRhcmVhXG4gICAgICAgICAgY2xhc3M9XCJpbnB1dFwiXG4gICAgICAgICAgc3R5bGU9JHtzdHlsZU1hcChzdHlsZSl9XG4gICAgICAgICAgYXJpYS1kZXNjcmliZWRieT1cImRlc2NyaXB0aW9uXCJcbiAgICAgICAgICBhcmlhLWludmFsaWQ9JHt0aGlzLmhhc0Vycm9yfVxuICAgICAgICAgIGFyaWEtbGFiZWw9JHthcmlhTGFiZWx9XG4gICAgICAgICAgYXV0b2NvbXBsZXRlPSR7YXV0b2NvbXBsZXRlIHx8IG5vdGhpbmd9XG4gICAgICAgICAgbmFtZT0ke3RoaXMubmFtZSB8fCBub3RoaW5nfVxuICAgICAgICAgID9kaXNhYmxlZD0ke3RoaXMuZGlzYWJsZWR9XG4gICAgICAgICAgbWF4bGVuZ3RoPSR7aGFzTWF4TGVuZ3RoID8gdGhpcy5tYXhMZW5ndGggOiBub3RoaW5nfVxuICAgICAgICAgIG1pbmxlbmd0aD0ke2hhc01pbkxlbmd0aCA/IHRoaXMubWluTGVuZ3RoIDogbm90aGluZ31cbiAgICAgICAgICBwbGFjZWhvbGRlcj0ke3RoaXMucGxhY2Vob2xkZXIgfHwgbm90aGluZ31cbiAgICAgICAgICA/cmVhZG9ubHk9JHt0aGlzLnJlYWRPbmx5fVxuICAgICAgICAgID9yZXF1aXJlZD0ke3RoaXMucmVxdWlyZWR9XG4gICAgICAgICAgcm93cz0ke3RoaXMucm93c31cbiAgICAgICAgICBjb2xzPSR7dGhpcy5jb2xzfVxuICAgICAgICAgIC52YWx1ZT0ke2xpdmUodGhpcy52YWx1ZSl9XG4gICAgICAgICAgQGNoYW5nZT0ke3RoaXMucmVkaXNwYXRjaEV2ZW50fVxuICAgICAgICAgIEBmb2N1cz0ke3RoaXMuaGFuZGxlRm9jdXNDaGFuZ2V9XG4gICAgICAgICAgQGJsdXI9JHt0aGlzLmhhbmRsZUZvY3VzQ2hhbmdlfVxuICAgICAgICAgIEBpbnB1dD0ke3RoaXMuaGFuZGxlSW5wdXR9XG4gICAgICAgICAgQHNlbGVjdD0ke3RoaXMucmVkaXNwYXRjaEV2ZW50fT48L3RleHRhcmVhPlxuICAgICAgYDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBwcmVmaXggPSB0aGlzLnJlbmRlclByZWZpeCgpO1xuICAgICAgICBjb25zdCBzdWZmaXggPSB0aGlzLnJlbmRlclN1ZmZpeCgpO1xuICAgICAgICAvLyBUT0RPKGIvMjQzODA1ODQ4KTogcmVtb3ZlIGBhcyB1bmtub3duIGFzIG51bWJlcmAgYW5kIGBhcyBhbnlgIG9uY2UgbGl0XG4gICAgICAgIC8vIGFuYWx5emVyIGlzIGZpeGVkXG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgICAgICAgY29uc3QgaW5wdXRNb2RlID0gdGhpcy5pbnB1dE1vZGU7XG4gICAgICAgIHJldHVybiBodG1sIGBcbiAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC13cmFwcGVyXCI+XG4gICAgICAgICR7cHJlZml4fVxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjbGFzcz1cImlucHV0XCJcbiAgICAgICAgICBzdHlsZT0ke3N0eWxlTWFwKHN0eWxlKX1cbiAgICAgICAgICBhcmlhLWRlc2NyaWJlZGJ5PVwiZGVzY3JpcHRpb25cIlxuICAgICAgICAgIGFyaWEtaW52YWxpZD0ke3RoaXMuaGFzRXJyb3J9XG4gICAgICAgICAgYXJpYS1sYWJlbD0ke2FyaWFMYWJlbH1cbiAgICAgICAgICBhdXRvY29tcGxldGU9JHthdXRvY29tcGxldGUgfHwgbm90aGluZ31cbiAgICAgICAgICBuYW1lPSR7dGhpcy5uYW1lIHx8IG5vdGhpbmd9XG4gICAgICAgICAgP2Rpc2FibGVkPSR7dGhpcy5kaXNhYmxlZH1cbiAgICAgICAgICBpbnB1dG1vZGU9JHtpbnB1dE1vZGUgfHwgbm90aGluZ31cbiAgICAgICAgICBtYXg9JHsodGhpcy5tYXggfHwgbm90aGluZyl9XG4gICAgICAgICAgbWF4bGVuZ3RoPSR7aGFzTWF4TGVuZ3RoID8gdGhpcy5tYXhMZW5ndGggOiBub3RoaW5nfVxuICAgICAgICAgIG1pbj0keyh0aGlzLm1pbiB8fCBub3RoaW5nKX1cbiAgICAgICAgICBtaW5sZW5ndGg9JHtoYXNNaW5MZW5ndGggPyB0aGlzLm1pbkxlbmd0aCA6IG5vdGhpbmd9XG4gICAgICAgICAgcGF0dGVybj0ke3RoaXMucGF0dGVybiB8fCBub3RoaW5nfVxuICAgICAgICAgIHBsYWNlaG9sZGVyPSR7dGhpcy5wbGFjZWhvbGRlciB8fCBub3RoaW5nfVxuICAgICAgICAgID9yZWFkb25seT0ke3RoaXMucmVhZE9ubHl9XG4gICAgICAgICAgP3JlcXVpcmVkPSR7dGhpcy5yZXF1aXJlZH1cbiAgICAgICAgICA/bXVsdGlwbGU9JHt0aGlzLm11bHRpcGxlfVxuICAgICAgICAgIHN0ZXA9JHsodGhpcy5zdGVwIHx8IG5vdGhpbmcpfVxuICAgICAgICAgIHR5cGU9JHt0aGlzLnR5cGV9XG4gICAgICAgICAgLnZhbHVlPSR7bGl2ZSh0aGlzLnZhbHVlKX1cbiAgICAgICAgICBAY2hhbmdlPSR7dGhpcy5yZWRpc3BhdGNoRXZlbnR9XG4gICAgICAgICAgQGZvY3VzPSR7dGhpcy5oYW5kbGVGb2N1c0NoYW5nZX1cbiAgICAgICAgICBAYmx1cj0ke3RoaXMuaGFuZGxlRm9jdXNDaGFuZ2V9XG4gICAgICAgICAgQGlucHV0PSR7dGhpcy5oYW5kbGVJbnB1dH1cbiAgICAgICAgICBAc2VsZWN0PSR7dGhpcy5yZWRpc3BhdGNoRXZlbnR9IC8+XG4gICAgICAgICR7c3VmZml4fVxuICAgICAgPC9kaXY+XG4gICAgYDtcbiAgICB9XG4gICAgcmVuZGVyUHJlZml4KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZW5kZXJBZmZpeCh0aGlzLnByZWZpeFRleHQsIC8qIGlzU3VmZml4ICovIGZhbHNlKTtcbiAgICB9XG4gICAgcmVuZGVyU3VmZml4KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5yZW5kZXJBZmZpeCh0aGlzLnN1ZmZpeFRleHQsIC8qIGlzU3VmZml4ICovIHRydWUpO1xuICAgIH1cbiAgICByZW5kZXJBZmZpeCh0ZXh0LCBpc1N1ZmZpeCkge1xuICAgICAgICBpZiAoIXRleHQpIHtcbiAgICAgICAgICAgIHJldHVybiBub3RoaW5nO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNsYXNzZXMgPSB7XG4gICAgICAgICAgICAnc3VmZml4JzogaXNTdWZmaXgsXG4gICAgICAgICAgICAncHJlZml4JzogIWlzU3VmZml4LFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gaHRtbCBgPHNwYW4gY2xhc3M9XCIke2NsYXNzTWFwKGNsYXNzZXMpfVwiPiR7dGV4dH08L3NwYW4+YDtcbiAgICB9XG4gICAgZ2V0RXJyb3JUZXh0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5lcnJvciA/IHRoaXMuZXJyb3JUZXh0IDogdGhpcy5uYXRpdmVFcnJvclRleHQ7XG4gICAgfVxuICAgIGhhbmRsZUZvY3VzQ2hhbmdlKCkge1xuICAgICAgICAvLyBXaGVuIGNhbGxpbmcgZm9jdXMoKSBvciByZXBvcnRWYWxpZGl0eSgpIGR1cmluZyBjaGFuZ2UsIGl0J3MgcG9zc2libGVcbiAgICAgICAgLy8gZm9yIGJsdXIgdG8gYmUgY2FsbGVkIGFmdGVyIHRoZSBuZXcgZm9jdXMgZXZlbnQuIFJhdGhlciB0aGFuIHNldFxuICAgICAgICAvLyBgdGhpcy5mb2N1c2VkYCB0byB0cnVlL2ZhbHNlIG9uIGZvY3VzL2JsdXIsIHdlIGFsd2F5cyBzZXQgaXQgdG8gd2hldGhlclxuICAgICAgICAvLyBvciBub3QgdGhlIGlucHV0IGl0c2VsZiBpcyBmb2N1c2VkLlxuICAgICAgICB0aGlzLmZvY3VzZWQgPSB0aGlzLmlucHV0T3JUZXh0YXJlYT8ubWF0Y2hlcygnOmZvY3VzJykgPz8gZmFsc2U7XG4gICAgfVxuICAgIGhhbmRsZUlucHV0KGV2ZW50KSB7XG4gICAgICAgIHRoaXMuZGlydHkgPSB0cnVlO1xuICAgICAgICB0aGlzLnZhbHVlID0gZXZlbnQudGFyZ2V0LnZhbHVlO1xuICAgIH1cbiAgICByZWRpc3BhdGNoRXZlbnQoZXZlbnQpIHtcbiAgICAgICAgcmVkaXNwYXRjaEV2ZW50KHRoaXMsIGV2ZW50KTtcbiAgICB9XG4gICAgZ2V0SW5wdXRPclRleHRhcmVhKCkge1xuICAgICAgICBpZiAoIXRoaXMuaW5wdXRPclRleHRhcmVhKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgaW5wdXQgaXMgbm90IHlldCBkZWZpbmVkLCBzeW5jaHJvbm91c2x5IHJlbmRlci5cbiAgICAgICAgICAgIC8vIGUuZy5cbiAgICAgICAgICAgIC8vIGNvbnN0IHRleHRGaWVsZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ21kLW91dGxpbmVkLXRleHQtZmllbGQnKTtcbiAgICAgICAgICAgIC8vIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodGV4dEZpZWxkKTtcbiAgICAgICAgICAgIC8vIHRleHRGaWVsZC5mb2N1cygpOyAvLyBzeW5jaHJvbm91c2x5IHJlbmRlclxuICAgICAgICAgICAgdGhpcy5jb25uZWN0ZWRDYWxsYmFjaygpO1xuICAgICAgICAgICAgdGhpcy5zY2hlZHVsZVVwZGF0ZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLmlzVXBkYXRlUGVuZGluZykge1xuICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIHBlbmRpbmcgdXBkYXRlcywgc3luY2hyb25vdXNseSBwZXJmb3JtIHRoZW0uIFRoaXMgZW5zdXJlc1xuICAgICAgICAgICAgLy8gdGhhdCBjb25zdHJhaW50IHZhbGlkYXRpb24gcHJvcGVydGllcyAobGlrZSBgcmVxdWlyZWRgKSBhcmUgc3luY2VkXG4gICAgICAgICAgICAvLyBiZWZvcmUgaW50ZXJhY3Rpbmcgd2l0aCBpbnB1dCBBUElzIHRoYXQgZGVwZW5kIG9uIHRoZW0uXG4gICAgICAgICAgICB0aGlzLnNjaGVkdWxlVXBkYXRlKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuaW5wdXRPclRleHRhcmVhO1xuICAgIH1cbiAgICBnZXRJbnB1dCgpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZSA9PT0gJ3RleHRhcmVhJykge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SW5wdXRPclRleHRhcmVhKCk7XG4gICAgfVxuICAgIGhhbmRsZUljb25DaGFuZ2UoKSB7XG4gICAgICAgIHRoaXMuaGFzTGVhZGluZ0ljb24gPSB0aGlzLmxlYWRpbmdJY29ucy5sZW5ndGggPiAwO1xuICAgICAgICB0aGlzLmhhc1RyYWlsaW5nSWNvbiA9IHRoaXMudHJhaWxpbmdJY29ucy5sZW5ndGggPiAwO1xuICAgIH1cbiAgICBbZ2V0Rm9ybVZhbHVlXSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgfVxuICAgIGZvcm1SZXNldENhbGxiYWNrKCkge1xuICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgfVxuICAgIGZvcm1TdGF0ZVJlc3RvcmVDYWxsYmFjayhzdGF0ZSkge1xuICAgICAgICB0aGlzLnZhbHVlID0gc3RhdGU7XG4gICAgfVxuICAgIGZvY3VzKCkge1xuICAgICAgICAvLyBSZXF1aXJlZCBmb3IgdGhlIGNhc2UgdGhhdCB0aGUgdXNlciBzbG90cyBhIGZvY3VzYWJsZSBlbGVtZW50IGludG8gdGhlXG4gICAgICAgIC8vIGxlYWRpbmcgaWNvbiBzbG90IHN1Y2ggYXMgYW4gaWNvbmJ1dHRvbiBkdWUgdG8gaG93IGRlbGVnYXRlc0ZvY3VzIHdvcmtzLlxuICAgICAgICB0aGlzLmdldElucHV0T3JUZXh0YXJlYSgpLmZvY3VzKCk7XG4gICAgfVxuICAgIFtjcmVhdGVWYWxpZGF0b3JdKCkge1xuICAgICAgICByZXR1cm4gbmV3IFRleHRGaWVsZFZhbGlkYXRvcigoKSA9PiAoe1xuICAgICAgICAgICAgc3RhdGU6IHRoaXMsXG4gICAgICAgICAgICByZW5kZXJlZENvbnRyb2w6IHRoaXMuaW5wdXRPclRleHRhcmVhLFxuICAgICAgICB9KSk7XG4gICAgfVxuICAgIFtnZXRWYWxpZGl0eUFuY2hvcl0oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlucHV0T3JUZXh0YXJlYTtcbiAgICB9XG4gICAgW29uUmVwb3J0VmFsaWRpdHldKGludmFsaWRFdmVudCkge1xuICAgICAgICAvLyBQcmV2ZW50IGRlZmF1bHQgcG9wLXVwIGJlaGF2aW9yLlxuICAgICAgICBpbnZhbGlkRXZlbnQ/LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGNvbnN0IHByZXZNZXNzYWdlID0gdGhpcy5nZXRFcnJvclRleHQoKTtcbiAgICAgICAgdGhpcy5uYXRpdmVFcnJvciA9ICEhaW52YWxpZEV2ZW50O1xuICAgICAgICB0aGlzLm5hdGl2ZUVycm9yVGV4dCA9IHRoaXMudmFsaWRhdGlvbk1lc3NhZ2U7XG4gICAgICAgIGlmIChwcmV2TWVzc2FnZSA9PT0gdGhpcy5nZXRFcnJvclRleHQoKSkge1xuICAgICAgICAgICAgdGhpcy5maWVsZD8ucmVhbm5vdW5jZUVycm9yKCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4vKiogQG5vY29sbGFwc2UgKi9cblRleHRGaWVsZC5zaGFkb3dSb290T3B0aW9ucyA9IHtcbiAgICAuLi5MaXRFbGVtZW50LnNoYWRvd1Jvb3RPcHRpb25zLFxuICAgIGRlbGVnYXRlc0ZvY3VzOiB0cnVlLFxufTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgcmVmbGVjdDogdHJ1ZSB9KVxuXSwgVGV4dEZpZWxkLnByb3RvdHlwZSwgXCJlcnJvclwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyBhdHRyaWJ1dGU6ICdlcnJvci10ZXh0JyB9KVxuXSwgVGV4dEZpZWxkLnByb3RvdHlwZSwgXCJlcnJvclRleHRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KClcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwibGFiZWxcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgYXR0cmlidXRlOiAnbm8tYXN0ZXJpc2snIH0pXG5dLCBUZXh0RmllbGQucHJvdG90eXBlLCBcIm5vQXN0ZXJpc2tcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgcmVmbGVjdDogdHJ1ZSB9KVxuXSwgVGV4dEZpZWxkLnByb3RvdHlwZSwgXCJyZXF1aXJlZFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoKVxuXSwgVGV4dEZpZWxkLnByb3RvdHlwZSwgXCJ2YWx1ZVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyBhdHRyaWJ1dGU6ICdwcmVmaXgtdGV4dCcgfSlcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwicHJlZml4VGV4dFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyBhdHRyaWJ1dGU6ICdzdWZmaXgtdGV4dCcgfSlcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwic3VmZml4VGV4dFwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCBhdHRyaWJ1dGU6ICdoYXMtbGVhZGluZy1pY29uJyB9KVxuXSwgVGV4dEZpZWxkLnByb3RvdHlwZSwgXCJoYXNMZWFkaW5nSWNvblwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCBhdHRyaWJ1dGU6ICdoYXMtdHJhaWxpbmctaWNvbicgfSlcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwiaGFzVHJhaWxpbmdJY29uXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IGF0dHJpYnV0ZTogJ3N1cHBvcnRpbmctdGV4dCcgfSlcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwic3VwcG9ydGluZ1RleHRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgYXR0cmlidXRlOiAndGV4dC1kaXJlY3Rpb24nIH0pXG5dLCBUZXh0RmllbGQucHJvdG90eXBlLCBcInRleHREaXJlY3Rpb25cIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogTnVtYmVyIH0pXG5dLCBUZXh0RmllbGQucHJvdG90eXBlLCBcInJvd3NcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogTnVtYmVyIH0pXG5dLCBUZXh0RmllbGQucHJvdG90eXBlLCBcImNvbHNcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgcmVmbGVjdDogdHJ1ZSB9KVxuXSwgVGV4dEZpZWxkLnByb3RvdHlwZSwgXCJpbnB1dE1vZGVcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KClcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwibWF4XCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IE51bWJlciB9KVxuXSwgVGV4dEZpZWxkLnByb3RvdHlwZSwgXCJtYXhMZW5ndGhcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KClcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwibWluXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHR5cGU6IE51bWJlciB9KVxuXSwgVGV4dEZpZWxkLnByb3RvdHlwZSwgXCJtaW5MZW5ndGhcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgYXR0cmlidXRlOiAnbm8tc3Bpbm5lcicgfSlcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwibm9TcGlubmVyXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSgpXG5dLCBUZXh0RmllbGQucHJvdG90eXBlLCBcInBhdHRlcm5cIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgcmVmbGVjdDogdHJ1ZSwgY29udmVydGVyOiBzdHJpbmdDb252ZXJ0ZXIgfSlcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwicGxhY2Vob2xkZXJcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgdHlwZTogQm9vbGVhbiwgcmVmbGVjdDogdHJ1ZSB9KVxuXSwgVGV4dEZpZWxkLnByb3RvdHlwZSwgXCJyZWFkT25seVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoeyB0eXBlOiBCb29sZWFuLCByZWZsZWN0OiB0cnVlIH0pXG5dLCBUZXh0RmllbGQucHJvdG90eXBlLCBcIm11bHRpcGxlXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSgpXG5dLCBUZXh0RmllbGQucHJvdG90eXBlLCBcInN0ZXBcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHByb3BlcnR5KHsgcmVmbGVjdDogdHJ1ZSB9KVxuXSwgVGV4dEZpZWxkLnByb3RvdHlwZSwgXCJ0eXBlXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSh7IHJlZmxlY3Q6IHRydWUgfSlcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwiYXV0b2NvbXBsZXRlXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBzdGF0ZSgpXG5dLCBUZXh0RmllbGQucHJvdG90eXBlLCBcImRpcnR5XCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBzdGF0ZSgpXG5dLCBUZXh0RmllbGQucHJvdG90eXBlLCBcImZvY3VzZWRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHN0YXRlKClcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwibmF0aXZlRXJyb3JcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHN0YXRlKClcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwibmF0aXZlRXJyb3JUZXh0XCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBxdWVyeSgnLmlucHV0Jylcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwiaW5wdXRPclRleHRhcmVhXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBxdWVyeSgnLmZpZWxkJylcbl0sIFRleHRGaWVsZC5wcm90b3R5cGUsIFwiZmllbGRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHF1ZXJ5QXNzaWduZWRFbGVtZW50cyh7IHNsb3Q6ICdsZWFkaW5nLWljb24nIH0pXG5dLCBUZXh0RmllbGQucHJvdG90eXBlLCBcImxlYWRpbmdJY29uc1wiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcXVlcnlBc3NpZ25lZEVsZW1lbnRzKHsgc2xvdDogJ3RyYWlsaW5nLWljb24nIH0pXG5dLCBUZXh0RmllbGQucHJvdG90eXBlLCBcInRyYWlsaW5nSWNvbnNcIiwgdm9pZCAwKTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXRleHQtZmllbGQuanMubWFwIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBfYXRvYihzdHIpIHtcbiAgcmV0dXJuIGF0b2Ioc3RyKVxufVxuIiwiaW1wb3J0IHsgQ2hlY2tib3ggfSBmcm9tIFwiQG1hdGVyaWFsL3dlYi9jaGVja2JveC9pbnRlcm5hbC9jaGVja2JveC5qc1wiO1xuaW1wb3J0IHsgc3R5bGVzIH0gZnJvbSBcIkBtYXRlcmlhbC93ZWIvY2hlY2tib3gvaW50ZXJuYWwvY2hlY2tib3gtc3R5bGVzLmpzXCI7XG5leHBvcnQgY2xhc3MgRXdDaGVja2JveCBleHRlbmRzIENoZWNrYm94IHtcbn1cbkV3Q2hlY2tib3guc3R5bGVzID0gW3N0eWxlc107XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoXCJldy1jaGVja2JveFwiLCBFd0NoZWNrYm94KTtcbiIsImltcG9ydCB7IENpcmN1bGFyUHJvZ3Jlc3MgfSBmcm9tIFwiQG1hdGVyaWFsL3dlYi9wcm9ncmVzcy9pbnRlcm5hbC9jaXJjdWxhci1wcm9ncmVzcy5qc1wiO1xuaW1wb3J0IHsgc3R5bGVzIH0gZnJvbSBcIkBtYXRlcmlhbC93ZWIvcHJvZ3Jlc3MvaW50ZXJuYWwvY2lyY3VsYXItcHJvZ3Jlc3Mtc3R5bGVzLmpzXCI7XG5leHBvcnQgY2xhc3MgRXdDaXJjdWxhclByb2dyZXNzIGV4dGVuZHMgQ2lyY3VsYXJQcm9ncmVzcyB7XG59XG5Fd0NpcmN1bGFyUHJvZ3Jlc3Muc3R5bGVzID0gW3N0eWxlc107XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoXCJldy1jaXJjdWxhci1wcm9ncmVzc1wiLCBFd0NpcmN1bGFyUHJvZ3Jlc3MpO1xuIiwiaW1wb3J0IHsgRGl2aWRlciB9IGZyb20gXCJAbWF0ZXJpYWwvd2ViL2RpdmlkZXIvaW50ZXJuYWwvZGl2aWRlci5qc1wiO1xuaW1wb3J0IHsgc3R5bGVzIH0gZnJvbSBcIkBtYXRlcmlhbC93ZWIvZGl2aWRlci9pbnRlcm5hbC9kaXZpZGVyLXN0eWxlcy5qc1wiO1xuZXhwb3J0IGNsYXNzIEV3RGl2aWRlciBleHRlbmRzIERpdmlkZXIge1xufVxuRXdEaXZpZGVyLnN0eWxlcyA9IFtzdHlsZXNdO1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKFwiZXctZGl2aWRlclwiLCBFd0RpdmlkZXIpO1xuIiwiaW1wb3J0IHsgRmlsbGVkU2VsZWN0IH0gZnJvbSBcIkBtYXRlcmlhbC93ZWIvc2VsZWN0L2ludGVybmFsL2ZpbGxlZC1zZWxlY3QuanNcIjtcbmltcG9ydCB7IHN0eWxlcyB9IGZyb20gXCJAbWF0ZXJpYWwvd2ViL3NlbGVjdC9pbnRlcm5hbC9maWxsZWQtc2VsZWN0LXN0eWxlcy5qc1wiO1xuaW1wb3J0IHsgc3R5bGVzIGFzIHNoYXJlZFN0eWxlcyB9IGZyb20gXCJAbWF0ZXJpYWwvd2ViL3NlbGVjdC9pbnRlcm5hbC9zaGFyZWQtc3R5bGVzLmpzXCI7XG5leHBvcnQgY2xhc3MgRXdGaWxsZWRTZWxlY3QgZXh0ZW5kcyBGaWxsZWRTZWxlY3Qge1xufVxuRXdGaWxsZWRTZWxlY3Quc3R5bGVzID0gW3NoYXJlZFN0eWxlcywgc3R5bGVzXTtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZShcImV3LWZpbGxlZC1zZWxlY3RcIiwgRXdGaWxsZWRTZWxlY3QpO1xuIiwiaW1wb3J0IHsgc3R5bGVzIGFzIGZpbGxlZFN0eWxlcyB9IGZyb20gXCJAbWF0ZXJpYWwvd2ViL3RleHRmaWVsZC9pbnRlcm5hbC9maWxsZWQtc3R5bGVzLmpzXCI7XG5pbXBvcnQgeyBGaWxsZWRUZXh0RmllbGQgfSBmcm9tIFwiQG1hdGVyaWFsL3dlYi90ZXh0ZmllbGQvaW50ZXJuYWwvZmlsbGVkLXRleHQtZmllbGQuanNcIjtcbmltcG9ydCB7IHN0eWxlcyBhcyBzaGFyZWRTdHlsZXMgfSBmcm9tIFwiQG1hdGVyaWFsL3dlYi90ZXh0ZmllbGQvaW50ZXJuYWwvc2hhcmVkLXN0eWxlcy5qc1wiO1xuaW1wb3J0IHsgbGl0ZXJhbCB9IGZyb20gXCJsaXQvc3RhdGljLWh0bWwuanNcIjtcbmV4cG9ydCBjbGFzcyBFd0ZpbGxlZFRleHRGaWVsZCBleHRlbmRzIEZpbGxlZFRleHRGaWVsZCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuZmllbGRUYWcgPSBsaXRlcmFsIGBtZC1maWxsZWQtZmllbGRgO1xuICAgIH1cbn1cbkV3RmlsbGVkVGV4dEZpZWxkLnN0eWxlcyA9IFtzaGFyZWRTdHlsZXMsIGZpbGxlZFN0eWxlc107XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoXCJldy1maWxsZWQtdGV4dC1maWVsZFwiLCBFd0ZpbGxlZFRleHRGaWVsZCk7XG4iLCJpbXBvcnQgeyBJY29uQnV0dG9uIH0gZnJvbSBcIkBtYXRlcmlhbC93ZWIvaWNvbmJ1dHRvbi9pbnRlcm5hbC9pY29uLWJ1dHRvbi5qc1wiO1xuaW1wb3J0IHsgc3R5bGVzIGFzIHNoYXJlZFN0eWxlcyB9IGZyb20gXCJAbWF0ZXJpYWwvd2ViL2ljb25idXR0b24vaW50ZXJuYWwvc2hhcmVkLXN0eWxlcy5qc1wiO1xuaW1wb3J0IHsgc3R5bGVzIH0gZnJvbSBcIkBtYXRlcmlhbC93ZWIvaWNvbmJ1dHRvbi9pbnRlcm5hbC9zdGFuZGFyZC1zdHlsZXMuanNcIjtcbmV4cG9ydCBjbGFzcyBFd0ljb25CdXR0b24gZXh0ZW5kcyBJY29uQnV0dG9uIHtcbn1cbkV3SWNvbkJ1dHRvbi5zdHlsZXMgPSBbc2hhcmVkU3R5bGVzLCBzdHlsZXNdO1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKFwiZXctaWNvbi1idXR0b25cIiwgRXdJY29uQnV0dG9uKTtcbiIsImltcG9ydCB7IExpc3RJdGVtRWwgYXMgTGlzdEl0ZW0gfSBmcm9tIFwiQG1hdGVyaWFsL3dlYi9saXN0L2ludGVybmFsL2xpc3RpdGVtL2xpc3QtaXRlbS5qc1wiO1xuaW1wb3J0IHsgc3R5bGVzIH0gZnJvbSBcIkBtYXRlcmlhbC93ZWIvbGlzdC9pbnRlcm5hbC9saXN0aXRlbS9saXN0LWl0ZW0tc3R5bGVzLmpzXCI7XG5leHBvcnQgY2xhc3MgRXdMaXN0SXRlbSBleHRlbmRzIExpc3RJdGVtIHtcbn1cbkV3TGlzdEl0ZW0uc3R5bGVzID0gW3N0eWxlc107XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoXCJldy1saXN0LWl0ZW1cIiwgRXdMaXN0SXRlbSk7XG4iLCJpbXBvcnQgeyBMaXN0IH0gZnJvbSBcIkBtYXRlcmlhbC93ZWIvbGlzdC9pbnRlcm5hbC9saXN0LmpzXCI7XG5pbXBvcnQgeyBzdHlsZXMgfSBmcm9tIFwiQG1hdGVyaWFsL3dlYi9saXN0L2ludGVybmFsL2xpc3Qtc3R5bGVzLmpzXCI7XG5leHBvcnQgY2xhc3MgRXdMaXN0IGV4dGVuZHMgTGlzdCB7XG59XG5Fd0xpc3Quc3R5bGVzID0gW3N0eWxlc107XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoXCJldy1saXN0XCIsIEV3TGlzdCk7XG4iLCJpbXBvcnQgeyBzdHlsZXMgfSBmcm9tIFwiQG1hdGVyaWFsL3dlYi9tZW51L2ludGVybmFsL21lbnVpdGVtL21lbnUtaXRlbS1zdHlsZXMuanNcIjtcbmltcG9ydCB7IFNlbGVjdE9wdGlvbkVsIH0gZnJvbSBcIkBtYXRlcmlhbC93ZWIvc2VsZWN0L2ludGVybmFsL3NlbGVjdG9wdGlvbi9zZWxlY3Qtb3B0aW9uLmpzXCI7XG5leHBvcnQgY2xhc3MgRXdTZWxlY3RPcHRpb24gZXh0ZW5kcyBTZWxlY3RPcHRpb25FbCB7XG59XG5Fd1NlbGVjdE9wdGlvbi5zdHlsZXMgPSBbc3R5bGVzXTtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZShcImV3LXNlbGVjdC1vcHRpb25cIiwgRXdTZWxlY3RPcHRpb24pO1xuIiwiaW1wb3J0IHsgQ29sb3JlZENvbnNvbGUsIGNvbG9yZWRDb25zb2xlU3R5bGVzIH0gZnJvbSBcIi4uL3V0aWwvY29uc29sZS1jb2xvclwiO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tIFwiLi4vdXRpbC9zbGVlcFwiO1xuaW1wb3J0IHsgTGluZUJyZWFrVHJhbnNmb3JtZXIgfSBmcm9tIFwiLi4vdXRpbC9saW5lLWJyZWFrLXRyYW5zZm9ybWVyXCI7XG5pbXBvcnQgeyBUaW1lc3RhbXBUcmFuc2Zvcm1lciB9IGZyb20gXCIuLi91dGlsL3RpbWVzdGFtcC10cmFuc2Zvcm1lclwiO1xuZXhwb3J0IGNsYXNzIEV3dENvbnNvbGUgZXh0ZW5kcyBIVE1MRWxlbWVudCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuYWxsb3dJbnB1dCA9IHRydWU7XG4gICAgfVxuICAgIGxvZ3MoKSB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgcmV0dXJuICgoX2EgPSB0aGlzLl9jb25zb2xlKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EubG9ncygpKSB8fCBcIlwiO1xuICAgIH1cbiAgICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICAgICAgaWYgKHRoaXMuX2NvbnNvbGUpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzaGFkb3dSb290ID0gdGhpcy5hdHRhY2hTaGFkb3coeyBtb2RlOiBcIm9wZW5cIiB9KTtcbiAgICAgICAgc2hhZG93Um9vdC5pbm5lckhUTUwgPSBgXG4gICAgICA8c3R5bGU+XG4gICAgICAgIDpob3N0LCBpbnB1dCB7XG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogIzFjMWMxYztcbiAgICAgICAgICBjb2xvcjogI2RkZDtcbiAgICAgICAgICBmb250LWZhbWlseTogXCJTRk1vbm8tUmVndWxhclwiLCBDb25zb2xhcywgXCJMaWJlcmF0aW9uIE1vbm9cIiwgTWVubG8sIENvdXJpZXIsXG4gICAgICAgICAgICBtb25vc3BhY2U7XG4gICAgICAgICAgbGluZS1oZWlnaHQ6IDEuNDU7XG4gICAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgICB9XG4gICAgICAgIGZvcm0ge1xuICAgICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgICAgICBwYWRkaW5nOiAwIDhweCAwIDE2cHg7XG4gICAgICAgIH1cbiAgICAgICAgaW5wdXQge1xuICAgICAgICAgIGZsZXg6IDE7XG4gICAgICAgICAgcGFkZGluZzogNHB4O1xuICAgICAgICAgIG1hcmdpbjogMCA4cHg7XG4gICAgICAgICAgYm9yZGVyOiAwO1xuICAgICAgICAgIG91dGxpbmU6IG5vbmU7XG4gICAgICAgIH1cbiAgICAgICAgJHtjb2xvcmVkQ29uc29sZVN0eWxlc31cbiAgICAgIDwvc3R5bGU+XG4gICAgICA8ZGl2IGNsYXNzPVwibG9nXCI+PC9kaXY+XG4gICAgICAke3RoaXMuYWxsb3dJbnB1dFxuICAgICAgICAgICAgPyBgPGZvcm0+XG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDxpbnB1dCBhdXRvZm9jdXM+XG4gICAgICAgICAgICAgIDwvZm9ybT5cbiAgICAgICAgICAgIGBcbiAgICAgICAgICAgIDogXCJcIn1cbiAgICBgO1xuICAgICAgICB0aGlzLl9jb25zb2xlID0gbmV3IENvbG9yZWRDb25zb2xlKHRoaXMuc2hhZG93Um9vdC5xdWVyeVNlbGVjdG9yKFwiZGl2XCIpKTtcbiAgICAgICAgaWYgKHRoaXMuYWxsb3dJbnB1dCkge1xuICAgICAgICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLnNoYWRvd1Jvb3QucXVlcnlTZWxlY3RvcihcImlucHV0XCIpO1xuICAgICAgICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHZhciBfYTtcbiAgICAgICAgICAgICAgICAvLyBPbmx5IGZvY3VzIGlucHV0IGlmIHVzZXIgZGlkbid0IHNlbGVjdCBzb21lIHRleHRcbiAgICAgICAgICAgICAgICBpZiAoKChfYSA9IGdldFNlbGVjdGlvbigpKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EudG9TdHJpbmcoKSkgPT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoXCJrZXlkb3duXCIsIChldikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChldi5rZXkgPT09IFwiRW50ZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2VuZENvbW1hbmQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB0aGlzLl9jb25uZWN0KGFib3J0Q29udHJvbGxlci5zaWduYWwpO1xuICAgICAgICB0aGlzLl9jYW5jZWxDb25uZWN0aW9uID0gKCkgPT4ge1xuICAgICAgICAgICAgYWJvcnRDb250cm9sbGVyLmFib3J0KCk7XG4gICAgICAgICAgICByZXR1cm4gY29ubmVjdGlvbjtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgYXN5bmMgX2Nvbm5lY3QoYWJvcnRTaWduYWwpIHtcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXCJTdGFydGluZyBjb25zb2xlIHJlYWQgbG9vcFwiKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucG9ydFxuICAgICAgICAgICAgICAgIC5yZWFkYWJsZS5waXBlVGhyb3VnaChuZXcgVGV4dERlY29kZXJTdHJlYW0oKSwge1xuICAgICAgICAgICAgICAgIHNpZ25hbDogYWJvcnRTaWduYWwsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5waXBlVGhyb3VnaChuZXcgVHJhbnNmb3JtU3RyZWFtKG5ldyBMaW5lQnJlYWtUcmFuc2Zvcm1lcigpKSlcbiAgICAgICAgICAgICAgICAucGlwZVRocm91Z2gobmV3IFRyYW5zZm9ybVN0cmVhbShuZXcgVGltZXN0YW1wVHJhbnNmb3JtZXIoKSkpXG4gICAgICAgICAgICAgICAgLnBpcGVUbyhuZXcgV3JpdGFibGVTdHJlYW0oe1xuICAgICAgICAgICAgICAgIHdyaXRlOiAoY2h1bmspID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29uc29sZS5hZGRMaW5lKGNodW5rLnJlcGxhY2UoXCJcXHJcIiwgXCJcIikpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICBpZiAoIWFib3J0U2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9jb25zb2xlLmFkZExpbmUoXCJcIik7XG4gICAgICAgICAgICAgICAgdGhpcy5fY29uc29sZS5hZGRMaW5lKFwiXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuX2NvbnNvbGUuYWRkTGluZShcIlRlcm1pbmFsIGRpc2Nvbm5lY3RlZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgdGhpcy5fY29uc29sZS5hZGRMaW5lKFwiXCIpO1xuICAgICAgICAgICAgdGhpcy5fY29uc29sZS5hZGRMaW5lKFwiXCIpO1xuICAgICAgICAgICAgdGhpcy5fY29uc29sZS5hZGRMaW5lKGBUZXJtaW5hbCBkaXNjb25uZWN0ZWQ6ICR7ZX1gKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIGF3YWl0IHNsZWVwKDEwMCk7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhcIkZpbmlzaGVkIGNvbnNvbGUgcmVhZCBsb29wXCIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGFzeW5jIF9zZW5kQ29tbWFuZCgpIHtcbiAgICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLnNoYWRvd1Jvb3QucXVlcnlTZWxlY3RvcihcImlucHV0XCIpO1xuICAgICAgICBjb25zdCBjb21tYW5kID0gaW5wdXQudmFsdWU7XG4gICAgICAgIGNvbnN0IGVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKTtcbiAgICAgICAgY29uc3Qgd3JpdGVyID0gdGhpcy5wb3J0LndyaXRhYmxlLmdldFdyaXRlcigpO1xuICAgICAgICBhd2FpdCB3cml0ZXIud3JpdGUoZW5jb2Rlci5lbmNvZGUoY29tbWFuZCArIFwiXFxyXFxuXCIpKTtcbiAgICAgICAgdGhpcy5fY29uc29sZS5hZGRMaW5lKGA+ICR7Y29tbWFuZH1cXHJcXG5gKTtcbiAgICAgICAgaW5wdXQudmFsdWUgPSBcIlwiO1xuICAgICAgICBpbnB1dC5mb2N1cygpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgd3JpdGVyLnJlbGVhc2VMb2NrKCk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIklnbm9yaW5nIHJlbGVhc2UgbG9jayBlcnJvclwiLCBlcnIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGFzeW5jIGRpc2Nvbm5lY3QoKSB7XG4gICAgICAgIGlmICh0aGlzLl9jYW5jZWxDb25uZWN0aW9uKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9jYW5jZWxDb25uZWN0aW9uKCk7XG4gICAgICAgICAgICB0aGlzLl9jYW5jZWxDb25uZWN0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgfVxuICAgIGFzeW5jIHJlc2V0KCkge1xuICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhcIlRyaWdnZXJpbmcgcmVzZXRcIik7XG4gICAgICAgIGF3YWl0IHRoaXMucG9ydC5zZXRTaWduYWxzKHtcbiAgICAgICAgICAgIGRhdGFUZXJtaW5hbFJlYWR5OiBmYWxzZSxcbiAgICAgICAgICAgIHJlcXVlc3RUb1NlbmQ6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgICBhd2FpdCBzbGVlcCgyNTApO1xuICAgICAgICBhd2FpdCB0aGlzLnBvcnQuc2V0U2lnbmFscyh7XG4gICAgICAgICAgICBkYXRhVGVybWluYWxSZWFkeTogZmFsc2UsXG4gICAgICAgICAgICByZXF1ZXN0VG9TZW5kOiBmYWxzZSxcbiAgICAgICAgfSk7XG4gICAgICAgIGF3YWl0IHNsZWVwKDI1MCk7XG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwMDApKTtcbiAgICB9XG59XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoXCJld3QtY29uc29sZVwiLCBFd3RDb25zb2xlKTtcbiIsImltcG9ydCB7IHN2ZyB9IGZyb20gXCJsaXRcIjtcbmV4cG9ydCBjb25zdCBjbG9zZUljb24gPSBzdmcgYFxuICA8c3ZnIHdpZHRoPVwiMjRcIiBoZWlnaHQ9XCIyNFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIj5cbiAgICA8cGF0aFxuICAgICAgZmlsbD1cImN1cnJlbnRDb2xvclwiXG4gICAgICBkPVwiTTE5LDYuNDFMMTcuNTksNUwxMiwxMC41OUw2LjQxLDVMNSw2LjQxTDEwLjU5LDEyTDUsMTcuNTlMNi40MSwxOUwxMiwxMy40MUwxNy41OSwxOUwxOSwxNy41OUwxMy40MSwxMkwxOSw2LjQxWlwiXG4gICAgLz5cbiAgPC9zdmc+XG5gO1xuZXhwb3J0IGNvbnN0IHJlZnJlc2hJY29uID0gc3ZnIGBcbiAgPHN2ZyB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgPHBhdGhcbiAgICAgIGZpbGw9XCJjdXJyZW50Q29sb3JcIlxuICAgICAgZD1cIk0xNy42NSw2LjM1QzE2LjIsNC45IDE0LjIxLDQgMTIsNEE4LDggMCAwLDAgNCwxMkE4LDggMCAwLDAgMTIsMjBDMTUuNzMsMjAgMTguODQsMTcuNDUgMTkuNzMsMTRIMTcuNjVDMTYuODMsMTYuMzMgMTQuNjEsMTggMTIsMThBNiw2IDAgMCwxIDYsMTJBNiw2IDAgMCwxIDEyLDZDMTMuNjYsNiAxNS4xNCw2LjY5IDE2LjIyLDcuNzhMMTMsMTFIMjBWNEwxNy42NSw2LjM1WlwiXG4gICAgLz5cbiAgPC9zdmc+XG5gO1xuZXhwb3J0IGNvbnN0IGxpc3RJdGVtSW5zdGFsbEljb24gPSBzdmcgYFxuICA8c3ZnIHNsb3Q9XCJzdGFydFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIj5cbiAgICA8cGF0aCBkPVwiTTUsMjBIMTlWMThINU0xOSw5SDE1VjNIOVY5SDVMMTIsMTZMMTksOVpcIiAvPlxuICA8L3N2Zz5cbmA7XG5leHBvcnQgY29uc3QgbGlzdEl0ZW1XaWZpID0gc3ZnIGBcbiAgPHN2ZyBzbG90PVwic3RhcnRcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgPHBhdGggZD1cIk0xMiwyMUwxNS42LDE2LjJDMTQuNiwxNS40NSAxMy4zNSwxNSAxMiwxNUMxMC42NSwxNSA5LjQsMTUuNDUgOC40LDE2LjJMMTIsMjFNMTIsM0M3Ljk1LDMgNC4yMSw0LjM0IDEuMiw2LjZMMyw5QzUuNSw3LjEyIDguNjIsNiAxMiw2QzE1LjM4LDYgMTguNSw3LjEyIDIxLDlMMjIuOCw2LjZDMTkuNzksNC4zNCAxNi4wNSwzIDEyLDNNMTIsOUM5LjMsOSA2LjgxLDkuODkgNC44LDExLjRMNi42LDEzLjhDOC4xLDEyLjY3IDkuOTcsMTIgMTIsMTJDMTQuMDMsMTIgMTUuOSwxMi42NyAxNy40LDEzLjhMMTkuMiwxMS40QzE3LjE5LDkuODkgMTQuNyw5IDEyLDlaXCIgLz5cbiAgPC9zdmc+XG5gO1xuZXhwb3J0IGNvbnN0IGxpc3RJdGVtQ29uc29sZSA9IHN2ZyBgXG4gIDxzdmcgc2xvdD1cInN0YXJ0XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICAgIDxwYXRoIGQ9XCJNMjAsMTlWN0g0VjE5SDIwTTIwLDNBMiwyIDAgMCwxIDIyLDVWMTlBMiwyIDAgMCwxIDIwLDIxSDRBMiwyIDAgMCwxIDIsMTlWNUMyLDMuODkgMi45LDMgNCwzSDIwTTEzLDE3VjE1SDE4VjE3SDEzTTkuNTgsMTNMNS41Nyw5SDguNEwxMS43LDEyLjNDMTIuMDksMTIuNjkgMTIuMDksMTMuMzMgMTEuNywxMy43Mkw4LjQyLDE3SDUuNTlMOS41OCwxM1pcIiAvPlxuICA8L3N2Zz5cbmA7XG5leHBvcnQgY29uc3QgbGlzdEl0ZW1WaXNpdERldmljZSA9IHN2ZyBgXG4gIDxzdmcgc2xvdD1cInN0YXJ0XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiPlxuICA8cGF0aCBkPVwiTTE2LjM2LDE0QzE2LjQ0LDEzLjM0IDE2LjUsMTIuNjggMTYuNSwxMkMxNi41LDExLjMyIDE2LjQ0LDEwLjY2IDE2LjM2LDEwSDE5Ljc0QzE5LjksMTAuNjQgMjAsMTEuMzEgMjAsMTJDMjAsMTIuNjkgMTkuOSwxMy4zNiAxOS43NCwxNE0xNC41OSwxOS41NkMxNS4xOSwxOC40NSAxNS42NSwxNy4yNSAxNS45NywxNkgxOC45MkMxNy45NiwxNy42NSAxNi40MywxOC45MyAxNC41OSwxOS41Nk0xNC4zNCwxNEg5LjY2QzkuNTYsMTMuMzQgOS41LDEyLjY4IDkuNSwxMkM5LjUsMTEuMzIgOS41NiwxMC42NSA5LjY2LDEwSDE0LjM0QzE0LjQzLDEwLjY1IDE0LjUsMTEuMzIgMTQuNSwxMkMxNC41LDEyLjY4IDE0LjQzLDEzLjM0IDE0LjM0LDE0TTEyLDE5Ljk2QzExLjE3LDE4Ljc2IDEwLjUsMTcuNDMgMTAuMDksMTZIMTMuOTFDMTMuNSwxNy40MyAxMi44MywxOC43NiAxMiwxOS45Nk04LDhINS4wOEM2LjAzLDYuMzQgNy41Nyw1LjA2IDkuNCw0LjQ0QzguOCw1LjU1IDguMzUsNi43NSA4LDhNNS4wOCwxNkg4QzguMzUsMTcuMjUgOC44LDE4LjQ1IDkuNCwxOS41NkM3LjU3LDE4LjkzIDYuMDMsMTcuNjUgNS4wOCwxNk00LjI2LDE0QzQuMSwxMy4zNiA0LDEyLjY5IDQsMTJDNCwxMS4zMSA0LjEsMTAuNjQgNC4yNiwxMEg3LjY0QzcuNTYsMTAuNjYgNy41LDExLjMyIDcuNSwxMkM3LjUsMTIuNjggNy41NiwxMy4zNCA3LjY0LDE0TTEyLDQuMDNDMTIuODMsNS4yMyAxMy41LDYuNTcgMTMuOTEsOEgxMC4wOUMxMC41LDYuNTcgMTEuMTcsNS4yMyAxMiw0LjAzTTE4LjkyLDhIMTUuOTdDMTUuNjUsNi43NSAxNS4xOSw1LjU1IDE0LjU5LDQuNDRDMTYuNDMsNS4wNyAxNy45Niw2LjM0IDE4LjkyLDhNMTIsMkM2LjQ3LDIgMiw2LjUgMiwxMkExMCwxMCAwIDAsMCAxMiwyMkExMCwxMCAwIDAsMCAyMiwxMkExMCwxMCAwIDAsMCAxMiwyWlwiIC8+XG4gIDwvc3ZnPlxuYDtcbmV4cG9ydCBjb25zdCBsaXN0SXRlbUhvbWVBc3Npc3RhbnQgPSBzdmcgYFxuICA8c3ZnIHNsb3Q9XCJzdGFydFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIj5cbiAgICA8cGF0aCBkPVwibTEyLjE1MSAxLjU4ODJjLS4zMjYyIDAtLjY1MjMuMTI5MS0uODk5Ni4zODY3bC04LjM4NDggOC43MzU0Yy0uMDYxOS4wNjQ0LS4xMjIzLjEzNjgtLjE4MDcuMjE1NC0uMDU4OC4wNzg5LS4xMTUxLjE2MzgtLjE2ODguMjUzNC0uMjU5My40MzI1LS40NTUyLjk3NDktLjUyMzIgMS40NTU1LS4wMDI2LjAxOC0uMDA3Ni4wMzY5LS4wMDk0LjA1NDgtLjAxMjEuMDk4Ny0uMDE4NC4xOTQ0LS4wMTg0LjI4NTd2OC4wMTI0YTEuMjczMSAxLjI3MzEgMCAwMDEuMjczMSAxLjI3MzFoNy44MzEzbC0zLjQ0ODQtMy41OTNhMS43Mzk5IDEuNzM5OSAwIDExMS4wODAzLTEuMTI1bDIuNjg0NyAyLjc5NzJ2LTEwLjI0OGExLjczOTkgMS43Mzk5IDAgMTExLjUyNzYtMHY3LjE4N2wyLjY3MDItMi43ODJhMS43Mzk5IDEuNzM5OSAwIDExMS4wNTY2IDEuMTUwNWwtMy43MjY5IDMuODgzMXYyLjcyOTloOC4xNzRhMS4yNDcxIDEuMjQ3MSAwIDAwMS4yNDcxLTEuMjQ3MXYtOC4wMzc1YzAtLjA5MTItLjAwNTktLjE4NjgtLjAxODQtLjI4NTUtLjA2MDMtLjQ5MzUtLjI2MzYtMS4wNjE3LS41MzI2LTEuNTEwNS0uMDUzNy0uMDg5Ni0uMTEwMS0uMTc0NS0uMTY4NC0uMjUzLS4wNTg4LS4wNzktLjExOTEtLjE1MTMtLjE4MS0uMjE1OGwtOC4zODQ4LTguNzM2M2MtLjI0NzMtLjI1NzctLjU3MzUtLjM4NjYtLjg5OTUtLjM4NjRcIiAvPlxuICA8L3N2Zz5cbmA7XG5leHBvcnQgY29uc3QgbGlzdEl0ZW1FcmFzZVVzZXJEYXRhID0gc3ZnIGBcbiAgPHN2ZyBzbG90PVwic3RhcnRcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgPHBhdGggZD1cIk0xNSwxNEMxNy42NywxNCAyMywxNS4zMyAyMywxOFYyMEg3VjE4QzcsMTUuMzMgMTIuMzMsMTQgMTUsMTRNMTUsMTJBNCw0IDAgMCwxIDExLDhBNCw0IDAgMCwxIDE1LDRBNCw0IDAgMCwxIDE5LDhBNCw0IDAgMCwxIDE1LDEyTTUsOS41OUw3LjEyLDcuNDZMOC41NCw4Ljg4TDYuNDEsMTFMOC41NCwxMy4xMkw3LjEyLDE0LjU0TDUsMTIuNDFMMi44OCwxNC41NEwxLjQ2LDEzLjEyTDMuNTksMTFMMS40Niw4Ljg4TDIuODgsNy40Nkw1LDkuNTlaXCIgLz5cbiAgPC9zdmc+XG5gO1xuZXhwb3J0IGNvbnN0IGxpc3RJdGVtRnVuZERldmVsb3BtZW50ID0gc3ZnIGBcbiAgPHN2ZyBzbG90PVwic3RhcnRcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCI+XG4gICAgPHBhdGggZD1cIk0xMiwyMS4zNUwxMC41NSwyMC4wM0M1LjQsMTUuMzYgMiwxMi4yNyAyLDguNUMyLDUuNDEgNC40MiwzIDcuNSwzQzkuMjQsMyAxMC45MSwzLjgxIDEyLDUuMDhDMTMuMDksMy44MSAxNC43NiwzIDE2LjUsM0MxOS41OCwzIDIyLDUuNDEgMjIsOC41QzIyLDEyLjI3IDE4LjYsMTUuMzYgMTMuNDUsMjAuMDNMMTIsMjEuMzVaXCIgLz5cbiAgPC9zdmc+XG5gO1xuIiwiaW1wb3J0IHsgVHJhbnNwb3J0LCBFU1BMb2FkZXIgfSBmcm9tIFwiZXNwdG9vbC1qc1wiO1xuaW1wb3J0IHsgaGFyZFJlc2V0IH0gZnJvbSBcIi4vdXRpbC9yZXNldFwiO1xuZXhwb3J0IGNvbnN0IGZsYXNoID0gYXN5bmMgKG9uRXZlbnQsIHBvcnQsIG1hbmlmZXN0UGF0aCwgbWFuaWZlc3QsIGVyYXNlRmlyc3QpID0+IHtcbiAgICBsZXQgYnVpbGQ7XG4gICAgbGV0IGNoaXBGYW1pbHk7XG4gICAgY29uc3QgZmlyZVN0YXRlRXZlbnQgPSAoc3RhdGVVcGRhdGUpID0+IG9uRXZlbnQoe1xuICAgICAgICAuLi5zdGF0ZVVwZGF0ZSxcbiAgICAgICAgbWFuaWZlc3QsXG4gICAgICAgIGJ1aWxkLFxuICAgICAgICBjaGlwRmFtaWx5LFxuICAgIH0pO1xuICAgIGNvbnN0IHRyYW5zcG9ydCA9IG5ldyBUcmFuc3BvcnQocG9ydCk7XG4gICAgY29uc3QgZXNwbG9hZGVyID0gbmV3IEVTUExvYWRlcih7XG4gICAgICAgIHRyYW5zcG9ydCxcbiAgICAgICAgYmF1ZHJhdGU6IDExNTIwMCxcbiAgICAgICAgcm9tQmF1ZHJhdGU6IDExNTIwMCxcbiAgICAgICAgZW5hYmxlVHJhY2luZzogZmFsc2UsXG4gICAgfSk7XG4gICAgLy8gRm9yIGRlYnVnZ2luZ1xuICAgIHdpbmRvdy5lc3Bsb2FkZXIgPSBlc3Bsb2FkZXI7XG4gICAgZmlyZVN0YXRlRXZlbnQoe1xuICAgICAgICBzdGF0ZTogXCJpbml0aWFsaXppbmdcIiAvKiBGbGFzaFN0YXRlVHlwZS5JTklUSUFMSVpJTkcgKi8sXG4gICAgICAgIG1lc3NhZ2U6IFwiSW5pdGlhbGl6aW5nLi4uXCIsXG4gICAgICAgIGRldGFpbHM6IHsgZG9uZTogZmFsc2UgfSxcbiAgICB9KTtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBlc3Bsb2FkZXIubWFpbigpO1xuICAgICAgICBhd2FpdCBlc3Bsb2FkZXIuZmxhc2hJZCgpO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcbiAgICAgICAgZmlyZVN0YXRlRXZlbnQoe1xuICAgICAgICAgICAgc3RhdGU6IFwiZXJyb3JcIiAvKiBGbGFzaFN0YXRlVHlwZS5FUlJPUiAqLyxcbiAgICAgICAgICAgIG1lc3NhZ2U6IFwiRmFpbGVkIHRvIGluaXRpYWxpemUuIFRyeSByZXNldHRpbmcgeW91ciBkZXZpY2Ugb3IgaG9sZGluZyB0aGUgQk9PVCBidXR0b24gd2hpbGUgY2xpY2tpbmcgSU5TVEFMTC5cIixcbiAgICAgICAgICAgIGRldGFpbHM6IHsgZXJyb3I6IFwiZmFpbGVkX2luaXRpYWxpemVcIiAvKiBGbGFzaEVycm9yLkZBSUxFRF9JTklUSUFMSVpJTkcgKi8sIGRldGFpbHM6IGVyciB9LFxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgaGFyZFJlc2V0KHRyYW5zcG9ydCk7XG4gICAgICAgIGF3YWl0IHRyYW5zcG9ydC5kaXNjb25uZWN0KCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY2hpcEZhbWlseSA9IGVzcGxvYWRlci5jaGlwLkNISVBfTkFNRTtcbiAgICBmaXJlU3RhdGVFdmVudCh7XG4gICAgICAgIHN0YXRlOiBcImluaXRpYWxpemluZ1wiIC8qIEZsYXNoU3RhdGVUeXBlLklOSVRJQUxJWklORyAqLyxcbiAgICAgICAgbWVzc2FnZTogYEluaXRpYWxpemVkLiBGb3VuZCAke2NoaXBGYW1pbHl9YCxcbiAgICAgICAgZGV0YWlsczogeyBkb25lOiB0cnVlIH0sXG4gICAgfSk7XG4gICAgYnVpbGQgPSBtYW5pZmVzdC5idWlsZHMuZmluZCgoYikgPT4gYi5jaGlwRmFtaWx5ID09PSBjaGlwRmFtaWx5KTtcbiAgICBpZiAoIWJ1aWxkKSB7XG4gICAgICAgIGZpcmVTdGF0ZUV2ZW50KHtcbiAgICAgICAgICAgIHN0YXRlOiBcImVycm9yXCIgLyogRmxhc2hTdGF0ZVR5cGUuRVJST1IgKi8sXG4gICAgICAgICAgICBtZXNzYWdlOiBgWW91ciAke2NoaXBGYW1pbHl9IGJvYXJkIGlzIG5vdCBzdXBwb3J0ZWQuYCxcbiAgICAgICAgICAgIGRldGFpbHM6IHsgZXJyb3I6IFwibm90X3N1cHBvcnRlZFwiIC8qIEZsYXNoRXJyb3IuTk9UX1NVUFBPUlRFRCAqLywgZGV0YWlsczogY2hpcEZhbWlseSB9LFxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgaGFyZFJlc2V0KHRyYW5zcG9ydCk7XG4gICAgICAgIGF3YWl0IHRyYW5zcG9ydC5kaXNjb25uZWN0KCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZmlyZVN0YXRlRXZlbnQoe1xuICAgICAgICBzdGF0ZTogXCJwcmVwYXJpbmdcIiAvKiBGbGFzaFN0YXRlVHlwZS5QUkVQQVJJTkcgKi8sXG4gICAgICAgIG1lc3NhZ2U6IFwiUHJlcGFyaW5nIGluc3RhbGxhdGlvbi4uLlwiLFxuICAgICAgICBkZXRhaWxzOiB7IGRvbmU6IGZhbHNlIH0sXG4gICAgfSk7XG4gICAgY29uc3QgbWFuaWZlc3RVUkwgPSBuZXcgVVJMKG1hbmlmZXN0UGF0aCwgbG9jYXRpb24udG9TdHJpbmcoKSkudG9TdHJpbmcoKTtcbiAgICBjb25zdCBmaWxlUHJvbWlzZXMgPSBidWlsZC5wYXJ0cy5tYXAoYXN5bmMgKHBhcnQpID0+IHtcbiAgICAgICAgY29uc3QgdXJsID0gbmV3IFVSTChwYXJ0LnBhdGgsIG1hbmlmZXN0VVJMKS50b1N0cmluZygpO1xuICAgICAgICBjb25zdCByZXNwID0gYXdhaXQgZmV0Y2godXJsKTtcbiAgICAgICAgaWYgKCFyZXNwLm9rKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERvd25sYWRpbmcgZmlybXdhcmUgJHtwYXJ0LnBhdGh9IGZhaWxlZDogJHtyZXNwLnN0YXR1c31gKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgICAgICBjb25zdCBibG9iID0gYXdhaXQgcmVzcC5ibG9iKCk7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgcmVhZGVyLmFkZEV2ZW50TGlzdGVuZXIoXCJsb2FkXCIsICgpID0+IHJlc29sdmUocmVhZGVyLnJlc3VsdCkpO1xuICAgICAgICAgICAgcmVhZGVyLnJlYWRBc0JpbmFyeVN0cmluZyhibG9iKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgY29uc3QgZmlsZUFycmF5ID0gW107XG4gICAgbGV0IHRvdGFsU2l6ZSA9IDA7XG4gICAgZm9yIChsZXQgcGFydCA9IDA7IHBhcnQgPCBmaWxlUHJvbWlzZXMubGVuZ3RoOyBwYXJ0KyspIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBmaWxlUHJvbWlzZXNbcGFydF07XG4gICAgICAgICAgICBmaWxlQXJyYXkucHVzaCh7IGRhdGEsIGFkZHJlc3M6IGJ1aWxkLnBhcnRzW3BhcnRdLm9mZnNldCB9KTtcbiAgICAgICAgICAgIHRvdGFsU2l6ZSArPSBkYXRhLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBmaXJlU3RhdGVFdmVudCh7XG4gICAgICAgICAgICAgICAgc3RhdGU6IFwiZXJyb3JcIiAvKiBGbGFzaFN0YXRlVHlwZS5FUlJPUiAqLyxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICBkZXRhaWxzOiB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiBcImZhaWxlZF9maXJtd2FyZV9kb3dubG9hZFwiIC8qIEZsYXNoRXJyb3IuRkFJTEVEX0ZJUk1XQVJFX0RPV05MT0FEICovLFxuICAgICAgICAgICAgICAgICAgICBkZXRhaWxzOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBhd2FpdCBoYXJkUmVzZXQodHJhbnNwb3J0KTtcbiAgICAgICAgICAgIGF3YWl0IHRyYW5zcG9ydC5kaXNjb25uZWN0KCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG4gICAgZmlyZVN0YXRlRXZlbnQoe1xuICAgICAgICBzdGF0ZTogXCJwcmVwYXJpbmdcIiAvKiBGbGFzaFN0YXRlVHlwZS5QUkVQQVJJTkcgKi8sXG4gICAgICAgIG1lc3NhZ2U6IFwiSW5zdGFsbGF0aW9uIHByZXBhcmVkXCIsXG4gICAgICAgIGRldGFpbHM6IHsgZG9uZTogdHJ1ZSB9LFxuICAgIH0pO1xuICAgIGlmIChlcmFzZUZpcnN0KSB7XG4gICAgICAgIGZpcmVTdGF0ZUV2ZW50KHtcbiAgICAgICAgICAgIHN0YXRlOiBcImVyYXNpbmdcIiAvKiBGbGFzaFN0YXRlVHlwZS5FUkFTSU5HICovLFxuICAgICAgICAgICAgbWVzc2FnZTogXCJFcmFzaW5nIGRldmljZS4uLlwiLFxuICAgICAgICAgICAgZGV0YWlsczogeyBkb25lOiBmYWxzZSB9LFxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgZXNwbG9hZGVyLmVyYXNlRmxhc2goKTtcbiAgICAgICAgZmlyZVN0YXRlRXZlbnQoe1xuICAgICAgICAgICAgc3RhdGU6IFwiZXJhc2luZ1wiIC8qIEZsYXNoU3RhdGVUeXBlLkVSQVNJTkcgKi8sXG4gICAgICAgICAgICBtZXNzYWdlOiBcIkRldmljZSBlcmFzZWRcIixcbiAgICAgICAgICAgIGRldGFpbHM6IHsgZG9uZTogdHJ1ZSB9LFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZmlyZVN0YXRlRXZlbnQoe1xuICAgICAgICBzdGF0ZTogXCJ3cml0aW5nXCIgLyogRmxhc2hTdGF0ZVR5cGUuV1JJVElORyAqLyxcbiAgICAgICAgbWVzc2FnZTogYFdyaXRpbmcgcHJvZ3Jlc3M6IDAlYCxcbiAgICAgICAgZGV0YWlsczoge1xuICAgICAgICAgICAgYnl0ZXNUb3RhbDogdG90YWxTaXplLFxuICAgICAgICAgICAgYnl0ZXNXcml0dGVuOiAwLFxuICAgICAgICAgICAgcGVyY2VudGFnZTogMCxcbiAgICAgICAgfSxcbiAgICB9KTtcbiAgICBsZXQgdG90YWxXcml0dGVuID0gMDtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBlc3Bsb2FkZXIud3JpdGVGbGFzaCh7XG4gICAgICAgICAgICBmaWxlQXJyYXksXG4gICAgICAgICAgICBmbGFzaFNpemU6IFwia2VlcFwiLFxuICAgICAgICAgICAgZmxhc2hNb2RlOiBcImtlZXBcIixcbiAgICAgICAgICAgIGZsYXNoRnJlcTogXCJrZWVwXCIsXG4gICAgICAgICAgICBlcmFzZUFsbDogZmFsc2UsXG4gICAgICAgICAgICBjb21wcmVzczogdHJ1ZSxcbiAgICAgICAgICAgIC8vIHJlcG9ydCBwcm9ncmVzc1xuICAgICAgICAgICAgcmVwb3J0UHJvZ3Jlc3M6IChmaWxlSW5kZXgsIHdyaXR0ZW4sIHRvdGFsKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgdW5jb21wcmVzc2VkV3JpdHRlbiA9ICh3cml0dGVuIC8gdG90YWwpICogZmlsZUFycmF5W2ZpbGVJbmRleF0uZGF0YS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgY29uc3QgbmV3UGN0ID0gTWF0aC5mbG9vcigoKHRvdGFsV3JpdHRlbiArIHVuY29tcHJlc3NlZFdyaXR0ZW4pIC8gdG90YWxTaXplKSAqIDEwMCk7XG4gICAgICAgICAgICAgICAgLy8gd2UncmUgZG9uZSB3aXRoIHRoaXMgZmlsZVxuICAgICAgICAgICAgICAgIGlmICh3cml0dGVuID09PSB0b3RhbCkge1xuICAgICAgICAgICAgICAgICAgICB0b3RhbFdyaXR0ZW4gKz0gdW5jb21wcmVzc2VkV3JpdHRlbjtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmaXJlU3RhdGVFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlOiBcIndyaXRpbmdcIiAvKiBGbGFzaFN0YXRlVHlwZS5XUklUSU5HICovLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBgV3JpdGluZyBwcm9ncmVzczogJHtuZXdQY3R9JWAsXG4gICAgICAgICAgICAgICAgICAgIGRldGFpbHM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzVG90YWw6IHRvdGFsU2l6ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzV3JpdHRlbjogdG90YWxXcml0dGVuICsgd3JpdHRlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHBlcmNlbnRhZ2U6IG5ld1BjdCxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGZpcmVTdGF0ZUV2ZW50KHtcbiAgICAgICAgICAgIHN0YXRlOiBcImVycm9yXCIgLyogRmxhc2hTdGF0ZVR5cGUuRVJST1IgKi8sXG4gICAgICAgICAgICBtZXNzYWdlOiBlcnIubWVzc2FnZSxcbiAgICAgICAgICAgIGRldGFpbHM6IHsgZXJyb3I6IFwid3JpdGVfZmFpbGVkXCIgLyogRmxhc2hFcnJvci5XUklURV9GQUlMRUQgKi8sIGRldGFpbHM6IGVyciB9LFxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgaGFyZFJlc2V0KHRyYW5zcG9ydCk7XG4gICAgICAgIGF3YWl0IHRyYW5zcG9ydC5kaXNjb25uZWN0KCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZmlyZVN0YXRlRXZlbnQoe1xuICAgICAgICBzdGF0ZTogXCJ3cml0aW5nXCIgLyogRmxhc2hTdGF0ZVR5cGUuV1JJVElORyAqLyxcbiAgICAgICAgbWVzc2FnZTogXCJXcml0aW5nIGNvbXBsZXRlXCIsXG4gICAgICAgIGRldGFpbHM6IHtcbiAgICAgICAgICAgIGJ5dGVzVG90YWw6IHRvdGFsU2l6ZSxcbiAgICAgICAgICAgIGJ5dGVzV3JpdHRlbjogdG90YWxXcml0dGVuLFxuICAgICAgICAgICAgcGVyY2VudGFnZTogMTAwLFxuICAgICAgICB9LFxuICAgIH0pO1xuICAgIGF3YWl0IGhhcmRSZXNldCh0cmFuc3BvcnQpO1xuICAgIGNvbnNvbGUubG9nKFwiRElTQ09OTkVDVFwiKTtcbiAgICBhd2FpdCB0cmFuc3BvcnQuZGlzY29ubmVjdCgpO1xuICAgIGZpcmVTdGF0ZUV2ZW50KHtcbiAgICAgICAgc3RhdGU6IFwiZmluaXNoZWRcIiAvKiBGbGFzaFN0YXRlVHlwZS5GSU5JU0hFRCAqLyxcbiAgICAgICAgbWVzc2FnZTogXCJBbGwgZG9uZSFcIixcbiAgICB9KTtcbn07XG4iLCJpbXBvcnQgeyBfX2RlY29yYXRlIH0gZnJvbSBcInRzbGliXCI7XG5pbXBvcnQgeyBMaXRFbGVtZW50LCBodG1sLCBjc3MgfSBmcm9tIFwibGl0XCI7XG5pbXBvcnQgeyBzdGF0ZSB9IGZyb20gXCJsaXQvZGVjb3JhdG9ycy5qc1wiO1xuaW1wb3J0IFwiLi9jb21wb25lbnRzL2V3LXRleHQtYnV0dG9uXCI7XG5pbXBvcnQgXCIuL2NvbXBvbmVudHMvZXctbGlzdFwiO1xuaW1wb3J0IFwiLi9jb21wb25lbnRzL2V3LWxpc3QtaXRlbVwiO1xuaW1wb3J0IFwiLi9jb21wb25lbnRzL2V3LWRpdmlkZXJcIjtcbmltcG9ydCBcIi4vY29tcG9uZW50cy9ldy1jaGVja2JveFwiO1xuaW1wb3J0IFwiLi9jb21wb25lbnRzL2V3dC1jb25zb2xlXCI7XG5pbXBvcnQgXCIuL2NvbXBvbmVudHMvZXctZGlhbG9nXCI7XG5pbXBvcnQgXCIuL2NvbXBvbmVudHMvZXctaWNvbi1idXR0b25cIjtcbmltcG9ydCBcIi4vY29tcG9uZW50cy9ldy1maWxsZWQtdGV4dC1maWVsZFwiO1xuaW1wb3J0IFwiLi9jb21wb25lbnRzL2V3LWZpbGxlZC1zZWxlY3RcIjtcbmltcG9ydCBcIi4vY29tcG9uZW50cy9ldy1zZWxlY3Qtb3B0aW9uXCI7XG5pbXBvcnQgXCIuL3BhZ2VzL2V3dC1wYWdlLXByb2dyZXNzXCI7XG5pbXBvcnQgXCIuL3BhZ2VzL2V3dC1wYWdlLW1lc3NhZ2VcIjtcbmltcG9ydCB7IGNsb3NlSWNvbiwgbGlzdEl0ZW1Db25zb2xlLCBsaXN0SXRlbUVyYXNlVXNlckRhdGEsIGxpc3RJdGVtRnVuZERldmVsb3BtZW50LCBsaXN0SXRlbUhvbWVBc3Npc3RhbnQsIGxpc3RJdGVtSW5zdGFsbEljb24sIGxpc3RJdGVtVmlzaXREZXZpY2UsIGxpc3RJdGVtV2lmaSwgcmVmcmVzaEljb24sIH0gZnJvbSBcIi4vY29tcG9uZW50cy9zdmdcIjtcbmltcG9ydCB7IEltcHJvdlNlcmlhbCB9IGZyb20gXCJpbXByb3Ytd2lmaS1zZXJpYWwtc2RrL2Rpc3Qvc2VyaWFsXCI7XG5pbXBvcnQgeyBJbXByb3ZTZXJpYWxDdXJyZW50U3RhdGUsIFBvcnROb3RSZWFkeSwgfSBmcm9tIFwiaW1wcm92LXdpZmktc2VyaWFsLXNkay9kaXN0L2NvbnN0XCI7XG5pbXBvcnQgeyBmbGFzaCB9IGZyb20gXCIuL2ZsYXNoXCI7XG5pbXBvcnQgeyB0ZXh0RG93bmxvYWQgfSBmcm9tIFwiLi91dGlsL2ZpbGUtZG93bmxvYWRcIjtcbmltcG9ydCB7IGZpcmVFdmVudCB9IGZyb20gXCIuL3V0aWwvZmlyZS1ldmVudFwiO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tIFwiLi91dGlsL3NsZWVwXCI7XG5pbXBvcnQgeyBkb3dubG9hZE1hbmlmZXN0IH0gZnJvbSBcIi4vdXRpbC9tYW5pZmVzdFwiO1xuaW1wb3J0IHsgZGlhbG9nU3R5bGVzIH0gZnJvbSBcIi4vc3R5bGVzXCI7XG5pbXBvcnQgeyB2ZXJzaW9uIH0gZnJvbSBcIi4vdmVyc2lvblwiO1xuY29uc29sZS5sb2coYEVTUCBXZWIgVG9vbHMgJHt2ZXJzaW9ufSBieSBPcGVuIEhvbWUgRm91bmRhdGlvbjsgaHR0cHM6Ly9lc3Bob21lLmdpdGh1Yi5pby9lc3Atd2ViLXRvb2xzL2ApO1xuY29uc3QgRVJST1JfSUNPTiA9IFwi4pqg77iPXCI7XG5jb25zdCBPS19JQ09OID0gXCLwn46JXCI7XG5leHBvcnQgY2xhc3MgRXd0SW5zdGFsbERpYWxvZyBleHRlbmRzIExpdEVsZW1lbnQge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGNvbnNvbGU7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gXCJEQVNIQk9BUkRcIjtcbiAgICAgICAgdGhpcy5faW5zdGFsbEVyYXNlID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2luc3RhbGxDb25maXJtZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fcHJvdmlzaW9uRm9yY2UgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fd2FzUHJvdmlzaW9uZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fYnVzeSA9IGZhbHNlO1xuICAgICAgICAvLyBOYW1lIG9mIFNzaWQuIE51bGwgPSBvdGhlclxuICAgICAgICB0aGlzLl9zZWxlY3RlZFNzaWQgPSBudWxsO1xuICAgICAgICB0aGlzLl9ib2R5T3ZlcmZsb3cgPSBudWxsO1xuICAgICAgICB0aGlzLl9oYW5kbGVEaXNjb25uZWN0ID0gKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fc3RhdGUgPSBcIkVSUk9SXCI7XG4gICAgICAgICAgICB0aGlzLl9lcnJvciA9IFwiRGlzY29ubmVjdGVkXCI7XG4gICAgICAgIH07XG4gICAgfVxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgaWYgKCF0aGlzLnBvcnQpIHtcbiAgICAgICAgICAgIHJldHVybiBodG1sIGBgO1xuICAgICAgICB9XG4gICAgICAgIGxldCBoZWFkaW5nO1xuICAgICAgICBsZXQgY29udGVudDtcbiAgICAgICAgbGV0IGFsbG93Q2xvc2luZyA9IGZhbHNlO1xuICAgICAgICAvLyBEdXJpbmcgaW5zdGFsbGF0aW9uIHBoYXNlIHdlIHRlbXBvcmFyaWx5IHJlbW92ZSB0aGUgY2xpZW50XG4gICAgICAgIGlmICh0aGlzLl9jbGllbnQgPT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgdGhpcy5fc3RhdGUgIT09IFwiSU5TVEFMTFwiICYmXG4gICAgICAgICAgICB0aGlzLl9zdGF0ZSAhPT0gXCJMT0dTXCIpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9lcnJvcikge1xuICAgICAgICAgICAgICAgIFtoZWFkaW5nLCBjb250ZW50XSA9IHRoaXMuX3JlbmRlckVycm9yKHRoaXMuX2Vycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQgPSB0aGlzLl9yZW5kZXJQcm9ncmVzcyhcIkNvbm5lY3RpbmdcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5fc3RhdGUgPT09IFwiSU5TVEFMTFwiKSB7XG4gICAgICAgICAgICBbaGVhZGluZywgY29udGVudCwgYWxsb3dDbG9zaW5nXSA9IHRoaXMuX3JlbmRlckluc3RhbGwoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLl9zdGF0ZSA9PT0gXCJBU0tfRVJBU0VcIikge1xuICAgICAgICAgICAgW2hlYWRpbmcsIGNvbnRlbnRdID0gdGhpcy5fcmVuZGVyQXNrRXJhc2UoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLl9zdGF0ZSA9PT0gXCJFUlJPUlwiKSB7XG4gICAgICAgICAgICBbaGVhZGluZywgY29udGVudF0gPSB0aGlzLl9yZW5kZXJFcnJvcih0aGlzLl9lcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5fc3RhdGUgPT09IFwiREFTSEJPQVJEXCIpIHtcbiAgICAgICAgICAgIFtoZWFkaW5nLCBjb250ZW50LCBhbGxvd0Nsb3NpbmddID0gdGhpcy5fY2xpZW50XG4gICAgICAgICAgICAgICAgPyB0aGlzLl9yZW5kZXJEYXNoYm9hcmQoKVxuICAgICAgICAgICAgICAgIDogdGhpcy5fcmVuZGVyRGFzaGJvYXJkTm9JbXByb3YoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLl9zdGF0ZSA9PT0gXCJQUk9WSVNJT05cIikge1xuICAgICAgICAgICAgW2hlYWRpbmcsIGNvbnRlbnRdID0gdGhpcy5fcmVuZGVyUHJvdmlzaW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5fc3RhdGUgPT09IFwiTE9HU1wiKSB7XG4gICAgICAgICAgICBbaGVhZGluZywgY29udGVudF0gPSB0aGlzLl9yZW5kZXJMb2dzKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGh0bWwgYFxuICAgICAgPGV3LWRpYWxvZ1xuICAgICAgICBvcGVuXG4gICAgICAgIC5oZWFkaW5nPSR7aGVhZGluZ31cbiAgICAgICAgQGNhbmNlbD0ke3RoaXMuX3ByZXZlbnREZWZhdWx0fVxuICAgICAgICBAY2xvc2VkPSR7dGhpcy5faGFuZGxlQ2xvc2V9XG4gICAgICA+XG4gICAgICAgICR7aGVhZGluZyA/IGh0bWwgYDxkaXYgc2xvdD1cImhlYWRsaW5lXCI+JHtoZWFkaW5nfTwvZGl2PmAgOiBcIlwifVxuICAgICAgICAke2FsbG93Q2xvc2luZ1xuICAgICAgICAgICAgPyBodG1sIGBcbiAgICAgICAgICAgICAgPGV3LWljb24tYnV0dG9uIHNsb3Q9XCJoZWFkbGluZVwiIEBjbGljaz0ke3RoaXMuX2Nsb3NlRGlhbG9nfT5cbiAgICAgICAgICAgICAgICAke2Nsb3NlSWNvbn1cbiAgICAgICAgICAgICAgPC9ldy1pY29uLWJ1dHRvbj5cbiAgICAgICAgICAgIGBcbiAgICAgICAgICAgIDogXCJcIn1cbiAgICAgICAgJHtjb250ZW50fVxuICAgICAgPC9ldy1kaWFsb2c+XG4gICAgYDtcbiAgICB9XG4gICAgX3JlbmRlclByb2dyZXNzKGxhYmVsLCBwcm9ncmVzcykge1xuICAgICAgICByZXR1cm4gaHRtbCBgXG4gICAgICA8ZXd0LXBhZ2UtcHJvZ3Jlc3NcbiAgICAgICAgc2xvdD1cImNvbnRlbnRcIlxuICAgICAgICAubGFiZWw9JHtsYWJlbH1cbiAgICAgICAgLnByb2dyZXNzPSR7cHJvZ3Jlc3N9XG4gICAgICA+PC9ld3QtcGFnZS1wcm9ncmVzcz5cbiAgICBgO1xuICAgIH1cbiAgICBfcmVuZGVyRXJyb3IobGFiZWwpIHtcbiAgICAgICAgY29uc3QgaGVhZGluZyA9IFwiRXJyb3JcIjtcbiAgICAgICAgY29uc3QgY29udGVudCA9IGh0bWwgYFxuICAgICAgPGV3dC1wYWdlLW1lc3NhZ2VcbiAgICAgICAgc2xvdD1cImNvbnRlbnRcIlxuICAgICAgICAuaWNvbj0ke0VSUk9SX0lDT059XG4gICAgICAgIC5sYWJlbD0ke2xhYmVsfVxuICAgICAgPjwvZXd0LXBhZ2UtbWVzc2FnZT5cbiAgICAgIDxkaXYgc2xvdD1cImFjdGlvbnNcIj5cbiAgICAgICAgPGV3LXRleHQtYnV0dG9uIEBjbGljaz0ke3RoaXMuX2Nsb3NlRGlhbG9nfT5DbG9zZTwvZXctdGV4dC1idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICBgO1xuICAgICAgICByZXR1cm4gW2hlYWRpbmcsIGNvbnRlbnRdO1xuICAgIH1cbiAgICBfcmVuZGVyRGFzaGJvYXJkKCkge1xuICAgICAgICBjb25zdCBoZWFkaW5nID0gdGhpcy5fbWFuaWZlc3QubmFtZTtcbiAgICAgICAgbGV0IGNvbnRlbnQ7XG4gICAgICAgIGxldCBhbGxvd0Nsb3NpbmcgPSB0cnVlO1xuICAgICAgICBjb250ZW50ID0gaHRtbCBgXG4gICAgICA8ZGl2IHNsb3Q9XCJjb250ZW50XCI+XG4gICAgICAgIDxldy1saXN0PlxuICAgICAgICAgIDxldy1saXN0LWl0ZW0+XG4gICAgICAgICAgICA8ZGl2IHNsb3Q9XCJoZWFkbGluZVwiPkNvbm5lY3RlZCB0byAke3RoaXMuX2luZm8ubmFtZX08L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgc2xvdD1cInN1cHBvcnRpbmctdGV4dFwiPlxuICAgICAgICAgICAgICAke3RoaXMuX2luZm8uZmlybXdhcmV9Jm5ic3A7JHt0aGlzLl9pbmZvLnZlcnNpb259XG4gICAgICAgICAgICAgICgke3RoaXMuX2luZm8uY2hpcEZhbWlseX0pXG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2V3LWxpc3QtaXRlbT5cbiAgICAgICAgICAkeyF0aGlzLl9pc1NhbWVWZXJzaW9uXG4gICAgICAgICAgICA/IGh0bWwgYFxuICAgICAgICAgICAgICAgIDxldy1saXN0LWl0ZW1cbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgQGNsaWNrPSR7KCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9pc1NhbWVGaXJtd2FyZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdGFydEluc3RhbGwoZmFsc2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0aGlzLl9tYW5pZmVzdC5uZXdfaW5zdGFsbF9wcm9tcHRfZXJhc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RhdGUgPSBcIkFTS19FUkFTRVwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RhcnRJbnN0YWxsKHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgJHtsaXN0SXRlbUluc3RhbGxJY29ufVxuICAgICAgICAgICAgICAgICAgPGRpdiBzbG90PVwiaGVhZGxpbmVcIj5cbiAgICAgICAgICAgICAgICAgICAgJHshdGhpcy5faXNTYW1lRmlybXdhcmVcbiAgICAgICAgICAgICAgICA/IGBJbnN0YWxsICR7dGhpcy5fbWFuaWZlc3QubmFtZX1gXG4gICAgICAgICAgICAgICAgOiBgVXBkYXRlICR7dGhpcy5fbWFuaWZlc3QubmFtZX1gfVxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9ldy1saXN0LWl0ZW0+XG4gICAgICAgICAgICAgIGBcbiAgICAgICAgICAgIDogXCJcIn1cbiAgICAgICAgICAke3RoaXMuX2NsaWVudC5uZXh0VXJsID09PSB1bmRlZmluZWRcbiAgICAgICAgICAgID8gXCJcIlxuICAgICAgICAgICAgOiBodG1sIGBcbiAgICAgICAgICAgICAgICA8ZXctbGlzdC1pdGVtXG4gICAgICAgICAgICAgICAgICB0eXBlPVwibGlua1wiXG4gICAgICAgICAgICAgICAgICBocmVmPSR7dGhpcy5fY2xpZW50Lm5leHRVcmx9XG4gICAgICAgICAgICAgICAgICB0YXJnZXQ9XCJfYmxhbmtcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICR7bGlzdEl0ZW1WaXNpdERldmljZX1cbiAgICAgICAgICAgICAgICAgIDxkaXYgc2xvdD1cImhlYWRsaW5lXCI+VmlzaXQgRGV2aWNlPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9ldy1saXN0LWl0ZW0+XG4gICAgICAgICAgICAgIGB9XG4gICAgICAgICAgJHshdGhpcy5fbWFuaWZlc3QuaG9tZV9hc3Npc3RhbnRfZG9tYWluIHx8XG4gICAgICAgICAgICB0aGlzLl9jbGllbnQuc3RhdGUgIT09IEltcHJvdlNlcmlhbEN1cnJlbnRTdGF0ZS5QUk9WSVNJT05FRFxuICAgICAgICAgICAgPyBcIlwiXG4gICAgICAgICAgICA6IGh0bWwgYFxuICAgICAgICAgICAgICAgIDxldy1saXN0LWl0ZW1cbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJsaW5rXCJcbiAgICAgICAgICAgICAgICAgIGhyZWY9JHtgaHR0cHM6Ly9teS5ob21lLWFzc2lzdGFudC5pby9yZWRpcmVjdC9jb25maWdfZmxvd19zdGFydC8/ZG9tYWluPSR7dGhpcy5fbWFuaWZlc3QuaG9tZV9hc3Npc3RhbnRfZG9tYWlufWB9XG4gICAgICAgICAgICAgICAgICB0YXJnZXQ9XCJfYmxhbmtcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICR7bGlzdEl0ZW1Ib21lQXNzaXN0YW50fVxuICAgICAgICAgICAgICAgICAgPGRpdiBzbG90PVwiaGVhZGxpbmVcIj5BZGQgdG8gSG9tZSBBc3Npc3RhbnQ8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2V3LWxpc3QtaXRlbT5cbiAgICAgICAgICAgICAgYH1cbiAgICAgICAgICA8ZXctbGlzdC1pdGVtXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIEBjbGljaz0keygpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3N0YXRlID0gXCJQUk9WSVNJT05cIjtcbiAgICAgICAgICAgIGlmICh0aGlzLl9jbGllbnQuc3RhdGUgPT09IEltcHJvdlNlcmlhbEN1cnJlbnRTdGF0ZS5QUk9WSVNJT05FRCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3Byb3Zpc2lvbkZvcmNlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfX1cbiAgICAgICAgICA+XG4gICAgICAgICAgICAke2xpc3RJdGVtV2lmaX1cbiAgICAgICAgICAgIDxkaXYgc2xvdD1cImhlYWRsaW5lXCI+XG4gICAgICAgICAgICAgICR7dGhpcy5fY2xpZW50LnN0YXRlID09PSBJbXByb3ZTZXJpYWxDdXJyZW50U3RhdGUuUkVBRFlcbiAgICAgICAgICAgID8gXCJDb25uZWN0IHRvIFdpLUZpXCJcbiAgICAgICAgICAgIDogXCJDaGFuZ2UgV2ktRmlcIn1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZXctbGlzdC1pdGVtPlxuICAgICAgICAgIDxldy1saXN0LWl0ZW1cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgQGNsaWNrPSR7YXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY2xpZW50ID0gdGhpcy5fY2xpZW50O1xuICAgICAgICAgICAgaWYgKGNsaWVudCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuX2Nsb3NlQ2xpZW50V2l0aG91dEV2ZW50cyhjbGllbnQpO1xuICAgICAgICAgICAgICAgIGF3YWl0IHNsZWVwKDEwMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBBbHNvIHNldCBgbnVsbGAgYmFjayB0byB1bmRlZmluZWQuXG4gICAgICAgICAgICB0aGlzLl9jbGllbnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLl9zdGF0ZSA9IFwiTE9HU1wiO1xuICAgICAgICB9fVxuICAgICAgICAgID5cbiAgICAgICAgICAgICR7bGlzdEl0ZW1Db25zb2xlfVxuICAgICAgICAgICAgPGRpdiBzbG90PVwiaGVhZGxpbmVcIj5Mb2dzICYgQ29uc29sZTwvZGl2PlxuICAgICAgICAgIDwvZXctbGlzdC1pdGVtPlxuICAgICAgICAgICR7dGhpcy5faXNTYW1lRmlybXdhcmUgJiYgdGhpcy5fbWFuaWZlc3QuZnVuZGluZ191cmxcbiAgICAgICAgICAgID8gaHRtbCBgXG4gICAgICAgICAgICAgICAgPGV3LWxpc3QtaXRlbVxuICAgICAgICAgICAgICAgICAgdHlwZT1cImxpbmtcIlxuICAgICAgICAgICAgICAgICAgaHJlZj0ke3RoaXMuX21hbmlmZXN0LmZ1bmRpbmdfdXJsfVxuICAgICAgICAgICAgICAgICAgdGFyZ2V0PVwiX2JsYW5rXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAke2xpc3RJdGVtRnVuZERldmVsb3BtZW50fVxuICAgICAgICAgICAgICAgICAgPGRpdiBzbG90PVwiaGVhZGxpbmVcIj5GdW5kIERldmVsb3BtZW50PC9kaXY+XG4gICAgICAgICAgICAgICAgPC9ldy1saXN0LWl0ZW0+XG4gICAgICAgICAgICAgIGBcbiAgICAgICAgICAgIDogXCJcIn1cbiAgICAgICAgICAke3RoaXMuX2lzU2FtZVZlcnNpb25cbiAgICAgICAgICAgID8gaHRtbCBgXG4gICAgICAgICAgICAgICAgPGV3LWxpc3QtaXRlbVxuICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cImRhbmdlclwiXG4gICAgICAgICAgICAgICAgICBAY2xpY2s9JHsoKSA9PiB0aGlzLl9zdGFydEluc3RhbGwodHJ1ZSl9XG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgJHtsaXN0SXRlbUVyYXNlVXNlckRhdGF9XG4gICAgICAgICAgICAgICAgICA8ZGl2IHNsb3Q9XCJoZWFkbGluZVwiPkVyYXNlIFVzZXIgRGF0YTwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZXctbGlzdC1pdGVtPlxuICAgICAgICAgICAgICBgXG4gICAgICAgICAgICA6IFwiXCJ9XG4gICAgICAgIDwvZXctbGlzdD5cbiAgICAgIDwvZGl2PlxuICAgIGA7XG4gICAgICAgIHJldHVybiBbaGVhZGluZywgY29udGVudCwgYWxsb3dDbG9zaW5nXTtcbiAgICB9XG4gICAgX3JlbmRlckRhc2hib2FyZE5vSW1wcm92KCkge1xuICAgICAgICBjb25zdCBoZWFkaW5nID0gdGhpcy5fbWFuaWZlc3QubmFtZTtcbiAgICAgICAgbGV0IGNvbnRlbnQ7XG4gICAgICAgIGxldCBhbGxvd0Nsb3NpbmcgPSB0cnVlO1xuICAgICAgICBjb250ZW50ID0gaHRtbCBgXG4gICAgICA8ZGl2IHNsb3Q9XCJjb250ZW50XCI+XG4gICAgICAgIDxldy1saXN0PlxuICAgICAgICAgIDxldy1saXN0LWl0ZW1cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgQGNsaWNrPSR7KCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuX21hbmlmZXN0Lm5ld19pbnN0YWxsX3Byb21wdF9lcmFzZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3N0YXRlID0gXCJBU0tfRVJBU0VcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIERlZmF1bHQgaXMgdG8gZXJhc2UgYSBkZXZpY2UgdGhhdCBkb2VzIG5vdCBzdXBwb3J0IEltcHJvdiBTZXJpYWxcbiAgICAgICAgICAgICAgICB0aGlzLl9zdGFydEluc3RhbGwodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH19XG4gICAgICAgICAgPlxuICAgICAgICAgICAgJHtsaXN0SXRlbUluc3RhbGxJY29ufVxuICAgICAgICAgICAgPGRpdiBzbG90PVwiaGVhZGxpbmVcIj4ke2BJbnN0YWxsICR7dGhpcy5fbWFuaWZlc3QubmFtZX1gfTwvZGl2PlxuICAgICAgICAgIDwvZXctbGlzdC1pdGVtPlxuICAgICAgICAgIDxldy1saXN0LWl0ZW1cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgQGNsaWNrPSR7YXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgLy8gQWxzbyBzZXQgYG51bGxgIGJhY2sgdG8gdW5kZWZpbmVkLlxuICAgICAgICAgICAgdGhpcy5fY2xpZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5fc3RhdGUgPSBcIkxPR1NcIjtcbiAgICAgICAgfX1cbiAgICAgICAgICA+XG4gICAgICAgICAgICAke2xpc3RJdGVtQ29uc29sZX1cbiAgICAgICAgICAgIDxkaXYgc2xvdD1cImhlYWRsaW5lXCI+TG9ncyAmIENvbnNvbGU8L2Rpdj5cbiAgICAgICAgICA8L2V3LWxpc3QtaXRlbT5cbiAgICAgICAgPC9ldy1saXN0PlxuICAgICAgPC9kaXY+XG4gICAgYDtcbiAgICAgICAgcmV0dXJuIFtoZWFkaW5nLCBjb250ZW50LCBhbGxvd0Nsb3NpbmddO1xuICAgIH1cbiAgICBfcmVuZGVyUHJvdmlzaW9uKCkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIGxldCBoZWFkaW5nID0gXCJDb25maWd1cmUgV2ktRmlcIjtcbiAgICAgICAgbGV0IGNvbnRlbnQ7XG4gICAgICAgIGlmICh0aGlzLl9idXN5KSB7XG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgIGhlYWRpbmcsXG4gICAgICAgICAgICAgICAgdGhpcy5fcmVuZGVyUHJvZ3Jlc3ModGhpcy5fc3NpZHMgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICA/IFwiU2Nhbm5pbmcgZm9yIG5ldHdvcmtzXCJcbiAgICAgICAgICAgICAgICAgICAgOiBcIlRyeWluZyB0byBjb25uZWN0XCIpLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuX3Byb3Zpc2lvbkZvcmNlICYmXG4gICAgICAgICAgICB0aGlzLl9jbGllbnQuc3RhdGUgPT09IEltcHJvdlNlcmlhbEN1cnJlbnRTdGF0ZS5QUk9WSVNJT05FRCkge1xuICAgICAgICAgICAgaGVhZGluZyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGNvbnN0IHNob3dTZXR1cExpbmtzID0gIXRoaXMuX3dhc1Byb3Zpc2lvbmVkICYmXG4gICAgICAgICAgICAgICAgKHRoaXMuX2NsaWVudC5uZXh0VXJsICE9PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgICAgICAgICAgXCJob21lX2Fzc2lzdGFudF9kb21haW5cIiBpbiB0aGlzLl9tYW5pZmVzdCk7XG4gICAgICAgICAgICBjb250ZW50ID0gaHRtbCBgXG4gICAgICAgIDxkaXYgc2xvdD1cImNvbnRlbnRcIj5cbiAgICAgICAgICA8ZXd0LXBhZ2UtbWVzc2FnZVxuICAgICAgICAgICAgLmljb249JHtPS19JQ09OfVxuICAgICAgICAgICAgbGFiZWw9XCJEZXZpY2UgY29ubmVjdGVkIHRvIHRoZSBuZXR3b3JrIVwiXG4gICAgICAgICAgPjwvZXd0LXBhZ2UtbWVzc2FnZT5cbiAgICAgICAgICAke3Nob3dTZXR1cExpbmtzXG4gICAgICAgICAgICAgICAgPyBodG1sIGBcbiAgICAgICAgICAgICAgICA8ZXctbGlzdD5cbiAgICAgICAgICAgICAgICAgICR7dGhpcy5fY2xpZW50Lm5leHRVcmwgPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICA/IFwiXCJcbiAgICAgICAgICAgICAgICAgICAgOiBodG1sIGBcbiAgICAgICAgICAgICAgICAgICAgICAgIDxldy1saXN0LWl0ZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImxpbmtcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBocmVmPSR7dGhpcy5fY2xpZW50Lm5leHRVcmx9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldD1cIl9ibGFua1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIEBjbGljaz0keygpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3N0YXRlID0gXCJEQVNIQk9BUkRcIjtcbiAgICAgICAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgJHtsaXN0SXRlbVZpc2l0RGV2aWNlfVxuICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IHNsb3Q9XCJoZWFkbGluZVwiPlZpc2l0IERldmljZTwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9ldy1saXN0LWl0ZW0+XG4gICAgICAgICAgICAgICAgICAgICAgYH1cbiAgICAgICAgICAgICAgICAgICR7IXRoaXMuX21hbmlmZXN0LmhvbWVfYXNzaXN0YW50X2RvbWFpblxuICAgICAgICAgICAgICAgICAgICA/IFwiXCJcbiAgICAgICAgICAgICAgICAgICAgOiBodG1sIGBcbiAgICAgICAgICAgICAgICAgICAgICAgIDxldy1saXN0LWl0ZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImxpbmtcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBocmVmPSR7YGh0dHBzOi8vbXkuaG9tZS1hc3Npc3RhbnQuaW8vcmVkaXJlY3QvY29uZmlnX2Zsb3dfc3RhcnQvP2RvbWFpbj0ke3RoaXMuX21hbmlmZXN0LmhvbWVfYXNzaXN0YW50X2RvbWFpbn1gfVxuICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQ9XCJfYmxhbmtcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBAY2xpY2s9JHsoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdGF0ZSA9IFwiREFTSEJPQVJEXCI7XG4gICAgICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICR7bGlzdEl0ZW1Ib21lQXNzaXN0YW50fVxuICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IHNsb3Q9XCJoZWFkbGluZVwiPkFkZCB0byBIb21lIEFzc2lzdGFudDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9ldy1saXN0LWl0ZW0+XG4gICAgICAgICAgICAgICAgICAgICAgYH1cbiAgICAgICAgICAgICAgICAgIDxldy1saXN0LWl0ZW1cbiAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgIEBjbGljaz0keygpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RhdGUgPSBcIkRBU0hCT0FSRFwiO1xuICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgc2xvdD1cInN0YXJ0XCIgY2xhc3M9XCJmYWtlLWljb25cIj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBzbG90PVwiaGVhZGxpbmVcIj5Ta2lwPC9kaXY+XG4gICAgICAgICAgICAgICAgICA8L2V3LWxpc3QtaXRlbT5cbiAgICAgICAgICAgICAgICA8L2V3LWxpc3Q+XG4gICAgICAgICAgICAgIGBcbiAgICAgICAgICAgICAgICA6IFwiXCJ9XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgICR7IXNob3dTZXR1cExpbmtzXG4gICAgICAgICAgICAgICAgPyBodG1sIGBcbiAgICAgICAgICAgICAgPGRpdiBzbG90PVwiYWN0aW9uc1wiPlxuICAgICAgICAgICAgICAgIDxldy10ZXh0LWJ1dHRvblxuICAgICAgICAgICAgICAgICAgQGNsaWNrPSR7KCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdGF0ZSA9IFwiREFTSEJPQVJEXCI7XG4gICAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICBDb250aW51ZVxuICAgICAgICAgICAgICAgIDwvZXctdGV4dC1idXR0b24+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgIDogXCJcIn1cbiAgICAgIGA7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBsZXQgZXJyb3I7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuX2NsaWVudC5lcnJvcikge1xuICAgICAgICAgICAgICAgIGNhc2UgMyAvKiBJbXByb3ZTZXJpYWxFcnJvclN0YXRlLlVOQUJMRV9UT19DT05ORUNUICovOlxuICAgICAgICAgICAgICAgICAgICBlcnJvciA9IFwiVW5hYmxlIHRvIGNvbm5lY3RcIjtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyNTQgLyogSW1wcm92U2VyaWFsRXJyb3JTdGF0ZS5USU1FT1VUICovOlxuICAgICAgICAgICAgICAgICAgICBlcnJvciA9IFwiVGltZW91dFwiO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDAgLyogSW1wcm92U2VyaWFsRXJyb3JTdGF0ZS5OT19FUlJPUiAqLzpcbiAgICAgICAgICAgICAgICAvLyBIYXBwZW5zIHdoZW4gbGlzdCBTU0lEcyBub3Qgc3VwcG9ydGVkLlxuICAgICAgICAgICAgICAgIGNhc2UgMiAvKiBJbXByb3ZTZXJpYWxFcnJvclN0YXRlLlVOS05PV05fUlBDX0NPTU1BTkQgKi86XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGVycm9yID0gYFVua25vd24gZXJyb3IgKCR7dGhpcy5fY2xpZW50LmVycm9yfSlgO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc2VsZWN0ZWRTc2lkID0gKF9hID0gdGhpcy5fc3NpZHMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5maW5kKChpbmZvKSA9PiBpbmZvLm5hbWUgPT09IHRoaXMuX3NlbGVjdGVkU3NpZCk7XG4gICAgICAgICAgICBjb250ZW50ID0gaHRtbCBgXG4gICAgICAgIDxldy1pY29uLWJ1dHRvbiBzbG90PVwiaGVhZGxpbmVcIiBAY2xpY2s9JHt0aGlzLl91cGRhdGVTc2lkc30+XG4gICAgICAgICAgJHtyZWZyZXNoSWNvbn1cbiAgICAgICAgPC9ldy1pY29uLWJ1dHRvbj5cbiAgICAgICAgPGRpdiBzbG90PVwiY29udGVudFwiPlxuICAgICAgICAgIDxkaXY+Q29ubmVjdCB5b3VyIGRldmljZSB0byB0aGUgbmV0d29yayB0byBzdGFydCB1c2luZyBpdC48L2Rpdj5cbiAgICAgICAgICAke2Vycm9yID8gaHRtbCBgPHAgY2xhc3M9XCJlcnJvclwiPiR7ZXJyb3J9PC9wPmAgOiBcIlwifVxuICAgICAgICAgICR7dGhpcy5fc3NpZHMgIT09IG51bGxcbiAgICAgICAgICAgICAgICA/IGh0bWwgYFxuICAgICAgICAgICAgICAgIDxldy1maWxsZWQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICBtZW51LXBvc2l0aW9uaW5nPVwiZml4ZWRcIlxuICAgICAgICAgICAgICAgICAgbGFiZWw9XCJOZXR3b3JrXCJcbiAgICAgICAgICAgICAgICAgIEBjaGFuZ2U9JHsoZXYpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5kZXggPSBldi50YXJnZXQuc2VsZWN0ZWRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIFwiSm9pbiBPdGhlclwiIGl0ZW0gaXMgYWx3YXlzIHRoZSBsYXN0IGl0ZW0uXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NlbGVjdGVkU3NpZCA9XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCA9PT0gdGhpcy5fc3NpZHMubGVuZ3RoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBudWxsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB0aGlzLl9zc2lkc1tpbmRleF0ubmFtZTtcbiAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICR7dGhpcy5fc3NpZHMubWFwKChpbmZvKSA9PiBodG1sIGBcbiAgICAgICAgICAgICAgICAgICAgICA8ZXctc2VsZWN0LW9wdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgLnNlbGVjdGVkPSR7c2VsZWN0ZWRTc2lkID09PSBpbmZvfVxuICAgICAgICAgICAgICAgICAgICAgICAgLnZhbHVlPSR7aW5mby5uYW1lfVxuICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICR7aW5mby5uYW1lfVxuICAgICAgICAgICAgICAgICAgICAgIDwvZXctc2VsZWN0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgYCl9XG4gICAgICAgICAgICAgICAgICA8ZXctZGl2aWRlcj48L2V3LWRpdmlkZXI+XG4gICAgICAgICAgICAgICAgICA8ZXctc2VsZWN0LW9wdGlvbiAuc2VsZWN0ZWQ9JHshc2VsZWN0ZWRTc2lkfT5cbiAgICAgICAgICAgICAgICAgICAgSm9pbiBvdGhlcuKAplxuICAgICAgICAgICAgICAgICAgPC9ldy1zZWxlY3Qtb3B0aW9uPlxuICAgICAgICAgICAgICAgIDwvZXctZmlsbGVkLXNlbGVjdD5cbiAgICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgIDogXCJcIn1cbiAgICAgICAgICAke1xuICAgICAgICAgICAgLy8gU2hvdyBpbnB1dCBib3ggaWYgY29tbWFuZCBub3Qgc3VwcG9ydGVkIG9yIFwiSm9pbiBPdGhlclwiIHNlbGVjdGVkXG4gICAgICAgICAgICAhc2VsZWN0ZWRTc2lkXG4gICAgICAgICAgICAgICAgPyBodG1sIGBcbiAgICAgICAgICAgICAgICAgIDxldy1maWxsZWQtdGV4dC1maWVsZFxuICAgICAgICAgICAgICAgICAgICBsYWJlbD1cIk5ldHdvcmsgTmFtZVwiXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJzc2lkXCJcbiAgICAgICAgICAgICAgICAgID48L2V3LWZpbGxlZC10ZXh0LWZpZWxkPlxuICAgICAgICAgICAgICAgIGBcbiAgICAgICAgICAgICAgICA6IFwiXCJ9XG4gICAgICAgICAgJHshc2VsZWN0ZWRTc2lkIHx8IHNlbGVjdGVkU3NpZC5zZWN1cmVkXG4gICAgICAgICAgICAgICAgPyBodG1sIGBcbiAgICAgICAgICAgICAgICA8ZXctZmlsbGVkLXRleHQtZmllbGRcbiAgICAgICAgICAgICAgICAgIGxhYmVsPVwiUGFzc3dvcmRcIlxuICAgICAgICAgICAgICAgICAgbmFtZT1cInBhc3N3b3JkXCJcbiAgICAgICAgICAgICAgICAgIHR5cGU9XCJwYXNzd29yZFwiXG4gICAgICAgICAgICAgICAgPjwvZXctZmlsbGVkLXRleHQtZmllbGQ+XG4gICAgICAgICAgICAgIGBcbiAgICAgICAgICAgICAgICA6IFwiXCJ9XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IHNsb3Q9XCJhY3Rpb25zXCI+XG4gICAgICAgICAgPGV3LXRleHQtYnV0dG9uXG4gICAgICAgICAgICBAY2xpY2s9JHsoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc3RhdGUgPSBcIkRBU0hCT0FSRFwiO1xuICAgICAgICAgICAgfX1cbiAgICAgICAgICA+XG4gICAgICAgICAgICAke3RoaXMuX2luc3RhbGxTdGF0ZSAmJiB0aGlzLl9pbnN0YWxsRXJhc2UgPyBcIlNraXBcIiA6IFwiQmFja1wifVxuICAgICAgICAgIDwvZXctdGV4dC1idXR0b24+XG4gICAgICAgICAgPGV3LXRleHQtYnV0dG9uIEBjbGljaz0ke3RoaXMuX2RvUHJvdmlzaW9ufT5Db25uZWN0PC9ldy10ZXh0LWJ1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICBgO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbaGVhZGluZywgY29udGVudF07XG4gICAgfVxuICAgIF9yZW5kZXJBc2tFcmFzZSgpIHtcbiAgICAgICAgY29uc3QgaGVhZGluZyA9IFwiRXJhc2UgZGV2aWNlXCI7XG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSBodG1sIGBcbiAgICAgIDxkaXYgc2xvdD1cImNvbnRlbnRcIj5cbiAgICAgICAgPGRpdj5cbiAgICAgICAgICBEbyB5b3Ugd2FudCB0byBlcmFzZSB0aGUgZGV2aWNlIGJlZm9yZSBpbnN0YWxsaW5nXG4gICAgICAgICAgJHt0aGlzLl9tYW5pZmVzdC5uYW1lfT8gQWxsIGRhdGEgb24gdGhlIGRldmljZSB3aWxsIGJlIGxvc3QuXG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtZmllbGRcIj5cbiAgICAgICAgICA8ZXctY2hlY2tib3ggdG91Y2gtdGFyZ2V0PVwid3JhcHBlclwiIGNsYXNzPVwiZGFuZ2VyXCI+PC9ldy1jaGVja2JveD5cbiAgICAgICAgICBFcmFzZSBkZXZpY2VcbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBzbG90PVwiYWN0aW9uc1wiPlxuICAgICAgICA8ZXctdGV4dC1idXR0b25cbiAgICAgICAgICBAY2xpY2s9JHsoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9zdGF0ZSA9IFwiREFTSEJPQVJEXCI7XG4gICAgICAgIH19XG4gICAgICAgID5cbiAgICAgICAgICBCYWNrXG4gICAgICAgIDwvZXctdGV4dC1idXR0b24+XG4gICAgICAgIDxldy10ZXh0LWJ1dHRvblxuICAgICAgICAgIEBjbGljaz0keygpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNoZWNrYm94ID0gdGhpcy5zaGFkb3dSb290LnF1ZXJ5U2VsZWN0b3IoXCJldy1jaGVja2JveFwiKTtcbiAgICAgICAgICAgIHRoaXMuX3N0YXJ0SW5zdGFsbChjaGVja2JveC5jaGVja2VkKTtcbiAgICAgICAgfX1cbiAgICAgICAgPlxuICAgICAgICAgIE5leHRcbiAgICAgICAgPC9ldy10ZXh0LWJ1dHRvbj5cbiAgICAgIDwvZGl2PlxuICAgIGA7XG4gICAgICAgIHJldHVybiBbaGVhZGluZywgY29udGVudF07XG4gICAgfVxuICAgIF9yZW5kZXJJbnN0YWxsKCkge1xuICAgICAgICBsZXQgaGVhZGluZztcbiAgICAgICAgbGV0IGNvbnRlbnQ7XG4gICAgICAgIGNvbnN0IGFsbG93Q2xvc2luZyA9IGZhbHNlO1xuICAgICAgICBjb25zdCBpc1VwZGF0ZSA9ICF0aGlzLl9pbnN0YWxsRXJhc2UgJiYgdGhpcy5faXNTYW1lRmlybXdhcmU7XG4gICAgICAgIGlmICghdGhpcy5faW5zdGFsbENvbmZpcm1lZCAmJiB0aGlzLl9pc1NhbWVWZXJzaW9uKSB7XG4gICAgICAgICAgICBoZWFkaW5nID0gXCJFcmFzZSBVc2VyIERhdGFcIjtcbiAgICAgICAgICAgIGNvbnRlbnQgPSBodG1sIGBcbiAgICAgICAgPGRpdiBzbG90PVwiY29udGVudFwiPlxuICAgICAgICAgIERvIHlvdSB3YW50IHRvIHJlc2V0IHlvdXIgZGV2aWNlIGFuZCBlcmFzZSBhbGwgdXNlciBkYXRhIGZyb20geW91clxuICAgICAgICAgIGRldmljZT9cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgc2xvdD1cImFjdGlvbnNcIj5cbiAgICAgICAgICA8ZXctdGV4dC1idXR0b24gY2xhc3M9XCJkYW5nZXJcIiBAY2xpY2s9JHt0aGlzLl9jb25maXJtSW5zdGFsbH0+XG4gICAgICAgICAgICBFcmFzZSBVc2VyIERhdGFcbiAgICAgICAgICA8L2V3LXRleHQtYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIGA7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIXRoaXMuX2luc3RhbGxDb25maXJtZWQpIHtcbiAgICAgICAgICAgIGhlYWRpbmcgPSBcIkNvbmZpcm0gSW5zdGFsbGF0aW9uXCI7XG4gICAgICAgICAgICBjb25zdCBhY3Rpb24gPSBpc1VwZGF0ZSA/IFwidXBkYXRlIHRvXCIgOiBcImluc3RhbGxcIjtcbiAgICAgICAgICAgIGNvbnRlbnQgPSBodG1sIGBcbiAgICAgICAgPGRpdiBzbG90PVwiY29udGVudFwiPlxuICAgICAgICAgICR7aXNVcGRhdGVcbiAgICAgICAgICAgICAgICA/IGh0bWwgYFlvdXIgZGV2aWNlIGlzIHJ1bm5pbmdcbiAgICAgICAgICAgICAgICAke3RoaXMuX2luZm8uZmlybXdhcmV9Jm5ic3A7JHt0aGlzLl9pbmZvLnZlcnNpb259LjxiciAvPjxiciAvPmBcbiAgICAgICAgICAgICAgICA6IFwiXCJ9XG4gICAgICAgICAgRG8geW91IHdhbnQgdG8gJHthY3Rpb259XG4gICAgICAgICAgJHt0aGlzLl9tYW5pZmVzdC5uYW1lfSZuYnNwOyR7dGhpcy5fbWFuaWZlc3QudmVyc2lvbn0/XG4gICAgICAgICAgJHt0aGlzLl9pbnN0YWxsRXJhc2VcbiAgICAgICAgICAgICAgICA/IGh0bWwgYDxiciAvPjxiciAvPkFsbCBkYXRhIG9uIHRoZSBkZXZpY2Ugd2lsbCBiZSBlcmFzZWQuYFxuICAgICAgICAgICAgICAgIDogXCJcIn1cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgc2xvdD1cImFjdGlvbnNcIj5cbiAgICAgICAgICA8ZXctdGV4dC1idXR0b25cbiAgICAgICAgICAgIEBjbGljaz0keygpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zdGF0ZSA9IFwiREFTSEJPQVJEXCI7XG4gICAgICAgICAgICB9fVxuICAgICAgICAgID5cbiAgICAgICAgICAgIEJhY2tcbiAgICAgICAgICA8L2V3LXRleHQtYnV0dG9uPlxuICAgICAgICAgIDxldy10ZXh0LWJ1dHRvbiBAY2xpY2s9JHt0aGlzLl9jb25maXJtSW5zdGFsbH0+XG4gICAgICAgICAgICBJbnN0YWxsXG4gICAgICAgICAgPC9ldy10ZXh0LWJ1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICBgO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCF0aGlzLl9pbnN0YWxsU3RhdGUgfHxcbiAgICAgICAgICAgIHRoaXMuX2luc3RhbGxTdGF0ZS5zdGF0ZSA9PT0gXCJpbml0aWFsaXppbmdcIiAvKiBGbGFzaFN0YXRlVHlwZS5JTklUSUFMSVpJTkcgKi8gfHxcbiAgICAgICAgICAgIHRoaXMuX2luc3RhbGxTdGF0ZS5zdGF0ZSA9PT0gXCJwcmVwYXJpbmdcIiAvKiBGbGFzaFN0YXRlVHlwZS5QUkVQQVJJTkcgKi8pIHtcbiAgICAgICAgICAgIGhlYWRpbmcgPSBcIkluc3RhbGxpbmdcIjtcbiAgICAgICAgICAgIGNvbnRlbnQgPSB0aGlzLl9yZW5kZXJQcm9ncmVzcyhcIlByZXBhcmluZyBpbnN0YWxsYXRpb25cIik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5faW5zdGFsbFN0YXRlLnN0YXRlID09PSBcImVyYXNpbmdcIiAvKiBGbGFzaFN0YXRlVHlwZS5FUkFTSU5HICovKSB7XG4gICAgICAgICAgICBoZWFkaW5nID0gXCJJbnN0YWxsaW5nXCI7XG4gICAgICAgICAgICBjb250ZW50ID0gdGhpcy5fcmVuZGVyUHJvZ3Jlc3MoXCJFcmFzaW5nXCIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMuX2luc3RhbGxTdGF0ZS5zdGF0ZSA9PT0gXCJ3cml0aW5nXCIgLyogRmxhc2hTdGF0ZVR5cGUuV1JJVElORyAqLyB8fFxuICAgICAgICAgICAgLy8gV2hlbiB3ZSdyZSBmaW5pc2hlZCwga2VlcCBzaG93aW5nIHRoaXMgc2NyZWVuIHdpdGggMTAwJSB3cml0dGVuXG4gICAgICAgICAgICAvLyB1bnRpbCBJbXByb3YgaXMgaW5pdGlhbGl6ZWQgLyBub3QgZGV0ZWN0ZWQuXG4gICAgICAgICAgICAodGhpcy5faW5zdGFsbFN0YXRlLnN0YXRlID09PSBcImZpbmlzaGVkXCIgLyogRmxhc2hTdGF0ZVR5cGUuRklOSVNIRUQgKi8gJiZcbiAgICAgICAgICAgICAgICB0aGlzLl9jbGllbnQgPT09IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgICAgIGhlYWRpbmcgPSBcIkluc3RhbGxpbmdcIjtcbiAgICAgICAgICAgIGxldCBwZXJjZW50YWdlO1xuICAgICAgICAgICAgbGV0IHVuZGV0ZXJtaW5hdGVMYWJlbDtcbiAgICAgICAgICAgIGlmICh0aGlzLl9pbnN0YWxsU3RhdGUuc3RhdGUgPT09IFwiZmluaXNoZWRcIiAvKiBGbGFzaFN0YXRlVHlwZS5GSU5JU0hFRCAqLykge1xuICAgICAgICAgICAgICAgIC8vIFdlJ3JlIGRvbmUgd3JpdGluZyBhbmQgZGV0ZWN0aW5nIGltcHJvdiwgc2hvdyBzcGlubmVyXG4gICAgICAgICAgICAgICAgdW5kZXRlcm1pbmF0ZUxhYmVsID0gXCJXcmFwcGluZyB1cFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5faW5zdGFsbFN0YXRlLmRldGFpbHMucGVyY2VudGFnZSA8IDQpIHtcbiAgICAgICAgICAgICAgICAvLyBXZSdyZSB3cml0aW5nIHRoZSBmaXJtd2FyZSB1bmRlciA0JSwgc2hvdyBzcGlubmVyIG9yIGVsc2Ugd2UgZG9uJ3Qgc2hvdyBhbnkgcGl4ZWxzXG4gICAgICAgICAgICAgICAgdW5kZXRlcm1pbmF0ZUxhYmVsID0gXCJJbnN0YWxsaW5nXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBXZSdyZSB3cml0aW5nIHRoZSBmaXJtd2FyZSBvdmVyIDQlLCBzaG93IHByb2dyZXNzIGJhclxuICAgICAgICAgICAgICAgIHBlcmNlbnRhZ2UgPSB0aGlzLl9pbnN0YWxsU3RhdGUuZGV0YWlscy5wZXJjZW50YWdlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29udGVudCA9IHRoaXMuX3JlbmRlclByb2dyZXNzKGh0bWwgYFxuICAgICAgICAgICR7dW5kZXRlcm1pbmF0ZUxhYmVsID8gaHRtbCBgJHt1bmRldGVybWluYXRlTGFiZWx9PGJyIC8+YCA6IFwiXCJ9XG4gICAgICAgICAgPGJyIC8+XG4gICAgICAgICAgVGhpcyB3aWxsIHRha2VcbiAgICAgICAgICAke3RoaXMuX2luc3RhbGxTdGF0ZS5jaGlwRmFtaWx5ID09PSBcIkVTUDgyNjZcIlxuICAgICAgICAgICAgICAgID8gXCJhIG1pbnV0ZVwiXG4gICAgICAgICAgICAgICAgOiBcIjIgbWludXRlc1wifS48YnIgLz5cbiAgICAgICAgICBLZWVwIHRoaXMgcGFnZSB2aXNpYmxlIHRvIHByZXZlbnQgc2xvdyBkb3duXG4gICAgICAgIGAsIHBlcmNlbnRhZ2UpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMuX2luc3RhbGxTdGF0ZS5zdGF0ZSA9PT0gXCJmaW5pc2hlZFwiIC8qIEZsYXNoU3RhdGVUeXBlLkZJTklTSEVEICovKSB7XG4gICAgICAgICAgICBoZWFkaW5nID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgY29uc3Qgc3VwcG9ydHNJbXByb3YgPSB0aGlzLl9jbGllbnQgIT09IG51bGw7XG4gICAgICAgICAgICBjb250ZW50ID0gaHRtbCBgXG4gICAgICAgIDxld3QtcGFnZS1tZXNzYWdlXG4gICAgICAgICAgc2xvdD1cImNvbnRlbnRcIlxuICAgICAgICAgIC5pY29uPSR7T0tfSUNPTn1cbiAgICAgICAgICBsYWJlbD1cIkluc3RhbGxhdGlvbiBjb21wbGV0ZSFcIlxuICAgICAgICA+PC9ld3QtcGFnZS1tZXNzYWdlPlxuXG4gICAgICAgIDxkaXYgc2xvdD1cImFjdGlvbnNcIj5cbiAgICAgICAgICA8ZXctdGV4dC1idXR0b25cbiAgICAgICAgICAgIEBjbGljaz0keygpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zdGF0ZSA9XG4gICAgICAgICAgICAgICAgICAgIHN1cHBvcnRzSW1wcm92ICYmIHRoaXMuX2luc3RhbGxFcmFzZVxuICAgICAgICAgICAgICAgICAgICAgICAgPyBcIlBST1ZJU0lPTlwiXG4gICAgICAgICAgICAgICAgICAgICAgICA6IFwiREFTSEJPQVJEXCI7XG4gICAgICAgICAgICB9fVxuICAgICAgICAgID5cbiAgICAgICAgICAgIE5leHRcbiAgICAgICAgICA8L2V3LXRleHQtYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIGA7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5faW5zdGFsbFN0YXRlLnN0YXRlID09PSBcImVycm9yXCIgLyogRmxhc2hTdGF0ZVR5cGUuRVJST1IgKi8pIHtcbiAgICAgICAgICAgIGhlYWRpbmcgPSBcIkluc3RhbGxhdGlvbiBmYWlsZWRcIjtcbiAgICAgICAgICAgIGNvbnRlbnQgPSBodG1sIGBcbiAgICAgICAgPGV3dC1wYWdlLW1lc3NhZ2VcbiAgICAgICAgICBzbG90PVwiY29udGVudFwiXG4gICAgICAgICAgLmljb249JHtFUlJPUl9JQ09OfVxuICAgICAgICAgIC5sYWJlbD0ke3RoaXMuX2luc3RhbGxTdGF0ZS5tZXNzYWdlfVxuICAgICAgICA+PC9ld3QtcGFnZS1tZXNzYWdlPlxuICAgICAgICA8ZGl2IHNsb3Q9XCJhY3Rpb25zXCI+XG4gICAgICAgICAgPGV3LXRleHQtYnV0dG9uXG4gICAgICAgICAgICBAY2xpY2s9JHthc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5faW5pdGlhbGl6ZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3N0YXRlID0gXCJEQVNIQk9BUkRcIjtcbiAgICAgICAgICAgIH19XG4gICAgICAgICAgPlxuICAgICAgICAgICAgQmFja1xuICAgICAgICAgIDwvZXctdGV4dC1idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgYDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW2hlYWRpbmcsIGNvbnRlbnQsIGFsbG93Q2xvc2luZ107XG4gICAgfVxuICAgIF9yZW5kZXJMb2dzKCkge1xuICAgICAgICBsZXQgaGVhZGluZyA9IGBMb2dzYDtcbiAgICAgICAgbGV0IGNvbnRlbnQ7XG4gICAgICAgIGNvbnRlbnQgPSBodG1sIGBcbiAgICAgIDxkaXYgc2xvdD1cImNvbnRlbnRcIj5cbiAgICAgICAgPGV3dC1jb25zb2xlIC5wb3J0PSR7dGhpcy5wb3J0fSAubG9nZ2VyPSR7dGhpcy5sb2dnZXJ9PjwvZXd0LWNvbnNvbGU+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgc2xvdD1cImFjdGlvbnNcIj5cbiAgICAgICAgPGV3LXRleHQtYnV0dG9uXG4gICAgICAgICAgQGNsaWNrPSR7YXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5zaGFkb3dSb290LnF1ZXJ5U2VsZWN0b3IoXCJld3QtY29uc29sZVwiKS5yZXNldCgpO1xuICAgICAgICB9fVxuICAgICAgICA+XG4gICAgICAgICAgUmVzZXQgRGV2aWNlXG4gICAgICAgIDwvZXctdGV4dC1idXR0b24+XG4gICAgICAgIDxldy10ZXh0LWJ1dHRvblxuICAgICAgICAgIEBjbGljaz0keygpID0+IHtcbiAgICAgICAgICAgIHRleHREb3dubG9hZCh0aGlzLnNoYWRvd1Jvb3QucXVlcnlTZWxlY3RvcihcImV3dC1jb25zb2xlXCIpLmxvZ3MoKSwgYGVzcC13ZWItdG9vbHMtbG9ncy50eHRgKTtcbiAgICAgICAgICAgIHRoaXMuc2hhZG93Um9vdC5xdWVyeVNlbGVjdG9yKFwiZXd0LWNvbnNvbGVcIikucmVzZXQoKTtcbiAgICAgICAgfX1cbiAgICAgICAgPlxuICAgICAgICAgIERvd25sb2FkIExvZ3NcbiAgICAgICAgPC9ldy10ZXh0LWJ1dHRvbj5cbiAgICAgICAgPGV3LXRleHQtYnV0dG9uXG4gICAgICAgICAgQGNsaWNrPSR7YXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5zaGFkb3dSb290LnF1ZXJ5U2VsZWN0b3IoXCJld3QtY29uc29sZVwiKS5kaXNjb25uZWN0KCk7XG4gICAgICAgICAgICB0aGlzLl9zdGF0ZSA9IFwiREFTSEJPQVJEXCI7XG4gICAgICAgICAgICB0aGlzLl9pbml0aWFsaXplKCk7XG4gICAgICAgIH19XG4gICAgICAgID5cbiAgICAgICAgICBCYWNrXG4gICAgICAgIDwvZXctdGV4dC1idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICBgO1xuICAgICAgICByZXR1cm4gW2hlYWRpbmcsIGNvbnRlbnRdO1xuICAgIH1cbiAgICB3aWxsVXBkYXRlKGNoYW5nZWRQcm9wcykge1xuICAgICAgICBpZiAoIWNoYW5nZWRQcm9wcy5oYXMoXCJfc3RhdGVcIikpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBDbGVhciBlcnJvcnMgd2hlbiBjaGFuZ2luZyBiZXR3ZWVuIHBhZ2VzIHVubGVzcyB3ZSBjaGFuZ2VcbiAgICAgICAgLy8gdG8gdGhlIGVycm9yIHBhZ2UuXG4gICAgICAgIGlmICh0aGlzLl9zdGF0ZSAhPT0gXCJFUlJPUlwiKSB7XG4gICAgICAgICAgICB0aGlzLl9lcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICAvLyBTY2FuIGZvciBTU0lEcyBvbiBwcm92aXNpb25cbiAgICAgICAgaWYgKHRoaXMuX3N0YXRlID09PSBcIlBST1ZJU0lPTlwiKSB7XG4gICAgICAgICAgICB0aGlzLl91cGRhdGVTc2lkcygpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gUmVzZXQgdGhpcyB2YWx1ZSBpZiB3ZSBsZWF2ZSBwcm92aXNpb25pbmcuXG4gICAgICAgICAgICB0aGlzLl9wcm92aXNpb25Gb3JjZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9zdGF0ZSA9PT0gXCJJTlNUQUxMXCIpIHtcbiAgICAgICAgICAgIHRoaXMuX2luc3RhbGxDb25maXJtZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuX2luc3RhbGxTdGF0ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhc3luYyBfdXBkYXRlU3NpZHModHJpZXMgPSAwKSB7XG4gICAgICAgIGNvbnN0IG9sZFNzaWRzID0gdGhpcy5fc3NpZHM7XG4gICAgICAgIHRoaXMuX3NzaWRzID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLl9idXN5ID0gdHJ1ZTtcbiAgICAgICAgbGV0IHNzaWRzO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgc3NpZHMgPSBhd2FpdCB0aGlzLl9jbGllbnQuc2NhbigpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgZmFpbCB3aGlsZSBsb2FkaW5nLCBwaWNrIFwiSm9pbiBvdGhlclwiXG4gICAgICAgICAgICBpZiAodGhpcy5fc3NpZHMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NzaWRzID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZWxlY3RlZFNzaWQgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fYnVzeSA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdlIHdpbGwgcmV0cnkgYSBmZXcgdGltZXMgaWYgd2UgZG9uJ3QgZ2V0IGFueSByZXN1bHRzXG4gICAgICAgIGlmIChzc2lkcy5sZW5ndGggPT09IDAgJiYgdHJpZXMgPCAzKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIlNDSEVEVUxFIFJFVFJZXCIsIHRyaWVzKTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5fdXBkYXRlU3NpZHModHJpZXMgKyAxKSwgMTAwMCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9sZFNzaWRzKSB7XG4gICAgICAgICAgICAvLyBJZiB3ZSBoYWQgYSBwcmV2aW91cyBsaXN0LCBlbnN1cmUgdGhlIHNlbGVjdGlvbiBpcyBzdGlsbCB2YWxpZFxuICAgICAgICAgICAgaWYgKHRoaXMuX3NlbGVjdGVkU3NpZCAmJlxuICAgICAgICAgICAgICAgICFzc2lkcy5maW5kKChzKSA9PiBzLm5hbWUgPT09IHRoaXMuX3NlbGVjdGVkU3NpZCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZWxlY3RlZFNzaWQgPSBzc2lkc1swXS5uYW1lO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fc2VsZWN0ZWRTc2lkID0gc3NpZHMubGVuZ3RoID8gc3NpZHNbMF0ubmFtZSA6IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fc3NpZHMgPSBzc2lkcztcbiAgICAgICAgdGhpcy5fYnVzeSA9IGZhbHNlO1xuICAgIH1cbiAgICBmaXJzdFVwZGF0ZWQoY2hhbmdlZFByb3BzKSB7XG4gICAgICAgIHN1cGVyLmZpcnN0VXBkYXRlZChjaGFuZ2VkUHJvcHMpO1xuICAgICAgICB0aGlzLl9ib2R5T3ZlcmZsb3cgPSBkb2N1bWVudC5ib2R5LnN0eWxlLm92ZXJmbG93O1xuICAgICAgICBkb2N1bWVudC5ib2R5LnN0eWxlLm92ZXJmbG93ID0gXCJoaWRkZW5cIjtcbiAgICAgICAgdGhpcy5faW5pdGlhbGl6ZSgpO1xuICAgIH1cbiAgICB1cGRhdGVkKGNoYW5nZWRQcm9wcykge1xuICAgICAgICBzdXBlci51cGRhdGVkKGNoYW5nZWRQcm9wcyk7XG4gICAgICAgIGlmIChjaGFuZ2VkUHJvcHMuaGFzKFwiX3N0YXRlXCIpKSB7XG4gICAgICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZShcInN0YXRlXCIsIHRoaXMuX3N0YXRlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fc3RhdGUgIT09IFwiUFJPVklTSU9OXCIpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2hhbmdlZFByb3BzLmhhcyhcIl9zZWxlY3RlZFNzaWRcIikgJiYgdGhpcy5fc2VsZWN0ZWRTc2lkID09PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBJZiB3ZSBwaWNrIFwiSm9pbiBvdGhlclwiLCBzZWxlY3QgU1NJRCBpbnB1dC5cbiAgICAgICAgICAgIHRoaXMuX2ZvY3VzRm9ybUVsZW1lbnQoXCJldy1maWxsZWQtdGV4dC1maWVsZFtuYW1lPXNzaWRdXCIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGNoYW5nZWRQcm9wcy5oYXMoXCJfc3NpZHNcIikpIHtcbiAgICAgICAgICAgIC8vIEZvcm0gaXMgc2hvd24gd2hlbiBTU0lEcyBhcmUgbG9hZGVkL21hcmtlZCBub3Qgc3VwcG9ydGVkXG4gICAgICAgICAgICB0aGlzLl9mb2N1c0Zvcm1FbGVtZW50KCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgX2ZvY3VzRm9ybUVsZW1lbnQoc2VsZWN0b3IgPSBcImV3LWZpbGxlZC10ZXh0LWZpZWxkLCBldy1maWxsZWQtc2VsZWN0XCIpIHtcbiAgICAgICAgY29uc3QgZm9ybUVsID0gdGhpcy5zaGFkb3dSb290LnF1ZXJ5U2VsZWN0b3Ioc2VsZWN0b3IpO1xuICAgICAgICBpZiAoZm9ybUVsKSB7XG4gICAgICAgICAgICBmb3JtRWwudXBkYXRlQ29tcGxldGUudGhlbigoKSA9PiBzZXRUaW1lb3V0KCgpID0+IGZvcm1FbC5mb2N1cygpLCAxMDApKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhc3luYyBfaW5pdGlhbGl6ZShqdXN0SW5zdGFsbGVkID0gZmFsc2UpIHtcbiAgICAgICAgaWYgKHRoaXMucG9ydC5yZWFkYWJsZSA9PT0gbnVsbCB8fCB0aGlzLnBvcnQud3JpdGFibGUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuX3N0YXRlID0gXCJFUlJPUlwiO1xuICAgICAgICAgICAgdGhpcy5fZXJyb3IgPVxuICAgICAgICAgICAgICAgIFwiU2VyaWFsIHBvcnQgaXMgbm90IHJlYWRhYmxlL3dyaXRhYmxlLiBDbG9zZSBhbnkgb3RoZXIgYXBwbGljYXRpb24gdXNpbmcgaXQgYW5kIHRyeSBhZ2Fpbi5cIjtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdGhpcy5fbWFuaWZlc3QgPSBhd2FpdCBkb3dubG9hZE1hbmlmZXN0KHRoaXMubWFuaWZlc3RQYXRoKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLl9zdGF0ZSA9IFwiRVJST1JcIjtcbiAgICAgICAgICAgIHRoaXMuX2Vycm9yID0gXCJGYWlsZWQgdG8gZG93bmxvYWQgbWFuaWZlc3RcIjtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5fbWFuaWZlc3QubmV3X2luc3RhbGxfaW1wcm92X3dhaXRfdGltZSA9PT0gMCkge1xuICAgICAgICAgICAgdGhpcy5fY2xpZW50ID0gbnVsbDtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjbGllbnQgPSBuZXcgSW1wcm92U2VyaWFsKHRoaXMucG9ydCwgdGhpcy5sb2dnZXIpO1xuICAgICAgICBjbGllbnQuYWRkRXZlbnRMaXN0ZW5lcihcInN0YXRlLWNoYW5nZWRcIiwgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZXF1ZXN0VXBkYXRlKCk7XG4gICAgICAgIH0pO1xuICAgICAgICBjbGllbnQuYWRkRXZlbnRMaXN0ZW5lcihcImVycm9yLWNoYW5nZWRcIiwgKCkgPT4gdGhpcy5yZXF1ZXN0VXBkYXRlKCkpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gSWYgYSBkZXZpY2Ugd2FzIGp1c3QgaW5zdGFsbGVkLCBnaXZlIG5ldyBmaXJtd2FyZSAxMCBzZWNvbmRzIChvdmVycmlkYWJsZSkgdG9cbiAgICAgICAgICAgIC8vIGZvcm1hdCB0aGUgcmVzdCBvZiB0aGUgZmxhc2ggYW5kIGRvIG90aGVyIHN0dWZmLlxuICAgICAgICAgICAgY29uc3QgdGltZW91dCA9ICFqdXN0SW5zdGFsbGVkXG4gICAgICAgICAgICAgICAgPyAxMDAwXG4gICAgICAgICAgICAgICAgOiB0aGlzLl9tYW5pZmVzdC5uZXdfaW5zdGFsbF9pbXByb3Zfd2FpdF90aW1lICE9PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgPyB0aGlzLl9tYW5pZmVzdC5uZXdfaW5zdGFsbF9pbXByb3Zfd2FpdF90aW1lICogMTAwMFxuICAgICAgICAgICAgICAgICAgICA6IDEwMDAwO1xuICAgICAgICAgICAgdGhpcy5faW5mbyA9IGF3YWl0IGNsaWVudC5pbml0aWFsaXplKHRpbWVvdXQpO1xuICAgICAgICAgICAgdGhpcy5fY2xpZW50ID0gY2xpZW50O1xuICAgICAgICAgICAgY2xpZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJkaXNjb25uZWN0XCIsIHRoaXMuX2hhbmRsZURpc2Nvbm5lY3QpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIC8vIENsZWFyIG9sZCB2YWx1ZVxuICAgICAgICAgICAgdGhpcy5faW5mbyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBQb3J0Tm90UmVhZHkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zdGF0ZSA9IFwiRVJST1JcIjtcbiAgICAgICAgICAgICAgICB0aGlzLl9lcnJvciA9XG4gICAgICAgICAgICAgICAgICAgIFwiU2VyaWFsIHBvcnQgaXMgbm90IHJlYWR5LiBDbG9zZSBhbnkgb3RoZXIgYXBwbGljYXRpb24gdXNpbmcgaXQgYW5kIHRyeSBhZ2Fpbi5cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX2NsaWVudCA9IG51bGw7IC8vIG5vdCBzdXBwb3J0ZWRcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihcIkltcHJvdiBpbml0aWFsaXphdGlvbiBmYWlsZWQuXCIsIGVycik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgX3N0YXJ0SW5zdGFsbChlcmFzZSkge1xuICAgICAgICB0aGlzLl9zdGF0ZSA9IFwiSU5TVEFMTFwiO1xuICAgICAgICB0aGlzLl9pbnN0YWxsRXJhc2UgPSBlcmFzZTtcbiAgICAgICAgdGhpcy5faW5zdGFsbENvbmZpcm1lZCA9IGZhbHNlO1xuICAgIH1cbiAgICBhc3luYyBfY29uZmlybUluc3RhbGwoKSB7XG4gICAgICAgIHRoaXMuX2luc3RhbGxDb25maXJtZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLl9pbnN0YWxsU3RhdGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmICh0aGlzLl9jbGllbnQpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX2Nsb3NlQ2xpZW50V2l0aG91dEV2ZW50cyh0aGlzLl9jbGllbnQpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2NsaWVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgLy8gQ2xvc2UgcG9ydC4gRVNQTG9hZGVyIGxpa2VzIG9wZW5pbmcgaXQuXG4gICAgICAgIGF3YWl0IHRoaXMucG9ydC5jbG9zZSgpO1xuICAgICAgICBmbGFzaCgoc3RhdGUpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX2luc3RhbGxTdGF0ZSA9IHN0YXRlO1xuICAgICAgICAgICAgaWYgKHN0YXRlLnN0YXRlID09PSBcImZpbmlzaGVkXCIgLyogRmxhc2hTdGF0ZVR5cGUuRklOSVNIRUQgKi8pIHtcbiAgICAgICAgICAgICAgICBzbGVlcCgxMDApXG4gICAgICAgICAgICAgICAgICAgIC8vIEZsYXNoaW5nIGNsb3NlcyB0aGUgcG9ydFxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLnBvcnQub3Blbih7IGJhdWRSYXRlOiAxMTUyMDAsIGJ1ZmZlclNpemU6IDgxOTIgfSkpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHRoaXMuX2luaXRpYWxpemUodHJ1ZSkpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHRoaXMucmVxdWVzdFVwZGF0ZSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHN0YXRlLnN0YXRlID09PSBcImVycm9yXCIgLyogRmxhc2hTdGF0ZVR5cGUuRVJST1IgKi8pIHtcbiAgICAgICAgICAgICAgICBzbGVlcCgxMDApXG4gICAgICAgICAgICAgICAgICAgIC8vIEZsYXNoaW5nIGNsb3NlcyB0aGUgcG9ydFxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLnBvcnQub3Blbih7IGJhdWRSYXRlOiAxMTUyMDAsIGJ1ZmZlclNpemU6IDgxOTIgfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB0aGlzLnBvcnQsIHRoaXMubWFuaWZlc3RQYXRoLCB0aGlzLl9tYW5pZmVzdCwgdGhpcy5faW5zdGFsbEVyYXNlKTtcbiAgICB9XG4gICAgYXN5bmMgX2RvUHJvdmlzaW9uKCkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHRoaXMuX2J1c3kgPSB0cnVlO1xuICAgICAgICB0aGlzLl93YXNQcm92aXNpb25lZCA9XG4gICAgICAgICAgICB0aGlzLl9jbGllbnQuc3RhdGUgPT09IEltcHJvdlNlcmlhbEN1cnJlbnRTdGF0ZS5QUk9WSVNJT05FRDtcbiAgICAgICAgY29uc3Qgc3NpZCA9IHRoaXMuX3NlbGVjdGVkU3NpZCA9PT0gbnVsbFxuICAgICAgICAgICAgPyB0aGlzLnNoYWRvd1Jvb3QucXVlcnlTZWxlY3RvcihcImV3LWZpbGxlZC10ZXh0LWZpZWxkW25hbWU9c3NpZF1cIikudmFsdWVcbiAgICAgICAgICAgIDogdGhpcy5fc2VsZWN0ZWRTc2lkO1xuICAgICAgICBjb25zdCBwYXNzd29yZCA9ICgoX2EgPSB0aGlzLnNoYWRvd1Jvb3QucXVlcnlTZWxlY3RvcihcImV3LWZpbGxlZC10ZXh0LWZpZWxkW25hbWU9cGFzc3dvcmRdXCIpKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EudmFsdWUpIHx8IFwiXCI7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9jbGllbnQucHJvdmlzaW9uKHNzaWQsIHBhc3N3b3JkLCAzMDAwMCk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgdGhpcy5fYnVzeSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5fcHJvdmlzaW9uRm9yY2UgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBfY2xvc2VEaWFsb2coKSB7XG4gICAgICAgIHRoaXMuc2hhZG93Um9vdC5xdWVyeVNlbGVjdG9yKFwiZXctZGlhbG9nXCIpLmNsb3NlKCk7XG4gICAgfVxuICAgIGFzeW5jIF9oYW5kbGVDbG9zZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuX2NsaWVudCkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5fY2xvc2VDbGllbnRXaXRob3V0RXZlbnRzKHRoaXMuX2NsaWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgZmlyZUV2ZW50KHRoaXMsIFwiY2xvc2VkXCIpO1xuICAgICAgICBkb2N1bWVudC5ib2R5LnN0eWxlLm92ZXJmbG93ID0gdGhpcy5fYm9keU92ZXJmbG93O1xuICAgICAgICB0aGlzLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybiBpZiB0aGUgZGV2aWNlIHJ1bnMgc2FtZSBmaXJtd2FyZSBhcyBtYW5pZmVzdC5cbiAgICAgKi9cbiAgICBnZXQgX2lzU2FtZUZpcm13YXJlKCkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIHJldHVybiAhdGhpcy5faW5mb1xuICAgICAgICAgICAgPyBmYWxzZVxuICAgICAgICAgICAgOiAoKF9hID0gdGhpcy5vdmVycmlkZXMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5jaGVja1NhbWVGaXJtd2FyZSlcbiAgICAgICAgICAgICAgICA/IHRoaXMub3ZlcnJpZGVzLmNoZWNrU2FtZUZpcm13YXJlKHRoaXMuX21hbmlmZXN0LCB0aGlzLl9pbmZvKVxuICAgICAgICAgICAgICAgIDogdGhpcy5faW5mby5maXJtd2FyZSA9PT0gdGhpcy5fbWFuaWZlc3QubmFtZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJuIGlmIHRoZSBkZXZpY2UgcnVucyBzYW1lIGZpcm13YXJlIGFuZCB2ZXJzaW9uIGFzIG1hbmlmZXN0LlxuICAgICAqL1xuICAgIGdldCBfaXNTYW1lVmVyc2lvbigpIHtcbiAgICAgICAgcmV0dXJuICh0aGlzLl9pc1NhbWVGaXJtd2FyZSAmJiB0aGlzLl9pbmZvLnZlcnNpb24gPT09IHRoaXMuX21hbmlmZXN0LnZlcnNpb24pO1xuICAgIH1cbiAgICBhc3luYyBfY2xvc2VDbGllbnRXaXRob3V0RXZlbnRzKGNsaWVudCkge1xuICAgICAgICBjbGllbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImRpc2Nvbm5lY3RcIiwgdGhpcy5faGFuZGxlRGlzY29ubmVjdCk7XG4gICAgICAgIGF3YWl0IGNsaWVudC5jbG9zZSgpO1xuICAgIH1cbiAgICBfcHJldmVudERlZmF1bHQoZXYpIHtcbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG59XG5Fd3RJbnN0YWxsRGlhbG9nLnN0eWxlcyA9IFtcbiAgICBkaWFsb2dTdHlsZXMsXG4gICAgY3NzIGBcbiAgICAgIDpob3N0IHtcbiAgICAgICAgLS1tZGMtZGlhbG9nLW1heC13aWR0aDogMzkwcHg7XG4gICAgICB9XG4gICAgICBkaXZbc2xvdD1cImhlYWRsaW5lXCJdIHtcbiAgICAgICAgcGFkZGluZy1yaWdodDogNDhweDtcbiAgICAgIH1cbiAgICAgIGV3LWljb24tYnV0dG9uW3Nsb3Q9XCJoZWFkbGluZVwiXSB7XG4gICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgICAgcmlnaHQ6IDRweDtcbiAgICAgICAgdG9wOiA4cHg7XG4gICAgICB9XG4gICAgICBldy1pY29uLWJ1dHRvbltzbG90PVwiaGVhZGxpbmVcIl0gc3ZnIHtcbiAgICAgICAgcGFkZGluZzogOHB4O1xuICAgICAgICBjb2xvcjogdmFyKC0tdGV4dC1jb2xvcik7XG4gICAgICB9XG4gICAgICAuZGlhbG9nLW5hdiBzdmcge1xuICAgICAgICBjb2xvcjogdmFyKC0tdGV4dC1jb2xvcik7XG4gICAgICB9XG4gICAgICAudGFibGUtcm93IHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIH1cbiAgICAgIC50YWJsZS1yb3cubGFzdCB7XG4gICAgICAgIG1hcmdpbi1ib3R0b206IDE2cHg7XG4gICAgICB9XG4gICAgICAudGFibGUtcm93IHN2ZyB7XG4gICAgICAgIHdpZHRoOiAyMHB4O1xuICAgICAgICBtYXJnaW4tcmlnaHQ6IDhweDtcbiAgICAgIH1cbiAgICAgIGV3LWZpbGxlZC10ZXh0LWZpZWxkLFxuICAgICAgZXctZmlsbGVkLXNlbGVjdCB7XG4gICAgICAgIGRpc3BsYXk6IGJsb2NrO1xuICAgICAgICBtYXJnaW4tdG9wOiAxNnB4O1xuICAgICAgfVxuICAgICAgbGFiZWwuZm9ybWZpZWxkIHtcbiAgICAgICAgZGlzcGxheTogaW5saW5lLWZsZXg7XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIHBhZGRpbmctcmlnaHQ6IDhweDtcbiAgICAgIH1cbiAgICAgIGV3LWxpc3Qge1xuICAgICAgICBtYXJnaW46IDAgLTI0cHg7XG4gICAgICAgIHBhZGRpbmc6IDA7XG4gICAgICB9XG4gICAgICBldy1saXN0LWl0ZW0gc3ZnIHtcbiAgICAgICAgaGVpZ2h0OiAyNHB4O1xuICAgICAgfVxuICAgICAgZXd0LXBhZ2UtbWVzc2FnZSArIGV3LWxpc3Qge1xuICAgICAgICBwYWRkaW5nLXRvcDogMTZweDtcbiAgICAgIH1cbiAgICAgIC5mYWtlLWljb24ge1xuICAgICAgICB3aWR0aDogMjRweDtcbiAgICAgIH1cbiAgICAgIC5lcnJvciB7XG4gICAgICAgIGNvbG9yOiB2YXIoLS1kYW5nZXItY29sb3IpO1xuICAgICAgfVxuICAgICAgLmRhbmdlciB7XG4gICAgICAgIC0tbWRjLXRoZW1lLXByaW1hcnk6IHZhcigtLWRhbmdlci1jb2xvcik7XG4gICAgICAgIC0tbWRjLXRoZW1lLXNlY29uZGFyeTogdmFyKC0tZGFuZ2VyLWNvbG9yKTtcbiAgICAgICAgLS1tZC1zeXMtY29sb3ItcHJpbWFyeTogdmFyKC0tZGFuZ2VyLWNvbG9yKTtcbiAgICAgICAgLS1tZC1zeXMtY29sb3Itb24tc3VyZmFjZTogdmFyKC0tZGFuZ2VyLWNvbG9yKTtcbiAgICAgIH1cbiAgICAgIGJ1dHRvbi5saW5rIHtcbiAgICAgICAgYmFja2dyb3VuZDogbm9uZTtcbiAgICAgICAgY29sb3I6IGluaGVyaXQ7XG4gICAgICAgIGJvcmRlcjogbm9uZTtcbiAgICAgICAgcGFkZGluZzogMDtcbiAgICAgICAgZm9udDogaW5oZXJpdDtcbiAgICAgICAgdGV4dC1hbGlnbjogbGVmdDtcbiAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7XG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICAgIH1cbiAgICAgIDpob3N0KFtzdGF0ZT1cIkxPR1NcIl0pIGV3LWRpYWxvZyB7XG4gICAgICAgIG1heC13aWR0aDogOTB2dztcbiAgICAgICAgbWF4LWhlaWdodDogOTB2aDtcbiAgICAgIH1cbiAgICAgIGV3dC1jb25zb2xlIHtcbiAgICAgICAgd2lkdGg6IGNhbGMoODB2dyAtIDQ4cHgpO1xuICAgICAgICBoZWlnaHQ6IGNhbGMoOTB2aCAtIDE2OHB4KTtcbiAgICAgIH1cbiAgICBgLFxuXTtcbl9fZGVjb3JhdGUoW1xuICAgIHN0YXRlKClcbl0sIEV3dEluc3RhbGxEaWFsb2cucHJvdG90eXBlLCBcIl9jbGllbnRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHN0YXRlKClcbl0sIEV3dEluc3RhbGxEaWFsb2cucHJvdG90eXBlLCBcIl9zdGF0ZVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgc3RhdGUoKVxuXSwgRXd0SW5zdGFsbERpYWxvZy5wcm90b3R5cGUsIFwiX2luc3RhbGxFcmFzZVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgc3RhdGUoKVxuXSwgRXd0SW5zdGFsbERpYWxvZy5wcm90b3R5cGUsIFwiX2luc3RhbGxDb25maXJtZWRcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHN0YXRlKClcbl0sIEV3dEluc3RhbGxEaWFsb2cucHJvdG90eXBlLCBcIl9pbnN0YWxsU3RhdGVcIiwgdm9pZCAwKTtcbl9fZGVjb3JhdGUoW1xuICAgIHN0YXRlKClcbl0sIEV3dEluc3RhbGxEaWFsb2cucHJvdG90eXBlLCBcIl9wcm92aXNpb25Gb3JjZVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgc3RhdGUoKVxuXSwgRXd0SW5zdGFsbERpYWxvZy5wcm90b3R5cGUsIFwiX2Vycm9yXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBzdGF0ZSgpXG5dLCBFd3RJbnN0YWxsRGlhbG9nLnByb3RvdHlwZSwgXCJfYnVzeVwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgc3RhdGUoKVxuXSwgRXd0SW5zdGFsbERpYWxvZy5wcm90b3R5cGUsIFwiX3NzaWRzXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBzdGF0ZSgpXG5dLCBFd3RJbnN0YWxsRGlhbG9nLnByb3RvdHlwZSwgXCJfc2VsZWN0ZWRTc2lkXCIsIHZvaWQgMCk7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoXCJld3QtaW5zdGFsbC1kaWFsb2dcIiwgRXd0SW5zdGFsbERpYWxvZyk7XG4iLCJpbXBvcnQgeyBfX2RlY29yYXRlIH0gZnJvbSBcInRzbGliXCI7XG5pbXBvcnQgeyBMaXRFbGVtZW50LCBodG1sLCBjc3MgfSBmcm9tIFwibGl0XCI7XG5pbXBvcnQgeyBwcm9wZXJ0eSB9IGZyb20gXCJsaXQvZGVjb3JhdG9ycy5qc1wiO1xuY2xhc3MgRXd0UGFnZU1lc3NhZ2UgZXh0ZW5kcyBMaXRFbGVtZW50IHtcbiAgICByZW5kZXIoKSB7XG4gICAgICAgIHJldHVybiBodG1sIGBcbiAgICAgIDxkaXYgY2xhc3M9XCJpY29uXCI+JHt0aGlzLmljb259PC9kaXY+XG4gICAgICAke3RoaXMubGFiZWx9XG4gICAgYDtcbiAgICB9XG59XG5Fd3RQYWdlTWVzc2FnZS5zdHlsZXMgPSBjc3MgYFxuICAgIDpob3N0IHtcbiAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgdGV4dC1hbGlnbjogY2VudGVyO1xuICAgIH1cbiAgICAuaWNvbiB7XG4gICAgICBmb250LXNpemU6IDUwcHg7XG4gICAgICBsaW5lLWhlaWdodDogODBweDtcbiAgICAgIGNvbG9yOiBibGFjaztcbiAgICB9XG4gIGA7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSgpXG5dLCBFd3RQYWdlTWVzc2FnZS5wcm90b3R5cGUsIFwiaWNvblwiLCB2b2lkIDApO1xuX19kZWNvcmF0ZShbXG4gICAgcHJvcGVydHkoKVxuXSwgRXd0UGFnZU1lc3NhZ2UucHJvdG90eXBlLCBcImxhYmVsXCIsIHZvaWQgMCk7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoXCJld3QtcGFnZS1tZXNzYWdlXCIsIEV3dFBhZ2VNZXNzYWdlKTtcbiIsImltcG9ydCB7IF9fZGVjb3JhdGUgfSBmcm9tIFwidHNsaWJcIjtcbmltcG9ydCB7IExpdEVsZW1lbnQsIGh0bWwsIGNzcyB9IGZyb20gXCJsaXRcIjtcbmltcG9ydCB7IHByb3BlcnR5IH0gZnJvbSBcImxpdC9kZWNvcmF0b3JzLmpzXCI7XG5pbXBvcnQgXCIuLi9jb21wb25lbnRzL2V3LWNpcmN1bGFyLXByb2dyZXNzXCI7XG5jbGFzcyBFd3RQYWdlUHJvZ3Jlc3MgZXh0ZW5kcyBMaXRFbGVtZW50IHtcbiAgICByZW5kZXIoKSB7XG4gICAgICAgIHJldHVybiBodG1sIGBcbiAgICAgIDxkaXY+XG4gICAgICAgIDxldy1jaXJjdWxhci1wcm9ncmVzc1xuICAgICAgICAgIGFjdGl2ZVxuICAgICAgICAgID9pbmRldGVybWluYXRlPSR7dGhpcy5wcm9ncmVzcyA9PT0gdW5kZWZpbmVkfVxuICAgICAgICAgIC52YWx1ZT0ke3RoaXMucHJvZ3Jlc3MgIT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgPyB0aGlzLnByb2dyZXNzIC8gMTAwXG4gICAgICAgICAgICA6IHVuZGVmaW5lZH1cbiAgICAgICAgPjwvZXctY2lyY3VsYXItcHJvZ3Jlc3M+XG4gICAgICAgICR7dGhpcy5wcm9ncmVzcyAhPT0gdW5kZWZpbmVkID8gaHRtbCBgPGRpdj4ke3RoaXMucHJvZ3Jlc3N9JTwvZGl2PmAgOiBcIlwifVxuICAgICAgPC9kaXY+XG4gICAgICAke3RoaXMubGFiZWx9XG4gICAgYDtcbiAgICB9XG59XG5Fd3RQYWdlUHJvZ3Jlc3Muc3R5bGVzID0gY3NzIGBcbiAgICA6aG9zdCB7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgICB9XG4gICAgZXctY2lyY3VsYXItcHJvZ3Jlc3Mge1xuICAgICAgbWFyZ2luLWJvdHRvbTogMTZweDtcbiAgICB9XG4gIGA7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSgpXG5dLCBFd3RQYWdlUHJvZ3Jlc3MucHJvdG90eXBlLCBcImxhYmVsXCIsIHZvaWQgMCk7XG5fX2RlY29yYXRlKFtcbiAgICBwcm9wZXJ0eSgpXG5dLCBFd3RQYWdlUHJvZ3Jlc3MucHJvdG90eXBlLCBcInByb2dyZXNzXCIsIHZvaWQgMCk7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoXCJld3QtcGFnZS1wcm9ncmVzc1wiLCBFd3RQYWdlUHJvZ3Jlc3MpO1xuIiwiZXhwb3J0IGNsYXNzIENvbG9yZWRDb25zb2xlIHtcbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXRFbGVtZW50KSB7XG4gICAgICAgIHRoaXMudGFyZ2V0RWxlbWVudCA9IHRhcmdldEVsZW1lbnQ7XG4gICAgICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICAgICAgICBib2xkOiBmYWxzZSxcbiAgICAgICAgICAgIGl0YWxpYzogZmFsc2UsXG4gICAgICAgICAgICB1bmRlcmxpbmU6IGZhbHNlLFxuICAgICAgICAgICAgc3RyaWtldGhyb3VnaDogZmFsc2UsXG4gICAgICAgICAgICBmb3JlZ3JvdW5kQ29sb3I6IG51bGwsXG4gICAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IG51bGwsXG4gICAgICAgICAgICBjYXJyaWFnZVJldHVybjogZmFsc2UsXG4gICAgICAgICAgICBsaW5lczogW10sXG4gICAgICAgICAgICBzZWNyZXQ6IGZhbHNlLFxuICAgICAgICB9O1xuICAgIH1cbiAgICBsb2dzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy50YXJnZXRFbGVtZW50LmlubmVyVGV4dDtcbiAgICB9XG4gICAgcHJvY2Vzc0xpbmUobGluZSkge1xuICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgIGNvbnN0IHJlID0gLyg/OlxcMDMzfFxcXFwwMzMpKD86XFxbKC4qPylbQC1+XXxcXF0uKj8oPzpcXDAwN3xcXDAzM1xcXFwpKS9nO1xuICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgIGNvbnN0IGxpbmVTcGFuID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIik7XG4gICAgICAgIGxpbmVTcGFuLmNsYXNzTGlzdC5hZGQoXCJsaW5lXCIpO1xuICAgICAgICBjb25zdCBhZGRTcGFuID0gKGNvbnRlbnQpID0+IHtcbiAgICAgICAgICAgIGlmIChjb250ZW50ID09PSBcIlwiKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIGNvbnN0IHNwYW4gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlLmJvbGQpXG4gICAgICAgICAgICAgICAgc3Bhbi5jbGFzc0xpc3QuYWRkKFwibG9nLWJvbGRcIik7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5pdGFsaWMpXG4gICAgICAgICAgICAgICAgc3Bhbi5jbGFzc0xpc3QuYWRkKFwibG9nLWl0YWxpY1wiKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlLnVuZGVybGluZSlcbiAgICAgICAgICAgICAgICBzcGFuLmNsYXNzTGlzdC5hZGQoXCJsb2ctdW5kZXJsaW5lXCIpO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUuc3RyaWtldGhyb3VnaClcbiAgICAgICAgICAgICAgICBzcGFuLmNsYXNzTGlzdC5hZGQoXCJsb2ctc3RyaWtldGhyb3VnaFwiKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlLnNlY3JldClcbiAgICAgICAgICAgICAgICBzcGFuLmNsYXNzTGlzdC5hZGQoXCJsb2ctc2VjcmV0XCIpO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUuZm9yZWdyb3VuZENvbG9yICE9PSBudWxsKVxuICAgICAgICAgICAgICAgIHNwYW4uY2xhc3NMaXN0LmFkZChgbG9nLWZnLSR7dGhpcy5zdGF0ZS5mb3JlZ3JvdW5kQ29sb3J9YCk7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5iYWNrZ3JvdW5kQ29sb3IgIT09IG51bGwpXG4gICAgICAgICAgICAgICAgc3Bhbi5jbGFzc0xpc3QuYWRkKGBsb2ctYmctJHt0aGlzLnN0YXRlLmJhY2tncm91bmRDb2xvcn1gKTtcbiAgICAgICAgICAgIHNwYW4uYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoY29udGVudCkpO1xuICAgICAgICAgICAgbGluZVNwYW4uYXBwZW5kQ2hpbGQoc3Bhbik7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5zZWNyZXQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWRhY3RlZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIpO1xuICAgICAgICAgICAgICAgIHJlZGFjdGVkLmNsYXNzTGlzdC5hZGQoXCJsb2ctc2VjcmV0LXJlZGFjdGVkXCIpO1xuICAgICAgICAgICAgICAgIHJlZGFjdGVkLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKFwiW3JlZGFjdGVkXVwiKSk7XG4gICAgICAgICAgICAgICAgbGluZVNwYW4uYXBwZW5kQ2hpbGQocmVkYWN0ZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgY29uc3QgbWF0Y2ggPSByZS5leGVjKGxpbmUpO1xuICAgICAgICAgICAgaWYgKG1hdGNoID09PSBudWxsKVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY29uc3QgaiA9IG1hdGNoLmluZGV4O1xuICAgICAgICAgICAgYWRkU3BhbihsaW5lLnN1YnN0cmluZyhpLCBqKSk7XG4gICAgICAgICAgICBpID0gaiArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgIGlmIChtYXRjaFsxXSA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgZm9yIChjb25zdCBjb2xvckNvZGUgb2YgbWF0Y2hbMV0uc3BsaXQoXCI7XCIpKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChwYXJzZUludChjb2xvckNvZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJlc2V0XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLmJvbGQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUuaXRhbGljID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLnVuZGVybGluZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0ZS5zdHJpa2V0aHJvdWdoID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLmZvcmVncm91bmRDb2xvciA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLmJhY2tncm91bmRDb2xvciA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLnNlY3JldCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUuYm9sZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0ZS5pdGFsaWMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUudW5kZXJsaW5lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLnNlY3JldCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0ZS5zZWNyZXQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDk6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLnN0cmlrZXRocm91Z2ggPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjI6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLmJvbGQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDIzOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0ZS5pdGFsaWMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI0OlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0ZS51bmRlcmxpbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI5OlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0ZS5zdHJpa2V0aHJvdWdoID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUuZm9yZWdyb3VuZENvbG9yID0gXCJibGFja1wiO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzE6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLmZvcmVncm91bmRDb2xvciA9IFwicmVkXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzMjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUuZm9yZWdyb3VuZENvbG9yID0gXCJncmVlblwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzM6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLmZvcmVncm91bmRDb2xvciA9IFwieWVsbG93XCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzNDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUuZm9yZWdyb3VuZENvbG9yID0gXCJibHVlXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzNTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUuZm9yZWdyb3VuZENvbG9yID0gXCJtYWdlbnRhXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUuZm9yZWdyb3VuZENvbG9yID0gXCJjeWFuXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzNzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUuZm9yZWdyb3VuZENvbG9yID0gXCJ3aGl0ZVwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzk6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLmZvcmVncm91bmRDb2xvciA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0MTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUuYmFja2dyb3VuZENvbG9yID0gXCJyZWRcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDQyOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0ZS5iYWNrZ3JvdW5kQ29sb3IgPSBcImdyZWVuXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0MzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUuYmFja2dyb3VuZENvbG9yID0gXCJ5ZWxsb3dcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ0OlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0ZS5iYWNrZ3JvdW5kQ29sb3IgPSBcImJsdWVcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ1OlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0ZS5iYWNrZ3JvdW5kQ29sb3IgPSBcIm1hZ2VudGFcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ2OlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0ZS5iYWNrZ3JvdW5kQ29sb3IgPSBcImN5YW5cIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDQ3OlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0ZS5iYWNrZ3JvdW5kQ29sb3IgPSBcIndoaXRlXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0MDpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUuYmFja2dyb3VuZENvbG9yID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhZGRTcGFuKGxpbmUuc3Vic3RyaW5nKGkpKTtcbiAgICAgICAgcmV0dXJuIGxpbmVTcGFuO1xuICAgIH1cbiAgICBwcm9jZXNzTGluZXMoKSB7XG4gICAgICAgIGNvbnN0IGF0Qm90dG9tID0gdGhpcy50YXJnZXRFbGVtZW50LnNjcm9sbFRvcCA+XG4gICAgICAgICAgICB0aGlzLnRhcmdldEVsZW1lbnQuc2Nyb2xsSGVpZ2h0IC0gdGhpcy50YXJnZXRFbGVtZW50Lm9mZnNldEhlaWdodCAtIDUwO1xuICAgICAgICBjb25zdCBwcmV2Q2FycmlhZ2VSZXR1cm4gPSB0aGlzLnN0YXRlLmNhcnJpYWdlUmV0dXJuO1xuICAgICAgICBjb25zdCBmcmFnbWVudCA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUubGluZXMubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IGxpbmUgb2YgdGhpcy5zdGF0ZS5saW5lcykge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUuY2FycmlhZ2VSZXR1cm4gJiYgbGluZSAhPT0gXCJcXG5cIikge1xuICAgICAgICAgICAgICAgIGlmIChmcmFnbWVudC5jaGlsZEVsZW1lbnRDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICBmcmFnbWVudC5yZW1vdmVDaGlsZChmcmFnbWVudC5sYXN0Q2hpbGQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZyYWdtZW50LmFwcGVuZENoaWxkKHRoaXMucHJvY2Vzc0xpbmUobGluZSkpO1xuICAgICAgICAgICAgdGhpcy5zdGF0ZS5jYXJyaWFnZVJldHVybiA9IGxpbmUuaW5jbHVkZXMoXCJcXHJcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByZXZDYXJyaWFnZVJldHVybiAmJiB0aGlzLnN0YXRlLmxpbmVzWzBdICE9PSBcIlxcblwiKSB7XG4gICAgICAgICAgICB0aGlzLnRhcmdldEVsZW1lbnQucmVwbGFjZUNoaWxkKGZyYWdtZW50LCB0aGlzLnRhcmdldEVsZW1lbnQubGFzdENoaWxkKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMudGFyZ2V0RWxlbWVudC5hcHBlbmRDaGlsZChmcmFnbWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdGF0ZS5saW5lcyA9IFtdO1xuICAgICAgICAvLyBLZWVwIHNjcm9sbCBhdCBib3R0b21cbiAgICAgICAgaWYgKGF0Qm90dG9tKSB7XG4gICAgICAgICAgICB0aGlzLnRhcmdldEVsZW1lbnQuc2Nyb2xsVG9wID0gdGhpcy50YXJnZXRFbGVtZW50LnNjcm9sbEhlaWdodDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhZGRMaW5lKGxpbmUpIHtcbiAgICAgICAgLy8gUHJvY2Vzc2luZyBvZiBsaW5lcyBpcyBkZWZlcnJlZCBmb3IgcGVyZm9ybWFuY2UgcmVhc29uc1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS5saW5lcy5sZW5ndGggPT0gMCkge1xuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLnByb2Nlc3NMaW5lcygpLCAwKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0YXRlLmxpbmVzLnB1c2gobGluZSk7XG4gICAgfVxufVxuZXhwb3J0IGNvbnN0IGNvbG9yZWRDb25zb2xlU3R5bGVzID0gYFxuICAubG9nIHtcbiAgICBmbGV4OiAxO1xuICAgIGJhY2tncm91bmQtY29sb3I6ICMxYzFjMWM7XG4gICAgZm9udC1mYW1pbHk6IFwiU0ZNb25vLVJlZ3VsYXJcIiwgQ29uc29sYXMsIFwiTGliZXJhdGlvbiBNb25vXCIsIE1lbmxvLCBDb3VyaWVyLFxuICAgICAgbW9ub3NwYWNlO1xuICAgIGZvbnQtc2l6ZTogMTJweDtcbiAgICBwYWRkaW5nOiAxNnB4O1xuICAgIG92ZXJmbG93OiBhdXRvO1xuICAgIGxpbmUtaGVpZ2h0OiAxLjQ1O1xuICAgIGJvcmRlci1yYWRpdXM6IDNweDtcbiAgICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7XG4gICAgb3ZlcmZsb3ctd3JhcDogYnJlYWstd29yZDtcbiAgICBjb2xvcjogI2RkZDtcbiAgfVxuXG4gIC5sb2ctYm9sZCB7XG4gICAgZm9udC13ZWlnaHQ6IGJvbGQ7XG4gIH1cbiAgLmxvZy1pdGFsaWMge1xuICAgIGZvbnQtc3R5bGU6IGl0YWxpYztcbiAgfVxuICAubG9nLXVuZGVybGluZSB7XG4gICAgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7XG4gIH1cbiAgLmxvZy1zdHJpa2V0aHJvdWdoIHtcbiAgICB0ZXh0LWRlY29yYXRpb246IGxpbmUtdGhyb3VnaDtcbiAgfVxuICAubG9nLXVuZGVybGluZS5sb2ctc3RyaWtldGhyb3VnaCB7XG4gICAgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmUgbGluZS10aHJvdWdoO1xuICB9XG4gIC5sb2ctc2VjcmV0IHtcbiAgICAtd2Via2l0LXVzZXItc2VsZWN0OiBub25lO1xuICAgIC1tb3otdXNlci1zZWxlY3Q6IG5vbmU7XG4gICAgLW1zLXVzZXItc2VsZWN0OiBub25lO1xuICAgIHVzZXItc2VsZWN0OiBub25lO1xuICB9XG4gIC5sb2ctc2VjcmV0LXJlZGFjdGVkIHtcbiAgICBvcGFjaXR5OiAwO1xuICAgIHdpZHRoOiAxcHg7XG4gICAgZm9udC1zaXplOiAxcHg7XG4gIH1cbiAgLmxvZy1mZy1ibGFjayB7XG4gICAgY29sb3I6IHJnYigxMjgsIDEyOCwgMTI4KTtcbiAgfVxuICAubG9nLWZnLXJlZCB7XG4gICAgY29sb3I6IHJnYigyNTUsIDAsIDApO1xuICB9XG4gIC5sb2ctZmctZ3JlZW4ge1xuICAgIGNvbG9yOiByZ2IoMCwgMjU1LCAwKTtcbiAgfVxuICAubG9nLWZnLXllbGxvdyB7XG4gICAgY29sb3I6IHJnYigyNTUsIDI1NSwgMCk7XG4gIH1cbiAgLmxvZy1mZy1ibHVlIHtcbiAgICBjb2xvcjogcmdiKDAsIDAsIDI1NSk7XG4gIH1cbiAgLmxvZy1mZy1tYWdlbnRhIHtcbiAgICBjb2xvcjogcmdiKDI1NSwgMCwgMjU1KTtcbiAgfVxuICAubG9nLWZnLWN5YW4ge1xuICAgIGNvbG9yOiByZ2IoMCwgMjU1LCAyNTUpO1xuICB9XG4gIC5sb2ctZmctd2hpdGUge1xuICAgIGNvbG9yOiByZ2IoMTg3LCAxODcsIDE4Nyk7XG4gIH1cbiAgLmxvZy1iZy1ibGFjayB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiKDAsIDAsIDApO1xuICB9XG4gIC5sb2ctYmctcmVkIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2IoMjU1LCAwLCAwKTtcbiAgfVxuICAubG9nLWJnLWdyZWVuIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2IoMCwgMjU1LCAwKTtcbiAgfVxuICAubG9nLWJnLXllbGxvdyB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiKDI1NSwgMjU1LCAwKTtcbiAgfVxuICAubG9nLWJnLWJsdWUge1xuICAgIGJhY2tncm91bmQtY29sb3I6IHJnYigwLCAwLCAyNTUpO1xuICB9XG4gIC5sb2ctYmctbWFnZW50YSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiKDI1NSwgMCwgMjU1KTtcbiAgfVxuICAubG9nLWJnLWN5YW4ge1xuICAgIGJhY2tncm91bmQtY29sb3I6IHJnYigwLCAyNTUsIDI1NSk7XG4gIH1cbiAgLmxvZy1iZy13aGl0ZSB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiKDI1NSwgMjU1LCAyNTUpO1xuICB9XG5gO1xuIiwiZXhwb3J0IGNvbnN0IGZpbGVEb3dubG9hZCA9IChocmVmLCBmaWxlbmFtZSA9IFwiXCIpID0+IHtcbiAgICBjb25zdCBhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImFcIik7XG4gICAgYS50YXJnZXQgPSBcIl9ibGFua1wiO1xuICAgIGEuaHJlZiA9IGhyZWY7XG4gICAgYS5kb3dubG9hZCA9IGZpbGVuYW1lO1xuICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG4gICAgYS5kaXNwYXRjaEV2ZW50KG5ldyBNb3VzZUV2ZW50KFwiY2xpY2tcIikpO1xuICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoYSk7XG59O1xuZXhwb3J0IGNvbnN0IHRleHREb3dubG9hZCA9ICh0ZXh0LCBmaWxlbmFtZSA9IFwiXCIpID0+IHtcbiAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW3RleHRdLCB7IHR5cGU6IFwidGV4dC9wbGFpblwiIH0pO1xuICAgIGNvbnN0IHVybCA9IFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYik7XG4gICAgZmlsZURvd25sb2FkKHVybCwgZmlsZW5hbWUpO1xuICAgIHNldFRpbWVvdXQoKCkgPT4gVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpLCAwKTtcbn07XG4iLCJleHBvcnQgY29uc3QgZmlyZUV2ZW50ID0gKGV2ZW50VGFyZ2V0LCB0eXBlLCBcbi8vIEB0cy1pZ25vcmVcbmRldGFpbCwgb3B0aW9ucykgPT4ge1xuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgIGNvbnN0IGV2ZW50ID0gbmV3IEN1c3RvbUV2ZW50KHR5cGUsIHtcbiAgICAgICAgYnViYmxlczogb3B0aW9ucy5idWJibGVzID09PSB1bmRlZmluZWQgPyB0cnVlIDogb3B0aW9ucy5idWJibGVzLFxuICAgICAgICBjYW5jZWxhYmxlOiBCb29sZWFuKG9wdGlvbnMuY2FuY2VsYWJsZSksXG4gICAgICAgIGNvbXBvc2VkOiBvcHRpb25zLmNvbXBvc2VkID09PSB1bmRlZmluZWQgPyB0cnVlIDogb3B0aW9ucy5jb21wb3NlZCxcbiAgICAgICAgZGV0YWlsLFxuICAgIH0pO1xuICAgIGV2ZW50VGFyZ2V0LmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xufTtcbiIsImV4cG9ydCBjbGFzcyBMaW5lQnJlYWtUcmFuc2Zvcm1lciB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuY2h1bmtzID0gXCJcIjtcbiAgICB9XG4gICAgdHJhbnNmb3JtKGNodW5rLCBjb250cm9sbGVyKSB7XG4gICAgICAgIC8vIEFwcGVuZCBuZXcgY2h1bmtzIHRvIGV4aXN0aW5nIGNodW5rcy5cbiAgICAgICAgdGhpcy5jaHVua3MgKz0gY2h1bms7XG4gICAgICAgIC8vIEZvciBlYWNoIGxpbmUgYnJlYWtzIGluIGNodW5rcywgc2VuZCB0aGUgcGFyc2VkIGxpbmVzIG91dC5cbiAgICAgICAgY29uc3QgbGluZXMgPSB0aGlzLmNodW5rcy5zcGxpdCgvXFxyP1xcbi8pO1xuICAgICAgICB0aGlzLmNodW5rcyA9IGxpbmVzLnBvcCgpO1xuICAgICAgICBsaW5lcy5mb3JFYWNoKChsaW5lKSA9PiBjb250cm9sbGVyLmVucXVldWUobGluZSArIFwiXFxyXFxuXCIpKTtcbiAgICB9XG4gICAgZmx1c2goY29udHJvbGxlcikge1xuICAgICAgICAvLyBXaGVuIHRoZSBzdHJlYW0gaXMgY2xvc2VkLCBmbHVzaCBhbnkgcmVtYWluaW5nIGNodW5rcyBvdXQuXG4gICAgICAgIGNvbnRyb2xsZXIuZW5xdWV1ZSh0aGlzLmNodW5rcyk7XG4gICAgfVxufVxuIiwiZXhwb3J0IGNvbnN0IGRvd25sb2FkTWFuaWZlc3QgPSBhc3luYyAobWFuaWZlc3RQYXRoKSA9PiB7XG4gICAgY29uc3QgbWFuaWZlc3RVUkwgPSBuZXcgVVJMKG1hbmlmZXN0UGF0aCwgbG9jYXRpb24udG9TdHJpbmcoKSkudG9TdHJpbmcoKTtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgZmV0Y2gobWFuaWZlc3RVUkwpO1xuICAgIGNvbnN0IG1hbmlmZXN0ID0gYXdhaXQgcmVzcC5qc29uKCk7XG4gICAgaWYgKFwibmV3X2luc3RhbGxfc2tpcF9lcmFzZVwiIGluIG1hbmlmZXN0KSB7XG4gICAgICAgIGNvbnNvbGUud2FybignTWFuaWZlc3Qgb3B0aW9uIFwibmV3X2luc3RhbGxfc2tpcF9lcmFzZVwiIGlzIGRlcHJlY2F0ZWQuIFVzZSBcIm5ld19pbnN0YWxsX3Byb21wdF9lcmFzZVwiIGluc3RlYWQuJyk7XG4gICAgICAgIGlmIChtYW5pZmVzdC5uZXdfaW5zdGFsbF9za2lwX2VyYXNlKSB7XG4gICAgICAgICAgICBtYW5pZmVzdC5uZXdfaW5zdGFsbF9wcm9tcHRfZXJhc2UgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBtYW5pZmVzdDtcbn07XG4iLCJpbXBvcnQgeyBzbGVlcCB9IGZyb20gXCIuL3NsZWVwXCI7XG5leHBvcnQgY29uc3QgaGFyZFJlc2V0ID0gYXN5bmMgKHRyYW5zcG9ydCkgPT4ge1xuICAgIGNvbnNvbGUubG9nKFwiVHJpZ2dlcmluZyByZXNldFwiKTtcbiAgICBhd2FpdCB0cmFuc3BvcnQuZGV2aWNlLnNldFNpZ25hbHMoe1xuICAgICAgICBkYXRhVGVybWluYWxSZWFkeTogZmFsc2UsXG4gICAgICAgIHJlcXVlc3RUb1NlbmQ6IHRydWUsXG4gICAgfSk7XG4gICAgYXdhaXQgc2xlZXAoMjUwKTtcbiAgICBhd2FpdCB0cmFuc3BvcnQuZGV2aWNlLnNldFNpZ25hbHMoe1xuICAgICAgICBkYXRhVGVybWluYWxSZWFkeTogZmFsc2UsXG4gICAgICAgIHJlcXVlc3RUb1NlbmQ6IGZhbHNlLFxuICAgIH0pO1xuICAgIGF3YWl0IHNsZWVwKDI1MCk7XG4gICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgMTAwMCkpO1xufTtcbiIsImV4cG9ydCBjb25zdCBzbGVlcCA9ICh0aW1lKSA9PiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCB0aW1lKSk7XG4iLCJleHBvcnQgY2xhc3MgVGltZXN0YW1wVHJhbnNmb3JtZXIge1xuICAgIHRyYW5zZm9ybShjaHVuaywgY29udHJvbGxlcikge1xuICAgICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoKTtcbiAgICAgICAgY29uc3QgaCA9IGRhdGUuZ2V0SG91cnMoKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsIFwiMFwiKTtcbiAgICAgICAgY29uc3QgbSA9IGRhdGUuZ2V0TWludXRlcygpLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgXCIwXCIpO1xuICAgICAgICBjb25zdCBzID0gZGF0ZS5nZXRTZWNvbmRzKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCBcIjBcIik7XG4gICAgICAgIGNvbnRyb2xsZXIuZW5xdWV1ZShgWyR7aH06JHttfToke3N9XSR7Y2h1bmt9YCk7XG4gICAgfVxufVxuIiwiZXhwb3J0IGNvbnN0IHZlcnNpb24gPSBcIjEwLjEuMVwiO1xuIiwiaW1wb3J0IHsgRVNQRXJyb3IgfSBmcm9tIFwiLi90eXBlcy9lcnJvci5qc1wiO1xuaW1wb3J0IHsgZGVmbGF0ZSwgSW5mbGF0ZSB9IGZyb20gXCJwYWtvXCI7XG5pbXBvcnQgeyBUcmFuc3BvcnQgfSBmcm9tIFwiLi93ZWJzZXJpYWwuanNcIjtcbmltcG9ydCB7IENsYXNzaWNSZXNldCwgQ3VzdG9tUmVzZXQsIEhhcmRSZXNldCwgVXNiSnRhZ1NlcmlhbFJlc2V0IH0gZnJvbSBcIi4vcmVzZXQuanNcIjtcbmltcG9ydCB7IGdldFN0dWJKc29uQnlDaGlwTmFtZSB9IGZyb20gXCIuL3N0dWJGbGFzaGVyLmpzXCI7XG5pbXBvcnQgeyBwYWRUbyB9IGZyb20gXCIuL3V0aWwuanNcIjtcbi8qKlxuICogUmV0dXJuIHRoZSBjaGlwIFJPTSBiYXNlZCBvbiB0aGUgZ2l2ZW4gbWFnaWMgbnVtYmVyXG4gKiBAcGFyYW0ge251bWJlcn0gbWFnaWMgLSBtYWdpYyBoZXggbnVtYmVyIHRvIHNlbGVjdCBST00uXG4gKiBAcmV0dXJucyB7Uk9NfSBUaGUgY2hpcCBST00gY2xhc3MgcmVsYXRlZCB0byBnaXZlbiBtYWdpYyBoZXggbnVtYmVyLlxuICovXG5hc3luYyBmdW5jdGlvbiBtYWdpYzJDaGlwKG1hZ2ljKSB7XG4gICAgc3dpdGNoIChtYWdpYykge1xuICAgICAgICBjYXNlIDB4MDBmMDFkODM6IHtcbiAgICAgICAgICAgIGNvbnN0IHsgRVNQMzJST00gfSA9IGF3YWl0IGltcG9ydChcIi4vdGFyZ2V0cy9lc3AzMi5qc1wiKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRVNQMzJST00oKTtcbiAgICAgICAgfVxuICAgICAgICBjYXNlIDB4YzIxZTA2ZjpcbiAgICAgICAgY2FzZSAweDZmNTEzMDZmOlxuICAgICAgICBjYXNlIDB4N2M0MWEwNmY6IHtcbiAgICAgICAgICAgIGNvbnN0IHsgRVNQMzJDMlJPTSB9ID0gYXdhaXQgaW1wb3J0KFwiLi90YXJnZXRzL2VzcDMyYzIuanNcIik7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEVTUDMyQzJST00oKTtcbiAgICAgICAgfVxuICAgICAgICBjYXNlIDB4NjkyMTUwNmY6XG4gICAgICAgIGNhc2UgMHgxYjMxNTA2ZjpcbiAgICAgICAgY2FzZSAweDQ4ODE2MDZmOlxuICAgICAgICBjYXNlIDB4NDM2MTYwNmY6IHtcbiAgICAgICAgICAgIGNvbnN0IHsgRVNQMzJDM1JPTSB9ID0gYXdhaXQgaW1wb3J0KFwiLi90YXJnZXRzL2VzcDMyYzMuanNcIik7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEVTUDMyQzNST00oKTtcbiAgICAgICAgfVxuICAgICAgICBjYXNlIDB4MmNlMDgwNmY6IHtcbiAgICAgICAgICAgIGNvbnN0IHsgRVNQMzJDNlJPTSB9ID0gYXdhaXQgaW1wb3J0KFwiLi90YXJnZXRzL2VzcDMyYzYuanNcIik7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEVTUDMyQzZST00oKTtcbiAgICAgICAgfVxuICAgICAgICBjYXNlIDB4MjQyMTYwNmY6XG4gICAgICAgIGNhc2UgMHgzM2YwMjA2ZjpcbiAgICAgICAgY2FzZSAweDRmODE2MDZmOiB7XG4gICAgICAgICAgICBjb25zdCB7IEVTUDMyQzYxUk9NIH0gPSBhd2FpdCBpbXBvcnQoXCIuL3RhcmdldHMvZXNwMzJjNjEuanNcIik7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEVTUDMyQzYxUk9NKCk7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAweDExMDE0MDZmOlxuICAgICAgICBjYXNlIDB4NjNlMTQwNmY6XG4gICAgICAgIGNhc2UgMHg1ZmQxNDA2Zjoge1xuICAgICAgICAgICAgY29uc3QgeyBFU1AzMkM1Uk9NIH0gPSBhd2FpdCBpbXBvcnQoXCIuL3RhcmdldHMvZXNwMzJjNS5qc1wiKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRVNQMzJDNVJPTSgpO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgMHhkN2I3M2U4MDoge1xuICAgICAgICAgICAgY29uc3QgeyBFU1AzMkgyUk9NIH0gPSBhd2FpdCBpbXBvcnQoXCIuL3RhcmdldHMvZXNwMzJoMi5qc1wiKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRVNQMzJIMlJPTSgpO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgMHgwOToge1xuICAgICAgICAgICAgY29uc3QgeyBFU1AzMlMzUk9NIH0gPSBhd2FpdCBpbXBvcnQoXCIuL3RhcmdldHMvZXNwMzJzMy5qc1wiKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRVNQMzJTM1JPTSgpO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgMHgwMDAwMDdjNjoge1xuICAgICAgICAgICAgY29uc3QgeyBFU1AzMlMyUk9NIH0gPSBhd2FpdCBpbXBvcnQoXCIuL3RhcmdldHMvZXNwMzJzMi5qc1wiKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRVNQMzJTMlJPTSgpO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgMHhmZmYwYzEwMToge1xuICAgICAgICAgICAgY29uc3QgeyBFU1A4MjY2Uk9NIH0gPSBhd2FpdCBpbXBvcnQoXCIuL3RhcmdldHMvZXNwODI2Ni5qc1wiKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRVNQODI2NlJPTSgpO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgMHgwOlxuICAgICAgICBjYXNlIDB4MGFkZGJhZDA6XG4gICAgICAgIGNhc2UgMHg3MDM5YWQ5OiB7XG4gICAgICAgICAgICBjb25zdCB7IEVTUDMyUDRST00gfSA9IGF3YWl0IGltcG9ydChcIi4vdGFyZ2V0cy9lc3AzMnA0LmpzXCIpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBFU1AzMlA0Uk9NKCk7XG4gICAgICAgIH1cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbn1cbmV4cG9ydCBjbGFzcyBFU1BMb2FkZXIge1xuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIG5ldyBFU1BMb2FkZXIgdG8gcGVyZm9ybSBzZXJpYWwgY29tbXVuaWNhdGlvblxuICAgICAqIHN1Y2ggYXMgcmVhZC93cml0ZSBmbGFzaCBtZW1vcnkgYW5kIHJlZ2lzdGVycyB1c2luZyBhIExvYWRlck9wdGlvbnMgb2JqZWN0LlxuICAgICAqIEBwYXJhbSB7TG9hZGVyT3B0aW9uc30gb3B0aW9ucyAtIExvYWRlck9wdGlvbnMgb2JqZWN0IGFyZ3VtZW50IGZvciBFU1BMb2FkZXIuXG4gICAgICogYGBgXG4gICAgICogY29uc3QgbXlMb2FkZXIgPSBuZXcgRVNQTG9hZGVyKHsgdHJhbnNwb3J0OiBUcmFuc3BvcnQsIGJhdWRyYXRlOiBudW1iZXIsIHRlcm1pbmFsPzogSUVzcExvYWRlclRlcm1pbmFsIH0pO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIF9hLCBfYiwgX2MsIF9kLCBfZSwgX2YsIF9nLCBfaDtcbiAgICAgICAgdGhpcy5FU1BfUkFNX0JMT0NLID0gMHgxODAwO1xuICAgICAgICB0aGlzLkVTUF9GTEFTSF9CRUdJTiA9IDB4MDI7XG4gICAgICAgIHRoaXMuRVNQX0ZMQVNIX0RBVEEgPSAweDAzO1xuICAgICAgICB0aGlzLkVTUF9GTEFTSF9FTkQgPSAweDA0O1xuICAgICAgICB0aGlzLkVTUF9NRU1fQkVHSU4gPSAweDA1O1xuICAgICAgICB0aGlzLkVTUF9NRU1fRU5EID0gMHgwNjtcbiAgICAgICAgdGhpcy5FU1BfTUVNX0RBVEEgPSAweDA3O1xuICAgICAgICB0aGlzLkVTUF9XUklURV9SRUcgPSAweDA5O1xuICAgICAgICB0aGlzLkVTUF9SRUFEX1JFRyA9IDB4MGE7XG4gICAgICAgIHRoaXMuRVNQX1NQSV9BVFRBQ0ggPSAweDBkO1xuICAgICAgICB0aGlzLkVTUF9DSEFOR0VfQkFVRFJBVEUgPSAweDBmO1xuICAgICAgICB0aGlzLkVTUF9GTEFTSF9ERUZMX0JFR0lOID0gMHgxMDtcbiAgICAgICAgdGhpcy5FU1BfRkxBU0hfREVGTF9EQVRBID0gMHgxMTtcbiAgICAgICAgdGhpcy5FU1BfRkxBU0hfREVGTF9FTkQgPSAweDEyO1xuICAgICAgICB0aGlzLkVTUF9TUElfRkxBU0hfTUQ1ID0gMHgxMztcbiAgICAgICAgLy8gT25seSBTdHViIHN1cHBvcnRlZCBjb21tYW5kc1xuICAgICAgICB0aGlzLkVTUF9FUkFTRV9GTEFTSCA9IDB4ZDA7XG4gICAgICAgIHRoaXMuRVNQX0VSQVNFX1JFR0lPTiA9IDB4ZDE7XG4gICAgICAgIHRoaXMuRVNQX1JFQURfRkxBU0ggPSAweGQyO1xuICAgICAgICB0aGlzLkVTUF9SVU5fVVNFUl9DT0RFID0gMHhkMztcbiAgICAgICAgdGhpcy5FU1BfSU1BR0VfTUFHSUMgPSAweGU5O1xuICAgICAgICB0aGlzLkVTUF9DSEVDS1NVTV9NQUdJQyA9IDB4ZWY7XG4gICAgICAgIC8vIFJlc3BvbnNlIGNvZGUocykgc2VudCBieSBST01cbiAgICAgICAgdGhpcy5ST01fSU5WQUxJRF9SRUNWX01TRyA9IDB4MDU7IC8vIHJlc3BvbnNlIGlmIGFuIGludmFsaWQgbWVzc2FnZSBpcyByZWNlaXZlZFxuICAgICAgICB0aGlzLkRFRkFVTFRfVElNRU9VVCA9IDMwMDA7XG4gICAgICAgIHRoaXMuRVJBU0VfUkVHSU9OX1RJTUVPVVRfUEVSX01CID0gMzAwMDA7XG4gICAgICAgIHRoaXMuRVJBU0VfV1JJVEVfVElNRU9VVF9QRVJfTUIgPSA0MDAwMDtcbiAgICAgICAgdGhpcy5NRDVfVElNRU9VVF9QRVJfTUIgPSA4MDAwO1xuICAgICAgICB0aGlzLkNISVBfRVJBU0VfVElNRU9VVCA9IDEyMDAwMDtcbiAgICAgICAgdGhpcy5GTEFTSF9SRUFEX1RJTUVPVVQgPSAxMDAwMDA7XG4gICAgICAgIHRoaXMuTUFYX1RJTUVPVVQgPSB0aGlzLkNISVBfRVJBU0VfVElNRU9VVCAqIDI7XG4gICAgICAgIHRoaXMuQ0hJUF9ERVRFQ1RfTUFHSUNfUkVHX0FERFIgPSAweDQwMDAxMDAwO1xuICAgICAgICB0aGlzLkRFVEVDVEVEX0ZMQVNIX1NJWkVTID0ge1xuICAgICAgICAgICAgMHgxMjogXCIyNTZLQlwiLFxuICAgICAgICAgICAgMHgxMzogXCI1MTJLQlwiLFxuICAgICAgICAgICAgMHgxNDogXCIxTUJcIixcbiAgICAgICAgICAgIDB4MTU6IFwiMk1CXCIsXG4gICAgICAgICAgICAweDE2OiBcIjRNQlwiLFxuICAgICAgICAgICAgMHgxNzogXCI4TUJcIixcbiAgICAgICAgICAgIDB4MTg6IFwiMTZNQlwiLFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLkRFVEVDVEVEX0ZMQVNIX1NJWkVTX05VTSA9IHtcbiAgICAgICAgICAgIDB4MTI6IDI1NixcbiAgICAgICAgICAgIDB4MTM6IDUxMixcbiAgICAgICAgICAgIDB4MTQ6IDEwMjQsXG4gICAgICAgICAgICAweDE1OiAyMDQ4LFxuICAgICAgICAgICAgMHgxNjogNDA5NixcbiAgICAgICAgICAgIDB4MTc6IDgxOTIsXG4gICAgICAgICAgICAweDE4OiAxNjM4NCxcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5VU0JfSlRBR19TRVJJQUxfUElEID0gMHgxMDAxO1xuICAgICAgICB0aGlzLnJvbUJhdWRyYXRlID0gMTE1MjAwO1xuICAgICAgICB0aGlzLmRlYnVnTG9nZ2luZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnN5bmNTdHViRGV0ZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdldCBmbGFzaCBzaXplIGJ5dGVzIGZyb20gZmxhc2ggc2l6ZSBzdHJpbmcuXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBmbGFzaFNpemUgRmxhc2ggU2l6ZSBzdHJpbmdcbiAgICAgICAgICogQHJldHVybnMge251bWJlcn0gRmxhc2ggc2l6ZSBieXRlc1xuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5mbGFzaFNpemVCeXRlcyA9IGZ1bmN0aW9uIChmbGFzaFNpemUpIHtcbiAgICAgICAgICAgIGxldCBmbGFzaFNpemVCID0gLTE7XG4gICAgICAgICAgICBpZiAoZmxhc2hTaXplLmluZGV4T2YoXCJLQlwiKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICBmbGFzaFNpemVCID0gcGFyc2VJbnQoZmxhc2hTaXplLnNsaWNlKDAsIGZsYXNoU2l6ZS5pbmRleE9mKFwiS0JcIikpKSAqIDEwMjQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChmbGFzaFNpemUuaW5kZXhPZihcIk1CXCIpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIGZsYXNoU2l6ZUIgPSBwYXJzZUludChmbGFzaFNpemUuc2xpY2UoMCwgZmxhc2hTaXplLmluZGV4T2YoXCJNQlwiKSkpICogMTAyNCAqIDEwMjQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmxhc2hTaXplQjtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5JU19TVFVCID0gZmFsc2U7XG4gICAgICAgIHRoaXMuRkxBU0hfV1JJVEVfU0laRSA9IDB4NDAwMDtcbiAgICAgICAgdGhpcy50cmFuc3BvcnQgPSBvcHRpb25zLnRyYW5zcG9ydDtcbiAgICAgICAgdGhpcy5iYXVkcmF0ZSA9IG9wdGlvbnMuYmF1ZHJhdGU7XG4gICAgICAgIHRoaXMucmVzZXRDb25zdHJ1Y3RvcnMgPSB7XG4gICAgICAgICAgICBjbGFzc2ljUmVzZXQ6ICh0cmFuc3BvcnQsIHJlc2V0RGVsYXkpID0+IG5ldyBDbGFzc2ljUmVzZXQodHJhbnNwb3J0LCByZXNldERlbGF5KSxcbiAgICAgICAgICAgIGN1c3RvbVJlc2V0OiAodHJhbnNwb3J0LCBzZXF1ZW5jZVN0cmluZykgPT4gbmV3IEN1c3RvbVJlc2V0KHRyYW5zcG9ydCwgc2VxdWVuY2VTdHJpbmcpLFxuICAgICAgICAgICAgaGFyZFJlc2V0OiAodHJhbnNwb3J0LCB1c2luZ1VzYk90ZykgPT4gbmV3IEhhcmRSZXNldCh0cmFuc3BvcnQsIHVzaW5nVXNiT3RnKSxcbiAgICAgICAgICAgIHVzYkpUQUdTZXJpYWxSZXNldDogKHRyYW5zcG9ydCkgPT4gbmV3IFVzYkp0YWdTZXJpYWxSZXNldCh0cmFuc3BvcnQpLFxuICAgICAgICB9O1xuICAgICAgICBpZiAob3B0aW9ucy5zZXJpYWxPcHRpb25zKSB7XG4gICAgICAgICAgICB0aGlzLnNlcmlhbE9wdGlvbnMgPSBvcHRpb25zLnNlcmlhbE9wdGlvbnM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbnMucm9tQmF1ZHJhdGUpIHtcbiAgICAgICAgICAgIHRoaXMucm9tQmF1ZHJhdGUgPSBvcHRpb25zLnJvbUJhdWRyYXRlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLnRlcm1pbmFsKSB7XG4gICAgICAgICAgICB0aGlzLnRlcm1pbmFsID0gb3B0aW9ucy50ZXJtaW5hbDtcbiAgICAgICAgICAgIHRoaXMudGVybWluYWwuY2xlYW4oKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMuZGVidWdMb2dnaW5nICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICB0aGlzLmRlYnVnTG9nZ2luZyA9IG9wdGlvbnMuZGVidWdMb2dnaW5nO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLnBvcnQpIHtcbiAgICAgICAgICAgIHRoaXMudHJhbnNwb3J0ID0gbmV3IFRyYW5zcG9ydChvcHRpb25zLnBvcnQpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5lbmFibGVUcmFjaW5nICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICB0aGlzLnRyYW5zcG9ydC50cmFjaW5nID0gb3B0aW9ucy5lbmFibGVUcmFjaW5nO1xuICAgICAgICB9XG4gICAgICAgIGlmICgoX2EgPSBvcHRpb25zLnJlc2V0Q29uc3RydWN0b3JzKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuY2xhc3NpY1Jlc2V0KSB7XG4gICAgICAgICAgICB0aGlzLnJlc2V0Q29uc3RydWN0b3JzLmNsYXNzaWNSZXNldCA9IChfYiA9IG9wdGlvbnMucmVzZXRDb25zdHJ1Y3RvcnMpID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5jbGFzc2ljUmVzZXQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChfYyA9IG9wdGlvbnMucmVzZXRDb25zdHJ1Y3RvcnMpID09PSBudWxsIHx8IF9jID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYy5jdXN0b21SZXNldCkge1xuICAgICAgICAgICAgdGhpcy5yZXNldENvbnN0cnVjdG9ycy5jdXN0b21SZXNldCA9IChfZCA9IG9wdGlvbnMucmVzZXRDb25zdHJ1Y3RvcnMpID09PSBudWxsIHx8IF9kID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZC5jdXN0b21SZXNldDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKF9lID0gb3B0aW9ucy5yZXNldENvbnN0cnVjdG9ycykgPT09IG51bGwgfHwgX2UgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9lLmhhcmRSZXNldCkge1xuICAgICAgICAgICAgdGhpcy5yZXNldENvbnN0cnVjdG9ycy5oYXJkUmVzZXQgPSAoX2YgPSBvcHRpb25zLnJlc2V0Q29uc3RydWN0b3JzKSA9PT0gbnVsbCB8fCBfZiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2YuaGFyZFJlc2V0O1xuICAgICAgICB9XG4gICAgICAgIGlmICgoX2cgPSBvcHRpb25zLnJlc2V0Q29uc3RydWN0b3JzKSA9PT0gbnVsbCB8fCBfZyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2cudXNiSlRBR1NlcmlhbFJlc2V0KSB7XG4gICAgICAgICAgICB0aGlzLnJlc2V0Q29uc3RydWN0b3JzLnVzYkpUQUdTZXJpYWxSZXNldCA9IChfaCA9IG9wdGlvbnMucmVzZXRDb25zdHJ1Y3RvcnMpID09PSBudWxsIHx8IF9oID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfaC51c2JKVEFHU2VyaWFsUmVzZXQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pbmZvKFwiZXNwdG9vbC5qc1wiKTtcbiAgICAgICAgdGhpcy5pbmZvKFwiU2VyaWFsIHBvcnQgXCIgKyB0aGlzLnRyYW5zcG9ydC5nZXRJbmZvKCkpO1xuICAgIH1cbiAgICBfc2xlZXAobXMpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFdyaXRlIHRvIEVTUCBMb2FkZXIgY29uc3RydWN0b3IncyB0ZXJtaW5hbCB3aXRoIG9yIHdpdGhvdXQgbmV3IGxpbmUuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIFN0cmluZyB0byB3cml0ZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHdpdGhOZXdsaW5lIC0gQWRkIG5ldyBsaW5lIGF0IHRoZSBlbmQgP1xuICAgICAqL1xuICAgIHdyaXRlKHN0ciwgd2l0aE5ld2xpbmUgPSB0cnVlKSB7XG4gICAgICAgIGlmICh0aGlzLnRlcm1pbmFsKSB7XG4gICAgICAgICAgICBpZiAod2l0aE5ld2xpbmUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRlcm1pbmFsLndyaXRlTGluZShzdHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXJtaW5hbC53cml0ZShzdHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKHN0cik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogV3JpdGUgZXJyb3IgbWVzc2FnZSB0byBFU1AgTG9hZGVyIGNvbnN0cnVjdG9yJ3MgdGVybWluYWwgd2l0aCBvciB3aXRob3V0IG5ldyBsaW5lLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBTdHJpbmcgdG8gd3JpdGUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSB3aXRoTmV3bGluZSAtIEFkZCBuZXcgbGluZSBhdCB0aGUgZW5kID9cbiAgICAgKi9cbiAgICBlcnJvcihzdHIsIHdpdGhOZXdsaW5lID0gdHJ1ZSkge1xuICAgICAgICB0aGlzLndyaXRlKGBFcnJvcjogJHtzdHJ9YCwgd2l0aE5ld2xpbmUpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBXcml0ZSBpbmZvcm1hdGlvbiBtZXNzYWdlIHRvIEVTUCBMb2FkZXIgY29uc3RydWN0b3IncyB0ZXJtaW5hbCB3aXRoIG9yIHdpdGhvdXQgbmV3IGxpbmUuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIFN0cmluZyB0byB3cml0ZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHdpdGhOZXdsaW5lIC0gQWRkIG5ldyBsaW5lIGF0IHRoZSBlbmQgP1xuICAgICAqL1xuICAgIGluZm8oc3RyLCB3aXRoTmV3bGluZSA9IHRydWUpIHtcbiAgICAgICAgdGhpcy53cml0ZShzdHIsIHdpdGhOZXdsaW5lKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogV3JpdGUgZGVidWcgbWVzc2FnZSB0byBFU1AgTG9hZGVyIGNvbnN0cnVjdG9yJ3MgdGVybWluYWwgd2l0aCBvciB3aXRob3V0IG5ldyBsaW5lLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBTdHJpbmcgdG8gd3JpdGUuXG4gICAgICogQHBhcmFtIHtib29sZWFufSB3aXRoTmV3bGluZSAtIEFkZCBuZXcgbGluZSBhdCB0aGUgZW5kID9cbiAgICAgKi9cbiAgICBkZWJ1ZyhzdHIsIHdpdGhOZXdsaW5lID0gdHJ1ZSkge1xuICAgICAgICBpZiAodGhpcy5kZWJ1Z0xvZ2dpbmcpIHtcbiAgICAgICAgICAgIHRoaXMud3JpdGUoYERlYnVnOiAke3N0cn1gLCB3aXRoTmV3bGluZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29udmVydCBzaG9ydCBpbnRlZ2VyIHRvIGJ5dGUgYXJyYXlcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gaSAtIE51bWJlciB0byBjb252ZXJ0LlxuICAgICAqIEByZXR1cm5zIHtVaW50OEFycmF5fSBCeXRlIGFycmF5LlxuICAgICAqL1xuICAgIF9zaG9ydFRvQnl0ZWFycmF5KGkpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFtpICYgMHhmZiwgKGkgPj4gOCkgJiAweGZmXSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENvbnZlcnQgYW4gaW50ZWdlciB0byBieXRlIGFycmF5XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGkgLSBOdW1iZXIgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7Uk9NfSBUaGUgY2hpcCBST00gY2xhc3MgcmVsYXRlZCB0byBnaXZlbiBtYWdpYyBoZXggbnVtYmVyLlxuICAgICAqL1xuICAgIF9pbnRUb0J5dGVBcnJheShpKSB7XG4gICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShbaSAmIDB4ZmYsIChpID4+IDgpICYgMHhmZiwgKGkgPj4gMTYpICYgMHhmZiwgKGkgPj4gMjQpICYgMHhmZl0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IGEgYnl0ZSBhcnJheSB0byBzaG9ydCBpbnRlZ2VyLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBpIC0gTnVtYmVyIHRvIGNvbnZlcnQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGogLSBOdW1iZXIgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm4gYSBzaG9ydCBpbnRlZ2VyIG51bWJlci5cbiAgICAgKi9cbiAgICBfYnl0ZUFycmF5VG9TaG9ydChpLCBqKSB7XG4gICAgICAgIHJldHVybiBpIHwgKGogPj4gOCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENvbnZlcnQgYSBieXRlIGFycmF5IHRvIGludGVnZXIuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGkgLSBOdW1iZXIgdG8gY29udmVydC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gaiAtIE51bWJlciB0byBjb252ZXJ0LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBrIC0gTnVtYmVyIHRvIGNvbnZlcnQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGwgLSBOdW1iZXIgdG8gY29udmVydC5cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm4gYSBpbnRlZ2VyIG51bWJlci5cbiAgICAgKi9cbiAgICBfYnl0ZUFycmF5VG9JbnQoaSwgaiwgaywgbCkge1xuICAgICAgICByZXR1cm4gaSB8IChqIDw8IDgpIHwgKGsgPDwgMTYpIHwgKGwgPDwgMjQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBcHBlbmQgYSBidWZmZXIgYXJyYXkgYWZ0ZXIgYW5vdGhlciBidWZmZXIgYXJyYXlcbiAgICAgKiBAcGFyYW0ge0FycmF5QnVmZmVyfSBidWZmZXIxIC0gRmlyc3QgYXJyYXkgYnVmZmVyLlxuICAgICAqIEBwYXJhbSB7QXJyYXlCdWZmZXJ9IGJ1ZmZlcjIgLSBtYWdpYyBoZXggbnVtYmVyIHRvIHNlbGVjdCBST00uXG4gICAgICogQHJldHVybnMge0FycmF5QnVmZmVyTGlrZX0gUmV0dXJuIGFuIGFycmF5IGJ1ZmZlci5cbiAgICAgKi9cbiAgICBfYXBwZW5kQnVmZmVyKGJ1ZmZlcjEsIGJ1ZmZlcjIpIHtcbiAgICAgICAgY29uc3QgdG1wID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyMS5ieXRlTGVuZ3RoICsgYnVmZmVyMi5ieXRlTGVuZ3RoKTtcbiAgICAgICAgdG1wLnNldChuZXcgVWludDhBcnJheShidWZmZXIxKSwgMCk7XG4gICAgICAgIHRtcC5zZXQobmV3IFVpbnQ4QXJyYXkoYnVmZmVyMiksIGJ1ZmZlcjEuYnl0ZUxlbmd0aCk7XG4gICAgICAgIHJldHVybiB0bXAuYnVmZmVyO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBcHBlbmQgYSBidWZmZXIgYXJyYXkgYWZ0ZXIgYW5vdGhlciBidWZmZXIgYXJyYXlcbiAgICAgKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGFycjEgLSBGaXJzdCBhcnJheSBidWZmZXIuXG4gICAgICogQHBhcmFtIHtVaW50OEFycmF5fSBhcnIyIC0gbWFnaWMgaGV4IG51bWJlciB0byBzZWxlY3QgUk9NLlxuICAgICAqIEByZXR1cm5zIHtVaW50OEFycmF5fSBSZXR1cm4gYSA4IGJpdCB1bnNpZ25lZCBhcnJheS5cbiAgICAgKi9cbiAgICBfYXBwZW5kQXJyYXkoYXJyMSwgYXJyMikge1xuICAgICAgICBjb25zdCBjID0gbmV3IFVpbnQ4QXJyYXkoYXJyMS5sZW5ndGggKyBhcnIyLmxlbmd0aCk7XG4gICAgICAgIGMuc2V0KGFycjEsIDApO1xuICAgICAgICBjLnNldChhcnIyLCBhcnIxLmxlbmd0aCk7XG4gICAgICAgIHJldHVybiBjO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IGEgdW5zaWduZWQgOCBiaXQgaW50ZWdlciBhcnJheSB0byBieXRlIHN0cmluZy5cbiAgICAgKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IHU4QXJyYXkgLSBtYWdpYyBoZXggbnVtYmVyIHRvIHNlbGVjdCBST00uXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJuIHRoZSBlcXVpdmFsZW50IHN0cmluZy5cbiAgICAgKi9cbiAgICB1aThUb0JzdHIodThBcnJheSkge1xuICAgICAgICBsZXQgYlN0ciA9IFwiXCI7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdThBcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYlN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHU4QXJyYXlbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBiU3RyO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IGEgYnl0ZSBzdHJpbmcgdG8gdW5zaWduZWQgOCBiaXQgaW50ZWdlciBhcnJheS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gYlN0ciAtIGJpbmFyeSBzdHJpbmcgaW5wdXRcbiAgICAgKiBAcmV0dXJucyB7VWludDhBcnJheX0gUmV0dXJuIGEgOCBiaXQgdW5zaWduZWQgaW50ZWdlciBhcnJheS5cbiAgICAgKi9cbiAgICBic3RyVG9VaTgoYlN0cikge1xuICAgICAgICBjb25zdCB1OEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoYlN0ci5sZW5ndGgpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJTdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHU4QXJyYXlbaV0gPSBiU3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHU4QXJyYXk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEZsdXNoIHRoZSBzZXJpYWwgaW5wdXQgYnkgcmF3IHJlYWQgd2l0aCAyMDAgbXMgdGltZW91dC5cbiAgICAgKi9cbiAgICBhc3luYyBmbHVzaElucHV0KCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy50cmFuc3BvcnQuZmx1c2hJbnB1dCgpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICB0aGlzLmVycm9yKGUubWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogVXNlIHRoZSBkZXZpY2Ugc2VyaWFsIHBvcnQgcmVhZCBmdW5jdGlvbiB3aXRoIGdpdmVuIHRpbWVvdXQgdG8gY3JlYXRlIGEgdmFsaWQgcGFja2V0LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvcCBPcGVyYXRpb24gbnVtYmVyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHRpbWVvdXQgdGltZW91dCBudW1iZXIgaW4gbWlsbGlzZWNvbmRzXG4gICAgICogQHJldHVybnMge1tudW1iZXIsIFVpbnQ4QXJyYXldfSB2YWxpZCByZXNwb25zZSBwYWNrZXQuXG4gICAgICovXG4gICAgYXN5bmMgcmVhZFBhY2tldChvcCA9IG51bGwsIHRpbWVvdXQgPSB0aGlzLkRFRkFVTFRfVElNRU9VVCkge1xuICAgICAgICAvLyBDaGVjayB1cC10byBuZXh0IDEwMCBwYWNrZXRzIGZvciB2YWxpZCByZXNwb25zZSBwYWNrZXRcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxMDA7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgeyB2YWx1ZTogcCB9ID0gYXdhaXQgdGhpcy50cmFuc3BvcnQucmVhZCh0aW1lb3V0KS5uZXh0KCk7XG4gICAgICAgICAgICBpZiAoIXAgfHwgcC5sZW5ndGggPCA4KSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXNwID0gcFswXTtcbiAgICAgICAgICAgIGlmIChyZXNwICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvcFJldCA9IHBbMV07XG4gICAgICAgICAgICBjb25zdCB2YWwgPSB0aGlzLl9ieXRlQXJyYXlUb0ludChwWzRdLCBwWzVdLCBwWzZdLCBwWzddKTtcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBwLnNsaWNlKDgpO1xuICAgICAgICAgICAgaWYgKHJlc3AgPT0gMSkge1xuICAgICAgICAgICAgICAgIGlmIChvcCA9PSBudWxsIHx8IG9wUmV0ID09IG9wKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbdmFsLCBkYXRhXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZGF0YVswXSAhPSAwICYmIGRhdGFbMV0gPT0gdGhpcy5ST01fSU5WQUxJRF9SRUNWX01TRykge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmZsdXNoSW5wdXQoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVTUEVycm9yKFwidW5zdXBwb3J0ZWQgY29tbWFuZCBlcnJvclwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IEVTUEVycm9yKFwiaW52YWxpZCByZXNwb25zZVwiKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogV3JpdGUgYSBzZXJpYWwgY29tbWFuZCB0byB0aGUgY2hpcFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvcCAtIE9wZXJhdGlvbiBudW1iZXJcbiAgICAgKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGRhdGEgLSBVbnNpZ25lZCA4IGJpdCBhcnJheVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBjaGsgLSBjaGFubmVsIG51bWJlclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gd2FpdFJlc3BvbnNlIC0gd2FpdCBmb3IgcmVzcG9uc2UgP1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB0aW1lb3V0IC0gdGltZW91dCBudW1iZXIgaW4gbWlsbGlzZWNvbmRzXG4gICAgICogQHJldHVybnMge1Byb21pc2U8W251bWJlciwgVWludDhBcnJheV0+fSBSZXR1cm4gYSBudW1iZXIgYW5kIGEgOCBiaXQgdW5zaWduZWQgaW50ZWdlciBhcnJheS5cbiAgICAgKi9cbiAgICBhc3luYyBjb21tYW5kKG9wID0gbnVsbCwgZGF0YSA9IG5ldyBVaW50OEFycmF5KDApLCBjaGsgPSAwLCB3YWl0UmVzcG9uc2UgPSB0cnVlLCB0aW1lb3V0ID0gdGhpcy5ERUZBVUxUX1RJTUVPVVQpIHtcbiAgICAgICAgaWYgKG9wICE9IG51bGwpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnRyYW5zcG9ydC50cmFjaW5nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50cmFuc3BvcnQudHJhY2UoYGNvbW1hbmQgb3A6MHgke29wLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCBcIjBcIil9IGRhdGEgbGVuPSR7ZGF0YS5sZW5ndGh9IHdhaXRfcmVzcG9uc2U9JHt3YWl0UmVzcG9uc2UgPyAxIDogMH0gdGltZW91dD0keyh0aW1lb3V0IC8gMTAwMCkudG9GaXhlZCgzKX0gZGF0YT0ke3RoaXMudHJhbnNwb3J0LmhleENvbnZlcnQoZGF0YSl9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBwa3QgPSBuZXcgVWludDhBcnJheSg4ICsgZGF0YS5sZW5ndGgpO1xuICAgICAgICAgICAgcGt0WzBdID0gMHgwMDtcbiAgICAgICAgICAgIHBrdFsxXSA9IG9wO1xuICAgICAgICAgICAgcGt0WzJdID0gdGhpcy5fc2hvcnRUb0J5dGVhcnJheShkYXRhLmxlbmd0aClbMF07XG4gICAgICAgICAgICBwa3RbM10gPSB0aGlzLl9zaG9ydFRvQnl0ZWFycmF5KGRhdGEubGVuZ3RoKVsxXTtcbiAgICAgICAgICAgIHBrdFs0XSA9IHRoaXMuX2ludFRvQnl0ZUFycmF5KGNoaylbMF07XG4gICAgICAgICAgICBwa3RbNV0gPSB0aGlzLl9pbnRUb0J5dGVBcnJheShjaGspWzFdO1xuICAgICAgICAgICAgcGt0WzZdID0gdGhpcy5faW50VG9CeXRlQXJyYXkoY2hrKVsyXTtcbiAgICAgICAgICAgIHBrdFs3XSA9IHRoaXMuX2ludFRvQnl0ZUFycmF5KGNoaylbM107XG4gICAgICAgICAgICBsZXQgaTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcGt0WzggKyBpXSA9IGRhdGFbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnRyYW5zcG9ydC53cml0ZShwa3QpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghd2FpdFJlc3BvbnNlKSB7XG4gICAgICAgICAgICByZXR1cm4gWzAsIG5ldyBVaW50OEFycmF5KDApXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yZWFkUGFja2V0KG9wLCB0aW1lb3V0KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVhZCBhIHJlZ2lzdGVyIGZyb20gY2hpcC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYWRkciAtIFJlZ2lzdGVyIGFkZHJlc3MgbnVtYmVyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHRpbWVvdXQgLSBUaW1lb3V0IGluIG1pbGxpc2Vjb25kcyAoRGVmYXVsdDogMzAwMG1zKVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IC0gQ29tbWFuZCBudW1iZXIgdmFsdWVcbiAgICAgKi9cbiAgICBhc3luYyByZWFkUmVnKGFkZHIsIHRpbWVvdXQgPSB0aGlzLkRFRkFVTFRfVElNRU9VVCkge1xuICAgICAgICBjb25zdCBwa3QgPSB0aGlzLl9pbnRUb0J5dGVBcnJheShhZGRyKTtcbiAgICAgICAgY29uc3QgdmFsID0gYXdhaXQgdGhpcy5jb21tYW5kKHRoaXMuRVNQX1JFQURfUkVHLCBwa3QsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB0aW1lb3V0KTtcbiAgICAgICAgcmV0dXJuIHZhbFswXTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogV3JpdGUgYSBudW1iZXIgdmFsdWUgdG8gcmVnaXN0ZXIgYWRkcmVzcyBpbiBjaGlwLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBhZGRyIC0gUmVnaXN0ZXIgYWRkcmVzcyBudW1iZXJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgLSBOdW1iZXIgdmFsdWUgdG8gd3JpdGUgaW4gcmVnaXN0ZXJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbWFzayAtIEhleCBudW1iZXIgZm9yIG1hc2tcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZGVsYXlVcyBEZWxheSBudW1iZXJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZGVsYXlBZnRlclVzIERlbGF5IGFmdGVyIHByZXZpb3VzIGRlbGF5XG4gICAgICovXG4gICAgYXN5bmMgd3JpdGVSZWcoYWRkciwgdmFsdWUsIG1hc2sgPSAweGZmZmZmZmZmLCBkZWxheVVzID0gMCwgZGVsYXlBZnRlclVzID0gMCkge1xuICAgICAgICBsZXQgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkodGhpcy5faW50VG9CeXRlQXJyYXkoYWRkciksIHRoaXMuX2ludFRvQnl0ZUFycmF5KHZhbHVlKSk7XG4gICAgICAgIHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHBrdCwgdGhpcy5faW50VG9CeXRlQXJyYXkobWFzaykpO1xuICAgICAgICBwa3QgPSB0aGlzLl9hcHBlbmRBcnJheShwa3QsIHRoaXMuX2ludFRvQnl0ZUFycmF5KGRlbGF5VXMpKTtcbiAgICAgICAgaWYgKGRlbGF5QWZ0ZXJVcyA+IDApIHtcbiAgICAgICAgICAgIHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHBrdCwgdGhpcy5faW50VG9CeXRlQXJyYXkodGhpcy5jaGlwLlVBUlRfREFURV9SRUdfQUREUikpO1xuICAgICAgICAgICAgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkocGt0LCB0aGlzLl9pbnRUb0J5dGVBcnJheSgwKSk7XG4gICAgICAgICAgICBwa3QgPSB0aGlzLl9hcHBlbmRBcnJheShwa3QsIHRoaXMuX2ludFRvQnl0ZUFycmF5KDApKTtcbiAgICAgICAgICAgIHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHBrdCwgdGhpcy5faW50VG9CeXRlQXJyYXkoZGVsYXlBZnRlclVzKSk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgdGhpcy5jaGVja0NvbW1hbmQoXCJ3cml0ZSB0YXJnZXQgbWVtb3J5XCIsIHRoaXMuRVNQX1dSSVRFX1JFRywgcGt0KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3luYyBjaGlwIGJ5IHNlbmRpbmcgc3luYyBjb21tYW5kLlxuICAgICAqIEByZXR1cm5zIHtbbnVtYmVyLCBVaW50OEFycmF5XX0gQ29tbWFuZCByZXN1bHRcbiAgICAgKi9cbiAgICBhc3luYyBzeW5jKCkge1xuICAgICAgICB0aGlzLmRlYnVnKFwiU3luY1wiKTtcbiAgICAgICAgY29uc3QgY21kID0gbmV3IFVpbnQ4QXJyYXkoMzYpO1xuICAgICAgICBsZXQgaTtcbiAgICAgICAgY21kWzBdID0gMHgwNztcbiAgICAgICAgY21kWzFdID0gMHgwNztcbiAgICAgICAgY21kWzJdID0gMHgxMjtcbiAgICAgICAgY21kWzNdID0gMHgyMDtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDMyOyBpKyspIHtcbiAgICAgICAgICAgIGNtZFs0ICsgaV0gPSAweDU1O1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsZXQgcmVzcCA9IGF3YWl0IHRoaXMuY29tbWFuZCgweDA4LCBjbWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCAxMDApO1xuICAgICAgICAgICAgLy8gUk9NIGJvb3Rsb2FkZXJzIHNlbmQgc29tZSBub24temVybyBcInZhbFwiIHJlc3BvbnNlLiBUaGUgZmxhc2hlciBzdHViIHNlbmRzIDAuXG4gICAgICAgICAgICAvLyBJZiB3ZSByZWNlaXZlIDAgdGhlbiBpdCBwcm9iYWJseSBpbmRpY2F0ZXMgdGhhdCB0aGUgY2hpcCB3YXNuJ3Qgb3IgY291bGRuJ3QgYmVcbiAgICAgICAgICAgIC8vIHJlc2V0IHByb3Blcmx5IGFuZCBlc3B0b29sIGlzIHRhbGtpbmcgdG8gdGhlIGZsYXNoZXIgc3R1Yi5cbiAgICAgICAgICAgIHRoaXMuc3luY1N0dWJEZXRlY3RlZCA9IHJlc3BbMF0gPT09IDA7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDc7IGkrKykge1xuICAgICAgICAgICAgICAgIHJlc3AgPSBhd2FpdCB0aGlzLmNvbW1hbmQoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnN5bmNTdHViRGV0ZWN0ZWQgPSB0aGlzLnN5bmNTdHViRGV0ZWN0ZWQgJiYgcmVzcFswXSA9PT0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXNwO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICB0aGlzLmRlYnVnKFwiU3luYyBlcnIgXCIgKyBlKTtcbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogQXR0ZW1wdCB0byBjb25uZWN0IHRvIHRoZSBjaGlwIGJ5IHNlbmRpbmcgYSByZXNldCBzZXF1ZW5jZSBhbmQgbGF0ZXIgYSBzeW5jIGNvbW1hbmQuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1vZGUgLSBSZXNldCBtb2RlIHRvIHVzZVxuICAgICAqIEBwYXJhbSB7UmVzZXRTdHJhdGVneX0gcmVzZXRTdHJhdGVneSAtIFJlc2V0IHN0cmF0ZWd5IGNsYXNzIHRvIHVzZSBmb3IgY29ubmVjdFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IC0gUmV0dXJucyAnc3VjY2Vzcycgb3IgJ2Vycm9yJyBtZXNzYWdlLlxuICAgICAqL1xuICAgIGFzeW5jIF9jb25uZWN0QXR0ZW1wdChtb2RlID0gXCJkZWZhdWx0X3Jlc2V0XCIsIHJlc2V0U3RyYXRlZ3kpIHtcbiAgICAgICAgdGhpcy5kZWJ1ZyhcIl9jb25uZWN0X2F0dGVtcHQgXCIgKyBtb2RlKTtcbiAgICAgICAgaWYgKHJlc2V0U3RyYXRlZ3kpIHtcbiAgICAgICAgICAgIGF3YWl0IHJlc2V0U3RyYXRlZ3kucmVzZXQoKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB3YWl0aW5nQnl0ZXMgPSB0aGlzLnRyYW5zcG9ydC5pbldhaXRpbmcoKTtcbiAgICAgICAgY29uc3QgcmVhZEJ5dGVzID0gYXdhaXQgdGhpcy50cmFuc3BvcnQubmV3UmVhZCh3YWl0aW5nQnl0ZXMgPiAwID8gd2FpdGluZ0J5dGVzIDogMSwgdGhpcy5ERUZBVUxUX1RJTUVPVVQpO1xuICAgICAgICBjb25zdCBiaW5hcnlTdHJpbmcgPSBBcnJheS5mcm9tKHJlYWRCeXRlcywgKGJ5dGUpID0+IFN0cmluZy5mcm9tQ2hhckNvZGUoYnl0ZSkpLmpvaW4oXCJcIik7XG4gICAgICAgIGNvbnN0IHJlZ2V4ID0gL2Jvb3Q6KDB4WzAtOWEtZkEtRl0rKSguKndhaXRpbmcgZm9yIGRvd25sb2FkKT8vO1xuICAgICAgICBjb25zdCBtYXRjaCA9IGJpbmFyeVN0cmluZy5tYXRjaChyZWdleCk7XG4gICAgICAgIGxldCBib290TG9nRGV0ZWN0ZWQgPSBmYWxzZSwgYm9vdE1vZGUgPSBcIlwiLCBkb3dubG9hZE1vZGUgPSBmYWxzZTtcbiAgICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgICAgICBib290TG9nRGV0ZWN0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgYm9vdE1vZGUgPSBtYXRjaFsxXTtcbiAgICAgICAgICAgIGRvd25sb2FkTW9kZSA9ICEhbWF0Y2hbMl07XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGxhc3RFcnJvciA9IFwiXCI7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNTsgaSsrKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGVidWcoYFN5bmMgY29ubmVjdCBhdHRlbXB0ICR7aX1gKTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5zeW5jKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5kZWJ1ZyhyZXNwWzBdLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIHJldHVybiBcInN1Y2Nlc3NcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHRoaXMuZGVidWcoYEVycm9yIGF0IHN5bmMgJHtlcnJvcn1gKTtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBsYXN0RXJyb3IgPSBlcnJvci5tZXNzYWdlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgZXJyb3IgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbGFzdEVycm9yID0gZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsYXN0RXJyb3IgPSBKU09OLnN0cmluZ2lmeShlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChib290TG9nRGV0ZWN0ZWQpIHtcbiAgICAgICAgICAgIGxhc3RFcnJvciA9IGBXcm9uZyBib290IG1vZGUgZGV0ZWN0ZWQgKCR7Ym9vdE1vZGV9KS5cbiAgICAgICAgVGhpcyBjaGlwIG5lZWRzIHRvIGJlIGluIGRvd25sb2FkIG1vZGUuYDtcbiAgICAgICAgICAgIGlmIChkb3dubG9hZE1vZGUpIHtcbiAgICAgICAgICAgICAgICBsYXN0RXJyb3IgPSBgRG93bmxvYWQgbW9kZSBzdWNjZXNzZnVsbHkgZGV0ZWN0ZWQsIGJ1dCBnZXR0aW5nIG5vIHN5bmMgcmVwbHk6XG4gICAgICAgICAgIFRoZSBzZXJpYWwgVFggcGF0aCBzZWVtcyB0byBiZSBkb3duLmA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxhc3RFcnJvcjtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0cyBhIHNlcXVlbmNlIG9mIHJlc2V0IHN0cmF0ZWdpZXMgYmFzZWQgb24gdGhlIE9TLFxuICAgICAqIHVzZWQgRVNQIGNoaXAsIGV4dGVybmFsIHNldHRpbmdzLCBhbmQgZW52aXJvbm1lbnQgdmFyaWFibGVzLlxuICAgICAqIFJldHVybnMgYSB0dXBsZSBvZiBvbmUgb3IgbW9yZSByZXNldCBzdHJhdGVnaWVzIHRvIGJlIHRyaWVkIHNlcXVlbnRpYWxseS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbW9kZSAtIFJlc2V0IG1vZGUgdG8gdXNlXG4gICAgICogQHJldHVybnMge1Jlc2V0U3RyYXRlZ3lbXX0gLSBBcnJheSBvZiByZXNldCBzdHJhdGVnaWVzXG4gICAgICovXG4gICAgY29uc3RydWN0UmVzZXRTZXF1ZW5jZShtb2RlKSB7XG4gICAgICAgIGlmIChtb2RlICE9PSBcIm5vX3Jlc2V0XCIpIHtcbiAgICAgICAgICAgIGlmIChtb2RlID09PSBcInVzYl9yZXNldFwiIHx8IHRoaXMudHJhbnNwb3J0LmdldFBpZCgpID09PSB0aGlzLlVTQl9KVEFHX1NFUklBTF9QSUQpIHtcbiAgICAgICAgICAgICAgICAvLyBDdXN0b20gcmVzZXQgc2VxdWVuY2UsIHdoaWNoIGlzIHJlcXVpcmVkIHdoZW4gdGhlIGRldmljZVxuICAgICAgICAgICAgICAgIC8vIGlzIGNvbm5lY3RpbmcgdmlhIGl0cyBVU0ItSlRBRy1TZXJpYWwgcGVyaXBoZXJhbFxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlc2V0Q29uc3RydWN0b3JzLnVzYkpUQUdTZXJpYWxSZXNldCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRlYnVnKFwidXNpbmcgVVNCIEpUQUcgU2VyaWFsIFJlc2V0XCIpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gW3RoaXMucmVzZXRDb25zdHJ1Y3RvcnMudXNiSlRBR1NlcmlhbFJlc2V0KHRoaXMudHJhbnNwb3J0KV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgREVGQVVMVF9SRVNFVF9ERUxBWSA9IDUwO1xuICAgICAgICAgICAgICAgIGNvbnN0IEVYVFJBX0RFTEFZID0gREVGQVVMVF9SRVNFVF9ERUxBWSArIDUwMDtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yZXNldENvbnN0cnVjdG9ycy5jbGFzc2ljUmVzZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWJ1ZyhcInVzaW5nIENsYXNzaWMgU2VyaWFsIFJlc2V0XCIpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNldENvbnN0cnVjdG9ycy5jbGFzc2ljUmVzZXQodGhpcy50cmFuc3BvcnQsIERFRkFVTFRfUkVTRVRfREVMQVkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNldENvbnN0cnVjdG9ycy5jbGFzc2ljUmVzZXQodGhpcy50cmFuc3BvcnQsIEVYVFJBX0RFTEFZKSxcbiAgICAgICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtIGEgY29ubmVjdGlvbiB0byBjaGlwLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtb2RlIC0gUmVzZXQgbW9kZSB0byB1c2UuIEV4YW1wbGU6ICdkZWZhdWx0X3Jlc2V0JyB8ICdub19yZXNldCdcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYXR0ZW1wdHMgLSBOdW1iZXIgb2YgY29ubmVjdGlvbiBhdHRlbXB0c1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gZGV0ZWN0aW5nIC0gRGV0ZWN0IHRoZSBjb25uZWN0ZWQgY2hpcFxuICAgICAqL1xuICAgIGFzeW5jIGNvbm5lY3QobW9kZSA9IFwiZGVmYXVsdF9yZXNldFwiLCBhdHRlbXB0cyA9IDcsIGRldGVjdGluZyA9IHRydWUpIHtcbiAgICAgICAgbGV0IHJlc3A7XG4gICAgICAgIHRoaXMuaW5mbyhcIkNvbm5lY3RpbmcuLi5cIiwgZmFsc2UpO1xuICAgICAgICBhd2FpdCB0aGlzLnRyYW5zcG9ydC5jb25uZWN0KHRoaXMucm9tQmF1ZHJhdGUsIHRoaXMuc2VyaWFsT3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IHJlc2V0U2VxdWVuY2VzID0gdGhpcy5jb25zdHJ1Y3RSZXNldFNlcXVlbmNlKG1vZGUpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dGVtcHRzOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc2V0U2VxdWVuY2UgPSByZXNldFNlcXVlbmNlcy5sZW5ndGggPiAwID8gcmVzZXRTZXF1ZW5jZXNbaSAlIHJlc2V0U2VxdWVuY2VzLmxlbmd0aF0gOiBudWxsO1xuICAgICAgICAgICAgcmVzcCA9IGF3YWl0IHRoaXMuX2Nvbm5lY3RBdHRlbXB0KG1vZGUsIHJlc2V0U2VxdWVuY2UpO1xuICAgICAgICAgICAgaWYgKHJlc3AgPT09IFwic3VjY2Vzc1wiKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc3AgIT09IFwic3VjY2Vzc1wiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRVNQRXJyb3IoXCJGYWlsZWQgdG8gY29ubmVjdCB3aXRoIHRoZSBkZXZpY2VcIik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kZWJ1ZyhcIkNvbm5lY3QgYXR0ZW1wdCBzdWNjZXNzZnVsLlwiKTtcbiAgICAgICAgdGhpcy5pbmZvKFwiXFxuXFxyXCIsIGZhbHNlKTtcbiAgICAgICAgaWYgKGRldGVjdGluZykge1xuICAgICAgICAgICAgY29uc3QgY2hpcE1hZ2ljVmFsdWUgPSAoYXdhaXQgdGhpcy5yZWFkUmVnKHRoaXMuQ0hJUF9ERVRFQ1RfTUFHSUNfUkVHX0FERFIpKSA+Pj4gMDtcbiAgICAgICAgICAgIHRoaXMuZGVidWcoXCJDaGlwIE1hZ2ljIFwiICsgY2hpcE1hZ2ljVmFsdWUudG9TdHJpbmcoMTYpKTtcbiAgICAgICAgICAgIGNvbnN0IGNoaXAgPSBhd2FpdCBtYWdpYzJDaGlwKGNoaXBNYWdpY1ZhbHVlKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmNoaXAgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRVNQRXJyb3IoYFVuZXhwZWN0ZWQgQ0hJUCBtYWdpYyB2YWx1ZSAke2NoaXBNYWdpY1ZhbHVlfS4gRmFpbGVkIHRvIGF1dG9kZXRlY3QgY2hpcCB0eXBlLmApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlwID0gY2hpcDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBDb25uZWN0IGFuZCBkZXRlY3QgdGhlIGV4aXN0aW5nIGNoaXAuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1vZGUgUmVzZXQgbW9kZSB0byB1c2UgZm9yIGNvbm5lY3Rpb24uXG4gICAgICovXG4gICAgYXN5bmMgZGV0ZWN0Q2hpcChtb2RlID0gXCJkZWZhdWx0X3Jlc2V0XCIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5jb25uZWN0KG1vZGUpO1xuICAgICAgICB0aGlzLmluZm8oXCJEZXRlY3RpbmcgY2hpcCB0eXBlLi4uIFwiLCBmYWxzZSk7XG4gICAgICAgIGlmICh0aGlzLmNoaXAgIT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5pbmZvKHRoaXMuY2hpcC5DSElQX05BTUUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5pbmZvKFwidW5rbm93biFcIik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogRXhlY3V0ZSB0aGUgY29tbWFuZCBhbmQgY2hlY2sgdGhlIGNvbW1hbmQgcmVzcG9uc2UuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wRGVzY3JpcHRpb24gQ29tbWFuZCBvcGVyYXRpb24gZGVzY3JpcHRpb24uXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG9wIENvbW1hbmQgb3BlcmF0aW9uIG51bWJlclxuICAgICAqIEBwYXJhbSB7VWludDhBcnJheX0gZGF0YSBDb21tYW5kIHZhbHVlXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGNoayBDaGVja3N1bSB0byB1c2VcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdGltZW91dCBUSW1lb3V0IG51bWJlciBpbiBtaWxsaXNlY29uZHMgKG1zKVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IENvbW1hbmQgcmVzdWx0XG4gICAgICovXG4gICAgYXN5bmMgY2hlY2tDb21tYW5kKG9wRGVzY3JpcHRpb24gPSBcIlwiLCBvcCA9IG51bGwsIGRhdGEgPSBuZXcgVWludDhBcnJheSgwKSwgY2hrID0gMCwgdGltZW91dCA9IHRoaXMuREVGQVVMVF9USU1FT1VUKSB7XG4gICAgICAgIHRoaXMuZGVidWcoXCJjaGVja19jb21tYW5kIFwiICsgb3BEZXNjcmlwdGlvbik7XG4gICAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmNvbW1hbmQob3AsIGRhdGEsIGNoaywgdW5kZWZpbmVkLCB0aW1lb3V0KTtcbiAgICAgICAgaWYgKHJlc3BbMV0ubGVuZ3RoID4gNCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3BbMV07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzcFswXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBTdGFydCBkb3dubG9hZGluZyBhbiBhcHBsaWNhdGlvbiBpbWFnZSB0byBSQU1cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc2l6ZSBJbWFnZSBzaXplIG51bWJlclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBibG9ja3MgTnVtYmVyIG9mIGRhdGEgYmxvY2tzXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGJsb2Nrc2l6ZSBTaXplIG9mIGVhY2ggZGF0YSBibG9ja1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgSW1hZ2Ugb2Zmc2V0IG51bWJlclxuICAgICAqL1xuICAgIGFzeW5jIG1lbUJlZ2luKHNpemUsIGJsb2NrcywgYmxvY2tzaXplLCBvZmZzZXQpIHtcbiAgICAgICAgLyogWFhYOiBBZGQgY2hlY2sgdG8gZW5zdXJlIHRoYXQgU1RVQiBpcyBub3QgZ2V0dGluZyBvdmVyd3JpdHRlbiAqL1xuICAgICAgICBpZiAodGhpcy5JU19TVFVCKSB7XG4gICAgICAgICAgICBjb25zdCBsb2FkU3RhcnQgPSBvZmZzZXQ7XG4gICAgICAgICAgICBjb25zdCBsb2FkRW5kID0gb2Zmc2V0ICsgc2l6ZTtcbiAgICAgICAgICAgIGNvbnN0IHN0dWIgPSBhd2FpdCBnZXRTdHViSnNvbkJ5Q2hpcE5hbWUodGhpcy5jaGlwLkNISVBfTkFNRSk7XG4gICAgICAgICAgICBpZiAoc3R1Yikge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFyZWFzVG9DaGVjayA9IFtcbiAgICAgICAgICAgICAgICAgICAgW3N0dWIuYnNzX3N0YXJ0IHx8IHN0dWIuZGF0YV9zdGFydCwgc3R1Yi5kYXRhX3N0YXJ0ICsgc3R1Yi5kZWNvZGVkRGF0YS5sZW5ndGhdLFxuICAgICAgICAgICAgICAgICAgICBbc3R1Yi50ZXh0X3N0YXJ0LCBzdHViLnRleHRfc3RhcnQgKyBzdHViLmRlY29kZWRUZXh0Lmxlbmd0aF0sXG4gICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IFtzdHViU3RhcnQsIHN0dWJFbmRdIG9mIGFyZWFzVG9DaGVjaykge1xuICAgICAgICAgICAgICAgICAgICBpZiAobG9hZFN0YXJ0IDwgc3R1YkVuZCAmJiBsb2FkRW5kID4gc3R1YlN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRVNQRXJyb3IoYFNvZnR3YXJlIGxvYWRlciBpcyByZXNpZGVudCBhdCAweCR7c3R1YlN0YXJ0LnRvU3RyaW5nKDE2KS5wYWRTdGFydCg4LCBcIjBcIil9LTB4JHtzdHViRW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRvU3RyaW5nKDE2KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5wYWRTdGFydCg4LCBcIjBcIil9LlxuICAgICAgICAgICAgQ2FuJ3QgbG9hZCBiaW5hcnkgYXQgb3ZlcmxhcHBpbmcgYWRkcmVzcyByYW5nZSAweCR7bG9hZFN0YXJ0LnRvU3RyaW5nKDE2KS5wYWRTdGFydCg4LCBcIjBcIil9LTB4JHtsb2FkRW5kXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRvU3RyaW5nKDE2KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5wYWRTdGFydCg4LCBcIjBcIil9LlxuICAgICAgICAgICAgRWl0aGVyIGNoYW5nZSBiaW5hcnkgbG9hZGluZyBhZGRyZXNzLCBvciB1c2UgdGhlIG5vLXN0dWIgb3B0aW9uIHRvIGRpc2FibGUgdGhlIHNvZnR3YXJlIGxvYWRlci5gKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRlYnVnKFwibWVtX2JlZ2luIFwiICsgc2l6ZSArIFwiIFwiICsgYmxvY2tzICsgXCIgXCIgKyBibG9ja3NpemUgKyBcIiBcIiArIG9mZnNldC50b1N0cmluZygxNikpO1xuICAgICAgICBsZXQgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkodGhpcy5faW50VG9CeXRlQXJyYXkoc2l6ZSksIHRoaXMuX2ludFRvQnl0ZUFycmF5KGJsb2NrcykpO1xuICAgICAgICBwa3QgPSB0aGlzLl9hcHBlbmRBcnJheShwa3QsIHRoaXMuX2ludFRvQnl0ZUFycmF5KGJsb2Nrc2l6ZSkpO1xuICAgICAgICBwa3QgPSB0aGlzLl9hcHBlbmRBcnJheShwa3QsIHRoaXMuX2ludFRvQnl0ZUFycmF5KG9mZnNldCkpO1xuICAgICAgICBhd2FpdCB0aGlzLmNoZWNrQ29tbWFuZChcImVudGVyIFJBTSBkb3dubG9hZCBtb2RlXCIsIHRoaXMuRVNQX01FTV9CRUdJTiwgcGt0KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBjaGVja3N1bSBmb3IgZ2l2ZW4gdW5zaWduZWQgOC1iaXQgYXJyYXlcbiAgICAgKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGRhdGEgVW5zaWduZWQgOC1iaXQgaW50ZWdlciBhcnJheVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzdGF0ZSBJbml0aWFsIGNoZWNrc3VtXG4gICAgICogQHJldHVybnMge251bWJlcn0gLSBBcnJheSBjaGVja3N1bVxuICAgICAqL1xuICAgIGNoZWNrc3VtKGRhdGEsIHN0YXRlID0gdGhpcy5FU1BfQ0hFQ0tTVU1fTUFHSUMpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBzdGF0ZSBePSBkYXRhW2ldO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdGF0ZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2VuZCBhIGJsb2NrIG9mIGltYWdlIHRvIFJBTVxuICAgICAqIEBwYXJhbSB7VWludDhBcnJheX0gYnVmZmVyIFVuc2lnbmVkIDgtYml0IGFycmF5XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHNlcSBTZXF1ZW5jZSBudW1iZXJcbiAgICAgKi9cbiAgICBhc3luYyBtZW1CbG9jayhidWZmZXIsIHNlcSkge1xuICAgICAgICBsZXQgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkodGhpcy5faW50VG9CeXRlQXJyYXkoYnVmZmVyLmxlbmd0aCksIHRoaXMuX2ludFRvQnl0ZUFycmF5KHNlcSkpO1xuICAgICAgICBwa3QgPSB0aGlzLl9hcHBlbmRBcnJheShwa3QsIHRoaXMuX2ludFRvQnl0ZUFycmF5KDApKTtcbiAgICAgICAgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkocGt0LCB0aGlzLl9pbnRUb0J5dGVBcnJheSgwKSk7XG4gICAgICAgIHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHBrdCwgYnVmZmVyKTtcbiAgICAgICAgY29uc3QgY2hlY2tzdW0gPSB0aGlzLmNoZWNrc3VtKGJ1ZmZlcik7XG4gICAgICAgIGF3YWl0IHRoaXMuY2hlY2tDb21tYW5kKFwid3JpdGUgdG8gdGFyZ2V0IFJBTVwiLCB0aGlzLkVTUF9NRU1fREFUQSwgcGt0LCBjaGVja3N1bSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIExlYXZlIFJBTSBkb3dubG9hZCBtb2RlIGFuZCBydW4gYXBwbGljYXRpb25cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZW50cnlwb2ludCAtIEVudHJ5cG9pbnQgbnVtYmVyXG4gICAgICovXG4gICAgYXN5bmMgbWVtRmluaXNoKGVudHJ5cG9pbnQpIHtcbiAgICAgICAgY29uc3QgaXNFbnRyeSA9IGVudHJ5cG9pbnQgPT09IDAgPyAxIDogMDtcbiAgICAgICAgY29uc3QgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkodGhpcy5faW50VG9CeXRlQXJyYXkoaXNFbnRyeSksIHRoaXMuX2ludFRvQnl0ZUFycmF5KGVudHJ5cG9pbnQpKTtcbiAgICAgICAgYXdhaXQgdGhpcy5jaGVja0NvbW1hbmQoXCJsZWF2ZSBSQU0gZG93bmxvYWQgbW9kZVwiLCB0aGlzLkVTUF9NRU1fRU5ELCBwa3QsIHVuZGVmaW5lZCwgMjAwKTsgLy8gWFhYOiBoYW5kbGUgbm9uLXN0dWIgd2l0aCBkaWZmIHRpbWVvdXRcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29uZmlndXJlIFNQSSBmbGFzaCBwaW5zXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGhzcGlBcmcgLSAgQXJndW1lbnQgZm9yIFNQSSBhdHRhY2htZW50XG4gICAgICovXG4gICAgYXN5bmMgZmxhc2hTcGlBdHRhY2goaHNwaUFyZykge1xuICAgICAgICBjb25zdCBwa3QgPSB0aGlzLl9pbnRUb0J5dGVBcnJheShoc3BpQXJnKTtcbiAgICAgICAgYXdhaXQgdGhpcy5jaGVja0NvbW1hbmQoXCJjb25maWd1cmUgU1BJIGZsYXNoIHBpbnNcIiwgdGhpcy5FU1BfU1BJX0FUVEFDSCwgcGt0KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2NhbGUgdGltZW91dHMgd2hpY2ggYXJlIHNpemUtc3BlY2lmaWMuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHNlY29uZHNQZXJNYiBTZWNvbmRzIHBlciBtZWdhYnl0ZXMgYXMgbnVtYmVyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHNpemVCeXRlcyBTaXplIGJ5dGVzIG51bWJlclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IC0gU2NhbGVkIHRpbWVvdXQgZm9yIHNwZWNpZmllZCBzaXplLlxuICAgICAqL1xuICAgIHRpbWVvdXRQZXJNYihzZWNvbmRzUGVyTWIsIHNpemVCeXRlcykge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBzZWNvbmRzUGVyTWIgKiAoc2l6ZUJ5dGVzIC8gMTAwMDAwMCk7XG4gICAgICAgIGlmIChyZXN1bHQgPCAzMDAwKSB7XG4gICAgICAgICAgICByZXR1cm4gMzAwMDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogU3RhcnQgZG93bmxvYWRpbmcgdG8gRmxhc2ggKHBlcmZvcm1zIGFuIGVyYXNlKVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIFNpemUgdG8gZXJhc2VcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldCB0byBlcmFzZVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IE51bWJlciBvZiBibG9ja3MgKG9mIHNpemUgc2VsZi5GTEFTSF9XUklURV9TSVpFKSB0byB3cml0ZS5cbiAgICAgKi9cbiAgICBhc3luYyBmbGFzaEJlZ2luKHNpemUsIG9mZnNldCkge1xuICAgICAgICBjb25zdCBudW1CbG9ja3MgPSBNYXRoLmZsb29yKChzaXplICsgdGhpcy5GTEFTSF9XUklURV9TSVpFIC0gMSkgLyB0aGlzLkZMQVNIX1dSSVRFX1NJWkUpO1xuICAgICAgICBjb25zdCBlcmFzZVNpemUgPSB0aGlzLmNoaXAuZ2V0RXJhc2VTaXplKG9mZnNldCwgc2l6ZSk7XG4gICAgICAgIGNvbnN0IGQgPSBuZXcgRGF0ZSgpO1xuICAgICAgICBjb25zdCB0MSA9IGQuZ2V0VGltZSgpO1xuICAgICAgICBsZXQgdGltZW91dCA9IDMwMDA7XG4gICAgICAgIGlmICh0aGlzLklTX1NUVUIgPT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHRpbWVvdXQgPSB0aGlzLnRpbWVvdXRQZXJNYih0aGlzLkVSQVNFX1JFR0lPTl9USU1FT1VUX1BFUl9NQiwgc2l6ZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kZWJ1ZyhcImZsYXNoIGJlZ2luIFwiICsgZXJhc2VTaXplICsgXCIgXCIgKyBudW1CbG9ja3MgKyBcIiBcIiArIHRoaXMuRkxBU0hfV1JJVEVfU0laRSArIFwiIFwiICsgb2Zmc2V0ICsgXCIgXCIgKyBzaXplKTtcbiAgICAgICAgbGV0IHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHRoaXMuX2ludFRvQnl0ZUFycmF5KGVyYXNlU2l6ZSksIHRoaXMuX2ludFRvQnl0ZUFycmF5KG51bUJsb2NrcykpO1xuICAgICAgICBwa3QgPSB0aGlzLl9hcHBlbmRBcnJheShwa3QsIHRoaXMuX2ludFRvQnl0ZUFycmF5KHRoaXMuRkxBU0hfV1JJVEVfU0laRSkpO1xuICAgICAgICBwa3QgPSB0aGlzLl9hcHBlbmRBcnJheShwa3QsIHRoaXMuX2ludFRvQnl0ZUFycmF5KG9mZnNldCkpO1xuICAgICAgICBpZiAodGhpcy5JU19TVFVCID09IGZhbHNlKSB7XG4gICAgICAgICAgICBwa3QgPSB0aGlzLl9hcHBlbmRBcnJheShwa3QsIHRoaXMuX2ludFRvQnl0ZUFycmF5KDApKTsgLy8gWFhYOiBTdXBwb3J0IGVuY3J5cHRlZFxuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHRoaXMuY2hlY2tDb21tYW5kKFwiZW50ZXIgRmxhc2ggZG93bmxvYWQgbW9kZVwiLCB0aGlzLkVTUF9GTEFTSF9CRUdJTiwgcGt0LCB1bmRlZmluZWQsIHRpbWVvdXQpO1xuICAgICAgICBjb25zdCB0MiA9IGQuZ2V0VGltZSgpO1xuICAgICAgICBpZiAoc2l6ZSAhPSAwICYmIHRoaXMuSVNfU1RVQiA9PSBmYWxzZSkge1xuICAgICAgICAgICAgdGhpcy5pbmZvKFwiVG9vayBcIiArICh0MiAtIHQxKSAvIDEwMDAgKyBcIi5cIiArICgodDIgLSB0MSkgJSAxMDAwKSArIFwicyB0byBlcmFzZSBmbGFzaCBibG9ja1wiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVtQmxvY2tzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTdGFydCBkb3dubG9hZGluZyBjb21wcmVzc2VkIGRhdGEgdG8gRmxhc2ggKHBlcmZvcm1zIGFuIGVyYXNlKVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIFdyaXRlIHNpemVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gY29tcHNpemUgQ29tcHJlc3NlZCBzaXplXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQgZm9yIHdyaXRlXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyBudW1iZXIgb2YgYmxvY2tzIChzaXplIHNlbGYuRkxBU0hfV1JJVEVfU0laRSkgdG8gd3JpdGUuXG4gICAgICovXG4gICAgYXN5bmMgZmxhc2hEZWZsQmVnaW4oc2l6ZSwgY29tcHNpemUsIG9mZnNldCkge1xuICAgICAgICBjb25zdCBudW1CbG9ja3MgPSBNYXRoLmZsb29yKChjb21wc2l6ZSArIHRoaXMuRkxBU0hfV1JJVEVfU0laRSAtIDEpIC8gdGhpcy5GTEFTSF9XUklURV9TSVpFKTtcbiAgICAgICAgY29uc3QgZXJhc2VCbG9ja3MgPSBNYXRoLmZsb29yKChzaXplICsgdGhpcy5GTEFTSF9XUklURV9TSVpFIC0gMSkgLyB0aGlzLkZMQVNIX1dSSVRFX1NJWkUpO1xuICAgICAgICBjb25zdCBkID0gbmV3IERhdGUoKTtcbiAgICAgICAgY29uc3QgdDEgPSBkLmdldFRpbWUoKTtcbiAgICAgICAgbGV0IHdyaXRlU2l6ZSwgdGltZW91dDtcbiAgICAgICAgaWYgKHRoaXMuSVNfU1RVQikge1xuICAgICAgICAgICAgd3JpdGVTaXplID0gc2l6ZTtcbiAgICAgICAgICAgIHRpbWVvdXQgPSB0aGlzLkRFRkFVTFRfVElNRU9VVDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHdyaXRlU2l6ZSA9IGVyYXNlQmxvY2tzICogdGhpcy5GTEFTSF9XUklURV9TSVpFO1xuICAgICAgICAgICAgdGltZW91dCA9IHRoaXMudGltZW91dFBlck1iKHRoaXMuRVJBU0VfUkVHSU9OX1RJTUVPVVRfUEVSX01CLCB3cml0ZVNpemUpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaW5mbyhcIkNvbXByZXNzZWQgXCIgKyBzaXplICsgXCIgYnl0ZXMgdG8gXCIgKyBjb21wc2l6ZSArIFwiLi4uXCIpO1xuICAgICAgICBsZXQgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkodGhpcy5faW50VG9CeXRlQXJyYXkod3JpdGVTaXplKSwgdGhpcy5faW50VG9CeXRlQXJyYXkobnVtQmxvY2tzKSk7XG4gICAgICAgIHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHBrdCwgdGhpcy5faW50VG9CeXRlQXJyYXkodGhpcy5GTEFTSF9XUklURV9TSVpFKSk7XG4gICAgICAgIHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHBrdCwgdGhpcy5faW50VG9CeXRlQXJyYXkob2Zmc2V0KSk7XG4gICAgICAgIGlmICgodGhpcy5jaGlwLkNISVBfTkFNRSA9PT0gXCJFU1AzMi1TMlwiIHx8XG4gICAgICAgICAgICB0aGlzLmNoaXAuQ0hJUF9OQU1FID09PSBcIkVTUDMyLVMzXCIgfHxcbiAgICAgICAgICAgIHRoaXMuY2hpcC5DSElQX05BTUUgPT09IFwiRVNQMzItQzNcIiB8fFxuICAgICAgICAgICAgdGhpcy5jaGlwLkNISVBfTkFNRSA9PT0gXCJFU1AzMi1DMlwiKSAmJlxuICAgICAgICAgICAgdGhpcy5JU19TVFVCID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkocGt0LCB0aGlzLl9pbnRUb0J5dGVBcnJheSgwKSk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgdGhpcy5jaGVja0NvbW1hbmQoXCJlbnRlciBjb21wcmVzc2VkIGZsYXNoIG1vZGVcIiwgdGhpcy5FU1BfRkxBU0hfREVGTF9CRUdJTiwgcGt0LCB1bmRlZmluZWQsIHRpbWVvdXQpO1xuICAgICAgICBjb25zdCB0MiA9IGQuZ2V0VGltZSgpO1xuICAgICAgICBpZiAoc2l6ZSAhPSAwICYmIHRoaXMuSVNfU1RVQiA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHRoaXMuaW5mbyhcIlRvb2sgXCIgKyAodDIgLSB0MSkgLyAxMDAwICsgXCIuXCIgKyAoKHQyIC0gdDEpICUgMTAwMCkgKyBcInMgdG8gZXJhc2UgZmxhc2ggYmxvY2tcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bUJsb2NrcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogV3JpdGUgYmxvY2sgdG8gZmxhc2gsIHJldHJ5IGlmIGZhaWxcbiAgICAgKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGRhdGEgVW5zaWduZWQgOC1iaXQgYXJyYXkgZGF0YS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc2VxIFNlcXVlbmNlIG51bWJlclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB0aW1lb3V0IFRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIChtcylcbiAgICAgKi9cbiAgICBhc3luYyBmbGFzaEJsb2NrKGRhdGEsIHNlcSwgdGltZW91dCkge1xuICAgICAgICBsZXQgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkodGhpcy5faW50VG9CeXRlQXJyYXkoZGF0YS5sZW5ndGgpLCB0aGlzLl9pbnRUb0J5dGVBcnJheShzZXEpKTtcbiAgICAgICAgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkocGt0LCB0aGlzLl9pbnRUb0J5dGVBcnJheSgwKSk7XG4gICAgICAgIHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHBrdCwgdGhpcy5faW50VG9CeXRlQXJyYXkoMCkpO1xuICAgICAgICBwa3QgPSB0aGlzLl9hcHBlbmRBcnJheShwa3QsIGRhdGEpO1xuICAgICAgICBjb25zdCBjaGVja3N1bSA9IHRoaXMuY2hlY2tzdW0oZGF0YSk7XG4gICAgICAgIGF3YWl0IHRoaXMuY2hlY2tDb21tYW5kKFwid3JpdGUgdG8gdGFyZ2V0IEZsYXNoIGFmdGVyIHNlcSBcIiArIHNlcSwgdGhpcy5FU1BfRkxBU0hfREFUQSwgcGt0LCBjaGVja3N1bSwgdGltZW91dCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFdyaXRlIGJsb2NrIHRvIGZsYXNoLCBzZW5kIGNvbXByZXNzZWQsIHJldHJ5IGlmIGZhaWxcbiAgICAgKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGRhdGEgVW5zaWduZWQgaW50IDgtYml0IGFycmF5IGRhdGEgdG8gd3JpdGVcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc2VxIFNlcXVlbmNlIG51bWJlclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB0aW1lb3V0IFRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIChtcylcbiAgICAgKi9cbiAgICBhc3luYyBmbGFzaERlZmxCbG9jayhkYXRhLCBzZXEsIHRpbWVvdXQpIHtcbiAgICAgICAgbGV0IHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHRoaXMuX2ludFRvQnl0ZUFycmF5KGRhdGEubGVuZ3RoKSwgdGhpcy5faW50VG9CeXRlQXJyYXkoc2VxKSk7XG4gICAgICAgIHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHBrdCwgdGhpcy5faW50VG9CeXRlQXJyYXkoMCkpO1xuICAgICAgICBwa3QgPSB0aGlzLl9hcHBlbmRBcnJheShwa3QsIHRoaXMuX2ludFRvQnl0ZUFycmF5KDApKTtcbiAgICAgICAgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkocGt0LCBkYXRhKTtcbiAgICAgICAgY29uc3QgY2hlY2tzdW0gPSB0aGlzLmNoZWNrc3VtKGRhdGEpO1xuICAgICAgICB0aGlzLmRlYnVnKFwiZmxhc2hfZGVmbF9ibG9jayBcIiArIGRhdGFbMF0udG9TdHJpbmcoMTYpICsgXCIgXCIgKyBkYXRhWzFdLnRvU3RyaW5nKDE2KSk7XG4gICAgICAgIGF3YWl0IHRoaXMuY2hlY2tDb21tYW5kKFwid3JpdGUgY29tcHJlc3NlZCBkYXRhIHRvIGZsYXNoIGFmdGVyIHNlcSBcIiArIHNlcSwgdGhpcy5FU1BfRkxBU0hfREVGTF9EQVRBLCBwa3QsIGNoZWNrc3VtLCB0aW1lb3V0KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogTGVhdmUgZmxhc2ggbW9kZSBhbmQgcnVuL3JlYm9vdFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcmVib290IFJlYm9vdCBhZnRlciBsZWF2aW5nIGZsYXNoIG1vZGUgP1xuICAgICAqL1xuICAgIGFzeW5jIGZsYXNoRmluaXNoKHJlYm9vdCA9IGZhbHNlKSB7XG4gICAgICAgIGNvbnN0IHZhbCA9IHJlYm9vdCA/IDAgOiAxO1xuICAgICAgICBjb25zdCBwa3QgPSB0aGlzLl9pbnRUb0J5dGVBcnJheSh2YWwpO1xuICAgICAgICBhd2FpdCB0aGlzLmNoZWNrQ29tbWFuZChcImxlYXZlIEZsYXNoIG1vZGVcIiwgdGhpcy5FU1BfRkxBU0hfRU5ELCBwa3QpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBMZWF2ZSBjb21wcmVzc2VkIGZsYXNoIG1vZGUgYW5kIHJ1bi9yZWJvb3RcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHJlYm9vdCBSZWJvb3QgYWZ0ZXIgbGVhdmluZyBmbGFzaCBtb2RlID9cbiAgICAgKi9cbiAgICBhc3luYyBmbGFzaERlZmxGaW5pc2gocmVib290ID0gZmFsc2UpIHtcbiAgICAgICAgY29uc3QgdmFsID0gcmVib290ID8gMCA6IDE7XG4gICAgICAgIGNvbnN0IHBrdCA9IHRoaXMuX2ludFRvQnl0ZUFycmF5KHZhbCk7XG4gICAgICAgIGF3YWl0IHRoaXMuY2hlY2tDb21tYW5kKFwibGVhdmUgY29tcHJlc3NlZCBmbGFzaCBtb2RlXCIsIHRoaXMuRVNQX0ZMQVNIX0RFRkxfRU5ELCBwa3QpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSdW4gYW4gYXJiaXRyYXJ5IFNQSSBmbGFzaCBjb21tYW5kLlxuICAgICAqXG4gICAgICogVGhpcyBmdW5jdGlvbiB1c2VzIHRoZSBcIlVTUl9DT01NQU5EXCIgZnVuY3Rpb25hbGl0eSBpbiB0aGUgRVNQXG4gICAgICogU1BJIGhhcmR3YXJlLCByYXRoZXIgdGhhbiB0aGUgcHJlY2FubmVkIGNvbW1hbmRzIHN1cHBvcnRlZCBieVxuICAgICAqIGhhcmR3YXJlLiBTbyB0aGUgdmFsdWUgb2Ygc3BpZmxhc2hDb21tYW5kIGlzIGFuIGFjdHVhbCBjb21tYW5kXG4gICAgICogYnl0ZSwgc2VudCBvdmVyIHRoZSB3aXJlLlxuICAgICAqXG4gICAgICogQWZ0ZXIgd3JpdGluZyBjb21tYW5kIGJ5dGUsIHdyaXRlcyAnZGF0YScgdG8gTU9TSSBhbmQgdGhlblxuICAgICAqIHJlYWRzIGJhY2sgJ3JlYWRCaXRzJyBvZiByZXBseSBvbiBNSVNPLiBSZXN1bHQgaXMgYSBudW1iZXIuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHNwaWZsYXNoQ29tbWFuZCBDb21tYW5kIHRvIGV4ZWN1dGUgaW4gU1BJXG4gICAgICogQHBhcmFtIHtVaW50OEFycmF5fSBkYXRhIERhdGEgdG8gc2VuZFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSByZWFkQml0cyBOdW1iZXIgb2YgYml0cyB0byByZWFkXG4gICAgICogQHJldHVybnMge251bWJlcn0gUmVnaXN0ZXIgU1BJX1cwX1JFRyB2YWx1ZVxuICAgICAqL1xuICAgIGFzeW5jIHJ1blNwaWZsYXNoQ29tbWFuZChzcGlmbGFzaENvbW1hbmQsIGRhdGEsIHJlYWRCaXRzKSB7XG4gICAgICAgIC8vIFNQSV9VU1IgcmVnaXN0ZXIgZmxhZ3NcbiAgICAgICAgY29uc3QgU1BJX1VTUl9DT01NQU5EID0gMSA8PCAzMTtcbiAgICAgICAgY29uc3QgU1BJX1VTUl9NSVNPID0gMSA8PCAyODtcbiAgICAgICAgY29uc3QgU1BJX1VTUl9NT1NJID0gMSA8PCAyNztcbiAgICAgICAgLy8gU1BJIHJlZ2lzdGVycywgYmFzZSBhZGRyZXNzIGRpZmZlcnMgRVNQMzIqIHZzIDgyNjZcbiAgICAgICAgY29uc3QgYmFzZSA9IHRoaXMuY2hpcC5TUElfUkVHX0JBU0U7XG4gICAgICAgIGNvbnN0IFNQSV9DTURfUkVHID0gYmFzZSArIDB4MDA7XG4gICAgICAgIGNvbnN0IFNQSV9VU1JfUkVHID0gYmFzZSArIHRoaXMuY2hpcC5TUElfVVNSX09GRlM7XG4gICAgICAgIGNvbnN0IFNQSV9VU1IxX1JFRyA9IGJhc2UgKyB0aGlzLmNoaXAuU1BJX1VTUjFfT0ZGUztcbiAgICAgICAgY29uc3QgU1BJX1VTUjJfUkVHID0gYmFzZSArIHRoaXMuY2hpcC5TUElfVVNSMl9PRkZTO1xuICAgICAgICBjb25zdCBTUElfVzBfUkVHID0gYmFzZSArIHRoaXMuY2hpcC5TUElfVzBfT0ZGUztcbiAgICAgICAgbGV0IHNldERhdGFMZW5ndGhzO1xuICAgICAgICBpZiAodGhpcy5jaGlwLlNQSV9NT1NJX0RMRU5fT0ZGUyAhPSBudWxsKSB7XG4gICAgICAgICAgICBzZXREYXRhTGVuZ3RocyA9IGFzeW5jIChtb3NpQml0cywgbWlzb0JpdHMpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBTUElfTU9TSV9ETEVOX1JFRyA9IGJhc2UgKyB0aGlzLmNoaXAuU1BJX01PU0lfRExFTl9PRkZTO1xuICAgICAgICAgICAgICAgIGNvbnN0IFNQSV9NSVNPX0RMRU5fUkVHID0gYmFzZSArIHRoaXMuY2hpcC5TUElfTUlTT19ETEVOX09GRlM7XG4gICAgICAgICAgICAgICAgaWYgKG1vc2lCaXRzID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLndyaXRlUmVnKFNQSV9NT1NJX0RMRU5fUkVHLCBtb3NpQml0cyAtIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWlzb0JpdHMgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMud3JpdGVSZWcoU1BJX01JU09fRExFTl9SRUcsIG1pc29CaXRzIC0gMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNldERhdGFMZW5ndGhzID0gYXN5bmMgKG1vc2lCaXRzLCBtaXNvQml0cykgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IFNQSV9EQVRBX0xFTl9SRUcgPSBTUElfVVNSMV9SRUc7XG4gICAgICAgICAgICAgICAgY29uc3QgU1BJX01PU0lfQklUTEVOX1MgPSAxNztcbiAgICAgICAgICAgICAgICBjb25zdCBTUElfTUlTT19CSVRMRU5fUyA9IDg7XG4gICAgICAgICAgICAgICAgY29uc3QgbW9zaU1hc2sgPSBtb3NpQml0cyA9PT0gMCA/IDAgOiBtb3NpQml0cyAtIDE7XG4gICAgICAgICAgICAgICAgY29uc3QgbWlzb01hc2sgPSBtaXNvQml0cyA9PT0gMCA/IDAgOiBtaXNvQml0cyAtIDE7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsID0gKG1pc29NYXNrIDw8IFNQSV9NSVNPX0JJVExFTl9TKSB8IChtb3NpTWFzayA8PCBTUElfTU9TSV9CSVRMRU5fUyk7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy53cml0ZVJlZyhTUElfREFUQV9MRU5fUkVHLCB2YWwpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBTUElfQ01EX1VTUiA9IDEgPDwgMTg7XG4gICAgICAgIGNvbnN0IFNQSV9VU1IyX0NPTU1BTkRfTEVOX1NISUZUID0gMjg7XG4gICAgICAgIGlmIChyZWFkQml0cyA+IDMyKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRVNQRXJyb3IoXCJSZWFkaW5nIG1vcmUgdGhhbiAzMiBiaXRzIGJhY2sgZnJvbSBhIFNQSSBmbGFzaCBvcGVyYXRpb24gaXMgdW5zdXBwb3J0ZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRhdGEubGVuZ3RoID4gNjQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFU1BFcnJvcihcIldyaXRpbmcgbW9yZSB0aGFuIDY0IGJ5dGVzIG9mIGRhdGEgd2l0aCBvbmUgU1BJIGNvbW1hbmQgaXMgdW5zdXBwb3J0ZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGF0YUJpdHMgPSBkYXRhLmxlbmd0aCAqIDg7XG4gICAgICAgIGNvbnN0IG9sZFNwaVVzciA9IGF3YWl0IHRoaXMucmVhZFJlZyhTUElfVVNSX1JFRyk7XG4gICAgICAgIGNvbnN0IG9sZFNwaVVzcjIgPSBhd2FpdCB0aGlzLnJlYWRSZWcoU1BJX1VTUjJfUkVHKTtcbiAgICAgICAgbGV0IGZsYWdzID0gU1BJX1VTUl9DT01NQU5EO1xuICAgICAgICBsZXQgaTtcbiAgICAgICAgaWYgKHJlYWRCaXRzID4gMCkge1xuICAgICAgICAgICAgZmxhZ3MgfD0gU1BJX1VTUl9NSVNPO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkYXRhQml0cyA+IDApIHtcbiAgICAgICAgICAgIGZsYWdzIHw9IFNQSV9VU1JfTU9TSTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBzZXREYXRhTGVuZ3RocyhkYXRhQml0cywgcmVhZEJpdHMpO1xuICAgICAgICBhd2FpdCB0aGlzLndyaXRlUmVnKFNQSV9VU1JfUkVHLCBmbGFncyk7XG4gICAgICAgIGxldCB2YWwgPSAoNyA8PCBTUElfVVNSMl9DT01NQU5EX0xFTl9TSElGVCkgfCBzcGlmbGFzaENvbW1hbmQ7XG4gICAgICAgIGF3YWl0IHRoaXMud3JpdGVSZWcoU1BJX1VTUjJfUkVHLCB2YWwpO1xuICAgICAgICBpZiAoZGF0YUJpdHMgPT0gMCkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy53cml0ZVJlZyhTUElfVzBfUkVHLCAwKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlmIChkYXRhLmxlbmd0aCAlIDQgIT0gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhZGRpbmcgPSBuZXcgVWludDhBcnJheShkYXRhLmxlbmd0aCAlIDQpO1xuICAgICAgICAgICAgICAgIGRhdGEgPSB0aGlzLl9hcHBlbmRBcnJheShkYXRhLCBwYWRkaW5nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBuZXh0UmVnID0gU1BJX1cwX1JFRztcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBkYXRhLmxlbmd0aCAtIDQ7IGkgKz0gNCkge1xuICAgICAgICAgICAgICAgIHZhbCA9IHRoaXMuX2J5dGVBcnJheVRvSW50KGRhdGFbaV0sIGRhdGFbaSArIDFdLCBkYXRhW2kgKyAyXSwgZGF0YVtpICsgM10pO1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMud3JpdGVSZWcobmV4dFJlZywgdmFsKTtcbiAgICAgICAgICAgICAgICBuZXh0UmVnICs9IDQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgdGhpcy53cml0ZVJlZyhTUElfQ01EX1JFRywgU1BJX0NNRF9VU1IpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTA7IGkrKykge1xuICAgICAgICAgICAgdmFsID0gKGF3YWl0IHRoaXMucmVhZFJlZyhTUElfQ01EX1JFRykpICYgU1BJX0NNRF9VU1I7XG4gICAgICAgICAgICBpZiAodmFsID09IDApIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoaSA9PT0gMTApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFU1BFcnJvcihcIlNQSSBjb21tYW5kIGRpZCBub3QgY29tcGxldGUgaW4gdGltZVwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzdGF0ID0gYXdhaXQgdGhpcy5yZWFkUmVnKFNQSV9XMF9SRUcpO1xuICAgICAgICBhd2FpdCB0aGlzLndyaXRlUmVnKFNQSV9VU1JfUkVHLCBvbGRTcGlVc3IpO1xuICAgICAgICBhd2FpdCB0aGlzLndyaXRlUmVnKFNQSV9VU1IyX1JFRywgb2xkU3BpVXNyMik7XG4gICAgICAgIHJldHVybiBzdGF0O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWFkIGZsYXNoIGlkIGJ5IGV4ZWN1dGluZyB0aGUgU1BJRkxBU0hfUkRJRCBmbGFzaCBjb21tYW5kLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPG51bWJlcj59IFJlZ2lzdGVyIFNQSV9XMF9SRUcgdmFsdWVcbiAgICAgKi9cbiAgICBhc3luYyByZWFkRmxhc2hJZCgpIHtcbiAgICAgICAgY29uc3QgU1BJRkxBU0hfUkRJRCA9IDB4OWY7XG4gICAgICAgIGNvbnN0IHBrdCA9IG5ldyBVaW50OEFycmF5KDApO1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5ydW5TcGlmbGFzaENvbW1hbmQoU1BJRkxBU0hfUkRJRCwgcGt0LCAyNCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEV4ZWN1dGUgdGhlIGVyYXNlIGZsYXNoIGNvbW1hbmRcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxudW1iZXIgfCBVaW50OEFycmF5Pn0gRXJhc2UgZmxhc2ggY29tbWFuZCByZXN1bHRcbiAgICAgKi9cbiAgICBhc3luYyBlcmFzZUZsYXNoKCkge1xuICAgICAgICB0aGlzLmluZm8oXCJFcmFzaW5nIGZsYXNoICh0aGlzIG1heSB0YWtlIGEgd2hpbGUpLi4uXCIpO1xuICAgICAgICBsZXQgZCA9IG5ldyBEYXRlKCk7XG4gICAgICAgIGNvbnN0IHQxID0gZC5nZXRUaW1lKCk7XG4gICAgICAgIGNvbnN0IHJldCA9IGF3YWl0IHRoaXMuY2hlY2tDb21tYW5kKFwiZXJhc2UgZmxhc2hcIiwgdGhpcy5FU1BfRVJBU0VfRkxBU0gsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB0aGlzLkNISVBfRVJBU0VfVElNRU9VVCk7XG4gICAgICAgIGQgPSBuZXcgRGF0ZSgpO1xuICAgICAgICBjb25zdCB0MiA9IGQuZ2V0VGltZSgpO1xuICAgICAgICB0aGlzLmluZm8oXCJDaGlwIGVyYXNlIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHkgaW4gXCIgKyAodDIgLSB0MSkgLyAxMDAwICsgXCJzXCIpO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IGEgbnVtYmVyIG9yIHVuc2lnbmVkIDgtYml0IGFycmF5IHRvIGhleCBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge251bWJlciB8IFVpbnQ4QXJyYXkgfSBidWZmZXIgRGF0YSB0byBjb252ZXJ0IHRvIGhleCBzdHJpbmcuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gQSBoZXggc3RyaW5nXG4gICAgICovXG4gICAgdG9IZXgoYnVmZmVyKSB7XG4gICAgICAgIHJldHVybiBBcnJheS5wcm90b3R5cGUubWFwLmNhbGwoYnVmZmVyLCAoeCkgPT4gKFwiMDBcIiArIHgudG9TdHJpbmcoMTYpKS5zbGljZSgtMikpLmpvaW4oXCJcIik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZSB0aGUgTUQ1IENoZWNrc3VtIGNvbW1hbmRcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYWRkciBBZGRyZXNzIG51bWJlclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIFBhY2thZ2Ugc2l6ZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IE1ENSBDaGVja3N1bSBzdHJpbmdcbiAgICAgKi9cbiAgICBhc3luYyBmbGFzaE1kNXN1bShhZGRyLCBzaXplKSB7XG4gICAgICAgIGNvbnN0IHRpbWVvdXQgPSB0aGlzLnRpbWVvdXRQZXJNYih0aGlzLk1ENV9USU1FT1VUX1BFUl9NQiwgc2l6ZSk7XG4gICAgICAgIGxldCBwa3QgPSB0aGlzLl9hcHBlbmRBcnJheSh0aGlzLl9pbnRUb0J5dGVBcnJheShhZGRyKSwgdGhpcy5faW50VG9CeXRlQXJyYXkoc2l6ZSkpO1xuICAgICAgICBwa3QgPSB0aGlzLl9hcHBlbmRBcnJheShwa3QsIHRoaXMuX2ludFRvQnl0ZUFycmF5KDApKTtcbiAgICAgICAgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkocGt0LCB0aGlzLl9pbnRUb0J5dGVBcnJheSgwKSk7XG4gICAgICAgIGxldCByZXMgPSBhd2FpdCB0aGlzLmNoZWNrQ29tbWFuZChcImNhbGN1bGF0ZSBtZDVzdW1cIiwgdGhpcy5FU1BfU1BJX0ZMQVNIX01ENSwgcGt0LCB1bmRlZmluZWQsIHRpbWVvdXQpO1xuICAgICAgICBpZiAocmVzIGluc3RhbmNlb2YgVWludDhBcnJheSAmJiByZXMubGVuZ3RoID4gMTYpIHtcbiAgICAgICAgICAgIHJlcyA9IHJlcy5zbGljZSgwLCAxNik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc3RybWQ1ID0gdGhpcy50b0hleChyZXMpO1xuICAgICAgICByZXR1cm4gc3RybWQ1O1xuICAgIH1cbiAgICBhc3luYyByZWFkRmxhc2goYWRkciwgc2l6ZSwgb25QYWNrZXRSZWNlaXZlZCA9IG51bGwpIHtcbiAgICAgICAgbGV0IHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHRoaXMuX2ludFRvQnl0ZUFycmF5KGFkZHIpLCB0aGlzLl9pbnRUb0J5dGVBcnJheShzaXplKSk7XG4gICAgICAgIHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHBrdCwgdGhpcy5faW50VG9CeXRlQXJyYXkoMHgxMDAwKSk7XG4gICAgICAgIHBrdCA9IHRoaXMuX2FwcGVuZEFycmF5KHBrdCwgdGhpcy5faW50VG9CeXRlQXJyYXkoMTAyNCkpO1xuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLmNoZWNrQ29tbWFuZChcInJlYWQgZmxhc2hcIiwgdGhpcy5FU1BfUkVBRF9GTEFTSCwgcGt0KTtcbiAgICAgICAgaWYgKHJlcyAhPSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRVNQRXJyb3IoXCJGYWlsZWQgdG8gcmVhZCBtZW1vcnk6IFwiICsgcmVzKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcmVzcCA9IG5ldyBVaW50OEFycmF5KDApO1xuICAgICAgICB3aGlsZSAocmVzcC5sZW5ndGggPCBzaXplKSB7XG4gICAgICAgICAgICBjb25zdCB7IHZhbHVlOiBwYWNrZXQgfSA9IGF3YWl0IHRoaXMudHJhbnNwb3J0LnJlYWQodGhpcy5GTEFTSF9SRUFEX1RJTUVPVVQpLm5leHQoKTtcbiAgICAgICAgICAgIGlmIChwYWNrZXQgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgICAgICAgICAgICAgaWYgKHBhY2tldC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3AgPSB0aGlzLl9hcHBlbmRBcnJheShyZXNwLCBwYWNrZXQpO1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnRyYW5zcG9ydC53cml0ZSh0aGlzLl9pbnRUb0J5dGVBcnJheShyZXNwLmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAob25QYWNrZXRSZWNlaXZlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb25QYWNrZXRSZWNlaXZlZChwYWNrZXQsIHJlc3AubGVuZ3RoLCBzaXplKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFU1BFcnJvcihcIkZhaWxlZCB0byByZWFkIG1lbW9yeTogXCIgKyBwYWNrZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXNwO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBVcGxvYWQgdGhlIGZsYXNoZXIgUk9NIGJvb3Rsb2FkZXIgKGZsYXNoZXIgc3R1YikgdG8gdGhlIGNoaXAuXG4gICAgICogQHJldHVybnMge1JPTX0gVGhlIENoaXAgUk9NXG4gICAgICovXG4gICAgYXN5bmMgcnVuU3R1YigpIHtcbiAgICAgICAgaWYgKHRoaXMuc3luY1N0dWJEZXRlY3RlZCkge1xuICAgICAgICAgICAgdGhpcy5pbmZvKFwiU3R1YiBpcyBhbHJlYWR5IHJ1bm5pbmcuIE5vIHVwbG9hZCBpcyBuZWNlc3NhcnkuXCIpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hpcDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmluZm8oXCJVcGxvYWRpbmcgc3R1Yi4uLlwiKTtcbiAgICAgICAgY29uc3Qgc3R1YkZsYXNoZXIgPSBhd2FpdCBnZXRTdHViSnNvbkJ5Q2hpcE5hbWUodGhpcy5jaGlwLkNISVBfTkFNRSk7XG4gICAgICAgIGlmIChzdHViRmxhc2hlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmRlYnVnKFwiRXJyb3IgbG9hZGluZyBTdHViIGpzb25cIik7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJFcnJvciBsb2FkaW5nIFN0dWIganNvblwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzdHViID0gW3N0dWJGbGFzaGVyLmRlY29kZWRUZXh0LCBzdHViRmxhc2hlci5kZWNvZGVkRGF0YV07XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3R1Yi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHN0dWJbaV0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvZmZzID0gaSA9PT0gMCA/IHN0dWJGbGFzaGVyLnRleHRfc3RhcnQgOiBzdHViRmxhc2hlci5kYXRhX3N0YXJ0O1xuICAgICAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IHN0dWJbaV0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGNvbnN0IGJsb2NrcyA9IE1hdGguZmxvb3IoKGxlbmd0aCArIHRoaXMuRVNQX1JBTV9CTE9DSyAtIDEpIC8gdGhpcy5FU1BfUkFNX0JMT0NLKTtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLm1lbUJlZ2luKGxlbmd0aCwgYmxvY2tzLCB0aGlzLkVTUF9SQU1fQkxPQ0ssIG9mZnMpO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IHNlcSA9IDA7IHNlcSA8IGJsb2Nrczsgc2VxKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZnJvbU9mZnMgPSBzZXEgKiB0aGlzLkVTUF9SQU1fQkxPQ0s7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRvT2ZmcyA9IGZyb21PZmZzICsgdGhpcy5FU1BfUkFNX0JMT0NLO1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLm1lbUJsb2NrKHN0dWJbaV0uc2xpY2UoZnJvbU9mZnMsIHRvT2ZmcyksIHNlcSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuaW5mbyhcIlJ1bm5pbmcgc3R1Yi4uLlwiKTtcbiAgICAgICAgYXdhaXQgdGhpcy5tZW1GaW5pc2goc3R1YkZsYXNoZXIuZW50cnkpO1xuICAgICAgICBjb25zdCB7IHZhbHVlOiBwYWNrZXRSZXN1bHQgfSA9IGF3YWl0IHRoaXMudHJhbnNwb3J0LnJlYWQodGhpcy5ERUZBVUxUX1RJTUVPVVQpLm5leHQoKTtcbiAgICAgICAgY29uc3QgcGFja2V0U3RyID0gU3RyaW5nLmZyb21DaGFyQ29kZSguLi5wYWNrZXRSZXN1bHQpO1xuICAgICAgICBpZiAocGFja2V0U3RyICE9PSBcIk9IQUlcIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVTUEVycm9yKGBGYWlsZWQgdG8gc3RhcnQgc3R1Yi4gVW5leHBlY3RlZCByZXNwb25zZSAke3BhY2tldFN0cn1gKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmluZm8oXCJTdHViIHJ1bm5pbmcuLi5cIik7XG4gICAgICAgIHRoaXMuSVNfU1RVQiA9IHRydWU7XG4gICAgICAgIHJldHVybiB0aGlzLmNoaXA7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENoYW5nZSB0aGUgY2hpcCBiYXVkcmF0ZS5cbiAgICAgKi9cbiAgICBhc3luYyBjaGFuZ2VCYXVkKCkge1xuICAgICAgICB0aGlzLmluZm8oXCJDaGFuZ2luZyBiYXVkcmF0ZSB0byBcIiArIHRoaXMuYmF1ZHJhdGUpO1xuICAgICAgICBjb25zdCBzZWNvbmRBcmcgPSB0aGlzLklTX1NUVUIgPyB0aGlzLnJvbUJhdWRyYXRlIDogMDtcbiAgICAgICAgY29uc3QgcGt0ID0gdGhpcy5fYXBwZW5kQXJyYXkodGhpcy5faW50VG9CeXRlQXJyYXkodGhpcy5iYXVkcmF0ZSksIHRoaXMuX2ludFRvQnl0ZUFycmF5KHNlY29uZEFyZykpO1xuICAgICAgICBhd2FpdCB0aGlzLmNvbW1hbmQodGhpcy5FU1BfQ0hBTkdFX0JBVURSQVRFLCBwa3QpO1xuICAgICAgICB0aGlzLmluZm8oXCJDaGFuZ2VkXCIpO1xuICAgICAgICBhd2FpdCB0aGlzLnRyYW5zcG9ydC5kaXNjb25uZWN0KCk7XG4gICAgICAgIGF3YWl0IHRoaXMuX3NsZWVwKDUwKTtcbiAgICAgICAgYXdhaXQgdGhpcy50cmFuc3BvcnQuY29ubmVjdCh0aGlzLmJhdWRyYXRlLCB0aGlzLnNlcmlhbE9wdGlvbnMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlIHRoZSBtYWluIGZ1bmN0aW9uIG9mIEVTUExvYWRlci5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbW9kZSBSZXNldCBtb2RlIHRvIHVzZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IGNoaXAgUk9NXG4gICAgICovXG4gICAgYXN5bmMgbWFpbihtb2RlID0gXCJkZWZhdWx0X3Jlc2V0XCIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5kZXRlY3RDaGlwKG1vZGUpO1xuICAgICAgICBjb25zdCBjaGlwID0gYXdhaXQgdGhpcy5jaGlwLmdldENoaXBEZXNjcmlwdGlvbih0aGlzKTtcbiAgICAgICAgdGhpcy5pbmZvKFwiQ2hpcCBpcyBcIiArIGNoaXApO1xuICAgICAgICB0aGlzLmluZm8oXCJGZWF0dXJlczogXCIgKyAoYXdhaXQgdGhpcy5jaGlwLmdldENoaXBGZWF0dXJlcyh0aGlzKSkpO1xuICAgICAgICB0aGlzLmluZm8oXCJDcnlzdGFsIGlzIFwiICsgKGF3YWl0IHRoaXMuY2hpcC5nZXRDcnlzdGFsRnJlcSh0aGlzKSkgKyBcIk1IelwiKTtcbiAgICAgICAgdGhpcy5pbmZvKFwiTUFDOiBcIiArIChhd2FpdCB0aGlzLmNoaXAucmVhZE1hYyh0aGlzKSkpO1xuICAgICAgICBhd2FpdCB0aGlzLmNoaXAucmVhZE1hYyh0aGlzKTtcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmNoaXAucG9zdENvbm5lY3QgIT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5jaGlwLnBvc3RDb25uZWN0KHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHRoaXMucnVuU3R1YigpO1xuICAgICAgICBpZiAodGhpcy5yb21CYXVkcmF0ZSAhPT0gdGhpcy5iYXVkcmF0ZSkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5jaGFuZ2VCYXVkKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNoaXA7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFBhcnNlIGEgZ2l2ZW4gZmxhc2ggc2l6ZSBzdHJpbmcgdG8gYSBudW1iZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZmxzeiBGbGFzaCBzaXplIHRvIHJlcXVlc3RcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBGbGFzaCBzaXplIG51bWJlclxuICAgICAqL1xuICAgIHBhcnNlRmxhc2hTaXplQXJnKGZsc3opIHtcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmNoaXAuRkxBU0hfU0laRVNbZmxzel0gPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFU1BFcnJvcihcIkZsYXNoIHNpemUgXCIgKyBmbHN6ICsgXCIgaXMgbm90IHN1cHBvcnRlZCBieSB0aGlzIGNoaXAgdHlwZS4gU3VwcG9ydGVkIHNpemVzOiBcIiArIHRoaXMuY2hpcC5GTEFTSF9TSVpFUyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuY2hpcC5GTEFTSF9TSVpFU1tmbHN6XTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBpbWFnZSBmbGFzaCBwYXJhbWV0ZXJzIHdpdGggZ2l2ZW4gYXJndW1lbnRzLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpbWFnZSBiaW5hcnkgaW1hZ2UgYXMgc3RyaW5nXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGFkZHJlc3MgZmxhc2ggYWRkcmVzcyBudW1iZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZmxhc2hTaXplIEZsYXNoIHNpemUgc3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGZsYXNoTW9kZSBGbGFzaCBtb2RlIHN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBmbGFzaEZyZXEgRmxhc2ggZnJlcXVlbmN5IHN0cmluZ1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IG1vZGlmaWVkIGltYWdlIHN0cmluZ1xuICAgICAqL1xuICAgIF91cGRhdGVJbWFnZUZsYXNoUGFyYW1zKGltYWdlLCBhZGRyZXNzLCBmbGFzaFNpemUsIGZsYXNoTW9kZSwgZmxhc2hGcmVxKSB7XG4gICAgICAgIHRoaXMuZGVidWcoXCJfdXBkYXRlX2ltYWdlX2ZsYXNoX3BhcmFtcyBcIiArIGZsYXNoU2l6ZSArIFwiIFwiICsgZmxhc2hNb2RlICsgXCIgXCIgKyBmbGFzaEZyZXEpO1xuICAgICAgICBpZiAoaW1hZ2UubGVuZ3RoIDwgOCkge1xuICAgICAgICAgICAgcmV0dXJuIGltYWdlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhZGRyZXNzICE9IHRoaXMuY2hpcC5CT09UTE9BREVSX0ZMQVNIX09GRlNFVCkge1xuICAgICAgICAgICAgcmV0dXJuIGltYWdlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmbGFzaFNpemUgPT09IFwia2VlcFwiICYmIGZsYXNoTW9kZSA9PT0gXCJrZWVwXCIgJiYgZmxhc2hGcmVxID09PSBcImtlZXBcIikge1xuICAgICAgICAgICAgdGhpcy5pbmZvKFwiTm90IGNoYW5naW5nIHRoZSBpbWFnZVwiKTtcbiAgICAgICAgICAgIHJldHVybiBpbWFnZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBtYWdpYyA9IHBhcnNlSW50KGltYWdlWzBdKTtcbiAgICAgICAgbGV0IGFGbGFzaE1vZGUgPSBwYXJzZUludChpbWFnZVsyXSk7XG4gICAgICAgIGNvbnN0IGZsYXNoU2l6ZUZyZXEgPSBwYXJzZUludChpbWFnZVszXSk7XG4gICAgICAgIGlmIChtYWdpYyAhPT0gdGhpcy5FU1BfSU1BR0VfTUFHSUMpIHtcbiAgICAgICAgICAgIHRoaXMuaW5mbyhcIldhcm5pbmc6IEltYWdlIGZpbGUgYXQgMHhcIiArXG4gICAgICAgICAgICAgICAgYWRkcmVzcy50b1N0cmluZygxNikgK1xuICAgICAgICAgICAgICAgIFwiIGRvZXNuJ3QgbG9vayBsaWtlIGFuIGltYWdlIGZpbGUsIHNvIG5vdCBjaGFuZ2luZyBhbnkgZmxhc2ggc2V0dGluZ3MuXCIpO1xuICAgICAgICAgICAgcmV0dXJuIGltYWdlO1xuICAgICAgICB9XG4gICAgICAgIC8qIFhYWDogWWV0IHRvIGltcGxlbWVudCBhY3R1YWwgaW1hZ2UgdmVyaWZpY2F0aW9uICovXG4gICAgICAgIGlmIChmbGFzaE1vZGUgIT09IFwia2VlcFwiKSB7XG4gICAgICAgICAgICBjb25zdCBmbGFzaE1vZGVzID0geyBxaW86IDAsIHFvdXQ6IDEsIGRpbzogMiwgZG91dDogMyB9O1xuICAgICAgICAgICAgYUZsYXNoTW9kZSA9IGZsYXNoTW9kZXNbZmxhc2hNb2RlXTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgYUZsYXNoRnJlcSA9IGZsYXNoU2l6ZUZyZXEgJiAweDBmO1xuICAgICAgICBpZiAoZmxhc2hGcmVxICE9PSBcImtlZXBcIikge1xuICAgICAgICAgICAgY29uc3QgZmxhc2hGcmVxcyA9IHsgXCI0MG1cIjogMCwgXCIyNm1cIjogMSwgXCIyMG1cIjogMiwgXCI4MG1cIjogMHhmIH07XG4gICAgICAgICAgICBhRmxhc2hGcmVxID0gZmxhc2hGcmVxc1tmbGFzaEZyZXFdO1xuICAgICAgICB9XG4gICAgICAgIGxldCBhRmxhc2hTaXplID0gZmxhc2hTaXplRnJlcSAmIDB4ZjA7XG4gICAgICAgIGlmIChmbGFzaFNpemUgIT09IFwia2VlcFwiKSB7XG4gICAgICAgICAgICBhRmxhc2hTaXplID0gdGhpcy5wYXJzZUZsYXNoU2l6ZUFyZyhmbGFzaFNpemUpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGZsYXNoUGFyYW1zID0gKGFGbGFzaE1vZGUgPDwgOCkgfCAoYUZsYXNoRnJlcSArIGFGbGFzaFNpemUpO1xuICAgICAgICB0aGlzLmluZm8oXCJGbGFzaCBwYXJhbXMgc2V0IHRvIFwiICsgZmxhc2hQYXJhbXMudG9TdHJpbmcoMTYpKTtcbiAgICAgICAgaWYgKHBhcnNlSW50KGltYWdlWzJdKSAhPT0gYUZsYXNoTW9kZSA8PCA4KSB7XG4gICAgICAgICAgICBpbWFnZSA9IGltYWdlLnN1YnN0cmluZygwLCAyKSArIChhRmxhc2hNb2RlIDw8IDgpLnRvU3RyaW5nKCkgKyBpbWFnZS5zdWJzdHJpbmcoMiArIDEpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYXJzZUludChpbWFnZVszXSkgIT09IGFGbGFzaEZyZXEgKyBhRmxhc2hTaXplKSB7XG4gICAgICAgICAgICBpbWFnZSA9IGltYWdlLnN1YnN0cmluZygwLCAzKSArIChhRmxhc2hGcmVxICsgYUZsYXNoU2l6ZSkudG9TdHJpbmcoKSArIGltYWdlLnN1YnN0cmluZygzICsgMSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGltYWdlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBXcml0ZSBzZXQgb2YgZmlsZSBpbWFnZXMgaW50byBnaXZlbiBhZGRyZXNzIGJhc2VkIG9uIGdpdmVuIEZsYXNoT3B0aW9ucyBvYmplY3QuXG4gICAgICogQHBhcmFtIHtGbGFzaE9wdGlvbnN9IG9wdGlvbnMgRmxhc2hPcHRpb25zIHRvIGNvbmZpZ3VyZSBob3cgYW5kIHdoYXQgdG8gd3JpdGUgaW50byBmbGFzaC5cbiAgICAgKi9cbiAgICBhc3luYyB3cml0ZUZsYXNoKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5kZWJ1ZyhcIkVzcExvYWRlciBwcm9ncmFtXCIpO1xuICAgICAgICBpZiAob3B0aW9ucy5mbGFzaFNpemUgIT09IFwia2VlcFwiKSB7XG4gICAgICAgICAgICBjb25zdCBmbGFzaEVuZCA9IHRoaXMuZmxhc2hTaXplQnl0ZXMob3B0aW9ucy5mbGFzaFNpemUpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvcHRpb25zLmZpbGVBcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmZpbGVBcnJheVtpXS5kYXRhLmxlbmd0aCArIG9wdGlvbnMuZmlsZUFycmF5W2ldLmFkZHJlc3MgPiBmbGFzaEVuZCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRVNQRXJyb3IoYEZpbGUgJHtpICsgMX0gZG9lc24ndCBmaXQgaW4gdGhlIGF2YWlsYWJsZSBmbGFzaGApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5JU19TVFVCID09PSB0cnVlICYmIG9wdGlvbnMuZXJhc2VBbGwgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZXJhc2VGbGFzaCgpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBpbWFnZSwgYWRkcmVzcztcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvcHRpb25zLmZpbGVBcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpcy5kZWJ1ZyhcIkRhdGEgTGVuZ3RoIFwiICsgb3B0aW9ucy5maWxlQXJyYXlbaV0uZGF0YS5sZW5ndGgpO1xuICAgICAgICAgICAgaW1hZ2UgPSBvcHRpb25zLmZpbGVBcnJheVtpXS5kYXRhO1xuICAgICAgICAgICAgdGhpcy5kZWJ1ZyhcIkltYWdlIExlbmd0aCBcIiArIGltYWdlLmxlbmd0aCk7XG4gICAgICAgICAgICBpZiAoaW1hZ2UubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kZWJ1ZyhcIldhcm5pbmc6IEZpbGUgaXMgZW1wdHlcIik7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpbWFnZSA9IHRoaXMudWk4VG9Cc3RyKHBhZFRvKHRoaXMuYnN0clRvVWk4KGltYWdlKSwgNCkpO1xuICAgICAgICAgICAgYWRkcmVzcyA9IG9wdGlvbnMuZmlsZUFycmF5W2ldLmFkZHJlc3M7XG4gICAgICAgICAgICBpbWFnZSA9IHRoaXMuX3VwZGF0ZUltYWdlRmxhc2hQYXJhbXMoaW1hZ2UsIGFkZHJlc3MsIG9wdGlvbnMuZmxhc2hTaXplLCBvcHRpb25zLmZsYXNoTW9kZSwgb3B0aW9ucy5mbGFzaEZyZXEpO1xuICAgICAgICAgICAgbGV0IGNhbGNtZDUgPSBudWxsO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuY2FsY3VsYXRlTUQ1SGFzaCkge1xuICAgICAgICAgICAgICAgIGNhbGNtZDUgPSBvcHRpb25zLmNhbGN1bGF0ZU1ENUhhc2goaW1hZ2UpO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVidWcoXCJJbWFnZSBNRDUgXCIgKyBjYWxjbWQ1KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHVuY3NpemUgPSBpbWFnZS5sZW5ndGg7XG4gICAgICAgICAgICBsZXQgYmxvY2tzO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuY29tcHJlc3MpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB1bmNpbWFnZSA9IHRoaXMuYnN0clRvVWk4KGltYWdlKTtcbiAgICAgICAgICAgICAgICBpbWFnZSA9IHRoaXMudWk4VG9Cc3RyKGRlZmxhdGUodW5jaW1hZ2UsIHsgbGV2ZWw6IDkgfSkpO1xuICAgICAgICAgICAgICAgIGJsb2NrcyA9IGF3YWl0IHRoaXMuZmxhc2hEZWZsQmVnaW4odW5jc2l6ZSwgaW1hZ2UubGVuZ3RoLCBhZGRyZXNzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGJsb2NrcyA9IGF3YWl0IHRoaXMuZmxhc2hCZWdpbih1bmNzaXplLCBhZGRyZXNzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBzZXEgPSAwO1xuICAgICAgICAgICAgbGV0IGJ5dGVzU2VudCA9IDA7XG4gICAgICAgICAgICBjb25zdCB0b3RhbEJ5dGVzID0gaW1hZ2UubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMucmVwb3J0UHJvZ3Jlc3MpXG4gICAgICAgICAgICAgICAgb3B0aW9ucy5yZXBvcnRQcm9ncmVzcyhpLCAwLCB0b3RhbEJ5dGVzKTtcbiAgICAgICAgICAgIGxldCBkID0gbmV3IERhdGUoKTtcbiAgICAgICAgICAgIGNvbnN0IHQxID0gZC5nZXRUaW1lKCk7XG4gICAgICAgICAgICBsZXQgdGltZW91dCA9IDUwMDA7XG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBkZWNvbXByZXNzb3IgdG8ga2VlcCB0cmFjayBvZiB0aGUgc2l6ZSBvZiB1bmNvbXByZXNzZWQgZGF0YVxuICAgICAgICAgICAgLy8gdG8gYmUgd3JpdHRlbiBpbiBlYWNoIGNodW5rLlxuICAgICAgICAgICAgY29uc3QgaW5mbGF0ZSA9IG5ldyBJbmZsYXRlKHsgY2h1bmtTaXplOiAxIH0pO1xuICAgICAgICAgICAgbGV0IHRvdGFsTGVuVW5jb21wcmVzc2VkID0gMDtcbiAgICAgICAgICAgIGluZmxhdGUub25EYXRhID0gZnVuY3Rpb24gKGNodW5rKSB7XG4gICAgICAgICAgICAgICAgdG90YWxMZW5VbmNvbXByZXNzZWQgKz0gY2h1bmsuYnl0ZUxlbmd0aDtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB3aGlsZSAoaW1hZ2UubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGVidWcoXCJXcml0ZSBsb29wIFwiICsgYWRkcmVzcyArIFwiIFwiICsgc2VxICsgXCIgXCIgKyBibG9ja3MpO1xuICAgICAgICAgICAgICAgIHRoaXMuaW5mbyhcIldyaXRpbmcgYXQgMHhcIiArXG4gICAgICAgICAgICAgICAgICAgIChhZGRyZXNzICsgdG90YWxMZW5VbmNvbXByZXNzZWQpLnRvU3RyaW5nKDE2KSArXG4gICAgICAgICAgICAgICAgICAgIFwiLi4uIChcIiArXG4gICAgICAgICAgICAgICAgICAgIE1hdGguZmxvb3IoKDEwMCAqIChzZXEgKyAxKSkgLyBibG9ja3MpICtcbiAgICAgICAgICAgICAgICAgICAgXCIlKVwiKTtcbiAgICAgICAgICAgICAgICBjb25zdCBibG9jayA9IHRoaXMuYnN0clRvVWk4KGltYWdlLnNsaWNlKDAsIHRoaXMuRkxBU0hfV1JJVEVfU0laRSkpO1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmNvbXByZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxlblVuY29tcHJlc3NlZFByZXZpb3VzID0gdG90YWxMZW5VbmNvbXByZXNzZWQ7XG4gICAgICAgICAgICAgICAgICAgIGluZmxhdGUucHVzaChibG9jaywgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBibG9ja1VuY29tcHJlc3NlZCA9IHRvdGFsTGVuVW5jb21wcmVzc2VkIC0gbGVuVW5jb21wcmVzc2VkUHJldmlvdXM7XG4gICAgICAgICAgICAgICAgICAgIGxldCBibG9ja1RpbWVvdXQgPSAzMDAwO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy50aW1lb3V0UGVyTWIodGhpcy5FUkFTRV9XUklURV9USU1FT1VUX1BFUl9NQiwgYmxvY2tVbmNvbXByZXNzZWQpID4gMzAwMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYmxvY2tUaW1lb3V0ID0gdGhpcy50aW1lb3V0UGVyTWIodGhpcy5FUkFTRV9XUklURV9USU1FT1VUX1BFUl9NQiwgYmxvY2tVbmNvbXByZXNzZWQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLklTX1NUVUIgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBST00gY29kZSB3cml0ZXMgYmxvY2sgdG8gZmxhc2ggYmVmb3JlIEFDS2luZ1xuICAgICAgICAgICAgICAgICAgICAgICAgdGltZW91dCA9IGJsb2NrVGltZW91dDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmZsYXNoRGVmbEJsb2NrKGJsb2NrLCBzZXEsIHRpbWVvdXQpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5JU19TVFVCKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTdHViIEFDS3Mgd2hlbiBibG9jayBpcyByZWNlaXZlZCwgdGhlbiB3cml0ZXMgdG8gZmxhc2ggd2hpbGUgcmVjZWl2aW5nIHRoZSBibG9jayBhZnRlciBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgdGltZW91dCA9IGJsb2NrVGltZW91dDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVTUEVycm9yKFwiWWV0IHRvIGhhbmRsZSBOb24gQ29tcHJlc3NlZCB3cml0ZXNcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJ5dGVzU2VudCArPSBibG9jay5sZW5ndGg7XG4gICAgICAgICAgICAgICAgaW1hZ2UgPSBpbWFnZS5zbGljZSh0aGlzLkZMQVNIX1dSSVRFX1NJWkUsIGltYWdlLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgc2VxKys7XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMucmVwb3J0UHJvZ3Jlc3MpXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMucmVwb3J0UHJvZ3Jlc3MoaSwgYnl0ZXNTZW50LCB0b3RhbEJ5dGVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLklTX1NUVUIpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJlYWRSZWcodGhpcy5DSElQX0RFVEVDVF9NQUdJQ19SRUdfQUREUiwgdGltZW91dCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkID0gbmV3IERhdGUoKTtcbiAgICAgICAgICAgIGNvbnN0IHQgPSBkLmdldFRpbWUoKSAtIHQxO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuY29tcHJlc3MpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmluZm8oXCJXcm90ZSBcIiArXG4gICAgICAgICAgICAgICAgICAgIHVuY3NpemUgK1xuICAgICAgICAgICAgICAgICAgICBcIiBieXRlcyAoXCIgK1xuICAgICAgICAgICAgICAgICAgICBieXRlc1NlbnQgK1xuICAgICAgICAgICAgICAgICAgICBcIiBjb21wcmVzc2VkKSBhdCAweFwiICtcbiAgICAgICAgICAgICAgICAgICAgYWRkcmVzcy50b1N0cmluZygxNikgK1xuICAgICAgICAgICAgICAgICAgICBcIiBpbiBcIiArXG4gICAgICAgICAgICAgICAgICAgIHQgLyAxMDAwICtcbiAgICAgICAgICAgICAgICAgICAgXCIgc2Vjb25kcy5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2FsY21kNSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMuZmxhc2hNZDVzdW0oYWRkcmVzcywgdW5jc2l6ZSk7XG4gICAgICAgICAgICAgICAgaWYgKG5ldyBTdHJpbmcocmVzKS52YWx1ZU9mKCkgIT0gbmV3IFN0cmluZyhjYWxjbWQ1KS52YWx1ZU9mKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbmZvKFwiRmlsZSAgbWQ1OiBcIiArIGNhbGNtZDUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmluZm8oXCJGbGFzaCBtZDU6IFwiICsgcmVzKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVTUEVycm9yKFwiTUQ1IG9mIGZpbGUgZG9lcyBub3QgbWF0Y2ggZGF0YSBpbiBmbGFzaCFcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmluZm8oXCJIYXNoIG9mIGRhdGEgdmVyaWZpZWQuXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmluZm8oXCJMZWF2aW5nLi4uXCIpO1xuICAgICAgICBpZiAodGhpcy5JU19TVFVCKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmZsYXNoQmVnaW4oMCwgMCk7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5jb21wcmVzcykge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZmxhc2hEZWZsRmluaXNoKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmZsYXNoRmluaXNoKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVhZCBTUEkgZmxhc2ggbWFudWZhY3R1cmVyIGFuZCBkZXZpY2UgaWQuXG4gICAgICovXG4gICAgYXN5bmMgZmxhc2hJZCgpIHtcbiAgICAgICAgdGhpcy5kZWJ1ZyhcImZsYXNoX2lkXCIpO1xuICAgICAgICBjb25zdCBmbGFzaGlkID0gYXdhaXQgdGhpcy5yZWFkRmxhc2hJZCgpO1xuICAgICAgICB0aGlzLmluZm8oXCJNYW51ZmFjdHVyZXI6IFwiICsgKGZsYXNoaWQgJiAweGZmKS50b1N0cmluZygxNikpO1xuICAgICAgICBjb25zdCBmbGlkTG93Ynl0ZSA9IChmbGFzaGlkID4+IDE2KSAmIDB4ZmY7XG4gICAgICAgIHRoaXMuaW5mbyhcIkRldmljZTogXCIgKyAoKGZsYXNoaWQgPj4gOCkgJiAweGZmKS50b1N0cmluZygxNikgKyBmbGlkTG93Ynl0ZS50b1N0cmluZygxNikpO1xuICAgICAgICB0aGlzLmluZm8oXCJEZXRlY3RlZCBmbGFzaCBzaXplOiBcIiArIHRoaXMuREVURUNURURfRkxBU0hfU0laRVNbZmxpZExvd2J5dGVdKTtcbiAgICB9XG4gICAgYXN5bmMgZ2V0Rmxhc2hTaXplKCkge1xuICAgICAgICB0aGlzLmRlYnVnKFwiZmxhc2hfaWRcIik7XG4gICAgICAgIGNvbnN0IGZsYXNoaWQgPSBhd2FpdCB0aGlzLnJlYWRGbGFzaElkKCk7XG4gICAgICAgIGNvbnN0IGZsaWRMb3dieXRlID0gKGZsYXNoaWQgPj4gMTYpICYgMHhmZjtcbiAgICAgICAgcmV0dXJuIHRoaXMuREVURUNURURfRkxBU0hfU0laRVNfTlVNW2ZsaWRMb3dieXRlXTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU29mdCByZXNldCB0aGUgZGV2aWNlIGNoaXAuIFNvZnQgcmVzZXQgd2l0aCBydW4gdXNlciBjb2RlIGlzIHRoZSBjbG9zZXN0LlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc3RheUluQm9vdGxvYWRlciBGbGFnIHRvIGluZGljYXRlIGlmIHRvIHN0YXkgaW4gYm9vdGxvYWRlclxuICAgICAqL1xuICAgIGFzeW5jIHNvZnRSZXNldChzdGF5SW5Cb290bG9hZGVyKSB7XG4gICAgICAgIGlmICghdGhpcy5JU19TVFVCKSB7XG4gICAgICAgICAgICBpZiAoc3RheUluQm9vdGxvYWRlcikge1xuICAgICAgICAgICAgICAgIHJldHVybjsgLy8gUk9NIGJvb3Rsb2FkZXIgaXMgYWxyZWFkeSBpbiBib290bG9hZGVyIVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gXCJydW4gdXNlciBjb2RlXCIgaXMgYXMgY2xvc2UgdG8gYSBzb2Z0IHJlc2V0IGFzIHdlIGNhbiBkb1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5mbGFzaEJlZ2luKDAsIDApO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5mbGFzaEZpbmlzaChmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy5jaGlwLkNISVBfTkFNRSAhPSBcIkVTUDgyNjZcIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVTUEVycm9yKFwiU29mdCByZXNldHRpbmcgaXMgY3VycmVudGx5IG9ubHkgc3VwcG9ydGVkIG9uIEVTUDgyNjZcIik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoc3RheUluQm9vdGxvYWRlcikge1xuICAgICAgICAgICAgICAgIC8vIHNvZnQgcmVzZXR0aW5nIGZyb20gdGhlIHN0dWIgbG9hZGVyXG4gICAgICAgICAgICAgICAgLy8gd2lsbCByZS1sb2FkIHRoZSBST00gYm9vdGxvYWRlclxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZmxhc2hCZWdpbigwLCAwKTtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmZsYXNoRmluaXNoKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gcnVubmluZyB1c2VyIGNvZGUgZnJvbSBzdHViIGxvYWRlciByZXF1aXJlcyBzb21lIGhhY2tzXG4gICAgICAgICAgICAgICAgLy8gaW4gdGhlIHN0dWIgbG9hZGVyXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5jb21tYW5kKHRoaXMuRVNQX1JVTl9VU0VSX0NPREUsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBmYWxzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogRXhlY3V0ZSB0aGlzIGZ1bmN0aW9uIHRvIGV4ZWN1dGUgYWZ0ZXIgb3BlcmF0aW9uIHJlc2V0IGZ1bmN0aW9ucy5cbiAgICAgKiBAcGFyYW0ge0FmdGVyfSBtb2RlIEFmdGVyIG9wZXJhdGlvbiBtb2RlLiBEZWZhdWx0IGlzICdoYXJkX3Jlc2V0Jy5cbiAgICAgKiBAcGFyYW0geyBib29sZWFuIH0gdXNpbmdVc2JPdGcgRm9yICdoYXJkX3Jlc2V0JyB0byBzcGVjaWZ5IGlmIHVzaW5nIFVTQi1PVEdcbiAgICAgKi9cbiAgICBhc3luYyBhZnRlcihtb2RlID0gXCJoYXJkX3Jlc2V0XCIsIHVzaW5nVXNiT3RnKSB7XG4gICAgICAgIHN3aXRjaCAobW9kZSkge1xuICAgICAgICAgICAgY2FzZSBcImhhcmRfcmVzZXRcIjpcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yZXNldENvbnN0cnVjdG9ycy5oYXJkUmVzZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbmZvKFwiSGFyZCByZXNldHRpbmcgdmlhIFJUUyBwaW4uLi5cIik7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGhhcmRSZXNldCA9IHRoaXMucmVzZXRDb25zdHJ1Y3RvcnMuaGFyZFJlc2V0KHRoaXMudHJhbnNwb3J0LCB1c2luZ1VzYk90Zyk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGhhcmRSZXNldC5yZXNldCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJzb2Z0X3Jlc2V0XCI6XG4gICAgICAgICAgICAgICAgdGhpcy5pbmZvKFwiU29mdCByZXNldHRpbmcuLi5cIik7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zb2Z0UmVzZXQoZmFsc2UpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIm5vX3Jlc2V0X3N0dWJcIjpcbiAgICAgICAgICAgICAgICB0aGlzLmluZm8oXCJTdGF5aW5nIGluIGZsYXNoZXIgc3R1Yi5cIik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRoaXMuaW5mbyhcIlN0YXlpbmcgaW4gYm9vdGxvYWRlci5cIik7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuSVNfU1RVQikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNvZnRSZXNldCh0cnVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCJleHBvcnQgeyBFU1BMb2FkZXIgfSBmcm9tIFwiLi9lc3Bsb2FkZXIuanNcIjtcbmV4cG9ydCB7IENsYXNzaWNSZXNldCwgQ3VzdG9tUmVzZXQsIEhhcmRSZXNldCwgVXNiSnRhZ1NlcmlhbFJlc2V0LCB2YWxpZGF0ZUN1c3RvbVJlc2V0U3RyaW5nU2VxdWVuY2UsIH0gZnJvbSBcIi4vcmVzZXQuanNcIjtcbmV4cG9ydCB7IFJPTSB9IGZyb20gXCIuL3RhcmdldHMvcm9tLmpzXCI7XG5leHBvcnQgeyBUcmFuc3BvcnQgfSBmcm9tIFwiLi93ZWJzZXJpYWwuanNcIjtcbmV4cG9ydCB7IGRlY29kZUJhc2U2NERhdGEsIGdldFN0dWJKc29uQnlDaGlwTmFtZSB9IGZyb20gXCIuL3N0dWJGbGFzaGVyLmpzXCI7XG4iLCIvKipcbiAqIFNsZWVwIGZvciBtcyBtaWxsaXNlY29uZHNcbiAqIEBwYXJhbSB7bnVtYmVyfSBtcyBNaWxsaXNlY29uZHMgdG8gd2FpdFxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gKi9cbmZ1bmN0aW9uIHNsZWVwKG1zKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG59XG4vKipcbiAqIEV4ZWN1dGUgYSBjbGFzc2ljIHNldCBvZiBjb21tYW5kcyB0aGF0IHdpbGwgcmVzZXQgdGhlIGNoaXAuXG4gKlxuICogQ29tbWFuZHMgKGUuZy4gUjApIGFyZSBkZWZpbmVkIGJ5IGEgY29kZSAoUikgYW5kIGFuIGFyZ3VtZW50ICgwKS5cbiAqXG4gKiBUaGUgY29tbWFuZHMgYXJlOlxuICpcbiAqIEQ6IHNldERUUiAtIDE9VHJ1ZSAvIDA9RmFsc2VcbiAqXG4gKiBSOiBzZXRSVFMgLSAxPVRydWUgLyAwPUZhbHNlXG4gKlxuICogVzogV2FpdCAodGltZSBkZWxheSkgLSBwb3NpdGl2ZSBpbnRlZ2VyIG51bWJlciAobWlsaXNlY29uZHMpXG4gKlxuICogXCJEMHxSMXxXMTAwfEQxfFIwfFc1MHxEMFwiIHJlcHJlc2VudHMgdGhlIGNsYXNzaWMgcmVzZXQgc3RyYXRlZ3lcbiAqIEBwYXJhbSB7VHJhbnNwb3J0fSB0cmFuc3BvcnQgVHJhbnNwb3J0IGNsYXNzIHRvIHBlcmZvcm0gc2VyaWFsIGNvbW11bmljYXRpb24uXG4gKiBAcGFyYW0ge251bWJlcn0gcmVzZXREZWxheSBEZWxheSBpbiBtaWxsaXNlY29uZHMgZm9yIHJlc2V0LlxuICovXG5leHBvcnQgY2xhc3MgQ2xhc3NpY1Jlc2V0IHtcbiAgICBjb25zdHJ1Y3Rvcih0cmFuc3BvcnQsIHJlc2V0RGVsYXkpIHtcbiAgICAgICAgdGhpcy5yZXNldERlbGF5ID0gcmVzZXREZWxheTtcbiAgICAgICAgdGhpcy50cmFuc3BvcnQgPSB0cmFuc3BvcnQ7XG4gICAgfVxuICAgIGFzeW5jIHJlc2V0KCkge1xuICAgICAgICBhd2FpdCB0aGlzLnRyYW5zcG9ydC5zZXREVFIoZmFsc2UpO1xuICAgICAgICBhd2FpdCB0aGlzLnRyYW5zcG9ydC5zZXRSVFModHJ1ZSk7XG4gICAgICAgIGF3YWl0IHNsZWVwKDEwMCk7XG4gICAgICAgIGF3YWl0IHRoaXMudHJhbnNwb3J0LnNldERUUih0cnVlKTtcbiAgICAgICAgYXdhaXQgdGhpcy50cmFuc3BvcnQuc2V0UlRTKGZhbHNlKTtcbiAgICAgICAgYXdhaXQgc2xlZXAodGhpcy5yZXNldERlbGF5KTtcbiAgICAgICAgYXdhaXQgdGhpcy50cmFuc3BvcnQuc2V0RFRSKGZhbHNlKTtcbiAgICB9XG59XG4vKipcbiAqIEV4ZWN1dGUgYSBzZXQgb2YgY29tbWFuZHMgZm9yIFVTQiBKVEFHIHNlcmlhbCByZXNldC5cbiAqXG4gKiBDb21tYW5kcyAoZS5nLiBSMCkgYXJlIGRlZmluZWQgYnkgYSBjb2RlIChSKSBhbmQgYW4gYXJndW1lbnQgKDApLlxuICpcbiAqIFRoZSBjb21tYW5kcyBhcmU6XG4gKlxuICogRDogc2V0RFRSIC0gMT1UcnVlIC8gMD1GYWxzZVxuICpcbiAqIFI6IHNldFJUUyAtIDE9VHJ1ZSAvIDA9RmFsc2VcbiAqXG4gKiBXOiBXYWl0ICh0aW1lIGRlbGF5KSAtIHBvc2l0aXZlIGludGVnZXIgbnVtYmVyIChtaWxpc2Vjb25kcylcbiAqIEBwYXJhbSB7VHJhbnNwb3J0fSB0cmFuc3BvcnQgVHJhbnNwb3J0IGNsYXNzIHRvIHBlcmZvcm0gc2VyaWFsIGNvbW11bmljYXRpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBVc2JKdGFnU2VyaWFsUmVzZXQge1xuICAgIGNvbnN0cnVjdG9yKHRyYW5zcG9ydCkge1xuICAgICAgICB0aGlzLnRyYW5zcG9ydCA9IHRyYW5zcG9ydDtcbiAgICB9XG4gICAgYXN5bmMgcmVzZXQoKSB7XG4gICAgICAgIGF3YWl0IHRoaXMudHJhbnNwb3J0LnNldFJUUyhmYWxzZSk7XG4gICAgICAgIGF3YWl0IHRoaXMudHJhbnNwb3J0LnNldERUUihmYWxzZSk7XG4gICAgICAgIGF3YWl0IHNsZWVwKDEwMCk7XG4gICAgICAgIGF3YWl0IHRoaXMudHJhbnNwb3J0LnNldERUUih0cnVlKTtcbiAgICAgICAgYXdhaXQgdGhpcy50cmFuc3BvcnQuc2V0UlRTKGZhbHNlKTtcbiAgICAgICAgYXdhaXQgc2xlZXAoMTAwKTtcbiAgICAgICAgYXdhaXQgdGhpcy50cmFuc3BvcnQuc2V0UlRTKHRydWUpO1xuICAgICAgICBhd2FpdCB0aGlzLnRyYW5zcG9ydC5zZXREVFIoZmFsc2UpO1xuICAgICAgICBhd2FpdCB0aGlzLnRyYW5zcG9ydC5zZXRSVFModHJ1ZSk7XG4gICAgICAgIGF3YWl0IHNsZWVwKDEwMCk7XG4gICAgICAgIGF3YWl0IHRoaXMudHJhbnNwb3J0LnNldFJUUyhmYWxzZSk7XG4gICAgICAgIGF3YWl0IHRoaXMudHJhbnNwb3J0LnNldERUUihmYWxzZSk7XG4gICAgfVxufVxuLyoqXG4gKiBFeGVjdXRlIGEgc2V0IG9mIGNvbW1hbmRzIHRoYXQgd2lsbCBoYXJkIHJlc2V0IHRoZSBjaGlwLlxuICpcbiAqIENvbW1hbmRzIChlLmcuIFIwKSBhcmUgZGVmaW5lZCBieSBhIGNvZGUgKFIpIGFuZCBhbiBhcmd1bWVudCAoMCkuXG4gKlxuICogVGhlIGNvbW1hbmRzIGFyZTpcbiAqXG4gKiBEOiBzZXREVFIgLSAxPVRydWUgLyAwPUZhbHNlXG4gKlxuICogUjogc2V0UlRTIC0gMT1UcnVlIC8gMD1GYWxzZVxuICpcbiAqIFc6IFdhaXQgKHRpbWUgZGVsYXkpIC0gcG9zaXRpdmUgaW50ZWdlciBudW1iZXIgKG1pbGlzZWNvbmRzKVxuICogQHBhcmFtIHtUcmFuc3BvcnR9IHRyYW5zcG9ydCBUcmFuc3BvcnQgY2xhc3MgdG8gcGVyZm9ybSBzZXJpYWwgY29tbXVuaWNhdGlvbi5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gdXNpbmdVc2JPdGcgaXMgaXQgdXNpbmcgVVNCLU9URyA/XG4gKi9cbmV4cG9ydCBjbGFzcyBIYXJkUmVzZXQge1xuICAgIGNvbnN0cnVjdG9yKHRyYW5zcG9ydCwgdXNpbmdVc2JPdGcgPSBmYWxzZSkge1xuICAgICAgICB0aGlzLnRyYW5zcG9ydCA9IHRyYW5zcG9ydDtcbiAgICAgICAgdGhpcy51c2luZ1VzYk90ZyA9IHVzaW5nVXNiT3RnO1xuICAgICAgICB0aGlzLnRyYW5zcG9ydCA9IHRyYW5zcG9ydDtcbiAgICB9XG4gICAgYXN5bmMgcmVzZXQoKSB7XG4gICAgICAgIGlmICh0aGlzLnVzaW5nVXNiT3RnKSB7XG4gICAgICAgICAgICBhd2FpdCBzbGVlcCgyMDApO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy50cmFuc3BvcnQuc2V0UlRTKGZhbHNlKTtcbiAgICAgICAgICAgIGF3YWl0IHNsZWVwKDIwMCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBhd2FpdCBzbGVlcCgxMDApO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy50cmFuc3BvcnQuc2V0UlRTKGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbi8qKlxuICogVmFsaWRhdGUgYSBzZXF1ZW5jZSBzdHJpbmcgYmFzZWQgb24gdGhlIGZvbGxvd2luZyBmb3JtYXQ6XG4gKlxuICogQ29tbWFuZHMgKGUuZy4gUjApIGFyZSBkZWZpbmVkIGJ5IGEgY29kZSAoUikgYW5kIGFuIGFyZ3VtZW50ICgwKS5cbiAqXG4gKiBUaGUgY29tbWFuZHMgYXJlOlxuICpcbiAqIEQ6IHNldERUUiAtIDE9VHJ1ZSAvIDA9RmFsc2VcbiAqXG4gKiBSOiBzZXRSVFMgLSAxPVRydWUgLyAwPUZhbHNlXG4gKlxuICogVzogV2FpdCAodGltZSBkZWxheSkgLSBwb3NpdGl2ZSBpbnRlZ2VyIG51bWJlciAobWlsaXNlY29uZHMpXG4gKiBAcGFyYW0ge3N0cmluZ30gc2VxU3RyIFNlcXVlbmNlIHN0cmluZyB0byB2YWxpZGF0ZVxuICogQHJldHVybnMge2Jvb2xlYW59IElzIHRoZSBzZXF1ZW5jZSBzdHJpbmcgdmFsaWQgP1xuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVDdXN0b21SZXNldFN0cmluZ1NlcXVlbmNlKHNlcVN0cikge1xuICAgIGNvbnN0IGNvbW1hbmRzID0gW1wiRFwiLCBcIlJcIiwgXCJXXCJdO1xuICAgIGNvbnN0IGNvbW1hbmRzTGlzdCA9IHNlcVN0ci5zcGxpdChcInxcIik7XG4gICAgZm9yIChjb25zdCBjbWQgb2YgY29tbWFuZHNMaXN0KSB7XG4gICAgICAgIGNvbnN0IGNvZGUgPSBjbWRbMF07XG4gICAgICAgIGNvbnN0IGFyZyA9IGNtZC5zbGljZSgxKTtcbiAgICAgICAgaWYgKCFjb21tYW5kcy5pbmNsdWRlcyhjb2RlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBJbnZhbGlkIGNvbW1hbmQgY29kZVxuICAgICAgICB9XG4gICAgICAgIGlmIChjb2RlID09PSBcIkRcIiB8fCBjb2RlID09PSBcIlJcIikge1xuICAgICAgICAgICAgaWYgKGFyZyAhPT0gXCIwXCIgJiYgYXJnICE9PSBcIjFcIikge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsgLy8gSW52YWxpZCBhcmd1bWVudCBmb3IgRCBhbmQgUiBjb21tYW5kc1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGNvZGUgPT09IFwiV1wiKSB7XG4gICAgICAgICAgICBjb25zdCBkZWxheSA9IHBhcnNlSW50KGFyZyk7XG4gICAgICAgICAgICBpZiAoaXNOYU4oZGVsYXkpIHx8IGRlbGF5IDw9IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7IC8vIEludmFsaWQgYXJndW1lbnQgZm9yIFcgY29tbWFuZFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlOyAvLyBBbGwgY29tbWFuZHMgYXJlIHZhbGlkXG59XG4vKipcbiAqIEN1c3RvbSByZXNldCBzdHJhdGVneSBkZWZpbmVkIHdpdGggYSBzdHJpbmcuXG4gKlxuICogVGhlIHNlcXVlbmNlU3RyaW5nIGlucHV0IHN0cmluZyBjb25zaXN0cyBvZiBpbmRpdmlkdWFsIGNvbW1hbmRzIGRpdmlkZWQgYnkgXCJ8XCIuXG4gKlxuICogQ29tbWFuZHMgKGUuZy4gUjApIGFyZSBkZWZpbmVkIGJ5IGEgY29kZSAoUikgYW5kIGFuIGFyZ3VtZW50ICgwKS5cbiAqXG4gKiBUaGUgY29tbWFuZHMgYXJlOlxuICpcbiAqIEQ6IHNldERUUiAtIDE9VHJ1ZSAvIDA9RmFsc2VcbiAqXG4gKiBSOiBzZXRSVFMgLSAxPVRydWUgLyAwPUZhbHNlXG4gKlxuICogVzogV2FpdCAodGltZSBkZWxheSkgLSBwb3NpdGl2ZSBpbnRlZ2VyIG51bWJlciAobWlsaXNlY29uZHMpXG4gKlxuICogXCJEMHxSMXxXMTAwfEQxfFIwfFc1MHxEMFwiIHJlcHJlc2VudHMgdGhlIGNsYXNzaWMgcmVzZXQgc3RyYXRlZ3lcbiAqIEBwYXJhbSB7VHJhbnNwb3J0fSB0cmFuc3BvcnQgVHJhbnNwb3J0IGNsYXNzIHRvIHBlcmZvcm0gc2VyaWFsIGNvbW11bmljYXRpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gc2VxdWVuY2VTdHJpbmcgQ3VzdG9tIHN0cmluZyBzZXF1ZW5jZSBmb3IgcmVzZXQgc3RyYXRlZ3lcbiAqL1xuZXhwb3J0IGNsYXNzIEN1c3RvbVJlc2V0IHtcbiAgICBjb25zdHJ1Y3Rvcih0cmFuc3BvcnQsIHNlcXVlbmNlU3RyaW5nKSB7XG4gICAgICAgIHRoaXMudHJhbnNwb3J0ID0gdHJhbnNwb3J0O1xuICAgICAgICB0aGlzLnNlcXVlbmNlU3RyaW5nID0gc2VxdWVuY2VTdHJpbmc7XG4gICAgICAgIHRoaXMudHJhbnNwb3J0ID0gdHJhbnNwb3J0O1xuICAgIH1cbiAgICBhc3luYyByZXNldCgpIHtcbiAgICAgICAgY29uc3QgcmVzZXREaWN0aW9uYXJ5ID0ge1xuICAgICAgICAgICAgRDogYXN5bmMgKGFyZykgPT4gYXdhaXQgdGhpcy50cmFuc3BvcnQuc2V0RFRSKGFyZyksXG4gICAgICAgICAgICBSOiBhc3luYyAoYXJnKSA9PiBhd2FpdCB0aGlzLnRyYW5zcG9ydC5zZXRSVFMoYXJnKSxcbiAgICAgICAgICAgIFc6IGFzeW5jIChkZWxheSkgPT4gYXdhaXQgc2xlZXAoZGVsYXkpLFxuICAgICAgICB9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgaXNWYWxpZFNlcXVlbmNlID0gdmFsaWRhdGVDdXN0b21SZXNldFN0cmluZ1NlcXVlbmNlKHRoaXMuc2VxdWVuY2VTdHJpbmcpO1xuICAgICAgICAgICAgaWYgKCFpc1ZhbGlkU2VxdWVuY2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBjbWRzID0gdGhpcy5zZXF1ZW5jZVN0cmluZy5zcGxpdChcInxcIik7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNtZCBvZiBjbWRzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY21kS2V5ID0gY21kWzBdO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNtZFZhbCA9IGNtZC5zbGljZSgxKTtcbiAgICAgICAgICAgICAgICBpZiAoY21kS2V5ID09PSBcIldcIikge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCByZXNldERpY3Rpb25hcnlbXCJXXCJdKE51bWJlcihjbWRWYWwpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoY21kS2V5ID09PSBcIkRcIiB8fCBjbWRLZXkgPT09IFwiUlwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHJlc2V0RGljdGlvbmFyeVtjbWRLZXldKGNtZFZhbCA9PT0gXCIxXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgY3VzdG9tIHJlc2V0IHNlcXVlbmNlXCIpO1xuICAgICAgICB9XG4gICAgfVxufVxuZXhwb3J0IGRlZmF1bHQgeyBDbGFzc2ljUmVzZXQsIEN1c3RvbVJlc2V0LCBIYXJkUmVzZXQsIFVzYkp0YWdTZXJpYWxSZXNldCwgdmFsaWRhdGVDdXN0b21SZXNldFN0cmluZ1NlcXVlbmNlIH07XG4iLCJpbXBvcnQgYXRvYiBmcm9tIFwiYXRvYi1saXRlXCI7XG4vKipcbiAqIEltcG9ydCBmbGFzaCBzdHViIGpzb24gZm9yIHRoZSBnaXZlbiBjaGlwIG5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gY2hpcE5hbWUgTmFtZSBvZiBjaGlwIHRvIG9idGFpbiBmbGFzaGVyIHN0dWJcbiAqIEByZXR1cm5zIHtTdHVifSBTdHViIGluZm9ybWF0aW9uIGFuZCBkZWNvZGVkIHRleHQgYW5kIGRhdGFcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFN0dWJKc29uQnlDaGlwTmFtZShjaGlwTmFtZSkge1xuICAgIGxldCBqc29uU3R1YjtcbiAgICBzd2l0Y2ggKGNoaXBOYW1lKSB7XG4gICAgICAgIGNhc2UgXCJFU1AzMlwiOlxuICAgICAgICAgICAganNvblN0dWIgPSBhd2FpdCBpbXBvcnQoXCIuL3RhcmdldHMvc3R1Yl9mbGFzaGVyL3N0dWJfZmxhc2hlcl8zMi5qc29uXCIpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJFU1AzMi1DMlwiOlxuICAgICAgICAgICAganNvblN0dWIgPSBhd2FpdCBpbXBvcnQoXCIuL3RhcmdldHMvc3R1Yl9mbGFzaGVyL3N0dWJfZmxhc2hlcl8zMmMyLmpzb25cIik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcIkVTUDMyLUMzXCI6XG4gICAgICAgICAgICBqc29uU3R1YiA9IGF3YWl0IGltcG9ydChcIi4vdGFyZ2V0cy9zdHViX2ZsYXNoZXIvc3R1Yl9mbGFzaGVyXzMyYzMuanNvblwiKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiRVNQMzItQzVcIjpcbiAgICAgICAgICAgIGpzb25TdHViID0gYXdhaXQgaW1wb3J0KFwiLi90YXJnZXRzL3N0dWJfZmxhc2hlci9zdHViX2ZsYXNoZXJfMzJjNS5qc29uXCIpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJFU1AzMi1DNlwiOlxuICAgICAgICAgICAganNvblN0dWIgPSBhd2FpdCBpbXBvcnQoXCIuL3RhcmdldHMvc3R1Yl9mbGFzaGVyL3N0dWJfZmxhc2hlcl8zMmM2Lmpzb25cIik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcIkVTUDMyLUM2MVwiOlxuICAgICAgICAgICAganNvblN0dWIgPSBhd2FpdCBpbXBvcnQoXCIuL3RhcmdldHMvc3R1Yl9mbGFzaGVyL3N0dWJfZmxhc2hlcl8zMmM2MS5qc29uXCIpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJFU1AzMi1IMlwiOlxuICAgICAgICAgICAganNvblN0dWIgPSBhd2FpdCBpbXBvcnQoXCIuL3RhcmdldHMvc3R1Yl9mbGFzaGVyL3N0dWJfZmxhc2hlcl8zMmgyLmpzb25cIik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcIkVTUDMyLVA0XCI6XG4gICAgICAgICAgICBqc29uU3R1YiA9IGF3YWl0IGltcG9ydChcIi4vdGFyZ2V0cy9zdHViX2ZsYXNoZXIvc3R1Yl9mbGFzaGVyXzMycDQuanNvblwiKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiRVNQMzItUzJcIjpcbiAgICAgICAgICAgIGpzb25TdHViID0gYXdhaXQgaW1wb3J0KFwiLi90YXJnZXRzL3N0dWJfZmxhc2hlci9zdHViX2ZsYXNoZXJfMzJzMi5qc29uXCIpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJFU1AzMi1TM1wiOlxuICAgICAgICAgICAganNvblN0dWIgPSBhd2FpdCBpbXBvcnQoXCIuL3RhcmdldHMvc3R1Yl9mbGFzaGVyL3N0dWJfZmxhc2hlcl8zMnMzLmpzb25cIik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcIkVTUDgyNjZcIjpcbiAgICAgICAgICAgIGpzb25TdHViID0gYXdhaXQgaW1wb3J0KFwiLi90YXJnZXRzL3N0dWJfZmxhc2hlci9zdHViX2ZsYXNoZXJfODI2Ni5qc29uXCIpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGlmIChqc29uU3R1Yikge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgYnNzX3N0YXJ0OiBqc29uU3R1Yi5ic3Nfc3RhcnQsXG4gICAgICAgICAgICBkYXRhOiBqc29uU3R1Yi5kYXRhLFxuICAgICAgICAgICAgZGF0YV9zdGFydDoganNvblN0dWIuZGF0YV9zdGFydCxcbiAgICAgICAgICAgIGVudHJ5OiBqc29uU3R1Yi5lbnRyeSxcbiAgICAgICAgICAgIHRleHQ6IGpzb25TdHViLnRleHQsXG4gICAgICAgICAgICB0ZXh0X3N0YXJ0OiBqc29uU3R1Yi50ZXh0X3N0YXJ0LFxuICAgICAgICAgICAgZGVjb2RlZERhdGE6IGRlY29kZUJhc2U2NERhdGEoanNvblN0dWIuZGF0YSksXG4gICAgICAgICAgICBkZWNvZGVkVGV4dDogZGVjb2RlQmFzZTY0RGF0YShqc29uU3R1Yi50ZXh0KSxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuO1xufVxuLyoqXG4gKiBDb252ZXJ0IGEgYmFzZSA2NCBzdHJpbmcgdG8gVWludDhBcnJheS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhU3RyIEJhc2U2NCBTdHJpbmcgdG8gZGVjb2RlXG4gKiBAcmV0dXJucyB7VWludDhBcnJheX0gRGVjb2RlZCBVaW50OEFycmF5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVCYXNlNjREYXRhKGRhdGFTdHIpIHtcbiAgICBjb25zdCBkZWNvZGVkID0gYXRvYihkYXRhU3RyKTtcbiAgICBjb25zdCBjaGFyZGF0YSA9IGRlY29kZWQuc3BsaXQoXCJcIikubWFwKGZ1bmN0aW9uICh4KSB7XG4gICAgICAgIHJldHVybiB4LmNoYXJDb2RlQXQoMCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGNoYXJkYXRhKTtcbn1cbiIsIi8qKlxuICogUmVwcmVzZW50cyBhIGNoaXAgUk9NIHdpdGggYmFzaWMgcmVnaXN0ZXJzIGZpZWxkIGFuZCBhYnN0cmFjdCBmdW5jdGlvbnMuXG4gKi9cbmV4cG9ydCBjbGFzcyBST00ge1xuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY2hpcCBlcmFzZSBzaXplLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgLSBPZmZzZXQgdG8gc3RhcnQgZXJhc2UuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHNpemUgLSBTaXplIHRvIGVyYXNlLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFRoZSBlcmFzZSBzaXplIG9mIHRoZSBjaGlwIGFzIG51bWJlci5cbiAgICAgKi9cbiAgICBnZXRFcmFzZVNpemUob2Zmc2V0LCBzaXplKSB7XG4gICAgICAgIHJldHVybiBzaXplO1xuICAgIH1cbn1cbiIsIi8qKlxuICogUmVwcmVzZW50cyBhIEVzcHJlc3NpZiBjaGlwIGVycm9yLlxuICovXG5jbGFzcyBFU1BFcnJvciBleHRlbmRzIEVycm9yIHtcbn1cbi8qKlxuICogUmVwcmVzZW50cyBhIEVzcHJlc3NpZiB0aW1lb3V0IGNoaXAgZXJyb3IuXG4gKi9cbmNsYXNzIFRpbWVvdXRFcnJvciBleHRlbmRzIEVTUEVycm9yIHtcbn1cbmV4cG9ydCB7IEVTUEVycm9yLCBUaW1lb3V0RXJyb3IgfTtcbiIsIi8qKlxuICogUGFkIHRvIHRoZSBuZXh0IGFsaWdubWVudCBib3VuZGFyeVxuICogQHBhcmFtIHtVaW50OEFycmF5fSBkYXRhIFVpbnQ4QXJyYXkgZGF0YSB0byBwYWRcbiAqIEBwYXJhbSB7bnVtYmVyfSBhbGlnbm1lbnQgQWxpZ25tZW50IGJvdW5kYXJ5IHRvIGZ1bGZpbGxcbiAqIEBwYXJhbSB7bnVtYmVyfSBwYWRDaGFyYWN0ZXIgQ2hhcmFjdGVyIHRvIGZpbGwgd2l0aFxuICogQHJldHVybnMge1VpbnQ4QXJyYXl9IFBhZGRlZCBVSW50OEFycmF5IGltYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYWRUbyhkYXRhLCBhbGlnbm1lbnQsIHBhZENoYXJhY3RlciA9IDB4ZmYpIHtcbiAgICBjb25zdCBwYWRNb2QgPSBkYXRhLmxlbmd0aCAlIGFsaWdubWVudDtcbiAgICBpZiAocGFkTW9kICE9PSAwKSB7XG4gICAgICAgIGNvbnN0IHBhZGRpbmcgPSBuZXcgVWludDhBcnJheShhbGlnbm1lbnQgLSBwYWRNb2QpLmZpbGwocGFkQ2hhcmFjdGVyKTtcbiAgICAgICAgY29uc3QgcGFkZGVkRGF0YSA9IG5ldyBVaW50OEFycmF5KGRhdGEubGVuZ3RoICsgcGFkZGluZy5sZW5ndGgpO1xuICAgICAgICBwYWRkZWREYXRhLnNldChkYXRhKTtcbiAgICAgICAgcGFkZGVkRGF0YS5zZXQocGFkZGluZywgZGF0YS5sZW5ndGgpO1xuICAgICAgICByZXR1cm4gcGFkZGVkRGF0YTtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGE7XG59XG4iLCIvKiBnbG9iYWwgU2VyaWFsUG9ydCwgUGFyaXR5VHlwZSwgRmxvd0NvbnRyb2xUeXBlICovXG4vKipcbiAqIFdyYXBwZXIgY2xhc3MgYXJvdW5kIFdlYnNlcmlhbCBBUEkgdG8gY29tbXVuaWNhdGUgd2l0aCB0aGUgc2VyaWFsIGRldmljZS5cbiAqIEBwYXJhbSB7dHlwZW9mIGltcG9ydChcInczYy13ZWItc2VyaWFsXCIpLlNlcmlhbFBvcnR9IGRldmljZSAtIFJlcXVlc3RlZCBkZXZpY2UgcHJvbXB0ZWQgYnkgdGhlIGJyb3dzZXIuXG4gKlxuICogYGBgXG4gKiBjb25zdCBwb3J0ID0gYXdhaXQgbmF2aWdhdG9yLnNlcmlhbC5yZXF1ZXN0UG9ydCgpO1xuICogYGBgXG4gKi9cbmNsYXNzIFRyYW5zcG9ydCB7XG4gICAgY29uc3RydWN0b3IoZGV2aWNlLCB0cmFjaW5nID0gZmFsc2UsIGVuYWJsZVNsaXBSZWFkZXIgPSB0cnVlKSB7XG4gICAgICAgIHRoaXMuZGV2aWNlID0gZGV2aWNlO1xuICAgICAgICB0aGlzLnRyYWNpbmcgPSB0cmFjaW5nO1xuICAgICAgICB0aGlzLnNsaXBSZWFkZXJFbmFibGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuYmF1ZHJhdGUgPSAwO1xuICAgICAgICB0aGlzLnRyYWNlTG9nID0gXCJcIjtcbiAgICAgICAgdGhpcy5sYXN0VHJhY2VUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgdGhpcy5idWZmZXIgPSBuZXcgVWludDhBcnJheSgwKTtcbiAgICAgICAgdGhpcy5TTElQX0VORCA9IDB4YzA7XG4gICAgICAgIHRoaXMuU0xJUF9FU0MgPSAweGRiO1xuICAgICAgICB0aGlzLlNMSVBfRVNDX0VORCA9IDB4ZGM7XG4gICAgICAgIHRoaXMuU0xJUF9FU0NfRVNDID0gMHhkZDtcbiAgICAgICAgdGhpcy5fRFRSX3N0YXRlID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc2xpcFJlYWRlckVuYWJsZWQgPSBlbmFibGVTbGlwUmVhZGVyO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXF1ZXN0IHRoZSBzZXJpYWwgZGV2aWNlIHZlbmRvciBJRCBhbmQgUHJvZHVjdCBJRCBhcyBzdHJpbmcuXG4gICAgICogQHJldHVybnMge3N0cmluZ30gUmV0dXJuIHRoZSBkZXZpY2UgVmVuZG9ySUQgYW5kIFByb2R1Y3RJRCBmcm9tIFNlcmlhbFBvcnRJbmZvIGFzIGZvcm1hdHRlZCBzdHJpbmcuXG4gICAgICovXG4gICAgZ2V0SW5mbygpIHtcbiAgICAgICAgY29uc3QgaW5mbyA9IHRoaXMuZGV2aWNlLmdldEluZm8oKTtcbiAgICAgICAgcmV0dXJuIGluZm8udXNiVmVuZG9ySWQgJiYgaW5mby51c2JQcm9kdWN0SWRcbiAgICAgICAgICAgID8gYFdlYlNlcmlhbCBWZW5kb3JJRCAweCR7aW5mby51c2JWZW5kb3JJZC50b1N0cmluZygxNil9IFByb2R1Y3RJRCAweCR7aW5mby51c2JQcm9kdWN0SWQudG9TdHJpbmcoMTYpfWBcbiAgICAgICAgICAgIDogXCJcIjtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVxdWVzdCB0aGUgc2VyaWFsIGRldmljZSBwcm9kdWN0IGlkIGZyb20gU2VyaWFsUG9ydEluZm8uXG4gICAgICogQHJldHVybnMge251bWJlciB8IHVuZGVmaW5lZH0gUmV0dXJuIHRoZSBwcm9kdWN0IElELlxuICAgICAqL1xuICAgIGdldFBpZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGV2aWNlLmdldEluZm8oKS51c2JQcm9kdWN0SWQ7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEZvcm1hdCByZWNlaXZlZCBvciBzZW50IGRhdGEgZm9yIHRyYWNpbmcgb3V0cHV0LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIE1lc3NhZ2UgdG8gZm9ybWF0IGFzIHRyYWNlIGxpbmUuXG4gICAgICovXG4gICAgdHJhY2UobWVzc2FnZSkge1xuICAgICAgICBjb25zdCBkZWx0YSA9IERhdGUubm93KCkgLSB0aGlzLmxhc3RUcmFjZVRpbWU7XG4gICAgICAgIGNvbnN0IHByZWZpeCA9IGBUUkFDRSAke2RlbHRhLnRvRml4ZWQoMyl9YDtcbiAgICAgICAgY29uc3QgdHJhY2VNZXNzYWdlID0gYCR7cHJlZml4fSAke21lc3NhZ2V9YDtcbiAgICAgICAgY29uc29sZS5sb2codHJhY2VNZXNzYWdlKTtcbiAgICAgICAgdGhpcy50cmFjZUxvZyArPSB0cmFjZU1lc3NhZ2UgKyBcIlxcblwiO1xuICAgIH1cbiAgICBhc3luYyByZXR1cm5UcmFjZSgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KHRoaXMudHJhY2VMb2cpO1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJUZXh0IGNvcGllZCB0byBjbGlwYm9hcmQhXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJGYWlsZWQgdG8gY29weSB0ZXh0OlwiLCBlcnIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGhleGlmeShzKSB7XG4gICAgICAgIHJldHVybiBBcnJheS5mcm9tKHMpXG4gICAgICAgICAgICAubWFwKChieXRlKSA9PiBieXRlLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCBcIjBcIikpXG4gICAgICAgICAgICAuam9pbihcIlwiKVxuICAgICAgICAgICAgLnBhZEVuZCgxNiwgXCIgXCIpO1xuICAgIH1cbiAgICBoZXhDb252ZXJ0KHVpbnQ4QXJyYXksIGF1dG9TcGxpdCA9IHRydWUpIHtcbiAgICAgICAgaWYgKGF1dG9TcGxpdCAmJiB1aW50OEFycmF5Lmxlbmd0aCA+IDE2KSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gXCJcIjtcbiAgICAgICAgICAgIGxldCBzID0gdWludDhBcnJheTtcbiAgICAgICAgICAgIHdoaWxlIChzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsaW5lID0gcy5zbGljZSgwLCAxNik7XG4gICAgICAgICAgICAgICAgY29uc3QgYXNjaWlMaW5lID0gU3RyaW5nLmZyb21DaGFyQ29kZSguLi5saW5lKVxuICAgICAgICAgICAgICAgICAgICAuc3BsaXQoXCJcIilcbiAgICAgICAgICAgICAgICAgICAgLm1hcCgoYykgPT4gKGMgPT09IFwiIFwiIHx8IChjID49IFwiIFwiICYmIGMgPD0gXCJ+XCIgJiYgYyAhPT0gXCIgIFwiKSA/IGMgOiBcIi5cIikpXG4gICAgICAgICAgICAgICAgICAgIC5qb2luKFwiXCIpO1xuICAgICAgICAgICAgICAgIHMgPSBzLnNsaWNlKDE2KTtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gYFxcbiAgICAke3RoaXMuaGV4aWZ5KGxpbmUuc2xpY2UoMCwgOCkpfSAke3RoaXMuaGV4aWZ5KGxpbmUuc2xpY2UoOCkpfSB8ICR7YXNjaWlMaW5lfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGV4aWZ5KHVpbnQ4QXJyYXkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEZvcm1hdCBkYXRhIHBhY2tldCB1c2luZyB0aGUgU2VyaWFsIExpbmUgSW50ZXJuZXQgUHJvdG9jb2wgKFNMSVApLlxuICAgICAqIEBwYXJhbSB7VWludDhBcnJheX0gZGF0YSBCaW5hcnkgdW5zaWduZWQgOCBiaXQgYXJyYXkgZGF0YSB0byBmb3JtYXQuXG4gICAgICogQHJldHVybnMge1VpbnQ4QXJyYXl9IEZvcm1hdHRlZCB1bnNpZ25lZCA4IGJpdCBkYXRhIGFycmF5LlxuICAgICAqL1xuICAgIHNsaXBXcml0ZXIoZGF0YSkge1xuICAgICAgICBjb25zdCBvdXREYXRhID0gW107XG4gICAgICAgIG91dERhdGEucHVzaCgweGMwKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoZGF0YVtpXSA9PT0gMHhkYikge1xuICAgICAgICAgICAgICAgIG91dERhdGEucHVzaCgweGRiLCAweGRkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGRhdGFbaV0gPT09IDB4YzApIHtcbiAgICAgICAgICAgICAgICBvdXREYXRhLnB1c2goMHhkYiwgMHhkYyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBvdXREYXRhLnB1c2goZGF0YVtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgb3V0RGF0YS5wdXNoKDB4YzApO1xuICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkob3V0RGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFdyaXRlIGJpbmFyeSBkYXRhIHRvIGRldmljZSB1c2luZyB0aGUgV2ViU2VyaWFsIGRldmljZSB3cml0YWJsZSBzdHJlYW0uXG4gICAgICogQHBhcmFtIHtVaW50OEFycmF5fSBkYXRhIDggYml0IHVuc2lnbmVkIGRhdGEgYXJyYXkgdG8gd3JpdGUgdG8gZGV2aWNlLlxuICAgICAqL1xuICAgIGFzeW5jIHdyaXRlKGRhdGEpIHtcbiAgICAgICAgY29uc3Qgb3V0RGF0YSA9IHRoaXMuc2xpcFdyaXRlcihkYXRhKTtcbiAgICAgICAgaWYgKHRoaXMuZGV2aWNlLndyaXRhYmxlKSB7XG4gICAgICAgICAgICBjb25zdCB3cml0ZXIgPSB0aGlzLmRldmljZS53cml0YWJsZS5nZXRXcml0ZXIoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnRyYWNpbmcpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIldyaXRlIGJ5dGVzXCIpO1xuICAgICAgICAgICAgICAgIHRoaXMudHJhY2UoYFdyaXRlICR7b3V0RGF0YS5sZW5ndGh9IGJ5dGVzOiAke3RoaXMuaGV4Q29udmVydChvdXREYXRhKX1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF3YWl0IHdyaXRlci53cml0ZShvdXREYXRhKTtcbiAgICAgICAgICAgIHdyaXRlci5yZWxlYXNlTG9jaygpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFwcGVuZCBhIGJ1ZmZlciBhcnJheSBhZnRlciBhbm90aGVyIGJ1ZmZlciBhcnJheVxuICAgICAqIEBwYXJhbSB7VWludDhBcnJheX0gYXJyMSAtIEZpcnN0IGFycmF5IGJ1ZmZlci5cbiAgICAgKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGFycjIgLSBtYWdpYyBoZXggbnVtYmVyIHRvIHNlbGVjdCBST00uXG4gICAgICogQHJldHVybnMge1VpbnQ4QXJyYXl9IFJldHVybiBhIDggYml0IHVuc2lnbmVkIGFycmF5LlxuICAgICAqL1xuICAgIGFwcGVuZEFycmF5KGFycjEsIGFycjIpIHtcbiAgICAgICAgY29uc3QgY29tYmluZWQgPSBuZXcgVWludDhBcnJheShhcnIxLmxlbmd0aCArIGFycjIubGVuZ3RoKTtcbiAgICAgICAgY29tYmluZWQuc2V0KGFycjEpO1xuICAgICAgICBjb21iaW5lZC5zZXQoYXJyMiwgYXJyMS5sZW5ndGgpO1xuICAgICAgICByZXR1cm4gY29tYmluZWQ7XG4gICAgfVxuICAgIC8vIEFzeW5jaHJvbm91cyBnZW5lcmF0b3IgdG8geWllbGQgaW5jb21pbmcgZGF0YSBjaHVua3NcbiAgICBhc3luYyAqcmVhZExvb3AodGltZW91dCkge1xuICAgICAgICBpZiAoIXRoaXMucmVhZGVyKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0aW1lb3V0UHJvbWlzZSA9IG5ldyBQcm9taXNlKChfLCByZWplY3QpID0+IHNldFRpbWVvdXQoKCkgPT4gcmVqZWN0KG5ldyBFcnJvcihcIlJlYWQgdGltZW91dCBleGNlZWRlZFwiKSksIHRpbWVvdXQpKTtcbiAgICAgICAgICAgICAgICAvLyBBd2FpdCB0aGUgcmFjZSBiZXR3ZWVuIHRoZSB0aW1lb3V0IGFuZCB0aGUgcmVhZGVyIHJlYWRcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBQcm9taXNlLnJhY2UoW3RoaXMucmVhZGVyLnJlYWQoKSwgdGltZW91dFByb21pc2VdKTtcbiAgICAgICAgICAgICAgICAvLyBJZiBhIHRpbWVvdXQgb2NjdXJzLCByZXN1bHQgd2lsbCBiZSBudWxsOyBvdGhlcndpc2UsIGl0IHdpbGwgaGF2ZSB7IHZhbHVlLCBkb25lIH1cbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsKVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjb25zdCB7IHZhbHVlLCBkb25lIH0gPSByZXN1bHQ7XG4gICAgICAgICAgICAgICAgaWYgKGRvbmUgfHwgIXZhbHVlKVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB5aWVsZCB2YWx1ZTsgLy8gWWllbGQgZWFjaCBkYXRhIGNodW5rXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgcmVhZGluZyBmcm9tIHNlcmlhbCBwb3J0OlwiLCBlcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICB0aGlzLmJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KDApO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8vIFJlYWQgYSBzcGVjaWZpYyBudW1iZXIgb2YgYnl0ZXNcbiAgICBhc3luYyBuZXdSZWFkKG51bUJ5dGVzLCB0aW1lb3V0KSB7XG4gICAgICAgIGlmICh0aGlzLmJ1ZmZlci5sZW5ndGggPj0gbnVtQnl0ZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IG91dHB1dCA9IHRoaXMuYnVmZmVyLnNsaWNlKDAsIG51bUJ5dGVzKTtcbiAgICAgICAgICAgIHRoaXMuYnVmZmVyID0gdGhpcy5idWZmZXIuc2xpY2UobnVtQnl0ZXMpOyAvLyBSZW1vdmUgdGhlIHJldHVybmVkIGRhdGEgZnJvbSBidWZmZXJcbiAgICAgICAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUgKHRoaXMuYnVmZmVyLmxlbmd0aCA8IG51bUJ5dGVzKSB7XG4gICAgICAgICAgICBjb25zdCByZWFkTG9vcCA9IHRoaXMucmVhZExvb3AodGltZW91dCk7XG4gICAgICAgICAgICBjb25zdCB7IHZhbHVlLCBkb25lIH0gPSBhd2FpdCByZWFkTG9vcC5uZXh0KCk7XG4gICAgICAgICAgICBpZiAoZG9uZSB8fCAhdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEFwcGVuZCB0aGUgbmV3bHkgcmVhZCBkYXRhIHRvIHRoZSBidWZmZXJcbiAgICAgICAgICAgIHRoaXMuYnVmZmVyID0gdGhpcy5hcHBlbmRBcnJheSh0aGlzLmJ1ZmZlciwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJldHVybiBhcyBtdWNoIGRhdGEgYXMgcG9zc2libGVcbiAgICAgICAgY29uc3Qgb3V0cHV0ID0gdGhpcy5idWZmZXIuc2xpY2UoMCwgbnVtQnl0ZXMpO1xuICAgICAgICB0aGlzLmJ1ZmZlciA9IHRoaXMuYnVmZmVyLnNsaWNlKG51bUJ5dGVzKTtcbiAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICB9XG4gICAgYXN5bmMgZmx1c2hJbnB1dCgpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICBpZiAodGhpcy5yZWFkZXIgJiYgIShhd2FpdCB0aGlzLnJlYWRlci5jbG9zZWQpKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnJlYWRlci5jYW5jZWwoKTtcbiAgICAgICAgICAgIHRoaXMucmVhZGVyLnJlbGVhc2VMb2NrKCk7XG4gICAgICAgICAgICB0aGlzLnJlYWRlciA9IChfYSA9IHRoaXMuZGV2aWNlLnJlYWRhYmxlKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZ2V0UmVhZGVyKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYXN5bmMgZmx1c2hPdXRwdXQoKSB7XG4gICAgICAgIHZhciBfYSwgX2I7XG4gICAgICAgIHRoaXMuYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoMCk7XG4gICAgICAgIGF3YWl0ICgoX2EgPSB0aGlzLmRldmljZS53cml0YWJsZSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmdldFdyaXRlcigpLmNsb3NlKCkpO1xuICAgICAgICAoX2IgPSB0aGlzLmRldmljZS53cml0YWJsZSkgPT09IG51bGwgfHwgX2IgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9iLmdldFdyaXRlcigpLnJlbGVhc2VMb2NrKCk7XG4gICAgfVxuICAgIC8vIGBpbldhaXRpbmdgIHJldHVybnMgdGhlIGNvdW50IG9mIGJ5dGVzIGluIHRoZSBidWZmZXJcbiAgICBpbldhaXRpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmJ1ZmZlci5sZW5ndGg7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERldGVjdCBpZiB0aGUgZGF0YSByZWFkIGZyb20gZGV2aWNlIGlzIGEgRmF0YWwgb3IgR3VydSBtZWRpdGF0aW9uIGVycm9yLlxuICAgICAqIEBwYXJhbSB7VWludDhBcnJheX0gaW5wdXQgRGF0YSByZWFkIGZyb20gZGV2aWNlXG4gICAgICovXG4gICAgZGV0ZWN0UGFuaWNIYW5kbGVyKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IGd1cnVNZWRpdGF0aW9uUmVnZXggPSAvRz91cnUgTWVkaXRhdGlvbiBFcnJvcjogKD86Q29yZSBcXGQgcGFuaWMnZWQgXFwoKFthLXpBLVogXSopXFwpKT8vO1xuICAgICAgICBjb25zdCBmYXRhbEV4Y2VwdGlvblJlZ2V4ID0gL0Y/YXRhbCBleGNlcHRpb24gXFwoXFxkK1xcKTogKD86KFthLXpBLVogXSopPy4qZXBjKT8vO1xuICAgICAgICBjb25zdCBpbnB1dFN0cmluZyA9IG5ldyBUZXh0RGVjb2RlcihcInV0Zi04XCIpLmRlY29kZShpbnB1dCk7XG4gICAgICAgIGNvbnN0IG1hdGNoID0gaW5wdXRTdHJpbmcubWF0Y2goZ3VydU1lZGl0YXRpb25SZWdleCkgfHwgaW5wdXRTdHJpbmcubWF0Y2goZmF0YWxFeGNlcHRpb25SZWdleCk7XG4gICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgY29uc3QgY2F1c2UgPSBtYXRjaFsxXSB8fCBtYXRjaFsyXTtcbiAgICAgICAgICAgIGNvbnN0IG1zZyA9IGBHdXJ1IE1lZGl0YXRpb24gRXJyb3IgZGV0ZWN0ZWQke2NhdXNlID8gYCAoJHtjYXVzZX0pYCA6IFwiXCJ9YDtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRha2UgYSBkYXRhIGFycmF5IGFuZCByZXR1cm4gdGhlIGZpcnN0IHdlbGwgZm9ybWVkIHBhY2tldCBhZnRlclxuICAgICAqIHJlcGxhY2luZyB0aGUgZXNjYXBlIHNlcXVlbmNlLiBSZWFkcyBhdCBsZWFzdCA4IGJ5dGVzLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB0aW1lb3V0IFRpbWVvdXQgcmVhZCBkYXRhLlxuICAgICAqIEB5aWVsZHMge1VpbnQ4QXJyYXl9IEZvcm1hdHRlZCBwYWNrZXQgdXNpbmcgU0xJUCBlc2NhcGUgc2VxdWVuY2VzLlxuICAgICAqL1xuICAgIGFzeW5jICpyZWFkKHRpbWVvdXQpIHtcbiAgICAgICAgdmFyIF9hO1xuICAgICAgICBpZiAoIXRoaXMucmVhZGVyKSB7XG4gICAgICAgICAgICB0aGlzLnJlYWRlciA9IChfYSA9IHRoaXMuZGV2aWNlLnJlYWRhYmxlKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZ2V0UmVhZGVyKCk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHBhcnRpYWxQYWNrZXQgPSBudWxsO1xuICAgICAgICBsZXQgaXNFc2NhcGluZyA9IGZhbHNlO1xuICAgICAgICBsZXQgc3VjY2Vzc2Z1bFNsaXAgPSBmYWxzZTtcbiAgICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgICAgIGNvbnN0IHdhaXRpbmdCeXRlcyA9IHRoaXMuaW5XYWl0aW5nKCk7XG4gICAgICAgICAgICBjb25zdCByZWFkQnl0ZXMgPSBhd2FpdCB0aGlzLm5ld1JlYWQod2FpdGluZ0J5dGVzID4gMCA/IHdhaXRpbmdCeXRlcyA6IDEsIHRpbWVvdXQpO1xuICAgICAgICAgICAgaWYgKCFyZWFkQnl0ZXMgfHwgcmVhZEJ5dGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG1zZyA9IHBhcnRpYWxQYWNrZXQgPT09IG51bGxcbiAgICAgICAgICAgICAgICAgICAgPyBzdWNjZXNzZnVsU2xpcFxuICAgICAgICAgICAgICAgICAgICAgICAgPyBcIlNlcmlhbCBkYXRhIHN0cmVhbSBzdG9wcGVkOiBQb3NzaWJsZSBzZXJpYWwgbm9pc2Ugb3IgY29ycnVwdGlvbi5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgOiBcIk5vIHNlcmlhbCBkYXRhIHJlY2VpdmVkLlwiXG4gICAgICAgICAgICAgICAgICAgIDogYFBhY2tldCBjb250ZW50IHRyYW5zZmVyIHN0b3BwZWRgO1xuICAgICAgICAgICAgICAgIHRoaXMudHJhY2UobXNnKTtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudHJhY2UoYFJlYWQgJHtyZWFkQnl0ZXMubGVuZ3RofSBieXRlczogJHt0aGlzLmhleENvbnZlcnQocmVhZEJ5dGVzKX1gKTtcbiAgICAgICAgICAgIGxldCBpID0gMDsgLy8gVHJhY2sgcG9zaXRpb24gaW4gcmVhZEJ5dGVzXG4gICAgICAgICAgICB3aGlsZSAoaSA8IHJlYWRCeXRlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBieXRlID0gcmVhZEJ5dGVzW2krK107XG4gICAgICAgICAgICAgICAgaWYgKHBhcnRpYWxQYWNrZXQgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGJ5dGUgPT09IHRoaXMuU0xJUF9FTkQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnRpYWxQYWNrZXQgPSBuZXcgVWludDhBcnJheSgwKTsgLy8gU3RhcnQgb2YgYSBuZXcgcGFja2V0XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYWNlKGBSZWFkIGludmFsaWQgZGF0YTogJHt0aGlzLmhleENvbnZlcnQocmVhZEJ5dGVzKX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlbWFpbmluZ0RhdGEgPSBhd2FpdCB0aGlzLm5ld1JlYWQodGhpcy5pbldhaXRpbmcoKSwgdGltZW91dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYWNlKGBSZW1haW5pbmcgZGF0YSBpbiBzZXJpYWwgYnVmZmVyOiAke3RoaXMuaGV4Q29udmVydChyZW1haW5pbmdEYXRhKX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGV0ZWN0UGFuaWNIYW5kbGVyKG5ldyBVaW50OEFycmF5KFsuLi5yZWFkQnl0ZXMsIC4uLihyZW1haW5pbmdEYXRhIHx8IFtdKV0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBoZWFkIG9mIHBhY2tldCAoMHgke2J5dGUudG9TdHJpbmcoMTYpfSk6IFBvc3NpYmxlIHNlcmlhbCBub2lzZSBvciBjb3JydXB0aW9uLmApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGlzRXNjYXBpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNFc2NhcGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYnl0ZSA9PT0gdGhpcy5TTElQX0VTQ19FTkQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnRpYWxQYWNrZXQgPSB0aGlzLmFwcGVuZEFycmF5KHBhcnRpYWxQYWNrZXQsIG5ldyBVaW50OEFycmF5KFt0aGlzLlNMSVBfRU5EXSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKGJ5dGUgPT09IHRoaXMuU0xJUF9FU0NfRVNDKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJ0aWFsUGFja2V0ID0gdGhpcy5hcHBlbmRBcnJheShwYXJ0aWFsUGFja2V0LCBuZXcgVWludDhBcnJheShbdGhpcy5TTElQX0VTQ10pKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJhY2UoYFJlYWQgaW52YWxpZCBkYXRhOiAke3RoaXMuaGV4Q29udmVydChyZWFkQnl0ZXMpfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nRGF0YSA9IGF3YWl0IHRoaXMubmV3UmVhZCh0aGlzLmluV2FpdGluZygpLCB0aW1lb3V0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJhY2UoYFJlbWFpbmluZyBkYXRhIGluIHNlcmlhbCBidWZmZXI6ICR7dGhpcy5oZXhDb252ZXJ0KHJlbWFpbmluZ0RhdGEpfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZXRlY3RQYW5pY0hhbmRsZXIobmV3IFVpbnQ4QXJyYXkoWy4uLnJlYWRCeXRlcywgLi4uKHJlbWFpbmluZ0RhdGEgfHwgW10pXSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIFNMSVAgZXNjYXBlICgweGRiLCAweCR7Ynl0ZS50b1N0cmluZygxNil9KWApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGJ5dGUgPT09IHRoaXMuU0xJUF9FU0MpIHtcbiAgICAgICAgICAgICAgICAgICAgaXNFc2NhcGluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGJ5dGUgPT09IHRoaXMuU0xJUF9FTkQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFjZShgUmVjZWl2ZWQgZnVsbCBwYWNrZXQ6ICR7dGhpcy5oZXhDb252ZXJ0KHBhcnRpYWxQYWNrZXQpfWApO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZlciA9IHRoaXMuYXBwZW5kQXJyYXkodGhpcy5idWZmZXIsIHJlYWRCeXRlcy5zbGljZShpKSk7XG4gICAgICAgICAgICAgICAgICAgIHlpZWxkIHBhcnRpYWxQYWNrZXQ7XG4gICAgICAgICAgICAgICAgICAgIHBhcnRpYWxQYWNrZXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzZnVsU2xpcCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0aWFsUGFja2V0ID0gdGhpcy5hcHBlbmRBcnJheShwYXJ0aWFsUGFja2V0LCBuZXcgVWludDhBcnJheShbYnl0ZV0pKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVhZCBmcm9tIHNlcmlhbCBkZXZpY2Ugd2l0aG91dCBzbGlwIGZvcm1hdHRpbmcuXG4gICAgICogQHlpZWxkcyB7VWludDhBcnJheX0gVGhlIG5leHQgbnVtYmVyIGluIHRoZSBGaWJvbmFjY2kgc2VxdWVuY2UuXG4gICAgICovXG4gICAgYXN5bmMgKnJhd1JlYWQoKSB7XG4gICAgICAgIGlmICghdGhpcy5yZWFkZXIpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgdmFsdWUsIGRvbmUgfSA9IGF3YWl0IHRoaXMucmVhZGVyLnJlYWQoKTtcbiAgICAgICAgICAgICAgICBpZiAoZG9uZSB8fCAhdmFsdWUpXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnRyYWNpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJSYXcgUmVhZCBieXRlc1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFjZShgUmVhZCAke3ZhbHVlLmxlbmd0aH0gYnl0ZXM6ICR7dGhpcy5oZXhDb252ZXJ0KHZhbHVlKX1gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgeWllbGQgdmFsdWU7IC8vIFlpZWxkIGVhY2ggZGF0YSBjaHVua1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHJlYWRpbmcgZnJvbSBzZXJpYWwgcG9ydDpcIiwgZXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgdGhpcy5idWZmZXIgPSBuZXcgVWludDhBcnJheSgwKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZW5kIHRoZSBSZXF1ZXN0VG9TZW5kIChSVFMpIHNpZ25hbCB0byBnaXZlbiBzdGF0ZVxuICAgICAqICMgVHJ1ZSBmb3IgRU49TE9XLCBjaGlwIGluIHJlc2V0IGFuZCBGYWxzZSBFTj1ISUdILCBjaGlwIG91dCBvZiByZXNldFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc3RhdGUgQm9vbGVhbiBzdGF0ZSB0byBzZXQgdGhlIHNpZ25hbFxuICAgICAqL1xuICAgIGFzeW5jIHNldFJUUyhzdGF0ZSkge1xuICAgICAgICBhd2FpdCB0aGlzLmRldmljZS5zZXRTaWduYWxzKHsgcmVxdWVzdFRvU2VuZDogc3RhdGUgfSk7XG4gICAgICAgIC8vICMgV29yay1hcm91bmQgZm9yIGFkYXB0ZXJzIG9uIFdpbmRvd3MgdXNpbmcgdGhlIHVzYnNlci5zeXMgZHJpdmVyOlxuICAgICAgICAvLyAjIGdlbmVyYXRlIGEgZHVtbXkgY2hhbmdlIHRvIERUUiBzbyB0aGF0IHRoZSBzZXQtY29udHJvbC1saW5lLXN0YXRlXG4gICAgICAgIC8vICMgcmVxdWVzdCBpcyBzZW50IHdpdGggdGhlIHVwZGF0ZWQgUlRTIHN0YXRlIGFuZCB0aGUgc2FtZSBEVFIgc3RhdGVcbiAgICAgICAgLy8gUmVmZXJlbmNlZCB0byBlc3B0b29sLnB5XG4gICAgICAgIGF3YWl0IHRoaXMuc2V0RFRSKHRoaXMuX0RUUl9zdGF0ZSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNlbmQgdGhlIGRhdGFUZXJtaW5hbFJlYWR5IChEVFMpIHNpZ25hbCB0byBnaXZlbiBzdGF0ZVxuICAgICAqICMgVHJ1ZSBmb3IgSU8wPUxPVywgY2hpcCBpbiByZXNldCBhbmQgRmFsc2UgSU8wPUhJR0hcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHN0YXRlIEJvb2xlYW4gc3RhdGUgdG8gc2V0IHRoZSBzaWduYWxcbiAgICAgKi9cbiAgICBhc3luYyBzZXREVFIoc3RhdGUpIHtcbiAgICAgICAgdGhpcy5fRFRSX3N0YXRlID0gc3RhdGU7XG4gICAgICAgIGF3YWl0IHRoaXMuZGV2aWNlLnNldFNpZ25hbHMoeyBkYXRhVGVybWluYWxSZWFkeTogc3RhdGUgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENvbm5lY3QgdG8gc2VyaWFsIGRldmljZSB1c2luZyB0aGUgV2Vic2VyaWFsIG9wZW4gbWV0aG9kLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiYXVkIE51bWJlciBiYXVkIHJhdGUgZm9yIHNlcmlhbCBjb25uZWN0aW9uLiBEZWZhdWx0IGlzIDExNTIwMC5cbiAgICAgKiBAcGFyYW0ge3R5cGVvZiBpbXBvcnQoXCJ3M2Mtd2ViLXNlcmlhbFwiKS5TZXJpYWxPcHRpb25zfSBzZXJpYWxPcHRpb25zIFNlcmlhbCBPcHRpb25zIGZvciBXZWJVU0IgU2VyaWFsUG9ydCBjbGFzcy5cbiAgICAgKi9cbiAgICBhc3luYyBjb25uZWN0KGJhdWQgPSAxMTUyMDAsIHNlcmlhbE9wdGlvbnMgPSB7fSkge1xuICAgICAgICB2YXIgX2E7XG4gICAgICAgIGF3YWl0IHRoaXMuZGV2aWNlLm9wZW4oe1xuICAgICAgICAgICAgYmF1ZFJhdGU6IGJhdWQsXG4gICAgICAgICAgICBkYXRhQml0czogc2VyaWFsT3B0aW9ucyA9PT0gbnVsbCB8fCBzZXJpYWxPcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBzZXJpYWxPcHRpb25zLmRhdGFCaXRzLFxuICAgICAgICAgICAgc3RvcEJpdHM6IHNlcmlhbE9wdGlvbnMgPT09IG51bGwgfHwgc2VyaWFsT3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogc2VyaWFsT3B0aW9ucy5zdG9wQml0cyxcbiAgICAgICAgICAgIGJ1ZmZlclNpemU6IHNlcmlhbE9wdGlvbnMgPT09IG51bGwgfHwgc2VyaWFsT3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogc2VyaWFsT3B0aW9ucy5idWZmZXJTaXplLFxuICAgICAgICAgICAgcGFyaXR5OiBzZXJpYWxPcHRpb25zID09PSBudWxsIHx8IHNlcmlhbE9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHNlcmlhbE9wdGlvbnMucGFyaXR5LFxuICAgICAgICAgICAgZmxvd0NvbnRyb2w6IHNlcmlhbE9wdGlvbnMgPT09IG51bGwgfHwgc2VyaWFsT3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogc2VyaWFsT3B0aW9ucy5mbG93Q29udHJvbCxcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYmF1ZHJhdGUgPSBiYXVkO1xuICAgICAgICB0aGlzLnJlYWRlciA9IChfYSA9IHRoaXMuZGV2aWNlLnJlYWRhYmxlKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EuZ2V0UmVhZGVyKCk7XG4gICAgfVxuICAgIGFzeW5jIHNsZWVwKG1zKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCBtcykpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBXYWl0IGZvciBhIGdpdmVuIHRpbWVvdXQgbXMgZm9yIHNlcmlhbCBkZXZpY2UgdW5sb2NrLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB0aW1lb3V0IFRpbWVvdXQgdGltZSBpbiBtaWxsaXNlY29uZHMgKG1zKSB0byBzbGVlcFxuICAgICAqL1xuICAgIGFzeW5jIHdhaXRGb3JVbmxvY2sodGltZW91dCkge1xuICAgICAgICB3aGlsZSAoKHRoaXMuZGV2aWNlLnJlYWRhYmxlICYmIHRoaXMuZGV2aWNlLnJlYWRhYmxlLmxvY2tlZCkgfHxcbiAgICAgICAgICAgICh0aGlzLmRldmljZS53cml0YWJsZSAmJiB0aGlzLmRldmljZS53cml0YWJsZS5sb2NrZWQpKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNsZWVwKHRpbWVvdXQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERpc2Nvbm5lY3QgZnJvbSBzZXJpYWwgZGV2aWNlIGJ5IHJ1bm5pbmcgU2VyaWFsUG9ydC5jbG9zZSgpIGFmdGVyIHN0cmVhbXMgdW5sb2NrLlxuICAgICAqL1xuICAgIGFzeW5jIGRpc2Nvbm5lY3QoKSB7XG4gICAgICAgIHZhciBfYSwgX2I7XG4gICAgICAgIGlmICgoX2EgPSB0aGlzLmRldmljZS5yZWFkYWJsZSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmxvY2tlZCkge1xuICAgICAgICAgICAgYXdhaXQgKChfYiA9IHRoaXMucmVhZGVyKSA9PT0gbnVsbCB8fCBfYiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2IuY2FuY2VsKCkpO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHRoaXMud2FpdEZvclVubG9jayg0MDApO1xuICAgICAgICBhd2FpdCB0aGlzLmRldmljZS5jbG9zZSgpO1xuICAgICAgICB0aGlzLnJlYWRlciA9IHVuZGVmaW5lZDtcbiAgICB9XG59XG5leHBvcnQgeyBUcmFuc3BvcnQgfTtcbiIsImV4cG9ydCBjb25zdCBTRVJJQUxfUEFDS0VUX0hFQURFUiA9IFtcbiAgICBcIklcIi5jaGFyQ29kZUF0KDApLFxuICAgIFwiTVwiLmNoYXJDb2RlQXQoMCksXG4gICAgXCJQXCIuY2hhckNvZGVBdCgwKSxcbiAgICBcIlJcIi5jaGFyQ29kZUF0KDApLFxuICAgIFwiT1wiLmNoYXJDb2RlQXQoMCksXG4gICAgXCJWXCIuY2hhckNvZGVBdCgwKSxcbiAgICAxLCAvLyBwcm90b2NvbCB2ZXJzaW9uXG5dO1xuZXhwb3J0IHZhciBJbXByb3ZTZXJpYWxNZXNzYWdlVHlwZTtcbihmdW5jdGlvbiAoSW1wcm92U2VyaWFsTWVzc2FnZVR5cGUpIHtcbiAgICBJbXByb3ZTZXJpYWxNZXNzYWdlVHlwZVtJbXByb3ZTZXJpYWxNZXNzYWdlVHlwZVtcIkNVUlJFTlRfU1RBVEVcIl0gPSAxXSA9IFwiQ1VSUkVOVF9TVEFURVwiO1xuICAgIEltcHJvdlNlcmlhbE1lc3NhZ2VUeXBlW0ltcHJvdlNlcmlhbE1lc3NhZ2VUeXBlW1wiRVJST1JfU1RBVEVcIl0gPSAyXSA9IFwiRVJST1JfU1RBVEVcIjtcbiAgICBJbXByb3ZTZXJpYWxNZXNzYWdlVHlwZVtJbXByb3ZTZXJpYWxNZXNzYWdlVHlwZVtcIlJQQ1wiXSA9IDNdID0gXCJSUENcIjtcbiAgICBJbXByb3ZTZXJpYWxNZXNzYWdlVHlwZVtJbXByb3ZTZXJpYWxNZXNzYWdlVHlwZVtcIlJQQ19SRVNVTFRcIl0gPSA0XSA9IFwiUlBDX1JFU1VMVFwiO1xufSkoSW1wcm92U2VyaWFsTWVzc2FnZVR5cGUgfHwgKEltcHJvdlNlcmlhbE1lc3NhZ2VUeXBlID0ge30pKTtcbmV4cG9ydCB2YXIgSW1wcm92U2VyaWFsQ3VycmVudFN0YXRlO1xuKGZ1bmN0aW9uIChJbXByb3ZTZXJpYWxDdXJyZW50U3RhdGUpIHtcbiAgICBJbXByb3ZTZXJpYWxDdXJyZW50U3RhdGVbSW1wcm92U2VyaWFsQ3VycmVudFN0YXRlW1wiUkVBRFlcIl0gPSAyXSA9IFwiUkVBRFlcIjtcbiAgICBJbXByb3ZTZXJpYWxDdXJyZW50U3RhdGVbSW1wcm92U2VyaWFsQ3VycmVudFN0YXRlW1wiUFJPVklTSU9OSU5HXCJdID0gM10gPSBcIlBST1ZJU0lPTklOR1wiO1xuICAgIEltcHJvdlNlcmlhbEN1cnJlbnRTdGF0ZVtJbXByb3ZTZXJpYWxDdXJyZW50U3RhdGVbXCJQUk9WSVNJT05FRFwiXSA9IDRdID0gXCJQUk9WSVNJT05FRFwiO1xufSkoSW1wcm92U2VyaWFsQ3VycmVudFN0YXRlIHx8IChJbXByb3ZTZXJpYWxDdXJyZW50U3RhdGUgPSB7fSkpO1xuZXhwb3J0IGNvbnN0IEVSUk9SX01TR1MgPSB7XG4gICAgMHgwMDogXCJOT19FUlJPUlwiLFxuICAgIDB4MDE6IFwiSU5WQUxJRF9SUENfUEFDS0VUXCIsXG4gICAgMHgwMjogXCJVTktOT1dOX1JQQ19DT01NQU5EXCIsXG4gICAgMHgwMzogXCJVTkFCTEVfVE9fQ09OTkVDVFwiLFxuICAgIDB4ZmU6IFwiVElNRU9VVFwiLFxuICAgIDB4ZmY6IFwiVU5LTk9XTl9FUlJPUlwiLFxufTtcbmV4cG9ydCBjbGFzcyBQb3J0Tm90UmVhZHkgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKFwiUG9ydCBpcyBub3QgcmVhZHlcIik7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgRVJST1JfTVNHUywgSW1wcm92U2VyaWFsQ3VycmVudFN0YXRlLCBJbXByb3ZTZXJpYWxNZXNzYWdlVHlwZSwgUG9ydE5vdFJlYWR5LCBTRVJJQUxfUEFDS0VUX0hFQURFUiwgfSBmcm9tIFwiLi9jb25zdC5qc1wiO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tIFwiLi91dGlsL3NsZWVwXCI7XG5pbXBvcnQgeyBoZXhGb3JtYXR0ZXIgfSBmcm9tIFwiLi91dGlsL2hleC1mb3JtYXR0ZXJcIjtcbmV4cG9ydCBjbGFzcyBJbXByb3ZTZXJpYWwgZXh0ZW5kcyBFdmVudFRhcmdldCB7XG4gICAgY29uc3RydWN0b3IocG9ydCwgbG9nZ2VyKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMucG9ydCA9IHBvcnQ7XG4gICAgICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyO1xuICAgICAgICB0aGlzLmVycm9yID0gMCAvKiBJbXByb3ZTZXJpYWxFcnJvclN0YXRlLk5PX0VSUk9SICovO1xuICAgICAgICBpZiAocG9ydC5yZWFkYWJsZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUG9ydCBpcyBub3QgcmVhZGFibGVcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBvcnQud3JpdGFibGUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlBvcnQgaXMgbm90IHdyaXRhYmxlXCIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERldGVjdCBJbXByb3YgU2VyaWFsLCBmZXRjaCB0aGUgc3RhdGUgYW5kIHJldHVybiB0aGUgbmV4dCBVUkwgaWYgcHJvdmlzaW9uZWQuXG4gICAgICogQHBhcmFtIHRpbWVvdXQgVGltZW91dCBpbiBtcyB0byB3YWl0IGZvciB0aGUgZGV2aWNlIHRvIHJlc3BvbmQuIERlZmF1bHQgdG8gMTAwMG1zLlxuICAgICAqL1xuICAgIGFzeW5jIGluaXRpYWxpemUodGltZW91dCA9IDEwMDApIHtcbiAgICAgICAgdGhpcy5sb2dnZXIubG9nKFwiSW5pdGlhbGl6aW5nIEltcHJvdiBTZXJpYWxcIik7XG4gICAgICAgIHRoaXMuX3Byb2Nlc3NJbnB1dCgpO1xuICAgICAgICAvLyBUbyBnaXZlIHRoZSBpbnB1dCBwcm9jZXNzaW5nIHRpbWUgdG8gc3RhcnQuXG4gICAgICAgIGF3YWl0IHNsZWVwKDEwMDApO1xuICAgICAgICBpZiAodGhpcy5fcmVhZGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBQb3J0Tm90UmVhZHkoKTtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gcmVqZWN0KG5ldyBFcnJvcihcIkltcHJvdiBXaS1GaSBTZXJpYWwgbm90IGRldGVjdGVkXCIpKSwgdGltZW91dCk7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5yZXF1ZXN0Q3VycmVudFN0YXRlKCk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnJlcXVlc3RJbmZvKCk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5jbG9zZSgpO1xuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmluZm87XG4gICAgfVxuICAgIGFzeW5jIGNsb3NlKCkge1xuICAgICAgICBpZiAoIXRoaXMuX3JlYWRlcikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9yZWFkZXIuY2FuY2VsKCk7XG4gICAgICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoXCJkaXNjb25uZWN0XCIsIHJlc29sdmUsIHsgb25jZTogdHJ1ZSB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoaXMgY29tbWFuZCB3aWxsIHRyaWdnZXIgYXQgbGVhc3Qgb25lIHBhY2tldCxcbiAgICAgKiB0aGUgQ3VycmVudCBTdGF0ZSBhbmQgaWYgYWxyZWFkeSBwcm92aXNpb25lZCxcbiAgICAgKiB0aGUgc2FtZSByZXNwb25zZSB5b3Ugd291bGQgZ2V0IGlmIGRldmljZSBwcm92aXNpb25pbmdcbiAgICAgKiB3YXMgc3VjY2Vzc2Z1bCAoc2VlIGJlbG93KS5cbiAgICAgKi9cbiAgICBhc3luYyByZXF1ZXN0Q3VycmVudFN0YXRlKCkge1xuICAgICAgICAvLyBSZXF1ZXN0IGN1cnJlbnQgc3RhdGUgYW5kIHdhaXQgZm9yIDVzXG4gICAgICAgIGxldCBycGNSZXN1bHQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKFwic3RhdGUtY2hhbmdlZFwiLCByZXNvbHZlLCB7IG9uY2U6IHRydWUgfSk7XG4gICAgICAgICAgICAgICAgY29uc3QgY2xlYW51cEFuZFJlamVjdCA9IChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKFwic3RhdGUtY2hhbmdlZFwiLCByZXNvbHZlKTtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBycGNSZXN1bHQgPSB0aGlzLl9zZW5kUlBDV2l0aFJlc3BvbnNlKDIgLyogSW1wcm92U2VyaWFsUlBDQ29tbWFuZC5SRVFVRVNUX0NVUlJFTlRfU1RBVEUgKi8sIFtdKTtcbiAgICAgICAgICAgICAgICBycGNSZXN1bHQuY2F0Y2goY2xlYW51cEFuZFJlamVjdCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICB0aGlzLl9ycGNGZWVkYmFjayA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZmV0Y2hpbmcgY3VycmVudCBzdGF0ZTogJHtlcnJ9YCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gT25seSBpZiB3ZSBhcmUgcHJvdmlzaW9uZWQgd2lsbCB3ZSBnZXQgYW4gcnBjIHJlc3VsdFxuICAgICAgICBpZiAodGhpcy5zdGF0ZSAhPT0gSW1wcm92U2VyaWFsQ3VycmVudFN0YXRlLlBST1ZJU0lPTkVEKSB7XG4gICAgICAgICAgICB0aGlzLl9ycGNGZWVkYmFjayA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkYXRhID0gYXdhaXQgcnBjUmVzdWx0O1xuICAgICAgICB0aGlzLm5leHRVcmwgPSBkYXRhWzBdO1xuICAgIH1cbiAgICBhc3luYyByZXF1ZXN0SW5mbyh0aW1lb3V0KSB7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fc2VuZFJQQ1dpdGhSZXNwb25zZSgzIC8qIEltcHJvdlNlcmlhbFJQQ0NvbW1hbmQuUkVRVUVTVF9JTkZPICovLCBbXSwgdGltZW91dCk7XG4gICAgICAgIHRoaXMuaW5mbyA9IHtcbiAgICAgICAgICAgIGZpcm13YXJlOiByZXNwb25zZVswXSxcbiAgICAgICAgICAgIHZlcnNpb246IHJlc3BvbnNlWzFdLFxuICAgICAgICAgICAgbmFtZTogcmVzcG9uc2VbM10sXG4gICAgICAgICAgICBjaGlwRmFtaWx5OiByZXNwb25zZVsyXSxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgYXN5bmMgcHJvdmlzaW9uKHNzaWQsIHBhc3N3b3JkLCB0aW1lb3V0KSB7XG4gICAgICAgIGNvbnN0IGVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKTtcbiAgICAgICAgY29uc3Qgc3NpZEVuY29kZWQgPSBlbmNvZGVyLmVuY29kZShzc2lkKTtcbiAgICAgICAgY29uc3QgcHdFbmNvZGVkID0gZW5jb2Rlci5lbmNvZGUocGFzc3dvcmQpO1xuICAgICAgICBjb25zdCBkYXRhID0gW1xuICAgICAgICAgICAgc3NpZEVuY29kZWQubGVuZ3RoLFxuICAgICAgICAgICAgLi4uc3NpZEVuY29kZWQsXG4gICAgICAgICAgICBwd0VuY29kZWQubGVuZ3RoLFxuICAgICAgICAgICAgLi4ucHdFbmNvZGVkLFxuICAgICAgICBdO1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuX3NlbmRSUENXaXRoUmVzcG9uc2UoMSAvKiBJbXByb3ZTZXJpYWxSUENDb21tYW5kLlNFTkRfV0lGSV9TRVRUSU5HUyAqLywgZGF0YSwgdGltZW91dCk7XG4gICAgICAgIHRoaXMubmV4dFVybCA9IHJlc3BvbnNlWzBdO1xuICAgIH1cbiAgICBhc3luYyBzY2FuKCkge1xuICAgICAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgdGhpcy5fc2VuZFJQQ1dpdGhNdWx0aXBsZVJlc3BvbnNlcyg0IC8qIEltcHJvdlNlcmlhbFJQQ0NvbW1hbmQuUkVRVUVTVF9XSUZJX05FVFdPUktTICovLCBbXSk7XG4gICAgICAgIGNvbnN0IHNzaWRzID0gcmVzdWx0cy5tYXAoKFtuYW1lLCByc3NpLCBzZWN1cmVkXSkgPT4gKHtcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICByc3NpOiBwYXJzZUludChyc3NpKSxcbiAgICAgICAgICAgIHNlY3VyZWQ6IHNlY3VyZWQgPT09IFwiWUVTXCIsXG4gICAgICAgIH0pKTtcbiAgICAgICAgc3NpZHMuc29ydCgoYSwgYikgPT4gYS5uYW1lLnRvTG9jYWxlTG93ZXJDYXNlKCkubG9jYWxlQ29tcGFyZShiLm5hbWUudG9Mb2NhbGVMb3dlckNhc2UoKSkpO1xuICAgICAgICByZXR1cm4gc3NpZHM7XG4gICAgfVxuICAgIF9zZW5kUlBDKGNvbW1hbmQsIGRhdGEpIHtcbiAgICAgICAgdGhpcy53cml0ZVBhY2tldFRvU3RyZWFtKEltcHJvdlNlcmlhbE1lc3NhZ2VUeXBlLlJQQywgW1xuICAgICAgICAgICAgY29tbWFuZCxcbiAgICAgICAgICAgIGRhdGEubGVuZ3RoLFxuICAgICAgICAgICAgLi4uZGF0YSxcbiAgICAgICAgXSk7XG4gICAgfVxuICAgIGFzeW5jIF9zZW5kUlBDV2l0aFJlc3BvbnNlKGNvbW1hbmQsIGRhdGEsIHRpbWVvdXQpIHtcbiAgICAgICAgLy8gQ29tbWFuZHMgdGhhdCByZWNlaXZlIGZlZWRiYWNrIHdpbGwgZmluaXNoIHdoZW4gZWl0aGVyXG4gICAgICAgIC8vIHRoZSBzdGF0ZSBjaGFuZ2VzIG9yIHRoZSBlcnJvciBjb2RlIGJlY29tZXMgbm90IDAuXG4gICAgICAgIGlmICh0aGlzLl9ycGNGZWVkYmFjaykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiT25seSAxIFJQQyBjb21tYW5kIHRoYXQgcmVxdWlyZXMgZmVlZGJhY2sgY2FuIGJlIGFjdGl2ZVwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5fYXdhaXRSUENSZXN1bHRXaXRoVGltZW91dChuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9ycGNGZWVkYmFjayA9IHsgY29tbWFuZCwgcmVzb2x2ZSwgcmVqZWN0IH07XG4gICAgICAgICAgICB0aGlzLl9zZW5kUlBDKGNvbW1hbmQsIGRhdGEpO1xuICAgICAgICB9KSwgdGltZW91dCk7XG4gICAgfVxuICAgIGFzeW5jIF9zZW5kUlBDV2l0aE11bHRpcGxlUmVzcG9uc2VzKGNvbW1hbmQsIGRhdGEsIHRpbWVvdXQpIHtcbiAgICAgICAgLy8gQ29tbWFuZHMgdGhhdCByZWNlaXZlIG11bHRpcGxlIGZlZWRiYWNrcyB3aWxsIGZpbmlzaCB3aGVuIGVpdGhlclxuICAgICAgICAvLyB0aGUgc3RhdGUgY2hhbmdlcyBvciB0aGUgZXJyb3IgY29kZSBiZWNvbWVzIG5vdCAwLlxuICAgICAgICBpZiAodGhpcy5fcnBjRmVlZGJhY2spIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk9ubHkgMSBSUEMgY29tbWFuZCB0aGF0IHJlcXVpcmVzIGZlZWRiYWNrIGNhbiBiZSBhY3RpdmVcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2F3YWl0UlBDUmVzdWx0V2l0aFRpbWVvdXQobmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fcnBjRmVlZGJhY2sgPSB7XG4gICAgICAgICAgICAgICAgY29tbWFuZCxcbiAgICAgICAgICAgICAgICByZXNvbHZlLFxuICAgICAgICAgICAgICAgIHJlamVjdCxcbiAgICAgICAgICAgICAgICByZWNlaXZlZERhdGE6IFtdLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuX3NlbmRSUEMoY29tbWFuZCwgZGF0YSk7XG4gICAgICAgIH0pLCB0aW1lb3V0KTtcbiAgICB9XG4gICAgYXN5bmMgX2F3YWl0UlBDUmVzdWx0V2l0aFRpbWVvdXQoc2VuZFJQQ1Byb21pc2UsIHRpbWVvdXQpIHtcbiAgICAgICAgaWYgKCF0aW1lb3V0KSB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgc2VuZFJQQ1Byb21pc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHRpbWVvdXRSUEMgPSBzZXRUaW1lb3V0KCgpID0+IHRoaXMuX3NldEVycm9yKDI1NCAvKiBJbXByb3ZTZXJpYWxFcnJvclN0YXRlLlRJTUVPVVQgKi8pLCB0aW1lb3V0KTtcbiAgICAgICAgICAgIHNlbmRSUENQcm9taXNlLmZpbmFsbHkoKCkgPT4gY2xlYXJUaW1lb3V0KHRpbWVvdXRSUEMpKTtcbiAgICAgICAgICAgIHNlbmRSUENQcm9taXNlLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGFzeW5jIF9wcm9jZXNzSW5wdXQoKSB7XG4gICAgICAgIC8vIHJlYWQgdGhlIGRhdGEgZnJvbSBzZXJpYWwgcG9ydC5cbiAgICAgICAgLy8gY3VycmVudCBzdGF0ZSwgZXJyb3Igc3RhdGUsIHJwYyByZXN1bHRcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXCJTdGFydGluZyByZWFkIGxvb3BcIik7XG4gICAgICAgIHRoaXMuX3JlYWRlciA9IHRoaXMucG9ydC5yZWFkYWJsZS5nZXRSZWFkZXIoKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGxldCBsaW5lID0gW107XG4gICAgICAgICAgICAvLyB1bmRlZmluZWQgPSBub3Qgc3VyZSBpZiBpbXByb3YgcGFja2V0XG4gICAgICAgICAgICBsZXQgaXNJbXByb3Y7XG4gICAgICAgICAgICAvLyBsZW5ndGggb2YgaW1wcm92IGJ5dGVzIHRoYXQgd2UgZXhwZWN0XG4gICAgICAgICAgICBsZXQgaW1wcm92TGVuZ3RoID0gMDtcbiAgICAgICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeyB2YWx1ZSwgZG9uZSB9ID0gYXdhaXQgdGhpcy5fcmVhZGVyLnJlYWQoKTtcbiAgICAgICAgICAgICAgICBpZiAoZG9uZSkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF2YWx1ZSB8fCB2YWx1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgYnl0ZSBvZiB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNJbXByb3YgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIGl0IHdhc24ndCBhbiBpbXByb3YgbGluZSwgZGlzY2FyZCBldmVyeXRoaW5nIHVudGkgd2UgZmluZCBuZXcgbGluZSBjaGFyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYnl0ZSA9PT0gMTApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0ltcHJvdiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0ltcHJvdiA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGluZS5wdXNoKGJ5dGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxpbmUubGVuZ3RoID09PSBpbXByb3ZMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9oYW5kbGVJbmNvbWluZ1BhY2tldChsaW5lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0ltcHJvdiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoYnl0ZSA9PT0gMTApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmUgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGxpbmUucHVzaChieXRlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpbmUubGVuZ3RoICE9PSA5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBpdCdzIGltcHJvdlxuICAgICAgICAgICAgICAgICAgICBpc0ltcHJvdiA9IFN0cmluZy5mcm9tQ2hhckNvZGUoLi4ubGluZS5zbGljZSgwLCA2KSkgPT09IFwiSU1QUk9WXCI7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNJbXByb3YpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmUgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIEZvcm1hdDpcbiAgICAgICAgICAgICAgICAgICAgLy8gSSBNIFAgUiBPIFYgPFZFUlNJT04+IDxUWVBFPiA8TEVOR1RIPiA8REFUQT4gPENIRUNLU1VNPlxuICAgICAgICAgICAgICAgICAgICAvLyBPbmNlIHdlIGhhdmUgOSBieXRlcywgd2UgY2FuIGNoZWNrIGlmIGl0J3MgYW4gaW1wcm92IHBhY2tldFxuICAgICAgICAgICAgICAgICAgICAvLyBhbmQgZXh0cmFjdCBob3cgbXVjaCBtb3JlIHdlIG5lZWQgdG8gZmV0Y2guXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhY2tldExlbmd0aCA9IGxpbmVbOF07XG4gICAgICAgICAgICAgICAgICAgIGltcHJvdkxlbmd0aCA9IDkgKyBwYWNrZXRMZW5ndGggKyAxOyAvLyBoZWFkZXIgKyBkYXRhIGxlbmd0aCArIGNoZWNrc3VtXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKFwiRXJyb3Igd2hpbGUgcmVhZGluZyBzZXJpYWwgcG9ydFwiLCBlcnIpO1xuICAgICAgICB9XG4gICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgdGhpcy5fcmVhZGVyLnJlbGVhc2VMb2NrKCk7XG4gICAgICAgICAgICB0aGlzLl9yZWFkZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXCJGaW5pc2hlZCByZWFkIGxvb3BcIik7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoXCJkaXNjb25uZWN0XCIpKTtcbiAgICB9XG4gICAgX2hhbmRsZUluY29taW5nUGFja2V0KGxpbmUpIHtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IGxpbmUuc2xpY2UoNik7XG4gICAgICAgIGNvbnN0IHZlcnNpb24gPSBwYXlsb2FkWzBdO1xuICAgICAgICBjb25zdCBwYWNrZXRUeXBlID0gcGF5bG9hZFsxXTtcbiAgICAgICAgY29uc3QgcGFja2V0TGVuZ3RoID0gcGF5bG9hZFsyXTtcbiAgICAgICAgY29uc3QgZGF0YSA9IHBheWxvYWQuc2xpY2UoMywgMyArIHBhY2tldExlbmd0aCk7XG4gICAgICAgIHRoaXMubG9nZ2VyLmRlYnVnKFwiUFJPQ0VTU1wiLCB7XG4gICAgICAgICAgICB2ZXJzaW9uLFxuICAgICAgICAgICAgcGFja2V0VHlwZSxcbiAgICAgICAgICAgIHBhY2tldExlbmd0aCxcbiAgICAgICAgICAgIGRhdGE6IGhleEZvcm1hdHRlcihkYXRhKSxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh2ZXJzaW9uICE9PSAxKSB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihcIlJlY2VpdmVkIHVuc3VwcG9ydGVkIHZlcnNpb25cIiwgdmVyc2lvbik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gVmVyaWZ5IGNoZWNrc3VtXG4gICAgICAgIGxldCBwYWNrZXRDaGVja3N1bSA9IHBheWxvYWRbMyArIHBhY2tldExlbmd0aF07XG4gICAgICAgIGxldCBjYWxjdWxhdGVkQ2hlY2tzdW0gPSAwO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmUubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICBjYWxjdWxhdGVkQ2hlY2tzdW0gKz0gbGluZVtpXTtcbiAgICAgICAgfVxuICAgICAgICBjYWxjdWxhdGVkQ2hlY2tzdW0gPSBjYWxjdWxhdGVkQ2hlY2tzdW0gJiAweGZmO1xuICAgICAgICBpZiAoY2FsY3VsYXRlZENoZWNrc3VtICE9PSBwYWNrZXRDaGVja3N1bSkge1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoYFJlY2VpdmVkIGludmFsaWQgY2hlY2tzdW0gJHtwYWNrZXRDaGVja3N1bX0uIEV4cGVjdGVkICR7Y2FsY3VsYXRlZENoZWNrc3VtfWApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwYWNrZXRUeXBlID09PSBJbXByb3ZTZXJpYWxNZXNzYWdlVHlwZS5DVVJSRU5UX1NUQVRFKSB7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gZGF0YVswXTtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoXCJzdGF0ZS1jaGFuZ2VkXCIsIHtcbiAgICAgICAgICAgICAgICBkZXRhaWw6IHRoaXMuc3RhdGUsXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAocGFja2V0VHlwZSA9PT0gSW1wcm92U2VyaWFsTWVzc2FnZVR5cGUuRVJST1JfU1RBVEUpIHtcbiAgICAgICAgICAgIHRoaXMuX3NldEVycm9yKGRhdGFbMF0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHBhY2tldFR5cGUgPT09IEltcHJvdlNlcmlhbE1lc3NhZ2VUeXBlLlJQQ19SRVNVTFQpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5fcnBjRmVlZGJhY2spIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihcIlJlY2VpdmVkIHJlc3VsdCB3aGlsZSBub3Qgd2FpdGluZyBmb3Igb25lXCIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJwY0NvbW1hbmQgPSBkYXRhWzBdO1xuICAgICAgICAgICAgaWYgKHJwY0NvbW1hbmQgIT09IHRoaXMuX3JwY0ZlZWRiYWNrLmNvbW1hbmQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcihgUmVjZWl2ZWQgcmVzdWx0IGZvciBjb21tYW5kICR7cnBjQ29tbWFuZH0gYnV0IGV4cGVjdGVkICR7dGhpcy5fcnBjRmVlZGJhY2suY29tbWFuZH1gKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDaG9wIG9mZiBycGMgY29tbWFuZCBhbmQgY2hlY2tzdW1cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgICAgICAgICAgY29uc3QgdG90YWxMZW5ndGggPSBkYXRhWzFdO1xuICAgICAgICAgICAgbGV0IGlkeCA9IDI7XG4gICAgICAgICAgICB3aGlsZSAoaWR4IDwgMiArIHRvdGFsTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goU3RyaW5nLmZyb21Db2RlUG9pbnQoLi4uZGF0YS5zbGljZShpZHggKyAxLCBpZHggKyBkYXRhW2lkeF0gKyAxKSkpO1xuICAgICAgICAgICAgICAgIGlkeCArPSBkYXRhW2lkeF0gKyAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKFwicmVjZWl2ZWREYXRhXCIgaW4gdGhpcy5fcnBjRmVlZGJhY2spIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcnBjRmVlZGJhY2sucmVjZWl2ZWREYXRhLnB1c2gocmVzdWx0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc3VsdCBvZiAwIG1lYW5zIHdlJ3JlIGRvbmUuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3JwY0ZlZWRiYWNrLnJlc29sdmUodGhpcy5fcnBjRmVlZGJhY2sucmVjZWl2ZWREYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcnBjRmVlZGJhY2sgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcnBjRmVlZGJhY2sucmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3JwY0ZlZWRiYWNrID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoXCJVbmFibGUgdG8gaGFuZGxlIHBhY2tldFwiLCBwYXlsb2FkKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBBZGQgaGVhZGVyICsgY2hlY2tzdW0gYW5kIHdyaXRlIHBhY2tldCB0byBzdHJlYW1cbiAgICAgKi9cbiAgICBhc3luYyB3cml0ZVBhY2tldFRvU3RyZWFtKHR5cGUsIGRhdGEpIHtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IG5ldyBVaW50OEFycmF5KFtcbiAgICAgICAgICAgIC4uLlNFUklBTF9QQUNLRVRfSEVBREVSLFxuICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgIGRhdGEubGVuZ3RoLFxuICAgICAgICAgICAgLi4uZGF0YSxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAwLCAvLyBXaWxsIGJlIG5ld2xpbmVcbiAgICAgICAgXSk7XG4gICAgICAgIC8vIENhbGN1bGF0ZSBjaGVja3N1bVxuICAgICAgICBwYXlsb2FkW3BheWxvYWQubGVuZ3RoIC0gMl0gPVxuICAgICAgICAgICAgcGF5bG9hZC5yZWR1Y2UoKHN1bSwgY3VyKSA9PiBzdW0gKyBjdXIsIDApICYgMHhmZjtcbiAgICAgICAgcGF5bG9hZFtwYXlsb2FkLmxlbmd0aCAtIDFdID0gMTA7IC8vIE5ld2xpbmVcbiAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoXCJXcml0aW5nIHRvIHN0cmVhbTpcIiwgaGV4Rm9ybWF0dGVyKG5ldyBBcnJheSguLi5wYXlsb2FkKSkpO1xuICAgICAgICBjb25zdCB3cml0ZXIgPSB0aGlzLnBvcnQud3JpdGFibGUuZ2V0V3JpdGVyKCk7XG4gICAgICAgIGF3YWl0IHdyaXRlci53cml0ZShwYXlsb2FkKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHdyaXRlci5yZWxlYXNlTG9jaygpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJJZ25vcmluZyByZWxlYXNlIGxvY2sgZXJyb3JcIiwgZXJyKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBFcnJvciBpcyBlaXRoZXIgcmVjZWl2ZWQgZnJvbSBkZXZpY2Ugb3IgaXMgYSB0aW1lb3V0XG4gICAgX3NldEVycm9yKGVycm9yKSB7XG4gICAgICAgIHRoaXMuZXJyb3IgPSBlcnJvcjtcbiAgICAgICAgaWYgKGVycm9yID4gMCAmJiB0aGlzLl9ycGNGZWVkYmFjaykge1xuICAgICAgICAgICAgdGhpcy5fcnBjRmVlZGJhY2sucmVqZWN0KEVSUk9SX01TR1NbZXJyb3JdIHx8IGBVTktOT1dOX0VSUk9SICgke2Vycm9yfSlgKTtcbiAgICAgICAgICAgIHRoaXMuX3JwY0ZlZWRiYWNrID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoXCJlcnJvci1jaGFuZ2VkXCIsIHtcbiAgICAgICAgICAgIGRldGFpbDogdGhpcy5lcnJvcixcbiAgICAgICAgfSkpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IHRvSGV4IH0gZnJvbSBcIi4vdG8taGV4XCI7XG5leHBvcnQgY29uc3QgaGV4Rm9ybWF0dGVyID0gKGJ5dGVzKSA9PiBcIltcIiArIGJ5dGVzLm1hcCgodmFsdWUpID0+IHRvSGV4KHZhbHVlKSkuam9pbihcIiwgXCIpICsgXCJdXCI7XG4iLCJleHBvcnQgY29uc3Qgc2xlZXAgPSAobXMpID0+IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG4iLCJleHBvcnQgY29uc3QgdG9IZXggPSAodmFsdWUsIHNpemUgPSAyKSA9PiB7XG4gICAgbGV0IGhleCA9IHZhbHVlLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpO1xuICAgIGlmIChoZXguc3RhcnRzV2l0aChcIi1cIikpIHtcbiAgICAgICAgcmV0dXJuIFwiLTB4XCIgKyBoZXguc3Vic3RyaW5nKDEpLnBhZFN0YXJ0KHNpemUsIFwiMFwiKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBcIjB4XCIgKyBoZXgucGFkU3RhcnQoc2l6ZSwgXCIwXCIpO1xuICAgIH1cbn07XG4iLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQlNELTMtQ2xhdXNlXG4gKi9cbmltcG9ydCB7IF8kTEgsIH0gZnJvbSAnLi9saXQtaHRtbC5qcyc7XG5jb25zdCB7IF9DaGlsZFBhcnQ6IENoaWxkUGFydCB9ID0gXyRMSDtcbmNvbnN0IEVOQUJMRV9TSEFEWURPTV9OT1BBVENIID0gdHJ1ZTtcbmNvbnN0IHdyYXAgPSBFTkFCTEVfU0hBRFlET01fTk9QQVRDSCAmJlxuICAgIHdpbmRvdy5TaGFkeURPTT8uaW5Vc2UgJiZcbiAgICB3aW5kb3cuU2hhZHlET00/Lm5vUGF0Y2ggPT09IHRydWVcbiAgICA/IHdpbmRvdy5TaGFkeURPTS53cmFwXG4gICAgOiAobm9kZSkgPT4gbm9kZTtcbi8qKlxuICogVGVzdHMgaWYgYSB2YWx1ZSBpcyBhIHByaW1pdGl2ZSB2YWx1ZS5cbiAqXG4gKiBTZWUgaHR0cHM6Ly90YzM5LmdpdGh1Yi5pby9lY21hMjYyLyNzZWMtdHlwZW9mLW9wZXJhdG9yXG4gKi9cbmV4cG9ydCBjb25zdCBpc1ByaW1pdGl2ZSA9ICh2YWx1ZSkgPT4gdmFsdWUgPT09IG51bGwgfHwgKHR5cGVvZiB2YWx1ZSAhPSAnb2JqZWN0JyAmJiB0eXBlb2YgdmFsdWUgIT0gJ2Z1bmN0aW9uJyk7XG5leHBvcnQgY29uc3QgVGVtcGxhdGVSZXN1bHRUeXBlID0ge1xuICAgIEhUTUw6IDEsXG4gICAgU1ZHOiAyLFxuICAgIE1BVEhNTDogMyxcbn07XG4vKipcbiAqIFRlc3RzIGlmIGEgdmFsdWUgaXMgYSBUZW1wbGF0ZVJlc3VsdCBvciBhIENvbXBpbGVkVGVtcGxhdGVSZXN1bHQuXG4gKi9cbmV4cG9ydCBjb25zdCBpc1RlbXBsYXRlUmVzdWx0ID0gKHZhbHVlLCB0eXBlKSA9PiB0eXBlID09PSB1bmRlZmluZWRcbiAgICA/IC8vIFRoaXMgcHJvcGVydHkgbmVlZHMgdG8gcmVtYWluIHVubWluaWZpZWQuXG4gICAgICAgIHZhbHVlPy5bJ18kbGl0VHlwZSQnXSAhPT0gdW5kZWZpbmVkXG4gICAgOiB2YWx1ZT8uWydfJGxpdFR5cGUkJ10gPT09IHR5cGU7XG4vKipcbiAqIFRlc3RzIGlmIGEgdmFsdWUgaXMgYSBDb21waWxlZFRlbXBsYXRlUmVzdWx0LlxuICovXG5leHBvcnQgY29uc3QgaXNDb21waWxlZFRlbXBsYXRlUmVzdWx0ID0gKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIHZhbHVlPy5bJ18kbGl0VHlwZSQnXT8uaCAhPSBudWxsO1xufTtcbi8qKlxuICogVGVzdHMgaWYgYSB2YWx1ZSBpcyBhIERpcmVjdGl2ZVJlc3VsdC5cbiAqL1xuZXhwb3J0IGNvbnN0IGlzRGlyZWN0aXZlUmVzdWx0ID0gKHZhbHVlKSA9PiBcbi8vIFRoaXMgcHJvcGVydHkgbmVlZHMgdG8gcmVtYWluIHVubWluaWZpZWQuXG52YWx1ZT8uWydfJGxpdERpcmVjdGl2ZSQnXSAhPT0gdW5kZWZpbmVkO1xuLyoqXG4gKiBSZXRyaWV2ZXMgdGhlIERpcmVjdGl2ZSBjbGFzcyBmb3IgYSBEaXJlY3RpdmVSZXN1bHRcbiAqL1xuZXhwb3J0IGNvbnN0IGdldERpcmVjdGl2ZUNsYXNzID0gKHZhbHVlKSA9PiBcbi8vIFRoaXMgcHJvcGVydHkgbmVlZHMgdG8gcmVtYWluIHVubWluaWZpZWQuXG52YWx1ZT8uWydfJGxpdERpcmVjdGl2ZSQnXTtcbi8qKlxuICogVGVzdHMgd2hldGhlciBhIHBhcnQgaGFzIG9ubHkgYSBzaW5nbGUtZXhwcmVzc2lvbiB3aXRoIG5vIHN0cmluZ3MgdG9cbiAqIGludGVycG9sYXRlIGJldHdlZW4uXG4gKlxuICogT25seSBBdHRyaWJ1dGVQYXJ0IGFuZCBQcm9wZXJ0eVBhcnQgY2FuIGhhdmUgbXVsdGlwbGUgZXhwcmVzc2lvbnMuXG4gKiBNdWx0aS1leHByZXNzaW9uIHBhcnRzIGhhdmUgYSBgc3RyaW5nc2AgcHJvcGVydHkgYW5kIHNpbmdsZS1leHByZXNzaW9uXG4gKiBwYXJ0cyBkbyBub3QuXG4gKi9cbmV4cG9ydCBjb25zdCBpc1NpbmdsZUV4cHJlc3Npb24gPSAocGFydCkgPT4gcGFydC5zdHJpbmdzID09PSB1bmRlZmluZWQ7XG5jb25zdCBjcmVhdGVNYXJrZXIgPSAoKSA9PiBkb2N1bWVudC5jcmVhdGVDb21tZW50KCcnKTtcbi8qKlxuICogSW5zZXJ0cyBhIENoaWxkUGFydCBpbnRvIHRoZSBnaXZlbiBjb250YWluZXIgQ2hpbGRQYXJ0J3MgRE9NLCBlaXRoZXIgYXQgdGhlXG4gKiBlbmQgb2YgdGhlIGNvbnRhaW5lciBDaGlsZFBhcnQsIG9yIGJlZm9yZSB0aGUgb3B0aW9uYWwgYHJlZlBhcnRgLlxuICpcbiAqIFRoaXMgZG9lcyBub3QgYWRkIHRoZSBwYXJ0IHRvIHRoZSBjb250YWluZXJQYXJ0J3MgY29tbWl0dGVkIHZhbHVlLiBUaGF0IG11c3RcbiAqIGJlIGRvbmUgYnkgY2FsbGVycy5cbiAqXG4gKiBAcGFyYW0gY29udGFpbmVyUGFydCBQYXJ0IHdpdGhpbiB3aGljaCB0byBhZGQgdGhlIG5ldyBDaGlsZFBhcnRcbiAqIEBwYXJhbSByZWZQYXJ0IFBhcnQgYmVmb3JlIHdoaWNoIHRvIGFkZCB0aGUgbmV3IENoaWxkUGFydDsgd2hlbiBvbWl0dGVkIHRoZVxuICogICAgIHBhcnQgYWRkZWQgdG8gdGhlIGVuZCBvZiB0aGUgYGNvbnRhaW5lclBhcnRgXG4gKiBAcGFyYW0gcGFydCBQYXJ0IHRvIGluc2VydCwgb3IgdW5kZWZpbmVkIHRvIGNyZWF0ZSBhIG5ldyBwYXJ0XG4gKi9cbmV4cG9ydCBjb25zdCBpbnNlcnRQYXJ0ID0gKGNvbnRhaW5lclBhcnQsIHJlZlBhcnQsIHBhcnQpID0+IHtcbiAgICBjb25zdCBjb250YWluZXIgPSB3cmFwKGNvbnRhaW5lclBhcnQuXyRzdGFydE5vZGUpLnBhcmVudE5vZGU7XG4gICAgY29uc3QgcmVmTm9kZSA9IHJlZlBhcnQgPT09IHVuZGVmaW5lZCA/IGNvbnRhaW5lclBhcnQuXyRlbmROb2RlIDogcmVmUGFydC5fJHN0YXJ0Tm9kZTtcbiAgICBpZiAocGFydCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnN0IHN0YXJ0Tm9kZSA9IHdyYXAoY29udGFpbmVyKS5pbnNlcnRCZWZvcmUoY3JlYXRlTWFya2VyKCksIHJlZk5vZGUpO1xuICAgICAgICBjb25zdCBlbmROb2RlID0gd3JhcChjb250YWluZXIpLmluc2VydEJlZm9yZShjcmVhdGVNYXJrZXIoKSwgcmVmTm9kZSk7XG4gICAgICAgIHBhcnQgPSBuZXcgQ2hpbGRQYXJ0KHN0YXJ0Tm9kZSwgZW5kTm9kZSwgY29udGFpbmVyUGFydCwgY29udGFpbmVyUGFydC5vcHRpb25zKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGNvbnN0IGVuZE5vZGUgPSB3cmFwKHBhcnQuXyRlbmROb2RlKS5uZXh0U2libGluZztcbiAgICAgICAgY29uc3Qgb2xkUGFyZW50ID0gcGFydC5fJHBhcmVudDtcbiAgICAgICAgY29uc3QgcGFyZW50Q2hhbmdlZCA9IG9sZFBhcmVudCAhPT0gY29udGFpbmVyUGFydDtcbiAgICAgICAgaWYgKHBhcmVudENoYW5nZWQpIHtcbiAgICAgICAgICAgIHBhcnQuXyRyZXBhcmVudERpc2Nvbm5lY3RhYmxlcz8uKGNvbnRhaW5lclBhcnQpO1xuICAgICAgICAgICAgLy8gTm90ZSB0aGF0IGFsdGhvdWdoIGBfJHJlcGFyZW50RGlzY29ubmVjdGFibGVzYCB1cGRhdGVzIHRoZSBwYXJ0J3NcbiAgICAgICAgICAgIC8vIGBfJHBhcmVudGAgcmVmZXJlbmNlIGFmdGVyIHVubGlua2luZyBmcm9tIGl0cyBjdXJyZW50IHBhcmVudCwgdGhhdFxuICAgICAgICAgICAgLy8gbWV0aG9kIG9ubHkgZXhpc3RzIGlmIERpc2Nvbm5lY3RhYmxlcyBhcmUgcHJlc2VudCwgc28gd2UgbmVlZCB0b1xuICAgICAgICAgICAgLy8gdW5jb25kaXRpb25hbGx5IHNldCBpdCBoZXJlXG4gICAgICAgICAgICBwYXJ0Ll8kcGFyZW50ID0gY29udGFpbmVyUGFydDtcbiAgICAgICAgICAgIC8vIFNpbmNlIHRoZSBfJGlzQ29ubmVjdGVkIGdldHRlciBpcyBzb21ld2hhdCBjb3N0bHksIG9ubHlcbiAgICAgICAgICAgIC8vIHJlYWQgaXQgb25jZSB3ZSBrbm93IHRoZSBzdWJ0cmVlIGhhcyBkaXJlY3RpdmVzIHRoYXQgbmVlZFxuICAgICAgICAgICAgLy8gdG8gYmUgbm90aWZpZWRcbiAgICAgICAgICAgIGxldCBuZXdDb25uZWN0aW9uU3RhdGU7XG4gICAgICAgICAgICBpZiAocGFydC5fJG5vdGlmeUNvbm5lY3Rpb25DaGFuZ2VkICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgICAgICAobmV3Q29ubmVjdGlvblN0YXRlID0gY29udGFpbmVyUGFydC5fJGlzQ29ubmVjdGVkKSAhPT1cbiAgICAgICAgICAgICAgICAgICAgb2xkUGFyZW50Ll8kaXNDb25uZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICBwYXJ0Ll8kbm90aWZ5Q29ubmVjdGlvbkNoYW5nZWQobmV3Q29ubmVjdGlvblN0YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoZW5kTm9kZSAhPT0gcmVmTm9kZSB8fCBwYXJlbnRDaGFuZ2VkKSB7XG4gICAgICAgICAgICBsZXQgc3RhcnQgPSBwYXJ0Ll8kc3RhcnROb2RlO1xuICAgICAgICAgICAgd2hpbGUgKHN0YXJ0ICE9PSBlbmROb2RlKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbiA9IHdyYXAoc3RhcnQpLm5leHRTaWJsaW5nO1xuICAgICAgICAgICAgICAgIHdyYXAoY29udGFpbmVyKS5pbnNlcnRCZWZvcmUoc3RhcnQsIHJlZk5vZGUpO1xuICAgICAgICAgICAgICAgIHN0YXJ0ID0gbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcGFydDtcbn07XG4vKipcbiAqIFNldHMgdGhlIHZhbHVlIG9mIGEgUGFydC5cbiAqXG4gKiBOb3RlIHRoYXQgdGhpcyBzaG91bGQgb25seSBiZSB1c2VkIHRvIHNldC91cGRhdGUgdGhlIHZhbHVlIG9mIHVzZXItY3JlYXRlZFxuICogcGFydHMgKGkuZS4gdGhvc2UgY3JlYXRlZCB1c2luZyBgaW5zZXJ0UGFydGApOyBpdCBzaG91bGQgbm90IGJlIHVzZWRcbiAqIGJ5IGRpcmVjdGl2ZXMgdG8gc2V0IHRoZSB2YWx1ZSBvZiB0aGUgZGlyZWN0aXZlJ3MgY29udGFpbmVyIHBhcnQuIERpcmVjdGl2ZXNcbiAqIHNob3VsZCByZXR1cm4gYSB2YWx1ZSBmcm9tIGB1cGRhdGVgL2ByZW5kZXJgIHRvIHVwZGF0ZSB0aGVpciBwYXJ0IHN0YXRlLlxuICpcbiAqIEZvciBkaXJlY3RpdmVzIHRoYXQgcmVxdWlyZSBzZXR0aW5nIHRoZWlyIHBhcnQgdmFsdWUgYXN5bmNocm9ub3VzbHksIHRoZXlcbiAqIHNob3VsZCBleHRlbmQgYEFzeW5jRGlyZWN0aXZlYCBhbmQgY2FsbCBgdGhpcy5zZXRWYWx1ZSgpYC5cbiAqXG4gKiBAcGFyYW0gcGFydCBQYXJ0IHRvIHNldFxuICogQHBhcmFtIHZhbHVlIFZhbHVlIHRvIHNldFxuICogQHBhcmFtIGluZGV4IEZvciBgQXR0cmlidXRlUGFydGBzLCB0aGUgaW5kZXggdG8gc2V0XG4gKiBAcGFyYW0gZGlyZWN0aXZlUGFyZW50IFVzZWQgaW50ZXJuYWxseTsgc2hvdWxkIG5vdCBiZSBzZXQgYnkgdXNlclxuICovXG5leHBvcnQgY29uc3Qgc2V0Q2hpbGRQYXJ0VmFsdWUgPSAocGFydCwgdmFsdWUsIGRpcmVjdGl2ZVBhcmVudCA9IHBhcnQpID0+IHtcbiAgICBwYXJ0Ll8kc2V0VmFsdWUodmFsdWUsIGRpcmVjdGl2ZVBhcmVudCk7XG4gICAgcmV0dXJuIHBhcnQ7XG59O1xuLy8gQSBzZW50aW5lbCB2YWx1ZSB0aGF0IGNhbiBuZXZlciBhcHBlYXIgYXMgYSBwYXJ0IHZhbHVlIGV4Y2VwdCB3aGVuIHNldCBieVxuLy8gbGl2ZSgpLiBVc2VkIHRvIGZvcmNlIGEgZGlydHktY2hlY2sgdG8gZmFpbCBhbmQgY2F1c2UgYSByZS1yZW5kZXIuXG5jb25zdCBSRVNFVF9WQUxVRSA9IHt9O1xuLyoqXG4gKiBTZXRzIHRoZSBjb21taXR0ZWQgdmFsdWUgb2YgYSBDaGlsZFBhcnQgZGlyZWN0bHkgd2l0aG91dCB0cmlnZ2VyaW5nIHRoZVxuICogY29tbWl0IHN0YWdlIG9mIHRoZSBwYXJ0LlxuICpcbiAqIFRoaXMgaXMgdXNlZnVsIGluIGNhc2VzIHdoZXJlIGEgZGlyZWN0aXZlIG5lZWRzIHRvIHVwZGF0ZSB0aGUgcGFydCBzdWNoXG4gKiB0aGF0IHRoZSBuZXh0IHVwZGF0ZSBkZXRlY3RzIGEgdmFsdWUgY2hhbmdlIG9yIG5vdC4gV2hlbiB2YWx1ZSBpcyBvbWl0dGVkLFxuICogdGhlIG5leHQgdXBkYXRlIHdpbGwgYmUgZ3VhcmFudGVlZCB0byBiZSBkZXRlY3RlZCBhcyBhIGNoYW5nZS5cbiAqXG4gKiBAcGFyYW0gcGFydFxuICogQHBhcmFtIHZhbHVlXG4gKi9cbmV4cG9ydCBjb25zdCBzZXRDb21taXR0ZWRWYWx1ZSA9IChwYXJ0LCB2YWx1ZSA9IFJFU0VUX1ZBTFVFKSA9PiAocGFydC5fJGNvbW1pdHRlZFZhbHVlID0gdmFsdWUpO1xuLyoqXG4gKiBSZXR1cm5zIHRoZSBjb21taXR0ZWQgdmFsdWUgb2YgYSBDaGlsZFBhcnQuXG4gKlxuICogVGhlIGNvbW1pdHRlZCB2YWx1ZSBpcyB1c2VkIGZvciBjaGFuZ2UgZGV0ZWN0aW9uIGFuZCBlZmZpY2llbnQgdXBkYXRlcyBvZlxuICogdGhlIHBhcnQuIEl0IGNhbiBkaWZmZXIgZnJvbSB0aGUgdmFsdWUgc2V0IGJ5IHRoZSB0ZW1wbGF0ZSBvciBkaXJlY3RpdmUgaW5cbiAqIGNhc2VzIHdoZXJlIHRoZSB0ZW1wbGF0ZSB2YWx1ZSBpcyB0cmFuc2Zvcm1lZCBiZWZvcmUgYmVpbmcgY29tbWl0dGVkLlxuICpcbiAqIC0gYFRlbXBsYXRlUmVzdWx0YHMgYXJlIGNvbW1pdHRlZCBhcyBhIGBUZW1wbGF0ZUluc3RhbmNlYFxuICogLSBJdGVyYWJsZXMgYXJlIGNvbW1pdHRlZCBhcyBgQXJyYXk8Q2hpbGRQYXJ0PmBcbiAqIC0gQWxsIG90aGVyIHR5cGVzIGFyZSBjb21taXR0ZWQgYXMgdGhlIHRlbXBsYXRlIHZhbHVlIG9yIHZhbHVlIHJldHVybmVkIG9yXG4gKiAgIHNldCBieSBhIGRpcmVjdGl2ZS5cbiAqXG4gKiBAcGFyYW0gcGFydFxuICovXG5leHBvcnQgY29uc3QgZ2V0Q29tbWl0dGVkVmFsdWUgPSAocGFydCkgPT4gcGFydC5fJGNvbW1pdHRlZFZhbHVlO1xuLyoqXG4gKiBSZW1vdmVzIGEgQ2hpbGRQYXJ0IGZyb20gdGhlIERPTSwgaW5jbHVkaW5nIGFueSBvZiBpdHMgY29udGVudC5cbiAqXG4gKiBAcGFyYW0gcGFydCBUaGUgUGFydCB0byByZW1vdmVcbiAqL1xuZXhwb3J0IGNvbnN0IHJlbW92ZVBhcnQgPSAocGFydCkgPT4ge1xuICAgIHBhcnQuXyRub3RpZnlDb25uZWN0aW9uQ2hhbmdlZD8uKGZhbHNlLCB0cnVlKTtcbiAgICBsZXQgc3RhcnQgPSBwYXJ0Ll8kc3RhcnROb2RlO1xuICAgIGNvbnN0IGVuZCA9IHdyYXAocGFydC5fJGVuZE5vZGUpLm5leHRTaWJsaW5nO1xuICAgIHdoaWxlIChzdGFydCAhPT0gZW5kKSB7XG4gICAgICAgIGNvbnN0IG4gPSB3cmFwKHN0YXJ0KS5uZXh0U2libGluZztcbiAgICAgICAgd3JhcChzdGFydCkucmVtb3ZlKCk7XG4gICAgICAgIHN0YXJ0ID0gbjtcbiAgICB9XG59O1xuZXhwb3J0IGNvbnN0IGNsZWFyUGFydCA9IChwYXJ0KSA9PiB7XG4gICAgcGFydC5fJGNsZWFyKCk7XG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGlyZWN0aXZlLWhlbHBlcnMuanMubWFwIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEJTRC0zLUNsYXVzZVxuICovXG5pbXBvcnQgeyBub0NoYW5nZSwgbm90aGluZyB9IGZyb20gJy4uL2xpdC1odG1sLmpzJztcbmltcG9ydCB7IGRpcmVjdGl2ZSwgRGlyZWN0aXZlLCBQYXJ0VHlwZSwgfSBmcm9tICcuLi9kaXJlY3RpdmUuanMnO1xuaW1wb3J0IHsgaXNTaW5nbGVFeHByZXNzaW9uLCBzZXRDb21taXR0ZWRWYWx1ZSB9IGZyb20gJy4uL2RpcmVjdGl2ZS1oZWxwZXJzLmpzJztcbmNsYXNzIExpdmVEaXJlY3RpdmUgZXh0ZW5kcyBEaXJlY3RpdmUge1xuICAgIGNvbnN0cnVjdG9yKHBhcnRJbmZvKSB7XG4gICAgICAgIHN1cGVyKHBhcnRJbmZvKTtcbiAgICAgICAgaWYgKCEocGFydEluZm8udHlwZSA9PT0gUGFydFR5cGUuUFJPUEVSVFkgfHxcbiAgICAgICAgICAgIHBhcnRJbmZvLnR5cGUgPT09IFBhcnRUeXBlLkFUVFJJQlVURSB8fFxuICAgICAgICAgICAgcGFydEluZm8udHlwZSA9PT0gUGFydFR5cGUuQk9PTEVBTl9BVFRSSUJVVEUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBgbGl2ZWAgZGlyZWN0aXZlIGlzIG5vdCBhbGxvd2VkIG9uIGNoaWxkIG9yIGV2ZW50IGJpbmRpbmdzJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1NpbmdsZUV4cHJlc3Npb24ocGFydEluZm8pKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2BsaXZlYCBiaW5kaW5ncyBjYW4gb25seSBjb250YWluIGEgc2luZ2xlIGV4cHJlc3Npb24nKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZW5kZXIodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICB1cGRhdGUocGFydCwgW3ZhbHVlXSkge1xuICAgICAgICBpZiAodmFsdWUgPT09IG5vQ2hhbmdlIHx8IHZhbHVlID09PSBub3RoaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZWxlbWVudCA9IHBhcnQuZWxlbWVudDtcbiAgICAgICAgY29uc3QgbmFtZSA9IHBhcnQubmFtZTtcbiAgICAgICAgaWYgKHBhcnQudHlwZSA9PT0gUGFydFR5cGUuUFJPUEVSVFkpIHtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgICAgICBpZiAodmFsdWUgPT09IGVsZW1lbnRbbmFtZV0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbm9DaGFuZ2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAocGFydC50eXBlID09PSBQYXJ0VHlwZS5CT09MRUFOX0FUVFJJQlVURSkge1xuICAgICAgICAgICAgaWYgKCEhdmFsdWUgPT09IGVsZW1lbnQuaGFzQXR0cmlidXRlKG5hbWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vQ2hhbmdlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHBhcnQudHlwZSA9PT0gUGFydFR5cGUuQVRUUklCVVRFKSB7XG4gICAgICAgICAgICBpZiAoZWxlbWVudC5nZXRBdHRyaWJ1dGUobmFtZSkgPT09IFN0cmluZyh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbm9DaGFuZ2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmVzZXRzIHRoZSBwYXJ0J3MgdmFsdWUsIGNhdXNpbmcgaXRzIGRpcnR5LWNoZWNrIHRvIGZhaWwgc28gdGhhdCBpdFxuICAgICAgICAvLyBhbHdheXMgc2V0cyB0aGUgdmFsdWUuXG4gICAgICAgIHNldENvbW1pdHRlZFZhbHVlKHBhcnQpO1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxufVxuLyoqXG4gKiBDaGVja3MgYmluZGluZyB2YWx1ZXMgYWdhaW5zdCBsaXZlIERPTSB2YWx1ZXMsIGluc3RlYWQgb2YgcHJldmlvdXNseSBib3VuZFxuICogdmFsdWVzLCB3aGVuIGRldGVybWluaW5nIHdoZXRoZXIgdG8gdXBkYXRlIHRoZSB2YWx1ZS5cbiAqXG4gKiBUaGlzIGlzIHVzZWZ1bCBmb3IgY2FzZXMgd2hlcmUgdGhlIERPTSB2YWx1ZSBtYXkgY2hhbmdlIGZyb20gb3V0c2lkZSBvZlxuICogbGl0LWh0bWwsIHN1Y2ggYXMgd2l0aCBhIGJpbmRpbmcgdG8gYW4gYDxpbnB1dD5gIGVsZW1lbnQncyBgdmFsdWVgIHByb3BlcnR5LFxuICogYSBjb250ZW50IGVkaXRhYmxlIGVsZW1lbnRzIHRleHQsIG9yIHRvIGEgY3VzdG9tIGVsZW1lbnQgdGhhdCBjaGFuZ2VzIGl0J3NcbiAqIG93biBwcm9wZXJ0aWVzIG9yIGF0dHJpYnV0ZXMuXG4gKlxuICogSW4gdGhlc2UgY2FzZXMgaWYgdGhlIERPTSB2YWx1ZSBjaGFuZ2VzLCBidXQgdGhlIHZhbHVlIHNldCB0aHJvdWdoIGxpdC1odG1sXG4gKiBiaW5kaW5ncyBoYXNuJ3QsIGxpdC1odG1sIHdvbid0IGtub3cgdG8gdXBkYXRlIHRoZSBET00gdmFsdWUgYW5kIHdpbGwgbGVhdmVcbiAqIGl0IGFsb25lLiBJZiB0aGlzIGlzIG5vdCB3aGF0IHlvdSB3YW50LS1pZiB5b3Ugd2FudCB0byBvdmVyd3JpdGUgdGhlIERPTVxuICogdmFsdWUgd2l0aCB0aGUgYm91bmQgdmFsdWUgbm8gbWF0dGVyIHdoYXQtLXVzZSB0aGUgYGxpdmUoKWAgZGlyZWN0aXZlOlxuICpcbiAqIGBgYGpzXG4gKiBodG1sYDxpbnB1dCAudmFsdWU9JHtsaXZlKHgpfT5gXG4gKiBgYGBcbiAqXG4gKiBgbGl2ZSgpYCBwZXJmb3JtcyBhIHN0cmljdCBlcXVhbGl0eSBjaGVjayBhZ2FpbnN0IHRoZSBsaXZlIERPTSB2YWx1ZSwgYW5kIGlmXG4gKiB0aGUgbmV3IHZhbHVlIGlzIGVxdWFsIHRvIHRoZSBsaXZlIHZhbHVlLCBkb2VzIG5vdGhpbmcuIFRoaXMgbWVhbnMgdGhhdFxuICogYGxpdmUoKWAgc2hvdWxkIG5vdCBiZSB1c2VkIHdoZW4gdGhlIGJpbmRpbmcgd2lsbCBjYXVzZSBhIHR5cGUgY29udmVyc2lvbi4gSWZcbiAqIHlvdSB1c2UgYGxpdmUoKWAgd2l0aCBhbiBhdHRyaWJ1dGUgYmluZGluZywgbWFrZSBzdXJlIHRoYXQgb25seSBzdHJpbmdzIGFyZVxuICogcGFzc2VkIGluLCBvciB0aGUgYmluZGluZyB3aWxsIHVwZGF0ZSBldmVyeSByZW5kZXIuXG4gKi9cbmV4cG9ydCBjb25zdCBsaXZlID0gZGlyZWN0aXZlKExpdmVEaXJlY3RpdmUpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9bGl2ZS5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOCBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQlNELTMtQ2xhdXNlXG4gKi9cbmltcG9ydCB7IG5vQ2hhbmdlIH0gZnJvbSAnLi4vbGl0LWh0bWwuanMnO1xuaW1wb3J0IHsgZGlyZWN0aXZlLCBEaXJlY3RpdmUsIFBhcnRUeXBlLCB9IGZyb20gJy4uL2RpcmVjdGl2ZS5qcyc7XG5jb25zdCBpbXBvcnRhbnQgPSAnaW1wb3J0YW50Jztcbi8vIFRoZSBsZWFkaW5nIHNwYWNlIGlzIGltcG9ydGFudFxuY29uc3QgaW1wb3J0YW50RmxhZyA9ICcgIScgKyBpbXBvcnRhbnQ7XG4vLyBIb3cgbWFueSBjaGFyYWN0ZXJzIHRvIHJlbW92ZSBmcm9tIGEgdmFsdWUsIGFzIGEgbmVnYXRpdmUgbnVtYmVyXG5jb25zdCBmbGFnVHJpbSA9IDAgLSBpbXBvcnRhbnRGbGFnLmxlbmd0aDtcbmNsYXNzIFN0eWxlTWFwRGlyZWN0aXZlIGV4dGVuZHMgRGlyZWN0aXZlIHtcbiAgICBjb25zdHJ1Y3RvcihwYXJ0SW5mbykge1xuICAgICAgICBzdXBlcihwYXJ0SW5mbyk7XG4gICAgICAgIGlmIChwYXJ0SW5mby50eXBlICE9PSBQYXJ0VHlwZS5BVFRSSUJVVEUgfHxcbiAgICAgICAgICAgIHBhcnRJbmZvLm5hbWUgIT09ICdzdHlsZScgfHxcbiAgICAgICAgICAgIHBhcnRJbmZvLnN0cmluZ3M/Lmxlbmd0aCA+IDIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGBzdHlsZU1hcGAgZGlyZWN0aXZlIG11c3QgYmUgdXNlZCBpbiB0aGUgYHN0eWxlYCBhdHRyaWJ1dGUgJyArXG4gICAgICAgICAgICAgICAgJ2FuZCBtdXN0IGJlIHRoZSBvbmx5IHBhcnQgaW4gdGhlIGF0dHJpYnV0ZS4nKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZW5kZXIoc3R5bGVJbmZvKSB7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhzdHlsZUluZm8pLnJlZHVjZSgoc3R5bGUsIHByb3ApID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gc3R5bGVJbmZvW3Byb3BdO1xuICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3R5bGU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDb252ZXJ0IHByb3BlcnR5IG5hbWVzIGZyb20gY2FtZWwtY2FzZSB0byBkYXNoLWNhc2UsIGkuZS46XG4gICAgICAgICAgICAvLyAgYGJhY2tncm91bmRDb2xvcmAgLT4gYGJhY2tncm91bmQtY29sb3JgXG4gICAgICAgICAgICAvLyBWZW5kb3ItcHJlZml4ZWQgbmFtZXMgbmVlZCBhbiBleHRyYSBgLWAgYXBwZW5kZWQgdG8gZnJvbnQ6XG4gICAgICAgICAgICAvLyAgYHdlYmtpdEFwcGVhcmFuY2VgIC0+IGAtd2Via2l0LWFwcGVhcmFuY2VgXG4gICAgICAgICAgICAvLyBFeGNlcHRpb24gaXMgYW55IHByb3BlcnR5IG5hbWUgY29udGFpbmluZyBhIGRhc2gsIGluY2x1ZGluZ1xuICAgICAgICAgICAgLy8gY3VzdG9tIHByb3BlcnRpZXM7IHdlIGFzc3VtZSB0aGVzZSBhcmUgYWxyZWFkeSBkYXNoLWNhc2VkIGkuZS46XG4gICAgICAgICAgICAvLyAgYC0tbXktYnV0dG9uLWNvbG9yYCAtLT4gYC0tbXktYnV0dG9uLWNvbG9yYFxuICAgICAgICAgICAgcHJvcCA9IHByb3AuaW5jbHVkZXMoJy0nKVxuICAgICAgICAgICAgICAgID8gcHJvcFxuICAgICAgICAgICAgICAgIDogcHJvcFxuICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvKD86Xih3ZWJraXR8bW96fG1zfG8pfCkoPz1bQS1aXSkvZywgJy0kJicpXG4gICAgICAgICAgICAgICAgICAgIC50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgcmV0dXJuIHN0eWxlICsgYCR7cHJvcH06JHt2YWx1ZX07YDtcbiAgICAgICAgfSwgJycpO1xuICAgIH1cbiAgICB1cGRhdGUocGFydCwgW3N0eWxlSW5mb10pIHtcbiAgICAgICAgY29uc3QgeyBzdHlsZSB9ID0gcGFydC5lbGVtZW50O1xuICAgICAgICBpZiAodGhpcy5fcHJldmlvdXNTdHlsZVByb3BlcnRpZXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhpcy5fcHJldmlvdXNTdHlsZVByb3BlcnRpZXMgPSBuZXcgU2V0KE9iamVjdC5rZXlzKHN0eWxlSW5mbykpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVuZGVyKHN0eWxlSW5mbyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmVtb3ZlIG9sZCBwcm9wZXJ0aWVzIHRoYXQgbm8gbG9uZ2VyIGV4aXN0IGluIHN0eWxlSW5mb1xuICAgICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgdGhpcy5fcHJldmlvdXNTdHlsZVByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIC8vIElmIHRoZSBuYW1lIGlzbid0IGluIHN0eWxlSW5mbyBvciBpdCdzIG51bGwvdW5kZWZpbmVkXG4gICAgICAgICAgICBpZiAoc3R5bGVJbmZvW25hbWVdID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9wcmV2aW91c1N0eWxlUHJvcGVydGllcy5kZWxldGUobmFtZSk7XG4gICAgICAgICAgICAgICAgaWYgKG5hbWUuaW5jbHVkZXMoJy0nKSkge1xuICAgICAgICAgICAgICAgICAgICBzdHlsZS5yZW1vdmVQcm9wZXJ0eShuYW1lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgICAgICAgICAgICAgIHN0eWxlW25hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gQWRkIG9yIHVwZGF0ZSBwcm9wZXJ0aWVzXG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBpbiBzdHlsZUluZm8pIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gc3R5bGVJbmZvW25hbWVdO1xuICAgICAgICAgICAgaWYgKHZhbHVlICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9wcmV2aW91c1N0eWxlUHJvcGVydGllcy5hZGQobmFtZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgaXNJbXBvcnRhbnQgPSB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlLmVuZHNXaXRoKGltcG9ydGFudEZsYWcpO1xuICAgICAgICAgICAgICAgIGlmIChuYW1lLmluY2x1ZGVzKCctJykgfHwgaXNJbXBvcnRhbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgc3R5bGUuc2V0UHJvcGVydHkobmFtZSwgaXNJbXBvcnRhbnRcbiAgICAgICAgICAgICAgICAgICAgICAgID8gdmFsdWUuc2xpY2UoMCwgZmxhZ1RyaW0pXG4gICAgICAgICAgICAgICAgICAgICAgICA6IHZhbHVlLCBpc0ltcG9ydGFudCA/IGltcG9ydGFudCA6ICcnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgICAgICAgICAgICAgIHN0eWxlW25hbWVdID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBub0NoYW5nZTtcbiAgICB9XG59XG4vKipcbiAqIEEgZGlyZWN0aXZlIHRoYXQgYXBwbGllcyBDU1MgcHJvcGVydGllcyB0byBhbiBlbGVtZW50LlxuICpcbiAqIGBzdHlsZU1hcGAgY2FuIG9ubHkgYmUgdXNlZCBpbiB0aGUgYHN0eWxlYCBhdHRyaWJ1dGUgYW5kIG11c3QgYmUgdGhlIG9ubHlcbiAqIGV4cHJlc3Npb24gaW4gdGhlIGF0dHJpYnV0ZS4gSXQgdGFrZXMgdGhlIHByb3BlcnR5IG5hbWVzIGluIHRoZVxuICoge0BsaW5rIFN0eWxlSW5mbyBzdHlsZUluZm99IG9iamVjdCBhbmQgYWRkcyB0aGUgcHJvcGVydGllcyB0byB0aGUgaW5saW5lXG4gKiBzdHlsZSBvZiB0aGUgZWxlbWVudC5cbiAqXG4gKiBQcm9wZXJ0eSBuYW1lcyB3aXRoIGRhc2hlcyAoYC1gKSBhcmUgYXNzdW1lZCB0byBiZSB2YWxpZCBDU1NcbiAqIHByb3BlcnR5IG5hbWVzIGFuZCBzZXQgb24gdGhlIGVsZW1lbnQncyBzdHlsZSBvYmplY3QgdXNpbmcgYHNldFByb3BlcnR5KClgLlxuICogTmFtZXMgd2l0aG91dCBkYXNoZXMgYXJlIGFzc3VtZWQgdG8gYmUgY2FtZWxDYXNlZCBKYXZhU2NyaXB0IHByb3BlcnR5IG5hbWVzXG4gKiBhbmQgc2V0IG9uIHRoZSBlbGVtZW50J3Mgc3R5bGUgb2JqZWN0IHVzaW5nIHByb3BlcnR5IGFzc2lnbm1lbnQsIGFsbG93aW5nIHRoZVxuICogc3R5bGUgb2JqZWN0IHRvIHRyYW5zbGF0ZSBKYXZhU2NyaXB0LXN0eWxlIG5hbWVzIHRvIENTUyBwcm9wZXJ0eSBuYW1lcy5cbiAqXG4gKiBGb3IgZXhhbXBsZSBgc3R5bGVNYXAoe2JhY2tncm91bmRDb2xvcjogJ3JlZCcsICdib3JkZXItdG9wJzogJzVweCcsICctLXNpemUnOlxuICogJzAnfSlgIHNldHMgdGhlIGBiYWNrZ3JvdW5kLWNvbG9yYCwgYGJvcmRlci10b3BgIGFuZCBgLS1zaXplYCBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwYXJhbSBzdHlsZUluZm9cbiAqIEBzZWUge0BsaW5rIGh0dHBzOi8vbGl0LmRldi9kb2NzL3RlbXBsYXRlcy9kaXJlY3RpdmVzLyNzdHlsZW1hcCBzdHlsZU1hcCBjb2RlIHNhbXBsZXMgb24gTGl0LmRldn1cbiAqL1xuZXhwb3J0IGNvbnN0IHN0eWxlTWFwID0gZGlyZWN0aXZlKFN0eWxlTWFwRGlyZWN0aXZlKTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXN0eWxlLW1hcC5qcy5tYXAiLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQlNELTMtQ2xhdXNlXG4gKi9cbi8vIEFueSBuZXcgZXhwb3J0cyBuZWVkIHRvIGJlIGFkZGVkIHRvIHRoZSBleHBvcnQgc3RhdGVtZW50IGluXG4vLyBgcGFja2FnZXMvbGl0L3NyYy9pbmRleC5hbGwudHNgLlxuaW1wb3J0IHsgaHRtbCBhcyBjb3JlSHRtbCwgc3ZnIGFzIGNvcmVTdmcsIG1hdGhtbCBhcyBjb3JlTWF0aG1sLCB9IGZyb20gJy4vbGl0LWh0bWwuanMnO1xuLyoqXG4gKiBQcmV2ZW50cyBKU09OIGluamVjdGlvbiBhdHRhY2tzLlxuICpcbiAqIFRoZSBnb2FscyBvZiB0aGlzIGJyYW5kOlxuICogICAxKSBmYXN0IHRvIGNoZWNrXG4gKiAgIDIpIGNvZGUgaXMgc21hbGwgb24gdGhlIHdpcmVcbiAqICAgMykgbXVsdGlwbGUgdmVyc2lvbnMgb2YgTGl0IGluIGEgc2luZ2xlIHBhZ2Ugd2lsbCBhbGwgcHJvZHVjZSBtdXR1YWxseVxuICogICAgICBpbnRlcm9wZXJhYmxlIFN0YXRpY1ZhbHVlc1xuICogICA0KSBub3JtYWwgSlNPTi5wYXJzZSAod2l0aG91dCBhbiB1bnVzdWFsIHJldml2ZXIpIGNhbiBub3QgcHJvZHVjZSBhXG4gKiAgICAgIFN0YXRpY1ZhbHVlXG4gKlxuICogU3ltYm9scyBzYXRpc2Z5ICgxKSwgKDIpLCBhbmQgKDQpLiBXZSB1c2UgU3ltYm9sLmZvciB0byBzYXRpc2Z5ICgzKSwgYnV0XG4gKiB3ZSBkb24ndCBjYXJlIGFib3V0IHRoZSBrZXksIHNvIHdlIGJyZWFrIHRpZXMgdmlhICgyKSBhbmQgdXNlIHRoZSBlbXB0eVxuICogc3RyaW5nLlxuICovXG5jb25zdCBicmFuZCA9IFN5bWJvbC5mb3IoJycpO1xuLyoqIFNhZmVseSBleHRyYWN0cyB0aGUgc3RyaW5nIHBhcnQgb2YgYSBTdGF0aWNWYWx1ZS4gKi9cbmNvbnN0IHVud3JhcFN0YXRpY1ZhbHVlID0gKHZhbHVlKSA9PiB7XG4gICAgaWYgKHZhbHVlPy5yICE9PSBicmFuZCkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU/LlsnXyRsaXRTdGF0aWMkJ107XG59O1xuLyoqXG4gKiBXcmFwcyBhIHN0cmluZyBzbyB0aGF0IGl0IGJlaGF2ZXMgbGlrZSBwYXJ0IG9mIHRoZSBzdGF0aWMgdGVtcGxhdGVcbiAqIHN0cmluZ3MgaW5zdGVhZCBvZiBhIGR5bmFtaWMgdmFsdWUuXG4gKlxuICogVXNlcnMgbXVzdCB0YWtlIGNhcmUgdG8gZW5zdXJlIHRoYXQgYWRkaW5nIHRoZSBzdGF0aWMgc3RyaW5nIHRvIHRoZSB0ZW1wbGF0ZVxuICogcmVzdWx0cyBpbiB3ZWxsLWZvcm1lZCBIVE1MLCBvciBlbHNlIHRlbXBsYXRlcyBtYXkgYnJlYWsgdW5leHBlY3RlZGx5LlxuICpcbiAqIE5vdGUgdGhhdCB0aGlzIGZ1bmN0aW9uIGlzIHVuc2FmZSB0byB1c2Ugb24gdW50cnVzdGVkIGNvbnRlbnQsIGFzIGl0IHdpbGwgYmVcbiAqIGRpcmVjdGx5IHBhcnNlZCBpbnRvIEhUTUwuIERvIG5vdCBwYXNzIHVzZXIgaW5wdXQgdG8gdGhpcyBmdW5jdGlvblxuICogd2l0aG91dCBzYW5pdGl6aW5nIGl0LlxuICpcbiAqIFN0YXRpYyB2YWx1ZXMgY2FuIGJlIGNoYW5nZWQsIGJ1dCB0aGV5IHdpbGwgY2F1c2UgYSBjb21wbGV0ZSByZS1yZW5kZXJcbiAqIHNpbmNlIHRoZXkgZWZmZWN0aXZlbHkgY3JlYXRlIGEgbmV3IHRlbXBsYXRlLlxuICovXG5leHBvcnQgY29uc3QgdW5zYWZlU3RhdGljID0gKHZhbHVlKSA9PiAoe1xuICAgIFsnXyRsaXRTdGF0aWMkJ106IHZhbHVlLFxuICAgIHI6IGJyYW5kLFxufSk7XG5jb25zdCB0ZXh0RnJvbVN0YXRpYyA9ICh2YWx1ZSkgPT4ge1xuICAgIGlmICh2YWx1ZVsnXyRsaXRTdGF0aWMkJ10gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gdmFsdWVbJ18kbGl0U3RhdGljJCddO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBWYWx1ZSBwYXNzZWQgdG8gJ2xpdGVyYWwnIGZ1bmN0aW9uIG11c3QgYmUgYSAnbGl0ZXJhbCcgcmVzdWx0OiAke3ZhbHVlfS4gVXNlICd1bnNhZmVTdGF0aWMnIHRvIHBhc3Mgbm9uLWxpdGVyYWwgdmFsdWVzLCBidXRcbiAgICAgICAgICAgIHRha2UgY2FyZSB0byBlbnN1cmUgcGFnZSBzZWN1cml0eS5gKTtcbiAgICB9XG59O1xuLyoqXG4gKiBUYWdzIGEgc3RyaW5nIGxpdGVyYWwgc28gdGhhdCBpdCBiZWhhdmVzIGxpa2UgcGFydCBvZiB0aGUgc3RhdGljIHRlbXBsYXRlXG4gKiBzdHJpbmdzIGluc3RlYWQgb2YgYSBkeW5hbWljIHZhbHVlLlxuICpcbiAqIFRoZSBvbmx5IHZhbHVlcyB0aGF0IG1heSBiZSB1c2VkIGluIHRlbXBsYXRlIGV4cHJlc3Npb25zIGFyZSBvdGhlciB0YWdnZWRcbiAqIGBsaXRlcmFsYCByZXN1bHRzIG9yIGB1bnNhZmVTdGF0aWNgIHZhbHVlcyAobm90ZSB0aGF0IHVudHJ1c3RlZCBjb250ZW50XG4gKiBzaG91bGQgbmV2ZXIgYmUgcGFzc2VkIHRvIGB1bnNhZmVTdGF0aWNgKS5cbiAqXG4gKiBVc2VycyBtdXN0IHRha2UgY2FyZSB0byBlbnN1cmUgdGhhdCBhZGRpbmcgdGhlIHN0YXRpYyBzdHJpbmcgdG8gdGhlIHRlbXBsYXRlXG4gKiByZXN1bHRzIGluIHdlbGwtZm9ybWVkIEhUTUwsIG9yIGVsc2UgdGVtcGxhdGVzIG1heSBicmVhayB1bmV4cGVjdGVkbHkuXG4gKlxuICogU3RhdGljIHZhbHVlcyBjYW4gYmUgY2hhbmdlZCwgYnV0IHRoZXkgd2lsbCBjYXVzZSBhIGNvbXBsZXRlIHJlLXJlbmRlciBzaW5jZVxuICogdGhleSBlZmZlY3RpdmVseSBjcmVhdGUgYSBuZXcgdGVtcGxhdGUuXG4gKi9cbmV4cG9ydCBjb25zdCBsaXRlcmFsID0gKHN0cmluZ3MsIC4uLnZhbHVlcykgPT4gKHtcbiAgICBbJ18kbGl0U3RhdGljJCddOiB2YWx1ZXMucmVkdWNlKChhY2MsIHYsIGlkeCkgPT4gYWNjICsgdGV4dEZyb21TdGF0aWModikgKyBzdHJpbmdzW2lkeCArIDFdLCBzdHJpbmdzWzBdKSxcbiAgICByOiBicmFuZCxcbn0pO1xuY29uc3Qgc3RyaW5nc0NhY2hlID0gbmV3IE1hcCgpO1xuLyoqXG4gKiBXcmFwcyBhIGxpdC1odG1sIHRlbXBsYXRlIHRhZyAoYGh0bWxgIG9yIGBzdmdgKSB0byBhZGQgc3RhdGljIHZhbHVlIHN1cHBvcnQuXG4gKi9cbmV4cG9ydCBjb25zdCB3aXRoU3RhdGljID0gKGNvcmVUYWcpID0+IChzdHJpbmdzLCAuLi52YWx1ZXMpID0+IHtcbiAgICBjb25zdCBsID0gdmFsdWVzLmxlbmd0aDtcbiAgICBsZXQgc3RhdGljVmFsdWU7XG4gICAgbGV0IGR5bmFtaWNWYWx1ZTtcbiAgICBjb25zdCBzdGF0aWNTdHJpbmdzID0gW107XG4gICAgY29uc3QgZHluYW1pY1ZhbHVlcyA9IFtdO1xuICAgIGxldCBpID0gMDtcbiAgICBsZXQgaGFzU3RhdGljcyA9IGZhbHNlO1xuICAgIGxldCBzO1xuICAgIHdoaWxlIChpIDwgbCkge1xuICAgICAgICBzID0gc3RyaW5nc1tpXTtcbiAgICAgICAgLy8gQ29sbGVjdCBhbnkgdW5zYWZlU3RhdGljIHZhbHVlcywgYW5kIHRoZWlyIGZvbGxvd2luZyB0ZW1wbGF0ZSBzdHJpbmdzXG4gICAgICAgIC8vIHNvIHRoYXQgd2UgdHJlYXQgYSBydW4gb2YgdGVtcGxhdGUgc3RyaW5ncyBhbmQgdW5zYWZlIHN0YXRpYyB2YWx1ZXMgYXNcbiAgICAgICAgLy8gYSBzaW5nbGUgdGVtcGxhdGUgc3RyaW5nLlxuICAgICAgICB3aGlsZSAoaSA8IGwgJiZcbiAgICAgICAgICAgICgoZHluYW1pY1ZhbHVlID0gdmFsdWVzW2ldKSxcbiAgICAgICAgICAgICAgICAoc3RhdGljVmFsdWUgPSB1bndyYXBTdGF0aWNWYWx1ZShkeW5hbWljVmFsdWUpKSkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcyArPSBzdGF0aWNWYWx1ZSArIHN0cmluZ3NbKytpXTtcbiAgICAgICAgICAgIGhhc1N0YXRpY3MgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIElmIHRoZSBsYXN0IHZhbHVlIGlzIHN0YXRpYywgd2UgZG9uJ3QgbmVlZCB0byBwdXNoIGl0LlxuICAgICAgICBpZiAoaSAhPT0gbCkge1xuICAgICAgICAgICAgZHluYW1pY1ZhbHVlcy5wdXNoKGR5bmFtaWNWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljU3RyaW5ncy5wdXNoKHMpO1xuICAgICAgICBpKys7XG4gICAgfVxuICAgIC8vIElmIHRoZSBsYXN0IHZhbHVlIGlzbid0IHN0YXRpYyAod2hpY2ggd291bGQgaGF2ZSBjb25zdW1lZCB0aGUgbGFzdFxuICAgIC8vIHN0cmluZyksIHRoZW4gd2UgbmVlZCB0byBhZGQgdGhlIGxhc3Qgc3RyaW5nLlxuICAgIGlmIChpID09PSBsKSB7XG4gICAgICAgIHN0YXRpY1N0cmluZ3MucHVzaChzdHJpbmdzW2xdKTtcbiAgICB9XG4gICAgaWYgKGhhc1N0YXRpY3MpIHtcbiAgICAgICAgY29uc3Qga2V5ID0gc3RhdGljU3RyaW5ncy5qb2luKCckJGxpdCQkJyk7XG4gICAgICAgIHN0cmluZ3MgPSBzdHJpbmdzQ2FjaGUuZ2V0KGtleSk7XG4gICAgICAgIGlmIChzdHJpbmdzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIEJld2FyZTogaW4gZ2VuZXJhbCB0aGlzIHBhdHRlcm4gaXMgdW5zYWZlLCBhbmQgZG9pbmcgc28gbWF5IGJ5cGFzc1xuICAgICAgICAgICAgLy8gbGl0J3Mgc2VjdXJpdHkgY2hlY2tzIGFuZCBhbGxvdyBhbiBhdHRhY2tlciB0byBleGVjdXRlIGFyYml0cmFyeVxuICAgICAgICAgICAgLy8gY29kZSBhbmQgaW5qZWN0IGFyYml0cmFyeSBjb250ZW50LlxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgICAgIHN0YXRpY1N0cmluZ3MucmF3ID0gc3RhdGljU3RyaW5ncztcbiAgICAgICAgICAgIHN0cmluZ3NDYWNoZS5zZXQoa2V5LCAoc3RyaW5ncyA9IHN0YXRpY1N0cmluZ3MpKTtcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZXMgPSBkeW5hbWljVmFsdWVzO1xuICAgIH1cbiAgICByZXR1cm4gY29yZVRhZyhzdHJpbmdzLCAuLi52YWx1ZXMpO1xufTtcbi8qKlxuICogSW50ZXJwcmV0cyBhIHRlbXBsYXRlIGxpdGVyYWwgYXMgYW4gSFRNTCB0ZW1wbGF0ZSB0aGF0IGNhbiBlZmZpY2llbnRseVxuICogcmVuZGVyIHRvIGFuZCB1cGRhdGUgYSBjb250YWluZXIuXG4gKlxuICogSW5jbHVkZXMgc3RhdGljIHZhbHVlIHN1cHBvcnQgZnJvbSBgbGl0LWh0bWwvc3RhdGljLmpzYC5cbiAqL1xuZXhwb3J0IGNvbnN0IGh0bWwgPSB3aXRoU3RhdGljKGNvcmVIdG1sKTtcbi8qKlxuICogSW50ZXJwcmV0cyBhIHRlbXBsYXRlIGxpdGVyYWwgYXMgYW4gU1ZHIHRlbXBsYXRlIHRoYXQgY2FuIGVmZmljaWVudGx5XG4gKiByZW5kZXIgdG8gYW5kIHVwZGF0ZSBhIGNvbnRhaW5lci5cbiAqXG4gKiBJbmNsdWRlcyBzdGF0aWMgdmFsdWUgc3VwcG9ydCBmcm9tIGBsaXQtaHRtbC9zdGF0aWMuanNgLlxuICovXG5leHBvcnQgY29uc3Qgc3ZnID0gd2l0aFN0YXRpYyhjb3JlU3ZnKTtcbi8qKlxuICogSW50ZXJwcmV0cyBhIHRlbXBsYXRlIGxpdGVyYWwgYXMgTWF0aE1MIGZyYWdtZW50IHRoYXQgY2FuIGVmZmljaWVudGx5IHJlbmRlclxuICogdG8gYW5kIHVwZGF0ZSBhIGNvbnRhaW5lci5cbiAqXG4gKiBJbmNsdWRlcyBzdGF0aWMgdmFsdWUgc3VwcG9ydCBmcm9tIGBsaXQtaHRtbC9zdGF0aWMuanNgLlxuICovXG5leHBvcnQgY29uc3QgbWF0aG1sID0gd2l0aFN0YXRpYyhjb3JlTWF0aG1sKTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXN0YXRpYy5qcy5tYXAiLCJleHBvcnQqZnJvbVwibGl0LWh0bWwvZGlyZWN0aXZlcy9saXZlLmpzXCI7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1saXZlLmpzLm1hcFxuIiwiZXhwb3J0KmZyb21cImxpdC1odG1sL2RpcmVjdGl2ZXMvc3R5bGUtbWFwLmpzXCI7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1zdHlsZS1tYXAuanMubWFwXG4iLCJleHBvcnQqZnJvbVwibGl0LWh0bWwvc3RhdGljLmpzXCI7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1zdGF0aWMtaHRtbC5qcy5tYXBcbiIsIlxuLyohIHBha28gMi4xLjAgaHR0cHM6Ly9naXRodWIuY29tL25vZGVjYS9wYWtvIEBsaWNlbnNlIChNSVQgQU5EIFpsaWIpICovXG4vLyAoQykgMTk5NS0yMDEzIEplYW4tbG91cCBHYWlsbHkgYW5kIE1hcmsgQWRsZXJcbi8vIChDKSAyMDE0LTIwMTcgVml0YWx5IFB1enJpbiBhbmQgQW5kcmV5IFR1cGl0c2luXG4vL1xuLy8gVGhpcyBzb2Z0d2FyZSBpcyBwcm92aWRlZCAnYXMtaXMnLCB3aXRob3V0IGFueSBleHByZXNzIG9yIGltcGxpZWRcbi8vIHdhcnJhbnR5LiBJbiBubyBldmVudCB3aWxsIHRoZSBhdXRob3JzIGJlIGhlbGQgbGlhYmxlIGZvciBhbnkgZGFtYWdlc1xuLy8gYXJpc2luZyBmcm9tIHRoZSB1c2Ugb2YgdGhpcyBzb2Z0d2FyZS5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGdyYW50ZWQgdG8gYW55b25lIHRvIHVzZSB0aGlzIHNvZnR3YXJlIGZvciBhbnkgcHVycG9zZSxcbi8vIGluY2x1ZGluZyBjb21tZXJjaWFsIGFwcGxpY2F0aW9ucywgYW5kIHRvIGFsdGVyIGl0IGFuZCByZWRpc3RyaWJ1dGUgaXRcbi8vIGZyZWVseSwgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIHJlc3RyaWN0aW9uczpcbi8vXG4vLyAxLiBUaGUgb3JpZ2luIG9mIHRoaXMgc29mdHdhcmUgbXVzdCBub3QgYmUgbWlzcmVwcmVzZW50ZWQ7IHlvdSBtdXN0IG5vdFxuLy8gICBjbGFpbSB0aGF0IHlvdSB3cm90ZSB0aGUgb3JpZ2luYWwgc29mdHdhcmUuIElmIHlvdSB1c2UgdGhpcyBzb2Z0d2FyZVxuLy8gICBpbiBhIHByb2R1Y3QsIGFuIGFja25vd2xlZGdtZW50IGluIHRoZSBwcm9kdWN0IGRvY3VtZW50YXRpb24gd291bGQgYmVcbi8vICAgYXBwcmVjaWF0ZWQgYnV0IGlzIG5vdCByZXF1aXJlZC5cbi8vIDIuIEFsdGVyZWQgc291cmNlIHZlcnNpb25zIG11c3QgYmUgcGxhaW5seSBtYXJrZWQgYXMgc3VjaCwgYW5kIG11c3Qgbm90IGJlXG4vLyAgIG1pc3JlcHJlc2VudGVkIGFzIGJlaW5nIHRoZSBvcmlnaW5hbCBzb2Z0d2FyZS5cbi8vIDMuIFRoaXMgbm90aWNlIG1heSBub3QgYmUgcmVtb3ZlZCBvciBhbHRlcmVkIGZyb20gYW55IHNvdXJjZSBkaXN0cmlidXRpb24uXG5cbi8qIGVzbGludC1kaXNhYmxlIHNwYWNlLXVuYXJ5LW9wcyAqL1xuXG4vKiBQdWJsaWMgY29uc3RhbnRzID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qL1xuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki9cblxuXG4vL2NvbnN0IFpfRklMVEVSRUQgICAgICAgICAgPSAxO1xuLy9jb25zdCBaX0hVRkZNQU5fT05MWSAgICAgID0gMjtcbi8vY29uc3QgWl9STEUgICAgICAgICAgICAgICA9IDM7XG5jb25zdCBaX0ZJWEVEJDEgICAgICAgICAgICAgICA9IDQ7XG4vL2NvbnN0IFpfREVGQVVMVF9TVFJBVEVHWSAgPSAwO1xuXG4vKiBQb3NzaWJsZSB2YWx1ZXMgb2YgdGhlIGRhdGFfdHlwZSBmaWVsZCAodGhvdWdoIHNlZSBpbmZsYXRlKCkpICovXG5jb25zdCBaX0JJTkFSWSAgICAgICAgICAgICAgPSAwO1xuY29uc3QgWl9URVhUICAgICAgICAgICAgICAgID0gMTtcbi8vY29uc3QgWl9BU0NJSSAgICAgICAgICAgICA9IDE7IC8vID0gWl9URVhUXG5jb25zdCBaX1VOS05PV04kMSAgICAgICAgICAgICA9IDI7XG5cbi8qPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovXG5cblxuZnVuY3Rpb24gemVybyQxKGJ1ZikgeyBsZXQgbGVuID0gYnVmLmxlbmd0aDsgd2hpbGUgKC0tbGVuID49IDApIHsgYnVmW2xlbl0gPSAwOyB9IH1cblxuLy8gRnJvbSB6dXRpbC5oXG5cbmNvbnN0IFNUT1JFRF9CTE9DSyA9IDA7XG5jb25zdCBTVEFUSUNfVFJFRVMgPSAxO1xuY29uc3QgRFlOX1RSRUVTICAgID0gMjtcbi8qIFRoZSB0aHJlZSBraW5kcyBvZiBibG9jayB0eXBlICovXG5cbmNvbnN0IE1JTl9NQVRDSCQxICAgID0gMztcbmNvbnN0IE1BWF9NQVRDSCQxICAgID0gMjU4O1xuLyogVGhlIG1pbmltdW0gYW5kIG1heGltdW0gbWF0Y2ggbGVuZ3RocyAqL1xuXG4vLyBGcm9tIGRlZmxhdGUuaFxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBJbnRlcm5hbCBjb21wcmVzc2lvbiBzdGF0ZS5cbiAqL1xuXG5jb25zdCBMRU5HVEhfQ09ERVMkMSAgPSAyOTtcbi8qIG51bWJlciBvZiBsZW5ndGggY29kZXMsIG5vdCBjb3VudGluZyB0aGUgc3BlY2lhbCBFTkRfQkxPQ0sgY29kZSAqL1xuXG5jb25zdCBMSVRFUkFMUyQxICAgICAgPSAyNTY7XG4vKiBudW1iZXIgb2YgbGl0ZXJhbCBieXRlcyAwLi4yNTUgKi9cblxuY29uc3QgTF9DT0RFUyQxICAgICAgID0gTElURVJBTFMkMSArIDEgKyBMRU5HVEhfQ09ERVMkMTtcbi8qIG51bWJlciBvZiBMaXRlcmFsIG9yIExlbmd0aCBjb2RlcywgaW5jbHVkaW5nIHRoZSBFTkRfQkxPQ0sgY29kZSAqL1xuXG5jb25zdCBEX0NPREVTJDEgICAgICAgPSAzMDtcbi8qIG51bWJlciBvZiBkaXN0YW5jZSBjb2RlcyAqL1xuXG5jb25zdCBCTF9DT0RFUyQxICAgICAgPSAxOTtcbi8qIG51bWJlciBvZiBjb2RlcyB1c2VkIHRvIHRyYW5zZmVyIHRoZSBiaXQgbGVuZ3RocyAqL1xuXG5jb25zdCBIRUFQX1NJWkUkMSAgICAgPSAyICogTF9DT0RFUyQxICsgMTtcbi8qIG1heGltdW0gaGVhcCBzaXplICovXG5cbmNvbnN0IE1BWF9CSVRTJDEgICAgICA9IDE1O1xuLyogQWxsIGNvZGVzIG11c3Qgbm90IGV4Y2VlZCBNQVhfQklUUyBiaXRzICovXG5cbmNvbnN0IEJ1Zl9zaXplICAgICAgPSAxNjtcbi8qIHNpemUgb2YgYml0IGJ1ZmZlciBpbiBiaV9idWYgKi9cblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvbnN0YW50c1xuICovXG5cbmNvbnN0IE1BWF9CTF9CSVRTID0gNztcbi8qIEJpdCBsZW5ndGggY29kZXMgbXVzdCBub3QgZXhjZWVkIE1BWF9CTF9CSVRTIGJpdHMgKi9cblxuY29uc3QgRU5EX0JMT0NLICAgPSAyNTY7XG4vKiBlbmQgb2YgYmxvY2sgbGl0ZXJhbCBjb2RlICovXG5cbmNvbnN0IFJFUF8zXzYgICAgID0gMTY7XG4vKiByZXBlYXQgcHJldmlvdXMgYml0IGxlbmd0aCAzLTYgdGltZXMgKDIgYml0cyBvZiByZXBlYXQgY291bnQpICovXG5cbmNvbnN0IFJFUFpfM18xMCAgID0gMTc7XG4vKiByZXBlYXQgYSB6ZXJvIGxlbmd0aCAzLTEwIHRpbWVzICAoMyBiaXRzIG9mIHJlcGVhdCBjb3VudCkgKi9cblxuY29uc3QgUkVQWl8xMV8xMzggPSAxODtcbi8qIHJlcGVhdCBhIHplcm8gbGVuZ3RoIDExLTEzOCB0aW1lcyAgKDcgYml0cyBvZiByZXBlYXQgY291bnQpICovXG5cbi8qIGVzbGludC1kaXNhYmxlIGNvbW1hLXNwYWNpbmcsYXJyYXktYnJhY2tldC1zcGFjaW5nICovXG5jb25zdCBleHRyYV9sYml0cyA9ICAgLyogZXh0cmEgYml0cyBmb3IgZWFjaCBsZW5ndGggY29kZSAqL1xuICBuZXcgVWludDhBcnJheShbMCwwLDAsMCwwLDAsMCwwLDEsMSwxLDEsMiwyLDIsMiwzLDMsMywzLDQsNCw0LDQsNSw1LDUsNSwwXSk7XG5cbmNvbnN0IGV4dHJhX2RiaXRzID0gICAvKiBleHRyYSBiaXRzIGZvciBlYWNoIGRpc3RhbmNlIGNvZGUgKi9cbiAgbmV3IFVpbnQ4QXJyYXkoWzAsMCwwLDAsMSwxLDIsMiwzLDMsNCw0LDUsNSw2LDYsNyw3LDgsOCw5LDksMTAsMTAsMTEsMTEsMTIsMTIsMTMsMTNdKTtcblxuY29uc3QgZXh0cmFfYmxiaXRzID0gIC8qIGV4dHJhIGJpdHMgZm9yIGVhY2ggYml0IGxlbmd0aCBjb2RlICovXG4gIG5ldyBVaW50OEFycmF5KFswLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDIsMyw3XSk7XG5cbmNvbnN0IGJsX29yZGVyID1cbiAgbmV3IFVpbnQ4QXJyYXkoWzE2LDE3LDE4LDAsOCw3LDksNiwxMCw1LDExLDQsMTIsMywxMywyLDE0LDEsMTVdKTtcbi8qIGVzbGludC1lbmFibGUgY29tbWEtc3BhY2luZyxhcnJheS1icmFja2V0LXNwYWNpbmcgKi9cblxuLyogVGhlIGxlbmd0aHMgb2YgdGhlIGJpdCBsZW5ndGggY29kZXMgYXJlIHNlbnQgaW4gb3JkZXIgb2YgZGVjcmVhc2luZ1xuICogcHJvYmFiaWxpdHksIHRvIGF2b2lkIHRyYW5zbWl0dGluZyB0aGUgbGVuZ3RocyBmb3IgdW51c2VkIGJpdCBsZW5ndGggY29kZXMuXG4gKi9cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBMb2NhbCBkYXRhLiBUaGVzZSBhcmUgaW5pdGlhbGl6ZWQgb25seSBvbmNlLlxuICovXG5cbi8vIFdlIHByZS1maWxsIGFycmF5cyB3aXRoIDAgdG8gYXZvaWQgdW5pbml0aWFsaXplZCBnYXBzXG5cbmNvbnN0IERJU1RfQ09ERV9MRU4gPSA1MTI7IC8qIHNlZSBkZWZpbml0aW9uIG9mIGFycmF5IGRpc3RfY29kZSBiZWxvdyAqL1xuXG4vLyAhISEhIFVzZSBmbGF0IGFycmF5IGluc3RlYWQgb2Ygc3RydWN0dXJlLCBGcmVxID0gaSoyLCBMZW4gPSBpKjIrMVxuY29uc3Qgc3RhdGljX2x0cmVlICA9IG5ldyBBcnJheSgoTF9DT0RFUyQxICsgMikgKiAyKTtcbnplcm8kMShzdGF0aWNfbHRyZWUpO1xuLyogVGhlIHN0YXRpYyBsaXRlcmFsIHRyZWUuIFNpbmNlIHRoZSBiaXQgbGVuZ3RocyBhcmUgaW1wb3NlZCwgdGhlcmUgaXMgbm9cbiAqIG5lZWQgZm9yIHRoZSBMX0NPREVTIGV4dHJhIGNvZGVzIHVzZWQgZHVyaW5nIGhlYXAgY29uc3RydWN0aW9uLiBIb3dldmVyXG4gKiBUaGUgY29kZXMgMjg2IGFuZCAyODcgYXJlIG5lZWRlZCB0byBidWlsZCBhIGNhbm9uaWNhbCB0cmVlIChzZWUgX3RyX2luaXRcbiAqIGJlbG93KS5cbiAqL1xuXG5jb25zdCBzdGF0aWNfZHRyZWUgID0gbmV3IEFycmF5KERfQ09ERVMkMSAqIDIpO1xuemVybyQxKHN0YXRpY19kdHJlZSk7XG4vKiBUaGUgc3RhdGljIGRpc3RhbmNlIHRyZWUuIChBY3R1YWxseSBhIHRyaXZpYWwgdHJlZSBzaW5jZSBhbGwgY29kZXMgdXNlXG4gKiA1IGJpdHMuKVxuICovXG5cbmNvbnN0IF9kaXN0X2NvZGUgICAgPSBuZXcgQXJyYXkoRElTVF9DT0RFX0xFTik7XG56ZXJvJDEoX2Rpc3RfY29kZSk7XG4vKiBEaXN0YW5jZSBjb2Rlcy4gVGhlIGZpcnN0IDI1NiB2YWx1ZXMgY29ycmVzcG9uZCB0byB0aGUgZGlzdGFuY2VzXG4gKiAzIC4uIDI1OCwgdGhlIGxhc3QgMjU2IHZhbHVlcyBjb3JyZXNwb25kIHRvIHRoZSB0b3AgOCBiaXRzIG9mXG4gKiB0aGUgMTUgYml0IGRpc3RhbmNlcy5cbiAqL1xuXG5jb25zdCBfbGVuZ3RoX2NvZGUgID0gbmV3IEFycmF5KE1BWF9NQVRDSCQxIC0gTUlOX01BVENIJDEgKyAxKTtcbnplcm8kMShfbGVuZ3RoX2NvZGUpO1xuLyogbGVuZ3RoIGNvZGUgZm9yIGVhY2ggbm9ybWFsaXplZCBtYXRjaCBsZW5ndGggKDAgPT0gTUlOX01BVENIKSAqL1xuXG5jb25zdCBiYXNlX2xlbmd0aCAgID0gbmV3IEFycmF5KExFTkdUSF9DT0RFUyQxKTtcbnplcm8kMShiYXNlX2xlbmd0aCk7XG4vKiBGaXJzdCBub3JtYWxpemVkIGxlbmd0aCBmb3IgZWFjaCBjb2RlICgwID0gTUlOX01BVENIKSAqL1xuXG5jb25zdCBiYXNlX2Rpc3QgICAgID0gbmV3IEFycmF5KERfQ09ERVMkMSk7XG56ZXJvJDEoYmFzZV9kaXN0KTtcbi8qIEZpcnN0IG5vcm1hbGl6ZWQgZGlzdGFuY2UgZm9yIGVhY2ggY29kZSAoMCA9IGRpc3RhbmNlIG9mIDEpICovXG5cblxuZnVuY3Rpb24gU3RhdGljVHJlZURlc2Moc3RhdGljX3RyZWUsIGV4dHJhX2JpdHMsIGV4dHJhX2Jhc2UsIGVsZW1zLCBtYXhfbGVuZ3RoKSB7XG5cbiAgdGhpcy5zdGF0aWNfdHJlZSAgPSBzdGF0aWNfdHJlZTsgIC8qIHN0YXRpYyB0cmVlIG9yIE5VTEwgKi9cbiAgdGhpcy5leHRyYV9iaXRzICAgPSBleHRyYV9iaXRzOyAgIC8qIGV4dHJhIGJpdHMgZm9yIGVhY2ggY29kZSBvciBOVUxMICovXG4gIHRoaXMuZXh0cmFfYmFzZSAgID0gZXh0cmFfYmFzZTsgICAvKiBiYXNlIGluZGV4IGZvciBleHRyYV9iaXRzICovXG4gIHRoaXMuZWxlbXMgICAgICAgID0gZWxlbXM7ICAgICAgICAvKiBtYXggbnVtYmVyIG9mIGVsZW1lbnRzIGluIHRoZSB0cmVlICovXG4gIHRoaXMubWF4X2xlbmd0aCAgID0gbWF4X2xlbmd0aDsgICAvKiBtYXggYml0IGxlbmd0aCBmb3IgdGhlIGNvZGVzICovXG5cbiAgLy8gc2hvdyBpZiBgc3RhdGljX3RyZWVgIGhhcyBkYXRhIG9yIGR1bW15IC0gbmVlZGVkIGZvciBtb25vbW9ycGhpYyBvYmplY3RzXG4gIHRoaXMuaGFzX3N0cmVlICAgID0gc3RhdGljX3RyZWUgJiYgc3RhdGljX3RyZWUubGVuZ3RoO1xufVxuXG5cbmxldCBzdGF0aWNfbF9kZXNjO1xubGV0IHN0YXRpY19kX2Rlc2M7XG5sZXQgc3RhdGljX2JsX2Rlc2M7XG5cblxuZnVuY3Rpb24gVHJlZURlc2MoZHluX3RyZWUsIHN0YXRfZGVzYykge1xuICB0aGlzLmR5bl90cmVlID0gZHluX3RyZWU7ICAgICAvKiB0aGUgZHluYW1pYyB0cmVlICovXG4gIHRoaXMubWF4X2NvZGUgPSAwOyAgICAgICAgICAgIC8qIGxhcmdlc3QgY29kZSB3aXRoIG5vbiB6ZXJvIGZyZXF1ZW5jeSAqL1xuICB0aGlzLnN0YXRfZGVzYyA9IHN0YXRfZGVzYzsgICAvKiB0aGUgY29ycmVzcG9uZGluZyBzdGF0aWMgdHJlZSAqL1xufVxuXG5cblxuY29uc3QgZF9jb2RlID0gKGRpc3QpID0+IHtcblxuICByZXR1cm4gZGlzdCA8IDI1NiA/IF9kaXN0X2NvZGVbZGlzdF0gOiBfZGlzdF9jb2RlWzI1NiArIChkaXN0ID4+PiA3KV07XG59O1xuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogT3V0cHV0IGEgc2hvcnQgTFNCIGZpcnN0IG9uIHRoZSBzdHJlYW0uXG4gKiBJTiBhc3NlcnRpb246IHRoZXJlIGlzIGVub3VnaCByb29tIGluIHBlbmRpbmdCdWYuXG4gKi9cbmNvbnN0IHB1dF9zaG9ydCA9IChzLCB3KSA9PiB7XG4vLyAgICBwdXRfYnl0ZShzLCAodWNoKSgodykgJiAweGZmKSk7XG4vLyAgICBwdXRfYnl0ZShzLCAodWNoKSgodXNoKSh3KSA+PiA4KSk7XG4gIHMucGVuZGluZ19idWZbcy5wZW5kaW5nKytdID0gKHcpICYgMHhmZjtcbiAgcy5wZW5kaW5nX2J1ZltzLnBlbmRpbmcrK10gPSAodyA+Pj4gOCkgJiAweGZmO1xufTtcblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFNlbmQgYSB2YWx1ZSBvbiBhIGdpdmVuIG51bWJlciBvZiBiaXRzLlxuICogSU4gYXNzZXJ0aW9uOiBsZW5ndGggPD0gMTYgYW5kIHZhbHVlIGZpdHMgaW4gbGVuZ3RoIGJpdHMuXG4gKi9cbmNvbnN0IHNlbmRfYml0cyA9IChzLCB2YWx1ZSwgbGVuZ3RoKSA9PiB7XG5cbiAgaWYgKHMuYmlfdmFsaWQgPiAoQnVmX3NpemUgLSBsZW5ndGgpKSB7XG4gICAgcy5iaV9idWYgfD0gKHZhbHVlIDw8IHMuYmlfdmFsaWQpICYgMHhmZmZmO1xuICAgIHB1dF9zaG9ydChzLCBzLmJpX2J1Zik7XG4gICAgcy5iaV9idWYgPSB2YWx1ZSA+PiAoQnVmX3NpemUgLSBzLmJpX3ZhbGlkKTtcbiAgICBzLmJpX3ZhbGlkICs9IGxlbmd0aCAtIEJ1Zl9zaXplO1xuICB9IGVsc2Uge1xuICAgIHMuYmlfYnVmIHw9ICh2YWx1ZSA8PCBzLmJpX3ZhbGlkKSAmIDB4ZmZmZjtcbiAgICBzLmJpX3ZhbGlkICs9IGxlbmd0aDtcbiAgfVxufTtcblxuXG5jb25zdCBzZW5kX2NvZGUgPSAocywgYywgdHJlZSkgPT4ge1xuXG4gIHNlbmRfYml0cyhzLCB0cmVlW2MgKiAyXS8qLkNvZGUqLywgdHJlZVtjICogMiArIDFdLyouTGVuKi8pO1xufTtcblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFJldmVyc2UgdGhlIGZpcnN0IGxlbiBiaXRzIG9mIGEgY29kZSwgdXNpbmcgc3RyYWlnaHRmb3J3YXJkIGNvZGUgKGEgZmFzdGVyXG4gKiBtZXRob2Qgd291bGQgdXNlIGEgdGFibGUpXG4gKiBJTiBhc3NlcnRpb246IDEgPD0gbGVuIDw9IDE1XG4gKi9cbmNvbnN0IGJpX3JldmVyc2UgPSAoY29kZSwgbGVuKSA9PiB7XG5cbiAgbGV0IHJlcyA9IDA7XG4gIGRvIHtcbiAgICByZXMgfD0gY29kZSAmIDE7XG4gICAgY29kZSA+Pj49IDE7XG4gICAgcmVzIDw8PSAxO1xuICB9IHdoaWxlICgtLWxlbiA+IDApO1xuICByZXR1cm4gcmVzID4+PiAxO1xufTtcblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEZsdXNoIHRoZSBiaXQgYnVmZmVyLCBrZWVwaW5nIGF0IG1vc3QgNyBiaXRzIGluIGl0LlxuICovXG5jb25zdCBiaV9mbHVzaCA9IChzKSA9PiB7XG5cbiAgaWYgKHMuYmlfdmFsaWQgPT09IDE2KSB7XG4gICAgcHV0X3Nob3J0KHMsIHMuYmlfYnVmKTtcbiAgICBzLmJpX2J1ZiA9IDA7XG4gICAgcy5iaV92YWxpZCA9IDA7XG5cbiAgfSBlbHNlIGlmIChzLmJpX3ZhbGlkID49IDgpIHtcbiAgICBzLnBlbmRpbmdfYnVmW3MucGVuZGluZysrXSA9IHMuYmlfYnVmICYgMHhmZjtcbiAgICBzLmJpX2J1ZiA+Pj0gODtcbiAgICBzLmJpX3ZhbGlkIC09IDg7XG4gIH1cbn07XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb21wdXRlIHRoZSBvcHRpbWFsIGJpdCBsZW5ndGhzIGZvciBhIHRyZWUgYW5kIHVwZGF0ZSB0aGUgdG90YWwgYml0IGxlbmd0aFxuICogZm9yIHRoZSBjdXJyZW50IGJsb2NrLlxuICogSU4gYXNzZXJ0aW9uOiB0aGUgZmllbGRzIGZyZXEgYW5kIGRhZCBhcmUgc2V0LCBoZWFwW2hlYXBfbWF4XSBhbmRcbiAqICAgIGFib3ZlIGFyZSB0aGUgdHJlZSBub2RlcyBzb3J0ZWQgYnkgaW5jcmVhc2luZyBmcmVxdWVuY3kuXG4gKiBPVVQgYXNzZXJ0aW9uczogdGhlIGZpZWxkIGxlbiBpcyBzZXQgdG8gdGhlIG9wdGltYWwgYml0IGxlbmd0aCwgdGhlXG4gKiAgICAgYXJyYXkgYmxfY291bnQgY29udGFpbnMgdGhlIGZyZXF1ZW5jaWVzIGZvciBlYWNoIGJpdCBsZW5ndGguXG4gKiAgICAgVGhlIGxlbmd0aCBvcHRfbGVuIGlzIHVwZGF0ZWQ7IHN0YXRpY19sZW4gaXMgYWxzbyB1cGRhdGVkIGlmIHN0cmVlIGlzXG4gKiAgICAgbm90IG51bGwuXG4gKi9cbmNvbnN0IGdlbl9iaXRsZW4gPSAocywgZGVzYykgPT4ge1xuLy8gICAgZGVmbGF0ZV9zdGF0ZSAqcztcbi8vICAgIHRyZWVfZGVzYyAqZGVzYzsgICAgLyogdGhlIHRyZWUgZGVzY3JpcHRvciAqL1xuXG4gIGNvbnN0IHRyZWUgICAgICAgICAgICA9IGRlc2MuZHluX3RyZWU7XG4gIGNvbnN0IG1heF9jb2RlICAgICAgICA9IGRlc2MubWF4X2NvZGU7XG4gIGNvbnN0IHN0cmVlICAgICAgICAgICA9IGRlc2Muc3RhdF9kZXNjLnN0YXRpY190cmVlO1xuICBjb25zdCBoYXNfc3RyZWUgICAgICAgPSBkZXNjLnN0YXRfZGVzYy5oYXNfc3RyZWU7XG4gIGNvbnN0IGV4dHJhICAgICAgICAgICA9IGRlc2Muc3RhdF9kZXNjLmV4dHJhX2JpdHM7XG4gIGNvbnN0IGJhc2UgICAgICAgICAgICA9IGRlc2Muc3RhdF9kZXNjLmV4dHJhX2Jhc2U7XG4gIGNvbnN0IG1heF9sZW5ndGggICAgICA9IGRlc2Muc3RhdF9kZXNjLm1heF9sZW5ndGg7XG4gIGxldCBoOyAgICAgICAgICAgICAgLyogaGVhcCBpbmRleCAqL1xuICBsZXQgbiwgbTsgICAgICAgICAgIC8qIGl0ZXJhdGUgb3ZlciB0aGUgdHJlZSBlbGVtZW50cyAqL1xuICBsZXQgYml0czsgICAgICAgICAgIC8qIGJpdCBsZW5ndGggKi9cbiAgbGV0IHhiaXRzOyAgICAgICAgICAvKiBleHRyYSBiaXRzICovXG4gIGxldCBmOyAgICAgICAgICAgICAgLyogZnJlcXVlbmN5ICovXG4gIGxldCBvdmVyZmxvdyA9IDA7ICAgLyogbnVtYmVyIG9mIGVsZW1lbnRzIHdpdGggYml0IGxlbmd0aCB0b28gbGFyZ2UgKi9cblxuICBmb3IgKGJpdHMgPSAwOyBiaXRzIDw9IE1BWF9CSVRTJDE7IGJpdHMrKykge1xuICAgIHMuYmxfY291bnRbYml0c10gPSAwO1xuICB9XG5cbiAgLyogSW4gYSBmaXJzdCBwYXNzLCBjb21wdXRlIHRoZSBvcHRpbWFsIGJpdCBsZW5ndGhzICh3aGljaCBtYXlcbiAgICogb3ZlcmZsb3cgaW4gdGhlIGNhc2Ugb2YgdGhlIGJpdCBsZW5ndGggdHJlZSkuXG4gICAqL1xuICB0cmVlW3MuaGVhcFtzLmhlYXBfbWF4XSAqIDIgKyAxXS8qLkxlbiovID0gMDsgLyogcm9vdCBvZiB0aGUgaGVhcCAqL1xuXG4gIGZvciAoaCA9IHMuaGVhcF9tYXggKyAxOyBoIDwgSEVBUF9TSVpFJDE7IGgrKykge1xuICAgIG4gPSBzLmhlYXBbaF07XG4gICAgYml0cyA9IHRyZWVbdHJlZVtuICogMiArIDFdLyouRGFkKi8gKiAyICsgMV0vKi5MZW4qLyArIDE7XG4gICAgaWYgKGJpdHMgPiBtYXhfbGVuZ3RoKSB7XG4gICAgICBiaXRzID0gbWF4X2xlbmd0aDtcbiAgICAgIG92ZXJmbG93Kys7XG4gICAgfVxuICAgIHRyZWVbbiAqIDIgKyAxXS8qLkxlbiovID0gYml0cztcbiAgICAvKiBXZSBvdmVyd3JpdGUgdHJlZVtuXS5EYWQgd2hpY2ggaXMgbm8gbG9uZ2VyIG5lZWRlZCAqL1xuXG4gICAgaWYgKG4gPiBtYXhfY29kZSkgeyBjb250aW51ZTsgfSAvKiBub3QgYSBsZWFmIG5vZGUgKi9cblxuICAgIHMuYmxfY291bnRbYml0c10rKztcbiAgICB4Yml0cyA9IDA7XG4gICAgaWYgKG4gPj0gYmFzZSkge1xuICAgICAgeGJpdHMgPSBleHRyYVtuIC0gYmFzZV07XG4gICAgfVxuICAgIGYgPSB0cmVlW24gKiAyXS8qLkZyZXEqLztcbiAgICBzLm9wdF9sZW4gKz0gZiAqIChiaXRzICsgeGJpdHMpO1xuICAgIGlmIChoYXNfc3RyZWUpIHtcbiAgICAgIHMuc3RhdGljX2xlbiArPSBmICogKHN0cmVlW24gKiAyICsgMV0vKi5MZW4qLyArIHhiaXRzKTtcbiAgICB9XG4gIH1cbiAgaWYgKG92ZXJmbG93ID09PSAwKSB7IHJldHVybjsgfVxuXG4gIC8vIFRyYWNldigoc3RkZXJyLFwiXFxuYml0IGxlbmd0aCBvdmVyZmxvd1xcblwiKSk7XG4gIC8qIFRoaXMgaGFwcGVucyBmb3IgZXhhbXBsZSBvbiBvYmoyIGFuZCBwaWMgb2YgdGhlIENhbGdhcnkgY29ycHVzICovXG5cbiAgLyogRmluZCB0aGUgZmlyc3QgYml0IGxlbmd0aCB3aGljaCBjb3VsZCBpbmNyZWFzZTogKi9cbiAgZG8ge1xuICAgIGJpdHMgPSBtYXhfbGVuZ3RoIC0gMTtcbiAgICB3aGlsZSAocy5ibF9jb3VudFtiaXRzXSA9PT0gMCkgeyBiaXRzLS07IH1cbiAgICBzLmJsX2NvdW50W2JpdHNdLS07ICAgICAgLyogbW92ZSBvbmUgbGVhZiBkb3duIHRoZSB0cmVlICovXG4gICAgcy5ibF9jb3VudFtiaXRzICsgMV0gKz0gMjsgLyogbW92ZSBvbmUgb3ZlcmZsb3cgaXRlbSBhcyBpdHMgYnJvdGhlciAqL1xuICAgIHMuYmxfY291bnRbbWF4X2xlbmd0aF0tLTtcbiAgICAvKiBUaGUgYnJvdGhlciBvZiB0aGUgb3ZlcmZsb3cgaXRlbSBhbHNvIG1vdmVzIG9uZSBzdGVwIHVwLFxuICAgICAqIGJ1dCB0aGlzIGRvZXMgbm90IGFmZmVjdCBibF9jb3VudFttYXhfbGVuZ3RoXVxuICAgICAqL1xuICAgIG92ZXJmbG93IC09IDI7XG4gIH0gd2hpbGUgKG92ZXJmbG93ID4gMCk7XG5cbiAgLyogTm93IHJlY29tcHV0ZSBhbGwgYml0IGxlbmd0aHMsIHNjYW5uaW5nIGluIGluY3JlYXNpbmcgZnJlcXVlbmN5LlxuICAgKiBoIGlzIHN0aWxsIGVxdWFsIHRvIEhFQVBfU0laRS4gKEl0IGlzIHNpbXBsZXIgdG8gcmVjb25zdHJ1Y3QgYWxsXG4gICAqIGxlbmd0aHMgaW5zdGVhZCBvZiBmaXhpbmcgb25seSB0aGUgd3Jvbmcgb25lcy4gVGhpcyBpZGVhIGlzIHRha2VuXG4gICAqIGZyb20gJ2FyJyB3cml0dGVuIGJ5IEhhcnVoaWtvIE9rdW11cmEuKVxuICAgKi9cbiAgZm9yIChiaXRzID0gbWF4X2xlbmd0aDsgYml0cyAhPT0gMDsgYml0cy0tKSB7XG4gICAgbiA9IHMuYmxfY291bnRbYml0c107XG4gICAgd2hpbGUgKG4gIT09IDApIHtcbiAgICAgIG0gPSBzLmhlYXBbLS1oXTtcbiAgICAgIGlmIChtID4gbWF4X2NvZGUpIHsgY29udGludWU7IH1cbiAgICAgIGlmICh0cmVlW20gKiAyICsgMV0vKi5MZW4qLyAhPT0gYml0cykge1xuICAgICAgICAvLyBUcmFjZXYoKHN0ZGVycixcImNvZGUgJWQgYml0cyAlZC0+JWRcXG5cIiwgbSwgdHJlZVttXS5MZW4sIGJpdHMpKTtcbiAgICAgICAgcy5vcHRfbGVuICs9IChiaXRzIC0gdHJlZVttICogMiArIDFdLyouTGVuKi8pICogdHJlZVttICogMl0vKi5GcmVxKi87XG4gICAgICAgIHRyZWVbbSAqIDIgKyAxXS8qLkxlbiovID0gYml0cztcbiAgICAgIH1cbiAgICAgIG4tLTtcbiAgICB9XG4gIH1cbn07XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBHZW5lcmF0ZSB0aGUgY29kZXMgZm9yIGEgZ2l2ZW4gdHJlZSBhbmQgYml0IGNvdW50cyAod2hpY2ggbmVlZCBub3QgYmVcbiAqIG9wdGltYWwpLlxuICogSU4gYXNzZXJ0aW9uOiB0aGUgYXJyYXkgYmxfY291bnQgY29udGFpbnMgdGhlIGJpdCBsZW5ndGggc3RhdGlzdGljcyBmb3JcbiAqIHRoZSBnaXZlbiB0cmVlIGFuZCB0aGUgZmllbGQgbGVuIGlzIHNldCBmb3IgYWxsIHRyZWUgZWxlbWVudHMuXG4gKiBPVVQgYXNzZXJ0aW9uOiB0aGUgZmllbGQgY29kZSBpcyBzZXQgZm9yIGFsbCB0cmVlIGVsZW1lbnRzIG9mIG5vblxuICogICAgIHplcm8gY29kZSBsZW5ndGguXG4gKi9cbmNvbnN0IGdlbl9jb2RlcyA9ICh0cmVlLCBtYXhfY29kZSwgYmxfY291bnQpID0+IHtcbi8vICAgIGN0X2RhdGEgKnRyZWU7ICAgICAgICAgICAgIC8qIHRoZSB0cmVlIHRvIGRlY29yYXRlICovXG4vLyAgICBpbnQgbWF4X2NvZGU7ICAgICAgICAgICAgICAvKiBsYXJnZXN0IGNvZGUgd2l0aCBub24gemVybyBmcmVxdWVuY3kgKi9cbi8vICAgIHVzaGYgKmJsX2NvdW50OyAgICAgICAgICAgIC8qIG51bWJlciBvZiBjb2RlcyBhdCBlYWNoIGJpdCBsZW5ndGggKi9cblxuICBjb25zdCBuZXh0X2NvZGUgPSBuZXcgQXJyYXkoTUFYX0JJVFMkMSArIDEpOyAvKiBuZXh0IGNvZGUgdmFsdWUgZm9yIGVhY2ggYml0IGxlbmd0aCAqL1xuICBsZXQgY29kZSA9IDA7ICAgICAgICAgICAgICAvKiBydW5uaW5nIGNvZGUgdmFsdWUgKi9cbiAgbGV0IGJpdHM7ICAgICAgICAgICAgICAgICAgLyogYml0IGluZGV4ICovXG4gIGxldCBuOyAgICAgICAgICAgICAgICAgICAgIC8qIGNvZGUgaW5kZXggKi9cblxuICAvKiBUaGUgZGlzdHJpYnV0aW9uIGNvdW50cyBhcmUgZmlyc3QgdXNlZCB0byBnZW5lcmF0ZSB0aGUgY29kZSB2YWx1ZXNcbiAgICogd2l0aG91dCBiaXQgcmV2ZXJzYWwuXG4gICAqL1xuICBmb3IgKGJpdHMgPSAxOyBiaXRzIDw9IE1BWF9CSVRTJDE7IGJpdHMrKykge1xuICAgIGNvZGUgPSAoY29kZSArIGJsX2NvdW50W2JpdHMgLSAxXSkgPDwgMTtcbiAgICBuZXh0X2NvZGVbYml0c10gPSBjb2RlO1xuICB9XG4gIC8qIENoZWNrIHRoYXQgdGhlIGJpdCBjb3VudHMgaW4gYmxfY291bnQgYXJlIGNvbnNpc3RlbnQuIFRoZSBsYXN0IGNvZGVcbiAgICogbXVzdCBiZSBhbGwgb25lcy5cbiAgICovXG4gIC8vQXNzZXJ0IChjb2RlICsgYmxfY291bnRbTUFYX0JJVFNdLTEgPT0gKDE8PE1BWF9CSVRTKS0xLFxuICAvLyAgICAgICAgXCJpbmNvbnNpc3RlbnQgYml0IGNvdW50c1wiKTtcbiAgLy9UcmFjZXYoKHN0ZGVycixcIlxcbmdlbl9jb2RlczogbWF4X2NvZGUgJWQgXCIsIG1heF9jb2RlKSk7XG5cbiAgZm9yIChuID0gMDsgIG4gPD0gbWF4X2NvZGU7IG4rKykge1xuICAgIGxldCBsZW4gPSB0cmVlW24gKiAyICsgMV0vKi5MZW4qLztcbiAgICBpZiAobGVuID09PSAwKSB7IGNvbnRpbnVlOyB9XG4gICAgLyogTm93IHJldmVyc2UgdGhlIGJpdHMgKi9cbiAgICB0cmVlW24gKiAyXS8qLkNvZGUqLyA9IGJpX3JldmVyc2UobmV4dF9jb2RlW2xlbl0rKywgbGVuKTtcblxuICAgIC8vVHJhY2Vjdih0cmVlICE9IHN0YXRpY19sdHJlZSwgKHN0ZGVycixcIlxcbm4gJTNkICVjIGwgJTJkIGMgJTR4ICgleCkgXCIsXG4gICAgLy8gICAgIG4sIChpc2dyYXBoKG4pID8gbiA6ICcgJyksIGxlbiwgdHJlZVtuXS5Db2RlLCBuZXh0X2NvZGVbbGVuXS0xKSk7XG4gIH1cbn07XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBJbml0aWFsaXplIHRoZSB2YXJpb3VzICdjb25zdGFudCcgdGFibGVzLlxuICovXG5jb25zdCB0cl9zdGF0aWNfaW5pdCA9ICgpID0+IHtcblxuICBsZXQgbjsgICAgICAgIC8qIGl0ZXJhdGVzIG92ZXIgdHJlZSBlbGVtZW50cyAqL1xuICBsZXQgYml0czsgICAgIC8qIGJpdCBjb3VudGVyICovXG4gIGxldCBsZW5ndGg7ICAgLyogbGVuZ3RoIHZhbHVlICovXG4gIGxldCBjb2RlOyAgICAgLyogY29kZSB2YWx1ZSAqL1xuICBsZXQgZGlzdDsgICAgIC8qIGRpc3RhbmNlIGluZGV4ICovXG4gIGNvbnN0IGJsX2NvdW50ID0gbmV3IEFycmF5KE1BWF9CSVRTJDEgKyAxKTtcbiAgLyogbnVtYmVyIG9mIGNvZGVzIGF0IGVhY2ggYml0IGxlbmd0aCBmb3IgYW4gb3B0aW1hbCB0cmVlICovXG5cbiAgLy8gZG8gY2hlY2sgaW4gX3RyX2luaXQoKVxuICAvL2lmIChzdGF0aWNfaW5pdF9kb25lKSByZXR1cm47XG5cbiAgLyogRm9yIHNvbWUgZW1iZWRkZWQgdGFyZ2V0cywgZ2xvYmFsIHZhcmlhYmxlcyBhcmUgbm90IGluaXRpYWxpemVkOiAqL1xuLyojaWZkZWYgTk9fSU5JVF9HTE9CQUxfUE9JTlRFUlNcbiAgc3RhdGljX2xfZGVzYy5zdGF0aWNfdHJlZSA9IHN0YXRpY19sdHJlZTtcbiAgc3RhdGljX2xfZGVzYy5leHRyYV9iaXRzID0gZXh0cmFfbGJpdHM7XG4gIHN0YXRpY19kX2Rlc2Muc3RhdGljX3RyZWUgPSBzdGF0aWNfZHRyZWU7XG4gIHN0YXRpY19kX2Rlc2MuZXh0cmFfYml0cyA9IGV4dHJhX2RiaXRzO1xuICBzdGF0aWNfYmxfZGVzYy5leHRyYV9iaXRzID0gZXh0cmFfYmxiaXRzO1xuI2VuZGlmKi9cblxuICAvKiBJbml0aWFsaXplIHRoZSBtYXBwaW5nIGxlbmd0aCAoMC4uMjU1KSAtPiBsZW5ndGggY29kZSAoMC4uMjgpICovXG4gIGxlbmd0aCA9IDA7XG4gIGZvciAoY29kZSA9IDA7IGNvZGUgPCBMRU5HVEhfQ09ERVMkMSAtIDE7IGNvZGUrKykge1xuICAgIGJhc2VfbGVuZ3RoW2NvZGVdID0gbGVuZ3RoO1xuICAgIGZvciAobiA9IDA7IG4gPCAoMSA8PCBleHRyYV9sYml0c1tjb2RlXSk7IG4rKykge1xuICAgICAgX2xlbmd0aF9jb2RlW2xlbmd0aCsrXSA9IGNvZGU7XG4gICAgfVxuICB9XG4gIC8vQXNzZXJ0IChsZW5ndGggPT0gMjU2LCBcInRyX3N0YXRpY19pbml0OiBsZW5ndGggIT0gMjU2XCIpO1xuICAvKiBOb3RlIHRoYXQgdGhlIGxlbmd0aCAyNTUgKG1hdGNoIGxlbmd0aCAyNTgpIGNhbiBiZSByZXByZXNlbnRlZFxuICAgKiBpbiB0d28gZGlmZmVyZW50IHdheXM6IGNvZGUgMjg0ICsgNSBiaXRzIG9yIGNvZGUgMjg1LCBzbyB3ZVxuICAgKiBvdmVyd3JpdGUgbGVuZ3RoX2NvZGVbMjU1XSB0byB1c2UgdGhlIGJlc3QgZW5jb2Rpbmc6XG4gICAqL1xuICBfbGVuZ3RoX2NvZGVbbGVuZ3RoIC0gMV0gPSBjb2RlO1xuXG4gIC8qIEluaXRpYWxpemUgdGhlIG1hcHBpbmcgZGlzdCAoMC4uMzJLKSAtPiBkaXN0IGNvZGUgKDAuLjI5KSAqL1xuICBkaXN0ID0gMDtcbiAgZm9yIChjb2RlID0gMDsgY29kZSA8IDE2OyBjb2RlKyspIHtcbiAgICBiYXNlX2Rpc3RbY29kZV0gPSBkaXN0O1xuICAgIGZvciAobiA9IDA7IG4gPCAoMSA8PCBleHRyYV9kYml0c1tjb2RlXSk7IG4rKykge1xuICAgICAgX2Rpc3RfY29kZVtkaXN0KytdID0gY29kZTtcbiAgICB9XG4gIH1cbiAgLy9Bc3NlcnQgKGRpc3QgPT0gMjU2LCBcInRyX3N0YXRpY19pbml0OiBkaXN0ICE9IDI1NlwiKTtcbiAgZGlzdCA+Pj0gNzsgLyogZnJvbSBub3cgb24sIGFsbCBkaXN0YW5jZXMgYXJlIGRpdmlkZWQgYnkgMTI4ICovXG4gIGZvciAoOyBjb2RlIDwgRF9DT0RFUyQxOyBjb2RlKyspIHtcbiAgICBiYXNlX2Rpc3RbY29kZV0gPSBkaXN0IDw8IDc7XG4gICAgZm9yIChuID0gMDsgbiA8ICgxIDw8IChleHRyYV9kYml0c1tjb2RlXSAtIDcpKTsgbisrKSB7XG4gICAgICBfZGlzdF9jb2RlWzI1NiArIGRpc3QrK10gPSBjb2RlO1xuICAgIH1cbiAgfVxuICAvL0Fzc2VydCAoZGlzdCA9PSAyNTYsIFwidHJfc3RhdGljX2luaXQ6IDI1NitkaXN0ICE9IDUxMlwiKTtcblxuICAvKiBDb25zdHJ1Y3QgdGhlIGNvZGVzIG9mIHRoZSBzdGF0aWMgbGl0ZXJhbCB0cmVlICovXG4gIGZvciAoYml0cyA9IDA7IGJpdHMgPD0gTUFYX0JJVFMkMTsgYml0cysrKSB7XG4gICAgYmxfY291bnRbYml0c10gPSAwO1xuICB9XG5cbiAgbiA9IDA7XG4gIHdoaWxlIChuIDw9IDE0Mykge1xuICAgIHN0YXRpY19sdHJlZVtuICogMiArIDFdLyouTGVuKi8gPSA4O1xuICAgIG4rKztcbiAgICBibF9jb3VudFs4XSsrO1xuICB9XG4gIHdoaWxlIChuIDw9IDI1NSkge1xuICAgIHN0YXRpY19sdHJlZVtuICogMiArIDFdLyouTGVuKi8gPSA5O1xuICAgIG4rKztcbiAgICBibF9jb3VudFs5XSsrO1xuICB9XG4gIHdoaWxlIChuIDw9IDI3OSkge1xuICAgIHN0YXRpY19sdHJlZVtuICogMiArIDFdLyouTGVuKi8gPSA3O1xuICAgIG4rKztcbiAgICBibF9jb3VudFs3XSsrO1xuICB9XG4gIHdoaWxlIChuIDw9IDI4Nykge1xuICAgIHN0YXRpY19sdHJlZVtuICogMiArIDFdLyouTGVuKi8gPSA4O1xuICAgIG4rKztcbiAgICBibF9jb3VudFs4XSsrO1xuICB9XG4gIC8qIENvZGVzIDI4NiBhbmQgMjg3IGRvIG5vdCBleGlzdCwgYnV0IHdlIG11c3QgaW5jbHVkZSB0aGVtIGluIHRoZVxuICAgKiB0cmVlIGNvbnN0cnVjdGlvbiB0byBnZXQgYSBjYW5vbmljYWwgSHVmZm1hbiB0cmVlIChsb25nZXN0IGNvZGVcbiAgICogYWxsIG9uZXMpXG4gICAqL1xuICBnZW5fY29kZXMoc3RhdGljX2x0cmVlLCBMX0NPREVTJDEgKyAxLCBibF9jb3VudCk7XG5cbiAgLyogVGhlIHN0YXRpYyBkaXN0YW5jZSB0cmVlIGlzIHRyaXZpYWw6ICovXG4gIGZvciAobiA9IDA7IG4gPCBEX0NPREVTJDE7IG4rKykge1xuICAgIHN0YXRpY19kdHJlZVtuICogMiArIDFdLyouTGVuKi8gPSA1O1xuICAgIHN0YXRpY19kdHJlZVtuICogMl0vKi5Db2RlKi8gPSBiaV9yZXZlcnNlKG4sIDUpO1xuICB9XG5cbiAgLy8gTm93IGRhdGEgcmVhZHkgYW5kIHdlIGNhbiBpbml0IHN0YXRpYyB0cmVlc1xuICBzdGF0aWNfbF9kZXNjID0gbmV3IFN0YXRpY1RyZWVEZXNjKHN0YXRpY19sdHJlZSwgZXh0cmFfbGJpdHMsIExJVEVSQUxTJDEgKyAxLCBMX0NPREVTJDEsIE1BWF9CSVRTJDEpO1xuICBzdGF0aWNfZF9kZXNjID0gbmV3IFN0YXRpY1RyZWVEZXNjKHN0YXRpY19kdHJlZSwgZXh0cmFfZGJpdHMsIDAsICAgICAgICAgIERfQ09ERVMkMSwgTUFYX0JJVFMkMSk7XG4gIHN0YXRpY19ibF9kZXNjID0gbmV3IFN0YXRpY1RyZWVEZXNjKG5ldyBBcnJheSgwKSwgZXh0cmFfYmxiaXRzLCAwLCAgICAgICAgIEJMX0NPREVTJDEsIE1BWF9CTF9CSVRTKTtcblxuICAvL3N0YXRpY19pbml0X2RvbmUgPSB0cnVlO1xufTtcblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEluaXRpYWxpemUgYSBuZXcgYmxvY2suXG4gKi9cbmNvbnN0IGluaXRfYmxvY2sgPSAocykgPT4ge1xuXG4gIGxldCBuOyAvKiBpdGVyYXRlcyBvdmVyIHRyZWUgZWxlbWVudHMgKi9cblxuICAvKiBJbml0aWFsaXplIHRoZSB0cmVlcy4gKi9cbiAgZm9yIChuID0gMDsgbiA8IExfQ09ERVMkMTsgIG4rKykgeyBzLmR5bl9sdHJlZVtuICogMl0vKi5GcmVxKi8gPSAwOyB9XG4gIGZvciAobiA9IDA7IG4gPCBEX0NPREVTJDE7ICBuKyspIHsgcy5keW5fZHRyZWVbbiAqIDJdLyouRnJlcSovID0gMDsgfVxuICBmb3IgKG4gPSAwOyBuIDwgQkxfQ09ERVMkMTsgbisrKSB7IHMuYmxfdHJlZVtuICogMl0vKi5GcmVxKi8gPSAwOyB9XG5cbiAgcy5keW5fbHRyZWVbRU5EX0JMT0NLICogMl0vKi5GcmVxKi8gPSAxO1xuICBzLm9wdF9sZW4gPSBzLnN0YXRpY19sZW4gPSAwO1xuICBzLnN5bV9uZXh0ID0gcy5tYXRjaGVzID0gMDtcbn07XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBGbHVzaCB0aGUgYml0IGJ1ZmZlciBhbmQgYWxpZ24gdGhlIG91dHB1dCBvbiBhIGJ5dGUgYm91bmRhcnlcbiAqL1xuY29uc3QgYmlfd2luZHVwID0gKHMpID0+XG57XG4gIGlmIChzLmJpX3ZhbGlkID4gOCkge1xuICAgIHB1dF9zaG9ydChzLCBzLmJpX2J1Zik7XG4gIH0gZWxzZSBpZiAocy5iaV92YWxpZCA+IDApIHtcbiAgICAvL3B1dF9ieXRlKHMsIChCeXRlKXMtPmJpX2J1Zik7XG4gICAgcy5wZW5kaW5nX2J1ZltzLnBlbmRpbmcrK10gPSBzLmJpX2J1ZjtcbiAgfVxuICBzLmJpX2J1ZiA9IDA7XG4gIHMuYmlfdmFsaWQgPSAwO1xufTtcblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb21wYXJlcyB0byBzdWJ0cmVlcywgdXNpbmcgdGhlIHRyZWUgZGVwdGggYXMgdGllIGJyZWFrZXIgd2hlblxuICogdGhlIHN1YnRyZWVzIGhhdmUgZXF1YWwgZnJlcXVlbmN5LiBUaGlzIG1pbmltaXplcyB0aGUgd29yc3QgY2FzZSBsZW5ndGguXG4gKi9cbmNvbnN0IHNtYWxsZXIgPSAodHJlZSwgbiwgbSwgZGVwdGgpID0+IHtcblxuICBjb25zdCBfbjIgPSBuICogMjtcbiAgY29uc3QgX20yID0gbSAqIDI7XG4gIHJldHVybiAodHJlZVtfbjJdLyouRnJlcSovIDwgdHJlZVtfbTJdLyouRnJlcSovIHx8XG4gICAgICAgICAodHJlZVtfbjJdLyouRnJlcSovID09PSB0cmVlW19tMl0vKi5GcmVxKi8gJiYgZGVwdGhbbl0gPD0gZGVwdGhbbV0pKTtcbn07XG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogUmVzdG9yZSB0aGUgaGVhcCBwcm9wZXJ0eSBieSBtb3ZpbmcgZG93biB0aGUgdHJlZSBzdGFydGluZyBhdCBub2RlIGssXG4gKiBleGNoYW5naW5nIGEgbm9kZSB3aXRoIHRoZSBzbWFsbGVzdCBvZiBpdHMgdHdvIHNvbnMgaWYgbmVjZXNzYXJ5LCBzdG9wcGluZ1xuICogd2hlbiB0aGUgaGVhcCBwcm9wZXJ0eSBpcyByZS1lc3RhYmxpc2hlZCAoZWFjaCBmYXRoZXIgc21hbGxlciB0aGFuIGl0c1xuICogdHdvIHNvbnMpLlxuICovXG5jb25zdCBwcWRvd25oZWFwID0gKHMsIHRyZWUsIGspID0+IHtcbi8vICAgIGRlZmxhdGVfc3RhdGUgKnM7XG4vLyAgICBjdF9kYXRhICp0cmVlOyAgLyogdGhlIHRyZWUgdG8gcmVzdG9yZSAqL1xuLy8gICAgaW50IGs7ICAgICAgICAgICAgICAgLyogbm9kZSB0byBtb3ZlIGRvd24gKi9cblxuICBjb25zdCB2ID0gcy5oZWFwW2tdO1xuICBsZXQgaiA9IGsgPDwgMTsgIC8qIGxlZnQgc29uIG9mIGsgKi9cbiAgd2hpbGUgKGogPD0gcy5oZWFwX2xlbikge1xuICAgIC8qIFNldCBqIHRvIHRoZSBzbWFsbGVzdCBvZiB0aGUgdHdvIHNvbnM6ICovXG4gICAgaWYgKGogPCBzLmhlYXBfbGVuICYmXG4gICAgICBzbWFsbGVyKHRyZWUsIHMuaGVhcFtqICsgMV0sIHMuaGVhcFtqXSwgcy5kZXB0aCkpIHtcbiAgICAgIGorKztcbiAgICB9XG4gICAgLyogRXhpdCBpZiB2IGlzIHNtYWxsZXIgdGhhbiBib3RoIHNvbnMgKi9cbiAgICBpZiAoc21hbGxlcih0cmVlLCB2LCBzLmhlYXBbal0sIHMuZGVwdGgpKSB7IGJyZWFrOyB9XG5cbiAgICAvKiBFeGNoYW5nZSB2IHdpdGggdGhlIHNtYWxsZXN0IHNvbiAqL1xuICAgIHMuaGVhcFtrXSA9IHMuaGVhcFtqXTtcbiAgICBrID0gajtcblxuICAgIC8qIEFuZCBjb250aW51ZSBkb3duIHRoZSB0cmVlLCBzZXR0aW5nIGogdG8gdGhlIGxlZnQgc29uIG9mIGsgKi9cbiAgICBqIDw8PSAxO1xuICB9XG4gIHMuaGVhcFtrXSA9IHY7XG59O1xuXG5cbi8vIGlubGluZWQgbWFudWFsbHlcbi8vIGNvbnN0IFNNQUxMRVNUID0gMTtcblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBTZW5kIHRoZSBibG9jayBkYXRhIGNvbXByZXNzZWQgdXNpbmcgdGhlIGdpdmVuIEh1ZmZtYW4gdHJlZXNcbiAqL1xuY29uc3QgY29tcHJlc3NfYmxvY2sgPSAocywgbHRyZWUsIGR0cmVlKSA9PiB7XG4vLyAgICBkZWZsYXRlX3N0YXRlICpzO1xuLy8gICAgY29uc3QgY3RfZGF0YSAqbHRyZWU7IC8qIGxpdGVyYWwgdHJlZSAqL1xuLy8gICAgY29uc3QgY3RfZGF0YSAqZHRyZWU7IC8qIGRpc3RhbmNlIHRyZWUgKi9cblxuICBsZXQgZGlzdDsgICAgICAgICAgIC8qIGRpc3RhbmNlIG9mIG1hdGNoZWQgc3RyaW5nICovXG4gIGxldCBsYzsgICAgICAgICAgICAgLyogbWF0Y2ggbGVuZ3RoIG9yIHVubWF0Y2hlZCBjaGFyIChpZiBkaXN0ID09IDApICovXG4gIGxldCBzeCA9IDA7ICAgICAgICAgLyogcnVubmluZyBpbmRleCBpbiBzeW1fYnVmICovXG4gIGxldCBjb2RlOyAgICAgICAgICAgLyogdGhlIGNvZGUgdG8gc2VuZCAqL1xuICBsZXQgZXh0cmE7ICAgICAgICAgIC8qIG51bWJlciBvZiBleHRyYSBiaXRzIHRvIHNlbmQgKi9cblxuICBpZiAocy5zeW1fbmV4dCAhPT0gMCkge1xuICAgIGRvIHtcbiAgICAgIGRpc3QgPSBzLnBlbmRpbmdfYnVmW3Muc3ltX2J1ZiArIHN4KytdICYgMHhmZjtcbiAgICAgIGRpc3QgKz0gKHMucGVuZGluZ19idWZbcy5zeW1fYnVmICsgc3grK10gJiAweGZmKSA8PCA4O1xuICAgICAgbGMgPSBzLnBlbmRpbmdfYnVmW3Muc3ltX2J1ZiArIHN4KytdO1xuICAgICAgaWYgKGRpc3QgPT09IDApIHtcbiAgICAgICAgc2VuZF9jb2RlKHMsIGxjLCBsdHJlZSk7IC8qIHNlbmQgYSBsaXRlcmFsIGJ5dGUgKi9cbiAgICAgICAgLy9UcmFjZWN2KGlzZ3JhcGgobGMpLCAoc3RkZXJyLFwiICclYycgXCIsIGxjKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvKiBIZXJlLCBsYyBpcyB0aGUgbWF0Y2ggbGVuZ3RoIC0gTUlOX01BVENIICovXG4gICAgICAgIGNvZGUgPSBfbGVuZ3RoX2NvZGVbbGNdO1xuICAgICAgICBzZW5kX2NvZGUocywgY29kZSArIExJVEVSQUxTJDEgKyAxLCBsdHJlZSk7IC8qIHNlbmQgdGhlIGxlbmd0aCBjb2RlICovXG4gICAgICAgIGV4dHJhID0gZXh0cmFfbGJpdHNbY29kZV07XG4gICAgICAgIGlmIChleHRyYSAhPT0gMCkge1xuICAgICAgICAgIGxjIC09IGJhc2VfbGVuZ3RoW2NvZGVdO1xuICAgICAgICAgIHNlbmRfYml0cyhzLCBsYywgZXh0cmEpOyAgICAgICAvKiBzZW5kIHRoZSBleHRyYSBsZW5ndGggYml0cyAqL1xuICAgICAgICB9XG4gICAgICAgIGRpc3QtLTsgLyogZGlzdCBpcyBub3cgdGhlIG1hdGNoIGRpc3RhbmNlIC0gMSAqL1xuICAgICAgICBjb2RlID0gZF9jb2RlKGRpc3QpO1xuICAgICAgICAvL0Fzc2VydCAoY29kZSA8IERfQ09ERVMsIFwiYmFkIGRfY29kZVwiKTtcblxuICAgICAgICBzZW5kX2NvZGUocywgY29kZSwgZHRyZWUpOyAgICAgICAvKiBzZW5kIHRoZSBkaXN0YW5jZSBjb2RlICovXG4gICAgICAgIGV4dHJhID0gZXh0cmFfZGJpdHNbY29kZV07XG4gICAgICAgIGlmIChleHRyYSAhPT0gMCkge1xuICAgICAgICAgIGRpc3QgLT0gYmFzZV9kaXN0W2NvZGVdO1xuICAgICAgICAgIHNlbmRfYml0cyhzLCBkaXN0LCBleHRyYSk7ICAgLyogc2VuZCB0aGUgZXh0cmEgZGlzdGFuY2UgYml0cyAqL1xuICAgICAgICB9XG4gICAgICB9IC8qIGxpdGVyYWwgb3IgbWF0Y2ggcGFpciA/ICovXG5cbiAgICAgIC8qIENoZWNrIHRoYXQgdGhlIG92ZXJsYXkgYmV0d2VlbiBwZW5kaW5nX2J1ZiBhbmQgc3ltX2J1ZiBpcyBvazogKi9cbiAgICAgIC8vQXNzZXJ0KHMtPnBlbmRpbmcgPCBzLT5saXRfYnVmc2l6ZSArIHN4LCBcInBlbmRpbmdCdWYgb3ZlcmZsb3dcIik7XG5cbiAgICB9IHdoaWxlIChzeCA8IHMuc3ltX25leHQpO1xuICB9XG5cbiAgc2VuZF9jb2RlKHMsIEVORF9CTE9DSywgbHRyZWUpO1xufTtcblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvbnN0cnVjdCBvbmUgSHVmZm1hbiB0cmVlIGFuZCBhc3NpZ25zIHRoZSBjb2RlIGJpdCBzdHJpbmdzIGFuZCBsZW5ndGhzLlxuICogVXBkYXRlIHRoZSB0b3RhbCBiaXQgbGVuZ3RoIGZvciB0aGUgY3VycmVudCBibG9jay5cbiAqIElOIGFzc2VydGlvbjogdGhlIGZpZWxkIGZyZXEgaXMgc2V0IGZvciBhbGwgdHJlZSBlbGVtZW50cy5cbiAqIE9VVCBhc3NlcnRpb25zOiB0aGUgZmllbGRzIGxlbiBhbmQgY29kZSBhcmUgc2V0IHRvIHRoZSBvcHRpbWFsIGJpdCBsZW5ndGhcbiAqICAgICBhbmQgY29ycmVzcG9uZGluZyBjb2RlLiBUaGUgbGVuZ3RoIG9wdF9sZW4gaXMgdXBkYXRlZDsgc3RhdGljX2xlbiBpc1xuICogICAgIGFsc28gdXBkYXRlZCBpZiBzdHJlZSBpcyBub3QgbnVsbC4gVGhlIGZpZWxkIG1heF9jb2RlIGlzIHNldC5cbiAqL1xuY29uc3QgYnVpbGRfdHJlZSA9IChzLCBkZXNjKSA9PiB7XG4vLyAgICBkZWZsYXRlX3N0YXRlICpzO1xuLy8gICAgdHJlZV9kZXNjICpkZXNjOyAvKiB0aGUgdHJlZSBkZXNjcmlwdG9yICovXG5cbiAgY29uc3QgdHJlZSAgICAgPSBkZXNjLmR5bl90cmVlO1xuICBjb25zdCBzdHJlZSAgICA9IGRlc2Muc3RhdF9kZXNjLnN0YXRpY190cmVlO1xuICBjb25zdCBoYXNfc3RyZWUgPSBkZXNjLnN0YXRfZGVzYy5oYXNfc3RyZWU7XG4gIGNvbnN0IGVsZW1zICAgID0gZGVzYy5zdGF0X2Rlc2MuZWxlbXM7XG4gIGxldCBuLCBtOyAgICAgICAgICAvKiBpdGVyYXRlIG92ZXIgaGVhcCBlbGVtZW50cyAqL1xuICBsZXQgbWF4X2NvZGUgPSAtMTsgLyogbGFyZ2VzdCBjb2RlIHdpdGggbm9uIHplcm8gZnJlcXVlbmN5ICovXG4gIGxldCBub2RlOyAgICAgICAgICAvKiBuZXcgbm9kZSBiZWluZyBjcmVhdGVkICovXG5cbiAgLyogQ29uc3RydWN0IHRoZSBpbml0aWFsIGhlYXAsIHdpdGggbGVhc3QgZnJlcXVlbnQgZWxlbWVudCBpblxuICAgKiBoZWFwW1NNQUxMRVNUXS4gVGhlIHNvbnMgb2YgaGVhcFtuXSBhcmUgaGVhcFsyKm5dIGFuZCBoZWFwWzIqbisxXS5cbiAgICogaGVhcFswXSBpcyBub3QgdXNlZC5cbiAgICovXG4gIHMuaGVhcF9sZW4gPSAwO1xuICBzLmhlYXBfbWF4ID0gSEVBUF9TSVpFJDE7XG5cbiAgZm9yIChuID0gMDsgbiA8IGVsZW1zOyBuKyspIHtcbiAgICBpZiAodHJlZVtuICogMl0vKi5GcmVxKi8gIT09IDApIHtcbiAgICAgIHMuaGVhcFsrK3MuaGVhcF9sZW5dID0gbWF4X2NvZGUgPSBuO1xuICAgICAgcy5kZXB0aFtuXSA9IDA7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgdHJlZVtuICogMiArIDFdLyouTGVuKi8gPSAwO1xuICAgIH1cbiAgfVxuXG4gIC8qIFRoZSBwa3ppcCBmb3JtYXQgcmVxdWlyZXMgdGhhdCBhdCBsZWFzdCBvbmUgZGlzdGFuY2UgY29kZSBleGlzdHMsXG4gICAqIGFuZCB0aGF0IGF0IGxlYXN0IG9uZSBiaXQgc2hvdWxkIGJlIHNlbnQgZXZlbiBpZiB0aGVyZSBpcyBvbmx5IG9uZVxuICAgKiBwb3NzaWJsZSBjb2RlLiBTbyB0byBhdm9pZCBzcGVjaWFsIGNoZWNrcyBsYXRlciBvbiB3ZSBmb3JjZSBhdCBsZWFzdFxuICAgKiB0d28gY29kZXMgb2Ygbm9uIHplcm8gZnJlcXVlbmN5LlxuICAgKi9cbiAgd2hpbGUgKHMuaGVhcF9sZW4gPCAyKSB7XG4gICAgbm9kZSA9IHMuaGVhcFsrK3MuaGVhcF9sZW5dID0gKG1heF9jb2RlIDwgMiA/ICsrbWF4X2NvZGUgOiAwKTtcbiAgICB0cmVlW25vZGUgKiAyXS8qLkZyZXEqLyA9IDE7XG4gICAgcy5kZXB0aFtub2RlXSA9IDA7XG4gICAgcy5vcHRfbGVuLS07XG5cbiAgICBpZiAoaGFzX3N0cmVlKSB7XG4gICAgICBzLnN0YXRpY19sZW4gLT0gc3RyZWVbbm9kZSAqIDIgKyAxXS8qLkxlbiovO1xuICAgIH1cbiAgICAvKiBub2RlIGlzIDAgb3IgMSBzbyBpdCBkb2VzIG5vdCBoYXZlIGV4dHJhIGJpdHMgKi9cbiAgfVxuICBkZXNjLm1heF9jb2RlID0gbWF4X2NvZGU7XG5cbiAgLyogVGhlIGVsZW1lbnRzIGhlYXBbaGVhcF9sZW4vMisxIC4uIGhlYXBfbGVuXSBhcmUgbGVhdmVzIG9mIHRoZSB0cmVlLFxuICAgKiBlc3RhYmxpc2ggc3ViLWhlYXBzIG9mIGluY3JlYXNpbmcgbGVuZ3RoczpcbiAgICovXG4gIGZvciAobiA9IChzLmhlYXBfbGVuID4+IDEvKmludCAvMiovKTsgbiA+PSAxOyBuLS0pIHsgcHFkb3duaGVhcChzLCB0cmVlLCBuKTsgfVxuXG4gIC8qIENvbnN0cnVjdCB0aGUgSHVmZm1hbiB0cmVlIGJ5IHJlcGVhdGVkbHkgY29tYmluaW5nIHRoZSBsZWFzdCB0d29cbiAgICogZnJlcXVlbnQgbm9kZXMuXG4gICAqL1xuICBub2RlID0gZWxlbXM7ICAgICAgICAgICAgICAvKiBuZXh0IGludGVybmFsIG5vZGUgb2YgdGhlIHRyZWUgKi9cbiAgZG8ge1xuICAgIC8vcHFyZW1vdmUocywgdHJlZSwgbik7ICAvKiBuID0gbm9kZSBvZiBsZWFzdCBmcmVxdWVuY3kgKi9cbiAgICAvKioqIHBxcmVtb3ZlICoqKi9cbiAgICBuID0gcy5oZWFwWzEvKlNNQUxMRVNUKi9dO1xuICAgIHMuaGVhcFsxLypTTUFMTEVTVCovXSA9IHMuaGVhcFtzLmhlYXBfbGVuLS1dO1xuICAgIHBxZG93bmhlYXAocywgdHJlZSwgMS8qU01BTExFU1QqLyk7XG4gICAgLyoqKi9cblxuICAgIG0gPSBzLmhlYXBbMS8qU01BTExFU1QqL107IC8qIG0gPSBub2RlIG9mIG5leHQgbGVhc3QgZnJlcXVlbmN5ICovXG5cbiAgICBzLmhlYXBbLS1zLmhlYXBfbWF4XSA9IG47IC8qIGtlZXAgdGhlIG5vZGVzIHNvcnRlZCBieSBmcmVxdWVuY3kgKi9cbiAgICBzLmhlYXBbLS1zLmhlYXBfbWF4XSA9IG07XG5cbiAgICAvKiBDcmVhdGUgYSBuZXcgbm9kZSBmYXRoZXIgb2YgbiBhbmQgbSAqL1xuICAgIHRyZWVbbm9kZSAqIDJdLyouRnJlcSovID0gdHJlZVtuICogMl0vKi5GcmVxKi8gKyB0cmVlW20gKiAyXS8qLkZyZXEqLztcbiAgICBzLmRlcHRoW25vZGVdID0gKHMuZGVwdGhbbl0gPj0gcy5kZXB0aFttXSA/IHMuZGVwdGhbbl0gOiBzLmRlcHRoW21dKSArIDE7XG4gICAgdHJlZVtuICogMiArIDFdLyouRGFkKi8gPSB0cmVlW20gKiAyICsgMV0vKi5EYWQqLyA9IG5vZGU7XG5cbiAgICAvKiBhbmQgaW5zZXJ0IHRoZSBuZXcgbm9kZSBpbiB0aGUgaGVhcCAqL1xuICAgIHMuaGVhcFsxLypTTUFMTEVTVCovXSA9IG5vZGUrKztcbiAgICBwcWRvd25oZWFwKHMsIHRyZWUsIDEvKlNNQUxMRVNUKi8pO1xuXG4gIH0gd2hpbGUgKHMuaGVhcF9sZW4gPj0gMik7XG5cbiAgcy5oZWFwWy0tcy5oZWFwX21heF0gPSBzLmhlYXBbMS8qU01BTExFU1QqL107XG5cbiAgLyogQXQgdGhpcyBwb2ludCwgdGhlIGZpZWxkcyBmcmVxIGFuZCBkYWQgYXJlIHNldC4gV2UgY2FuIG5vd1xuICAgKiBnZW5lcmF0ZSB0aGUgYml0IGxlbmd0aHMuXG4gICAqL1xuICBnZW5fYml0bGVuKHMsIGRlc2MpO1xuXG4gIC8qIFRoZSBmaWVsZCBsZW4gaXMgbm93IHNldCwgd2UgY2FuIGdlbmVyYXRlIHRoZSBiaXQgY29kZXMgKi9cbiAgZ2VuX2NvZGVzKHRyZWUsIG1heF9jb2RlLCBzLmJsX2NvdW50KTtcbn07XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBTY2FuIGEgbGl0ZXJhbCBvciBkaXN0YW5jZSB0cmVlIHRvIGRldGVybWluZSB0aGUgZnJlcXVlbmNpZXMgb2YgdGhlIGNvZGVzXG4gKiBpbiB0aGUgYml0IGxlbmd0aCB0cmVlLlxuICovXG5jb25zdCBzY2FuX3RyZWUgPSAocywgdHJlZSwgbWF4X2NvZGUpID0+IHtcbi8vICAgIGRlZmxhdGVfc3RhdGUgKnM7XG4vLyAgICBjdF9kYXRhICp0cmVlOyAgIC8qIHRoZSB0cmVlIHRvIGJlIHNjYW5uZWQgKi9cbi8vICAgIGludCBtYXhfY29kZTsgICAgLyogYW5kIGl0cyBsYXJnZXN0IGNvZGUgb2Ygbm9uIHplcm8gZnJlcXVlbmN5ICovXG5cbiAgbGV0IG47ICAgICAgICAgICAgICAgICAgICAgLyogaXRlcmF0ZXMgb3ZlciBhbGwgdHJlZSBlbGVtZW50cyAqL1xuICBsZXQgcHJldmxlbiA9IC0xOyAgICAgICAgICAvKiBsYXN0IGVtaXR0ZWQgbGVuZ3RoICovXG4gIGxldCBjdXJsZW47ICAgICAgICAgICAgICAgIC8qIGxlbmd0aCBvZiBjdXJyZW50IGNvZGUgKi9cblxuICBsZXQgbmV4dGxlbiA9IHRyZWVbMCAqIDIgKyAxXS8qLkxlbiovOyAvKiBsZW5ndGggb2YgbmV4dCBjb2RlICovXG5cbiAgbGV0IGNvdW50ID0gMDsgICAgICAgICAgICAgLyogcmVwZWF0IGNvdW50IG9mIHRoZSBjdXJyZW50IGNvZGUgKi9cbiAgbGV0IG1heF9jb3VudCA9IDc7ICAgICAgICAgLyogbWF4IHJlcGVhdCBjb3VudCAqL1xuICBsZXQgbWluX2NvdW50ID0gNDsgICAgICAgICAvKiBtaW4gcmVwZWF0IGNvdW50ICovXG5cbiAgaWYgKG5leHRsZW4gPT09IDApIHtcbiAgICBtYXhfY291bnQgPSAxMzg7XG4gICAgbWluX2NvdW50ID0gMztcbiAgfVxuICB0cmVlWyhtYXhfY29kZSArIDEpICogMiArIDFdLyouTGVuKi8gPSAweGZmZmY7IC8qIGd1YXJkICovXG5cbiAgZm9yIChuID0gMDsgbiA8PSBtYXhfY29kZTsgbisrKSB7XG4gICAgY3VybGVuID0gbmV4dGxlbjtcbiAgICBuZXh0bGVuID0gdHJlZVsobiArIDEpICogMiArIDFdLyouTGVuKi87XG5cbiAgICBpZiAoKytjb3VudCA8IG1heF9jb3VudCAmJiBjdXJsZW4gPT09IG5leHRsZW4pIHtcbiAgICAgIGNvbnRpbnVlO1xuXG4gICAgfSBlbHNlIGlmIChjb3VudCA8IG1pbl9jb3VudCkge1xuICAgICAgcy5ibF90cmVlW2N1cmxlbiAqIDJdLyouRnJlcSovICs9IGNvdW50O1xuXG4gICAgfSBlbHNlIGlmIChjdXJsZW4gIT09IDApIHtcblxuICAgICAgaWYgKGN1cmxlbiAhPT0gcHJldmxlbikgeyBzLmJsX3RyZWVbY3VybGVuICogMl0vKi5GcmVxKi8rKzsgfVxuICAgICAgcy5ibF90cmVlW1JFUF8zXzYgKiAyXS8qLkZyZXEqLysrO1xuXG4gICAgfSBlbHNlIGlmIChjb3VudCA8PSAxMCkge1xuICAgICAgcy5ibF90cmVlW1JFUFpfM18xMCAqIDJdLyouRnJlcSovKys7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgcy5ibF90cmVlW1JFUFpfMTFfMTM4ICogMl0vKi5GcmVxKi8rKztcbiAgICB9XG5cbiAgICBjb3VudCA9IDA7XG4gICAgcHJldmxlbiA9IGN1cmxlbjtcblxuICAgIGlmIChuZXh0bGVuID09PSAwKSB7XG4gICAgICBtYXhfY291bnQgPSAxMzg7XG4gICAgICBtaW5fY291bnQgPSAzO1xuXG4gICAgfSBlbHNlIGlmIChjdXJsZW4gPT09IG5leHRsZW4pIHtcbiAgICAgIG1heF9jb3VudCA9IDY7XG4gICAgICBtaW5fY291bnQgPSAzO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgIG1heF9jb3VudCA9IDc7XG4gICAgICBtaW5fY291bnQgPSA0O1xuICAgIH1cbiAgfVxufTtcblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFNlbmQgYSBsaXRlcmFsIG9yIGRpc3RhbmNlIHRyZWUgaW4gY29tcHJlc3NlZCBmb3JtLCB1c2luZyB0aGUgY29kZXMgaW5cbiAqIGJsX3RyZWUuXG4gKi9cbmNvbnN0IHNlbmRfdHJlZSA9IChzLCB0cmVlLCBtYXhfY29kZSkgPT4ge1xuLy8gICAgZGVmbGF0ZV9zdGF0ZSAqcztcbi8vICAgIGN0X2RhdGEgKnRyZWU7IC8qIHRoZSB0cmVlIHRvIGJlIHNjYW5uZWQgKi9cbi8vICAgIGludCBtYXhfY29kZTsgICAgICAgLyogYW5kIGl0cyBsYXJnZXN0IGNvZGUgb2Ygbm9uIHplcm8gZnJlcXVlbmN5ICovXG5cbiAgbGV0IG47ICAgICAgICAgICAgICAgICAgICAgLyogaXRlcmF0ZXMgb3ZlciBhbGwgdHJlZSBlbGVtZW50cyAqL1xuICBsZXQgcHJldmxlbiA9IC0xOyAgICAgICAgICAvKiBsYXN0IGVtaXR0ZWQgbGVuZ3RoICovXG4gIGxldCBjdXJsZW47ICAgICAgICAgICAgICAgIC8qIGxlbmd0aCBvZiBjdXJyZW50IGNvZGUgKi9cblxuICBsZXQgbmV4dGxlbiA9IHRyZWVbMCAqIDIgKyAxXS8qLkxlbiovOyAvKiBsZW5ndGggb2YgbmV4dCBjb2RlICovXG5cbiAgbGV0IGNvdW50ID0gMDsgICAgICAgICAgICAgLyogcmVwZWF0IGNvdW50IG9mIHRoZSBjdXJyZW50IGNvZGUgKi9cbiAgbGV0IG1heF9jb3VudCA9IDc7ICAgICAgICAgLyogbWF4IHJlcGVhdCBjb3VudCAqL1xuICBsZXQgbWluX2NvdW50ID0gNDsgICAgICAgICAvKiBtaW4gcmVwZWF0IGNvdW50ICovXG5cbiAgLyogdHJlZVttYXhfY29kZSsxXS5MZW4gPSAtMTsgKi8gIC8qIGd1YXJkIGFscmVhZHkgc2V0ICovXG4gIGlmIChuZXh0bGVuID09PSAwKSB7XG4gICAgbWF4X2NvdW50ID0gMTM4O1xuICAgIG1pbl9jb3VudCA9IDM7XG4gIH1cblxuICBmb3IgKG4gPSAwOyBuIDw9IG1heF9jb2RlOyBuKyspIHtcbiAgICBjdXJsZW4gPSBuZXh0bGVuO1xuICAgIG5leHRsZW4gPSB0cmVlWyhuICsgMSkgKiAyICsgMV0vKi5MZW4qLztcblxuICAgIGlmICgrK2NvdW50IDwgbWF4X2NvdW50ICYmIGN1cmxlbiA9PT0gbmV4dGxlbikge1xuICAgICAgY29udGludWU7XG5cbiAgICB9IGVsc2UgaWYgKGNvdW50IDwgbWluX2NvdW50KSB7XG4gICAgICBkbyB7IHNlbmRfY29kZShzLCBjdXJsZW4sIHMuYmxfdHJlZSk7IH0gd2hpbGUgKC0tY291bnQgIT09IDApO1xuXG4gICAgfSBlbHNlIGlmIChjdXJsZW4gIT09IDApIHtcbiAgICAgIGlmIChjdXJsZW4gIT09IHByZXZsZW4pIHtcbiAgICAgICAgc2VuZF9jb2RlKHMsIGN1cmxlbiwgcy5ibF90cmVlKTtcbiAgICAgICAgY291bnQtLTtcbiAgICAgIH1cbiAgICAgIC8vQXNzZXJ0KGNvdW50ID49IDMgJiYgY291bnQgPD0gNiwgXCIgM182P1wiKTtcbiAgICAgIHNlbmRfY29kZShzLCBSRVBfM182LCBzLmJsX3RyZWUpO1xuICAgICAgc2VuZF9iaXRzKHMsIGNvdW50IC0gMywgMik7XG5cbiAgICB9IGVsc2UgaWYgKGNvdW50IDw9IDEwKSB7XG4gICAgICBzZW5kX2NvZGUocywgUkVQWl8zXzEwLCBzLmJsX3RyZWUpO1xuICAgICAgc2VuZF9iaXRzKHMsIGNvdW50IC0gMywgMyk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgc2VuZF9jb2RlKHMsIFJFUFpfMTFfMTM4LCBzLmJsX3RyZWUpO1xuICAgICAgc2VuZF9iaXRzKHMsIGNvdW50IC0gMTEsIDcpO1xuICAgIH1cblxuICAgIGNvdW50ID0gMDtcbiAgICBwcmV2bGVuID0gY3VybGVuO1xuICAgIGlmIChuZXh0bGVuID09PSAwKSB7XG4gICAgICBtYXhfY291bnQgPSAxMzg7XG4gICAgICBtaW5fY291bnQgPSAzO1xuXG4gICAgfSBlbHNlIGlmIChjdXJsZW4gPT09IG5leHRsZW4pIHtcbiAgICAgIG1heF9jb3VudCA9IDY7XG4gICAgICBtaW5fY291bnQgPSAzO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgIG1heF9jb3VudCA9IDc7XG4gICAgICBtaW5fY291bnQgPSA0O1xuICAgIH1cbiAgfVxufTtcblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvbnN0cnVjdCB0aGUgSHVmZm1hbiB0cmVlIGZvciB0aGUgYml0IGxlbmd0aHMgYW5kIHJldHVybiB0aGUgaW5kZXggaW5cbiAqIGJsX29yZGVyIG9mIHRoZSBsYXN0IGJpdCBsZW5ndGggY29kZSB0byBzZW5kLlxuICovXG5jb25zdCBidWlsZF9ibF90cmVlID0gKHMpID0+IHtcblxuICBsZXQgbWF4X2JsaW5kZXg7ICAvKiBpbmRleCBvZiBsYXN0IGJpdCBsZW5ndGggY29kZSBvZiBub24gemVybyBmcmVxICovXG5cbiAgLyogRGV0ZXJtaW5lIHRoZSBiaXQgbGVuZ3RoIGZyZXF1ZW5jaWVzIGZvciBsaXRlcmFsIGFuZCBkaXN0YW5jZSB0cmVlcyAqL1xuICBzY2FuX3RyZWUocywgcy5keW5fbHRyZWUsIHMubF9kZXNjLm1heF9jb2RlKTtcbiAgc2Nhbl90cmVlKHMsIHMuZHluX2R0cmVlLCBzLmRfZGVzYy5tYXhfY29kZSk7XG5cbiAgLyogQnVpbGQgdGhlIGJpdCBsZW5ndGggdHJlZTogKi9cbiAgYnVpbGRfdHJlZShzLCBzLmJsX2Rlc2MpO1xuICAvKiBvcHRfbGVuIG5vdyBpbmNsdWRlcyB0aGUgbGVuZ3RoIG9mIHRoZSB0cmVlIHJlcHJlc2VudGF0aW9ucywgZXhjZXB0XG4gICAqIHRoZSBsZW5ndGhzIG9mIHRoZSBiaXQgbGVuZ3RocyBjb2RlcyBhbmQgdGhlIDUrNSs0IGJpdHMgZm9yIHRoZSBjb3VudHMuXG4gICAqL1xuXG4gIC8qIERldGVybWluZSB0aGUgbnVtYmVyIG9mIGJpdCBsZW5ndGggY29kZXMgdG8gc2VuZC4gVGhlIHBremlwIGZvcm1hdFxuICAgKiByZXF1aXJlcyB0aGF0IGF0IGxlYXN0IDQgYml0IGxlbmd0aCBjb2RlcyBiZSBzZW50LiAoYXBwbm90ZS50eHQgc2F5c1xuICAgKiAzIGJ1dCB0aGUgYWN0dWFsIHZhbHVlIHVzZWQgaXMgNC4pXG4gICAqL1xuICBmb3IgKG1heF9ibGluZGV4ID0gQkxfQ09ERVMkMSAtIDE7IG1heF9ibGluZGV4ID49IDM7IG1heF9ibGluZGV4LS0pIHtcbiAgICBpZiAocy5ibF90cmVlW2JsX29yZGVyW21heF9ibGluZGV4XSAqIDIgKyAxXS8qLkxlbiovICE9PSAwKSB7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgLyogVXBkYXRlIG9wdF9sZW4gdG8gaW5jbHVkZSB0aGUgYml0IGxlbmd0aCB0cmVlIGFuZCBjb3VudHMgKi9cbiAgcy5vcHRfbGVuICs9IDMgKiAobWF4X2JsaW5kZXggKyAxKSArIDUgKyA1ICsgNDtcbiAgLy9UcmFjZXYoKHN0ZGVyciwgXCJcXG5keW4gdHJlZXM6IGR5biAlbGQsIHN0YXQgJWxkXCIsXG4gIC8vICAgICAgICBzLT5vcHRfbGVuLCBzLT5zdGF0aWNfbGVuKSk7XG5cbiAgcmV0dXJuIG1heF9ibGluZGV4O1xufTtcblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFNlbmQgdGhlIGhlYWRlciBmb3IgYSBibG9jayB1c2luZyBkeW5hbWljIEh1ZmZtYW4gdHJlZXM6IHRoZSBjb3VudHMsIHRoZVxuICogbGVuZ3RocyBvZiB0aGUgYml0IGxlbmd0aCBjb2RlcywgdGhlIGxpdGVyYWwgdHJlZSBhbmQgdGhlIGRpc3RhbmNlIHRyZWUuXG4gKiBJTiBhc3NlcnRpb246IGxjb2RlcyA+PSAyNTcsIGRjb2RlcyA+PSAxLCBibGNvZGVzID49IDQuXG4gKi9cbmNvbnN0IHNlbmRfYWxsX3RyZWVzID0gKHMsIGxjb2RlcywgZGNvZGVzLCBibGNvZGVzKSA9PiB7XG4vLyAgICBkZWZsYXRlX3N0YXRlICpzO1xuLy8gICAgaW50IGxjb2RlcywgZGNvZGVzLCBibGNvZGVzOyAvKiBudW1iZXIgb2YgY29kZXMgZm9yIGVhY2ggdHJlZSAqL1xuXG4gIGxldCByYW5rOyAgICAgICAgICAgICAgICAgICAgLyogaW5kZXggaW4gYmxfb3JkZXIgKi9cblxuICAvL0Fzc2VydCAobGNvZGVzID49IDI1NyAmJiBkY29kZXMgPj0gMSAmJiBibGNvZGVzID49IDQsIFwibm90IGVub3VnaCBjb2Rlc1wiKTtcbiAgLy9Bc3NlcnQgKGxjb2RlcyA8PSBMX0NPREVTICYmIGRjb2RlcyA8PSBEX0NPREVTICYmIGJsY29kZXMgPD0gQkxfQ09ERVMsXG4gIC8vICAgICAgICBcInRvbyBtYW55IGNvZGVzXCIpO1xuICAvL1RyYWNldigoc3RkZXJyLCBcIlxcbmJsIGNvdW50czogXCIpKTtcbiAgc2VuZF9iaXRzKHMsIGxjb2RlcyAtIDI1NywgNSk7IC8qIG5vdCArMjU1IGFzIHN0YXRlZCBpbiBhcHBub3RlLnR4dCAqL1xuICBzZW5kX2JpdHMocywgZGNvZGVzIC0gMSwgICA1KTtcbiAgc2VuZF9iaXRzKHMsIGJsY29kZXMgLSA0LCAgNCk7IC8qIG5vdCAtMyBhcyBzdGF0ZWQgaW4gYXBwbm90ZS50eHQgKi9cbiAgZm9yIChyYW5rID0gMDsgcmFuayA8IGJsY29kZXM7IHJhbmsrKykge1xuICAgIC8vVHJhY2V2KChzdGRlcnIsIFwiXFxuYmwgY29kZSAlMmQgXCIsIGJsX29yZGVyW3JhbmtdKSk7XG4gICAgc2VuZF9iaXRzKHMsIHMuYmxfdHJlZVtibF9vcmRlcltyYW5rXSAqIDIgKyAxXS8qLkxlbiovLCAzKTtcbiAgfVxuICAvL1RyYWNldigoc3RkZXJyLCBcIlxcbmJsIHRyZWU6IHNlbnQgJWxkXCIsIHMtPmJpdHNfc2VudCkpO1xuXG4gIHNlbmRfdHJlZShzLCBzLmR5bl9sdHJlZSwgbGNvZGVzIC0gMSk7IC8qIGxpdGVyYWwgdHJlZSAqL1xuICAvL1RyYWNldigoc3RkZXJyLCBcIlxcbmxpdCB0cmVlOiBzZW50ICVsZFwiLCBzLT5iaXRzX3NlbnQpKTtcblxuICBzZW5kX3RyZWUocywgcy5keW5fZHRyZWUsIGRjb2RlcyAtIDEpOyAvKiBkaXN0YW5jZSB0cmVlICovXG4gIC8vVHJhY2V2KChzdGRlcnIsIFwiXFxuZGlzdCB0cmVlOiBzZW50ICVsZFwiLCBzLT5iaXRzX3NlbnQpKTtcbn07XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDaGVjayBpZiB0aGUgZGF0YSB0eXBlIGlzIFRFWFQgb3IgQklOQVJZLCB1c2luZyB0aGUgZm9sbG93aW5nIGFsZ29yaXRobTpcbiAqIC0gVEVYVCBpZiB0aGUgdHdvIGNvbmRpdGlvbnMgYmVsb3cgYXJlIHNhdGlzZmllZDpcbiAqICAgIGEpIFRoZXJlIGFyZSBubyBub24tcG9ydGFibGUgY29udHJvbCBjaGFyYWN0ZXJzIGJlbG9uZ2luZyB0byB0aGVcbiAqICAgICAgIFwiYmxvY2sgbGlzdFwiICgwLi42LCAxNC4uMjUsIDI4Li4zMSkuXG4gKiAgICBiKSBUaGVyZSBpcyBhdCBsZWFzdCBvbmUgcHJpbnRhYmxlIGNoYXJhY3RlciBiZWxvbmdpbmcgdG8gdGhlXG4gKiAgICAgICBcImFsbG93IGxpc3RcIiAoOSB7VEFCfSwgMTAge0xGfSwgMTMge0NSfSwgMzIuLjI1NSkuXG4gKiAtIEJJTkFSWSBvdGhlcndpc2UuXG4gKiAtIFRoZSBmb2xsb3dpbmcgcGFydGlhbGx5LXBvcnRhYmxlIGNvbnRyb2wgY2hhcmFjdGVycyBmb3JtIGFcbiAqICAgXCJncmF5IGxpc3RcIiB0aGF0IGlzIGlnbm9yZWQgaW4gdGhpcyBkZXRlY3Rpb24gYWxnb3JpdGhtOlxuICogICAoNyB7QkVMfSwgOCB7QlN9LCAxMSB7VlR9LCAxMiB7RkZ9LCAyNiB7U1VCfSwgMjcge0VTQ30pLlxuICogSU4gYXNzZXJ0aW9uOiB0aGUgZmllbGRzIEZyZXEgb2YgZHluX2x0cmVlIGFyZSBzZXQuXG4gKi9cbmNvbnN0IGRldGVjdF9kYXRhX3R5cGUgPSAocykgPT4ge1xuICAvKiBibG9ja19tYXNrIGlzIHRoZSBiaXQgbWFzayBvZiBibG9jay1saXN0ZWQgYnl0ZXNcbiAgICogc2V0IGJpdHMgMC4uNiwgMTQuLjI1LCBhbmQgMjguLjMxXG4gICAqIDB4ZjNmZmMwN2YgPSBiaW5hcnkgMTExMTAwMTExMTExMTExMTExMDAwMDAwMDExMTExMTFcbiAgICovXG4gIGxldCBibG9ja19tYXNrID0gMHhmM2ZmYzA3ZjtcbiAgbGV0IG47XG5cbiAgLyogQ2hlY2sgZm9yIG5vbi10ZXh0dWFsIChcImJsb2NrLWxpc3RlZFwiKSBieXRlcy4gKi9cbiAgZm9yIChuID0gMDsgbiA8PSAzMTsgbisrLCBibG9ja19tYXNrID4+Pj0gMSkge1xuICAgIGlmICgoYmxvY2tfbWFzayAmIDEpICYmIChzLmR5bl9sdHJlZVtuICogMl0vKi5GcmVxKi8gIT09IDApKSB7XG4gICAgICByZXR1cm4gWl9CSU5BUlk7XG4gICAgfVxuICB9XG5cbiAgLyogQ2hlY2sgZm9yIHRleHR1YWwgKFwiYWxsb3ctbGlzdGVkXCIpIGJ5dGVzLiAqL1xuICBpZiAocy5keW5fbHRyZWVbOSAqIDJdLyouRnJlcSovICE9PSAwIHx8IHMuZHluX2x0cmVlWzEwICogMl0vKi5GcmVxKi8gIT09IDAgfHxcbiAgICAgIHMuZHluX2x0cmVlWzEzICogMl0vKi5GcmVxKi8gIT09IDApIHtcbiAgICByZXR1cm4gWl9URVhUO1xuICB9XG4gIGZvciAobiA9IDMyOyBuIDwgTElURVJBTFMkMTsgbisrKSB7XG4gICAgaWYgKHMuZHluX2x0cmVlW24gKiAyXS8qLkZyZXEqLyAhPT0gMCkge1xuICAgICAgcmV0dXJuIFpfVEVYVDtcbiAgICB9XG4gIH1cblxuICAvKiBUaGVyZSBhcmUgbm8gXCJibG9jay1saXN0ZWRcIiBvciBcImFsbG93LWxpc3RlZFwiIGJ5dGVzOlxuICAgKiB0aGlzIHN0cmVhbSBlaXRoZXIgaXMgZW1wdHkgb3IgaGFzIHRvbGVyYXRlZCAoXCJncmF5LWxpc3RlZFwiKSBieXRlcyBvbmx5LlxuICAgKi9cbiAgcmV0dXJuIFpfQklOQVJZO1xufTtcblxuXG5sZXQgc3RhdGljX2luaXRfZG9uZSA9IGZhbHNlO1xuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEluaXRpYWxpemUgdGhlIHRyZWUgZGF0YSBzdHJ1Y3R1cmVzIGZvciBhIG5ldyB6bGliIHN0cmVhbS5cbiAqL1xuY29uc3QgX3RyX2luaXQkMSA9IChzKSA9Plxue1xuXG4gIGlmICghc3RhdGljX2luaXRfZG9uZSkge1xuICAgIHRyX3N0YXRpY19pbml0KCk7XG4gICAgc3RhdGljX2luaXRfZG9uZSA9IHRydWU7XG4gIH1cblxuICBzLmxfZGVzYyAgPSBuZXcgVHJlZURlc2Mocy5keW5fbHRyZWUsIHN0YXRpY19sX2Rlc2MpO1xuICBzLmRfZGVzYyAgPSBuZXcgVHJlZURlc2Mocy5keW5fZHRyZWUsIHN0YXRpY19kX2Rlc2MpO1xuICBzLmJsX2Rlc2MgPSBuZXcgVHJlZURlc2Mocy5ibF90cmVlLCBzdGF0aWNfYmxfZGVzYyk7XG5cbiAgcy5iaV9idWYgPSAwO1xuICBzLmJpX3ZhbGlkID0gMDtcblxuICAvKiBJbml0aWFsaXplIHRoZSBmaXJzdCBibG9jayBvZiB0aGUgZmlyc3QgZmlsZTogKi9cbiAgaW5pdF9ibG9jayhzKTtcbn07XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBTZW5kIGEgc3RvcmVkIGJsb2NrXG4gKi9cbmNvbnN0IF90cl9zdG9yZWRfYmxvY2skMSA9IChzLCBidWYsIHN0b3JlZF9sZW4sIGxhc3QpID0+IHtcbi8vRGVmbGF0ZVN0YXRlICpzO1xuLy9jaGFyZiAqYnVmOyAgICAgICAvKiBpbnB1dCBibG9jayAqL1xuLy91bGcgc3RvcmVkX2xlbjsgICAvKiBsZW5ndGggb2YgaW5wdXQgYmxvY2sgKi9cbi8vaW50IGxhc3Q7ICAgICAgICAgLyogb25lIGlmIHRoaXMgaXMgdGhlIGxhc3QgYmxvY2sgZm9yIGEgZmlsZSAqL1xuXG4gIHNlbmRfYml0cyhzLCAoU1RPUkVEX0JMT0NLIDw8IDEpICsgKGxhc3QgPyAxIDogMCksIDMpOyAgICAvKiBzZW5kIGJsb2NrIHR5cGUgKi9cbiAgYmlfd2luZHVwKHMpOyAgICAgICAgLyogYWxpZ24gb24gYnl0ZSBib3VuZGFyeSAqL1xuICBwdXRfc2hvcnQocywgc3RvcmVkX2xlbik7XG4gIHB1dF9zaG9ydChzLCB+c3RvcmVkX2xlbik7XG4gIGlmIChzdG9yZWRfbGVuKSB7XG4gICAgcy5wZW5kaW5nX2J1Zi5zZXQocy53aW5kb3cuc3ViYXJyYXkoYnVmLCBidWYgKyBzdG9yZWRfbGVuKSwgcy5wZW5kaW5nKTtcbiAgfVxuICBzLnBlbmRpbmcgKz0gc3RvcmVkX2xlbjtcbn07XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBTZW5kIG9uZSBlbXB0eSBzdGF0aWMgYmxvY2sgdG8gZ2l2ZSBlbm91Z2ggbG9va2FoZWFkIGZvciBpbmZsYXRlLlxuICogVGhpcyB0YWtlcyAxMCBiaXRzLCBvZiB3aGljaCA3IG1heSByZW1haW4gaW4gdGhlIGJpdCBidWZmZXIuXG4gKi9cbmNvbnN0IF90cl9hbGlnbiQxID0gKHMpID0+IHtcbiAgc2VuZF9iaXRzKHMsIFNUQVRJQ19UUkVFUyA8PCAxLCAzKTtcbiAgc2VuZF9jb2RlKHMsIEVORF9CTE9DSywgc3RhdGljX2x0cmVlKTtcbiAgYmlfZmx1c2gocyk7XG59O1xuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogRGV0ZXJtaW5lIHRoZSBiZXN0IGVuY29kaW5nIGZvciB0aGUgY3VycmVudCBibG9jazogZHluYW1pYyB0cmVlcywgc3RhdGljXG4gKiB0cmVlcyBvciBzdG9yZSwgYW5kIHdyaXRlIG91dCB0aGUgZW5jb2RlZCBibG9jay5cbiAqL1xuY29uc3QgX3RyX2ZsdXNoX2Jsb2NrJDEgPSAocywgYnVmLCBzdG9yZWRfbGVuLCBsYXN0KSA9PiB7XG4vL0RlZmxhdGVTdGF0ZSAqcztcbi8vY2hhcmYgKmJ1ZjsgICAgICAgLyogaW5wdXQgYmxvY2ssIG9yIE5VTEwgaWYgdG9vIG9sZCAqL1xuLy91bGcgc3RvcmVkX2xlbjsgICAvKiBsZW5ndGggb2YgaW5wdXQgYmxvY2sgKi9cbi8vaW50IGxhc3Q7ICAgICAgICAgLyogb25lIGlmIHRoaXMgaXMgdGhlIGxhc3QgYmxvY2sgZm9yIGEgZmlsZSAqL1xuXG4gIGxldCBvcHRfbGVuYiwgc3RhdGljX2xlbmI7ICAvKiBvcHRfbGVuIGFuZCBzdGF0aWNfbGVuIGluIGJ5dGVzICovXG4gIGxldCBtYXhfYmxpbmRleCA9IDA7ICAgICAgICAvKiBpbmRleCBvZiBsYXN0IGJpdCBsZW5ndGggY29kZSBvZiBub24gemVybyBmcmVxICovXG5cbiAgLyogQnVpbGQgdGhlIEh1ZmZtYW4gdHJlZXMgdW5sZXNzIGEgc3RvcmVkIGJsb2NrIGlzIGZvcmNlZCAqL1xuICBpZiAocy5sZXZlbCA+IDApIHtcblxuICAgIC8qIENoZWNrIGlmIHRoZSBmaWxlIGlzIGJpbmFyeSBvciB0ZXh0ICovXG4gICAgaWYgKHMuc3RybS5kYXRhX3R5cGUgPT09IFpfVU5LTk9XTiQxKSB7XG4gICAgICBzLnN0cm0uZGF0YV90eXBlID0gZGV0ZWN0X2RhdGFfdHlwZShzKTtcbiAgICB9XG5cbiAgICAvKiBDb25zdHJ1Y3QgdGhlIGxpdGVyYWwgYW5kIGRpc3RhbmNlIHRyZWVzICovXG4gICAgYnVpbGRfdHJlZShzLCBzLmxfZGVzYyk7XG4gICAgLy8gVHJhY2V2KChzdGRlcnIsIFwiXFxubGl0IGRhdGE6IGR5biAlbGQsIHN0YXQgJWxkXCIsIHMtPm9wdF9sZW4sXG4gICAgLy8gICAgICAgIHMtPnN0YXRpY19sZW4pKTtcblxuICAgIGJ1aWxkX3RyZWUocywgcy5kX2Rlc2MpO1xuICAgIC8vIFRyYWNldigoc3RkZXJyLCBcIlxcbmRpc3QgZGF0YTogZHluICVsZCwgc3RhdCAlbGRcIiwgcy0+b3B0X2xlbixcbiAgICAvLyAgICAgICAgcy0+c3RhdGljX2xlbikpO1xuICAgIC8qIEF0IHRoaXMgcG9pbnQsIG9wdF9sZW4gYW5kIHN0YXRpY19sZW4gYXJlIHRoZSB0b3RhbCBiaXQgbGVuZ3RocyBvZlxuICAgICAqIHRoZSBjb21wcmVzc2VkIGJsb2NrIGRhdGEsIGV4Y2x1ZGluZyB0aGUgdHJlZSByZXByZXNlbnRhdGlvbnMuXG4gICAgICovXG5cbiAgICAvKiBCdWlsZCB0aGUgYml0IGxlbmd0aCB0cmVlIGZvciB0aGUgYWJvdmUgdHdvIHRyZWVzLCBhbmQgZ2V0IHRoZSBpbmRleFxuICAgICAqIGluIGJsX29yZGVyIG9mIHRoZSBsYXN0IGJpdCBsZW5ndGggY29kZSB0byBzZW5kLlxuICAgICAqL1xuICAgIG1heF9ibGluZGV4ID0gYnVpbGRfYmxfdHJlZShzKTtcblxuICAgIC8qIERldGVybWluZSB0aGUgYmVzdCBlbmNvZGluZy4gQ29tcHV0ZSB0aGUgYmxvY2sgbGVuZ3RocyBpbiBieXRlcy4gKi9cbiAgICBvcHRfbGVuYiA9IChzLm9wdF9sZW4gKyAzICsgNykgPj4+IDM7XG4gICAgc3RhdGljX2xlbmIgPSAocy5zdGF0aWNfbGVuICsgMyArIDcpID4+PiAzO1xuXG4gICAgLy8gVHJhY2V2KChzdGRlcnIsIFwiXFxub3B0ICVsdSglbHUpIHN0YXQgJWx1KCVsdSkgc3RvcmVkICVsdSBsaXQgJXUgXCIsXG4gICAgLy8gICAgICAgIG9wdF9sZW5iLCBzLT5vcHRfbGVuLCBzdGF0aWNfbGVuYiwgcy0+c3RhdGljX2xlbiwgc3RvcmVkX2xlbixcbiAgICAvLyAgICAgICAgcy0+c3ltX25leHQgLyAzKSk7XG5cbiAgICBpZiAoc3RhdGljX2xlbmIgPD0gb3B0X2xlbmIpIHsgb3B0X2xlbmIgPSBzdGF0aWNfbGVuYjsgfVxuXG4gIH0gZWxzZSB7XG4gICAgLy8gQXNzZXJ0KGJ1ZiAhPSAoY2hhciopMCwgXCJsb3N0IGJ1ZlwiKTtcbiAgICBvcHRfbGVuYiA9IHN0YXRpY19sZW5iID0gc3RvcmVkX2xlbiArIDU7IC8qIGZvcmNlIGEgc3RvcmVkIGJsb2NrICovXG4gIH1cblxuICBpZiAoKHN0b3JlZF9sZW4gKyA0IDw9IG9wdF9sZW5iKSAmJiAoYnVmICE9PSAtMSkpIHtcbiAgICAvKiA0OiB0d28gd29yZHMgZm9yIHRoZSBsZW5ndGhzICovXG5cbiAgICAvKiBUaGUgdGVzdCBidWYgIT0gTlVMTCBpcyBvbmx5IG5lY2Vzc2FyeSBpZiBMSVRfQlVGU0laRSA+IFdTSVpFLlxuICAgICAqIE90aGVyd2lzZSB3ZSBjYW4ndCBoYXZlIHByb2Nlc3NlZCBtb3JlIHRoYW4gV1NJWkUgaW5wdXQgYnl0ZXMgc2luY2VcbiAgICAgKiB0aGUgbGFzdCBibG9jayBmbHVzaCwgYmVjYXVzZSBjb21wcmVzc2lvbiB3b3VsZCBoYXZlIGJlZW5cbiAgICAgKiBzdWNjZXNzZnVsLiBJZiBMSVRfQlVGU0laRSA8PSBXU0laRSwgaXQgaXMgbmV2ZXIgdG9vIGxhdGUgdG9cbiAgICAgKiB0cmFuc2Zvcm0gYSBibG9jayBpbnRvIGEgc3RvcmVkIGJsb2NrLlxuICAgICAqL1xuICAgIF90cl9zdG9yZWRfYmxvY2skMShzLCBidWYsIHN0b3JlZF9sZW4sIGxhc3QpO1xuXG4gIH0gZWxzZSBpZiAocy5zdHJhdGVneSA9PT0gWl9GSVhFRCQxIHx8IHN0YXRpY19sZW5iID09PSBvcHRfbGVuYikge1xuXG4gICAgc2VuZF9iaXRzKHMsIChTVEFUSUNfVFJFRVMgPDwgMSkgKyAobGFzdCA/IDEgOiAwKSwgMyk7XG4gICAgY29tcHJlc3NfYmxvY2socywgc3RhdGljX2x0cmVlLCBzdGF0aWNfZHRyZWUpO1xuXG4gIH0gZWxzZSB7XG4gICAgc2VuZF9iaXRzKHMsIChEWU5fVFJFRVMgPDwgMSkgKyAobGFzdCA/IDEgOiAwKSwgMyk7XG4gICAgc2VuZF9hbGxfdHJlZXMocywgcy5sX2Rlc2MubWF4X2NvZGUgKyAxLCBzLmRfZGVzYy5tYXhfY29kZSArIDEsIG1heF9ibGluZGV4ICsgMSk7XG4gICAgY29tcHJlc3NfYmxvY2socywgcy5keW5fbHRyZWUsIHMuZHluX2R0cmVlKTtcbiAgfVxuICAvLyBBc3NlcnQgKHMtPmNvbXByZXNzZWRfbGVuID09IHMtPmJpdHNfc2VudCwgXCJiYWQgY29tcHJlc3NlZCBzaXplXCIpO1xuICAvKiBUaGUgYWJvdmUgY2hlY2sgaXMgbWFkZSBtb2QgMl4zMiwgZm9yIGZpbGVzIGxhcmdlciB0aGFuIDUxMiBNQlxuICAgKiBhbmQgdUxvbmcgaW1wbGVtZW50ZWQgb24gMzIgYml0cy5cbiAgICovXG4gIGluaXRfYmxvY2socyk7XG5cbiAgaWYgKGxhc3QpIHtcbiAgICBiaV93aW5kdXAocyk7XG4gIH1cbiAgLy8gVHJhY2V2KChzdGRlcnIsXCJcXG5jb21wcmxlbiAlbHUoJWx1KSBcIiwgcy0+Y29tcHJlc3NlZF9sZW4+PjMsXG4gIC8vICAgICAgIHMtPmNvbXByZXNzZWRfbGVuLTcqbGFzdCkpO1xufTtcblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBTYXZlIHRoZSBtYXRjaCBpbmZvIGFuZCB0YWxseSB0aGUgZnJlcXVlbmN5IGNvdW50cy4gUmV0dXJuIHRydWUgaWZcbiAqIHRoZSBjdXJyZW50IGJsb2NrIG11c3QgYmUgZmx1c2hlZC5cbiAqL1xuY29uc3QgX3RyX3RhbGx5JDEgPSAocywgZGlzdCwgbGMpID0+IHtcbi8vICAgIGRlZmxhdGVfc3RhdGUgKnM7XG4vLyAgICB1bnNpZ25lZCBkaXN0OyAgLyogZGlzdGFuY2Ugb2YgbWF0Y2hlZCBzdHJpbmcgKi9cbi8vICAgIHVuc2lnbmVkIGxjOyAgICAvKiBtYXRjaCBsZW5ndGgtTUlOX01BVENIIG9yIHVubWF0Y2hlZCBjaGFyIChpZiBkaXN0PT0wKSAqL1xuXG4gIHMucGVuZGluZ19idWZbcy5zeW1fYnVmICsgcy5zeW1fbmV4dCsrXSA9IGRpc3Q7XG4gIHMucGVuZGluZ19idWZbcy5zeW1fYnVmICsgcy5zeW1fbmV4dCsrXSA9IGRpc3QgPj4gODtcbiAgcy5wZW5kaW5nX2J1ZltzLnN5bV9idWYgKyBzLnN5bV9uZXh0KytdID0gbGM7XG4gIGlmIChkaXN0ID09PSAwKSB7XG4gICAgLyogbGMgaXMgdGhlIHVubWF0Y2hlZCBjaGFyICovXG4gICAgcy5keW5fbHRyZWVbbGMgKiAyXS8qLkZyZXEqLysrO1xuICB9IGVsc2Uge1xuICAgIHMubWF0Y2hlcysrO1xuICAgIC8qIEhlcmUsIGxjIGlzIHRoZSBtYXRjaCBsZW5ndGggLSBNSU5fTUFUQ0ggKi9cbiAgICBkaXN0LS07ICAgICAgICAgICAgIC8qIGRpc3QgPSBtYXRjaCBkaXN0YW5jZSAtIDEgKi9cbiAgICAvL0Fzc2VydCgodXNoKWRpc3QgPCAodXNoKU1BWF9ESVNUKHMpICYmXG4gICAgLy8gICAgICAgKHVzaClsYyA8PSAodXNoKShNQVhfTUFUQ0gtTUlOX01BVENIKSAmJlxuICAgIC8vICAgICAgICh1c2gpZF9jb2RlKGRpc3QpIDwgKHVzaClEX0NPREVTLCAgXCJfdHJfdGFsbHk6IGJhZCBtYXRjaFwiKTtcblxuICAgIHMuZHluX2x0cmVlWyhfbGVuZ3RoX2NvZGVbbGNdICsgTElURVJBTFMkMSArIDEpICogMl0vKi5GcmVxKi8rKztcbiAgICBzLmR5bl9kdHJlZVtkX2NvZGUoZGlzdCkgKiAyXS8qLkZyZXEqLysrO1xuICB9XG5cbiAgcmV0dXJuIChzLnN5bV9uZXh0ID09PSBzLnN5bV9lbmQpO1xufTtcblxudmFyIF90cl9pbml0XzEgID0gX3RyX2luaXQkMTtcbnZhciBfdHJfc3RvcmVkX2Jsb2NrXzEgPSBfdHJfc3RvcmVkX2Jsb2NrJDE7XG52YXIgX3RyX2ZsdXNoX2Jsb2NrXzEgID0gX3RyX2ZsdXNoX2Jsb2NrJDE7XG52YXIgX3RyX3RhbGx5XzEgPSBfdHJfdGFsbHkkMTtcbnZhciBfdHJfYWxpZ25fMSA9IF90cl9hbGlnbiQxO1xuXG52YXIgdHJlZXMgPSB7XG5cdF90cl9pbml0OiBfdHJfaW5pdF8xLFxuXHRfdHJfc3RvcmVkX2Jsb2NrOiBfdHJfc3RvcmVkX2Jsb2NrXzEsXG5cdF90cl9mbHVzaF9ibG9jazogX3RyX2ZsdXNoX2Jsb2NrXzEsXG5cdF90cl90YWxseTogX3RyX3RhbGx5XzEsXG5cdF90cl9hbGlnbjogX3RyX2FsaWduXzFcbn07XG5cbi8vIE5vdGU6IGFkbGVyMzIgdGFrZXMgMTIlIGZvciBsZXZlbCAwIGFuZCAyJSBmb3IgbGV2ZWwgNi5cbi8vIEl0IGlzbid0IHdvcnRoIGl0IHRvIG1ha2UgYWRkaXRpb25hbCBvcHRpbWl6YXRpb25zIGFzIGluIG9yaWdpbmFsLlxuLy8gU21hbGwgc2l6ZSBpcyBwcmVmZXJhYmxlLlxuXG4vLyAoQykgMTk5NS0yMDEzIEplYW4tbG91cCBHYWlsbHkgYW5kIE1hcmsgQWRsZXJcbi8vIChDKSAyMDE0LTIwMTcgVml0YWx5IFB1enJpbiBhbmQgQW5kcmV5IFR1cGl0c2luXG4vL1xuLy8gVGhpcyBzb2Z0d2FyZSBpcyBwcm92aWRlZCAnYXMtaXMnLCB3aXRob3V0IGFueSBleHByZXNzIG9yIGltcGxpZWRcbi8vIHdhcnJhbnR5LiBJbiBubyBldmVudCB3aWxsIHRoZSBhdXRob3JzIGJlIGhlbGQgbGlhYmxlIGZvciBhbnkgZGFtYWdlc1xuLy8gYXJpc2luZyBmcm9tIHRoZSB1c2Ugb2YgdGhpcyBzb2Z0d2FyZS5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGdyYW50ZWQgdG8gYW55b25lIHRvIHVzZSB0aGlzIHNvZnR3YXJlIGZvciBhbnkgcHVycG9zZSxcbi8vIGluY2x1ZGluZyBjb21tZXJjaWFsIGFwcGxpY2F0aW9ucywgYW5kIHRvIGFsdGVyIGl0IGFuZCByZWRpc3RyaWJ1dGUgaXRcbi8vIGZyZWVseSwgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIHJlc3RyaWN0aW9uczpcbi8vXG4vLyAxLiBUaGUgb3JpZ2luIG9mIHRoaXMgc29mdHdhcmUgbXVzdCBub3QgYmUgbWlzcmVwcmVzZW50ZWQ7IHlvdSBtdXN0IG5vdFxuLy8gICBjbGFpbSB0aGF0IHlvdSB3cm90ZSB0aGUgb3JpZ2luYWwgc29mdHdhcmUuIElmIHlvdSB1c2UgdGhpcyBzb2Z0d2FyZVxuLy8gICBpbiBhIHByb2R1Y3QsIGFuIGFja25vd2xlZGdtZW50IGluIHRoZSBwcm9kdWN0IGRvY3VtZW50YXRpb24gd291bGQgYmVcbi8vICAgYXBwcmVjaWF0ZWQgYnV0IGlzIG5vdCByZXF1aXJlZC5cbi8vIDIuIEFsdGVyZWQgc291cmNlIHZlcnNpb25zIG11c3QgYmUgcGxhaW5seSBtYXJrZWQgYXMgc3VjaCwgYW5kIG11c3Qgbm90IGJlXG4vLyAgIG1pc3JlcHJlc2VudGVkIGFzIGJlaW5nIHRoZSBvcmlnaW5hbCBzb2Z0d2FyZS5cbi8vIDMuIFRoaXMgbm90aWNlIG1heSBub3QgYmUgcmVtb3ZlZCBvciBhbHRlcmVkIGZyb20gYW55IHNvdXJjZSBkaXN0cmlidXRpb24uXG5cbmNvbnN0IGFkbGVyMzIgPSAoYWRsZXIsIGJ1ZiwgbGVuLCBwb3MpID0+IHtcbiAgbGV0IHMxID0gKGFkbGVyICYgMHhmZmZmKSB8MCxcbiAgICAgIHMyID0gKChhZGxlciA+Pj4gMTYpICYgMHhmZmZmKSB8MCxcbiAgICAgIG4gPSAwO1xuXG4gIHdoaWxlIChsZW4gIT09IDApIHtcbiAgICAvLyBTZXQgbGltaXQgfiB0d2ljZSBsZXNzIHRoYW4gNTU1MiwgdG8ga2VlcFxuICAgIC8vIHMyIGluIDMxLWJpdHMsIGJlY2F1c2Ugd2UgZm9yY2Ugc2lnbmVkIGludHMuXG4gICAgLy8gaW4gb3RoZXIgY2FzZSAlPSB3aWxsIGZhaWwuXG4gICAgbiA9IGxlbiA+IDIwMDAgPyAyMDAwIDogbGVuO1xuICAgIGxlbiAtPSBuO1xuXG4gICAgZG8ge1xuICAgICAgczEgPSAoczEgKyBidWZbcG9zKytdKSB8MDtcbiAgICAgIHMyID0gKHMyICsgczEpIHwwO1xuICAgIH0gd2hpbGUgKC0tbik7XG5cbiAgICBzMSAlPSA2NTUyMTtcbiAgICBzMiAlPSA2NTUyMTtcbiAgfVxuXG4gIHJldHVybiAoczEgfCAoczIgPDwgMTYpKSB8MDtcbn07XG5cblxudmFyIGFkbGVyMzJfMSA9IGFkbGVyMzI7XG5cbi8vIE5vdGU6IHdlIGNhbid0IGdldCBzaWduaWZpY2FudCBzcGVlZCBib29zdCBoZXJlLlxuLy8gU28gd3JpdGUgY29kZSB0byBtaW5pbWl6ZSBzaXplIC0gbm8gcHJlZ2VuZXJhdGVkIHRhYmxlc1xuLy8gYW5kIGFycmF5IHRvb2xzIGRlcGVuZGVuY2llcy5cblxuLy8gKEMpIDE5OTUtMjAxMyBKZWFuLWxvdXAgR2FpbGx5IGFuZCBNYXJrIEFkbGVyXG4vLyAoQykgMjAxNC0yMDE3IFZpdGFseSBQdXpyaW4gYW5kIEFuZHJleSBUdXBpdHNpblxuLy9cbi8vIFRoaXMgc29mdHdhcmUgaXMgcHJvdmlkZWQgJ2FzLWlzJywgd2l0aG91dCBhbnkgZXhwcmVzcyBvciBpbXBsaWVkXG4vLyB3YXJyYW50eS4gSW4gbm8gZXZlbnQgd2lsbCB0aGUgYXV0aG9ycyBiZSBoZWxkIGxpYWJsZSBmb3IgYW55IGRhbWFnZXNcbi8vIGFyaXNpbmcgZnJvbSB0aGUgdXNlIG9mIHRoaXMgc29mdHdhcmUuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBncmFudGVkIHRvIGFueW9uZSB0byB1c2UgdGhpcyBzb2Z0d2FyZSBmb3IgYW55IHB1cnBvc2UsXG4vLyBpbmNsdWRpbmcgY29tbWVyY2lhbCBhcHBsaWNhdGlvbnMsIGFuZCB0byBhbHRlciBpdCBhbmQgcmVkaXN0cmlidXRlIGl0XG4vLyBmcmVlbHksIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyByZXN0cmljdGlvbnM6XG4vL1xuLy8gMS4gVGhlIG9yaWdpbiBvZiB0aGlzIHNvZnR3YXJlIG11c3Qgbm90IGJlIG1pc3JlcHJlc2VudGVkOyB5b3UgbXVzdCBub3Rcbi8vICAgY2xhaW0gdGhhdCB5b3Ugd3JvdGUgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLiBJZiB5b3UgdXNlIHRoaXMgc29mdHdhcmVcbi8vICAgaW4gYSBwcm9kdWN0LCBhbiBhY2tub3dsZWRnbWVudCBpbiB0aGUgcHJvZHVjdCBkb2N1bWVudGF0aW9uIHdvdWxkIGJlXG4vLyAgIGFwcHJlY2lhdGVkIGJ1dCBpcyBub3QgcmVxdWlyZWQuXG4vLyAyLiBBbHRlcmVkIHNvdXJjZSB2ZXJzaW9ucyBtdXN0IGJlIHBsYWlubHkgbWFya2VkIGFzIHN1Y2gsIGFuZCBtdXN0IG5vdCBiZVxuLy8gICBtaXNyZXByZXNlbnRlZCBhcyBiZWluZyB0aGUgb3JpZ2luYWwgc29mdHdhcmUuXG4vLyAzLiBUaGlzIG5vdGljZSBtYXkgbm90IGJlIHJlbW92ZWQgb3IgYWx0ZXJlZCBmcm9tIGFueSBzb3VyY2UgZGlzdHJpYnV0aW9uLlxuXG4vLyBVc2Ugb3JkaW5hcnkgYXJyYXksIHNpbmNlIHVudHlwZWQgbWFrZXMgbm8gYm9vc3QgaGVyZVxuY29uc3QgbWFrZVRhYmxlID0gKCkgPT4ge1xuICBsZXQgYywgdGFibGUgPSBbXTtcblxuICBmb3IgKHZhciBuID0gMDsgbiA8IDI1NjsgbisrKSB7XG4gICAgYyA9IG47XG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCA4OyBrKyspIHtcbiAgICAgIGMgPSAoKGMgJiAxKSA/ICgweEVEQjg4MzIwIF4gKGMgPj4+IDEpKSA6IChjID4+PiAxKSk7XG4gICAgfVxuICAgIHRhYmxlW25dID0gYztcbiAgfVxuXG4gIHJldHVybiB0YWJsZTtcbn07XG5cbi8vIENyZWF0ZSB0YWJsZSBvbiBsb2FkLiBKdXN0IDI1NSBzaWduZWQgbG9uZ3MuIE5vdCBhIHByb2JsZW0uXG5jb25zdCBjcmNUYWJsZSA9IG5ldyBVaW50MzJBcnJheShtYWtlVGFibGUoKSk7XG5cblxuY29uc3QgY3JjMzIgPSAoY3JjLCBidWYsIGxlbiwgcG9zKSA9PiB7XG4gIGNvbnN0IHQgPSBjcmNUYWJsZTtcbiAgY29uc3QgZW5kID0gcG9zICsgbGVuO1xuXG4gIGNyYyBePSAtMTtcblxuICBmb3IgKGxldCBpID0gcG9zOyBpIDwgZW5kOyBpKyspIHtcbiAgICBjcmMgPSAoY3JjID4+PiA4KSBeIHRbKGNyYyBeIGJ1ZltpXSkgJiAweEZGXTtcbiAgfVxuXG4gIHJldHVybiAoY3JjIF4gKC0xKSk7IC8vID4+PiAwO1xufTtcblxuXG52YXIgY3JjMzJfMSA9IGNyYzMyO1xuXG4vLyAoQykgMTk5NS0yMDEzIEplYW4tbG91cCBHYWlsbHkgYW5kIE1hcmsgQWRsZXJcbi8vIChDKSAyMDE0LTIwMTcgVml0YWx5IFB1enJpbiBhbmQgQW5kcmV5IFR1cGl0c2luXG4vL1xuLy8gVGhpcyBzb2Z0d2FyZSBpcyBwcm92aWRlZCAnYXMtaXMnLCB3aXRob3V0IGFueSBleHByZXNzIG9yIGltcGxpZWRcbi8vIHdhcnJhbnR5LiBJbiBubyBldmVudCB3aWxsIHRoZSBhdXRob3JzIGJlIGhlbGQgbGlhYmxlIGZvciBhbnkgZGFtYWdlc1xuLy8gYXJpc2luZyBmcm9tIHRoZSB1c2Ugb2YgdGhpcyBzb2Z0d2FyZS5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGdyYW50ZWQgdG8gYW55b25lIHRvIHVzZSB0aGlzIHNvZnR3YXJlIGZvciBhbnkgcHVycG9zZSxcbi8vIGluY2x1ZGluZyBjb21tZXJjaWFsIGFwcGxpY2F0aW9ucywgYW5kIHRvIGFsdGVyIGl0IGFuZCByZWRpc3RyaWJ1dGUgaXRcbi8vIGZyZWVseSwgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIHJlc3RyaWN0aW9uczpcbi8vXG4vLyAxLiBUaGUgb3JpZ2luIG9mIHRoaXMgc29mdHdhcmUgbXVzdCBub3QgYmUgbWlzcmVwcmVzZW50ZWQ7IHlvdSBtdXN0IG5vdFxuLy8gICBjbGFpbSB0aGF0IHlvdSB3cm90ZSB0aGUgb3JpZ2luYWwgc29mdHdhcmUuIElmIHlvdSB1c2UgdGhpcyBzb2Z0d2FyZVxuLy8gICBpbiBhIHByb2R1Y3QsIGFuIGFja25vd2xlZGdtZW50IGluIHRoZSBwcm9kdWN0IGRvY3VtZW50YXRpb24gd291bGQgYmVcbi8vICAgYXBwcmVjaWF0ZWQgYnV0IGlzIG5vdCByZXF1aXJlZC5cbi8vIDIuIEFsdGVyZWQgc291cmNlIHZlcnNpb25zIG11c3QgYmUgcGxhaW5seSBtYXJrZWQgYXMgc3VjaCwgYW5kIG11c3Qgbm90IGJlXG4vLyAgIG1pc3JlcHJlc2VudGVkIGFzIGJlaW5nIHRoZSBvcmlnaW5hbCBzb2Z0d2FyZS5cbi8vIDMuIFRoaXMgbm90aWNlIG1heSBub3QgYmUgcmVtb3ZlZCBvciBhbHRlcmVkIGZyb20gYW55IHNvdXJjZSBkaXN0cmlidXRpb24uXG5cbnZhciBtZXNzYWdlcyA9IHtcbiAgMjogICAgICAnbmVlZCBkaWN0aW9uYXJ5JywgICAgIC8qIFpfTkVFRF9ESUNUICAgICAgIDIgICovXG4gIDE6ICAgICAgJ3N0cmVhbSBlbmQnLCAgICAgICAgICAvKiBaX1NUUkVBTV9FTkQgICAgICAxICAqL1xuICAwOiAgICAgICcnLCAgICAgICAgICAgICAgICAgICAgLyogWl9PSyAgICAgICAgICAgICAgMCAgKi9cbiAgJy0xJzogICAnZmlsZSBlcnJvcicsICAgICAgICAgIC8qIFpfRVJSTk8gICAgICAgICAoLTEpICovXG4gICctMic6ICAgJ3N0cmVhbSBlcnJvcicsICAgICAgICAvKiBaX1NUUkVBTV9FUlJPUiAgKC0yKSAqL1xuICAnLTMnOiAgICdkYXRhIGVycm9yJywgICAgICAgICAgLyogWl9EQVRBX0VSUk9SICAgICgtMykgKi9cbiAgJy00JzogICAnaW5zdWZmaWNpZW50IG1lbW9yeScsIC8qIFpfTUVNX0VSUk9SICAgICAoLTQpICovXG4gICctNSc6ICAgJ2J1ZmZlciBlcnJvcicsICAgICAgICAvKiBaX0JVRl9FUlJPUiAgICAgKC01KSAqL1xuICAnLTYnOiAgICdpbmNvbXBhdGlibGUgdmVyc2lvbicgLyogWl9WRVJTSU9OX0VSUk9SICgtNikgKi9cbn07XG5cbi8vIChDKSAxOTk1LTIwMTMgSmVhbi1sb3VwIEdhaWxseSBhbmQgTWFyayBBZGxlclxuLy8gKEMpIDIwMTQtMjAxNyBWaXRhbHkgUHV6cmluIGFuZCBBbmRyZXkgVHVwaXRzaW5cbi8vXG4vLyBUaGlzIHNvZnR3YXJlIGlzIHByb3ZpZGVkICdhcy1pcycsIHdpdGhvdXQgYW55IGV4cHJlc3Mgb3IgaW1wbGllZFxuLy8gd2FycmFudHkuIEluIG5vIGV2ZW50IHdpbGwgdGhlIGF1dGhvcnMgYmUgaGVsZCBsaWFibGUgZm9yIGFueSBkYW1hZ2VzXG4vLyBhcmlzaW5nIGZyb20gdGhlIHVzZSBvZiB0aGlzIHNvZnR3YXJlLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgZ3JhbnRlZCB0byBhbnlvbmUgdG8gdXNlIHRoaXMgc29mdHdhcmUgZm9yIGFueSBwdXJwb3NlLFxuLy8gaW5jbHVkaW5nIGNvbW1lcmNpYWwgYXBwbGljYXRpb25zLCBhbmQgdG8gYWx0ZXIgaXQgYW5kIHJlZGlzdHJpYnV0ZSBpdFxuLy8gZnJlZWx5LCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgcmVzdHJpY3Rpb25zOlxuLy9cbi8vIDEuIFRoZSBvcmlnaW4gb2YgdGhpcyBzb2Z0d2FyZSBtdXN0IG5vdCBiZSBtaXNyZXByZXNlbnRlZDsgeW91IG11c3Qgbm90XG4vLyAgIGNsYWltIHRoYXQgeW91IHdyb3RlIHRoZSBvcmlnaW5hbCBzb2Z0d2FyZS4gSWYgeW91IHVzZSB0aGlzIHNvZnR3YXJlXG4vLyAgIGluIGEgcHJvZHVjdCwgYW4gYWNrbm93bGVkZ21lbnQgaW4gdGhlIHByb2R1Y3QgZG9jdW1lbnRhdGlvbiB3b3VsZCBiZVxuLy8gICBhcHByZWNpYXRlZCBidXQgaXMgbm90IHJlcXVpcmVkLlxuLy8gMi4gQWx0ZXJlZCBzb3VyY2UgdmVyc2lvbnMgbXVzdCBiZSBwbGFpbmx5IG1hcmtlZCBhcyBzdWNoLCBhbmQgbXVzdCBub3QgYmVcbi8vICAgbWlzcmVwcmVzZW50ZWQgYXMgYmVpbmcgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLlxuLy8gMy4gVGhpcyBub3RpY2UgbWF5IG5vdCBiZSByZW1vdmVkIG9yIGFsdGVyZWQgZnJvbSBhbnkgc291cmNlIGRpc3RyaWJ1dGlvbi5cblxudmFyIGNvbnN0YW50cyQyID0ge1xuXG4gIC8qIEFsbG93ZWQgZmx1c2ggdmFsdWVzOyBzZWUgZGVmbGF0ZSgpIGFuZCBpbmZsYXRlKCkgYmVsb3cgZm9yIGRldGFpbHMgKi9cbiAgWl9OT19GTFVTSDogICAgICAgICAwLFxuICBaX1BBUlRJQUxfRkxVU0g6ICAgIDEsXG4gIFpfU1lOQ19GTFVTSDogICAgICAgMixcbiAgWl9GVUxMX0ZMVVNIOiAgICAgICAzLFxuICBaX0ZJTklTSDogICAgICAgICAgIDQsXG4gIFpfQkxPQ0s6ICAgICAgICAgICAgNSxcbiAgWl9UUkVFUzogICAgICAgICAgICA2LFxuXG4gIC8qIFJldHVybiBjb2RlcyBmb3IgdGhlIGNvbXByZXNzaW9uL2RlY29tcHJlc3Npb24gZnVuY3Rpb25zLiBOZWdhdGl2ZSB2YWx1ZXNcbiAgKiBhcmUgZXJyb3JzLCBwb3NpdGl2ZSB2YWx1ZXMgYXJlIHVzZWQgZm9yIHNwZWNpYWwgYnV0IG5vcm1hbCBldmVudHMuXG4gICovXG4gIFpfT0s6ICAgICAgICAgICAgICAgMCxcbiAgWl9TVFJFQU1fRU5EOiAgICAgICAxLFxuICBaX05FRURfRElDVDogICAgICAgIDIsXG4gIFpfRVJSTk86ICAgICAgICAgICAtMSxcbiAgWl9TVFJFQU1fRVJST1I6ICAgIC0yLFxuICBaX0RBVEFfRVJST1I6ICAgICAgLTMsXG4gIFpfTUVNX0VSUk9SOiAgICAgICAtNCxcbiAgWl9CVUZfRVJST1I6ICAgICAgIC01LFxuICAvL1pfVkVSU0lPTl9FUlJPUjogLTYsXG5cbiAgLyogY29tcHJlc3Npb24gbGV2ZWxzICovXG4gIFpfTk9fQ09NUFJFU1NJT046ICAgICAgICAgMCxcbiAgWl9CRVNUX1NQRUVEOiAgICAgICAgICAgICAxLFxuICBaX0JFU1RfQ09NUFJFU1NJT046ICAgICAgIDksXG4gIFpfREVGQVVMVF9DT01QUkVTU0lPTjogICAtMSxcblxuXG4gIFpfRklMVEVSRUQ6ICAgICAgICAgICAgICAgMSxcbiAgWl9IVUZGTUFOX09OTFk6ICAgICAgICAgICAyLFxuICBaX1JMRTogICAgICAgICAgICAgICAgICAgIDMsXG4gIFpfRklYRUQ6ICAgICAgICAgICAgICAgICAgNCxcbiAgWl9ERUZBVUxUX1NUUkFURUdZOiAgICAgICAwLFxuXG4gIC8qIFBvc3NpYmxlIHZhbHVlcyBvZiB0aGUgZGF0YV90eXBlIGZpZWxkICh0aG91Z2ggc2VlIGluZmxhdGUoKSkgKi9cbiAgWl9CSU5BUlk6ICAgICAgICAgICAgICAgICAwLFxuICBaX1RFWFQ6ICAgICAgICAgICAgICAgICAgIDEsXG4gIC8vWl9BU0NJSTogICAgICAgICAgICAgICAgMSwgLy8gPSBaX1RFWFQgKGRlcHJlY2F0ZWQpXG4gIFpfVU5LTk9XTjogICAgICAgICAgICAgICAgMixcblxuICAvKiBUaGUgZGVmbGF0ZSBjb21wcmVzc2lvbiBtZXRob2QgKi9cbiAgWl9ERUZMQVRFRDogICAgICAgICAgICAgICA4XG4gIC8vWl9OVUxMOiAgICAgICAgICAgICAgICAgbnVsbCAvLyBVc2UgLTEgb3IgbnVsbCBpbmxpbmUsIGRlcGVuZGluZyBvbiB2YXIgdHlwZVxufTtcblxuLy8gKEMpIDE5OTUtMjAxMyBKZWFuLWxvdXAgR2FpbGx5IGFuZCBNYXJrIEFkbGVyXG4vLyAoQykgMjAxNC0yMDE3IFZpdGFseSBQdXpyaW4gYW5kIEFuZHJleSBUdXBpdHNpblxuLy9cbi8vIFRoaXMgc29mdHdhcmUgaXMgcHJvdmlkZWQgJ2FzLWlzJywgd2l0aG91dCBhbnkgZXhwcmVzcyBvciBpbXBsaWVkXG4vLyB3YXJyYW50eS4gSW4gbm8gZXZlbnQgd2lsbCB0aGUgYXV0aG9ycyBiZSBoZWxkIGxpYWJsZSBmb3IgYW55IGRhbWFnZXNcbi8vIGFyaXNpbmcgZnJvbSB0aGUgdXNlIG9mIHRoaXMgc29mdHdhcmUuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBncmFudGVkIHRvIGFueW9uZSB0byB1c2UgdGhpcyBzb2Z0d2FyZSBmb3IgYW55IHB1cnBvc2UsXG4vLyBpbmNsdWRpbmcgY29tbWVyY2lhbCBhcHBsaWNhdGlvbnMsIGFuZCB0byBhbHRlciBpdCBhbmQgcmVkaXN0cmlidXRlIGl0XG4vLyBmcmVlbHksIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyByZXN0cmljdGlvbnM6XG4vL1xuLy8gMS4gVGhlIG9yaWdpbiBvZiB0aGlzIHNvZnR3YXJlIG11c3Qgbm90IGJlIG1pc3JlcHJlc2VudGVkOyB5b3UgbXVzdCBub3Rcbi8vICAgY2xhaW0gdGhhdCB5b3Ugd3JvdGUgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLiBJZiB5b3UgdXNlIHRoaXMgc29mdHdhcmVcbi8vICAgaW4gYSBwcm9kdWN0LCBhbiBhY2tub3dsZWRnbWVudCBpbiB0aGUgcHJvZHVjdCBkb2N1bWVudGF0aW9uIHdvdWxkIGJlXG4vLyAgIGFwcHJlY2lhdGVkIGJ1dCBpcyBub3QgcmVxdWlyZWQuXG4vLyAyLiBBbHRlcmVkIHNvdXJjZSB2ZXJzaW9ucyBtdXN0IGJlIHBsYWlubHkgbWFya2VkIGFzIHN1Y2gsIGFuZCBtdXN0IG5vdCBiZVxuLy8gICBtaXNyZXByZXNlbnRlZCBhcyBiZWluZyB0aGUgb3JpZ2luYWwgc29mdHdhcmUuXG4vLyAzLiBUaGlzIG5vdGljZSBtYXkgbm90IGJlIHJlbW92ZWQgb3IgYWx0ZXJlZCBmcm9tIGFueSBzb3VyY2UgZGlzdHJpYnV0aW9uLlxuXG5jb25zdCB7IF90cl9pbml0LCBfdHJfc3RvcmVkX2Jsb2NrLCBfdHJfZmx1c2hfYmxvY2ssIF90cl90YWxseSwgX3RyX2FsaWduIH0gPSB0cmVlcztcblxuXG5cblxuLyogUHVibGljIGNvbnN0YW50cyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki9cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovXG5cbmNvbnN0IHtcbiAgWl9OT19GTFVTSDogWl9OT19GTFVTSCQyLCBaX1BBUlRJQUxfRkxVU0gsIFpfRlVMTF9GTFVTSDogWl9GVUxMX0ZMVVNIJDEsIFpfRklOSVNIOiBaX0ZJTklTSCQzLCBaX0JMT0NLOiBaX0JMT0NLJDEsXG4gIFpfT0s6IFpfT0skMywgWl9TVFJFQU1fRU5EOiBaX1NUUkVBTV9FTkQkMywgWl9TVFJFQU1fRVJST1I6IFpfU1RSRUFNX0VSUk9SJDIsIFpfREFUQV9FUlJPUjogWl9EQVRBX0VSUk9SJDIsIFpfQlVGX0VSUk9SOiBaX0JVRl9FUlJPUiQxLFxuICBaX0RFRkFVTFRfQ09NUFJFU1NJT046IFpfREVGQVVMVF9DT01QUkVTU0lPTiQxLFxuICBaX0ZJTFRFUkVELCBaX0hVRkZNQU5fT05MWSwgWl9STEUsIFpfRklYRUQsIFpfREVGQVVMVF9TVFJBVEVHWTogWl9ERUZBVUxUX1NUUkFURUdZJDEsXG4gIFpfVU5LTk9XTixcbiAgWl9ERUZMQVRFRDogWl9ERUZMQVRFRCQyXG59ID0gY29uc3RhbnRzJDI7XG5cbi8qPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovXG5cblxuY29uc3QgTUFYX01FTV9MRVZFTCA9IDk7XG4vKiBNYXhpbXVtIHZhbHVlIGZvciBtZW1MZXZlbCBpbiBkZWZsYXRlSW5pdDIgKi9cbmNvbnN0IE1BWF9XQklUUyQxID0gMTU7XG4vKiAzMksgTFo3NyB3aW5kb3cgKi9cbmNvbnN0IERFRl9NRU1fTEVWRUwgPSA4O1xuXG5cbmNvbnN0IExFTkdUSF9DT0RFUyAgPSAyOTtcbi8qIG51bWJlciBvZiBsZW5ndGggY29kZXMsIG5vdCBjb3VudGluZyB0aGUgc3BlY2lhbCBFTkRfQkxPQ0sgY29kZSAqL1xuY29uc3QgTElURVJBTFMgICAgICA9IDI1Njtcbi8qIG51bWJlciBvZiBsaXRlcmFsIGJ5dGVzIDAuLjI1NSAqL1xuY29uc3QgTF9DT0RFUyAgICAgICA9IExJVEVSQUxTICsgMSArIExFTkdUSF9DT0RFUztcbi8qIG51bWJlciBvZiBMaXRlcmFsIG9yIExlbmd0aCBjb2RlcywgaW5jbHVkaW5nIHRoZSBFTkRfQkxPQ0sgY29kZSAqL1xuY29uc3QgRF9DT0RFUyAgICAgICA9IDMwO1xuLyogbnVtYmVyIG9mIGRpc3RhbmNlIGNvZGVzICovXG5jb25zdCBCTF9DT0RFUyAgICAgID0gMTk7XG4vKiBudW1iZXIgb2YgY29kZXMgdXNlZCB0byB0cmFuc2ZlciB0aGUgYml0IGxlbmd0aHMgKi9cbmNvbnN0IEhFQVBfU0laRSAgICAgPSAyICogTF9DT0RFUyArIDE7XG4vKiBtYXhpbXVtIGhlYXAgc2l6ZSAqL1xuY29uc3QgTUFYX0JJVFMgID0gMTU7XG4vKiBBbGwgY29kZXMgbXVzdCBub3QgZXhjZWVkIE1BWF9CSVRTIGJpdHMgKi9cblxuY29uc3QgTUlOX01BVENIID0gMztcbmNvbnN0IE1BWF9NQVRDSCA9IDI1ODtcbmNvbnN0IE1JTl9MT09LQUhFQUQgPSAoTUFYX01BVENIICsgTUlOX01BVENIICsgMSk7XG5cbmNvbnN0IFBSRVNFVF9ESUNUID0gMHgyMDtcblxuY29uc3QgSU5JVF9TVEFURSAgICA9ICA0MjsgICAgLyogemxpYiBoZWFkZXIgLT4gQlVTWV9TVEFURSAqL1xuLy8jaWZkZWYgR1pJUFxuY29uc3QgR1pJUF9TVEFURSAgICA9ICA1NzsgICAgLyogZ3ppcCBoZWFkZXIgLT4gQlVTWV9TVEFURSB8IEVYVFJBX1NUQVRFICovXG4vLyNlbmRpZlxuY29uc3QgRVhUUkFfU1RBVEUgICA9ICA2OTsgICAgLyogZ3ppcCBleHRyYSBibG9jayAtPiBOQU1FX1NUQVRFICovXG5jb25zdCBOQU1FX1NUQVRFICAgID0gIDczOyAgICAvKiBnemlwIGZpbGUgbmFtZSAtPiBDT01NRU5UX1NUQVRFICovXG5jb25zdCBDT01NRU5UX1NUQVRFID0gIDkxOyAgICAvKiBnemlwIGNvbW1lbnQgLT4gSENSQ19TVEFURSAqL1xuY29uc3QgSENSQ19TVEFURSAgICA9IDEwMzsgICAgLyogZ3ppcCBoZWFkZXIgQ1JDIC0+IEJVU1lfU1RBVEUgKi9cbmNvbnN0IEJVU1lfU1RBVEUgICAgPSAxMTM7ICAgIC8qIGRlZmxhdGUgLT4gRklOSVNIX1NUQVRFICovXG5jb25zdCBGSU5JU0hfU1RBVEUgID0gNjY2OyAgICAvKiBzdHJlYW0gY29tcGxldGUgKi9cblxuY29uc3QgQlNfTkVFRF9NT1JFICAgICAgPSAxOyAvKiBibG9jayBub3QgY29tcGxldGVkLCBuZWVkIG1vcmUgaW5wdXQgb3IgbW9yZSBvdXRwdXQgKi9cbmNvbnN0IEJTX0JMT0NLX0RPTkUgICAgID0gMjsgLyogYmxvY2sgZmx1c2ggcGVyZm9ybWVkICovXG5jb25zdCBCU19GSU5JU0hfU1RBUlRFRCA9IDM7IC8qIGZpbmlzaCBzdGFydGVkLCBuZWVkIG9ubHkgbW9yZSBvdXRwdXQgYXQgbmV4dCBkZWZsYXRlICovXG5jb25zdCBCU19GSU5JU0hfRE9ORSAgICA9IDQ7IC8qIGZpbmlzaCBkb25lLCBhY2NlcHQgbm8gbW9yZSBpbnB1dCBvciBvdXRwdXQgKi9cblxuY29uc3QgT1NfQ09ERSA9IDB4MDM7IC8vIFVuaXggOikgLiBEb24ndCBkZXRlY3QsIHVzZSB0aGlzIGRlZmF1bHQuXG5cbmNvbnN0IGVyciA9IChzdHJtLCBlcnJvckNvZGUpID0+IHtcbiAgc3RybS5tc2cgPSBtZXNzYWdlc1tlcnJvckNvZGVdO1xuICByZXR1cm4gZXJyb3JDb2RlO1xufTtcblxuY29uc3QgcmFuayA9IChmKSA9PiB7XG4gIHJldHVybiAoKGYpICogMikgLSAoKGYpID4gNCA/IDkgOiAwKTtcbn07XG5cbmNvbnN0IHplcm8gPSAoYnVmKSA9PiB7XG4gIGxldCBsZW4gPSBidWYubGVuZ3RoOyB3aGlsZSAoLS1sZW4gPj0gMCkgeyBidWZbbGVuXSA9IDA7IH1cbn07XG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogU2xpZGUgdGhlIGhhc2ggdGFibGUgd2hlbiBzbGlkaW5nIHRoZSB3aW5kb3cgZG93biAoY291bGQgYmUgYXZvaWRlZCB3aXRoIDMyXG4gKiBiaXQgdmFsdWVzIGF0IHRoZSBleHBlbnNlIG9mIG1lbW9yeSB1c2FnZSkuIFdlIHNsaWRlIGV2ZW4gd2hlbiBsZXZlbCA9PSAwIHRvXG4gKiBrZWVwIHRoZSBoYXNoIHRhYmxlIGNvbnNpc3RlbnQgaWYgd2Ugc3dpdGNoIGJhY2sgdG8gbGV2ZWwgPiAwIGxhdGVyLlxuICovXG5jb25zdCBzbGlkZV9oYXNoID0gKHMpID0+IHtcbiAgbGV0IG4sIG07XG4gIGxldCBwO1xuICBsZXQgd3NpemUgPSBzLndfc2l6ZTtcblxuICBuID0gcy5oYXNoX3NpemU7XG4gIHAgPSBuO1xuICBkbyB7XG4gICAgbSA9IHMuaGVhZFstLXBdO1xuICAgIHMuaGVhZFtwXSA9IChtID49IHdzaXplID8gbSAtIHdzaXplIDogMCk7XG4gIH0gd2hpbGUgKC0tbik7XG4gIG4gPSB3c2l6ZTtcbi8vI2lmbmRlZiBGQVNURVNUXG4gIHAgPSBuO1xuICBkbyB7XG4gICAgbSA9IHMucHJldlstLXBdO1xuICAgIHMucHJldltwXSA9IChtID49IHdzaXplID8gbSAtIHdzaXplIDogMCk7XG4gICAgLyogSWYgbiBpcyBub3Qgb24gYW55IGhhc2ggY2hhaW4sIHByZXZbbl0gaXMgZ2FyYmFnZSBidXRcbiAgICAgKiBpdHMgdmFsdWUgd2lsbCBuZXZlciBiZSB1c2VkLlxuICAgICAqL1xuICB9IHdoaWxlICgtLW4pO1xuLy8jZW5kaWZcbn07XG5cbi8qIGVzbGludC1kaXNhYmxlIG5ldy1jYXAgKi9cbmxldCBIQVNIX1pMSUIgPSAocywgcHJldiwgZGF0YSkgPT4gKChwcmV2IDw8IHMuaGFzaF9zaGlmdCkgXiBkYXRhKSAmIHMuaGFzaF9tYXNrO1xuLy8gVGhpcyBoYXNoIGNhdXNlcyBsZXNzIGNvbGxpc2lvbnMsIGh0dHBzOi8vZ2l0aHViLmNvbS9ub2RlY2EvcGFrby9pc3N1ZXMvMTM1XG4vLyBCdXQgYnJlYWtzIGJpbmFyeSBjb21wYXRpYmlsaXR5XG4vL2xldCBIQVNIX0ZBU1QgPSAocywgcHJldiwgZGF0YSkgPT4gKChwcmV2IDw8IDgpICsgKHByZXYgPj4gOCkgKyAoZGF0YSA8PCA0KSkgJiBzLmhhc2hfbWFzaztcbmxldCBIQVNIID0gSEFTSF9aTElCO1xuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEZsdXNoIGFzIG11Y2ggcGVuZGluZyBvdXRwdXQgYXMgcG9zc2libGUuIEFsbCBkZWZsYXRlKCkgb3V0cHV0LCBleGNlcHQgZm9yXG4gKiBzb21lIGRlZmxhdGVfc3RvcmVkKCkgb3V0cHV0LCBnb2VzIHRocm91Z2ggdGhpcyBmdW5jdGlvbiBzbyBzb21lXG4gKiBhcHBsaWNhdGlvbnMgbWF5IHdpc2ggdG8gbW9kaWZ5IGl0IHRvIGF2b2lkIGFsbG9jYXRpbmcgYSBsYXJnZVxuICogc3RybS0+bmV4dF9vdXQgYnVmZmVyIGFuZCBjb3B5aW5nIGludG8gaXQuIChTZWUgYWxzbyByZWFkX2J1ZigpKS5cbiAqL1xuY29uc3QgZmx1c2hfcGVuZGluZyA9IChzdHJtKSA9PiB7XG4gIGNvbnN0IHMgPSBzdHJtLnN0YXRlO1xuXG4gIC8vX3RyX2ZsdXNoX2JpdHMocyk7XG4gIGxldCBsZW4gPSBzLnBlbmRpbmc7XG4gIGlmIChsZW4gPiBzdHJtLmF2YWlsX291dCkge1xuICAgIGxlbiA9IHN0cm0uYXZhaWxfb3V0O1xuICB9XG4gIGlmIChsZW4gPT09IDApIHsgcmV0dXJuOyB9XG5cbiAgc3RybS5vdXRwdXQuc2V0KHMucGVuZGluZ19idWYuc3ViYXJyYXkocy5wZW5kaW5nX291dCwgcy5wZW5kaW5nX291dCArIGxlbiksIHN0cm0ubmV4dF9vdXQpO1xuICBzdHJtLm5leHRfb3V0ICArPSBsZW47XG4gIHMucGVuZGluZ19vdXQgICs9IGxlbjtcbiAgc3RybS50b3RhbF9vdXQgKz0gbGVuO1xuICBzdHJtLmF2YWlsX291dCAtPSBsZW47XG4gIHMucGVuZGluZyAgICAgIC09IGxlbjtcbiAgaWYgKHMucGVuZGluZyA9PT0gMCkge1xuICAgIHMucGVuZGluZ19vdXQgPSAwO1xuICB9XG59O1xuXG5cbmNvbnN0IGZsdXNoX2Jsb2NrX29ubHkgPSAocywgbGFzdCkgPT4ge1xuICBfdHJfZmx1c2hfYmxvY2socywgKHMuYmxvY2tfc3RhcnQgPj0gMCA/IHMuYmxvY2tfc3RhcnQgOiAtMSksIHMuc3Ryc3RhcnQgLSBzLmJsb2NrX3N0YXJ0LCBsYXN0KTtcbiAgcy5ibG9ja19zdGFydCA9IHMuc3Ryc3RhcnQ7XG4gIGZsdXNoX3BlbmRpbmcocy5zdHJtKTtcbn07XG5cblxuY29uc3QgcHV0X2J5dGUgPSAocywgYikgPT4ge1xuICBzLnBlbmRpbmdfYnVmW3MucGVuZGluZysrXSA9IGI7XG59O1xuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFB1dCBhIHNob3J0IGluIHRoZSBwZW5kaW5nIGJ1ZmZlci4gVGhlIDE2LWJpdCB2YWx1ZSBpcyBwdXQgaW4gTVNCIG9yZGVyLlxuICogSU4gYXNzZXJ0aW9uOiB0aGUgc3RyZWFtIHN0YXRlIGlzIGNvcnJlY3QgYW5kIHRoZXJlIGlzIGVub3VnaCByb29tIGluXG4gKiBwZW5kaW5nX2J1Zi5cbiAqL1xuY29uc3QgcHV0U2hvcnRNU0IgPSAocywgYikgPT4ge1xuXG4gIC8vICBwdXRfYnl0ZShzLCAoQnl0ZSkoYiA+PiA4KSk7XG4vLyAgcHV0X2J5dGUocywgKEJ5dGUpKGIgJiAweGZmKSk7XG4gIHMucGVuZGluZ19idWZbcy5wZW5kaW5nKytdID0gKGIgPj4+IDgpICYgMHhmZjtcbiAgcy5wZW5kaW5nX2J1ZltzLnBlbmRpbmcrK10gPSBiICYgMHhmZjtcbn07XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBSZWFkIGEgbmV3IGJ1ZmZlciBmcm9tIHRoZSBjdXJyZW50IGlucHV0IHN0cmVhbSwgdXBkYXRlIHRoZSBhZGxlcjMyXG4gKiBhbmQgdG90YWwgbnVtYmVyIG9mIGJ5dGVzIHJlYWQuICBBbGwgZGVmbGF0ZSgpIGlucHV0IGdvZXMgdGhyb3VnaFxuICogdGhpcyBmdW5jdGlvbiBzbyBzb21lIGFwcGxpY2F0aW9ucyBtYXkgd2lzaCB0byBtb2RpZnkgaXQgdG8gYXZvaWRcbiAqIGFsbG9jYXRpbmcgYSBsYXJnZSBzdHJtLT5pbnB1dCBidWZmZXIgYW5kIGNvcHlpbmcgZnJvbSBpdC5cbiAqIChTZWUgYWxzbyBmbHVzaF9wZW5kaW5nKCkpLlxuICovXG5jb25zdCByZWFkX2J1ZiA9IChzdHJtLCBidWYsIHN0YXJ0LCBzaXplKSA9PiB7XG5cbiAgbGV0IGxlbiA9IHN0cm0uYXZhaWxfaW47XG5cbiAgaWYgKGxlbiA+IHNpemUpIHsgbGVuID0gc2l6ZTsgfVxuICBpZiAobGVuID09PSAwKSB7IHJldHVybiAwOyB9XG5cbiAgc3RybS5hdmFpbF9pbiAtPSBsZW47XG5cbiAgLy8gem1lbWNweShidWYsIHN0cm0tPm5leHRfaW4sIGxlbik7XG4gIGJ1Zi5zZXQoc3RybS5pbnB1dC5zdWJhcnJheShzdHJtLm5leHRfaW4sIHN0cm0ubmV4dF9pbiArIGxlbiksIHN0YXJ0KTtcbiAgaWYgKHN0cm0uc3RhdGUud3JhcCA9PT0gMSkge1xuICAgIHN0cm0uYWRsZXIgPSBhZGxlcjMyXzEoc3RybS5hZGxlciwgYnVmLCBsZW4sIHN0YXJ0KTtcbiAgfVxuXG4gIGVsc2UgaWYgKHN0cm0uc3RhdGUud3JhcCA9PT0gMikge1xuICAgIHN0cm0uYWRsZXIgPSBjcmMzMl8xKHN0cm0uYWRsZXIsIGJ1ZiwgbGVuLCBzdGFydCk7XG4gIH1cblxuICBzdHJtLm5leHRfaW4gKz0gbGVuO1xuICBzdHJtLnRvdGFsX2luICs9IGxlbjtcblxuICByZXR1cm4gbGVuO1xufTtcblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFNldCBtYXRjaF9zdGFydCB0byB0aGUgbG9uZ2VzdCBtYXRjaCBzdGFydGluZyBhdCB0aGUgZ2l2ZW4gc3RyaW5nIGFuZFxuICogcmV0dXJuIGl0cyBsZW5ndGguIE1hdGNoZXMgc2hvcnRlciBvciBlcXVhbCB0byBwcmV2X2xlbmd0aCBhcmUgZGlzY2FyZGVkLFxuICogaW4gd2hpY2ggY2FzZSB0aGUgcmVzdWx0IGlzIGVxdWFsIHRvIHByZXZfbGVuZ3RoIGFuZCBtYXRjaF9zdGFydCBpc1xuICogZ2FyYmFnZS5cbiAqIElOIGFzc2VydGlvbnM6IGN1cl9tYXRjaCBpcyB0aGUgaGVhZCBvZiB0aGUgaGFzaCBjaGFpbiBmb3IgdGhlIGN1cnJlbnRcbiAqICAgc3RyaW5nIChzdHJzdGFydCkgYW5kIGl0cyBkaXN0YW5jZSBpcyA8PSBNQVhfRElTVCwgYW5kIHByZXZfbGVuZ3RoID49IDFcbiAqIE9VVCBhc3NlcnRpb246IHRoZSBtYXRjaCBsZW5ndGggaXMgbm90IGdyZWF0ZXIgdGhhbiBzLT5sb29rYWhlYWQuXG4gKi9cbmNvbnN0IGxvbmdlc3RfbWF0Y2ggPSAocywgY3VyX21hdGNoKSA9PiB7XG5cbiAgbGV0IGNoYWluX2xlbmd0aCA9IHMubWF4X2NoYWluX2xlbmd0aDsgICAgICAvKiBtYXggaGFzaCBjaGFpbiBsZW5ndGggKi9cbiAgbGV0IHNjYW4gPSBzLnN0cnN0YXJ0OyAvKiBjdXJyZW50IHN0cmluZyAqL1xuICBsZXQgbWF0Y2g7ICAgICAgICAgICAgICAgICAgICAgICAvKiBtYXRjaGVkIHN0cmluZyAqL1xuICBsZXQgbGVuOyAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIGxlbmd0aCBvZiBjdXJyZW50IG1hdGNoICovXG4gIGxldCBiZXN0X2xlbiA9IHMucHJldl9sZW5ndGg7ICAgICAgICAgICAgICAvKiBiZXN0IG1hdGNoIGxlbmd0aCBzbyBmYXIgKi9cbiAgbGV0IG5pY2VfbWF0Y2ggPSBzLm5pY2VfbWF0Y2g7ICAgICAgICAgICAgIC8qIHN0b3AgaWYgbWF0Y2ggbG9uZyBlbm91Z2ggKi9cbiAgY29uc3QgbGltaXQgPSAocy5zdHJzdGFydCA+IChzLndfc2l6ZSAtIE1JTl9MT09LQUhFQUQpKSA/XG4gICAgICBzLnN0cnN0YXJ0IC0gKHMud19zaXplIC0gTUlOX0xPT0tBSEVBRCkgOiAwLypOSUwqLztcblxuICBjb25zdCBfd2luID0gcy53aW5kb3c7IC8vIHNob3J0Y3V0XG5cbiAgY29uc3Qgd21hc2sgPSBzLndfbWFzaztcbiAgY29uc3QgcHJldiAgPSBzLnByZXY7XG5cbiAgLyogU3RvcCB3aGVuIGN1cl9tYXRjaCBiZWNvbWVzIDw9IGxpbWl0LiBUbyBzaW1wbGlmeSB0aGUgY29kZSxcbiAgICogd2UgcHJldmVudCBtYXRjaGVzIHdpdGggdGhlIHN0cmluZyBvZiB3aW5kb3cgaW5kZXggMC5cbiAgICovXG5cbiAgY29uc3Qgc3RyZW5kID0gcy5zdHJzdGFydCArIE1BWF9NQVRDSDtcbiAgbGV0IHNjYW5fZW5kMSAgPSBfd2luW3NjYW4gKyBiZXN0X2xlbiAtIDFdO1xuICBsZXQgc2Nhbl9lbmQgICA9IF93aW5bc2NhbiArIGJlc3RfbGVuXTtcblxuICAvKiBUaGUgY29kZSBpcyBvcHRpbWl6ZWQgZm9yIEhBU0hfQklUUyA+PSA4IGFuZCBNQVhfTUFUQ0gtMiBtdWx0aXBsZSBvZiAxNi5cbiAgICogSXQgaXMgZWFzeSB0byBnZXQgcmlkIG9mIHRoaXMgb3B0aW1pemF0aW9uIGlmIG5lY2Vzc2FyeS5cbiAgICovXG4gIC8vIEFzc2VydChzLT5oYXNoX2JpdHMgPj0gOCAmJiBNQVhfTUFUQ0ggPT0gMjU4LCBcIkNvZGUgdG9vIGNsZXZlclwiKTtcblxuICAvKiBEbyBub3Qgd2FzdGUgdG9vIG11Y2ggdGltZSBpZiB3ZSBhbHJlYWR5IGhhdmUgYSBnb29kIG1hdGNoOiAqL1xuICBpZiAocy5wcmV2X2xlbmd0aCA+PSBzLmdvb2RfbWF0Y2gpIHtcbiAgICBjaGFpbl9sZW5ndGggPj49IDI7XG4gIH1cbiAgLyogRG8gbm90IGxvb2sgZm9yIG1hdGNoZXMgYmV5b25kIHRoZSBlbmQgb2YgdGhlIGlucHV0LiBUaGlzIGlzIG5lY2Vzc2FyeVxuICAgKiB0byBtYWtlIGRlZmxhdGUgZGV0ZXJtaW5pc3RpYy5cbiAgICovXG4gIGlmIChuaWNlX21hdGNoID4gcy5sb29rYWhlYWQpIHsgbmljZV9tYXRjaCA9IHMubG9va2FoZWFkOyB9XG5cbiAgLy8gQXNzZXJ0KCh1bGcpcy0+c3Ryc3RhcnQgPD0gcy0+d2luZG93X3NpemUtTUlOX0xPT0tBSEVBRCwgXCJuZWVkIGxvb2thaGVhZFwiKTtcblxuICBkbyB7XG4gICAgLy8gQXNzZXJ0KGN1cl9tYXRjaCA8IHMtPnN0cnN0YXJ0LCBcIm5vIGZ1dHVyZVwiKTtcbiAgICBtYXRjaCA9IGN1cl9tYXRjaDtcblxuICAgIC8qIFNraXAgdG8gbmV4dCBtYXRjaCBpZiB0aGUgbWF0Y2ggbGVuZ3RoIGNhbm5vdCBpbmNyZWFzZVxuICAgICAqIG9yIGlmIHRoZSBtYXRjaCBsZW5ndGggaXMgbGVzcyB0aGFuIDIuICBOb3RlIHRoYXQgdGhlIGNoZWNrcyBiZWxvd1xuICAgICAqIGZvciBpbnN1ZmZpY2llbnQgbG9va2FoZWFkIG9ubHkgb2NjdXIgb2NjYXNpb25hbGx5IGZvciBwZXJmb3JtYW5jZVxuICAgICAqIHJlYXNvbnMuICBUaGVyZWZvcmUgdW5pbml0aWFsaXplZCBtZW1vcnkgd2lsbCBiZSBhY2Nlc3NlZCwgYW5kXG4gICAgICogY29uZGl0aW9uYWwganVtcHMgd2lsbCBiZSBtYWRlIHRoYXQgZGVwZW5kIG9uIHRob3NlIHZhbHVlcy5cbiAgICAgKiBIb3dldmVyIHRoZSBsZW5ndGggb2YgdGhlIG1hdGNoIGlzIGxpbWl0ZWQgdG8gdGhlIGxvb2thaGVhZCwgc29cbiAgICAgKiB0aGUgb3V0cHV0IG9mIGRlZmxhdGUgaXMgbm90IGFmZmVjdGVkIGJ5IHRoZSB1bmluaXRpYWxpemVkIHZhbHVlcy5cbiAgICAgKi9cblxuICAgIGlmIChfd2luW21hdGNoICsgYmVzdF9sZW5dICAgICAhPT0gc2Nhbl9lbmQgIHx8XG4gICAgICAgIF93aW5bbWF0Y2ggKyBiZXN0X2xlbiAtIDFdICE9PSBzY2FuX2VuZDEgfHxcbiAgICAgICAgX3dpblttYXRjaF0gICAgICAgICAgICAgICAgIT09IF93aW5bc2Nhbl0gfHxcbiAgICAgICAgX3dpblsrK21hdGNoXSAgICAgICAgICAgICAgIT09IF93aW5bc2NhbiArIDFdKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvKiBUaGUgY2hlY2sgYXQgYmVzdF9sZW4tMSBjYW4gYmUgcmVtb3ZlZCBiZWNhdXNlIGl0IHdpbGwgYmUgbWFkZVxuICAgICAqIGFnYWluIGxhdGVyLiAoVGhpcyBoZXVyaXN0aWMgaXMgbm90IGFsd2F5cyBhIHdpbi4pXG4gICAgICogSXQgaXMgbm90IG5lY2Vzc2FyeSB0byBjb21wYXJlIHNjYW5bMl0gYW5kIG1hdGNoWzJdIHNpbmNlIHRoZXlcbiAgICAgKiBhcmUgYWx3YXlzIGVxdWFsIHdoZW4gdGhlIG90aGVyIGJ5dGVzIG1hdGNoLCBnaXZlbiB0aGF0XG4gICAgICogdGhlIGhhc2gga2V5cyBhcmUgZXF1YWwgYW5kIHRoYXQgSEFTSF9CSVRTID49IDguXG4gICAgICovXG4gICAgc2NhbiArPSAyO1xuICAgIG1hdGNoKys7XG4gICAgLy8gQXNzZXJ0KCpzY2FuID09ICptYXRjaCwgXCJtYXRjaFsyXT9cIik7XG5cbiAgICAvKiBXZSBjaGVjayBmb3IgaW5zdWZmaWNpZW50IGxvb2thaGVhZCBvbmx5IGV2ZXJ5IDh0aCBjb21wYXJpc29uO1xuICAgICAqIHRoZSAyNTZ0aCBjaGVjayB3aWxsIGJlIG1hZGUgYXQgc3Ryc3RhcnQrMjU4LlxuICAgICAqL1xuICAgIGRvIHtcbiAgICAgIC8qanNoaW50IG5vZW1wdHk6ZmFsc2UqL1xuICAgIH0gd2hpbGUgKF93aW5bKytzY2FuXSA9PT0gX3dpblsrK21hdGNoXSAmJiBfd2luWysrc2Nhbl0gPT09IF93aW5bKyttYXRjaF0gJiZcbiAgICAgICAgICAgICBfd2luWysrc2Nhbl0gPT09IF93aW5bKyttYXRjaF0gJiYgX3dpblsrK3NjYW5dID09PSBfd2luWysrbWF0Y2hdICYmXG4gICAgICAgICAgICAgX3dpblsrK3NjYW5dID09PSBfd2luWysrbWF0Y2hdICYmIF93aW5bKytzY2FuXSA9PT0gX3dpblsrK21hdGNoXSAmJlxuICAgICAgICAgICAgIF93aW5bKytzY2FuXSA9PT0gX3dpblsrK21hdGNoXSAmJiBfd2luWysrc2Nhbl0gPT09IF93aW5bKyttYXRjaF0gJiZcbiAgICAgICAgICAgICBzY2FuIDwgc3RyZW5kKTtcblxuICAgIC8vIEFzc2VydChzY2FuIDw9IHMtPndpbmRvdysodW5zaWduZWQpKHMtPndpbmRvd19zaXplLTEpLCBcIndpbGQgc2NhblwiKTtcblxuICAgIGxlbiA9IE1BWF9NQVRDSCAtIChzdHJlbmQgLSBzY2FuKTtcbiAgICBzY2FuID0gc3RyZW5kIC0gTUFYX01BVENIO1xuXG4gICAgaWYgKGxlbiA+IGJlc3RfbGVuKSB7XG4gICAgICBzLm1hdGNoX3N0YXJ0ID0gY3VyX21hdGNoO1xuICAgICAgYmVzdF9sZW4gPSBsZW47XG4gICAgICBpZiAobGVuID49IG5pY2VfbWF0Y2gpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBzY2FuX2VuZDEgID0gX3dpbltzY2FuICsgYmVzdF9sZW4gLSAxXTtcbiAgICAgIHNjYW5fZW5kICAgPSBfd2luW3NjYW4gKyBiZXN0X2xlbl07XG4gICAgfVxuICB9IHdoaWxlICgoY3VyX21hdGNoID0gcHJldltjdXJfbWF0Y2ggJiB3bWFza10pID4gbGltaXQgJiYgLS1jaGFpbl9sZW5ndGggIT09IDApO1xuXG4gIGlmIChiZXN0X2xlbiA8PSBzLmxvb2thaGVhZCkge1xuICAgIHJldHVybiBiZXN0X2xlbjtcbiAgfVxuICByZXR1cm4gcy5sb29rYWhlYWQ7XG59O1xuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogRmlsbCB0aGUgd2luZG93IHdoZW4gdGhlIGxvb2thaGVhZCBiZWNvbWVzIGluc3VmZmljaWVudC5cbiAqIFVwZGF0ZXMgc3Ryc3RhcnQgYW5kIGxvb2thaGVhZC5cbiAqXG4gKiBJTiBhc3NlcnRpb246IGxvb2thaGVhZCA8IE1JTl9MT09LQUhFQURcbiAqIE9VVCBhc3NlcnRpb25zOiBzdHJzdGFydCA8PSB3aW5kb3dfc2l6ZS1NSU5fTE9PS0FIRUFEXG4gKiAgICBBdCBsZWFzdCBvbmUgYnl0ZSBoYXMgYmVlbiByZWFkLCBvciBhdmFpbF9pbiA9PSAwOyByZWFkcyBhcmVcbiAqICAgIHBlcmZvcm1lZCBmb3IgYXQgbGVhc3QgdHdvIGJ5dGVzIChyZXF1aXJlZCBmb3IgdGhlIHppcCB0cmFuc2xhdGVfZW9sXG4gKiAgICBvcHRpb24gLS0gbm90IHN1cHBvcnRlZCBoZXJlKS5cbiAqL1xuY29uc3QgZmlsbF93aW5kb3cgPSAocykgPT4ge1xuXG4gIGNvbnN0IF93X3NpemUgPSBzLndfc2l6ZTtcbiAgbGV0IG4sIG1vcmUsIHN0cjtcblxuICAvL0Fzc2VydChzLT5sb29rYWhlYWQgPCBNSU5fTE9PS0FIRUFELCBcImFscmVhZHkgZW5vdWdoIGxvb2thaGVhZFwiKTtcblxuICBkbyB7XG4gICAgbW9yZSA9IHMud2luZG93X3NpemUgLSBzLmxvb2thaGVhZCAtIHMuc3Ryc3RhcnQ7XG5cbiAgICAvLyBKUyBpbnRzIGhhdmUgMzIgYml0LCBibG9jayBiZWxvdyBub3QgbmVlZGVkXG4gICAgLyogRGVhbCB3aXRoICFAIyQlIDY0SyBsaW1pdDogKi9cbiAgICAvL2lmIChzaXplb2YoaW50KSA8PSAyKSB7XG4gICAgLy8gICAgaWYgKG1vcmUgPT0gMCAmJiBzLT5zdHJzdGFydCA9PSAwICYmIHMtPmxvb2thaGVhZCA9PSAwKSB7XG4gICAgLy8gICAgICAgIG1vcmUgPSB3c2l6ZTtcbiAgICAvL1xuICAgIC8vICB9IGVsc2UgaWYgKG1vcmUgPT0gKHVuc2lnbmVkKSgtMSkpIHtcbiAgICAvLyAgICAgICAgLyogVmVyeSB1bmxpa2VseSwgYnV0IHBvc3NpYmxlIG9uIDE2IGJpdCBtYWNoaW5lIGlmXG4gICAgLy8gICAgICAgICAqIHN0cnN0YXJ0ID09IDAgJiYgbG9va2FoZWFkID09IDEgKGlucHV0IGRvbmUgYSBieXRlIGF0IHRpbWUpXG4gICAgLy8gICAgICAgICAqL1xuICAgIC8vICAgICAgICBtb3JlLS07XG4gICAgLy8gICAgfVxuICAgIC8vfVxuXG5cbiAgICAvKiBJZiB0aGUgd2luZG93IGlzIGFsbW9zdCBmdWxsIGFuZCB0aGVyZSBpcyBpbnN1ZmZpY2llbnQgbG9va2FoZWFkLFxuICAgICAqIG1vdmUgdGhlIHVwcGVyIGhhbGYgdG8gdGhlIGxvd2VyIG9uZSB0byBtYWtlIHJvb20gaW4gdGhlIHVwcGVyIGhhbGYuXG4gICAgICovXG4gICAgaWYgKHMuc3Ryc3RhcnQgPj0gX3dfc2l6ZSArIChfd19zaXplIC0gTUlOX0xPT0tBSEVBRCkpIHtcblxuICAgICAgcy53aW5kb3cuc2V0KHMud2luZG93LnN1YmFycmF5KF93X3NpemUsIF93X3NpemUgKyBfd19zaXplIC0gbW9yZSksIDApO1xuICAgICAgcy5tYXRjaF9zdGFydCAtPSBfd19zaXplO1xuICAgICAgcy5zdHJzdGFydCAtPSBfd19zaXplO1xuICAgICAgLyogd2Ugbm93IGhhdmUgc3Ryc3RhcnQgPj0gTUFYX0RJU1QgKi9cbiAgICAgIHMuYmxvY2tfc3RhcnQgLT0gX3dfc2l6ZTtcbiAgICAgIGlmIChzLmluc2VydCA+IHMuc3Ryc3RhcnQpIHtcbiAgICAgICAgcy5pbnNlcnQgPSBzLnN0cnN0YXJ0O1xuICAgICAgfVxuICAgICAgc2xpZGVfaGFzaChzKTtcbiAgICAgIG1vcmUgKz0gX3dfc2l6ZTtcbiAgICB9XG4gICAgaWYgKHMuc3RybS5hdmFpbF9pbiA9PT0gMCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgLyogSWYgdGhlcmUgd2FzIG5vIHNsaWRpbmc6XG4gICAgICogICAgc3Ryc3RhcnQgPD0gV1NJWkUrTUFYX0RJU1QtMSAmJiBsb29rYWhlYWQgPD0gTUlOX0xPT0tBSEVBRCAtIDEgJiZcbiAgICAgKiAgICBtb3JlID09IHdpbmRvd19zaXplIC0gbG9va2FoZWFkIC0gc3Ryc3RhcnRcbiAgICAgKiA9PiBtb3JlID49IHdpbmRvd19zaXplIC0gKE1JTl9MT09LQUhFQUQtMSArIFdTSVpFICsgTUFYX0RJU1QtMSlcbiAgICAgKiA9PiBtb3JlID49IHdpbmRvd19zaXplIC0gMipXU0laRSArIDJcbiAgICAgKiBJbiB0aGUgQklHX01FTSBvciBNTUFQIGNhc2UgKG5vdCB5ZXQgc3VwcG9ydGVkKSxcbiAgICAgKiAgIHdpbmRvd19zaXplID09IGlucHV0X3NpemUgKyBNSU5fTE9PS0FIRUFEICAmJlxuICAgICAqICAgc3Ryc3RhcnQgKyBzLT5sb29rYWhlYWQgPD0gaW5wdXRfc2l6ZSA9PiBtb3JlID49IE1JTl9MT09LQUhFQUQuXG4gICAgICogT3RoZXJ3aXNlLCB3aW5kb3dfc2l6ZSA9PSAyKldTSVpFIHNvIG1vcmUgPj0gMi5cbiAgICAgKiBJZiB0aGVyZSB3YXMgc2xpZGluZywgbW9yZSA+PSBXU0laRS4gU28gaW4gYWxsIGNhc2VzLCBtb3JlID49IDIuXG4gICAgICovXG4gICAgLy9Bc3NlcnQobW9yZSA+PSAyLCBcIm1vcmUgPCAyXCIpO1xuICAgIG4gPSByZWFkX2J1ZihzLnN0cm0sIHMud2luZG93LCBzLnN0cnN0YXJ0ICsgcy5sb29rYWhlYWQsIG1vcmUpO1xuICAgIHMubG9va2FoZWFkICs9IG47XG5cbiAgICAvKiBJbml0aWFsaXplIHRoZSBoYXNoIHZhbHVlIG5vdyB0aGF0IHdlIGhhdmUgc29tZSBpbnB1dDogKi9cbiAgICBpZiAocy5sb29rYWhlYWQgKyBzLmluc2VydCA+PSBNSU5fTUFUQ0gpIHtcbiAgICAgIHN0ciA9IHMuc3Ryc3RhcnQgLSBzLmluc2VydDtcbiAgICAgIHMuaW5zX2ggPSBzLndpbmRvd1tzdHJdO1xuXG4gICAgICAvKiBVUERBVEVfSEFTSChzLCBzLT5pbnNfaCwgcy0+d2luZG93W3N0ciArIDFdKTsgKi9cbiAgICAgIHMuaW5zX2ggPSBIQVNIKHMsIHMuaW5zX2gsIHMud2luZG93W3N0ciArIDFdKTtcbi8vI2lmIE1JTl9NQVRDSCAhPSAzXG4vLyAgICAgICAgQ2FsbCB1cGRhdGVfaGFzaCgpIE1JTl9NQVRDSC0zIG1vcmUgdGltZXNcbi8vI2VuZGlmXG4gICAgICB3aGlsZSAocy5pbnNlcnQpIHtcbiAgICAgICAgLyogVVBEQVRFX0hBU0gocywgcy0+aW5zX2gsIHMtPndpbmRvd1tzdHIgKyBNSU5fTUFUQ0gtMV0pOyAqL1xuICAgICAgICBzLmluc19oID0gSEFTSChzLCBzLmluc19oLCBzLndpbmRvd1tzdHIgKyBNSU5fTUFUQ0ggLSAxXSk7XG5cbiAgICAgICAgcy5wcmV2W3N0ciAmIHMud19tYXNrXSA9IHMuaGVhZFtzLmluc19oXTtcbiAgICAgICAgcy5oZWFkW3MuaW5zX2hdID0gc3RyO1xuICAgICAgICBzdHIrKztcbiAgICAgICAgcy5pbnNlcnQtLTtcbiAgICAgICAgaWYgKHMubG9va2FoZWFkICsgcy5pbnNlcnQgPCBNSU5fTUFUQ0gpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICAvKiBJZiB0aGUgd2hvbGUgaW5wdXQgaGFzIGxlc3MgdGhhbiBNSU5fTUFUQ0ggYnl0ZXMsIGluc19oIGlzIGdhcmJhZ2UsXG4gICAgICogYnV0IHRoaXMgaXMgbm90IGltcG9ydGFudCBzaW5jZSBvbmx5IGxpdGVyYWwgYnl0ZXMgd2lsbCBiZSBlbWl0dGVkLlxuICAgICAqL1xuXG4gIH0gd2hpbGUgKHMubG9va2FoZWFkIDwgTUlOX0xPT0tBSEVBRCAmJiBzLnN0cm0uYXZhaWxfaW4gIT09IDApO1xuXG4gIC8qIElmIHRoZSBXSU5fSU5JVCBieXRlcyBhZnRlciB0aGUgZW5kIG9mIHRoZSBjdXJyZW50IGRhdGEgaGF2ZSBuZXZlciBiZWVuXG4gICAqIHdyaXR0ZW4sIHRoZW4gemVybyB0aG9zZSBieXRlcyBpbiBvcmRlciB0byBhdm9pZCBtZW1vcnkgY2hlY2sgcmVwb3J0cyBvZlxuICAgKiB0aGUgdXNlIG9mIHVuaW5pdGlhbGl6ZWQgKG9yIHVuaW5pdGlhbGlzZWQgYXMgSnVsaWFuIHdyaXRlcykgYnl0ZXMgYnlcbiAgICogdGhlIGxvbmdlc3QgbWF0Y2ggcm91dGluZXMuICBVcGRhdGUgdGhlIGhpZ2ggd2F0ZXIgbWFyayBmb3IgdGhlIG5leHRcbiAgICogdGltZSB0aHJvdWdoIGhlcmUuICBXSU5fSU5JVCBpcyBzZXQgdG8gTUFYX01BVENIIHNpbmNlIHRoZSBsb25nZXN0IG1hdGNoXG4gICAqIHJvdXRpbmVzIGFsbG93IHNjYW5uaW5nIHRvIHN0cnN0YXJ0ICsgTUFYX01BVENILCBpZ25vcmluZyBsb29rYWhlYWQuXG4gICAqL1xuLy8gIGlmIChzLmhpZ2hfd2F0ZXIgPCBzLndpbmRvd19zaXplKSB7XG4vLyAgICBjb25zdCBjdXJyID0gcy5zdHJzdGFydCArIHMubG9va2FoZWFkO1xuLy8gICAgbGV0IGluaXQgPSAwO1xuLy9cbi8vICAgIGlmIChzLmhpZ2hfd2F0ZXIgPCBjdXJyKSB7XG4vLyAgICAgIC8qIFByZXZpb3VzIGhpZ2ggd2F0ZXIgbWFyayBiZWxvdyBjdXJyZW50IGRhdGEgLS0gemVybyBXSU5fSU5JVFxuLy8gICAgICAgKiBieXRlcyBvciB1cCB0byBlbmQgb2Ygd2luZG93LCB3aGljaGV2ZXIgaXMgbGVzcy5cbi8vICAgICAgICovXG4vLyAgICAgIGluaXQgPSBzLndpbmRvd19zaXplIC0gY3Vycjtcbi8vICAgICAgaWYgKGluaXQgPiBXSU5fSU5JVClcbi8vICAgICAgICBpbml0ID0gV0lOX0lOSVQ7XG4vLyAgICAgIHptZW16ZXJvKHMtPndpbmRvdyArIGN1cnIsICh1bnNpZ25lZClpbml0KTtcbi8vICAgICAgcy0+aGlnaF93YXRlciA9IGN1cnIgKyBpbml0O1xuLy8gICAgfVxuLy8gICAgZWxzZSBpZiAocy0+aGlnaF93YXRlciA8ICh1bGcpY3VyciArIFdJTl9JTklUKSB7XG4vLyAgICAgIC8qIEhpZ2ggd2F0ZXIgbWFyayBhdCBvciBhYm92ZSBjdXJyZW50IGRhdGEsIGJ1dCBiZWxvdyBjdXJyZW50IGRhdGFcbi8vICAgICAgICogcGx1cyBXSU5fSU5JVCAtLSB6ZXJvIG91dCB0byBjdXJyZW50IGRhdGEgcGx1cyBXSU5fSU5JVCwgb3IgdXBcbi8vICAgICAgICogdG8gZW5kIG9mIHdpbmRvdywgd2hpY2hldmVyIGlzIGxlc3MuXG4vLyAgICAgICAqL1xuLy8gICAgICBpbml0ID0gKHVsZyljdXJyICsgV0lOX0lOSVQgLSBzLT5oaWdoX3dhdGVyO1xuLy8gICAgICBpZiAoaW5pdCA+IHMtPndpbmRvd19zaXplIC0gcy0+aGlnaF93YXRlcilcbi8vICAgICAgICBpbml0ID0gcy0+d2luZG93X3NpemUgLSBzLT5oaWdoX3dhdGVyO1xuLy8gICAgICB6bWVtemVybyhzLT53aW5kb3cgKyBzLT5oaWdoX3dhdGVyLCAodW5zaWduZWQpaW5pdCk7XG4vLyAgICAgIHMtPmhpZ2hfd2F0ZXIgKz0gaW5pdDtcbi8vICAgIH1cbi8vICB9XG4vL1xuLy8gIEFzc2VydCgodWxnKXMtPnN0cnN0YXJ0IDw9IHMtPndpbmRvd19zaXplIC0gTUlOX0xPT0tBSEVBRCxcbi8vICAgIFwibm90IGVub3VnaCByb29tIGZvciBzZWFyY2hcIik7XG59O1xuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHkgd2l0aG91dCBjb21wcmVzc2lvbiBhcyBtdWNoIGFzIHBvc3NpYmxlIGZyb20gdGhlIGlucHV0IHN0cmVhbSwgcmV0dXJuXG4gKiB0aGUgY3VycmVudCBibG9jayBzdGF0ZS5cbiAqXG4gKiBJbiBjYXNlIGRlZmxhdGVQYXJhbXMoKSBpcyB1c2VkIHRvIGxhdGVyIHN3aXRjaCB0byBhIG5vbi16ZXJvIGNvbXByZXNzaW9uXG4gKiBsZXZlbCwgcy0+bWF0Y2hlcyAob3RoZXJ3aXNlIHVudXNlZCB3aGVuIHN0b3JpbmcpIGtlZXBzIHRyYWNrIG9mIHRoZSBudW1iZXJcbiAqIG9mIGhhc2ggdGFibGUgc2xpZGVzIHRvIHBlcmZvcm0uIElmIHMtPm1hdGNoZXMgaXMgMSwgdGhlbiBvbmUgaGFzaCB0YWJsZVxuICogc2xpZGUgd2lsbCBiZSBkb25lIHdoZW4gc3dpdGNoaW5nLiBJZiBzLT5tYXRjaGVzIGlzIDIsIHRoZSBtYXhpbXVtIHZhbHVlXG4gKiBhbGxvd2VkIGhlcmUsIHRoZW4gdGhlIGhhc2ggdGFibGUgd2lsbCBiZSBjbGVhcmVkLCBzaW5jZSB0d28gb3IgbW9yZSBzbGlkZXNcbiAqIGlzIHRoZSBzYW1lIGFzIGEgY2xlYXIuXG4gKlxuICogZGVmbGF0ZV9zdG9yZWQoKSBpcyB3cml0dGVuIHRvIG1pbmltaXplIHRoZSBudW1iZXIgb2YgdGltZXMgYW4gaW5wdXQgYnl0ZSBpc1xuICogY29waWVkLiBJdCBpcyBtb3N0IGVmZmljaWVudCB3aXRoIGxhcmdlIGlucHV0IGFuZCBvdXRwdXQgYnVmZmVycywgd2hpY2hcbiAqIG1heGltaXplcyB0aGUgb3Bwb3J0dW5pdGVzIHRvIGhhdmUgYSBzaW5nbGUgY29weSBmcm9tIG5leHRfaW4gdG8gbmV4dF9vdXQuXG4gKi9cbmNvbnN0IGRlZmxhdGVfc3RvcmVkID0gKHMsIGZsdXNoKSA9PiB7XG5cbiAgLyogU21hbGxlc3Qgd29ydGh5IGJsb2NrIHNpemUgd2hlbiBub3QgZmx1c2hpbmcgb3IgZmluaXNoaW5nLiBCeSBkZWZhdWx0XG4gICAqIHRoaXMgaXMgMzJLLiBUaGlzIGNhbiBiZSBhcyBzbWFsbCBhcyA1MDcgYnl0ZXMgZm9yIG1lbUxldmVsID09IDEuIEZvclxuICAgKiBsYXJnZSBpbnB1dCBhbmQgb3V0cHV0IGJ1ZmZlcnMsIHRoZSBzdG9yZWQgYmxvY2sgc2l6ZSB3aWxsIGJlIGxhcmdlci5cbiAgICovXG4gIGxldCBtaW5fYmxvY2sgPSBzLnBlbmRpbmdfYnVmX3NpemUgLSA1ID4gcy53X3NpemUgPyBzLndfc2l6ZSA6IHMucGVuZGluZ19idWZfc2l6ZSAtIDU7XG5cbiAgLyogQ29weSBhcyBtYW55IG1pbl9ibG9jayBvciBsYXJnZXIgc3RvcmVkIGJsb2NrcyBkaXJlY3RseSB0byBuZXh0X291dCBhc1xuICAgKiBwb3NzaWJsZS4gSWYgZmx1c2hpbmcsIGNvcHkgdGhlIHJlbWFpbmluZyBhdmFpbGFibGUgaW5wdXQgdG8gbmV4dF9vdXQgYXNcbiAgICogc3RvcmVkIGJsb2NrcywgaWYgdGhlcmUgaXMgZW5vdWdoIHNwYWNlLlxuICAgKi9cbiAgbGV0IGxlbiwgbGVmdCwgaGF2ZSwgbGFzdCA9IDA7XG4gIGxldCB1c2VkID0gcy5zdHJtLmF2YWlsX2luO1xuICBkbyB7XG4gICAgLyogU2V0IGxlbiB0byB0aGUgbWF4aW11bSBzaXplIGJsb2NrIHRoYXQgd2UgY2FuIGNvcHkgZGlyZWN0bHkgd2l0aCB0aGVcbiAgICAgKiBhdmFpbGFibGUgaW5wdXQgZGF0YSBhbmQgb3V0cHV0IHNwYWNlLiBTZXQgbGVmdCB0byBob3cgbXVjaCBvZiB0aGF0XG4gICAgICogd291bGQgYmUgY29waWVkIGZyb20gd2hhdCdzIGxlZnQgaW4gdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBsZW4gPSA2NTUzNS8qIE1BWF9TVE9SRUQgKi87ICAgICAvKiBtYXhpbXVtIGRlZmxhdGUgc3RvcmVkIGJsb2NrIGxlbmd0aCAqL1xuICAgIGhhdmUgPSAocy5iaV92YWxpZCArIDQyKSA+PiAzOyAgICAgLyogbnVtYmVyIG9mIGhlYWRlciBieXRlcyAqL1xuICAgIGlmIChzLnN0cm0uYXZhaWxfb3V0IDwgaGF2ZSkgeyAgICAgICAgIC8qIG5lZWQgcm9vbSBmb3IgaGVhZGVyICovXG4gICAgICBicmVhaztcbiAgICB9XG4gICAgICAvKiBtYXhpbXVtIHN0b3JlZCBibG9jayBsZW5ndGggdGhhdCB3aWxsIGZpdCBpbiBhdmFpbF9vdXQ6ICovXG4gICAgaGF2ZSA9IHMuc3RybS5hdmFpbF9vdXQgLSBoYXZlO1xuICAgIGxlZnQgPSBzLnN0cnN0YXJ0IC0gcy5ibG9ja19zdGFydDsgIC8qIGJ5dGVzIGxlZnQgaW4gd2luZG93ICovXG4gICAgaWYgKGxlbiA+IGxlZnQgKyBzLnN0cm0uYXZhaWxfaW4pIHtcbiAgICAgIGxlbiA9IGxlZnQgKyBzLnN0cm0uYXZhaWxfaW47ICAgLyogbGltaXQgbGVuIHRvIHRoZSBpbnB1dCAqL1xuICAgIH1cbiAgICBpZiAobGVuID4gaGF2ZSkge1xuICAgICAgbGVuID0gaGF2ZTsgICAgICAgICAgICAgLyogbGltaXQgbGVuIHRvIHRoZSBvdXRwdXQgKi9cbiAgICB9XG5cbiAgICAvKiBJZiB0aGUgc3RvcmVkIGJsb2NrIHdvdWxkIGJlIGxlc3MgdGhhbiBtaW5fYmxvY2sgaW4gbGVuZ3RoLCBvciBpZlxuICAgICAqIHVuYWJsZSB0byBjb3B5IGFsbCBvZiB0aGUgYXZhaWxhYmxlIGlucHV0IHdoZW4gZmx1c2hpbmcsIHRoZW4gdHJ5XG4gICAgICogY29weWluZyB0byB0aGUgd2luZG93IGFuZCB0aGUgcGVuZGluZyBidWZmZXIgaW5zdGVhZC4gQWxzbyBkb24ndFxuICAgICAqIHdyaXRlIGFuIGVtcHR5IGJsb2NrIHdoZW4gZmx1c2hpbmcgLS0gZGVmbGF0ZSgpIGRvZXMgdGhhdC5cbiAgICAgKi9cbiAgICBpZiAobGVuIDwgbWluX2Jsb2NrICYmICgobGVuID09PSAwICYmIGZsdXNoICE9PSBaX0ZJTklTSCQzKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgZmx1c2ggPT09IFpfTk9fRkxVU0gkMiB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgbGVuICE9PSBsZWZ0ICsgcy5zdHJtLmF2YWlsX2luKSkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgLyogTWFrZSBhIGR1bW15IHN0b3JlZCBibG9jayBpbiBwZW5kaW5nIHRvIGdldCB0aGUgaGVhZGVyIGJ5dGVzLFxuICAgICAqIGluY2x1ZGluZyBhbnkgcGVuZGluZyBiaXRzLiBUaGlzIGFsc28gdXBkYXRlcyB0aGUgZGVidWdnaW5nIGNvdW50cy5cbiAgICAgKi9cbiAgICBsYXN0ID0gZmx1c2ggPT09IFpfRklOSVNIJDMgJiYgbGVuID09PSBsZWZ0ICsgcy5zdHJtLmF2YWlsX2luID8gMSA6IDA7XG4gICAgX3RyX3N0b3JlZF9ibG9jayhzLCAwLCAwLCBsYXN0KTtcblxuICAgIC8qIFJlcGxhY2UgdGhlIGxlbmd0aHMgaW4gdGhlIGR1bW15IHN0b3JlZCBibG9jayB3aXRoIGxlbi4gKi9cbiAgICBzLnBlbmRpbmdfYnVmW3MucGVuZGluZyAtIDRdID0gbGVuO1xuICAgIHMucGVuZGluZ19idWZbcy5wZW5kaW5nIC0gM10gPSBsZW4gPj4gODtcbiAgICBzLnBlbmRpbmdfYnVmW3MucGVuZGluZyAtIDJdID0gfmxlbjtcbiAgICBzLnBlbmRpbmdfYnVmW3MucGVuZGluZyAtIDFdID0gfmxlbiA+PiA4O1xuXG4gICAgLyogV3JpdGUgdGhlIHN0b3JlZCBibG9jayBoZWFkZXIgYnl0ZXMuICovXG4gICAgZmx1c2hfcGVuZGluZyhzLnN0cm0pO1xuXG4vLyNpZmRlZiBaTElCX0RFQlVHXG4vLyAgICAvKiBVcGRhdGUgZGVidWdnaW5nIGNvdW50cyBmb3IgdGhlIGRhdGEgYWJvdXQgdG8gYmUgY29waWVkLiAqL1xuLy8gICAgcy0+Y29tcHJlc3NlZF9sZW4gKz0gbGVuIDw8IDM7XG4vLyAgICBzLT5iaXRzX3NlbnQgKz0gbGVuIDw8IDM7XG4vLyNlbmRpZlxuXG4gICAgLyogQ29weSB1bmNvbXByZXNzZWQgYnl0ZXMgZnJvbSB0aGUgd2luZG93IHRvIG5leHRfb3V0LiAqL1xuICAgIGlmIChsZWZ0KSB7XG4gICAgICBpZiAobGVmdCA+IGxlbikge1xuICAgICAgICBsZWZ0ID0gbGVuO1xuICAgICAgfVxuICAgICAgLy96bWVtY3B5KHMtPnN0cm0tPm5leHRfb3V0LCBzLT53aW5kb3cgKyBzLT5ibG9ja19zdGFydCwgbGVmdCk7XG4gICAgICBzLnN0cm0ub3V0cHV0LnNldChzLndpbmRvdy5zdWJhcnJheShzLmJsb2NrX3N0YXJ0LCBzLmJsb2NrX3N0YXJ0ICsgbGVmdCksIHMuc3RybS5uZXh0X291dCk7XG4gICAgICBzLnN0cm0ubmV4dF9vdXQgKz0gbGVmdDtcbiAgICAgIHMuc3RybS5hdmFpbF9vdXQgLT0gbGVmdDtcbiAgICAgIHMuc3RybS50b3RhbF9vdXQgKz0gbGVmdDtcbiAgICAgIHMuYmxvY2tfc3RhcnQgKz0gbGVmdDtcbiAgICAgIGxlbiAtPSBsZWZ0O1xuICAgIH1cblxuICAgIC8qIENvcHkgdW5jb21wcmVzc2VkIGJ5dGVzIGRpcmVjdGx5IGZyb20gbmV4dF9pbiB0byBuZXh0X291dCwgdXBkYXRpbmdcbiAgICAgKiB0aGUgY2hlY2sgdmFsdWUuXG4gICAgICovXG4gICAgaWYgKGxlbikge1xuICAgICAgcmVhZF9idWYocy5zdHJtLCBzLnN0cm0ub3V0cHV0LCBzLnN0cm0ubmV4dF9vdXQsIGxlbik7XG4gICAgICBzLnN0cm0ubmV4dF9vdXQgKz0gbGVuO1xuICAgICAgcy5zdHJtLmF2YWlsX291dCAtPSBsZW47XG4gICAgICBzLnN0cm0udG90YWxfb3V0ICs9IGxlbjtcbiAgICB9XG4gIH0gd2hpbGUgKGxhc3QgPT09IDApO1xuXG4gIC8qIFVwZGF0ZSB0aGUgc2xpZGluZyB3aW5kb3cgd2l0aCB0aGUgbGFzdCBzLT53X3NpemUgYnl0ZXMgb2YgdGhlIGNvcGllZFxuICAgKiBkYXRhLCBvciBhcHBlbmQgYWxsIG9mIHRoZSBjb3BpZWQgZGF0YSB0byB0aGUgZXhpc3Rpbmcgd2luZG93IGlmIGxlc3NcbiAgICogdGhhbiBzLT53X3NpemUgYnl0ZXMgd2VyZSBjb3BpZWQuIEFsc28gdXBkYXRlIHRoZSBudW1iZXIgb2YgYnl0ZXMgdG9cbiAgICogaW5zZXJ0IGluIHRoZSBoYXNoIHRhYmxlcywgaW4gdGhlIGV2ZW50IHRoYXQgZGVmbGF0ZVBhcmFtcygpIHN3aXRjaGVzIHRvXG4gICAqIGEgbm9uLXplcm8gY29tcHJlc3Npb24gbGV2ZWwuXG4gICAqL1xuICB1c2VkIC09IHMuc3RybS5hdmFpbF9pbjsgICAgLyogbnVtYmVyIG9mIGlucHV0IGJ5dGVzIGRpcmVjdGx5IGNvcGllZCAqL1xuICBpZiAodXNlZCkge1xuICAgIC8qIElmIGFueSBpbnB1dCB3YXMgdXNlZCwgdGhlbiBubyB1bnVzZWQgaW5wdXQgcmVtYWlucyBpbiB0aGUgd2luZG93LFxuICAgICAqIHRoZXJlZm9yZSBzLT5ibG9ja19zdGFydCA9PSBzLT5zdHJzdGFydC5cbiAgICAgKi9cbiAgICBpZiAodXNlZCA+PSBzLndfc2l6ZSkgeyAgLyogc3VwcGxhbnQgdGhlIHByZXZpb3VzIGhpc3RvcnkgKi9cbiAgICAgIHMubWF0Y2hlcyA9IDI7ICAgICAvKiBjbGVhciBoYXNoICovXG4gICAgICAvL3ptZW1jcHkocy0+d2luZG93LCBzLT5zdHJtLT5uZXh0X2luIC0gcy0+d19zaXplLCBzLT53X3NpemUpO1xuICAgICAgcy53aW5kb3cuc2V0KHMuc3RybS5pbnB1dC5zdWJhcnJheShzLnN0cm0ubmV4dF9pbiAtIHMud19zaXplLCBzLnN0cm0ubmV4dF9pbiksIDApO1xuICAgICAgcy5zdHJzdGFydCA9IHMud19zaXplO1xuICAgICAgcy5pbnNlcnQgPSBzLnN0cnN0YXJ0O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIGlmIChzLndpbmRvd19zaXplIC0gcy5zdHJzdGFydCA8PSB1c2VkKSB7XG4gICAgICAgIC8qIFNsaWRlIHRoZSB3aW5kb3cgZG93bi4gKi9cbiAgICAgICAgcy5zdHJzdGFydCAtPSBzLndfc2l6ZTtcbiAgICAgICAgLy96bWVtY3B5KHMtPndpbmRvdywgcy0+d2luZG93ICsgcy0+d19zaXplLCBzLT5zdHJzdGFydCk7XG4gICAgICAgIHMud2luZG93LnNldChzLndpbmRvdy5zdWJhcnJheShzLndfc2l6ZSwgcy53X3NpemUgKyBzLnN0cnN0YXJ0KSwgMCk7XG4gICAgICAgIGlmIChzLm1hdGNoZXMgPCAyKSB7XG4gICAgICAgICAgcy5tYXRjaGVzKys7ICAgLyogYWRkIGEgcGVuZGluZyBzbGlkZV9oYXNoKCkgKi9cbiAgICAgICAgfVxuICAgICAgICBpZiAocy5pbnNlcnQgPiBzLnN0cnN0YXJ0KSB7XG4gICAgICAgICAgcy5pbnNlcnQgPSBzLnN0cnN0YXJ0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvL3ptZW1jcHkocy0+d2luZG93ICsgcy0+c3Ryc3RhcnQsIHMtPnN0cm0tPm5leHRfaW4gLSB1c2VkLCB1c2VkKTtcbiAgICAgIHMud2luZG93LnNldChzLnN0cm0uaW5wdXQuc3ViYXJyYXkocy5zdHJtLm5leHRfaW4gLSB1c2VkLCBzLnN0cm0ubmV4dF9pbiksIHMuc3Ryc3RhcnQpO1xuICAgICAgcy5zdHJzdGFydCArPSB1c2VkO1xuICAgICAgcy5pbnNlcnQgKz0gdXNlZCA+IHMud19zaXplIC0gcy5pbnNlcnQgPyBzLndfc2l6ZSAtIHMuaW5zZXJ0IDogdXNlZDtcbiAgICB9XG4gICAgcy5ibG9ja19zdGFydCA9IHMuc3Ryc3RhcnQ7XG4gIH1cbiAgaWYgKHMuaGlnaF93YXRlciA8IHMuc3Ryc3RhcnQpIHtcbiAgICBzLmhpZ2hfd2F0ZXIgPSBzLnN0cnN0YXJ0O1xuICB9XG5cbiAgLyogSWYgdGhlIGxhc3QgYmxvY2sgd2FzIHdyaXR0ZW4gdG8gbmV4dF9vdXQsIHRoZW4gZG9uZS4gKi9cbiAgaWYgKGxhc3QpIHtcbiAgICByZXR1cm4gQlNfRklOSVNIX0RPTkU7XG4gIH1cblxuICAvKiBJZiBmbHVzaGluZyBhbmQgYWxsIGlucHV0IGhhcyBiZWVuIGNvbnN1bWVkLCB0aGVuIGRvbmUuICovXG4gIGlmIChmbHVzaCAhPT0gWl9OT19GTFVTSCQyICYmIGZsdXNoICE9PSBaX0ZJTklTSCQzICYmXG4gICAgcy5zdHJtLmF2YWlsX2luID09PSAwICYmIHMuc3Ryc3RhcnQgPT09IHMuYmxvY2tfc3RhcnQpIHtcbiAgICByZXR1cm4gQlNfQkxPQ0tfRE9ORTtcbiAgfVxuXG4gIC8qIEZpbGwgdGhlIHdpbmRvdyB3aXRoIGFueSByZW1haW5pbmcgaW5wdXQuICovXG4gIGhhdmUgPSBzLndpbmRvd19zaXplIC0gcy5zdHJzdGFydDtcbiAgaWYgKHMuc3RybS5hdmFpbF9pbiA+IGhhdmUgJiYgcy5ibG9ja19zdGFydCA+PSBzLndfc2l6ZSkge1xuICAgIC8qIFNsaWRlIHRoZSB3aW5kb3cgZG93bi4gKi9cbiAgICBzLmJsb2NrX3N0YXJ0IC09IHMud19zaXplO1xuICAgIHMuc3Ryc3RhcnQgLT0gcy53X3NpemU7XG4gICAgLy96bWVtY3B5KHMtPndpbmRvdywgcy0+d2luZG93ICsgcy0+d19zaXplLCBzLT5zdHJzdGFydCk7XG4gICAgcy53aW5kb3cuc2V0KHMud2luZG93LnN1YmFycmF5KHMud19zaXplLCBzLndfc2l6ZSArIHMuc3Ryc3RhcnQpLCAwKTtcbiAgICBpZiAocy5tYXRjaGVzIDwgMikge1xuICAgICAgcy5tYXRjaGVzKys7ICAgICAgIC8qIGFkZCBhIHBlbmRpbmcgc2xpZGVfaGFzaCgpICovXG4gICAgfVxuICAgIGhhdmUgKz0gcy53X3NpemU7ICAgICAgLyogbW9yZSBzcGFjZSBub3cgKi9cbiAgICBpZiAocy5pbnNlcnQgPiBzLnN0cnN0YXJ0KSB7XG4gICAgICBzLmluc2VydCA9IHMuc3Ryc3RhcnQ7XG4gICAgfVxuICB9XG4gIGlmIChoYXZlID4gcy5zdHJtLmF2YWlsX2luKSB7XG4gICAgaGF2ZSA9IHMuc3RybS5hdmFpbF9pbjtcbiAgfVxuICBpZiAoaGF2ZSkge1xuICAgIHJlYWRfYnVmKHMuc3RybSwgcy53aW5kb3csIHMuc3Ryc3RhcnQsIGhhdmUpO1xuICAgIHMuc3Ryc3RhcnQgKz0gaGF2ZTtcbiAgICBzLmluc2VydCArPSBoYXZlID4gcy53X3NpemUgLSBzLmluc2VydCA/IHMud19zaXplIC0gcy5pbnNlcnQgOiBoYXZlO1xuICB9XG4gIGlmIChzLmhpZ2hfd2F0ZXIgPCBzLnN0cnN0YXJ0KSB7XG4gICAgcy5oaWdoX3dhdGVyID0gcy5zdHJzdGFydDtcbiAgfVxuXG4gIC8qIFRoZXJlIHdhcyBub3QgZW5vdWdoIGF2YWlsX291dCB0byB3cml0ZSBhIGNvbXBsZXRlIHdvcnRoeSBvciBmbHVzaGVkXG4gICAqIHN0b3JlZCBibG9jayB0byBuZXh0X291dC4gV3JpdGUgYSBzdG9yZWQgYmxvY2sgdG8gcGVuZGluZyBpbnN0ZWFkLCBpZiB3ZVxuICAgKiBoYXZlIGVub3VnaCBpbnB1dCBmb3IgYSB3b3J0aHkgYmxvY2ssIG9yIGlmIGZsdXNoaW5nIGFuZCB0aGVyZSBpcyBlbm91Z2hcbiAgICogcm9vbSBmb3IgdGhlIHJlbWFpbmluZyBpbnB1dCBhcyBhIHN0b3JlZCBibG9jayBpbiB0aGUgcGVuZGluZyBidWZmZXIuXG4gICAqL1xuICBoYXZlID0gKHMuYmlfdmFsaWQgKyA0MikgPj4gMzsgICAgIC8qIG51bWJlciBvZiBoZWFkZXIgYnl0ZXMgKi9cbiAgICAvKiBtYXhpbXVtIHN0b3JlZCBibG9jayBsZW5ndGggdGhhdCB3aWxsIGZpdCBpbiBwZW5kaW5nOiAqL1xuICBoYXZlID0gcy5wZW5kaW5nX2J1Zl9zaXplIC0gaGF2ZSA+IDY1NTM1LyogTUFYX1NUT1JFRCAqLyA/IDY1NTM1LyogTUFYX1NUT1JFRCAqLyA6IHMucGVuZGluZ19idWZfc2l6ZSAtIGhhdmU7XG4gIG1pbl9ibG9jayA9IGhhdmUgPiBzLndfc2l6ZSA/IHMud19zaXplIDogaGF2ZTtcbiAgbGVmdCA9IHMuc3Ryc3RhcnQgLSBzLmJsb2NrX3N0YXJ0O1xuICBpZiAobGVmdCA+PSBtaW5fYmxvY2sgfHxcbiAgICAgKChsZWZ0IHx8IGZsdXNoID09PSBaX0ZJTklTSCQzKSAmJiBmbHVzaCAhPT0gWl9OT19GTFVTSCQyICYmXG4gICAgIHMuc3RybS5hdmFpbF9pbiA9PT0gMCAmJiBsZWZ0IDw9IGhhdmUpKSB7XG4gICAgbGVuID0gbGVmdCA+IGhhdmUgPyBoYXZlIDogbGVmdDtcbiAgICBsYXN0ID0gZmx1c2ggPT09IFpfRklOSVNIJDMgJiYgcy5zdHJtLmF2YWlsX2luID09PSAwICYmXG4gICAgICAgICBsZW4gPT09IGxlZnQgPyAxIDogMDtcbiAgICBfdHJfc3RvcmVkX2Jsb2NrKHMsIHMuYmxvY2tfc3RhcnQsIGxlbiwgbGFzdCk7XG4gICAgcy5ibG9ja19zdGFydCArPSBsZW47XG4gICAgZmx1c2hfcGVuZGluZyhzLnN0cm0pO1xuICB9XG5cbiAgLyogV2UndmUgZG9uZSBhbGwgd2UgY2FuIHdpdGggdGhlIGF2YWlsYWJsZSBpbnB1dCBhbmQgb3V0cHV0LiAqL1xuICByZXR1cm4gbGFzdCA/IEJTX0ZJTklTSF9TVEFSVEVEIDogQlNfTkVFRF9NT1JFO1xufTtcblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvbXByZXNzIGFzIG11Y2ggYXMgcG9zc2libGUgZnJvbSB0aGUgaW5wdXQgc3RyZWFtLCByZXR1cm4gdGhlIGN1cnJlbnRcbiAqIGJsb2NrIHN0YXRlLlxuICogVGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBwZXJmb3JtIGxhenkgZXZhbHVhdGlvbiBvZiBtYXRjaGVzIGFuZCBpbnNlcnRzXG4gKiBuZXcgc3RyaW5ncyBpbiB0aGUgZGljdGlvbmFyeSBvbmx5IGZvciB1bm1hdGNoZWQgc3RyaW5ncyBvciBmb3Igc2hvcnRcbiAqIG1hdGNoZXMuIEl0IGlzIHVzZWQgb25seSBmb3IgdGhlIGZhc3QgY29tcHJlc3Npb24gb3B0aW9ucy5cbiAqL1xuY29uc3QgZGVmbGF0ZV9mYXN0ID0gKHMsIGZsdXNoKSA9PiB7XG5cbiAgbGV0IGhhc2hfaGVhZDsgICAgICAgIC8qIGhlYWQgb2YgdGhlIGhhc2ggY2hhaW4gKi9cbiAgbGV0IGJmbHVzaDsgICAgICAgICAgIC8qIHNldCBpZiBjdXJyZW50IGJsb2NrIG11c3QgYmUgZmx1c2hlZCAqL1xuXG4gIGZvciAoOzspIHtcbiAgICAvKiBNYWtlIHN1cmUgdGhhdCB3ZSBhbHdheXMgaGF2ZSBlbm91Z2ggbG9va2FoZWFkLCBleGNlcHRcbiAgICAgKiBhdCB0aGUgZW5kIG9mIHRoZSBpbnB1dCBmaWxlLiBXZSBuZWVkIE1BWF9NQVRDSCBieXRlc1xuICAgICAqIGZvciB0aGUgbmV4dCBtYXRjaCwgcGx1cyBNSU5fTUFUQ0ggYnl0ZXMgdG8gaW5zZXJ0IHRoZVxuICAgICAqIHN0cmluZyBmb2xsb3dpbmcgdGhlIG5leHQgbWF0Y2guXG4gICAgICovXG4gICAgaWYgKHMubG9va2FoZWFkIDwgTUlOX0xPT0tBSEVBRCkge1xuICAgICAgZmlsbF93aW5kb3cocyk7XG4gICAgICBpZiAocy5sb29rYWhlYWQgPCBNSU5fTE9PS0FIRUFEICYmIGZsdXNoID09PSBaX05PX0ZMVVNIJDIpIHtcbiAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgIH1cbiAgICAgIGlmIChzLmxvb2thaGVhZCA9PT0gMCkge1xuICAgICAgICBicmVhazsgLyogZmx1c2ggdGhlIGN1cnJlbnQgYmxvY2sgKi9cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKiBJbnNlcnQgdGhlIHN0cmluZyB3aW5kb3dbc3Ryc3RhcnQgLi4gc3Ryc3RhcnQrMl0gaW4gdGhlXG4gICAgICogZGljdGlvbmFyeSwgYW5kIHNldCBoYXNoX2hlYWQgdG8gdGhlIGhlYWQgb2YgdGhlIGhhc2ggY2hhaW46XG4gICAgICovXG4gICAgaGFzaF9oZWFkID0gMC8qTklMKi87XG4gICAgaWYgKHMubG9va2FoZWFkID49IE1JTl9NQVRDSCkge1xuICAgICAgLyoqKiBJTlNFUlRfU1RSSU5HKHMsIHMuc3Ryc3RhcnQsIGhhc2hfaGVhZCk7ICoqKi9cbiAgICAgIHMuaW5zX2ggPSBIQVNIKHMsIHMuaW5zX2gsIHMud2luZG93W3Muc3Ryc3RhcnQgKyBNSU5fTUFUQ0ggLSAxXSk7XG4gICAgICBoYXNoX2hlYWQgPSBzLnByZXZbcy5zdHJzdGFydCAmIHMud19tYXNrXSA9IHMuaGVhZFtzLmluc19oXTtcbiAgICAgIHMuaGVhZFtzLmluc19oXSA9IHMuc3Ryc3RhcnQ7XG4gICAgICAvKioqL1xuICAgIH1cblxuICAgIC8qIEZpbmQgdGhlIGxvbmdlc3QgbWF0Y2gsIGRpc2NhcmRpbmcgdGhvc2UgPD0gcHJldl9sZW5ndGguXG4gICAgICogQXQgdGhpcyBwb2ludCB3ZSBoYXZlIGFsd2F5cyBtYXRjaF9sZW5ndGggPCBNSU5fTUFUQ0hcbiAgICAgKi9cbiAgICBpZiAoaGFzaF9oZWFkICE9PSAwLypOSUwqLyAmJiAoKHMuc3Ryc3RhcnQgLSBoYXNoX2hlYWQpIDw9IChzLndfc2l6ZSAtIE1JTl9MT09LQUhFQUQpKSkge1xuICAgICAgLyogVG8gc2ltcGxpZnkgdGhlIGNvZGUsIHdlIHByZXZlbnQgbWF0Y2hlcyB3aXRoIHRoZSBzdHJpbmdcbiAgICAgICAqIG9mIHdpbmRvdyBpbmRleCAwIChpbiBwYXJ0aWN1bGFyIHdlIGhhdmUgdG8gYXZvaWQgYSBtYXRjaFxuICAgICAgICogb2YgdGhlIHN0cmluZyB3aXRoIGl0c2VsZiBhdCB0aGUgc3RhcnQgb2YgdGhlIGlucHV0IGZpbGUpLlxuICAgICAgICovXG4gICAgICBzLm1hdGNoX2xlbmd0aCA9IGxvbmdlc3RfbWF0Y2gocywgaGFzaF9oZWFkKTtcbiAgICAgIC8qIGxvbmdlc3RfbWF0Y2goKSBzZXRzIG1hdGNoX3N0YXJ0ICovXG4gICAgfVxuICAgIGlmIChzLm1hdGNoX2xlbmd0aCA+PSBNSU5fTUFUQ0gpIHtcbiAgICAgIC8vIGNoZWNrX21hdGNoKHMsIHMuc3Ryc3RhcnQsIHMubWF0Y2hfc3RhcnQsIHMubWF0Y2hfbGVuZ3RoKTsgLy8gZm9yIGRlYnVnIG9ubHlcblxuICAgICAgLyoqKiBfdHJfdGFsbHlfZGlzdChzLCBzLnN0cnN0YXJ0IC0gcy5tYXRjaF9zdGFydCxcbiAgICAgICAgICAgICAgICAgICAgIHMubWF0Y2hfbGVuZ3RoIC0gTUlOX01BVENILCBiZmx1c2gpOyAqKiovXG4gICAgICBiZmx1c2ggPSBfdHJfdGFsbHkocywgcy5zdHJzdGFydCAtIHMubWF0Y2hfc3RhcnQsIHMubWF0Y2hfbGVuZ3RoIC0gTUlOX01BVENIKTtcblxuICAgICAgcy5sb29rYWhlYWQgLT0gcy5tYXRjaF9sZW5ndGg7XG5cbiAgICAgIC8qIEluc2VydCBuZXcgc3RyaW5ncyBpbiB0aGUgaGFzaCB0YWJsZSBvbmx5IGlmIHRoZSBtYXRjaCBsZW5ndGhcbiAgICAgICAqIGlzIG5vdCB0b28gbGFyZ2UuIFRoaXMgc2F2ZXMgdGltZSBidXQgZGVncmFkZXMgY29tcHJlc3Npb24uXG4gICAgICAgKi9cbiAgICAgIGlmIChzLm1hdGNoX2xlbmd0aCA8PSBzLm1heF9sYXp5X21hdGNoLyptYXhfaW5zZXJ0X2xlbmd0aCovICYmIHMubG9va2FoZWFkID49IE1JTl9NQVRDSCkge1xuICAgICAgICBzLm1hdGNoX2xlbmd0aC0tOyAvKiBzdHJpbmcgYXQgc3Ryc3RhcnQgYWxyZWFkeSBpbiB0YWJsZSAqL1xuICAgICAgICBkbyB7XG4gICAgICAgICAgcy5zdHJzdGFydCsrO1xuICAgICAgICAgIC8qKiogSU5TRVJUX1NUUklORyhzLCBzLnN0cnN0YXJ0LCBoYXNoX2hlYWQpOyAqKiovXG4gICAgICAgICAgcy5pbnNfaCA9IEhBU0gocywgcy5pbnNfaCwgcy53aW5kb3dbcy5zdHJzdGFydCArIE1JTl9NQVRDSCAtIDFdKTtcbiAgICAgICAgICBoYXNoX2hlYWQgPSBzLnByZXZbcy5zdHJzdGFydCAmIHMud19tYXNrXSA9IHMuaGVhZFtzLmluc19oXTtcbiAgICAgICAgICBzLmhlYWRbcy5pbnNfaF0gPSBzLnN0cnN0YXJ0O1xuICAgICAgICAgIC8qKiovXG4gICAgICAgICAgLyogc3Ryc3RhcnQgbmV2ZXIgZXhjZWVkcyBXU0laRS1NQVhfTUFUQ0gsIHNvIHRoZXJlIGFyZVxuICAgICAgICAgICAqIGFsd2F5cyBNSU5fTUFUQ0ggYnl0ZXMgYWhlYWQuXG4gICAgICAgICAgICovXG4gICAgICAgIH0gd2hpbGUgKC0tcy5tYXRjaF9sZW5ndGggIT09IDApO1xuICAgICAgICBzLnN0cnN0YXJ0Kys7XG4gICAgICB9IGVsc2VcbiAgICAgIHtcbiAgICAgICAgcy5zdHJzdGFydCArPSBzLm1hdGNoX2xlbmd0aDtcbiAgICAgICAgcy5tYXRjaF9sZW5ndGggPSAwO1xuICAgICAgICBzLmluc19oID0gcy53aW5kb3dbcy5zdHJzdGFydF07XG4gICAgICAgIC8qIFVQREFURV9IQVNIKHMsIHMuaW5zX2gsIHMud2luZG93W3Muc3Ryc3RhcnQrMV0pOyAqL1xuICAgICAgICBzLmluc19oID0gSEFTSChzLCBzLmluc19oLCBzLndpbmRvd1tzLnN0cnN0YXJ0ICsgMV0pO1xuXG4vLyNpZiBNSU5fTUFUQ0ggIT0gM1xuLy8gICAgICAgICAgICAgICAgQ2FsbCBVUERBVEVfSEFTSCgpIE1JTl9NQVRDSC0zIG1vcmUgdGltZXNcbi8vI2VuZGlmXG4gICAgICAgIC8qIElmIGxvb2thaGVhZCA8IE1JTl9NQVRDSCwgaW5zX2ggaXMgZ2FyYmFnZSwgYnV0IGl0IGRvZXMgbm90XG4gICAgICAgICAqIG1hdHRlciBzaW5jZSBpdCB3aWxsIGJlIHJlY29tcHV0ZWQgYXQgbmV4dCBkZWZsYXRlIGNhbGwuXG4gICAgICAgICAqL1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvKiBObyBtYXRjaCwgb3V0cHV0IGEgbGl0ZXJhbCBieXRlICovXG4gICAgICAvL1RyYWNldnYoKHN0ZGVycixcIiVjXCIsIHMud2luZG93W3Muc3Ryc3RhcnRdKSk7XG4gICAgICAvKioqIF90cl90YWxseV9saXQocywgcy53aW5kb3dbcy5zdHJzdGFydF0sIGJmbHVzaCk7ICoqKi9cbiAgICAgIGJmbHVzaCA9IF90cl90YWxseShzLCAwLCBzLndpbmRvd1tzLnN0cnN0YXJ0XSk7XG5cbiAgICAgIHMubG9va2FoZWFkLS07XG4gICAgICBzLnN0cnN0YXJ0Kys7XG4gICAgfVxuICAgIGlmIChiZmx1c2gpIHtcbiAgICAgIC8qKiogRkxVU0hfQkxPQ0socywgMCk7ICoqKi9cbiAgICAgIGZsdXNoX2Jsb2NrX29ubHkocywgZmFsc2UpO1xuICAgICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgIH1cbiAgICAgIC8qKiovXG4gICAgfVxuICB9XG4gIHMuaW5zZXJ0ID0gKChzLnN0cnN0YXJ0IDwgKE1JTl9NQVRDSCAtIDEpKSA/IHMuc3Ryc3RhcnQgOiBNSU5fTUFUQ0ggLSAxKTtcbiAgaWYgKGZsdXNoID09PSBaX0ZJTklTSCQzKSB7XG4gICAgLyoqKiBGTFVTSF9CTE9DSyhzLCAxKTsgKioqL1xuICAgIGZsdXNoX2Jsb2NrX29ubHkocywgdHJ1ZSk7XG4gICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgIHJldHVybiBCU19GSU5JU0hfU1RBUlRFRDtcbiAgICB9XG4gICAgLyoqKi9cbiAgICByZXR1cm4gQlNfRklOSVNIX0RPTkU7XG4gIH1cbiAgaWYgKHMuc3ltX25leHQpIHtcbiAgICAvKioqIEZMVVNIX0JMT0NLKHMsIDApOyAqKiovXG4gICAgZmx1c2hfYmxvY2tfb25seShzLCBmYWxzZSk7XG4gICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgIHJldHVybiBCU19ORUVEX01PUkU7XG4gICAgfVxuICAgIC8qKiovXG4gIH1cbiAgcmV0dXJuIEJTX0JMT0NLX0RPTkU7XG59O1xuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFNhbWUgYXMgYWJvdmUsIGJ1dCBhY2hpZXZlcyBiZXR0ZXIgY29tcHJlc3Npb24uIFdlIHVzZSBhIGxhenlcbiAqIGV2YWx1YXRpb24gZm9yIG1hdGNoZXM6IGEgbWF0Y2ggaXMgZmluYWxseSBhZG9wdGVkIG9ubHkgaWYgdGhlcmUgaXNcbiAqIG5vIGJldHRlciBtYXRjaCBhdCB0aGUgbmV4dCB3aW5kb3cgcG9zaXRpb24uXG4gKi9cbmNvbnN0IGRlZmxhdGVfc2xvdyA9IChzLCBmbHVzaCkgPT4ge1xuXG4gIGxldCBoYXNoX2hlYWQ7ICAgICAgICAgIC8qIGhlYWQgb2YgaGFzaCBjaGFpbiAqL1xuICBsZXQgYmZsdXNoOyAgICAgICAgICAgICAgLyogc2V0IGlmIGN1cnJlbnQgYmxvY2sgbXVzdCBiZSBmbHVzaGVkICovXG5cbiAgbGV0IG1heF9pbnNlcnQ7XG5cbiAgLyogUHJvY2VzcyB0aGUgaW5wdXQgYmxvY2suICovXG4gIGZvciAoOzspIHtcbiAgICAvKiBNYWtlIHN1cmUgdGhhdCB3ZSBhbHdheXMgaGF2ZSBlbm91Z2ggbG9va2FoZWFkLCBleGNlcHRcbiAgICAgKiBhdCB0aGUgZW5kIG9mIHRoZSBpbnB1dCBmaWxlLiBXZSBuZWVkIE1BWF9NQVRDSCBieXRlc1xuICAgICAqIGZvciB0aGUgbmV4dCBtYXRjaCwgcGx1cyBNSU5fTUFUQ0ggYnl0ZXMgdG8gaW5zZXJ0IHRoZVxuICAgICAqIHN0cmluZyBmb2xsb3dpbmcgdGhlIG5leHQgbWF0Y2guXG4gICAgICovXG4gICAgaWYgKHMubG9va2FoZWFkIDwgTUlOX0xPT0tBSEVBRCkge1xuICAgICAgZmlsbF93aW5kb3cocyk7XG4gICAgICBpZiAocy5sb29rYWhlYWQgPCBNSU5fTE9PS0FIRUFEICYmIGZsdXNoID09PSBaX05PX0ZMVVNIJDIpIHtcbiAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgIH1cbiAgICAgIGlmIChzLmxvb2thaGVhZCA9PT0gMCkgeyBicmVhazsgfSAvKiBmbHVzaCB0aGUgY3VycmVudCBibG9jayAqL1xuICAgIH1cblxuICAgIC8qIEluc2VydCB0aGUgc3RyaW5nIHdpbmRvd1tzdHJzdGFydCAuLiBzdHJzdGFydCsyXSBpbiB0aGVcbiAgICAgKiBkaWN0aW9uYXJ5LCBhbmQgc2V0IGhhc2hfaGVhZCB0byB0aGUgaGVhZCBvZiB0aGUgaGFzaCBjaGFpbjpcbiAgICAgKi9cbiAgICBoYXNoX2hlYWQgPSAwLypOSUwqLztcbiAgICBpZiAocy5sb29rYWhlYWQgPj0gTUlOX01BVENIKSB7XG4gICAgICAvKioqIElOU0VSVF9TVFJJTkcocywgcy5zdHJzdGFydCwgaGFzaF9oZWFkKTsgKioqL1xuICAgICAgcy5pbnNfaCA9IEhBU0gocywgcy5pbnNfaCwgcy53aW5kb3dbcy5zdHJzdGFydCArIE1JTl9NQVRDSCAtIDFdKTtcbiAgICAgIGhhc2hfaGVhZCA9IHMucHJldltzLnN0cnN0YXJ0ICYgcy53X21hc2tdID0gcy5oZWFkW3MuaW5zX2hdO1xuICAgICAgcy5oZWFkW3MuaW5zX2hdID0gcy5zdHJzdGFydDtcbiAgICAgIC8qKiovXG4gICAgfVxuXG4gICAgLyogRmluZCB0aGUgbG9uZ2VzdCBtYXRjaCwgZGlzY2FyZGluZyB0aG9zZSA8PSBwcmV2X2xlbmd0aC5cbiAgICAgKi9cbiAgICBzLnByZXZfbGVuZ3RoID0gcy5tYXRjaF9sZW5ndGg7XG4gICAgcy5wcmV2X21hdGNoID0gcy5tYXRjaF9zdGFydDtcbiAgICBzLm1hdGNoX2xlbmd0aCA9IE1JTl9NQVRDSCAtIDE7XG5cbiAgICBpZiAoaGFzaF9oZWFkICE9PSAwLypOSUwqLyAmJiBzLnByZXZfbGVuZ3RoIDwgcy5tYXhfbGF6eV9tYXRjaCAmJlxuICAgICAgICBzLnN0cnN0YXJ0IC0gaGFzaF9oZWFkIDw9IChzLndfc2l6ZSAtIE1JTl9MT09LQUhFQUQpLypNQVhfRElTVChzKSovKSB7XG4gICAgICAvKiBUbyBzaW1wbGlmeSB0aGUgY29kZSwgd2UgcHJldmVudCBtYXRjaGVzIHdpdGggdGhlIHN0cmluZ1xuICAgICAgICogb2Ygd2luZG93IGluZGV4IDAgKGluIHBhcnRpY3VsYXIgd2UgaGF2ZSB0byBhdm9pZCBhIG1hdGNoXG4gICAgICAgKiBvZiB0aGUgc3RyaW5nIHdpdGggaXRzZWxmIGF0IHRoZSBzdGFydCBvZiB0aGUgaW5wdXQgZmlsZSkuXG4gICAgICAgKi9cbiAgICAgIHMubWF0Y2hfbGVuZ3RoID0gbG9uZ2VzdF9tYXRjaChzLCBoYXNoX2hlYWQpO1xuICAgICAgLyogbG9uZ2VzdF9tYXRjaCgpIHNldHMgbWF0Y2hfc3RhcnQgKi9cblxuICAgICAgaWYgKHMubWF0Y2hfbGVuZ3RoIDw9IDUgJiZcbiAgICAgICAgIChzLnN0cmF0ZWd5ID09PSBaX0ZJTFRFUkVEIHx8IChzLm1hdGNoX2xlbmd0aCA9PT0gTUlOX01BVENIICYmIHMuc3Ryc3RhcnQgLSBzLm1hdGNoX3N0YXJ0ID4gNDA5Ni8qVE9PX0ZBUiovKSkpIHtcblxuICAgICAgICAvKiBJZiBwcmV2X21hdGNoIGlzIGFsc28gTUlOX01BVENILCBtYXRjaF9zdGFydCBpcyBnYXJiYWdlXG4gICAgICAgICAqIGJ1dCB3ZSB3aWxsIGlnbm9yZSB0aGUgY3VycmVudCBtYXRjaCBhbnl3YXkuXG4gICAgICAgICAqL1xuICAgICAgICBzLm1hdGNoX2xlbmd0aCA9IE1JTl9NQVRDSCAtIDE7XG4gICAgICB9XG4gICAgfVxuICAgIC8qIElmIHRoZXJlIHdhcyBhIG1hdGNoIGF0IHRoZSBwcmV2aW91cyBzdGVwIGFuZCB0aGUgY3VycmVudFxuICAgICAqIG1hdGNoIGlzIG5vdCBiZXR0ZXIsIG91dHB1dCB0aGUgcHJldmlvdXMgbWF0Y2g6XG4gICAgICovXG4gICAgaWYgKHMucHJldl9sZW5ndGggPj0gTUlOX01BVENIICYmIHMubWF0Y2hfbGVuZ3RoIDw9IHMucHJldl9sZW5ndGgpIHtcbiAgICAgIG1heF9pbnNlcnQgPSBzLnN0cnN0YXJ0ICsgcy5sb29rYWhlYWQgLSBNSU5fTUFUQ0g7XG4gICAgICAvKiBEbyBub3QgaW5zZXJ0IHN0cmluZ3MgaW4gaGFzaCB0YWJsZSBiZXlvbmQgdGhpcy4gKi9cblxuICAgICAgLy9jaGVja19tYXRjaChzLCBzLnN0cnN0YXJ0LTEsIHMucHJldl9tYXRjaCwgcy5wcmV2X2xlbmd0aCk7XG5cbiAgICAgIC8qKipfdHJfdGFsbHlfZGlzdChzLCBzLnN0cnN0YXJ0IC0gMSAtIHMucHJldl9tYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgIHMucHJldl9sZW5ndGggLSBNSU5fTUFUQ0gsIGJmbHVzaCk7KioqL1xuICAgICAgYmZsdXNoID0gX3RyX3RhbGx5KHMsIHMuc3Ryc3RhcnQgLSAxIC0gcy5wcmV2X21hdGNoLCBzLnByZXZfbGVuZ3RoIC0gTUlOX01BVENIKTtcbiAgICAgIC8qIEluc2VydCBpbiBoYXNoIHRhYmxlIGFsbCBzdHJpbmdzIHVwIHRvIHRoZSBlbmQgb2YgdGhlIG1hdGNoLlxuICAgICAgICogc3Ryc3RhcnQtMSBhbmQgc3Ryc3RhcnQgYXJlIGFscmVhZHkgaW5zZXJ0ZWQuIElmIHRoZXJlIGlzIG5vdFxuICAgICAgICogZW5vdWdoIGxvb2thaGVhZCwgdGhlIGxhc3QgdHdvIHN0cmluZ3MgYXJlIG5vdCBpbnNlcnRlZCBpblxuICAgICAgICogdGhlIGhhc2ggdGFibGUuXG4gICAgICAgKi9cbiAgICAgIHMubG9va2FoZWFkIC09IHMucHJldl9sZW5ndGggLSAxO1xuICAgICAgcy5wcmV2X2xlbmd0aCAtPSAyO1xuICAgICAgZG8ge1xuICAgICAgICBpZiAoKytzLnN0cnN0YXJ0IDw9IG1heF9pbnNlcnQpIHtcbiAgICAgICAgICAvKioqIElOU0VSVF9TVFJJTkcocywgcy5zdHJzdGFydCwgaGFzaF9oZWFkKTsgKioqL1xuICAgICAgICAgIHMuaW5zX2ggPSBIQVNIKHMsIHMuaW5zX2gsIHMud2luZG93W3Muc3Ryc3RhcnQgKyBNSU5fTUFUQ0ggLSAxXSk7XG4gICAgICAgICAgaGFzaF9oZWFkID0gcy5wcmV2W3Muc3Ryc3RhcnQgJiBzLndfbWFza10gPSBzLmhlYWRbcy5pbnNfaF07XG4gICAgICAgICAgcy5oZWFkW3MuaW5zX2hdID0gcy5zdHJzdGFydDtcbiAgICAgICAgICAvKioqL1xuICAgICAgICB9XG4gICAgICB9IHdoaWxlICgtLXMucHJldl9sZW5ndGggIT09IDApO1xuICAgICAgcy5tYXRjaF9hdmFpbGFibGUgPSAwO1xuICAgICAgcy5tYXRjaF9sZW5ndGggPSBNSU5fTUFUQ0ggLSAxO1xuICAgICAgcy5zdHJzdGFydCsrO1xuXG4gICAgICBpZiAoYmZsdXNoKSB7XG4gICAgICAgIC8qKiogRkxVU0hfQkxPQ0socywgMCk7ICoqKi9cbiAgICAgICAgZmx1c2hfYmxvY2tfb25seShzLCBmYWxzZSk7XG4gICAgICAgIGlmIChzLnN0cm0uYXZhaWxfb3V0ID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgICAgfVxuICAgICAgICAvKioqL1xuICAgICAgfVxuXG4gICAgfSBlbHNlIGlmIChzLm1hdGNoX2F2YWlsYWJsZSkge1xuICAgICAgLyogSWYgdGhlcmUgd2FzIG5vIG1hdGNoIGF0IHRoZSBwcmV2aW91cyBwb3NpdGlvbiwgb3V0cHV0IGFcbiAgICAgICAqIHNpbmdsZSBsaXRlcmFsLiBJZiB0aGVyZSB3YXMgYSBtYXRjaCBidXQgdGhlIGN1cnJlbnQgbWF0Y2hcbiAgICAgICAqIGlzIGxvbmdlciwgdHJ1bmNhdGUgdGhlIHByZXZpb3VzIG1hdGNoIHRvIGEgc2luZ2xlIGxpdGVyYWwuXG4gICAgICAgKi9cbiAgICAgIC8vVHJhY2V2digoc3RkZXJyLFwiJWNcIiwgcy0+d2luZG93W3MtPnN0cnN0YXJ0LTFdKSk7XG4gICAgICAvKioqIF90cl90YWxseV9saXQocywgcy53aW5kb3dbcy5zdHJzdGFydC0xXSwgYmZsdXNoKTsgKioqL1xuICAgICAgYmZsdXNoID0gX3RyX3RhbGx5KHMsIDAsIHMud2luZG93W3Muc3Ryc3RhcnQgLSAxXSk7XG5cbiAgICAgIGlmIChiZmx1c2gpIHtcbiAgICAgICAgLyoqKiBGTFVTSF9CTE9DS19PTkxZKHMsIDApICoqKi9cbiAgICAgICAgZmx1c2hfYmxvY2tfb25seShzLCBmYWxzZSk7XG4gICAgICAgIC8qKiovXG4gICAgICB9XG4gICAgICBzLnN0cnN0YXJ0Kys7XG4gICAgICBzLmxvb2thaGVhZC0tO1xuICAgICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLyogVGhlcmUgaXMgbm8gcHJldmlvdXMgbWF0Y2ggdG8gY29tcGFyZSB3aXRoLCB3YWl0IGZvclxuICAgICAgICogdGhlIG5leHQgc3RlcCB0byBkZWNpZGUuXG4gICAgICAgKi9cbiAgICAgIHMubWF0Y2hfYXZhaWxhYmxlID0gMTtcbiAgICAgIHMuc3Ryc3RhcnQrKztcbiAgICAgIHMubG9va2FoZWFkLS07XG4gICAgfVxuICB9XG4gIC8vQXNzZXJ0IChmbHVzaCAhPSBaX05PX0ZMVVNILCBcIm5vIGZsdXNoP1wiKTtcbiAgaWYgKHMubWF0Y2hfYXZhaWxhYmxlKSB7XG4gICAgLy9UcmFjZXZ2KChzdGRlcnIsXCIlY1wiLCBzLT53aW5kb3dbcy0+c3Ryc3RhcnQtMV0pKTtcbiAgICAvKioqIF90cl90YWxseV9saXQocywgcy53aW5kb3dbcy5zdHJzdGFydC0xXSwgYmZsdXNoKTsgKioqL1xuICAgIGJmbHVzaCA9IF90cl90YWxseShzLCAwLCBzLndpbmRvd1tzLnN0cnN0YXJ0IC0gMV0pO1xuXG4gICAgcy5tYXRjaF9hdmFpbGFibGUgPSAwO1xuICB9XG4gIHMuaW5zZXJ0ID0gcy5zdHJzdGFydCA8IE1JTl9NQVRDSCAtIDEgPyBzLnN0cnN0YXJ0IDogTUlOX01BVENIIC0gMTtcbiAgaWYgKGZsdXNoID09PSBaX0ZJTklTSCQzKSB7XG4gICAgLyoqKiBGTFVTSF9CTE9DSyhzLCAxKTsgKioqL1xuICAgIGZsdXNoX2Jsb2NrX29ubHkocywgdHJ1ZSk7XG4gICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgIHJldHVybiBCU19GSU5JU0hfU1RBUlRFRDtcbiAgICB9XG4gICAgLyoqKi9cbiAgICByZXR1cm4gQlNfRklOSVNIX0RPTkU7XG4gIH1cbiAgaWYgKHMuc3ltX25leHQpIHtcbiAgICAvKioqIEZMVVNIX0JMT0NLKHMsIDApOyAqKiovXG4gICAgZmx1c2hfYmxvY2tfb25seShzLCBmYWxzZSk7XG4gICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgIHJldHVybiBCU19ORUVEX01PUkU7XG4gICAgfVxuICAgIC8qKiovXG4gIH1cblxuICByZXR1cm4gQlNfQkxPQ0tfRE9ORTtcbn07XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBGb3IgWl9STEUsIHNpbXBseSBsb29rIGZvciBydW5zIG9mIGJ5dGVzLCBnZW5lcmF0ZSBtYXRjaGVzIG9ubHkgb2YgZGlzdGFuY2VcbiAqIG9uZS4gIERvIG5vdCBtYWludGFpbiBhIGhhc2ggdGFibGUuICAoSXQgd2lsbCBiZSByZWdlbmVyYXRlZCBpZiB0aGlzIHJ1biBvZlxuICogZGVmbGF0ZSBzd2l0Y2hlcyBhd2F5IGZyb20gWl9STEUuKVxuICovXG5jb25zdCBkZWZsYXRlX3JsZSA9IChzLCBmbHVzaCkgPT4ge1xuXG4gIGxldCBiZmx1c2g7ICAgICAgICAgICAgLyogc2V0IGlmIGN1cnJlbnQgYmxvY2sgbXVzdCBiZSBmbHVzaGVkICovXG4gIGxldCBwcmV2OyAgICAgICAgICAgICAgLyogYnl0ZSBhdCBkaXN0YW5jZSBvbmUgdG8gbWF0Y2ggKi9cbiAgbGV0IHNjYW4sIHN0cmVuZDsgICAgICAvKiBzY2FuIGdvZXMgdXAgdG8gc3RyZW5kIGZvciBsZW5ndGggb2YgcnVuICovXG5cbiAgY29uc3QgX3dpbiA9IHMud2luZG93O1xuXG4gIGZvciAoOzspIHtcbiAgICAvKiBNYWtlIHN1cmUgdGhhdCB3ZSBhbHdheXMgaGF2ZSBlbm91Z2ggbG9va2FoZWFkLCBleGNlcHRcbiAgICAgKiBhdCB0aGUgZW5kIG9mIHRoZSBpbnB1dCBmaWxlLiBXZSBuZWVkIE1BWF9NQVRDSCBieXRlc1xuICAgICAqIGZvciB0aGUgbG9uZ2VzdCBydW4sIHBsdXMgb25lIGZvciB0aGUgdW5yb2xsZWQgbG9vcC5cbiAgICAgKi9cbiAgICBpZiAocy5sb29rYWhlYWQgPD0gTUFYX01BVENIKSB7XG4gICAgICBmaWxsX3dpbmRvdyhzKTtcbiAgICAgIGlmIChzLmxvb2thaGVhZCA8PSBNQVhfTUFUQ0ggJiYgZmx1c2ggPT09IFpfTk9fRkxVU0gkMikge1xuICAgICAgICByZXR1cm4gQlNfTkVFRF9NT1JFO1xuICAgICAgfVxuICAgICAgaWYgKHMubG9va2FoZWFkID09PSAwKSB7IGJyZWFrOyB9IC8qIGZsdXNoIHRoZSBjdXJyZW50IGJsb2NrICovXG4gICAgfVxuXG4gICAgLyogU2VlIGhvdyBtYW55IHRpbWVzIHRoZSBwcmV2aW91cyBieXRlIHJlcGVhdHMgKi9cbiAgICBzLm1hdGNoX2xlbmd0aCA9IDA7XG4gICAgaWYgKHMubG9va2FoZWFkID49IE1JTl9NQVRDSCAmJiBzLnN0cnN0YXJ0ID4gMCkge1xuICAgICAgc2NhbiA9IHMuc3Ryc3RhcnQgLSAxO1xuICAgICAgcHJldiA9IF93aW5bc2Nhbl07XG4gICAgICBpZiAocHJldiA9PT0gX3dpblsrK3NjYW5dICYmIHByZXYgPT09IF93aW5bKytzY2FuXSAmJiBwcmV2ID09PSBfd2luWysrc2Nhbl0pIHtcbiAgICAgICAgc3RyZW5kID0gcy5zdHJzdGFydCArIE1BWF9NQVRDSDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgIC8qanNoaW50IG5vZW1wdHk6ZmFsc2UqL1xuICAgICAgICB9IHdoaWxlIChwcmV2ID09PSBfd2luWysrc2Nhbl0gJiYgcHJldiA9PT0gX3dpblsrK3NjYW5dICYmXG4gICAgICAgICAgICAgICAgIHByZXYgPT09IF93aW5bKytzY2FuXSAmJiBwcmV2ID09PSBfd2luWysrc2Nhbl0gJiZcbiAgICAgICAgICAgICAgICAgcHJldiA9PT0gX3dpblsrK3NjYW5dICYmIHByZXYgPT09IF93aW5bKytzY2FuXSAmJlxuICAgICAgICAgICAgICAgICBwcmV2ID09PSBfd2luWysrc2Nhbl0gJiYgcHJldiA9PT0gX3dpblsrK3NjYW5dICYmXG4gICAgICAgICAgICAgICAgIHNjYW4gPCBzdHJlbmQpO1xuICAgICAgICBzLm1hdGNoX2xlbmd0aCA9IE1BWF9NQVRDSCAtIChzdHJlbmQgLSBzY2FuKTtcbiAgICAgICAgaWYgKHMubWF0Y2hfbGVuZ3RoID4gcy5sb29rYWhlYWQpIHtcbiAgICAgICAgICBzLm1hdGNoX2xlbmd0aCA9IHMubG9va2FoZWFkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvL0Fzc2VydChzY2FuIDw9IHMtPndpbmRvdysodUludCkocy0+d2luZG93X3NpemUtMSksIFwid2lsZCBzY2FuXCIpO1xuICAgIH1cblxuICAgIC8qIEVtaXQgbWF0Y2ggaWYgaGF2ZSBydW4gb2YgTUlOX01BVENIIG9yIGxvbmdlciwgZWxzZSBlbWl0IGxpdGVyYWwgKi9cbiAgICBpZiAocy5tYXRjaF9sZW5ndGggPj0gTUlOX01BVENIKSB7XG4gICAgICAvL2NoZWNrX21hdGNoKHMsIHMuc3Ryc3RhcnQsIHMuc3Ryc3RhcnQgLSAxLCBzLm1hdGNoX2xlbmd0aCk7XG5cbiAgICAgIC8qKiogX3RyX3RhbGx5X2Rpc3QocywgMSwgcy5tYXRjaF9sZW5ndGggLSBNSU5fTUFUQ0gsIGJmbHVzaCk7ICoqKi9cbiAgICAgIGJmbHVzaCA9IF90cl90YWxseShzLCAxLCBzLm1hdGNoX2xlbmd0aCAtIE1JTl9NQVRDSCk7XG5cbiAgICAgIHMubG9va2FoZWFkIC09IHMubWF0Y2hfbGVuZ3RoO1xuICAgICAgcy5zdHJzdGFydCArPSBzLm1hdGNoX2xlbmd0aDtcbiAgICAgIHMubWF0Y2hfbGVuZ3RoID0gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgLyogTm8gbWF0Y2gsIG91dHB1dCBhIGxpdGVyYWwgYnl0ZSAqL1xuICAgICAgLy9UcmFjZXZ2KChzdGRlcnIsXCIlY1wiLCBzLT53aW5kb3dbcy0+c3Ryc3RhcnRdKSk7XG4gICAgICAvKioqIF90cl90YWxseV9saXQocywgcy53aW5kb3dbcy5zdHJzdGFydF0sIGJmbHVzaCk7ICoqKi9cbiAgICAgIGJmbHVzaCA9IF90cl90YWxseShzLCAwLCBzLndpbmRvd1tzLnN0cnN0YXJ0XSk7XG5cbiAgICAgIHMubG9va2FoZWFkLS07XG4gICAgICBzLnN0cnN0YXJ0Kys7XG4gICAgfVxuICAgIGlmIChiZmx1c2gpIHtcbiAgICAgIC8qKiogRkxVU0hfQkxPQ0socywgMCk7ICoqKi9cbiAgICAgIGZsdXNoX2Jsb2NrX29ubHkocywgZmFsc2UpO1xuICAgICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgIH1cbiAgICAgIC8qKiovXG4gICAgfVxuICB9XG4gIHMuaW5zZXJ0ID0gMDtcbiAgaWYgKGZsdXNoID09PSBaX0ZJTklTSCQzKSB7XG4gICAgLyoqKiBGTFVTSF9CTE9DSyhzLCAxKTsgKioqL1xuICAgIGZsdXNoX2Jsb2NrX29ubHkocywgdHJ1ZSk7XG4gICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgIHJldHVybiBCU19GSU5JU0hfU1RBUlRFRDtcbiAgICB9XG4gICAgLyoqKi9cbiAgICByZXR1cm4gQlNfRklOSVNIX0RPTkU7XG4gIH1cbiAgaWYgKHMuc3ltX25leHQpIHtcbiAgICAvKioqIEZMVVNIX0JMT0NLKHMsIDApOyAqKiovXG4gICAgZmx1c2hfYmxvY2tfb25seShzLCBmYWxzZSk7XG4gICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgIHJldHVybiBCU19ORUVEX01PUkU7XG4gICAgfVxuICAgIC8qKiovXG4gIH1cbiAgcmV0dXJuIEJTX0JMT0NLX0RPTkU7XG59O1xuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEZvciBaX0hVRkZNQU5fT05MWSwgZG8gbm90IGxvb2sgZm9yIG1hdGNoZXMuICBEbyBub3QgbWFpbnRhaW4gYSBoYXNoIHRhYmxlLlxuICogKEl0IHdpbGwgYmUgcmVnZW5lcmF0ZWQgaWYgdGhpcyBydW4gb2YgZGVmbGF0ZSBzd2l0Y2hlcyBhd2F5IGZyb20gSHVmZm1hbi4pXG4gKi9cbmNvbnN0IGRlZmxhdGVfaHVmZiA9IChzLCBmbHVzaCkgPT4ge1xuXG4gIGxldCBiZmx1c2g7ICAgICAgICAgICAgIC8qIHNldCBpZiBjdXJyZW50IGJsb2NrIG11c3QgYmUgZmx1c2hlZCAqL1xuXG4gIGZvciAoOzspIHtcbiAgICAvKiBNYWtlIHN1cmUgdGhhdCB3ZSBoYXZlIGEgbGl0ZXJhbCB0byB3cml0ZS4gKi9cbiAgICBpZiAocy5sb29rYWhlYWQgPT09IDApIHtcbiAgICAgIGZpbGxfd2luZG93KHMpO1xuICAgICAgaWYgKHMubG9va2FoZWFkID09PSAwKSB7XG4gICAgICAgIGlmIChmbHVzaCA9PT0gWl9OT19GTFVTSCQyKSB7XG4gICAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgICAgfVxuICAgICAgICBicmVhazsgICAgICAvKiBmbHVzaCB0aGUgY3VycmVudCBibG9jayAqL1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qIE91dHB1dCBhIGxpdGVyYWwgYnl0ZSAqL1xuICAgIHMubWF0Y2hfbGVuZ3RoID0gMDtcbiAgICAvL1RyYWNldnYoKHN0ZGVycixcIiVjXCIsIHMtPndpbmRvd1tzLT5zdHJzdGFydF0pKTtcbiAgICAvKioqIF90cl90YWxseV9saXQocywgcy53aW5kb3dbcy5zdHJzdGFydF0sIGJmbHVzaCk7ICoqKi9cbiAgICBiZmx1c2ggPSBfdHJfdGFsbHkocywgMCwgcy53aW5kb3dbcy5zdHJzdGFydF0pO1xuICAgIHMubG9va2FoZWFkLS07XG4gICAgcy5zdHJzdGFydCsrO1xuICAgIGlmIChiZmx1c2gpIHtcbiAgICAgIC8qKiogRkxVU0hfQkxPQ0socywgMCk7ICoqKi9cbiAgICAgIGZsdXNoX2Jsb2NrX29ubHkocywgZmFsc2UpO1xuICAgICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgIH1cbiAgICAgIC8qKiovXG4gICAgfVxuICB9XG4gIHMuaW5zZXJ0ID0gMDtcbiAgaWYgKGZsdXNoID09PSBaX0ZJTklTSCQzKSB7XG4gICAgLyoqKiBGTFVTSF9CTE9DSyhzLCAxKTsgKioqL1xuICAgIGZsdXNoX2Jsb2NrX29ubHkocywgdHJ1ZSk7XG4gICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgIHJldHVybiBCU19GSU5JU0hfU1RBUlRFRDtcbiAgICB9XG4gICAgLyoqKi9cbiAgICByZXR1cm4gQlNfRklOSVNIX0RPTkU7XG4gIH1cbiAgaWYgKHMuc3ltX25leHQpIHtcbiAgICAvKioqIEZMVVNIX0JMT0NLKHMsIDApOyAqKiovXG4gICAgZmx1c2hfYmxvY2tfb25seShzLCBmYWxzZSk7XG4gICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgIHJldHVybiBCU19ORUVEX01PUkU7XG4gICAgfVxuICAgIC8qKiovXG4gIH1cbiAgcmV0dXJuIEJTX0JMT0NLX0RPTkU7XG59O1xuXG4vKiBWYWx1ZXMgZm9yIG1heF9sYXp5X21hdGNoLCBnb29kX21hdGNoIGFuZCBtYXhfY2hhaW5fbGVuZ3RoLCBkZXBlbmRpbmcgb25cbiAqIHRoZSBkZXNpcmVkIHBhY2sgbGV2ZWwgKDAuLjkpLiBUaGUgdmFsdWVzIGdpdmVuIGJlbG93IGhhdmUgYmVlbiB0dW5lZCB0b1xuICogZXhjbHVkZSB3b3JzdCBjYXNlIHBlcmZvcm1hbmNlIGZvciBwYXRob2xvZ2ljYWwgZmlsZXMuIEJldHRlciB2YWx1ZXMgbWF5IGJlXG4gKiBmb3VuZCBmb3Igc3BlY2lmaWMgZmlsZXMuXG4gKi9cbmZ1bmN0aW9uIENvbmZpZyhnb29kX2xlbmd0aCwgbWF4X2xhenksIG5pY2VfbGVuZ3RoLCBtYXhfY2hhaW4sIGZ1bmMpIHtcblxuICB0aGlzLmdvb2RfbGVuZ3RoID0gZ29vZF9sZW5ndGg7XG4gIHRoaXMubWF4X2xhenkgPSBtYXhfbGF6eTtcbiAgdGhpcy5uaWNlX2xlbmd0aCA9IG5pY2VfbGVuZ3RoO1xuICB0aGlzLm1heF9jaGFpbiA9IG1heF9jaGFpbjtcbiAgdGhpcy5mdW5jID0gZnVuYztcbn1cblxuY29uc3QgY29uZmlndXJhdGlvbl90YWJsZSA9IFtcbiAgLyogICAgICBnb29kIGxhenkgbmljZSBjaGFpbiAqL1xuICBuZXcgQ29uZmlnKDAsIDAsIDAsIDAsIGRlZmxhdGVfc3RvcmVkKSwgICAgICAgICAgLyogMCBzdG9yZSBvbmx5ICovXG4gIG5ldyBDb25maWcoNCwgNCwgOCwgNCwgZGVmbGF0ZV9mYXN0KSwgICAgICAgICAgICAvKiAxIG1heCBzcGVlZCwgbm8gbGF6eSBtYXRjaGVzICovXG4gIG5ldyBDb25maWcoNCwgNSwgMTYsIDgsIGRlZmxhdGVfZmFzdCksICAgICAgICAgICAvKiAyICovXG4gIG5ldyBDb25maWcoNCwgNiwgMzIsIDMyLCBkZWZsYXRlX2Zhc3QpLCAgICAgICAgICAvKiAzICovXG5cbiAgbmV3IENvbmZpZyg0LCA0LCAxNiwgMTYsIGRlZmxhdGVfc2xvdyksICAgICAgICAgIC8qIDQgbGF6eSBtYXRjaGVzICovXG4gIG5ldyBDb25maWcoOCwgMTYsIDMyLCAzMiwgZGVmbGF0ZV9zbG93KSwgICAgICAgICAvKiA1ICovXG4gIG5ldyBDb25maWcoOCwgMTYsIDEyOCwgMTI4LCBkZWZsYXRlX3Nsb3cpLCAgICAgICAvKiA2ICovXG4gIG5ldyBDb25maWcoOCwgMzIsIDEyOCwgMjU2LCBkZWZsYXRlX3Nsb3cpLCAgICAgICAvKiA3ICovXG4gIG5ldyBDb25maWcoMzIsIDEyOCwgMjU4LCAxMDI0LCBkZWZsYXRlX3Nsb3cpLCAgICAvKiA4ICovXG4gIG5ldyBDb25maWcoMzIsIDI1OCwgMjU4LCA0MDk2LCBkZWZsYXRlX3Nsb3cpICAgICAvKiA5IG1heCBjb21wcmVzc2lvbiAqL1xuXTtcblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEluaXRpYWxpemUgdGhlIFwibG9uZ2VzdCBtYXRjaFwiIHJvdXRpbmVzIGZvciBhIG5ldyB6bGliIHN0cmVhbVxuICovXG5jb25zdCBsbV9pbml0ID0gKHMpID0+IHtcblxuICBzLndpbmRvd19zaXplID0gMiAqIHMud19zaXplO1xuXG4gIC8qKiogQ0xFQVJfSEFTSChzKTsgKioqL1xuICB6ZXJvKHMuaGVhZCk7IC8vIEZpbGwgd2l0aCBOSUwgKD0gMCk7XG5cbiAgLyogU2V0IHRoZSBkZWZhdWx0IGNvbmZpZ3VyYXRpb24gcGFyYW1ldGVyczpcbiAgICovXG4gIHMubWF4X2xhenlfbWF0Y2ggPSBjb25maWd1cmF0aW9uX3RhYmxlW3MubGV2ZWxdLm1heF9sYXp5O1xuICBzLmdvb2RfbWF0Y2ggPSBjb25maWd1cmF0aW9uX3RhYmxlW3MubGV2ZWxdLmdvb2RfbGVuZ3RoO1xuICBzLm5pY2VfbWF0Y2ggPSBjb25maWd1cmF0aW9uX3RhYmxlW3MubGV2ZWxdLm5pY2VfbGVuZ3RoO1xuICBzLm1heF9jaGFpbl9sZW5ndGggPSBjb25maWd1cmF0aW9uX3RhYmxlW3MubGV2ZWxdLm1heF9jaGFpbjtcblxuICBzLnN0cnN0YXJ0ID0gMDtcbiAgcy5ibG9ja19zdGFydCA9IDA7XG4gIHMubG9va2FoZWFkID0gMDtcbiAgcy5pbnNlcnQgPSAwO1xuICBzLm1hdGNoX2xlbmd0aCA9IHMucHJldl9sZW5ndGggPSBNSU5fTUFUQ0ggLSAxO1xuICBzLm1hdGNoX2F2YWlsYWJsZSA9IDA7XG4gIHMuaW5zX2ggPSAwO1xufTtcblxuXG5mdW5jdGlvbiBEZWZsYXRlU3RhdGUoKSB7XG4gIHRoaXMuc3RybSA9IG51bGw7ICAgICAgICAgICAgLyogcG9pbnRlciBiYWNrIHRvIHRoaXMgemxpYiBzdHJlYW0gKi9cbiAgdGhpcy5zdGF0dXMgPSAwOyAgICAgICAgICAgIC8qIGFzIHRoZSBuYW1lIGltcGxpZXMgKi9cbiAgdGhpcy5wZW5kaW5nX2J1ZiA9IG51bGw7ICAgICAgLyogb3V0cHV0IHN0aWxsIHBlbmRpbmcgKi9cbiAgdGhpcy5wZW5kaW5nX2J1Zl9zaXplID0gMDsgIC8qIHNpemUgb2YgcGVuZGluZ19idWYgKi9cbiAgdGhpcy5wZW5kaW5nX291dCA9IDA7ICAgICAgIC8qIG5leHQgcGVuZGluZyBieXRlIHRvIG91dHB1dCB0byB0aGUgc3RyZWFtICovXG4gIHRoaXMucGVuZGluZyA9IDA7ICAgICAgICAgICAvKiBuYiBvZiBieXRlcyBpbiB0aGUgcGVuZGluZyBidWZmZXIgKi9cbiAgdGhpcy53cmFwID0gMDsgICAgICAgICAgICAgIC8qIGJpdCAwIHRydWUgZm9yIHpsaWIsIGJpdCAxIHRydWUgZm9yIGd6aXAgKi9cbiAgdGhpcy5nemhlYWQgPSBudWxsOyAgICAgICAgIC8qIGd6aXAgaGVhZGVyIGluZm9ybWF0aW9uIHRvIHdyaXRlICovXG4gIHRoaXMuZ3ppbmRleCA9IDA7ICAgICAgICAgICAvKiB3aGVyZSBpbiBleHRyYSwgbmFtZSwgb3IgY29tbWVudCAqL1xuICB0aGlzLm1ldGhvZCA9IFpfREVGTEFURUQkMjsgLyogY2FuIG9ubHkgYmUgREVGTEFURUQgKi9cbiAgdGhpcy5sYXN0X2ZsdXNoID0gLTE7ICAgLyogdmFsdWUgb2YgZmx1c2ggcGFyYW0gZm9yIHByZXZpb3VzIGRlZmxhdGUgY2FsbCAqL1xuXG4gIHRoaXMud19zaXplID0gMDsgIC8qIExaNzcgd2luZG93IHNpemUgKDMySyBieSBkZWZhdWx0KSAqL1xuICB0aGlzLndfYml0cyA9IDA7ICAvKiBsb2cyKHdfc2l6ZSkgICg4Li4xNikgKi9cbiAgdGhpcy53X21hc2sgPSAwOyAgLyogd19zaXplIC0gMSAqL1xuXG4gIHRoaXMud2luZG93ID0gbnVsbDtcbiAgLyogU2xpZGluZyB3aW5kb3cuIElucHV0IGJ5dGVzIGFyZSByZWFkIGludG8gdGhlIHNlY29uZCBoYWxmIG9mIHRoZSB3aW5kb3csXG4gICAqIGFuZCBtb3ZlIHRvIHRoZSBmaXJzdCBoYWxmIGxhdGVyIHRvIGtlZXAgYSBkaWN0aW9uYXJ5IG9mIGF0IGxlYXN0IHdTaXplXG4gICAqIGJ5dGVzLiBXaXRoIHRoaXMgb3JnYW5pemF0aW9uLCBtYXRjaGVzIGFyZSBsaW1pdGVkIHRvIGEgZGlzdGFuY2Ugb2ZcbiAgICogd1NpemUtTUFYX01BVENIIGJ5dGVzLCBidXQgdGhpcyBlbnN1cmVzIHRoYXQgSU8gaXMgYWx3YXlzXG4gICAqIHBlcmZvcm1lZCB3aXRoIGEgbGVuZ3RoIG11bHRpcGxlIG9mIHRoZSBibG9jayBzaXplLlxuICAgKi9cblxuICB0aGlzLndpbmRvd19zaXplID0gMDtcbiAgLyogQWN0dWFsIHNpemUgb2Ygd2luZG93OiAyKndTaXplLCBleGNlcHQgd2hlbiB0aGUgdXNlciBpbnB1dCBidWZmZXJcbiAgICogaXMgZGlyZWN0bHkgdXNlZCBhcyBzbGlkaW5nIHdpbmRvdy5cbiAgICovXG5cbiAgdGhpcy5wcmV2ID0gbnVsbDtcbiAgLyogTGluayB0byBvbGRlciBzdHJpbmcgd2l0aCBzYW1lIGhhc2ggaW5kZXguIFRvIGxpbWl0IHRoZSBzaXplIG9mIHRoaXNcbiAgICogYXJyYXkgdG8gNjRLLCB0aGlzIGxpbmsgaXMgbWFpbnRhaW5lZCBvbmx5IGZvciB0aGUgbGFzdCAzMksgc3RyaW5ncy5cbiAgICogQW4gaW5kZXggaW4gdGhpcyBhcnJheSBpcyB0aHVzIGEgd2luZG93IGluZGV4IG1vZHVsbyAzMksuXG4gICAqL1xuXG4gIHRoaXMuaGVhZCA9IG51bGw7ICAgLyogSGVhZHMgb2YgdGhlIGhhc2ggY2hhaW5zIG9yIE5JTC4gKi9cblxuICB0aGlzLmluc19oID0gMDsgICAgICAgLyogaGFzaCBpbmRleCBvZiBzdHJpbmcgdG8gYmUgaW5zZXJ0ZWQgKi9cbiAgdGhpcy5oYXNoX3NpemUgPSAwOyAgIC8qIG51bWJlciBvZiBlbGVtZW50cyBpbiBoYXNoIHRhYmxlICovXG4gIHRoaXMuaGFzaF9iaXRzID0gMDsgICAvKiBsb2cyKGhhc2hfc2l6ZSkgKi9cbiAgdGhpcy5oYXNoX21hc2sgPSAwOyAgIC8qIGhhc2hfc2l6ZS0xICovXG5cbiAgdGhpcy5oYXNoX3NoaWZ0ID0gMDtcbiAgLyogTnVtYmVyIG9mIGJpdHMgYnkgd2hpY2ggaW5zX2ggbXVzdCBiZSBzaGlmdGVkIGF0IGVhY2ggaW5wdXRcbiAgICogc3RlcC4gSXQgbXVzdCBiZSBzdWNoIHRoYXQgYWZ0ZXIgTUlOX01BVENIIHN0ZXBzLCB0aGUgb2xkZXN0XG4gICAqIGJ5dGUgbm8gbG9uZ2VyIHRha2VzIHBhcnQgaW4gdGhlIGhhc2gga2V5LCB0aGF0IGlzOlxuICAgKiAgIGhhc2hfc2hpZnQgKiBNSU5fTUFUQ0ggPj0gaGFzaF9iaXRzXG4gICAqL1xuXG4gIHRoaXMuYmxvY2tfc3RhcnQgPSAwO1xuICAvKiBXaW5kb3cgcG9zaXRpb24gYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgY3VycmVudCBvdXRwdXQgYmxvY2suIEdldHNcbiAgICogbmVnYXRpdmUgd2hlbiB0aGUgd2luZG93IGlzIG1vdmVkIGJhY2t3YXJkcy5cbiAgICovXG5cbiAgdGhpcy5tYXRjaF9sZW5ndGggPSAwOyAgICAgIC8qIGxlbmd0aCBvZiBiZXN0IG1hdGNoICovXG4gIHRoaXMucHJldl9tYXRjaCA9IDA7ICAgICAgICAvKiBwcmV2aW91cyBtYXRjaCAqL1xuICB0aGlzLm1hdGNoX2F2YWlsYWJsZSA9IDA7ICAgLyogc2V0IGlmIHByZXZpb3VzIG1hdGNoIGV4aXN0cyAqL1xuICB0aGlzLnN0cnN0YXJ0ID0gMDsgICAgICAgICAgLyogc3RhcnQgb2Ygc3RyaW5nIHRvIGluc2VydCAqL1xuICB0aGlzLm1hdGNoX3N0YXJ0ID0gMDsgICAgICAgLyogc3RhcnQgb2YgbWF0Y2hpbmcgc3RyaW5nICovXG4gIHRoaXMubG9va2FoZWFkID0gMDsgICAgICAgICAvKiBudW1iZXIgb2YgdmFsaWQgYnl0ZXMgYWhlYWQgaW4gd2luZG93ICovXG5cbiAgdGhpcy5wcmV2X2xlbmd0aCA9IDA7XG4gIC8qIExlbmd0aCBvZiB0aGUgYmVzdCBtYXRjaCBhdCBwcmV2aW91cyBzdGVwLiBNYXRjaGVzIG5vdCBncmVhdGVyIHRoYW4gdGhpc1xuICAgKiBhcmUgZGlzY2FyZGVkLiBUaGlzIGlzIHVzZWQgaW4gdGhlIGxhenkgbWF0Y2ggZXZhbHVhdGlvbi5cbiAgICovXG5cbiAgdGhpcy5tYXhfY2hhaW5fbGVuZ3RoID0gMDtcbiAgLyogVG8gc3BlZWQgdXAgZGVmbGF0aW9uLCBoYXNoIGNoYWlucyBhcmUgbmV2ZXIgc2VhcmNoZWQgYmV5b25kIHRoaXNcbiAgICogbGVuZ3RoLiAgQSBoaWdoZXIgbGltaXQgaW1wcm92ZXMgY29tcHJlc3Npb24gcmF0aW8gYnV0IGRlZ3JhZGVzIHRoZVxuICAgKiBzcGVlZC5cbiAgICovXG5cbiAgdGhpcy5tYXhfbGF6eV9tYXRjaCA9IDA7XG4gIC8qIEF0dGVtcHQgdG8gZmluZCBhIGJldHRlciBtYXRjaCBvbmx5IHdoZW4gdGhlIGN1cnJlbnQgbWF0Y2ggaXMgc3RyaWN0bHlcbiAgICogc21hbGxlciB0aGFuIHRoaXMgdmFsdWUuIFRoaXMgbWVjaGFuaXNtIGlzIHVzZWQgb25seSBmb3IgY29tcHJlc3Npb25cbiAgICogbGV2ZWxzID49IDQuXG4gICAqL1xuICAvLyBUaGF0J3MgYWxpYXMgdG8gbWF4X2xhenlfbWF0Y2gsIGRvbid0IHVzZSBkaXJlY3RseVxuICAvL3RoaXMubWF4X2luc2VydF9sZW5ndGggPSAwO1xuICAvKiBJbnNlcnQgbmV3IHN0cmluZ3MgaW4gdGhlIGhhc2ggdGFibGUgb25seSBpZiB0aGUgbWF0Y2ggbGVuZ3RoIGlzIG5vdFxuICAgKiBncmVhdGVyIHRoYW4gdGhpcyBsZW5ndGguIFRoaXMgc2F2ZXMgdGltZSBidXQgZGVncmFkZXMgY29tcHJlc3Npb24uXG4gICAqIG1heF9pbnNlcnRfbGVuZ3RoIGlzIHVzZWQgb25seSBmb3IgY29tcHJlc3Npb24gbGV2ZWxzIDw9IDMuXG4gICAqL1xuXG4gIHRoaXMubGV2ZWwgPSAwOyAgICAgLyogY29tcHJlc3Npb24gbGV2ZWwgKDEuLjkpICovXG4gIHRoaXMuc3RyYXRlZ3kgPSAwOyAgLyogZmF2b3Igb3IgZm9yY2UgSHVmZm1hbiBjb2RpbmcqL1xuXG4gIHRoaXMuZ29vZF9tYXRjaCA9IDA7XG4gIC8qIFVzZSBhIGZhc3RlciBzZWFyY2ggd2hlbiB0aGUgcHJldmlvdXMgbWF0Y2ggaXMgbG9uZ2VyIHRoYW4gdGhpcyAqL1xuXG4gIHRoaXMubmljZV9tYXRjaCA9IDA7IC8qIFN0b3Agc2VhcmNoaW5nIHdoZW4gY3VycmVudCBtYXRjaCBleGNlZWRzIHRoaXMgKi9cblxuICAgICAgICAgICAgICAvKiB1c2VkIGJ5IHRyZWVzLmM6ICovXG5cbiAgLyogRGlkbid0IHVzZSBjdF9kYXRhIHR5cGVkZWYgYmVsb3cgdG8gc3VwcHJlc3MgY29tcGlsZXIgd2FybmluZyAqL1xuXG4gIC8vIHN0cnVjdCBjdF9kYXRhX3MgZHluX2x0cmVlW0hFQVBfU0laRV07ICAgLyogbGl0ZXJhbCBhbmQgbGVuZ3RoIHRyZWUgKi9cbiAgLy8gc3RydWN0IGN0X2RhdGFfcyBkeW5fZHRyZWVbMipEX0NPREVTKzFdOyAvKiBkaXN0YW5jZSB0cmVlICovXG4gIC8vIHN0cnVjdCBjdF9kYXRhX3MgYmxfdHJlZVsyKkJMX0NPREVTKzFdOyAgLyogSHVmZm1hbiB0cmVlIGZvciBiaXQgbGVuZ3RocyAqL1xuXG4gIC8vIFVzZSBmbGF0IGFycmF5IG9mIERPVUJMRSBzaXplLCB3aXRoIGludGVybGVhdmVkIGZhdGEsXG4gIC8vIGJlY2F1c2UgSlMgZG9lcyBub3Qgc3VwcG9ydCBlZmZlY3RpdmVcbiAgdGhpcy5keW5fbHRyZWUgID0gbmV3IFVpbnQxNkFycmF5KEhFQVBfU0laRSAqIDIpO1xuICB0aGlzLmR5bl9kdHJlZSAgPSBuZXcgVWludDE2QXJyYXkoKDIgKiBEX0NPREVTICsgMSkgKiAyKTtcbiAgdGhpcy5ibF90cmVlICAgID0gbmV3IFVpbnQxNkFycmF5KCgyICogQkxfQ09ERVMgKyAxKSAqIDIpO1xuICB6ZXJvKHRoaXMuZHluX2x0cmVlKTtcbiAgemVybyh0aGlzLmR5bl9kdHJlZSk7XG4gIHplcm8odGhpcy5ibF90cmVlKTtcblxuICB0aGlzLmxfZGVzYyAgID0gbnVsbDsgICAgICAgICAvKiBkZXNjLiBmb3IgbGl0ZXJhbCB0cmVlICovXG4gIHRoaXMuZF9kZXNjICAgPSBudWxsOyAgICAgICAgIC8qIGRlc2MuIGZvciBkaXN0YW5jZSB0cmVlICovXG4gIHRoaXMuYmxfZGVzYyAgPSBudWxsOyAgICAgICAgIC8qIGRlc2MuIGZvciBiaXQgbGVuZ3RoIHRyZWUgKi9cblxuICAvL3VzaCBibF9jb3VudFtNQVhfQklUUysxXTtcbiAgdGhpcy5ibF9jb3VudCA9IG5ldyBVaW50MTZBcnJheShNQVhfQklUUyArIDEpO1xuICAvKiBudW1iZXIgb2YgY29kZXMgYXQgZWFjaCBiaXQgbGVuZ3RoIGZvciBhbiBvcHRpbWFsIHRyZWUgKi9cblxuICAvL2ludCBoZWFwWzIqTF9DT0RFUysxXTsgICAgICAvKiBoZWFwIHVzZWQgdG8gYnVpbGQgdGhlIEh1ZmZtYW4gdHJlZXMgKi9cbiAgdGhpcy5oZWFwID0gbmV3IFVpbnQxNkFycmF5KDIgKiBMX0NPREVTICsgMSk7ICAvKiBoZWFwIHVzZWQgdG8gYnVpbGQgdGhlIEh1ZmZtYW4gdHJlZXMgKi9cbiAgemVybyh0aGlzLmhlYXApO1xuXG4gIHRoaXMuaGVhcF9sZW4gPSAwOyAgICAgICAgICAgICAgIC8qIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgaGVhcCAqL1xuICB0aGlzLmhlYXBfbWF4ID0gMDsgICAgICAgICAgICAgICAvKiBlbGVtZW50IG9mIGxhcmdlc3QgZnJlcXVlbmN5ICovXG4gIC8qIFRoZSBzb25zIG9mIGhlYXBbbl0gYXJlIGhlYXBbMipuXSBhbmQgaGVhcFsyKm4rMV0uIGhlYXBbMF0gaXMgbm90IHVzZWQuXG4gICAqIFRoZSBzYW1lIGhlYXAgYXJyYXkgaXMgdXNlZCB0byBidWlsZCBhbGwgdHJlZXMuXG4gICAqL1xuXG4gIHRoaXMuZGVwdGggPSBuZXcgVWludDE2QXJyYXkoMiAqIExfQ09ERVMgKyAxKTsgLy91Y2ggZGVwdGhbMipMX0NPREVTKzFdO1xuICB6ZXJvKHRoaXMuZGVwdGgpO1xuICAvKiBEZXB0aCBvZiBlYWNoIHN1YnRyZWUgdXNlZCBhcyB0aWUgYnJlYWtlciBmb3IgdHJlZXMgb2YgZXF1YWwgZnJlcXVlbmN5XG4gICAqL1xuXG4gIHRoaXMuc3ltX2J1ZiA9IDA7ICAgICAgICAvKiBidWZmZXIgZm9yIGRpc3RhbmNlcyBhbmQgbGl0ZXJhbHMvbGVuZ3RocyAqL1xuXG4gIHRoaXMubGl0X2J1ZnNpemUgPSAwO1xuICAvKiBTaXplIG9mIG1hdGNoIGJ1ZmZlciBmb3IgbGl0ZXJhbHMvbGVuZ3Rocy4gIFRoZXJlIGFyZSA0IHJlYXNvbnMgZm9yXG4gICAqIGxpbWl0aW5nIGxpdF9idWZzaXplIHRvIDY0SzpcbiAgICogICAtIGZyZXF1ZW5jaWVzIGNhbiBiZSBrZXB0IGluIDE2IGJpdCBjb3VudGVyc1xuICAgKiAgIC0gaWYgY29tcHJlc3Npb24gaXMgbm90IHN1Y2Nlc3NmdWwgZm9yIHRoZSBmaXJzdCBibG9jaywgYWxsIGlucHV0XG4gICAqICAgICBkYXRhIGlzIHN0aWxsIGluIHRoZSB3aW5kb3cgc28gd2UgY2FuIHN0aWxsIGVtaXQgYSBzdG9yZWQgYmxvY2sgZXZlblxuICAgKiAgICAgd2hlbiBpbnB1dCBjb21lcyBmcm9tIHN0YW5kYXJkIGlucHV0LiAgKFRoaXMgY2FuIGFsc28gYmUgZG9uZSBmb3JcbiAgICogICAgIGFsbCBibG9ja3MgaWYgbGl0X2J1ZnNpemUgaXMgbm90IGdyZWF0ZXIgdGhhbiAzMksuKVxuICAgKiAgIC0gaWYgY29tcHJlc3Npb24gaXMgbm90IHN1Y2Nlc3NmdWwgZm9yIGEgZmlsZSBzbWFsbGVyIHRoYW4gNjRLLCB3ZSBjYW5cbiAgICogICAgIGV2ZW4gZW1pdCBhIHN0b3JlZCBmaWxlIGluc3RlYWQgb2YgYSBzdG9yZWQgYmxvY2sgKHNhdmluZyA1IGJ5dGVzKS5cbiAgICogICAgIFRoaXMgaXMgYXBwbGljYWJsZSBvbmx5IGZvciB6aXAgKG5vdCBnemlwIG9yIHpsaWIpLlxuICAgKiAgIC0gY3JlYXRpbmcgbmV3IEh1ZmZtYW4gdHJlZXMgbGVzcyBmcmVxdWVudGx5IG1heSBub3QgcHJvdmlkZSBmYXN0XG4gICAqICAgICBhZGFwdGF0aW9uIHRvIGNoYW5nZXMgaW4gdGhlIGlucHV0IGRhdGEgc3RhdGlzdGljcy4gKFRha2UgZm9yXG4gICAqICAgICBleGFtcGxlIGEgYmluYXJ5IGZpbGUgd2l0aCBwb29ybHkgY29tcHJlc3NpYmxlIGNvZGUgZm9sbG93ZWQgYnlcbiAgICogICAgIGEgaGlnaGx5IGNvbXByZXNzaWJsZSBzdHJpbmcgdGFibGUuKSBTbWFsbGVyIGJ1ZmZlciBzaXplcyBnaXZlXG4gICAqICAgICBmYXN0IGFkYXB0YXRpb24gYnV0IGhhdmUgb2YgY291cnNlIHRoZSBvdmVyaGVhZCBvZiB0cmFuc21pdHRpbmdcbiAgICogICAgIHRyZWVzIG1vcmUgZnJlcXVlbnRseS5cbiAgICogICAtIEkgY2FuJ3QgY291bnQgYWJvdmUgNFxuICAgKi9cblxuICB0aGlzLnN5bV9uZXh0ID0gMDsgICAgICAvKiBydW5uaW5nIGluZGV4IGluIHN5bV9idWYgKi9cbiAgdGhpcy5zeW1fZW5kID0gMDsgICAgICAgLyogc3ltYm9sIHRhYmxlIGZ1bGwgd2hlbiBzeW1fbmV4dCByZWFjaGVzIHRoaXMgKi9cblxuICB0aGlzLm9wdF9sZW4gPSAwOyAgICAgICAvKiBiaXQgbGVuZ3RoIG9mIGN1cnJlbnQgYmxvY2sgd2l0aCBvcHRpbWFsIHRyZWVzICovXG4gIHRoaXMuc3RhdGljX2xlbiA9IDA7ICAgIC8qIGJpdCBsZW5ndGggb2YgY3VycmVudCBibG9jayB3aXRoIHN0YXRpYyB0cmVlcyAqL1xuICB0aGlzLm1hdGNoZXMgPSAwOyAgICAgICAvKiBudW1iZXIgb2Ygc3RyaW5nIG1hdGNoZXMgaW4gY3VycmVudCBibG9jayAqL1xuICB0aGlzLmluc2VydCA9IDA7ICAgICAgICAvKiBieXRlcyBhdCBlbmQgb2Ygd2luZG93IGxlZnQgdG8gaW5zZXJ0ICovXG5cblxuICB0aGlzLmJpX2J1ZiA9IDA7XG4gIC8qIE91dHB1dCBidWZmZXIuIGJpdHMgYXJlIGluc2VydGVkIHN0YXJ0aW5nIGF0IHRoZSBib3R0b20gKGxlYXN0XG4gICAqIHNpZ25pZmljYW50IGJpdHMpLlxuICAgKi9cbiAgdGhpcy5iaV92YWxpZCA9IDA7XG4gIC8qIE51bWJlciBvZiB2YWxpZCBiaXRzIGluIGJpX2J1Zi4gIEFsbCBiaXRzIGFib3ZlIHRoZSBsYXN0IHZhbGlkIGJpdFxuICAgKiBhcmUgYWx3YXlzIHplcm8uXG4gICAqL1xuXG4gIC8vIFVzZWQgZm9yIHdpbmRvdyBtZW1vcnkgaW5pdC4gV2Ugc2FmZWx5IGlnbm9yZSBpdCBmb3IgSlMuIFRoYXQgbWFrZXNcbiAgLy8gc2Vuc2Ugb25seSBmb3IgcG9pbnRlcnMgYW5kIG1lbW9yeSBjaGVjayB0b29scy5cbiAgLy90aGlzLmhpZ2hfd2F0ZXIgPSAwO1xuICAvKiBIaWdoIHdhdGVyIG1hcmsgb2Zmc2V0IGluIHdpbmRvdyBmb3IgaW5pdGlhbGl6ZWQgYnl0ZXMgLS0gYnl0ZXMgYWJvdmVcbiAgICogdGhpcyBhcmUgc2V0IHRvIHplcm8gaW4gb3JkZXIgdG8gYXZvaWQgbWVtb3J5IGNoZWNrIHdhcm5pbmdzIHdoZW5cbiAgICogbG9uZ2VzdCBtYXRjaCByb3V0aW5lcyBhY2Nlc3MgYnl0ZXMgcGFzdCB0aGUgaW5wdXQuICBUaGlzIGlzIHRoZW5cbiAgICogdXBkYXRlZCB0byB0aGUgbmV3IGhpZ2ggd2F0ZXIgbWFyay5cbiAgICovXG59XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQ2hlY2sgZm9yIGEgdmFsaWQgZGVmbGF0ZSBzdHJlYW0gc3RhdGUuIFJldHVybiAwIGlmIG9rLCAxIGlmIG5vdC5cbiAqL1xuY29uc3QgZGVmbGF0ZVN0YXRlQ2hlY2sgPSAoc3RybSkgPT4ge1xuXG4gIGlmICghc3RybSkge1xuICAgIHJldHVybiAxO1xuICB9XG4gIGNvbnN0IHMgPSBzdHJtLnN0YXRlO1xuICBpZiAoIXMgfHwgcy5zdHJtICE9PSBzdHJtIHx8IChzLnN0YXR1cyAhPT0gSU5JVF9TVEFURSAmJlxuLy8jaWZkZWYgR1pJUFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzLnN0YXR1cyAhPT0gR1pJUF9TVEFURSAmJlxuLy8jZW5kaWZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcy5zdGF0dXMgIT09IEVYVFJBX1NUQVRFICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMuc3RhdHVzICE9PSBOQU1FX1NUQVRFICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMuc3RhdHVzICE9PSBDT01NRU5UX1NUQVRFICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMuc3RhdHVzICE9PSBIQ1JDX1NUQVRFICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMuc3RhdHVzICE9PSBCVVNZX1NUQVRFICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHMuc3RhdHVzICE9PSBGSU5JU0hfU1RBVEUpKSB7XG4gICAgcmV0dXJuIDE7XG4gIH1cbiAgcmV0dXJuIDA7XG59O1xuXG5cbmNvbnN0IGRlZmxhdGVSZXNldEtlZXAgPSAoc3RybSkgPT4ge1xuXG4gIGlmIChkZWZsYXRlU3RhdGVDaGVjayhzdHJtKSkge1xuICAgIHJldHVybiBlcnIoc3RybSwgWl9TVFJFQU1fRVJST1IkMik7XG4gIH1cblxuICBzdHJtLnRvdGFsX2luID0gc3RybS50b3RhbF9vdXQgPSAwO1xuICBzdHJtLmRhdGFfdHlwZSA9IFpfVU5LTk9XTjtcblxuICBjb25zdCBzID0gc3RybS5zdGF0ZTtcbiAgcy5wZW5kaW5nID0gMDtcbiAgcy5wZW5kaW5nX291dCA9IDA7XG5cbiAgaWYgKHMud3JhcCA8IDApIHtcbiAgICBzLndyYXAgPSAtcy53cmFwO1xuICAgIC8qIHdhcyBtYWRlIG5lZ2F0aXZlIGJ5IGRlZmxhdGUoLi4uLCBaX0ZJTklTSCk7ICovXG4gIH1cbiAgcy5zdGF0dXMgPVxuLy8jaWZkZWYgR1pJUFxuICAgIHMud3JhcCA9PT0gMiA/IEdaSVBfU1RBVEUgOlxuLy8jZW5kaWZcbiAgICBzLndyYXAgPyBJTklUX1NUQVRFIDogQlVTWV9TVEFURTtcbiAgc3RybS5hZGxlciA9IChzLndyYXAgPT09IDIpID9cbiAgICAwICAvLyBjcmMzMigwLCBaX05VTEwsIDApXG4gIDpcbiAgICAxOyAvLyBhZGxlcjMyKDAsIFpfTlVMTCwgMClcbiAgcy5sYXN0X2ZsdXNoID0gLTI7XG4gIF90cl9pbml0KHMpO1xuICByZXR1cm4gWl9PSyQzO1xufTtcblxuXG5jb25zdCBkZWZsYXRlUmVzZXQgPSAoc3RybSkgPT4ge1xuXG4gIGNvbnN0IHJldCA9IGRlZmxhdGVSZXNldEtlZXAoc3RybSk7XG4gIGlmIChyZXQgPT09IFpfT0skMykge1xuICAgIGxtX2luaXQoc3RybS5zdGF0ZSk7XG4gIH1cbiAgcmV0dXJuIHJldDtcbn07XG5cblxuY29uc3QgZGVmbGF0ZVNldEhlYWRlciA9IChzdHJtLCBoZWFkKSA9PiB7XG5cbiAgaWYgKGRlZmxhdGVTdGF0ZUNoZWNrKHN0cm0pIHx8IHN0cm0uc3RhdGUud3JhcCAhPT0gMikge1xuICAgIHJldHVybiBaX1NUUkVBTV9FUlJPUiQyO1xuICB9XG4gIHN0cm0uc3RhdGUuZ3poZWFkID0gaGVhZDtcbiAgcmV0dXJuIFpfT0skMztcbn07XG5cblxuY29uc3QgZGVmbGF0ZUluaXQyID0gKHN0cm0sIGxldmVsLCBtZXRob2QsIHdpbmRvd0JpdHMsIG1lbUxldmVsLCBzdHJhdGVneSkgPT4ge1xuXG4gIGlmICghc3RybSkgeyAvLyA9PT0gWl9OVUxMXG4gICAgcmV0dXJuIFpfU1RSRUFNX0VSUk9SJDI7XG4gIH1cbiAgbGV0IHdyYXAgPSAxO1xuXG4gIGlmIChsZXZlbCA9PT0gWl9ERUZBVUxUX0NPTVBSRVNTSU9OJDEpIHtcbiAgICBsZXZlbCA9IDY7XG4gIH1cblxuICBpZiAod2luZG93Qml0cyA8IDApIHsgLyogc3VwcHJlc3MgemxpYiB3cmFwcGVyICovXG4gICAgd3JhcCA9IDA7XG4gICAgd2luZG93Qml0cyA9IC13aW5kb3dCaXRzO1xuICB9XG5cbiAgZWxzZSBpZiAod2luZG93Qml0cyA+IDE1KSB7XG4gICAgd3JhcCA9IDI7ICAgICAgICAgICAvKiB3cml0ZSBnemlwIHdyYXBwZXIgaW5zdGVhZCAqL1xuICAgIHdpbmRvd0JpdHMgLT0gMTY7XG4gIH1cblxuXG4gIGlmIChtZW1MZXZlbCA8IDEgfHwgbWVtTGV2ZWwgPiBNQVhfTUVNX0xFVkVMIHx8IG1ldGhvZCAhPT0gWl9ERUZMQVRFRCQyIHx8XG4gICAgd2luZG93Qml0cyA8IDggfHwgd2luZG93Qml0cyA+IDE1IHx8IGxldmVsIDwgMCB8fCBsZXZlbCA+IDkgfHxcbiAgICBzdHJhdGVneSA8IDAgfHwgc3RyYXRlZ3kgPiBaX0ZJWEVEIHx8ICh3aW5kb3dCaXRzID09PSA4ICYmIHdyYXAgIT09IDEpKSB7XG4gICAgcmV0dXJuIGVycihzdHJtLCBaX1NUUkVBTV9FUlJPUiQyKTtcbiAgfVxuXG5cbiAgaWYgKHdpbmRvd0JpdHMgPT09IDgpIHtcbiAgICB3aW5kb3dCaXRzID0gOTtcbiAgfVxuICAvKiB1bnRpbCAyNTYtYnl0ZSB3aW5kb3cgYnVnIGZpeGVkICovXG5cbiAgY29uc3QgcyA9IG5ldyBEZWZsYXRlU3RhdGUoKTtcblxuICBzdHJtLnN0YXRlID0gcztcbiAgcy5zdHJtID0gc3RybTtcbiAgcy5zdGF0dXMgPSBJTklUX1NUQVRFOyAgICAgLyogdG8gcGFzcyBzdGF0ZSB0ZXN0IGluIGRlZmxhdGVSZXNldCgpICovXG5cbiAgcy53cmFwID0gd3JhcDtcbiAgcy5nemhlYWQgPSBudWxsO1xuICBzLndfYml0cyA9IHdpbmRvd0JpdHM7XG4gIHMud19zaXplID0gMSA8PCBzLndfYml0cztcbiAgcy53X21hc2sgPSBzLndfc2l6ZSAtIDE7XG5cbiAgcy5oYXNoX2JpdHMgPSBtZW1MZXZlbCArIDc7XG4gIHMuaGFzaF9zaXplID0gMSA8PCBzLmhhc2hfYml0cztcbiAgcy5oYXNoX21hc2sgPSBzLmhhc2hfc2l6ZSAtIDE7XG4gIHMuaGFzaF9zaGlmdCA9IH5+KChzLmhhc2hfYml0cyArIE1JTl9NQVRDSCAtIDEpIC8gTUlOX01BVENIKTtcblxuICBzLndpbmRvdyA9IG5ldyBVaW50OEFycmF5KHMud19zaXplICogMik7XG4gIHMuaGVhZCA9IG5ldyBVaW50MTZBcnJheShzLmhhc2hfc2l6ZSk7XG4gIHMucHJldiA9IG5ldyBVaW50MTZBcnJheShzLndfc2l6ZSk7XG5cbiAgLy8gRG9uJ3QgbmVlZCBtZW0gaW5pdCBtYWdpYyBmb3IgSlMuXG4gIC8vcy5oaWdoX3dhdGVyID0gMDsgIC8qIG5vdGhpbmcgd3JpdHRlbiB0byBzLT53aW5kb3cgeWV0ICovXG5cbiAgcy5saXRfYnVmc2l6ZSA9IDEgPDwgKG1lbUxldmVsICsgNik7IC8qIDE2SyBlbGVtZW50cyBieSBkZWZhdWx0ICovXG5cbiAgLyogV2Ugb3ZlcmxheSBwZW5kaW5nX2J1ZiBhbmQgc3ltX2J1Zi4gVGhpcyB3b3JrcyBzaW5jZSB0aGUgYXZlcmFnZSBzaXplXG4gICAqIGZvciBsZW5ndGgvZGlzdGFuY2UgcGFpcnMgb3ZlciBhbnkgY29tcHJlc3NlZCBibG9jayBpcyBhc3N1cmVkIHRvIGJlIDMxXG4gICAqIGJpdHMgb3IgbGVzcy5cbiAgICpcbiAgICogQW5hbHlzaXM6IFRoZSBsb25nZXN0IGZpeGVkIGNvZGVzIGFyZSBhIGxlbmd0aCBjb2RlIG9mIDggYml0cyBwbHVzIDVcbiAgICogZXh0cmEgYml0cywgZm9yIGxlbmd0aHMgMTMxIHRvIDI1Ny4gVGhlIGxvbmdlc3QgZml4ZWQgZGlzdGFuY2UgY29kZXMgYXJlXG4gICAqIDUgYml0cyBwbHVzIDEzIGV4dHJhIGJpdHMsIGZvciBkaXN0YW5jZXMgMTYzODUgdG8gMzI3NjguIFRoZSBsb25nZXN0XG4gICAqIHBvc3NpYmxlIGZpeGVkLWNvZGVzIGxlbmd0aC9kaXN0YW5jZSBwYWlyIGlzIHRoZW4gMzEgYml0cyB0b3RhbC5cbiAgICpcbiAgICogc3ltX2J1ZiBzdGFydHMgb25lLWZvdXJ0aCBvZiB0aGUgd2F5IGludG8gcGVuZGluZ19idWYuIFNvIHRoZXJlIGFyZVxuICAgKiB0aHJlZSBieXRlcyBpbiBzeW1fYnVmIGZvciBldmVyeSBmb3VyIGJ5dGVzIGluIHBlbmRpbmdfYnVmLiBFYWNoIHN5bWJvbFxuICAgKiBpbiBzeW1fYnVmIGlzIHRocmVlIGJ5dGVzIC0tIHR3byBmb3IgdGhlIGRpc3RhbmNlIGFuZCBvbmUgZm9yIHRoZVxuICAgKiBsaXRlcmFsL2xlbmd0aC4gQXMgZWFjaCBzeW1ib2wgaXMgY29uc3VtZWQsIHRoZSBwb2ludGVyIHRvIHRoZSBuZXh0XG4gICAqIHN5bV9idWYgdmFsdWUgdG8gcmVhZCBtb3ZlcyBmb3J3YXJkIHRocmVlIGJ5dGVzLiBGcm9tIHRoYXQgc3ltYm9sLCB1cCB0b1xuICAgKiAzMSBiaXRzIGFyZSB3cml0dGVuIHRvIHBlbmRpbmdfYnVmLiBUaGUgY2xvc2VzdCB0aGUgd3JpdHRlbiBwZW5kaW5nX2J1ZlxuICAgKiBiaXRzIGdldHMgdG8gdGhlIG5leHQgc3ltX2J1ZiBzeW1ib2wgdG8gcmVhZCBpcyBqdXN0IGJlZm9yZSB0aGUgbGFzdFxuICAgKiBjb2RlIGlzIHdyaXR0ZW4uIEF0IHRoYXQgdGltZSwgMzEqKG4tMikgYml0cyBoYXZlIGJlZW4gd3JpdHRlbiwganVzdFxuICAgKiBhZnRlciAyNCoobi0yKSBiaXRzIGhhdmUgYmVlbiBjb25zdW1lZCBmcm9tIHN5bV9idWYuIHN5bV9idWYgc3RhcnRzIGF0XG4gICAqIDgqbiBiaXRzIGludG8gcGVuZGluZ19idWYuIChOb3RlIHRoYXQgdGhlIHN5bWJvbCBidWZmZXIgZmlsbHMgd2hlbiBuLTFcbiAgICogc3ltYm9scyBhcmUgd3JpdHRlbi4pIFRoZSBjbG9zZXN0IHRoZSB3cml0aW5nIGdldHMgdG8gd2hhdCBpcyB1bnJlYWQgaXNcbiAgICogdGhlbiBuKzE0IGJpdHMuIEhlcmUgbiBpcyBsaXRfYnVmc2l6ZSwgd2hpY2ggaXMgMTYzODQgYnkgZGVmYXVsdCwgYW5kXG4gICAqIGNhbiByYW5nZSBmcm9tIDEyOCB0byAzMjc2OC5cbiAgICpcbiAgICogVGhlcmVmb3JlLCBhdCBhIG1pbmltdW0sIHRoZXJlIGFyZSAxNDIgYml0cyBvZiBzcGFjZSBiZXR3ZWVuIHdoYXQgaXNcbiAgICogd3JpdHRlbiBhbmQgd2hhdCBpcyByZWFkIGluIHRoZSBvdmVybGFpbiBidWZmZXJzLCBzbyB0aGUgc3ltYm9scyBjYW5ub3RcbiAgICogYmUgb3ZlcndyaXR0ZW4gYnkgdGhlIGNvbXByZXNzZWQgZGF0YS4gVGhhdCBzcGFjZSBpcyBhY3R1YWxseSAxMzkgYml0cyxcbiAgICogZHVlIHRvIHRoZSB0aHJlZS1iaXQgZml4ZWQtY29kZSBibG9jayBoZWFkZXIuXG4gICAqXG4gICAqIFRoYXQgY292ZXJzIHRoZSBjYXNlIHdoZXJlIGVpdGhlciBaX0ZJWEVEIGlzIHNwZWNpZmllZCwgZm9yY2luZyBmaXhlZFxuICAgKiBjb2Rlcywgb3Igd2hlbiB0aGUgdXNlIG9mIGZpeGVkIGNvZGVzIGlzIGNob3NlbiwgYmVjYXVzZSB0aGF0IGNob2ljZVxuICAgKiByZXN1bHRzIGluIGEgc21hbGxlciBjb21wcmVzc2VkIGJsb2NrIHRoYW4gZHluYW1pYyBjb2Rlcy4gVGhhdCBsYXR0ZXJcbiAgICogY29uZGl0aW9uIHRoZW4gYXNzdXJlcyB0aGF0IHRoZSBhYm92ZSBhbmFseXNpcyBhbHNvIGNvdmVycyBhbGwgZHluYW1pY1xuICAgKiBibG9ja3MuIEEgZHluYW1pYy1jb2RlIGJsb2NrIHdpbGwgb25seSBiZSBjaG9zZW4gdG8gYmUgZW1pdHRlZCBpZiBpdCBoYXNcbiAgICogZmV3ZXIgYml0cyB0aGFuIGEgZml4ZWQtY29kZSBibG9jayB3b3VsZCBmb3IgdGhlIHNhbWUgc2V0IG9mIHN5bWJvbHMuXG4gICAqIFRoZXJlZm9yZSBpdHMgYXZlcmFnZSBzeW1ib2wgbGVuZ3RoIGlzIGFzc3VyZWQgdG8gYmUgbGVzcyB0aGFuIDMxLiBTb1xuICAgKiB0aGUgY29tcHJlc3NlZCBkYXRhIGZvciBhIGR5bmFtaWMgYmxvY2sgYWxzbyBjYW5ub3Qgb3ZlcndyaXRlIHRoZVxuICAgKiBzeW1ib2xzIGZyb20gd2hpY2ggaXQgaXMgYmVpbmcgY29uc3RydWN0ZWQuXG4gICAqL1xuXG4gIHMucGVuZGluZ19idWZfc2l6ZSA9IHMubGl0X2J1ZnNpemUgKiA0O1xuICBzLnBlbmRpbmdfYnVmID0gbmV3IFVpbnQ4QXJyYXkocy5wZW5kaW5nX2J1Zl9zaXplKTtcblxuICAvLyBJdCBpcyBvZmZzZXQgZnJvbSBgcy5wZW5kaW5nX2J1ZmAgKHNpemUgaXMgYHMubGl0X2J1ZnNpemUgKiAyYClcbiAgLy9zLT5zeW1fYnVmID0gcy0+cGVuZGluZ19idWYgKyBzLT5saXRfYnVmc2l6ZTtcbiAgcy5zeW1fYnVmID0gcy5saXRfYnVmc2l6ZTtcblxuICAvL3MtPnN5bV9lbmQgPSAocy0+bGl0X2J1ZnNpemUgLSAxKSAqIDM7XG4gIHMuc3ltX2VuZCA9IChzLmxpdF9idWZzaXplIC0gMSkgKiAzO1xuICAvKiBXZSBhdm9pZCBlcXVhbGl0eSB3aXRoIGxpdF9idWZzaXplKjMgYmVjYXVzZSBvZiB3cmFwYXJvdW5kIGF0IDY0S1xuICAgKiBvbiAxNiBiaXQgbWFjaGluZXMgYW5kIGJlY2F1c2Ugc3RvcmVkIGJsb2NrcyBhcmUgcmVzdHJpY3RlZCB0b1xuICAgKiA2NEstMSBieXRlcy5cbiAgICovXG5cbiAgcy5sZXZlbCA9IGxldmVsO1xuICBzLnN0cmF0ZWd5ID0gc3RyYXRlZ3k7XG4gIHMubWV0aG9kID0gbWV0aG9kO1xuXG4gIHJldHVybiBkZWZsYXRlUmVzZXQoc3RybSk7XG59O1xuXG5jb25zdCBkZWZsYXRlSW5pdCA9IChzdHJtLCBsZXZlbCkgPT4ge1xuXG4gIHJldHVybiBkZWZsYXRlSW5pdDIoc3RybSwgbGV2ZWwsIFpfREVGTEFURUQkMiwgTUFYX1dCSVRTJDEsIERFRl9NRU1fTEVWRUwsIFpfREVGQVVMVF9TVFJBVEVHWSQxKTtcbn07XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqL1xuY29uc3QgZGVmbGF0ZSQyID0gKHN0cm0sIGZsdXNoKSA9PiB7XG5cbiAgaWYgKGRlZmxhdGVTdGF0ZUNoZWNrKHN0cm0pIHx8IGZsdXNoID4gWl9CTE9DSyQxIHx8IGZsdXNoIDwgMCkge1xuICAgIHJldHVybiBzdHJtID8gZXJyKHN0cm0sIFpfU1RSRUFNX0VSUk9SJDIpIDogWl9TVFJFQU1fRVJST1IkMjtcbiAgfVxuXG4gIGNvbnN0IHMgPSBzdHJtLnN0YXRlO1xuXG4gIGlmICghc3RybS5vdXRwdXQgfHxcbiAgICAgIChzdHJtLmF2YWlsX2luICE9PSAwICYmICFzdHJtLmlucHV0KSB8fFxuICAgICAgKHMuc3RhdHVzID09PSBGSU5JU0hfU1RBVEUgJiYgZmx1c2ggIT09IFpfRklOSVNIJDMpKSB7XG4gICAgcmV0dXJuIGVycihzdHJtLCAoc3RybS5hdmFpbF9vdXQgPT09IDApID8gWl9CVUZfRVJST1IkMSA6IFpfU1RSRUFNX0VSUk9SJDIpO1xuICB9XG5cbiAgY29uc3Qgb2xkX2ZsdXNoID0gcy5sYXN0X2ZsdXNoO1xuICBzLmxhc3RfZmx1c2ggPSBmbHVzaDtcblxuICAvKiBGbHVzaCBhcyBtdWNoIHBlbmRpbmcgb3V0cHV0IGFzIHBvc3NpYmxlICovXG4gIGlmIChzLnBlbmRpbmcgIT09IDApIHtcbiAgICBmbHVzaF9wZW5kaW5nKHN0cm0pO1xuICAgIGlmIChzdHJtLmF2YWlsX291dCA9PT0gMCkge1xuICAgICAgLyogU2luY2UgYXZhaWxfb3V0IGlzIDAsIGRlZmxhdGUgd2lsbCBiZSBjYWxsZWQgYWdhaW4gd2l0aFxuICAgICAgICogbW9yZSBvdXRwdXQgc3BhY2UsIGJ1dCBwb3NzaWJseSB3aXRoIGJvdGggcGVuZGluZyBhbmRcbiAgICAgICAqIGF2YWlsX2luIGVxdWFsIHRvIHplcm8uIFRoZXJlIHdvbid0IGJlIGFueXRoaW5nIHRvIGRvLFxuICAgICAgICogYnV0IHRoaXMgaXMgbm90IGFuIGVycm9yIHNpdHVhdGlvbiBzbyBtYWtlIHN1cmUgd2VcbiAgICAgICAqIHJldHVybiBPSyBpbnN0ZWFkIG9mIEJVRl9FUlJPUiBhdCBuZXh0IGNhbGwgb2YgZGVmbGF0ZTpcbiAgICAgICAqL1xuICAgICAgcy5sYXN0X2ZsdXNoID0gLTE7XG4gICAgICByZXR1cm4gWl9PSyQzO1xuICAgIH1cblxuICAgIC8qIE1ha2Ugc3VyZSB0aGVyZSBpcyBzb21ldGhpbmcgdG8gZG8gYW5kIGF2b2lkIGR1cGxpY2F0ZSBjb25zZWN1dGl2ZVxuICAgICAqIGZsdXNoZXMuIEZvciByZXBlYXRlZCBhbmQgdXNlbGVzcyBjYWxscyB3aXRoIFpfRklOSVNILCB3ZSBrZWVwXG4gICAgICogcmV0dXJuaW5nIFpfU1RSRUFNX0VORCBpbnN0ZWFkIG9mIFpfQlVGX0VSUk9SLlxuICAgICAqL1xuICB9IGVsc2UgaWYgKHN0cm0uYXZhaWxfaW4gPT09IDAgJiYgcmFuayhmbHVzaCkgPD0gcmFuayhvbGRfZmx1c2gpICYmXG4gICAgZmx1c2ggIT09IFpfRklOSVNIJDMpIHtcbiAgICByZXR1cm4gZXJyKHN0cm0sIFpfQlVGX0VSUk9SJDEpO1xuICB9XG5cbiAgLyogVXNlciBtdXN0IG5vdCBwcm92aWRlIG1vcmUgaW5wdXQgYWZ0ZXIgdGhlIGZpcnN0IEZJTklTSDogKi9cbiAgaWYgKHMuc3RhdHVzID09PSBGSU5JU0hfU1RBVEUgJiYgc3RybS5hdmFpbF9pbiAhPT0gMCkge1xuICAgIHJldHVybiBlcnIoc3RybSwgWl9CVUZfRVJST1IkMSk7XG4gIH1cblxuICAvKiBXcml0ZSB0aGUgaGVhZGVyICovXG4gIGlmIChzLnN0YXR1cyA9PT0gSU5JVF9TVEFURSAmJiBzLndyYXAgPT09IDApIHtcbiAgICBzLnN0YXR1cyA9IEJVU1lfU1RBVEU7XG4gIH1cbiAgaWYgKHMuc3RhdHVzID09PSBJTklUX1NUQVRFKSB7XG4gICAgLyogemxpYiBoZWFkZXIgKi9cbiAgICBsZXQgaGVhZGVyID0gKFpfREVGTEFURUQkMiArICgocy53X2JpdHMgLSA4KSA8PCA0KSkgPDwgODtcbiAgICBsZXQgbGV2ZWxfZmxhZ3MgPSAtMTtcblxuICAgIGlmIChzLnN0cmF0ZWd5ID49IFpfSFVGRk1BTl9PTkxZIHx8IHMubGV2ZWwgPCAyKSB7XG4gICAgICBsZXZlbF9mbGFncyA9IDA7XG4gICAgfSBlbHNlIGlmIChzLmxldmVsIDwgNikge1xuICAgICAgbGV2ZWxfZmxhZ3MgPSAxO1xuICAgIH0gZWxzZSBpZiAocy5sZXZlbCA9PT0gNikge1xuICAgICAgbGV2ZWxfZmxhZ3MgPSAyO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXZlbF9mbGFncyA9IDM7XG4gICAgfVxuICAgIGhlYWRlciB8PSAobGV2ZWxfZmxhZ3MgPDwgNik7XG4gICAgaWYgKHMuc3Ryc3RhcnQgIT09IDApIHsgaGVhZGVyIHw9IFBSRVNFVF9ESUNUOyB9XG4gICAgaGVhZGVyICs9IDMxIC0gKGhlYWRlciAlIDMxKTtcblxuICAgIHB1dFNob3J0TVNCKHMsIGhlYWRlcik7XG5cbiAgICAvKiBTYXZlIHRoZSBhZGxlcjMyIG9mIHRoZSBwcmVzZXQgZGljdGlvbmFyeTogKi9cbiAgICBpZiAocy5zdHJzdGFydCAhPT0gMCkge1xuICAgICAgcHV0U2hvcnRNU0Iocywgc3RybS5hZGxlciA+Pj4gMTYpO1xuICAgICAgcHV0U2hvcnRNU0Iocywgc3RybS5hZGxlciAmIDB4ZmZmZik7XG4gICAgfVxuICAgIHN0cm0uYWRsZXIgPSAxOyAvLyBhZGxlcjMyKDBMLCBaX05VTEwsIDApO1xuICAgIHMuc3RhdHVzID0gQlVTWV9TVEFURTtcblxuICAgIC8qIENvbXByZXNzaW9uIG11c3Qgc3RhcnQgd2l0aCBhbiBlbXB0eSBwZW5kaW5nIGJ1ZmZlciAqL1xuICAgIGZsdXNoX3BlbmRpbmcoc3RybSk7XG4gICAgaWYgKHMucGVuZGluZyAhPT0gMCkge1xuICAgICAgcy5sYXN0X2ZsdXNoID0gLTE7XG4gICAgICByZXR1cm4gWl9PSyQzO1xuICAgIH1cbiAgfVxuLy8jaWZkZWYgR1pJUFxuICBpZiAocy5zdGF0dXMgPT09IEdaSVBfU1RBVEUpIHtcbiAgICAvKiBnemlwIGhlYWRlciAqL1xuICAgIHN0cm0uYWRsZXIgPSAwOyAgLy9jcmMzMigwTCwgWl9OVUxMLCAwKTtcbiAgICBwdXRfYnl0ZShzLCAzMSk7XG4gICAgcHV0X2J5dGUocywgMTM5KTtcbiAgICBwdXRfYnl0ZShzLCA4KTtcbiAgICBpZiAoIXMuZ3poZWFkKSB7IC8vIHMtPmd6aGVhZCA9PSBaX05VTExcbiAgICAgIHB1dF9ieXRlKHMsIDApO1xuICAgICAgcHV0X2J5dGUocywgMCk7XG4gICAgICBwdXRfYnl0ZShzLCAwKTtcbiAgICAgIHB1dF9ieXRlKHMsIDApO1xuICAgICAgcHV0X2J5dGUocywgMCk7XG4gICAgICBwdXRfYnl0ZShzLCBzLmxldmVsID09PSA5ID8gMiA6XG4gICAgICAgICAgICAgICAgICAocy5zdHJhdGVneSA+PSBaX0hVRkZNQU5fT05MWSB8fCBzLmxldmVsIDwgMiA/XG4gICAgICAgICAgICAgICAgICAgNCA6IDApKTtcbiAgICAgIHB1dF9ieXRlKHMsIE9TX0NPREUpO1xuICAgICAgcy5zdGF0dXMgPSBCVVNZX1NUQVRFO1xuXG4gICAgICAvKiBDb21wcmVzc2lvbiBtdXN0IHN0YXJ0IHdpdGggYW4gZW1wdHkgcGVuZGluZyBidWZmZXIgKi9cbiAgICAgIGZsdXNoX3BlbmRpbmcoc3RybSk7XG4gICAgICBpZiAocy5wZW5kaW5nICE9PSAwKSB7XG4gICAgICAgIHMubGFzdF9mbHVzaCA9IC0xO1xuICAgICAgICByZXR1cm4gWl9PSyQzO1xuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHB1dF9ieXRlKHMsIChzLmd6aGVhZC50ZXh0ID8gMSA6IDApICtcbiAgICAgICAgICAgICAgICAgIChzLmd6aGVhZC5oY3JjID8gMiA6IDApICtcbiAgICAgICAgICAgICAgICAgICghcy5nemhlYWQuZXh0cmEgPyAwIDogNCkgK1xuICAgICAgICAgICAgICAgICAgKCFzLmd6aGVhZC5uYW1lID8gMCA6IDgpICtcbiAgICAgICAgICAgICAgICAgICghcy5nemhlYWQuY29tbWVudCA/IDAgOiAxNilcbiAgICAgICk7XG4gICAgICBwdXRfYnl0ZShzLCBzLmd6aGVhZC50aW1lICYgMHhmZik7XG4gICAgICBwdXRfYnl0ZShzLCAocy5nemhlYWQudGltZSA+PiA4KSAmIDB4ZmYpO1xuICAgICAgcHV0X2J5dGUocywgKHMuZ3poZWFkLnRpbWUgPj4gMTYpICYgMHhmZik7XG4gICAgICBwdXRfYnl0ZShzLCAocy5nemhlYWQudGltZSA+PiAyNCkgJiAweGZmKTtcbiAgICAgIHB1dF9ieXRlKHMsIHMubGV2ZWwgPT09IDkgPyAyIDpcbiAgICAgICAgICAgICAgICAgIChzLnN0cmF0ZWd5ID49IFpfSFVGRk1BTl9PTkxZIHx8IHMubGV2ZWwgPCAyID9cbiAgICAgICAgICAgICAgICAgICA0IDogMCkpO1xuICAgICAgcHV0X2J5dGUocywgcy5nemhlYWQub3MgJiAweGZmKTtcbiAgICAgIGlmIChzLmd6aGVhZC5leHRyYSAmJiBzLmd6aGVhZC5leHRyYS5sZW5ndGgpIHtcbiAgICAgICAgcHV0X2J5dGUocywgcy5nemhlYWQuZXh0cmEubGVuZ3RoICYgMHhmZik7XG4gICAgICAgIHB1dF9ieXRlKHMsIChzLmd6aGVhZC5leHRyYS5sZW5ndGggPj4gOCkgJiAweGZmKTtcbiAgICAgIH1cbiAgICAgIGlmIChzLmd6aGVhZC5oY3JjKSB7XG4gICAgICAgIHN0cm0uYWRsZXIgPSBjcmMzMl8xKHN0cm0uYWRsZXIsIHMucGVuZGluZ19idWYsIHMucGVuZGluZywgMCk7XG4gICAgICB9XG4gICAgICBzLmd6aW5kZXggPSAwO1xuICAgICAgcy5zdGF0dXMgPSBFWFRSQV9TVEFURTtcbiAgICB9XG4gIH1cbiAgaWYgKHMuc3RhdHVzID09PSBFWFRSQV9TVEFURSkge1xuICAgIGlmIChzLmd6aGVhZC5leHRyYS8qICE9IFpfTlVMTCovKSB7XG4gICAgICBsZXQgYmVnID0gcy5wZW5kaW5nOyAgIC8qIHN0YXJ0IG9mIGJ5dGVzIHRvIHVwZGF0ZSBjcmMgKi9cbiAgICAgIGxldCBsZWZ0ID0gKHMuZ3poZWFkLmV4dHJhLmxlbmd0aCAmIDB4ZmZmZikgLSBzLmd6aW5kZXg7XG4gICAgICB3aGlsZSAocy5wZW5kaW5nICsgbGVmdCA+IHMucGVuZGluZ19idWZfc2l6ZSkge1xuICAgICAgICBsZXQgY29weSA9IHMucGVuZGluZ19idWZfc2l6ZSAtIHMucGVuZGluZztcbiAgICAgICAgLy8gem1lbWNweShzLnBlbmRpbmdfYnVmICsgcy5wZW5kaW5nLFxuICAgICAgICAvLyAgICBzLmd6aGVhZC5leHRyYSArIHMuZ3ppbmRleCwgY29weSk7XG4gICAgICAgIHMucGVuZGluZ19idWYuc2V0KHMuZ3poZWFkLmV4dHJhLnN1YmFycmF5KHMuZ3ppbmRleCwgcy5nemluZGV4ICsgY29weSksIHMucGVuZGluZyk7XG4gICAgICAgIHMucGVuZGluZyA9IHMucGVuZGluZ19idWZfc2l6ZTtcbiAgICAgICAgLy8tLS0gSENSQ19VUERBVEUoYmVnKSAtLS0vL1xuICAgICAgICBpZiAocy5nemhlYWQuaGNyYyAmJiBzLnBlbmRpbmcgPiBiZWcpIHtcbiAgICAgICAgICBzdHJtLmFkbGVyID0gY3JjMzJfMShzdHJtLmFkbGVyLCBzLnBlbmRpbmdfYnVmLCBzLnBlbmRpbmcgLSBiZWcsIGJlZyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8tLS0vL1xuICAgICAgICBzLmd6aW5kZXggKz0gY29weTtcbiAgICAgICAgZmx1c2hfcGVuZGluZyhzdHJtKTtcbiAgICAgICAgaWYgKHMucGVuZGluZyAhPT0gMCkge1xuICAgICAgICAgIHMubGFzdF9mbHVzaCA9IC0xO1xuICAgICAgICAgIHJldHVybiBaX09LJDM7XG4gICAgICAgIH1cbiAgICAgICAgYmVnID0gMDtcbiAgICAgICAgbGVmdCAtPSBjb3B5O1xuICAgICAgfVxuICAgICAgLy8gSlMgc3BlY2lmaWM6IHMuZ3poZWFkLmV4dHJhIG1heSBiZSBUeXBlZEFycmF5IG9yIEFycmF5IGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG4gICAgICAvLyAgICAgICAgICAgICAgVHlwZWRBcnJheS5zbGljZSBhbmQgVHlwZWRBcnJheS5mcm9tIGRvbid0IGV4aXN0IGluIElFMTAtSUUxMVxuICAgICAgbGV0IGd6aGVhZF9leHRyYSA9IG5ldyBVaW50OEFycmF5KHMuZ3poZWFkLmV4dHJhKTtcbiAgICAgIC8vIHptZW1jcHkocy0+cGVuZGluZ19idWYgKyBzLT5wZW5kaW5nLFxuICAgICAgLy8gICAgIHMtPmd6aGVhZC0+ZXh0cmEgKyBzLT5nemluZGV4LCBsZWZ0KTtcbiAgICAgIHMucGVuZGluZ19idWYuc2V0KGd6aGVhZF9leHRyYS5zdWJhcnJheShzLmd6aW5kZXgsIHMuZ3ppbmRleCArIGxlZnQpLCBzLnBlbmRpbmcpO1xuICAgICAgcy5wZW5kaW5nICs9IGxlZnQ7XG4gICAgICAvLy0tLSBIQ1JDX1VQREFURShiZWcpIC0tLS8vXG4gICAgICBpZiAocy5nemhlYWQuaGNyYyAmJiBzLnBlbmRpbmcgPiBiZWcpIHtcbiAgICAgICAgc3RybS5hZGxlciA9IGNyYzMyXzEoc3RybS5hZGxlciwgcy5wZW5kaW5nX2J1Ziwgcy5wZW5kaW5nIC0gYmVnLCBiZWcpO1xuICAgICAgfVxuICAgICAgLy8tLS0vL1xuICAgICAgcy5nemluZGV4ID0gMDtcbiAgICB9XG4gICAgcy5zdGF0dXMgPSBOQU1FX1NUQVRFO1xuICB9XG4gIGlmIChzLnN0YXR1cyA9PT0gTkFNRV9TVEFURSkge1xuICAgIGlmIChzLmd6aGVhZC5uYW1lLyogIT0gWl9OVUxMKi8pIHtcbiAgICAgIGxldCBiZWcgPSBzLnBlbmRpbmc7ICAgLyogc3RhcnQgb2YgYnl0ZXMgdG8gdXBkYXRlIGNyYyAqL1xuICAgICAgbGV0IHZhbDtcbiAgICAgIGRvIHtcbiAgICAgICAgaWYgKHMucGVuZGluZyA9PT0gcy5wZW5kaW5nX2J1Zl9zaXplKSB7XG4gICAgICAgICAgLy8tLS0gSENSQ19VUERBVEUoYmVnKSAtLS0vL1xuICAgICAgICAgIGlmIChzLmd6aGVhZC5oY3JjICYmIHMucGVuZGluZyA+IGJlZykge1xuICAgICAgICAgICAgc3RybS5hZGxlciA9IGNyYzMyXzEoc3RybS5hZGxlciwgcy5wZW5kaW5nX2J1Ziwgcy5wZW5kaW5nIC0gYmVnLCBiZWcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLy0tLS8vXG4gICAgICAgICAgZmx1c2hfcGVuZGluZyhzdHJtKTtcbiAgICAgICAgICBpZiAocy5wZW5kaW5nICE9PSAwKSB7XG4gICAgICAgICAgICBzLmxhc3RfZmx1c2ggPSAtMTtcbiAgICAgICAgICAgIHJldHVybiBaX09LJDM7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJlZyA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSlMgc3BlY2lmaWM6IGxpdHRsZSBtYWdpYyB0byBhZGQgemVybyB0ZXJtaW5hdG9yIHRvIGVuZCBvZiBzdHJpbmdcbiAgICAgICAgaWYgKHMuZ3ppbmRleCA8IHMuZ3poZWFkLm5hbWUubGVuZ3RoKSB7XG4gICAgICAgICAgdmFsID0gcy5nemhlYWQubmFtZS5jaGFyQ29kZUF0KHMuZ3ppbmRleCsrKSAmIDB4ZmY7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFsID0gMDtcbiAgICAgICAgfVxuICAgICAgICBwdXRfYnl0ZShzLCB2YWwpO1xuICAgICAgfSB3aGlsZSAodmFsICE9PSAwKTtcbiAgICAgIC8vLS0tIEhDUkNfVVBEQVRFKGJlZykgLS0tLy9cbiAgICAgIGlmIChzLmd6aGVhZC5oY3JjICYmIHMucGVuZGluZyA+IGJlZykge1xuICAgICAgICBzdHJtLmFkbGVyID0gY3JjMzJfMShzdHJtLmFkbGVyLCBzLnBlbmRpbmdfYnVmLCBzLnBlbmRpbmcgLSBiZWcsIGJlZyk7XG4gICAgICB9XG4gICAgICAvLy0tLS8vXG4gICAgICBzLmd6aW5kZXggPSAwO1xuICAgIH1cbiAgICBzLnN0YXR1cyA9IENPTU1FTlRfU1RBVEU7XG4gIH1cbiAgaWYgKHMuc3RhdHVzID09PSBDT01NRU5UX1NUQVRFKSB7XG4gICAgaWYgKHMuZ3poZWFkLmNvbW1lbnQvKiAhPSBaX05VTEwqLykge1xuICAgICAgbGV0IGJlZyA9IHMucGVuZGluZzsgICAvKiBzdGFydCBvZiBieXRlcyB0byB1cGRhdGUgY3JjICovXG4gICAgICBsZXQgdmFsO1xuICAgICAgZG8ge1xuICAgICAgICBpZiAocy5wZW5kaW5nID09PSBzLnBlbmRpbmdfYnVmX3NpemUpIHtcbiAgICAgICAgICAvLy0tLSBIQ1JDX1VQREFURShiZWcpIC0tLS8vXG4gICAgICAgICAgaWYgKHMuZ3poZWFkLmhjcmMgJiYgcy5wZW5kaW5nID4gYmVnKSB7XG4gICAgICAgICAgICBzdHJtLmFkbGVyID0gY3JjMzJfMShzdHJtLmFkbGVyLCBzLnBlbmRpbmdfYnVmLCBzLnBlbmRpbmcgLSBiZWcsIGJlZyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vLS0tLy9cbiAgICAgICAgICBmbHVzaF9wZW5kaW5nKHN0cm0pO1xuICAgICAgICAgIGlmIChzLnBlbmRpbmcgIT09IDApIHtcbiAgICAgICAgICAgIHMubGFzdF9mbHVzaCA9IC0xO1xuICAgICAgICAgICAgcmV0dXJuIFpfT0skMztcbiAgICAgICAgICB9XG4gICAgICAgICAgYmVnID0gMDtcbiAgICAgICAgfVxuICAgICAgICAvLyBKUyBzcGVjaWZpYzogbGl0dGxlIG1hZ2ljIHRvIGFkZCB6ZXJvIHRlcm1pbmF0b3IgdG8gZW5kIG9mIHN0cmluZ1xuICAgICAgICBpZiAocy5nemluZGV4IDwgcy5nemhlYWQuY29tbWVudC5sZW5ndGgpIHtcbiAgICAgICAgICB2YWwgPSBzLmd6aGVhZC5jb21tZW50LmNoYXJDb2RlQXQocy5nemluZGV4KyspICYgMHhmZjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YWwgPSAwO1xuICAgICAgICB9XG4gICAgICAgIHB1dF9ieXRlKHMsIHZhbCk7XG4gICAgICB9IHdoaWxlICh2YWwgIT09IDApO1xuICAgICAgLy8tLS0gSENSQ19VUERBVEUoYmVnKSAtLS0vL1xuICAgICAgaWYgKHMuZ3poZWFkLmhjcmMgJiYgcy5wZW5kaW5nID4gYmVnKSB7XG4gICAgICAgIHN0cm0uYWRsZXIgPSBjcmMzMl8xKHN0cm0uYWRsZXIsIHMucGVuZGluZ19idWYsIHMucGVuZGluZyAtIGJlZywgYmVnKTtcbiAgICAgIH1cbiAgICAgIC8vLS0tLy9cbiAgICB9XG4gICAgcy5zdGF0dXMgPSBIQ1JDX1NUQVRFO1xuICB9XG4gIGlmIChzLnN0YXR1cyA9PT0gSENSQ19TVEFURSkge1xuICAgIGlmIChzLmd6aGVhZC5oY3JjKSB7XG4gICAgICBpZiAocy5wZW5kaW5nICsgMiA+IHMucGVuZGluZ19idWZfc2l6ZSkge1xuICAgICAgICBmbHVzaF9wZW5kaW5nKHN0cm0pO1xuICAgICAgICBpZiAocy5wZW5kaW5nICE9PSAwKSB7XG4gICAgICAgICAgcy5sYXN0X2ZsdXNoID0gLTE7XG4gICAgICAgICAgcmV0dXJuIFpfT0skMztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcHV0X2J5dGUocywgc3RybS5hZGxlciAmIDB4ZmYpO1xuICAgICAgcHV0X2J5dGUocywgKHN0cm0uYWRsZXIgPj4gOCkgJiAweGZmKTtcbiAgICAgIHN0cm0uYWRsZXIgPSAwOyAvL2NyYzMyKDBMLCBaX05VTEwsIDApO1xuICAgIH1cbiAgICBzLnN0YXR1cyA9IEJVU1lfU1RBVEU7XG5cbiAgICAvKiBDb21wcmVzc2lvbiBtdXN0IHN0YXJ0IHdpdGggYW4gZW1wdHkgcGVuZGluZyBidWZmZXIgKi9cbiAgICBmbHVzaF9wZW5kaW5nKHN0cm0pO1xuICAgIGlmIChzLnBlbmRpbmcgIT09IDApIHtcbiAgICAgIHMubGFzdF9mbHVzaCA9IC0xO1xuICAgICAgcmV0dXJuIFpfT0skMztcbiAgICB9XG4gIH1cbi8vI2VuZGlmXG5cbiAgLyogU3RhcnQgYSBuZXcgYmxvY2sgb3IgY29udGludWUgdGhlIGN1cnJlbnQgb25lLlxuICAgKi9cbiAgaWYgKHN0cm0uYXZhaWxfaW4gIT09IDAgfHwgcy5sb29rYWhlYWQgIT09IDAgfHxcbiAgICAoZmx1c2ggIT09IFpfTk9fRkxVU0gkMiAmJiBzLnN0YXR1cyAhPT0gRklOSVNIX1NUQVRFKSkge1xuICAgIGxldCBic3RhdGUgPSBzLmxldmVsID09PSAwID8gZGVmbGF0ZV9zdG9yZWQocywgZmx1c2gpIDpcbiAgICAgICAgICAgICAgICAgcy5zdHJhdGVneSA9PT0gWl9IVUZGTUFOX09OTFkgPyBkZWZsYXRlX2h1ZmYocywgZmx1c2gpIDpcbiAgICAgICAgICAgICAgICAgcy5zdHJhdGVneSA9PT0gWl9STEUgPyBkZWZsYXRlX3JsZShzLCBmbHVzaCkgOlxuICAgICAgICAgICAgICAgICBjb25maWd1cmF0aW9uX3RhYmxlW3MubGV2ZWxdLmZ1bmMocywgZmx1c2gpO1xuXG4gICAgaWYgKGJzdGF0ZSA9PT0gQlNfRklOSVNIX1NUQVJURUQgfHwgYnN0YXRlID09PSBCU19GSU5JU0hfRE9ORSkge1xuICAgICAgcy5zdGF0dXMgPSBGSU5JU0hfU1RBVEU7XG4gICAgfVxuICAgIGlmIChic3RhdGUgPT09IEJTX05FRURfTU9SRSB8fCBic3RhdGUgPT09IEJTX0ZJTklTSF9TVEFSVEVEKSB7XG4gICAgICBpZiAoc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgICAgcy5sYXN0X2ZsdXNoID0gLTE7XG4gICAgICAgIC8qIGF2b2lkIEJVRl9FUlJPUiBuZXh0IGNhbGwsIHNlZSBhYm92ZSAqL1xuICAgICAgfVxuICAgICAgcmV0dXJuIFpfT0skMztcbiAgICAgIC8qIElmIGZsdXNoICE9IFpfTk9fRkxVU0ggJiYgYXZhaWxfb3V0ID09IDAsIHRoZSBuZXh0IGNhbGxcbiAgICAgICAqIG9mIGRlZmxhdGUgc2hvdWxkIHVzZSB0aGUgc2FtZSBmbHVzaCBwYXJhbWV0ZXIgdG8gbWFrZSBzdXJlXG4gICAgICAgKiB0aGF0IHRoZSBmbHVzaCBpcyBjb21wbGV0ZS4gU28gd2UgZG9uJ3QgaGF2ZSB0byBvdXRwdXQgYW5cbiAgICAgICAqIGVtcHR5IGJsb2NrIGhlcmUsIHRoaXMgd2lsbCBiZSBkb25lIGF0IG5leHQgY2FsbC4gVGhpcyBhbHNvXG4gICAgICAgKiBlbnN1cmVzIHRoYXQgZm9yIGEgdmVyeSBzbWFsbCBvdXRwdXQgYnVmZmVyLCB3ZSBlbWl0IGF0IG1vc3RcbiAgICAgICAqIG9uZSBlbXB0eSBibG9jay5cbiAgICAgICAqL1xuICAgIH1cbiAgICBpZiAoYnN0YXRlID09PSBCU19CTE9DS19ET05FKSB7XG4gICAgICBpZiAoZmx1c2ggPT09IFpfUEFSVElBTF9GTFVTSCkge1xuICAgICAgICBfdHJfYWxpZ24ocyk7XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChmbHVzaCAhPT0gWl9CTE9DSyQxKSB7IC8qIEZVTExfRkxVU0ggb3IgU1lOQ19GTFVTSCAqL1xuXG4gICAgICAgIF90cl9zdG9yZWRfYmxvY2socywgMCwgMCwgZmFsc2UpO1xuICAgICAgICAvKiBGb3IgYSBmdWxsIGZsdXNoLCB0aGlzIGVtcHR5IGJsb2NrIHdpbGwgYmUgcmVjb2duaXplZFxuICAgICAgICAgKiBhcyBhIHNwZWNpYWwgbWFya2VyIGJ5IGluZmxhdGVfc3luYygpLlxuICAgICAgICAgKi9cbiAgICAgICAgaWYgKGZsdXNoID09PSBaX0ZVTExfRkxVU0gkMSkge1xuICAgICAgICAgIC8qKiogQ0xFQVJfSEFTSChzKTsgKioqLyAgICAgICAgICAgICAvKiBmb3JnZXQgaGlzdG9yeSAqL1xuICAgICAgICAgIHplcm8ocy5oZWFkKTsgLy8gRmlsbCB3aXRoIE5JTCAoPSAwKTtcblxuICAgICAgICAgIGlmIChzLmxvb2thaGVhZCA9PT0gMCkge1xuICAgICAgICAgICAgcy5zdHJzdGFydCA9IDA7XG4gICAgICAgICAgICBzLmJsb2NrX3N0YXJ0ID0gMDtcbiAgICAgICAgICAgIHMuaW5zZXJ0ID0gMDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZsdXNoX3BlbmRpbmcoc3RybSk7XG4gICAgICBpZiAoc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgICAgcy5sYXN0X2ZsdXNoID0gLTE7IC8qIGF2b2lkIEJVRl9FUlJPUiBhdCBuZXh0IGNhbGwsIHNlZSBhYm92ZSAqL1xuICAgICAgICByZXR1cm4gWl9PSyQzO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmIChmbHVzaCAhPT0gWl9GSU5JU0gkMykgeyByZXR1cm4gWl9PSyQzOyB9XG4gIGlmIChzLndyYXAgPD0gMCkgeyByZXR1cm4gWl9TVFJFQU1fRU5EJDM7IH1cblxuICAvKiBXcml0ZSB0aGUgdHJhaWxlciAqL1xuICBpZiAocy53cmFwID09PSAyKSB7XG4gICAgcHV0X2J5dGUocywgc3RybS5hZGxlciAmIDB4ZmYpO1xuICAgIHB1dF9ieXRlKHMsIChzdHJtLmFkbGVyID4+IDgpICYgMHhmZik7XG4gICAgcHV0X2J5dGUocywgKHN0cm0uYWRsZXIgPj4gMTYpICYgMHhmZik7XG4gICAgcHV0X2J5dGUocywgKHN0cm0uYWRsZXIgPj4gMjQpICYgMHhmZik7XG4gICAgcHV0X2J5dGUocywgc3RybS50b3RhbF9pbiAmIDB4ZmYpO1xuICAgIHB1dF9ieXRlKHMsIChzdHJtLnRvdGFsX2luID4+IDgpICYgMHhmZik7XG4gICAgcHV0X2J5dGUocywgKHN0cm0udG90YWxfaW4gPj4gMTYpICYgMHhmZik7XG4gICAgcHV0X2J5dGUocywgKHN0cm0udG90YWxfaW4gPj4gMjQpICYgMHhmZik7XG4gIH1cbiAgZWxzZVxuICB7XG4gICAgcHV0U2hvcnRNU0Iocywgc3RybS5hZGxlciA+Pj4gMTYpO1xuICAgIHB1dFNob3J0TVNCKHMsIHN0cm0uYWRsZXIgJiAweGZmZmYpO1xuICB9XG5cbiAgZmx1c2hfcGVuZGluZyhzdHJtKTtcbiAgLyogSWYgYXZhaWxfb3V0IGlzIHplcm8sIHRoZSBhcHBsaWNhdGlvbiB3aWxsIGNhbGwgZGVmbGF0ZSBhZ2FpblxuICAgKiB0byBmbHVzaCB0aGUgcmVzdC5cbiAgICovXG4gIGlmIChzLndyYXAgPiAwKSB7IHMud3JhcCA9IC1zLndyYXA7IH1cbiAgLyogd3JpdGUgdGhlIHRyYWlsZXIgb25seSBvbmNlISAqL1xuICByZXR1cm4gcy5wZW5kaW5nICE9PSAwID8gWl9PSyQzIDogWl9TVFJFQU1fRU5EJDM7XG59O1xuXG5cbmNvbnN0IGRlZmxhdGVFbmQgPSAoc3RybSkgPT4ge1xuXG4gIGlmIChkZWZsYXRlU3RhdGVDaGVjayhzdHJtKSkge1xuICAgIHJldHVybiBaX1NUUkVBTV9FUlJPUiQyO1xuICB9XG5cbiAgY29uc3Qgc3RhdHVzID0gc3RybS5zdGF0ZS5zdGF0dXM7XG5cbiAgc3RybS5zdGF0ZSA9IG51bGw7XG5cbiAgcmV0dXJuIHN0YXR1cyA9PT0gQlVTWV9TVEFURSA/IGVycihzdHJtLCBaX0RBVEFfRVJST1IkMikgOiBaX09LJDM7XG59O1xuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEluaXRpYWxpemVzIHRoZSBjb21wcmVzc2lvbiBkaWN0aW9uYXJ5IGZyb20gdGhlIGdpdmVuIGJ5dGVcbiAqIHNlcXVlbmNlIHdpdGhvdXQgcHJvZHVjaW5nIGFueSBjb21wcmVzc2VkIG91dHB1dC5cbiAqL1xuY29uc3QgZGVmbGF0ZVNldERpY3Rpb25hcnkgPSAoc3RybSwgZGljdGlvbmFyeSkgPT4ge1xuXG4gIGxldCBkaWN0TGVuZ3RoID0gZGljdGlvbmFyeS5sZW5ndGg7XG5cbiAgaWYgKGRlZmxhdGVTdGF0ZUNoZWNrKHN0cm0pKSB7XG4gICAgcmV0dXJuIFpfU1RSRUFNX0VSUk9SJDI7XG4gIH1cblxuICBjb25zdCBzID0gc3RybS5zdGF0ZTtcbiAgY29uc3Qgd3JhcCA9IHMud3JhcDtcblxuICBpZiAod3JhcCA9PT0gMiB8fCAod3JhcCA9PT0gMSAmJiBzLnN0YXR1cyAhPT0gSU5JVF9TVEFURSkgfHwgcy5sb29rYWhlYWQpIHtcbiAgICByZXR1cm4gWl9TVFJFQU1fRVJST1IkMjtcbiAgfVxuXG4gIC8qIHdoZW4gdXNpbmcgemxpYiB3cmFwcGVycywgY29tcHV0ZSBBZGxlci0zMiBmb3IgcHJvdmlkZWQgZGljdGlvbmFyeSAqL1xuICBpZiAod3JhcCA9PT0gMSkge1xuICAgIC8qIGFkbGVyMzIoc3RybS0+YWRsZXIsIGRpY3Rpb25hcnksIGRpY3RMZW5ndGgpOyAqL1xuICAgIHN0cm0uYWRsZXIgPSBhZGxlcjMyXzEoc3RybS5hZGxlciwgZGljdGlvbmFyeSwgZGljdExlbmd0aCwgMCk7XG4gIH1cblxuICBzLndyYXAgPSAwOyAgIC8qIGF2b2lkIGNvbXB1dGluZyBBZGxlci0zMiBpbiByZWFkX2J1ZiAqL1xuXG4gIC8qIGlmIGRpY3Rpb25hcnkgd291bGQgZmlsbCB3aW5kb3csIGp1c3QgcmVwbGFjZSB0aGUgaGlzdG9yeSAqL1xuICBpZiAoZGljdExlbmd0aCA+PSBzLndfc2l6ZSkge1xuICAgIGlmICh3cmFwID09PSAwKSB7ICAgICAgICAgICAgLyogYWxyZWFkeSBlbXB0eSBvdGhlcndpc2UgKi9cbiAgICAgIC8qKiogQ0xFQVJfSEFTSChzKTsgKioqL1xuICAgICAgemVybyhzLmhlYWQpOyAvLyBGaWxsIHdpdGggTklMICg9IDApO1xuICAgICAgcy5zdHJzdGFydCA9IDA7XG4gICAgICBzLmJsb2NrX3N0YXJ0ID0gMDtcbiAgICAgIHMuaW5zZXJ0ID0gMDtcbiAgICB9XG4gICAgLyogdXNlIHRoZSB0YWlsICovXG4gICAgLy8gZGljdGlvbmFyeSA9IGRpY3Rpb25hcnkuc2xpY2UoZGljdExlbmd0aCAtIHMud19zaXplKTtcbiAgICBsZXQgdG1wRGljdCA9IG5ldyBVaW50OEFycmF5KHMud19zaXplKTtcbiAgICB0bXBEaWN0LnNldChkaWN0aW9uYXJ5LnN1YmFycmF5KGRpY3RMZW5ndGggLSBzLndfc2l6ZSwgZGljdExlbmd0aCksIDApO1xuICAgIGRpY3Rpb25hcnkgPSB0bXBEaWN0O1xuICAgIGRpY3RMZW5ndGggPSBzLndfc2l6ZTtcbiAgfVxuICAvKiBpbnNlcnQgZGljdGlvbmFyeSBpbnRvIHdpbmRvdyBhbmQgaGFzaCAqL1xuICBjb25zdCBhdmFpbCA9IHN0cm0uYXZhaWxfaW47XG4gIGNvbnN0IG5leHQgPSBzdHJtLm5leHRfaW47XG4gIGNvbnN0IGlucHV0ID0gc3RybS5pbnB1dDtcbiAgc3RybS5hdmFpbF9pbiA9IGRpY3RMZW5ndGg7XG4gIHN0cm0ubmV4dF9pbiA9IDA7XG4gIHN0cm0uaW5wdXQgPSBkaWN0aW9uYXJ5O1xuICBmaWxsX3dpbmRvdyhzKTtcbiAgd2hpbGUgKHMubG9va2FoZWFkID49IE1JTl9NQVRDSCkge1xuICAgIGxldCBzdHIgPSBzLnN0cnN0YXJ0O1xuICAgIGxldCBuID0gcy5sb29rYWhlYWQgLSAoTUlOX01BVENIIC0gMSk7XG4gICAgZG8ge1xuICAgICAgLyogVVBEQVRFX0hBU0gocywgcy0+aW5zX2gsIHMtPndpbmRvd1tzdHIgKyBNSU5fTUFUQ0gtMV0pOyAqL1xuICAgICAgcy5pbnNfaCA9IEhBU0gocywgcy5pbnNfaCwgcy53aW5kb3dbc3RyICsgTUlOX01BVENIIC0gMV0pO1xuXG4gICAgICBzLnByZXZbc3RyICYgcy53X21hc2tdID0gcy5oZWFkW3MuaW5zX2hdO1xuXG4gICAgICBzLmhlYWRbcy5pbnNfaF0gPSBzdHI7XG4gICAgICBzdHIrKztcbiAgICB9IHdoaWxlICgtLW4pO1xuICAgIHMuc3Ryc3RhcnQgPSBzdHI7XG4gICAgcy5sb29rYWhlYWQgPSBNSU5fTUFUQ0ggLSAxO1xuICAgIGZpbGxfd2luZG93KHMpO1xuICB9XG4gIHMuc3Ryc3RhcnQgKz0gcy5sb29rYWhlYWQ7XG4gIHMuYmxvY2tfc3RhcnQgPSBzLnN0cnN0YXJ0O1xuICBzLmluc2VydCA9IHMubG9va2FoZWFkO1xuICBzLmxvb2thaGVhZCA9IDA7XG4gIHMubWF0Y2hfbGVuZ3RoID0gcy5wcmV2X2xlbmd0aCA9IE1JTl9NQVRDSCAtIDE7XG4gIHMubWF0Y2hfYXZhaWxhYmxlID0gMDtcbiAgc3RybS5uZXh0X2luID0gbmV4dDtcbiAgc3RybS5pbnB1dCA9IGlucHV0O1xuICBzdHJtLmF2YWlsX2luID0gYXZhaWw7XG4gIHMud3JhcCA9IHdyYXA7XG4gIHJldHVybiBaX09LJDM7XG59O1xuXG5cbnZhciBkZWZsYXRlSW5pdF8xID0gZGVmbGF0ZUluaXQ7XG52YXIgZGVmbGF0ZUluaXQyXzEgPSBkZWZsYXRlSW5pdDI7XG52YXIgZGVmbGF0ZVJlc2V0XzEgPSBkZWZsYXRlUmVzZXQ7XG52YXIgZGVmbGF0ZVJlc2V0S2VlcF8xID0gZGVmbGF0ZVJlc2V0S2VlcDtcbnZhciBkZWZsYXRlU2V0SGVhZGVyXzEgPSBkZWZsYXRlU2V0SGVhZGVyO1xudmFyIGRlZmxhdGVfMiQxID0gZGVmbGF0ZSQyO1xudmFyIGRlZmxhdGVFbmRfMSA9IGRlZmxhdGVFbmQ7XG52YXIgZGVmbGF0ZVNldERpY3Rpb25hcnlfMSA9IGRlZmxhdGVTZXREaWN0aW9uYXJ5O1xudmFyIGRlZmxhdGVJbmZvID0gJ3Bha28gZGVmbGF0ZSAoZnJvbSBOb2RlY2EgcHJvamVjdCknO1xuXG4vKiBOb3QgaW1wbGVtZW50ZWRcbm1vZHVsZS5leHBvcnRzLmRlZmxhdGVCb3VuZCA9IGRlZmxhdGVCb3VuZDtcbm1vZHVsZS5leHBvcnRzLmRlZmxhdGVDb3B5ID0gZGVmbGF0ZUNvcHk7XG5tb2R1bGUuZXhwb3J0cy5kZWZsYXRlR2V0RGljdGlvbmFyeSA9IGRlZmxhdGVHZXREaWN0aW9uYXJ5O1xubW9kdWxlLmV4cG9ydHMuZGVmbGF0ZVBhcmFtcyA9IGRlZmxhdGVQYXJhbXM7XG5tb2R1bGUuZXhwb3J0cy5kZWZsYXRlUGVuZGluZyA9IGRlZmxhdGVQZW5kaW5nO1xubW9kdWxlLmV4cG9ydHMuZGVmbGF0ZVByaW1lID0gZGVmbGF0ZVByaW1lO1xubW9kdWxlLmV4cG9ydHMuZGVmbGF0ZVR1bmUgPSBkZWZsYXRlVHVuZTtcbiovXG5cbnZhciBkZWZsYXRlXzEkMiA9IHtcblx0ZGVmbGF0ZUluaXQ6IGRlZmxhdGVJbml0XzEsXG5cdGRlZmxhdGVJbml0MjogZGVmbGF0ZUluaXQyXzEsXG5cdGRlZmxhdGVSZXNldDogZGVmbGF0ZVJlc2V0XzEsXG5cdGRlZmxhdGVSZXNldEtlZXA6IGRlZmxhdGVSZXNldEtlZXBfMSxcblx0ZGVmbGF0ZVNldEhlYWRlcjogZGVmbGF0ZVNldEhlYWRlcl8xLFxuXHRkZWZsYXRlOiBkZWZsYXRlXzIkMSxcblx0ZGVmbGF0ZUVuZDogZGVmbGF0ZUVuZF8xLFxuXHRkZWZsYXRlU2V0RGljdGlvbmFyeTogZGVmbGF0ZVNldERpY3Rpb25hcnlfMSxcblx0ZGVmbGF0ZUluZm86IGRlZmxhdGVJbmZvXG59O1xuXG5jb25zdCBfaGFzID0gKG9iaiwga2V5KSA9PiB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpO1xufTtcblxudmFyIGFzc2lnbiA9IGZ1bmN0aW9uIChvYmogLypmcm9tMSwgZnJvbTIsIGZyb20zLCAuLi4qLykge1xuICBjb25zdCBzb3VyY2VzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgd2hpbGUgKHNvdXJjZXMubGVuZ3RoKSB7XG4gICAgY29uc3Qgc291cmNlID0gc291cmNlcy5zaGlmdCgpO1xuICAgIGlmICghc291cmNlKSB7IGNvbnRpbnVlOyB9XG5cbiAgICBpZiAodHlwZW9mIHNvdXJjZSAhPT0gJ29iamVjdCcpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3Ioc291cmNlICsgJ211c3QgYmUgbm9uLW9iamVjdCcpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgcCBpbiBzb3VyY2UpIHtcbiAgICAgIGlmIChfaGFzKHNvdXJjZSwgcCkpIHtcbiAgICAgICAgb2JqW3BdID0gc291cmNlW3BdO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBvYmo7XG59O1xuXG5cbi8vIEpvaW4gYXJyYXkgb2YgY2h1bmtzIHRvIHNpbmdsZSBhcnJheS5cbnZhciBmbGF0dGVuQ2h1bmtzID0gKGNodW5rcykgPT4ge1xuICAvLyBjYWxjdWxhdGUgZGF0YSBsZW5ndGhcbiAgbGV0IGxlbiA9IDA7XG5cbiAgZm9yIChsZXQgaSA9IDAsIGwgPSBjaHVua3MubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgbGVuICs9IGNodW5rc1tpXS5sZW5ndGg7XG4gIH1cblxuICAvLyBqb2luIGNodW5rc1xuICBjb25zdCByZXN1bHQgPSBuZXcgVWludDhBcnJheShsZW4pO1xuXG4gIGZvciAobGV0IGkgPSAwLCBwb3MgPSAwLCBsID0gY2h1bmtzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIGxldCBjaHVuayA9IGNodW5rc1tpXTtcbiAgICByZXN1bHQuc2V0KGNodW5rLCBwb3MpO1xuICAgIHBvcyArPSBjaHVuay5sZW5ndGg7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufTtcblxudmFyIGNvbW1vbiA9IHtcblx0YXNzaWduOiBhc3NpZ24sXG5cdGZsYXR0ZW5DaHVua3M6IGZsYXR0ZW5DaHVua3Ncbn07XG5cbi8vIFN0cmluZyBlbmNvZGUvZGVjb2RlIGhlbHBlcnNcblxuXG4vLyBRdWljayBjaGVjayBpZiB3ZSBjYW4gdXNlIGZhc3QgYXJyYXkgdG8gYmluIHN0cmluZyBjb252ZXJzaW9uXG4vL1xuLy8gLSBhcHBseShBcnJheSkgY2FuIGZhaWwgb24gQW5kcm9pZCAyLjJcbi8vIC0gYXBwbHkoVWludDhBcnJheSkgY2FuIGZhaWwgb24gaU9TIDUuMSBTYWZhcmlcbi8vXG5sZXQgU1RSX0FQUExZX1VJQV9PSyA9IHRydWU7XG5cbnRyeSB7IFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQ4QXJyYXkoMSkpOyB9IGNhdGNoIChfXykgeyBTVFJfQVBQTFlfVUlBX09LID0gZmFsc2U7IH1cblxuXG4vLyBUYWJsZSB3aXRoIHV0ZjggbGVuZ3RocyAoY2FsY3VsYXRlZCBieSBmaXJzdCBieXRlIG9mIHNlcXVlbmNlKVxuLy8gTm90ZSwgdGhhdCA1ICYgNi1ieXRlIHZhbHVlcyBhbmQgc29tZSA0LWJ5dGUgdmFsdWVzIGNhbiBub3QgYmUgcmVwcmVzZW50ZWQgaW4gSlMsXG4vLyBiZWNhdXNlIG1heCBwb3NzaWJsZSBjb2RlcG9pbnQgaXMgMHgxMGZmZmZcbmNvbnN0IF91dGY4bGVuID0gbmV3IFVpbnQ4QXJyYXkoMjU2KTtcbmZvciAobGV0IHEgPSAwOyBxIDwgMjU2OyBxKyspIHtcbiAgX3V0ZjhsZW5bcV0gPSAocSA+PSAyNTIgPyA2IDogcSA+PSAyNDggPyA1IDogcSA+PSAyNDAgPyA0IDogcSA+PSAyMjQgPyAzIDogcSA+PSAxOTIgPyAyIDogMSk7XG59XG5fdXRmOGxlblsyNTRdID0gX3V0ZjhsZW5bMjU0XSA9IDE7IC8vIEludmFsaWQgc2VxdWVuY2Ugc3RhcnRcblxuXG4vLyBjb252ZXJ0IHN0cmluZyB0byBhcnJheSAodHlwZWQsIHdoZW4gcG9zc2libGUpXG52YXIgc3RyaW5nMmJ1ZiA9IChzdHIpID0+IHtcbiAgaWYgKHR5cGVvZiBUZXh0RW5jb2RlciA9PT0gJ2Z1bmN0aW9uJyAmJiBUZXh0RW5jb2Rlci5wcm90b3R5cGUuZW5jb2RlKSB7XG4gICAgcmV0dXJuIG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzdHIpO1xuICB9XG5cbiAgbGV0IGJ1ZiwgYywgYzIsIG1fcG9zLCBpLCBzdHJfbGVuID0gc3RyLmxlbmd0aCwgYnVmX2xlbiA9IDA7XG5cbiAgLy8gY291bnQgYmluYXJ5IHNpemVcbiAgZm9yIChtX3BvcyA9IDA7IG1fcG9zIDwgc3RyX2xlbjsgbV9wb3MrKykge1xuICAgIGMgPSBzdHIuY2hhckNvZGVBdChtX3Bvcyk7XG4gICAgaWYgKChjICYgMHhmYzAwKSA9PT0gMHhkODAwICYmIChtX3BvcyArIDEgPCBzdHJfbGVuKSkge1xuICAgICAgYzIgPSBzdHIuY2hhckNvZGVBdChtX3BvcyArIDEpO1xuICAgICAgaWYgKChjMiAmIDB4ZmMwMCkgPT09IDB4ZGMwMCkge1xuICAgICAgICBjID0gMHgxMDAwMCArICgoYyAtIDB4ZDgwMCkgPDwgMTApICsgKGMyIC0gMHhkYzAwKTtcbiAgICAgICAgbV9wb3MrKztcbiAgICAgIH1cbiAgICB9XG4gICAgYnVmX2xlbiArPSBjIDwgMHg4MCA/IDEgOiBjIDwgMHg4MDAgPyAyIDogYyA8IDB4MTAwMDAgPyAzIDogNDtcbiAgfVxuXG4gIC8vIGFsbG9jYXRlIGJ1ZmZlclxuICBidWYgPSBuZXcgVWludDhBcnJheShidWZfbGVuKTtcblxuICAvLyBjb252ZXJ0XG4gIGZvciAoaSA9IDAsIG1fcG9zID0gMDsgaSA8IGJ1Zl9sZW47IG1fcG9zKyspIHtcbiAgICBjID0gc3RyLmNoYXJDb2RlQXQobV9wb3MpO1xuICAgIGlmICgoYyAmIDB4ZmMwMCkgPT09IDB4ZDgwMCAmJiAobV9wb3MgKyAxIDwgc3RyX2xlbikpIHtcbiAgICAgIGMyID0gc3RyLmNoYXJDb2RlQXQobV9wb3MgKyAxKTtcbiAgICAgIGlmICgoYzIgJiAweGZjMDApID09PSAweGRjMDApIHtcbiAgICAgICAgYyA9IDB4MTAwMDAgKyAoKGMgLSAweGQ4MDApIDw8IDEwKSArIChjMiAtIDB4ZGMwMCk7XG4gICAgICAgIG1fcG9zKys7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChjIDwgMHg4MCkge1xuICAgICAgLyogb25lIGJ5dGUgKi9cbiAgICAgIGJ1ZltpKytdID0gYztcbiAgICB9IGVsc2UgaWYgKGMgPCAweDgwMCkge1xuICAgICAgLyogdHdvIGJ5dGVzICovXG4gICAgICBidWZbaSsrXSA9IDB4QzAgfCAoYyA+Pj4gNik7XG4gICAgICBidWZbaSsrXSA9IDB4ODAgfCAoYyAmIDB4M2YpO1xuICAgIH0gZWxzZSBpZiAoYyA8IDB4MTAwMDApIHtcbiAgICAgIC8qIHRocmVlIGJ5dGVzICovXG4gICAgICBidWZbaSsrXSA9IDB4RTAgfCAoYyA+Pj4gMTIpO1xuICAgICAgYnVmW2krK10gPSAweDgwIHwgKGMgPj4+IDYgJiAweDNmKTtcbiAgICAgIGJ1ZltpKytdID0gMHg4MCB8IChjICYgMHgzZik7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8qIGZvdXIgYnl0ZXMgKi9cbiAgICAgIGJ1ZltpKytdID0gMHhmMCB8IChjID4+PiAxOCk7XG4gICAgICBidWZbaSsrXSA9IDB4ODAgfCAoYyA+Pj4gMTIgJiAweDNmKTtcbiAgICAgIGJ1ZltpKytdID0gMHg4MCB8IChjID4+PiA2ICYgMHgzZik7XG4gICAgICBidWZbaSsrXSA9IDB4ODAgfCAoYyAmIDB4M2YpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBidWY7XG59O1xuXG4vLyBIZWxwZXJcbmNvbnN0IGJ1ZjJiaW5zdHJpbmcgPSAoYnVmLCBsZW4pID0+IHtcbiAgLy8gT24gQ2hyb21lLCB0aGUgYXJndW1lbnRzIGluIGEgZnVuY3Rpb24gY2FsbCB0aGF0IGFyZSBhbGxvd2VkIGlzIGA2NTUzNGAuXG4gIC8vIElmIHRoZSBsZW5ndGggb2YgdGhlIGJ1ZmZlciBpcyBzbWFsbGVyIHRoYW4gdGhhdCwgd2UgY2FuIHVzZSB0aGlzIG9wdGltaXphdGlvbixcbiAgLy8gb3RoZXJ3aXNlIHdlIHdpbGwgdGFrZSBhIHNsb3dlciBwYXRoLlxuICBpZiAobGVuIDwgNjU1MzQpIHtcbiAgICBpZiAoYnVmLnN1YmFycmF5ICYmIFNUUl9BUFBMWV9VSUFfT0spIHtcbiAgICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIGJ1Zi5sZW5ndGggPT09IGxlbiA/IGJ1ZiA6IGJ1Zi5zdWJhcnJheSgwLCBsZW4pKTtcbiAgICB9XG4gIH1cblxuICBsZXQgcmVzdWx0ID0gJyc7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0pO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG5cbi8vIGNvbnZlcnQgYXJyYXkgdG8gc3RyaW5nXG52YXIgYnVmMnN0cmluZyA9IChidWYsIG1heCkgPT4ge1xuICBjb25zdCBsZW4gPSBtYXggfHwgYnVmLmxlbmd0aDtcblxuICBpZiAodHlwZW9mIFRleHREZWNvZGVyID09PSAnZnVuY3Rpb24nICYmIFRleHREZWNvZGVyLnByb3RvdHlwZS5kZWNvZGUpIHtcbiAgICByZXR1cm4gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGJ1Zi5zdWJhcnJheSgwLCBtYXgpKTtcbiAgfVxuXG4gIGxldCBpLCBvdXQ7XG5cbiAgLy8gUmVzZXJ2ZSBtYXggcG9zc2libGUgbGVuZ3RoICgyIHdvcmRzIHBlciBjaGFyKVxuICAvLyBOQjogYnkgdW5rbm93biByZWFzb25zLCBBcnJheSBpcyBzaWduaWZpY2FudGx5IGZhc3RlciBmb3JcbiAgLy8gICAgIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkgdGhhbiBVaW50MTZBcnJheS5cbiAgY29uc3QgdXRmMTZidWYgPSBuZXcgQXJyYXkobGVuICogMik7XG5cbiAgZm9yIChvdXQgPSAwLCBpID0gMDsgaSA8IGxlbjspIHtcbiAgICBsZXQgYyA9IGJ1ZltpKytdO1xuICAgIC8vIHF1aWNrIHByb2Nlc3MgYXNjaWlcbiAgICBpZiAoYyA8IDB4ODApIHsgdXRmMTZidWZbb3V0KytdID0gYzsgY29udGludWU7IH1cblxuICAgIGxldCBjX2xlbiA9IF91dGY4bGVuW2NdO1xuICAgIC8vIHNraXAgNSAmIDYgYnl0ZSBjb2Rlc1xuICAgIGlmIChjX2xlbiA+IDQpIHsgdXRmMTZidWZbb3V0KytdID0gMHhmZmZkOyBpICs9IGNfbGVuIC0gMTsgY29udGludWU7IH1cblxuICAgIC8vIGFwcGx5IG1hc2sgb24gZmlyc3QgYnl0ZVxuICAgIGMgJj0gY19sZW4gPT09IDIgPyAweDFmIDogY19sZW4gPT09IDMgPyAweDBmIDogMHgwNztcbiAgICAvLyBqb2luIHRoZSByZXN0XG4gICAgd2hpbGUgKGNfbGVuID4gMSAmJiBpIDwgbGVuKSB7XG4gICAgICBjID0gKGMgPDwgNikgfCAoYnVmW2krK10gJiAweDNmKTtcbiAgICAgIGNfbGVuLS07XG4gICAgfVxuXG4gICAgLy8gdGVybWluYXRlZCBieSBlbmQgb2Ygc3RyaW5nP1xuICAgIGlmIChjX2xlbiA+IDEpIHsgdXRmMTZidWZbb3V0KytdID0gMHhmZmZkOyBjb250aW51ZTsgfVxuXG4gICAgaWYgKGMgPCAweDEwMDAwKSB7XG4gICAgICB1dGYxNmJ1ZltvdXQrK10gPSBjO1xuICAgIH0gZWxzZSB7XG4gICAgICBjIC09IDB4MTAwMDA7XG4gICAgICB1dGYxNmJ1ZltvdXQrK10gPSAweGQ4MDAgfCAoKGMgPj4gMTApICYgMHgzZmYpO1xuICAgICAgdXRmMTZidWZbb3V0KytdID0gMHhkYzAwIHwgKGMgJiAweDNmZik7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1ZjJiaW5zdHJpbmcodXRmMTZidWYsIG91dCk7XG59O1xuXG5cbi8vIENhbGN1bGF0ZSBtYXggcG9zc2libGUgcG9zaXRpb24gaW4gdXRmOCBidWZmZXIsXG4vLyB0aGF0IHdpbGwgbm90IGJyZWFrIHNlcXVlbmNlLiBJZiB0aGF0J3Mgbm90IHBvc3NpYmxlXG4vLyAtICh2ZXJ5IHNtYWxsIGxpbWl0cykgcmV0dXJuIG1heCBzaXplIGFzIGlzLlxuLy9cbi8vIGJ1ZltdIC0gdXRmOCBieXRlcyBhcnJheVxuLy8gbWF4ICAgLSBsZW5ndGggbGltaXQgKG1hbmRhdG9yeSk7XG52YXIgdXRmOGJvcmRlciA9IChidWYsIG1heCkgPT4ge1xuXG4gIG1heCA9IG1heCB8fCBidWYubGVuZ3RoO1xuICBpZiAobWF4ID4gYnVmLmxlbmd0aCkgeyBtYXggPSBidWYubGVuZ3RoOyB9XG5cbiAgLy8gZ28gYmFjayBmcm9tIGxhc3QgcG9zaXRpb24sIHVudGlsIHN0YXJ0IG9mIHNlcXVlbmNlIGZvdW5kXG4gIGxldCBwb3MgPSBtYXggLSAxO1xuICB3aGlsZSAocG9zID49IDAgJiYgKGJ1Zltwb3NdICYgMHhDMCkgPT09IDB4ODApIHsgcG9zLS07IH1cblxuICAvLyBWZXJ5IHNtYWxsIGFuZCBicm9rZW4gc2VxdWVuY2UsXG4gIC8vIHJldHVybiBtYXgsIGJlY2F1c2Ugd2Ugc2hvdWxkIHJldHVybiBzb21ldGhpbmcgYW55d2F5LlxuICBpZiAocG9zIDwgMCkgeyByZXR1cm4gbWF4OyB9XG5cbiAgLy8gSWYgd2UgY2FtZSB0byBzdGFydCBvZiBidWZmZXIgLSB0aGF0IG1lYW5zIGJ1ZmZlciBpcyB0b28gc21hbGwsXG4gIC8vIHJldHVybiBtYXggdG9vLlxuICBpZiAocG9zID09PSAwKSB7IHJldHVybiBtYXg7IH1cblxuICByZXR1cm4gKHBvcyArIF91dGY4bGVuW2J1Zltwb3NdXSA+IG1heCkgPyBwb3MgOiBtYXg7XG59O1xuXG52YXIgc3RyaW5ncyA9IHtcblx0c3RyaW5nMmJ1Zjogc3RyaW5nMmJ1Zixcblx0YnVmMnN0cmluZzogYnVmMnN0cmluZyxcblx0dXRmOGJvcmRlcjogdXRmOGJvcmRlclxufTtcblxuLy8gKEMpIDE5OTUtMjAxMyBKZWFuLWxvdXAgR2FpbGx5IGFuZCBNYXJrIEFkbGVyXG4vLyAoQykgMjAxNC0yMDE3IFZpdGFseSBQdXpyaW4gYW5kIEFuZHJleSBUdXBpdHNpblxuLy9cbi8vIFRoaXMgc29mdHdhcmUgaXMgcHJvdmlkZWQgJ2FzLWlzJywgd2l0aG91dCBhbnkgZXhwcmVzcyBvciBpbXBsaWVkXG4vLyB3YXJyYW50eS4gSW4gbm8gZXZlbnQgd2lsbCB0aGUgYXV0aG9ycyBiZSBoZWxkIGxpYWJsZSBmb3IgYW55IGRhbWFnZXNcbi8vIGFyaXNpbmcgZnJvbSB0aGUgdXNlIG9mIHRoaXMgc29mdHdhcmUuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBncmFudGVkIHRvIGFueW9uZSB0byB1c2UgdGhpcyBzb2Z0d2FyZSBmb3IgYW55IHB1cnBvc2UsXG4vLyBpbmNsdWRpbmcgY29tbWVyY2lhbCBhcHBsaWNhdGlvbnMsIGFuZCB0byBhbHRlciBpdCBhbmQgcmVkaXN0cmlidXRlIGl0XG4vLyBmcmVlbHksIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyByZXN0cmljdGlvbnM6XG4vL1xuLy8gMS4gVGhlIG9yaWdpbiBvZiB0aGlzIHNvZnR3YXJlIG11c3Qgbm90IGJlIG1pc3JlcHJlc2VudGVkOyB5b3UgbXVzdCBub3Rcbi8vICAgY2xhaW0gdGhhdCB5b3Ugd3JvdGUgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLiBJZiB5b3UgdXNlIHRoaXMgc29mdHdhcmVcbi8vICAgaW4gYSBwcm9kdWN0LCBhbiBhY2tub3dsZWRnbWVudCBpbiB0aGUgcHJvZHVjdCBkb2N1bWVudGF0aW9uIHdvdWxkIGJlXG4vLyAgIGFwcHJlY2lhdGVkIGJ1dCBpcyBub3QgcmVxdWlyZWQuXG4vLyAyLiBBbHRlcmVkIHNvdXJjZSB2ZXJzaW9ucyBtdXN0IGJlIHBsYWlubHkgbWFya2VkIGFzIHN1Y2gsIGFuZCBtdXN0IG5vdCBiZVxuLy8gICBtaXNyZXByZXNlbnRlZCBhcyBiZWluZyB0aGUgb3JpZ2luYWwgc29mdHdhcmUuXG4vLyAzLiBUaGlzIG5vdGljZSBtYXkgbm90IGJlIHJlbW92ZWQgb3IgYWx0ZXJlZCBmcm9tIGFueSBzb3VyY2UgZGlzdHJpYnV0aW9uLlxuXG5mdW5jdGlvbiBaU3RyZWFtKCkge1xuICAvKiBuZXh0IGlucHV0IGJ5dGUgKi9cbiAgdGhpcy5pbnB1dCA9IG51bGw7IC8vIEpTIHNwZWNpZmljLCBiZWNhdXNlIHdlIGhhdmUgbm8gcG9pbnRlcnNcbiAgdGhpcy5uZXh0X2luID0gMDtcbiAgLyogbnVtYmVyIG9mIGJ5dGVzIGF2YWlsYWJsZSBhdCBpbnB1dCAqL1xuICB0aGlzLmF2YWlsX2luID0gMDtcbiAgLyogdG90YWwgbnVtYmVyIG9mIGlucHV0IGJ5dGVzIHJlYWQgc28gZmFyICovXG4gIHRoaXMudG90YWxfaW4gPSAwO1xuICAvKiBuZXh0IG91dHB1dCBieXRlIHNob3VsZCBiZSBwdXQgdGhlcmUgKi9cbiAgdGhpcy5vdXRwdXQgPSBudWxsOyAvLyBKUyBzcGVjaWZpYywgYmVjYXVzZSB3ZSBoYXZlIG5vIHBvaW50ZXJzXG4gIHRoaXMubmV4dF9vdXQgPSAwO1xuICAvKiByZW1haW5pbmcgZnJlZSBzcGFjZSBhdCBvdXRwdXQgKi9cbiAgdGhpcy5hdmFpbF9vdXQgPSAwO1xuICAvKiB0b3RhbCBudW1iZXIgb2YgYnl0ZXMgb3V0cHV0IHNvIGZhciAqL1xuICB0aGlzLnRvdGFsX291dCA9IDA7XG4gIC8qIGxhc3QgZXJyb3IgbWVzc2FnZSwgTlVMTCBpZiBubyBlcnJvciAqL1xuICB0aGlzLm1zZyA9ICcnLypaX05VTEwqLztcbiAgLyogbm90IHZpc2libGUgYnkgYXBwbGljYXRpb25zICovXG4gIHRoaXMuc3RhdGUgPSBudWxsO1xuICAvKiBiZXN0IGd1ZXNzIGFib3V0IHRoZSBkYXRhIHR5cGU6IGJpbmFyeSBvciB0ZXh0ICovXG4gIHRoaXMuZGF0YV90eXBlID0gMi8qWl9VTktOT1dOKi87XG4gIC8qIGFkbGVyMzIgdmFsdWUgb2YgdGhlIHVuY29tcHJlc3NlZCBkYXRhICovXG4gIHRoaXMuYWRsZXIgPSAwO1xufVxuXG52YXIgenN0cmVhbSA9IFpTdHJlYW07XG5cbmNvbnN0IHRvU3RyaW5nJDEgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG4vKiBQdWJsaWMgY29uc3RhbnRzID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qL1xuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki9cblxuY29uc3Qge1xuICBaX05PX0ZMVVNIOiBaX05PX0ZMVVNIJDEsIFpfU1lOQ19GTFVTSCwgWl9GVUxMX0ZMVVNILCBaX0ZJTklTSDogWl9GSU5JU0gkMixcbiAgWl9PSzogWl9PSyQyLCBaX1NUUkVBTV9FTkQ6IFpfU1RSRUFNX0VORCQyLFxuICBaX0RFRkFVTFRfQ09NUFJFU1NJT04sXG4gIFpfREVGQVVMVF9TVFJBVEVHWSxcbiAgWl9ERUZMQVRFRDogWl9ERUZMQVRFRCQxXG59ID0gY29uc3RhbnRzJDI7XG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovXG5cblxuLyoqXG4gKiBjbGFzcyBEZWZsYXRlXG4gKlxuICogR2VuZXJpYyBKUy1zdHlsZSB3cmFwcGVyIGZvciB6bGliIGNhbGxzLiBJZiB5b3UgZG9uJ3QgbmVlZFxuICogc3RyZWFtaW5nIGJlaGF2aW91ciAtIHVzZSBtb3JlIHNpbXBsZSBmdW5jdGlvbnM6IFtbZGVmbGF0ZV1dLFxuICogW1tkZWZsYXRlUmF3XV0gYW5kIFtbZ3ppcF1dLlxuICoqL1xuXG4vKiBpbnRlcm5hbFxuICogRGVmbGF0ZS5jaHVua3MgLT4gQXJyYXlcbiAqXG4gKiBDaHVua3Mgb2Ygb3V0cHV0IGRhdGEsIGlmIFtbRGVmbGF0ZSNvbkRhdGFdXSBub3Qgb3ZlcnJpZGRlbi5cbiAqKi9cblxuLyoqXG4gKiBEZWZsYXRlLnJlc3VsdCAtPiBVaW50OEFycmF5XG4gKlxuICogQ29tcHJlc3NlZCByZXN1bHQsIGdlbmVyYXRlZCBieSBkZWZhdWx0IFtbRGVmbGF0ZSNvbkRhdGFdXVxuICogYW5kIFtbRGVmbGF0ZSNvbkVuZF1dIGhhbmRsZXJzLiBGaWxsZWQgYWZ0ZXIgeW91IHB1c2ggbGFzdCBjaHVua1xuICogKGNhbGwgW1tEZWZsYXRlI3B1c2hdXSB3aXRoIGBaX0ZJTklTSGAgLyBgdHJ1ZWAgcGFyYW0pLlxuICoqL1xuXG4vKipcbiAqIERlZmxhdGUuZXJyIC0+IE51bWJlclxuICpcbiAqIEVycm9yIGNvZGUgYWZ0ZXIgZGVmbGF0ZSBmaW5pc2hlZC4gMCAoWl9PSykgb24gc3VjY2Vzcy5cbiAqIFlvdSB3aWxsIG5vdCBuZWVkIGl0IGluIHJlYWwgbGlmZSwgYmVjYXVzZSBkZWZsYXRlIGVycm9yc1xuICogYXJlIHBvc3NpYmxlIG9ubHkgb24gd3Jvbmcgb3B0aW9ucyBvciBiYWQgYG9uRGF0YWAgLyBgb25FbmRgXG4gKiBjdXN0b20gaGFuZGxlcnMuXG4gKiovXG5cbi8qKlxuICogRGVmbGF0ZS5tc2cgLT4gU3RyaW5nXG4gKlxuICogRXJyb3IgbWVzc2FnZSwgaWYgW1tEZWZsYXRlLmVycl1dICE9IDBcbiAqKi9cblxuXG4vKipcbiAqIG5ldyBEZWZsYXRlKG9wdGlvbnMpXG4gKiAtIG9wdGlvbnMgKE9iamVjdCk6IHpsaWIgZGVmbGF0ZSBvcHRpb25zLlxuICpcbiAqIENyZWF0ZXMgbmV3IGRlZmxhdG9yIGluc3RhbmNlIHdpdGggc3BlY2lmaWVkIHBhcmFtcy4gVGhyb3dzIGV4Y2VwdGlvblxuICogb24gYmFkIHBhcmFtcy4gU3VwcG9ydGVkIG9wdGlvbnM6XG4gKlxuICogLSBgbGV2ZWxgXG4gKiAtIGB3aW5kb3dCaXRzYFxuICogLSBgbWVtTGV2ZWxgXG4gKiAtIGBzdHJhdGVneWBcbiAqIC0gYGRpY3Rpb25hcnlgXG4gKlxuICogW2h0dHA6Ly96bGliLm5ldC9tYW51YWwuaHRtbCNBZHZhbmNlZF0oaHR0cDovL3psaWIubmV0L21hbnVhbC5odG1sI0FkdmFuY2VkKVxuICogZm9yIG1vcmUgaW5mb3JtYXRpb24gb24gdGhlc2UuXG4gKlxuICogQWRkaXRpb25hbCBvcHRpb25zLCBmb3IgaW50ZXJuYWwgbmVlZHM6XG4gKlxuICogLSBgY2h1bmtTaXplYCAtIHNpemUgb2YgZ2VuZXJhdGVkIGRhdGEgY2h1bmtzICgxNksgYnkgZGVmYXVsdClcbiAqIC0gYHJhd2AgKEJvb2xlYW4pIC0gZG8gcmF3IGRlZmxhdGVcbiAqIC0gYGd6aXBgIChCb29sZWFuKSAtIGNyZWF0ZSBnemlwIHdyYXBwZXJcbiAqIC0gYGhlYWRlcmAgKE9iamVjdCkgLSBjdXN0b20gaGVhZGVyIGZvciBnemlwXG4gKiAgIC0gYHRleHRgIChCb29sZWFuKSAtIHRydWUgaWYgY29tcHJlc3NlZCBkYXRhIGJlbGlldmVkIHRvIGJlIHRleHRcbiAqICAgLSBgdGltZWAgKE51bWJlcikgLSBtb2RpZmljYXRpb24gdGltZSwgdW5peCB0aW1lc3RhbXBcbiAqICAgLSBgb3NgIChOdW1iZXIpIC0gb3BlcmF0aW9uIHN5c3RlbSBjb2RlXG4gKiAgIC0gYGV4dHJhYCAoQXJyYXkpIC0gYXJyYXkgb2YgYnl0ZXMgd2l0aCBleHRyYSBkYXRhIChtYXggNjU1MzYpXG4gKiAgIC0gYG5hbWVgIChTdHJpbmcpIC0gZmlsZSBuYW1lIChiaW5hcnkgc3RyaW5nKVxuICogICAtIGBjb21tZW50YCAoU3RyaW5nKSAtIGNvbW1lbnQgKGJpbmFyeSBzdHJpbmcpXG4gKiAgIC0gYGhjcmNgIChCb29sZWFuKSAtIHRydWUgaWYgaGVhZGVyIGNyYyBzaG91bGQgYmUgYWRkZWRcbiAqXG4gKiAjIyMjIyBFeGFtcGxlOlxuICpcbiAqIGBgYGphdmFzY3JpcHRcbiAqIGNvbnN0IHBha28gPSByZXF1aXJlKCdwYWtvJylcbiAqICAgLCBjaHVuazEgPSBuZXcgVWludDhBcnJheShbMSwyLDMsNCw1LDYsNyw4LDldKVxuICogICAsIGNodW5rMiA9IG5ldyBVaW50OEFycmF5KFsxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwxOV0pO1xuICpcbiAqIGNvbnN0IGRlZmxhdGUgPSBuZXcgcGFrby5EZWZsYXRlKHsgbGV2ZWw6IDN9KTtcbiAqXG4gKiBkZWZsYXRlLnB1c2goY2h1bmsxLCBmYWxzZSk7XG4gKiBkZWZsYXRlLnB1c2goY2h1bmsyLCB0cnVlKTsgIC8vIHRydWUgLT4gbGFzdCBjaHVua1xuICpcbiAqIGlmIChkZWZsYXRlLmVycikgeyB0aHJvdyBuZXcgRXJyb3IoZGVmbGF0ZS5lcnIpOyB9XG4gKlxuICogY29uc29sZS5sb2coZGVmbGF0ZS5yZXN1bHQpO1xuICogYGBgXG4gKiovXG5mdW5jdGlvbiBEZWZsYXRlJDEob3B0aW9ucykge1xuICB0aGlzLm9wdGlvbnMgPSBjb21tb24uYXNzaWduKHtcbiAgICBsZXZlbDogWl9ERUZBVUxUX0NPTVBSRVNTSU9OLFxuICAgIG1ldGhvZDogWl9ERUZMQVRFRCQxLFxuICAgIGNodW5rU2l6ZTogMTYzODQsXG4gICAgd2luZG93Qml0czogMTUsXG4gICAgbWVtTGV2ZWw6IDgsXG4gICAgc3RyYXRlZ3k6IFpfREVGQVVMVF9TVFJBVEVHWVxuICB9LCBvcHRpb25zIHx8IHt9KTtcblxuICBsZXQgb3B0ID0gdGhpcy5vcHRpb25zO1xuXG4gIGlmIChvcHQucmF3ICYmIChvcHQud2luZG93Qml0cyA+IDApKSB7XG4gICAgb3B0LndpbmRvd0JpdHMgPSAtb3B0LndpbmRvd0JpdHM7XG4gIH1cblxuICBlbHNlIGlmIChvcHQuZ3ppcCAmJiAob3B0LndpbmRvd0JpdHMgPiAwKSAmJiAob3B0LndpbmRvd0JpdHMgPCAxNikpIHtcbiAgICBvcHQud2luZG93Qml0cyArPSAxNjtcbiAgfVxuXG4gIHRoaXMuZXJyICAgID0gMDsgICAgICAvLyBlcnJvciBjb2RlLCBpZiBoYXBwZW5zICgwID0gWl9PSylcbiAgdGhpcy5tc2cgICAgPSAnJzsgICAgIC8vIGVycm9yIG1lc3NhZ2VcbiAgdGhpcy5lbmRlZCAgPSBmYWxzZTsgIC8vIHVzZWQgdG8gYXZvaWQgbXVsdGlwbGUgb25FbmQoKSBjYWxsc1xuICB0aGlzLmNodW5rcyA9IFtdOyAgICAgLy8gY2h1bmtzIG9mIGNvbXByZXNzZWQgZGF0YVxuXG4gIHRoaXMuc3RybSA9IG5ldyB6c3RyZWFtKCk7XG4gIHRoaXMuc3RybS5hdmFpbF9vdXQgPSAwO1xuXG4gIGxldCBzdGF0dXMgPSBkZWZsYXRlXzEkMi5kZWZsYXRlSW5pdDIoXG4gICAgdGhpcy5zdHJtLFxuICAgIG9wdC5sZXZlbCxcbiAgICBvcHQubWV0aG9kLFxuICAgIG9wdC53aW5kb3dCaXRzLFxuICAgIG9wdC5tZW1MZXZlbCxcbiAgICBvcHQuc3RyYXRlZ3lcbiAgKTtcblxuICBpZiAoc3RhdHVzICE9PSBaX09LJDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZXNbc3RhdHVzXSk7XG4gIH1cblxuICBpZiAob3B0LmhlYWRlcikge1xuICAgIGRlZmxhdGVfMSQyLmRlZmxhdGVTZXRIZWFkZXIodGhpcy5zdHJtLCBvcHQuaGVhZGVyKTtcbiAgfVxuXG4gIGlmIChvcHQuZGljdGlvbmFyeSkge1xuICAgIGxldCBkaWN0O1xuICAgIC8vIENvbnZlcnQgZGF0YSBpZiBuZWVkZWRcbiAgICBpZiAodHlwZW9mIG9wdC5kaWN0aW9uYXJ5ID09PSAnc3RyaW5nJykge1xuICAgICAgLy8gSWYgd2UgbmVlZCB0byBjb21wcmVzcyB0ZXh0LCBjaGFuZ2UgZW5jb2RpbmcgdG8gdXRmOC5cbiAgICAgIGRpY3QgPSBzdHJpbmdzLnN0cmluZzJidWYob3B0LmRpY3Rpb25hcnkpO1xuICAgIH0gZWxzZSBpZiAodG9TdHJpbmckMS5jYWxsKG9wdC5kaWN0aW9uYXJ5KSA9PT0gJ1tvYmplY3QgQXJyYXlCdWZmZXJdJykge1xuICAgICAgZGljdCA9IG5ldyBVaW50OEFycmF5KG9wdC5kaWN0aW9uYXJ5KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGljdCA9IG9wdC5kaWN0aW9uYXJ5O1xuICAgIH1cblxuICAgIHN0YXR1cyA9IGRlZmxhdGVfMSQyLmRlZmxhdGVTZXREaWN0aW9uYXJ5KHRoaXMuc3RybSwgZGljdCk7XG5cbiAgICBpZiAoc3RhdHVzICE9PSBaX09LJDIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihtZXNzYWdlc1tzdGF0dXNdKTtcbiAgICB9XG5cbiAgICB0aGlzLl9kaWN0X3NldCA9IHRydWU7XG4gIH1cbn1cblxuLyoqXG4gKiBEZWZsYXRlI3B1c2goZGF0YVssIGZsdXNoX21vZGVdKSAtPiBCb29sZWFuXG4gKiAtIGRhdGEgKFVpbnQ4QXJyYXl8QXJyYXlCdWZmZXJ8U3RyaW5nKTogaW5wdXQgZGF0YS4gU3RyaW5ncyB3aWxsIGJlXG4gKiAgIGNvbnZlcnRlZCB0byB1dGY4IGJ5dGUgc2VxdWVuY2UuXG4gKiAtIGZsdXNoX21vZGUgKE51bWJlcnxCb29sZWFuKTogMC4uNiBmb3IgY29ycmVzcG9uZGluZyBaX05PX0ZMVVNILi5aX1RSRUUgbW9kZXMuXG4gKiAgIFNlZSBjb25zdGFudHMuIFNraXBwZWQgb3IgYGZhbHNlYCBtZWFucyBaX05PX0ZMVVNILCBgdHJ1ZWAgbWVhbnMgWl9GSU5JU0guXG4gKlxuICogU2VuZHMgaW5wdXQgZGF0YSB0byBkZWZsYXRlIHBpcGUsIGdlbmVyYXRpbmcgW1tEZWZsYXRlI29uRGF0YV1dIGNhbGxzIHdpdGhcbiAqIG5ldyBjb21wcmVzc2VkIGNodW5rcy4gUmV0dXJucyBgdHJ1ZWAgb24gc3VjY2Vzcy4gVGhlIGxhc3QgZGF0YSBibG9jayBtdXN0XG4gKiBoYXZlIGBmbHVzaF9tb2RlYCBaX0ZJTklTSCAob3IgYHRydWVgKS4gVGhhdCB3aWxsIGZsdXNoIGludGVybmFsIHBlbmRpbmdcbiAqIGJ1ZmZlcnMgYW5kIGNhbGwgW1tEZWZsYXRlI29uRW5kXV0uXG4gKlxuICogT24gZmFpbCBjYWxsIFtbRGVmbGF0ZSNvbkVuZF1dIHdpdGggZXJyb3IgY29kZSBhbmQgcmV0dXJuIGZhbHNlLlxuICpcbiAqICMjIyMjIEV4YW1wbGVcbiAqXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBwdXNoKGNodW5rLCBmYWxzZSk7IC8vIHB1c2ggb25lIG9mIGRhdGEgY2h1bmtzXG4gKiAuLi5cbiAqIHB1c2goY2h1bmssIHRydWUpOyAgLy8gcHVzaCBsYXN0IGNodW5rXG4gKiBgYGBcbiAqKi9cbkRlZmxhdGUkMS5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uIChkYXRhLCBmbHVzaF9tb2RlKSB7XG4gIGNvbnN0IHN0cm0gPSB0aGlzLnN0cm07XG4gIGNvbnN0IGNodW5rU2l6ZSA9IHRoaXMub3B0aW9ucy5jaHVua1NpemU7XG4gIGxldCBzdGF0dXMsIF9mbHVzaF9tb2RlO1xuXG4gIGlmICh0aGlzLmVuZGVkKSB7IHJldHVybiBmYWxzZTsgfVxuXG4gIGlmIChmbHVzaF9tb2RlID09PSB+fmZsdXNoX21vZGUpIF9mbHVzaF9tb2RlID0gZmx1c2hfbW9kZTtcbiAgZWxzZSBfZmx1c2hfbW9kZSA9IGZsdXNoX21vZGUgPT09IHRydWUgPyBaX0ZJTklTSCQyIDogWl9OT19GTFVTSCQxO1xuXG4gIC8vIENvbnZlcnQgZGF0YSBpZiBuZWVkZWRcbiAgaWYgKHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJykge1xuICAgIC8vIElmIHdlIG5lZWQgdG8gY29tcHJlc3MgdGV4dCwgY2hhbmdlIGVuY29kaW5nIHRvIHV0ZjguXG4gICAgc3RybS5pbnB1dCA9IHN0cmluZ3Muc3RyaW5nMmJ1ZihkYXRhKTtcbiAgfSBlbHNlIGlmICh0b1N0cmluZyQxLmNhbGwoZGF0YSkgPT09ICdbb2JqZWN0IEFycmF5QnVmZmVyXScpIHtcbiAgICBzdHJtLmlucHV0ID0gbmV3IFVpbnQ4QXJyYXkoZGF0YSk7XG4gIH0gZWxzZSB7XG4gICAgc3RybS5pbnB1dCA9IGRhdGE7XG4gIH1cblxuICBzdHJtLm5leHRfaW4gPSAwO1xuICBzdHJtLmF2YWlsX2luID0gc3RybS5pbnB1dC5sZW5ndGg7XG5cbiAgZm9yICg7Oykge1xuICAgIGlmIChzdHJtLmF2YWlsX291dCA9PT0gMCkge1xuICAgICAgc3RybS5vdXRwdXQgPSBuZXcgVWludDhBcnJheShjaHVua1NpemUpO1xuICAgICAgc3RybS5uZXh0X291dCA9IDA7XG4gICAgICBzdHJtLmF2YWlsX291dCA9IGNodW5rU2l6ZTtcbiAgICB9XG5cbiAgICAvLyBNYWtlIHN1cmUgYXZhaWxfb3V0ID4gNiB0byBhdm9pZCByZXBlYXRpbmcgbWFya2Vyc1xuICAgIGlmICgoX2ZsdXNoX21vZGUgPT09IFpfU1lOQ19GTFVTSCB8fCBfZmx1c2hfbW9kZSA9PT0gWl9GVUxMX0ZMVVNIKSAmJiBzdHJtLmF2YWlsX291dCA8PSA2KSB7XG4gICAgICB0aGlzLm9uRGF0YShzdHJtLm91dHB1dC5zdWJhcnJheSgwLCBzdHJtLm5leHRfb3V0KSk7XG4gICAgICBzdHJtLmF2YWlsX291dCA9IDA7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBzdGF0dXMgPSBkZWZsYXRlXzEkMi5kZWZsYXRlKHN0cm0sIF9mbHVzaF9tb2RlKTtcblxuICAgIC8vIEVuZGVkID0+IGZsdXNoIGFuZCBmaW5pc2hcbiAgICBpZiAoc3RhdHVzID09PSBaX1NUUkVBTV9FTkQkMikge1xuICAgICAgaWYgKHN0cm0ubmV4dF9vdXQgPiAwKSB7XG4gICAgICAgIHRoaXMub25EYXRhKHN0cm0ub3V0cHV0LnN1YmFycmF5KDAsIHN0cm0ubmV4dF9vdXQpKTtcbiAgICAgIH1cbiAgICAgIHN0YXR1cyA9IGRlZmxhdGVfMSQyLmRlZmxhdGVFbmQodGhpcy5zdHJtKTtcbiAgICAgIHRoaXMub25FbmQoc3RhdHVzKTtcbiAgICAgIHRoaXMuZW5kZWQgPSB0cnVlO1xuICAgICAgcmV0dXJuIHN0YXR1cyA9PT0gWl9PSyQyO1xuICAgIH1cblxuICAgIC8vIEZsdXNoIGlmIG91dCBidWZmZXIgZnVsbFxuICAgIGlmIChzdHJtLmF2YWlsX291dCA9PT0gMCkge1xuICAgICAgdGhpcy5vbkRhdGEoc3RybS5vdXRwdXQpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gRmx1c2ggaWYgcmVxdWVzdGVkIGFuZCBoYXMgZGF0YVxuICAgIGlmIChfZmx1c2hfbW9kZSA+IDAgJiYgc3RybS5uZXh0X291dCA+IDApIHtcbiAgICAgIHRoaXMub25EYXRhKHN0cm0ub3V0cHV0LnN1YmFycmF5KDAsIHN0cm0ubmV4dF9vdXQpKTtcbiAgICAgIHN0cm0uYXZhaWxfb3V0ID0gMDtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmIChzdHJtLmF2YWlsX2luID09PSAwKSBicmVhaztcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuXG4vKipcbiAqIERlZmxhdGUjb25EYXRhKGNodW5rKSAtPiBWb2lkXG4gKiAtIGNodW5rIChVaW50OEFycmF5KTogb3V0cHV0IGRhdGEuXG4gKlxuICogQnkgZGVmYXVsdCwgc3RvcmVzIGRhdGEgYmxvY2tzIGluIGBjaHVua3NbXWAgcHJvcGVydHkgYW5kIGdsdWVcbiAqIHRob3NlIGluIGBvbkVuZGAuIE92ZXJyaWRlIHRoaXMgaGFuZGxlciwgaWYgeW91IG5lZWQgYW5vdGhlciBiZWhhdmlvdXIuXG4gKiovXG5EZWZsYXRlJDEucHJvdG90eXBlLm9uRGF0YSA9IGZ1bmN0aW9uIChjaHVuaykge1xuICB0aGlzLmNodW5rcy5wdXNoKGNodW5rKTtcbn07XG5cblxuLyoqXG4gKiBEZWZsYXRlI29uRW5kKHN0YXR1cykgLT4gVm9pZFxuICogLSBzdGF0dXMgKE51bWJlcik6IGRlZmxhdGUgc3RhdHVzLiAwIChaX09LKSBvbiBzdWNjZXNzLFxuICogICBvdGhlciBpZiBub3QuXG4gKlxuICogQ2FsbGVkIG9uY2UgYWZ0ZXIgeW91IHRlbGwgZGVmbGF0ZSB0aGF0IHRoZSBpbnB1dCBzdHJlYW0gaXNcbiAqIGNvbXBsZXRlIChaX0ZJTklTSCkuIEJ5IGRlZmF1bHQgLSBqb2luIGNvbGxlY3RlZCBjaHVua3MsXG4gKiBmcmVlIG1lbW9yeSBhbmQgZmlsbCBgcmVzdWx0c2AgLyBgZXJyYCBwcm9wZXJ0aWVzLlxuICoqL1xuRGVmbGF0ZSQxLnByb3RvdHlwZS5vbkVuZCA9IGZ1bmN0aW9uIChzdGF0dXMpIHtcbiAgLy8gT24gc3VjY2VzcyAtIGpvaW5cbiAgaWYgKHN0YXR1cyA9PT0gWl9PSyQyKSB7XG4gICAgdGhpcy5yZXN1bHQgPSBjb21tb24uZmxhdHRlbkNodW5rcyh0aGlzLmNodW5rcyk7XG4gIH1cbiAgdGhpcy5jaHVua3MgPSBbXTtcbiAgdGhpcy5lcnIgPSBzdGF0dXM7XG4gIHRoaXMubXNnID0gdGhpcy5zdHJtLm1zZztcbn07XG5cblxuLyoqXG4gKiBkZWZsYXRlKGRhdGFbLCBvcHRpb25zXSkgLT4gVWludDhBcnJheVxuICogLSBkYXRhIChVaW50OEFycmF5fEFycmF5QnVmZmVyfFN0cmluZyk6IGlucHV0IGRhdGEgdG8gY29tcHJlc3MuXG4gKiAtIG9wdGlvbnMgKE9iamVjdCk6IHpsaWIgZGVmbGF0ZSBvcHRpb25zLlxuICpcbiAqIENvbXByZXNzIGBkYXRhYCB3aXRoIGRlZmxhdGUgYWxnb3JpdGhtIGFuZCBgb3B0aW9uc2AuXG4gKlxuICogU3VwcG9ydGVkIG9wdGlvbnMgYXJlOlxuICpcbiAqIC0gbGV2ZWxcbiAqIC0gd2luZG93Qml0c1xuICogLSBtZW1MZXZlbFxuICogLSBzdHJhdGVneVxuICogLSBkaWN0aW9uYXJ5XG4gKlxuICogW2h0dHA6Ly96bGliLm5ldC9tYW51YWwuaHRtbCNBZHZhbmNlZF0oaHR0cDovL3psaWIubmV0L21hbnVhbC5odG1sI0FkdmFuY2VkKVxuICogZm9yIG1vcmUgaW5mb3JtYXRpb24gb24gdGhlc2UuXG4gKlxuICogU3VnYXIgKG9wdGlvbnMpOlxuICpcbiAqIC0gYHJhd2AgKEJvb2xlYW4pIC0gc2F5IHRoYXQgd2Ugd29yayB3aXRoIHJhdyBzdHJlYW0sIGlmIHlvdSBkb24ndCB3aXNoIHRvIHNwZWNpZnlcbiAqICAgbmVnYXRpdmUgd2luZG93Qml0cyBpbXBsaWNpdGx5LlxuICpcbiAqICMjIyMjIEV4YW1wbGU6XG4gKlxuICogYGBgamF2YXNjcmlwdFxuICogY29uc3QgcGFrbyA9IHJlcXVpcmUoJ3Bha28nKVxuICogY29uc3QgZGF0YSA9IG5ldyBVaW50OEFycmF5KFsxLDIsMyw0LDUsNiw3LDgsOV0pO1xuICpcbiAqIGNvbnNvbGUubG9nKHBha28uZGVmbGF0ZShkYXRhKSk7XG4gKiBgYGBcbiAqKi9cbmZ1bmN0aW9uIGRlZmxhdGUkMShpbnB1dCwgb3B0aW9ucykge1xuICBjb25zdCBkZWZsYXRvciA9IG5ldyBEZWZsYXRlJDEob3B0aW9ucyk7XG5cbiAgZGVmbGF0b3IucHVzaChpbnB1dCwgdHJ1ZSk7XG5cbiAgLy8gVGhhdCB3aWxsIG5ldmVyIGhhcHBlbnMsIGlmIHlvdSBkb24ndCBjaGVhdCB3aXRoIG9wdGlvbnMgOilcbiAgaWYgKGRlZmxhdG9yLmVycikgeyB0aHJvdyBkZWZsYXRvci5tc2cgfHwgbWVzc2FnZXNbZGVmbGF0b3IuZXJyXTsgfVxuXG4gIHJldHVybiBkZWZsYXRvci5yZXN1bHQ7XG59XG5cblxuLyoqXG4gKiBkZWZsYXRlUmF3KGRhdGFbLCBvcHRpb25zXSkgLT4gVWludDhBcnJheVxuICogLSBkYXRhIChVaW50OEFycmF5fEFycmF5QnVmZmVyfFN0cmluZyk6IGlucHV0IGRhdGEgdG8gY29tcHJlc3MuXG4gKiAtIG9wdGlvbnMgKE9iamVjdCk6IHpsaWIgZGVmbGF0ZSBvcHRpb25zLlxuICpcbiAqIFRoZSBzYW1lIGFzIFtbZGVmbGF0ZV1dLCBidXQgY3JlYXRlcyByYXcgZGF0YSwgd2l0aG91dCB3cmFwcGVyXG4gKiAoaGVhZGVyIGFuZCBhZGxlcjMyIGNyYykuXG4gKiovXG5mdW5jdGlvbiBkZWZsYXRlUmF3JDEoaW5wdXQsIG9wdGlvbnMpIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIG9wdGlvbnMucmF3ID0gdHJ1ZTtcbiAgcmV0dXJuIGRlZmxhdGUkMShpbnB1dCwgb3B0aW9ucyk7XG59XG5cblxuLyoqXG4gKiBnemlwKGRhdGFbLCBvcHRpb25zXSkgLT4gVWludDhBcnJheVxuICogLSBkYXRhIChVaW50OEFycmF5fEFycmF5QnVmZmVyfFN0cmluZyk6IGlucHV0IGRhdGEgdG8gY29tcHJlc3MuXG4gKiAtIG9wdGlvbnMgKE9iamVjdCk6IHpsaWIgZGVmbGF0ZSBvcHRpb25zLlxuICpcbiAqIFRoZSBzYW1lIGFzIFtbZGVmbGF0ZV1dLCBidXQgY3JlYXRlIGd6aXAgd3JhcHBlciBpbnN0ZWFkIG9mXG4gKiBkZWZsYXRlIG9uZS5cbiAqKi9cbmZ1bmN0aW9uIGd6aXAkMShpbnB1dCwgb3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgb3B0aW9ucy5nemlwID0gdHJ1ZTtcbiAgcmV0dXJuIGRlZmxhdGUkMShpbnB1dCwgb3B0aW9ucyk7XG59XG5cblxudmFyIERlZmxhdGVfMSQxID0gRGVmbGF0ZSQxO1xudmFyIGRlZmxhdGVfMiA9IGRlZmxhdGUkMTtcbnZhciBkZWZsYXRlUmF3XzEkMSA9IGRlZmxhdGVSYXckMTtcbnZhciBnemlwXzEkMSA9IGd6aXAkMTtcbnZhciBjb25zdGFudHMkMSA9IGNvbnN0YW50cyQyO1xuXG52YXIgZGVmbGF0ZV8xJDEgPSB7XG5cdERlZmxhdGU6IERlZmxhdGVfMSQxLFxuXHRkZWZsYXRlOiBkZWZsYXRlXzIsXG5cdGRlZmxhdGVSYXc6IGRlZmxhdGVSYXdfMSQxLFxuXHRnemlwOiBnemlwXzEkMSxcblx0Y29uc3RhbnRzOiBjb25zdGFudHMkMVxufTtcblxuLy8gKEMpIDE5OTUtMjAxMyBKZWFuLWxvdXAgR2FpbGx5IGFuZCBNYXJrIEFkbGVyXG4vLyAoQykgMjAxNC0yMDE3IFZpdGFseSBQdXpyaW4gYW5kIEFuZHJleSBUdXBpdHNpblxuLy9cbi8vIFRoaXMgc29mdHdhcmUgaXMgcHJvdmlkZWQgJ2FzLWlzJywgd2l0aG91dCBhbnkgZXhwcmVzcyBvciBpbXBsaWVkXG4vLyB3YXJyYW50eS4gSW4gbm8gZXZlbnQgd2lsbCB0aGUgYXV0aG9ycyBiZSBoZWxkIGxpYWJsZSBmb3IgYW55IGRhbWFnZXNcbi8vIGFyaXNpbmcgZnJvbSB0aGUgdXNlIG9mIHRoaXMgc29mdHdhcmUuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBncmFudGVkIHRvIGFueW9uZSB0byB1c2UgdGhpcyBzb2Z0d2FyZSBmb3IgYW55IHB1cnBvc2UsXG4vLyBpbmNsdWRpbmcgY29tbWVyY2lhbCBhcHBsaWNhdGlvbnMsIGFuZCB0byBhbHRlciBpdCBhbmQgcmVkaXN0cmlidXRlIGl0XG4vLyBmcmVlbHksIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyByZXN0cmljdGlvbnM6XG4vL1xuLy8gMS4gVGhlIG9yaWdpbiBvZiB0aGlzIHNvZnR3YXJlIG11c3Qgbm90IGJlIG1pc3JlcHJlc2VudGVkOyB5b3UgbXVzdCBub3Rcbi8vICAgY2xhaW0gdGhhdCB5b3Ugd3JvdGUgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLiBJZiB5b3UgdXNlIHRoaXMgc29mdHdhcmVcbi8vICAgaW4gYSBwcm9kdWN0LCBhbiBhY2tub3dsZWRnbWVudCBpbiB0aGUgcHJvZHVjdCBkb2N1bWVudGF0aW9uIHdvdWxkIGJlXG4vLyAgIGFwcHJlY2lhdGVkIGJ1dCBpcyBub3QgcmVxdWlyZWQuXG4vLyAyLiBBbHRlcmVkIHNvdXJjZSB2ZXJzaW9ucyBtdXN0IGJlIHBsYWlubHkgbWFya2VkIGFzIHN1Y2gsIGFuZCBtdXN0IG5vdCBiZVxuLy8gICBtaXNyZXByZXNlbnRlZCBhcyBiZWluZyB0aGUgb3JpZ2luYWwgc29mdHdhcmUuXG4vLyAzLiBUaGlzIG5vdGljZSBtYXkgbm90IGJlIHJlbW92ZWQgb3IgYWx0ZXJlZCBmcm9tIGFueSBzb3VyY2UgZGlzdHJpYnV0aW9uLlxuXG4vLyBTZWUgc3RhdGUgZGVmcyBmcm9tIGluZmxhdGUuanNcbmNvbnN0IEJBRCQxID0gMTYyMDk7ICAgICAgIC8qIGdvdCBhIGRhdGEgZXJyb3IgLS0gcmVtYWluIGhlcmUgdW50aWwgcmVzZXQgKi9cbmNvbnN0IFRZUEUkMSA9IDE2MTkxOyAgICAgIC8qIGk6IHdhaXRpbmcgZm9yIHR5cGUgYml0cywgaW5jbHVkaW5nIGxhc3QtZmxhZyBiaXQgKi9cblxuLypcbiAgIERlY29kZSBsaXRlcmFsLCBsZW5ndGgsIGFuZCBkaXN0YW5jZSBjb2RlcyBhbmQgd3JpdGUgb3V0IHRoZSByZXN1bHRpbmdcbiAgIGxpdGVyYWwgYW5kIG1hdGNoIGJ5dGVzIHVudGlsIGVpdGhlciBub3QgZW5vdWdoIGlucHV0IG9yIG91dHB1dCBpc1xuICAgYXZhaWxhYmxlLCBhbiBlbmQtb2YtYmxvY2sgaXMgZW5jb3VudGVyZWQsIG9yIGEgZGF0YSBlcnJvciBpcyBlbmNvdW50ZXJlZC5cbiAgIFdoZW4gbGFyZ2UgZW5vdWdoIGlucHV0IGFuZCBvdXRwdXQgYnVmZmVycyBhcmUgc3VwcGxpZWQgdG8gaW5mbGF0ZSgpLCBmb3JcbiAgIGV4YW1wbGUsIGEgMTZLIGlucHV0IGJ1ZmZlciBhbmQgYSA2NEsgb3V0cHV0IGJ1ZmZlciwgbW9yZSB0aGFuIDk1JSBvZiB0aGVcbiAgIGluZmxhdGUgZXhlY3V0aW9uIHRpbWUgaXMgc3BlbnQgaW4gdGhpcyByb3V0aW5lLlxuXG4gICBFbnRyeSBhc3N1bXB0aW9uczpcblxuICAgICAgICBzdGF0ZS5tb2RlID09PSBMRU5cbiAgICAgICAgc3RybS5hdmFpbF9pbiA+PSA2XG4gICAgICAgIHN0cm0uYXZhaWxfb3V0ID49IDI1OFxuICAgICAgICBzdGFydCA+PSBzdHJtLmF2YWlsX291dFxuICAgICAgICBzdGF0ZS5iaXRzIDwgOFxuXG4gICBPbiByZXR1cm4sIHN0YXRlLm1vZGUgaXMgb25lIG9mOlxuXG4gICAgICAgIExFTiAtLSByYW4gb3V0IG9mIGVub3VnaCBvdXRwdXQgc3BhY2Ugb3IgZW5vdWdoIGF2YWlsYWJsZSBpbnB1dFxuICAgICAgICBUWVBFIC0tIHJlYWNoZWQgZW5kIG9mIGJsb2NrIGNvZGUsIGluZmxhdGUoKSB0byBpbnRlcnByZXQgbmV4dCBibG9ja1xuICAgICAgICBCQUQgLS0gZXJyb3IgaW4gYmxvY2sgZGF0YVxuXG4gICBOb3RlczpcblxuICAgIC0gVGhlIG1heGltdW0gaW5wdXQgYml0cyB1c2VkIGJ5IGEgbGVuZ3RoL2Rpc3RhbmNlIHBhaXIgaXMgMTUgYml0cyBmb3IgdGhlXG4gICAgICBsZW5ndGggY29kZSwgNSBiaXRzIGZvciB0aGUgbGVuZ3RoIGV4dHJhLCAxNSBiaXRzIGZvciB0aGUgZGlzdGFuY2UgY29kZSxcbiAgICAgIGFuZCAxMyBiaXRzIGZvciB0aGUgZGlzdGFuY2UgZXh0cmEuICBUaGlzIHRvdGFscyA0OCBiaXRzLCBvciBzaXggYnl0ZXMuXG4gICAgICBUaGVyZWZvcmUgaWYgc3RybS5hdmFpbF9pbiA+PSA2LCB0aGVuIHRoZXJlIGlzIGVub3VnaCBpbnB1dCB0byBhdm9pZFxuICAgICAgY2hlY2tpbmcgZm9yIGF2YWlsYWJsZSBpbnB1dCB3aGlsZSBkZWNvZGluZy5cblxuICAgIC0gVGhlIG1heGltdW0gYnl0ZXMgdGhhdCBhIHNpbmdsZSBsZW5ndGgvZGlzdGFuY2UgcGFpciBjYW4gb3V0cHV0IGlzIDI1OFxuICAgICAgYnl0ZXMsIHdoaWNoIGlzIHRoZSBtYXhpbXVtIGxlbmd0aCB0aGF0IGNhbiBiZSBjb2RlZC4gIGluZmxhdGVfZmFzdCgpXG4gICAgICByZXF1aXJlcyBzdHJtLmF2YWlsX291dCA+PSAyNTggZm9yIGVhY2ggbG9vcCB0byBhdm9pZCBjaGVja2luZyBmb3JcbiAgICAgIG91dHB1dCBzcGFjZS5cbiAqL1xudmFyIGluZmZhc3QgPSBmdW5jdGlvbiBpbmZsYXRlX2Zhc3Qoc3RybSwgc3RhcnQpIHtcbiAgbGV0IF9pbjsgICAgICAgICAgICAgICAgICAgIC8qIGxvY2FsIHN0cm0uaW5wdXQgKi9cbiAgbGV0IGxhc3Q7ICAgICAgICAgICAgICAgICAgIC8qIGhhdmUgZW5vdWdoIGlucHV0IHdoaWxlIGluIDwgbGFzdCAqL1xuICBsZXQgX291dDsgICAgICAgICAgICAgICAgICAgLyogbG9jYWwgc3RybS5vdXRwdXQgKi9cbiAgbGV0IGJlZzsgICAgICAgICAgICAgICAgICAgIC8qIGluZmxhdGUoKSdzIGluaXRpYWwgc3RybS5vdXRwdXQgKi9cbiAgbGV0IGVuZDsgICAgICAgICAgICAgICAgICAgIC8qIHdoaWxlIG91dCA8IGVuZCwgZW5vdWdoIHNwYWNlIGF2YWlsYWJsZSAqL1xuLy8jaWZkZWYgSU5GTEFURV9TVFJJQ1RcbiAgbGV0IGRtYXg7ICAgICAgICAgICAgICAgICAgIC8qIG1heGltdW0gZGlzdGFuY2UgZnJvbSB6bGliIGhlYWRlciAqL1xuLy8jZW5kaWZcbiAgbGV0IHdzaXplOyAgICAgICAgICAgICAgICAgIC8qIHdpbmRvdyBzaXplIG9yIHplcm8gaWYgbm90IHVzaW5nIHdpbmRvdyAqL1xuICBsZXQgd2hhdmU7ICAgICAgICAgICAgICAgICAgLyogdmFsaWQgYnl0ZXMgaW4gdGhlIHdpbmRvdyAqL1xuICBsZXQgd25leHQ7ICAgICAgICAgICAgICAgICAgLyogd2luZG93IHdyaXRlIGluZGV4ICovXG4gIC8vIFVzZSBgc193aW5kb3dgIGluc3RlYWQgYHdpbmRvd2AsIGF2b2lkIGNvbmZsaWN0IHdpdGggaW5zdHJ1bWVudGF0aW9uIHRvb2xzXG4gIGxldCBzX3dpbmRvdzsgICAgICAgICAgICAgICAvKiBhbGxvY2F0ZWQgc2xpZGluZyB3aW5kb3csIGlmIHdzaXplICE9IDAgKi9cbiAgbGV0IGhvbGQ7ICAgICAgICAgICAgICAgICAgIC8qIGxvY2FsIHN0cm0uaG9sZCAqL1xuICBsZXQgYml0czsgICAgICAgICAgICAgICAgICAgLyogbG9jYWwgc3RybS5iaXRzICovXG4gIGxldCBsY29kZTsgICAgICAgICAgICAgICAgICAvKiBsb2NhbCBzdHJtLmxlbmNvZGUgKi9cbiAgbGV0IGRjb2RlOyAgICAgICAgICAgICAgICAgIC8qIGxvY2FsIHN0cm0uZGlzdGNvZGUgKi9cbiAgbGV0IGxtYXNrOyAgICAgICAgICAgICAgICAgIC8qIG1hc2sgZm9yIGZpcnN0IGxldmVsIG9mIGxlbmd0aCBjb2RlcyAqL1xuICBsZXQgZG1hc2s7ICAgICAgICAgICAgICAgICAgLyogbWFzayBmb3IgZmlyc3QgbGV2ZWwgb2YgZGlzdGFuY2UgY29kZXMgKi9cbiAgbGV0IGhlcmU7ICAgICAgICAgICAgICAgICAgIC8qIHJldHJpZXZlZCB0YWJsZSBlbnRyeSAqL1xuICBsZXQgb3A7ICAgICAgICAgICAgICAgICAgICAgLyogY29kZSBiaXRzLCBvcGVyYXRpb24sIGV4dHJhIGJpdHMsIG9yICovXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvKiAgd2luZG93IHBvc2l0aW9uLCB3aW5kb3cgYnl0ZXMgdG8gY29weSAqL1xuICBsZXQgbGVuOyAgICAgICAgICAgICAgICAgICAgLyogbWF0Y2ggbGVuZ3RoLCB1bnVzZWQgYnl0ZXMgKi9cbiAgbGV0IGRpc3Q7ICAgICAgICAgICAgICAgICAgIC8qIG1hdGNoIGRpc3RhbmNlICovXG4gIGxldCBmcm9tOyAgICAgICAgICAgICAgICAgICAvKiB3aGVyZSB0byBjb3B5IG1hdGNoIGZyb20gKi9cbiAgbGV0IGZyb21fc291cmNlO1xuXG5cbiAgbGV0IGlucHV0LCBvdXRwdXQ7IC8vIEpTIHNwZWNpZmljLCBiZWNhdXNlIHdlIGhhdmUgbm8gcG9pbnRlcnNcblxuICAvKiBjb3B5IHN0YXRlIHRvIGxvY2FsIHZhcmlhYmxlcyAqL1xuICBjb25zdCBzdGF0ZSA9IHN0cm0uc3RhdGU7XG4gIC8vaGVyZSA9IHN0YXRlLmhlcmU7XG4gIF9pbiA9IHN0cm0ubmV4dF9pbjtcbiAgaW5wdXQgPSBzdHJtLmlucHV0O1xuICBsYXN0ID0gX2luICsgKHN0cm0uYXZhaWxfaW4gLSA1KTtcbiAgX291dCA9IHN0cm0ubmV4dF9vdXQ7XG4gIG91dHB1dCA9IHN0cm0ub3V0cHV0O1xuICBiZWcgPSBfb3V0IC0gKHN0YXJ0IC0gc3RybS5hdmFpbF9vdXQpO1xuICBlbmQgPSBfb3V0ICsgKHN0cm0uYXZhaWxfb3V0IC0gMjU3KTtcbi8vI2lmZGVmIElORkxBVEVfU1RSSUNUXG4gIGRtYXggPSBzdGF0ZS5kbWF4O1xuLy8jZW5kaWZcbiAgd3NpemUgPSBzdGF0ZS53c2l6ZTtcbiAgd2hhdmUgPSBzdGF0ZS53aGF2ZTtcbiAgd25leHQgPSBzdGF0ZS53bmV4dDtcbiAgc193aW5kb3cgPSBzdGF0ZS53aW5kb3c7XG4gIGhvbGQgPSBzdGF0ZS5ob2xkO1xuICBiaXRzID0gc3RhdGUuYml0cztcbiAgbGNvZGUgPSBzdGF0ZS5sZW5jb2RlO1xuICBkY29kZSA9IHN0YXRlLmRpc3Rjb2RlO1xuICBsbWFzayA9ICgxIDw8IHN0YXRlLmxlbmJpdHMpIC0gMTtcbiAgZG1hc2sgPSAoMSA8PCBzdGF0ZS5kaXN0Yml0cykgLSAxO1xuXG5cbiAgLyogZGVjb2RlIGxpdGVyYWxzIGFuZCBsZW5ndGgvZGlzdGFuY2VzIHVudGlsIGVuZC1vZi1ibG9jayBvciBub3QgZW5vdWdoXG4gICAgIGlucHV0IGRhdGEgb3Igb3V0cHV0IHNwYWNlICovXG5cbiAgdG9wOlxuICBkbyB7XG4gICAgaWYgKGJpdHMgPCAxNSkge1xuICAgICAgaG9sZCArPSBpbnB1dFtfaW4rK10gPDwgYml0cztcbiAgICAgIGJpdHMgKz0gODtcbiAgICAgIGhvbGQgKz0gaW5wdXRbX2luKytdIDw8IGJpdHM7XG4gICAgICBiaXRzICs9IDg7XG4gICAgfVxuXG4gICAgaGVyZSA9IGxjb2RlW2hvbGQgJiBsbWFza107XG5cbiAgICBkb2xlbjpcbiAgICBmb3IgKDs7KSB7IC8vIEdvdG8gZW11bGF0aW9uXG4gICAgICBvcCA9IGhlcmUgPj4+IDI0LypoZXJlLmJpdHMqLztcbiAgICAgIGhvbGQgPj4+PSBvcDtcbiAgICAgIGJpdHMgLT0gb3A7XG4gICAgICBvcCA9IChoZXJlID4+PiAxNikgJiAweGZmLypoZXJlLm9wKi87XG4gICAgICBpZiAob3AgPT09IDApIHsgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIGxpdGVyYWwgKi9cbiAgICAgICAgLy9UcmFjZXZ2KChzdGRlcnIsIGhlcmUudmFsID49IDB4MjAgJiYgaGVyZS52YWwgPCAweDdmID9cbiAgICAgICAgLy8gICAgICAgIFwiaW5mbGF0ZTogICAgICAgICBsaXRlcmFsICclYydcXG5cIiA6XG4gICAgICAgIC8vICAgICAgICBcImluZmxhdGU6ICAgICAgICAgbGl0ZXJhbCAweCUwMnhcXG5cIiwgaGVyZS52YWwpKTtcbiAgICAgICAgb3V0cHV0W19vdXQrK10gPSBoZXJlICYgMHhmZmZmLypoZXJlLnZhbCovO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAob3AgJiAxNikgeyAgICAgICAgICAgICAgICAgICAgIC8qIGxlbmd0aCBiYXNlICovXG4gICAgICAgIGxlbiA9IGhlcmUgJiAweGZmZmYvKmhlcmUudmFsKi87XG4gICAgICAgIG9wICY9IDE1OyAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIG51bWJlciBvZiBleHRyYSBiaXRzICovXG4gICAgICAgIGlmIChvcCkge1xuICAgICAgICAgIGlmIChiaXRzIDwgb3ApIHtcbiAgICAgICAgICAgIGhvbGQgKz0gaW5wdXRbX2luKytdIDw8IGJpdHM7XG4gICAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgfVxuICAgICAgICAgIGxlbiArPSBob2xkICYgKCgxIDw8IG9wKSAtIDEpO1xuICAgICAgICAgIGhvbGQgPj4+PSBvcDtcbiAgICAgICAgICBiaXRzIC09IG9wO1xuICAgICAgICB9XG4gICAgICAgIC8vVHJhY2V2digoc3RkZXJyLCBcImluZmxhdGU6ICAgICAgICAgbGVuZ3RoICV1XFxuXCIsIGxlbikpO1xuICAgICAgICBpZiAoYml0cyA8IDE1KSB7XG4gICAgICAgICAgaG9sZCArPSBpbnB1dFtfaW4rK10gPDwgYml0cztcbiAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgaG9sZCArPSBpbnB1dFtfaW4rK10gPDwgYml0cztcbiAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgIH1cbiAgICAgICAgaGVyZSA9IGRjb2RlW2hvbGQgJiBkbWFza107XG5cbiAgICAgICAgZG9kaXN0OlxuICAgICAgICBmb3IgKDs7KSB7IC8vIGdvdG8gZW11bGF0aW9uXG4gICAgICAgICAgb3AgPSBoZXJlID4+PiAyNC8qaGVyZS5iaXRzKi87XG4gICAgICAgICAgaG9sZCA+Pj49IG9wO1xuICAgICAgICAgIGJpdHMgLT0gb3A7XG4gICAgICAgICAgb3AgPSAoaGVyZSA+Pj4gMTYpICYgMHhmZi8qaGVyZS5vcCovO1xuXG4gICAgICAgICAgaWYgKG9wICYgMTYpIHsgICAgICAgICAgICAgICAgICAgICAgLyogZGlzdGFuY2UgYmFzZSAqL1xuICAgICAgICAgICAgZGlzdCA9IGhlcmUgJiAweGZmZmYvKmhlcmUudmFsKi87XG4gICAgICAgICAgICBvcCAmPSAxNTsgICAgICAgICAgICAgICAgICAgICAgIC8qIG51bWJlciBvZiBleHRyYSBiaXRzICovXG4gICAgICAgICAgICBpZiAoYml0cyA8IG9wKSB7XG4gICAgICAgICAgICAgIGhvbGQgKz0gaW5wdXRbX2luKytdIDw8IGJpdHM7XG4gICAgICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgICAgICAgaWYgKGJpdHMgPCBvcCkge1xuICAgICAgICAgICAgICAgIGhvbGQgKz0gaW5wdXRbX2luKytdIDw8IGJpdHM7XG4gICAgICAgICAgICAgICAgYml0cyArPSA4O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkaXN0ICs9IGhvbGQgJiAoKDEgPDwgb3ApIC0gMSk7XG4vLyNpZmRlZiBJTkZMQVRFX1NUUklDVFxuICAgICAgICAgICAgaWYgKGRpc3QgPiBkbWF4KSB7XG4gICAgICAgICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgZGlzdGFuY2UgdG9vIGZhciBiYWNrJztcbiAgICAgICAgICAgICAgc3RhdGUubW9kZSA9IEJBRCQxO1xuICAgICAgICAgICAgICBicmVhayB0b3A7XG4gICAgICAgICAgICB9XG4vLyNlbmRpZlxuICAgICAgICAgICAgaG9sZCA+Pj49IG9wO1xuICAgICAgICAgICAgYml0cyAtPSBvcDtcbiAgICAgICAgICAgIC8vVHJhY2V2digoc3RkZXJyLCBcImluZmxhdGU6ICAgICAgICAgZGlzdGFuY2UgJXVcXG5cIiwgZGlzdCkpO1xuICAgICAgICAgICAgb3AgPSBfb3V0IC0gYmVnOyAgICAgICAgICAgICAgICAvKiBtYXggZGlzdGFuY2UgaW4gb3V0cHV0ICovXG4gICAgICAgICAgICBpZiAoZGlzdCA+IG9wKSB7ICAgICAgICAgICAgICAgIC8qIHNlZSBpZiBjb3B5IGZyb20gd2luZG93ICovXG4gICAgICAgICAgICAgIG9wID0gZGlzdCAtIG9wOyAgICAgICAgICAgICAgIC8qIGRpc3RhbmNlIGJhY2sgaW4gd2luZG93ICovXG4gICAgICAgICAgICAgIGlmIChvcCA+IHdoYXZlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHN0YXRlLnNhbmUpIHtcbiAgICAgICAgICAgICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgZGlzdGFuY2UgdG9vIGZhciBiYWNrJztcbiAgICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQkMTtcbiAgICAgICAgICAgICAgICAgIGJyZWFrIHRvcDtcbiAgICAgICAgICAgICAgICB9XG5cbi8vICghKSBUaGlzIGJsb2NrIGlzIGRpc2FibGVkIGluIHpsaWIgZGVmYXVsdHMsXG4vLyBkb24ndCBlbmFibGUgaXQgZm9yIGJpbmFyeSBjb21wYXRpYmlsaXR5XG4vLyNpZmRlZiBJTkZMQVRFX0FMTE9XX0lOVkFMSURfRElTVEFOQ0VfVE9PRkFSX0FSUlJcbi8vICAgICAgICAgICAgICAgIGlmIChsZW4gPD0gb3AgLSB3aGF2ZSkge1xuLy8gICAgICAgICAgICAgICAgICBkbyB7XG4vLyAgICAgICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSAwO1xuLy8gICAgICAgICAgICAgICAgICB9IHdoaWxlICgtLWxlbik7XG4vLyAgICAgICAgICAgICAgICAgIGNvbnRpbnVlIHRvcDtcbi8vICAgICAgICAgICAgICAgIH1cbi8vICAgICAgICAgICAgICAgIGxlbiAtPSBvcCAtIHdoYXZlO1xuLy8gICAgICAgICAgICAgICAgZG8ge1xuLy8gICAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IDA7XG4vLyAgICAgICAgICAgICAgICB9IHdoaWxlICgtLW9wID4gd2hhdmUpO1xuLy8gICAgICAgICAgICAgICAgaWYgKG9wID09PSAwKSB7XG4vLyAgICAgICAgICAgICAgICAgIGZyb20gPSBfb3V0IC0gZGlzdDtcbi8vICAgICAgICAgICAgICAgICAgZG8ge1xuLy8gICAgICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gb3V0cHV0W2Zyb20rK107XG4vLyAgICAgICAgICAgICAgICAgIH0gd2hpbGUgKC0tbGVuKTtcbi8vICAgICAgICAgICAgICAgICAgY29udGludWUgdG9wO1xuLy8gICAgICAgICAgICAgICAgfVxuLy8jZW5kaWZcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBmcm9tID0gMDsgLy8gd2luZG93IGluZGV4XG4gICAgICAgICAgICAgIGZyb21fc291cmNlID0gc193aW5kb3c7XG4gICAgICAgICAgICAgIGlmICh3bmV4dCA9PT0gMCkgeyAgICAgICAgICAgLyogdmVyeSBjb21tb24gY2FzZSAqL1xuICAgICAgICAgICAgICAgIGZyb20gKz0gd3NpemUgLSBvcDtcbiAgICAgICAgICAgICAgICBpZiAob3AgPCBsZW4pIHsgICAgICAgICAvKiBzb21lIGZyb20gd2luZG93ICovXG4gICAgICAgICAgICAgICAgICBsZW4gLT0gb3A7XG4gICAgICAgICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gc193aW5kb3dbZnJvbSsrXTtcbiAgICAgICAgICAgICAgICAgIH0gd2hpbGUgKC0tb3ApO1xuICAgICAgICAgICAgICAgICAgZnJvbSA9IF9vdXQgLSBkaXN0OyAgLyogcmVzdCBmcm9tIG91dHB1dCAqL1xuICAgICAgICAgICAgICAgICAgZnJvbV9zb3VyY2UgPSBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGVsc2UgaWYgKHduZXh0IDwgb3ApIHsgICAgICAvKiB3cmFwIGFyb3VuZCB3aW5kb3cgKi9cbiAgICAgICAgICAgICAgICBmcm9tICs9IHdzaXplICsgd25leHQgLSBvcDtcbiAgICAgICAgICAgICAgICBvcCAtPSB3bmV4dDtcbiAgICAgICAgICAgICAgICBpZiAob3AgPCBsZW4pIHsgICAgICAgICAvKiBzb21lIGZyb20gZW5kIG9mIHdpbmRvdyAqL1xuICAgICAgICAgICAgICAgICAgbGVuIC09IG9wO1xuICAgICAgICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IHNfd2luZG93W2Zyb20rK107XG4gICAgICAgICAgICAgICAgICB9IHdoaWxlICgtLW9wKTtcbiAgICAgICAgICAgICAgICAgIGZyb20gPSAwO1xuICAgICAgICAgICAgICAgICAgaWYgKHduZXh0IDwgbGVuKSB7ICAvKiBzb21lIGZyb20gc3RhcnQgb2Ygd2luZG93ICovXG4gICAgICAgICAgICAgICAgICAgIG9wID0gd25leHQ7XG4gICAgICAgICAgICAgICAgICAgIGxlbiAtPSBvcDtcbiAgICAgICAgICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gc193aW5kb3dbZnJvbSsrXTtcbiAgICAgICAgICAgICAgICAgICAgfSB3aGlsZSAoLS1vcCk7XG4gICAgICAgICAgICAgICAgICAgIGZyb20gPSBfb3V0IC0gZGlzdDsgICAgICAvKiByZXN0IGZyb20gb3V0cHV0ICovXG4gICAgICAgICAgICAgICAgICAgIGZyb21fc291cmNlID0gb3V0cHV0O1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgLyogY29udGlndW91cyBpbiB3aW5kb3cgKi9cbiAgICAgICAgICAgICAgICBmcm9tICs9IHduZXh0IC0gb3A7XG4gICAgICAgICAgICAgICAgaWYgKG9wIDwgbGVuKSB7ICAgICAgICAgLyogc29tZSBmcm9tIHdpbmRvdyAqL1xuICAgICAgICAgICAgICAgICAgbGVuIC09IG9wO1xuICAgICAgICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IHNfd2luZG93W2Zyb20rK107XG4gICAgICAgICAgICAgICAgICB9IHdoaWxlICgtLW9wKTtcbiAgICAgICAgICAgICAgICAgIGZyb20gPSBfb3V0IC0gZGlzdDsgIC8qIHJlc3QgZnJvbSBvdXRwdXQgKi9cbiAgICAgICAgICAgICAgICAgIGZyb21fc291cmNlID0gb3V0cHV0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB3aGlsZSAobGVuID4gMikge1xuICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gZnJvbV9zb3VyY2VbZnJvbSsrXTtcbiAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IGZyb21fc291cmNlW2Zyb20rK107XG4gICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBmcm9tX3NvdXJjZVtmcm9tKytdO1xuICAgICAgICAgICAgICAgIGxlbiAtPSAzO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChsZW4pIHtcbiAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IGZyb21fc291cmNlW2Zyb20rK107XG4gICAgICAgICAgICAgICAgaWYgKGxlbiA+IDEpIHtcbiAgICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gZnJvbV9zb3VyY2VbZnJvbSsrXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICBmcm9tID0gX291dCAtIGRpc3Q7ICAgICAgICAgIC8qIGNvcHkgZGlyZWN0IGZyb20gb3V0cHV0ICovXG4gICAgICAgICAgICAgIGRvIHsgICAgICAgICAgICAgICAgICAgICAgICAvKiBtaW5pbXVtIGxlbmd0aCBpcyB0aHJlZSAqL1xuICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gb3V0cHV0W2Zyb20rK107XG4gICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBvdXRwdXRbZnJvbSsrXTtcbiAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IG91dHB1dFtmcm9tKytdO1xuICAgICAgICAgICAgICAgIGxlbiAtPSAzO1xuICAgICAgICAgICAgICB9IHdoaWxlIChsZW4gPiAyKTtcbiAgICAgICAgICAgICAgaWYgKGxlbikge1xuICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gb3V0cHV0W2Zyb20rK107XG4gICAgICAgICAgICAgICAgaWYgKGxlbiA+IDEpIHtcbiAgICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gb3V0cHV0W2Zyb20rK107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2UgaWYgKChvcCAmIDY0KSA9PT0gMCkgeyAgICAgICAgICAvKiAybmQgbGV2ZWwgZGlzdGFuY2UgY29kZSAqL1xuICAgICAgICAgICAgaGVyZSA9IGRjb2RlWyhoZXJlICYgMHhmZmZmKS8qaGVyZS52YWwqLyArIChob2xkICYgKCgxIDw8IG9wKSAtIDEpKV07XG4gICAgICAgICAgICBjb250aW51ZSBkb2Rpc3Q7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc3RybS5tc2cgPSAnaW52YWxpZCBkaXN0YW5jZSBjb2RlJztcbiAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQkMTtcbiAgICAgICAgICAgIGJyZWFrIHRvcDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBicmVhazsgLy8gbmVlZCB0byBlbXVsYXRlIGdvdG8gdmlhIFwiY29udGludWVcIlxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBlbHNlIGlmICgob3AgJiA2NCkgPT09IDApIHsgICAgICAgICAgICAgIC8qIDJuZCBsZXZlbCBsZW5ndGggY29kZSAqL1xuICAgICAgICBoZXJlID0gbGNvZGVbKGhlcmUgJiAweGZmZmYpLypoZXJlLnZhbCovICsgKGhvbGQgJiAoKDEgPDwgb3ApIC0gMSkpXTtcbiAgICAgICAgY29udGludWUgZG9sZW47XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChvcCAmIDMyKSB7ICAgICAgICAgICAgICAgICAgICAgLyogZW5kLW9mLWJsb2NrICovXG4gICAgICAgIC8vVHJhY2V2digoc3RkZXJyLCBcImluZmxhdGU6ICAgICAgICAgZW5kIG9mIGJsb2NrXFxuXCIpKTtcbiAgICAgICAgc3RhdGUubW9kZSA9IFRZUEUkMTtcbiAgICAgICAgYnJlYWsgdG9wO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgbGl0ZXJhbC9sZW5ndGggY29kZSc7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBCQUQkMTtcbiAgICAgICAgYnJlYWsgdG9wO1xuICAgICAgfVxuXG4gICAgICBicmVhazsgLy8gbmVlZCB0byBlbXVsYXRlIGdvdG8gdmlhIFwiY29udGludWVcIlxuICAgIH1cbiAgfSB3aGlsZSAoX2luIDwgbGFzdCAmJiBfb3V0IDwgZW5kKTtcblxuICAvKiByZXR1cm4gdW51c2VkIGJ5dGVzIChvbiBlbnRyeSwgYml0cyA8IDgsIHNvIGluIHdvbid0IGdvIHRvbyBmYXIgYmFjaykgKi9cbiAgbGVuID0gYml0cyA+PiAzO1xuICBfaW4gLT0gbGVuO1xuICBiaXRzIC09IGxlbiA8PCAzO1xuICBob2xkICY9ICgxIDw8IGJpdHMpIC0gMTtcblxuICAvKiB1cGRhdGUgc3RhdGUgYW5kIHJldHVybiAqL1xuICBzdHJtLm5leHRfaW4gPSBfaW47XG4gIHN0cm0ubmV4dF9vdXQgPSBfb3V0O1xuICBzdHJtLmF2YWlsX2luID0gKF9pbiA8IGxhc3QgPyA1ICsgKGxhc3QgLSBfaW4pIDogNSAtIChfaW4gLSBsYXN0KSk7XG4gIHN0cm0uYXZhaWxfb3V0ID0gKF9vdXQgPCBlbmQgPyAyNTcgKyAoZW5kIC0gX291dCkgOiAyNTcgLSAoX291dCAtIGVuZCkpO1xuICBzdGF0ZS5ob2xkID0gaG9sZDtcbiAgc3RhdGUuYml0cyA9IGJpdHM7XG4gIHJldHVybjtcbn07XG5cbi8vIChDKSAxOTk1LTIwMTMgSmVhbi1sb3VwIEdhaWxseSBhbmQgTWFyayBBZGxlclxuLy8gKEMpIDIwMTQtMjAxNyBWaXRhbHkgUHV6cmluIGFuZCBBbmRyZXkgVHVwaXRzaW5cbi8vXG4vLyBUaGlzIHNvZnR3YXJlIGlzIHByb3ZpZGVkICdhcy1pcycsIHdpdGhvdXQgYW55IGV4cHJlc3Mgb3IgaW1wbGllZFxuLy8gd2FycmFudHkuIEluIG5vIGV2ZW50IHdpbGwgdGhlIGF1dGhvcnMgYmUgaGVsZCBsaWFibGUgZm9yIGFueSBkYW1hZ2VzXG4vLyBhcmlzaW5nIGZyb20gdGhlIHVzZSBvZiB0aGlzIHNvZnR3YXJlLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgZ3JhbnRlZCB0byBhbnlvbmUgdG8gdXNlIHRoaXMgc29mdHdhcmUgZm9yIGFueSBwdXJwb3NlLFxuLy8gaW5jbHVkaW5nIGNvbW1lcmNpYWwgYXBwbGljYXRpb25zLCBhbmQgdG8gYWx0ZXIgaXQgYW5kIHJlZGlzdHJpYnV0ZSBpdFxuLy8gZnJlZWx5LCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgcmVzdHJpY3Rpb25zOlxuLy9cbi8vIDEuIFRoZSBvcmlnaW4gb2YgdGhpcyBzb2Z0d2FyZSBtdXN0IG5vdCBiZSBtaXNyZXByZXNlbnRlZDsgeW91IG11c3Qgbm90XG4vLyAgIGNsYWltIHRoYXQgeW91IHdyb3RlIHRoZSBvcmlnaW5hbCBzb2Z0d2FyZS4gSWYgeW91IHVzZSB0aGlzIHNvZnR3YXJlXG4vLyAgIGluIGEgcHJvZHVjdCwgYW4gYWNrbm93bGVkZ21lbnQgaW4gdGhlIHByb2R1Y3QgZG9jdW1lbnRhdGlvbiB3b3VsZCBiZVxuLy8gICBhcHByZWNpYXRlZCBidXQgaXMgbm90IHJlcXVpcmVkLlxuLy8gMi4gQWx0ZXJlZCBzb3VyY2UgdmVyc2lvbnMgbXVzdCBiZSBwbGFpbmx5IG1hcmtlZCBhcyBzdWNoLCBhbmQgbXVzdCBub3QgYmVcbi8vICAgbWlzcmVwcmVzZW50ZWQgYXMgYmVpbmcgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLlxuLy8gMy4gVGhpcyBub3RpY2UgbWF5IG5vdCBiZSByZW1vdmVkIG9yIGFsdGVyZWQgZnJvbSBhbnkgc291cmNlIGRpc3RyaWJ1dGlvbi5cblxuY29uc3QgTUFYQklUUyA9IDE1O1xuY29uc3QgRU5PVUdIX0xFTlMkMSA9IDg1MjtcbmNvbnN0IEVOT1VHSF9ESVNUUyQxID0gNTkyO1xuLy9jb25zdCBFTk9VR0ggPSAoRU5PVUdIX0xFTlMrRU5PVUdIX0RJU1RTKTtcblxuY29uc3QgQ09ERVMkMSA9IDA7XG5jb25zdCBMRU5TJDEgPSAxO1xuY29uc3QgRElTVFMkMSA9IDI7XG5cbmNvbnN0IGxiYXNlID0gbmV3IFVpbnQxNkFycmF5KFsgLyogTGVuZ3RoIGNvZGVzIDI1Ny4uMjg1IGJhc2UgKi9cbiAgMywgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExLCAxMywgMTUsIDE3LCAxOSwgMjMsIDI3LCAzMSxcbiAgMzUsIDQzLCA1MSwgNTksIDY3LCA4MywgOTksIDExNSwgMTMxLCAxNjMsIDE5NSwgMjI3LCAyNTgsIDAsIDBcbl0pO1xuXG5jb25zdCBsZXh0ID0gbmV3IFVpbnQ4QXJyYXkoWyAvKiBMZW5ndGggY29kZXMgMjU3Li4yODUgZXh0cmEgKi9cbiAgMTYsIDE2LCAxNiwgMTYsIDE2LCAxNiwgMTYsIDE2LCAxNywgMTcsIDE3LCAxNywgMTgsIDE4LCAxOCwgMTgsXG4gIDE5LCAxOSwgMTksIDE5LCAyMCwgMjAsIDIwLCAyMCwgMjEsIDIxLCAyMSwgMjEsIDE2LCA3MiwgNzhcbl0pO1xuXG5jb25zdCBkYmFzZSA9IG5ldyBVaW50MTZBcnJheShbIC8qIERpc3RhbmNlIGNvZGVzIDAuLjI5IGJhc2UgKi9cbiAgMSwgMiwgMywgNCwgNSwgNywgOSwgMTMsIDE3LCAyNSwgMzMsIDQ5LCA2NSwgOTcsIDEyOSwgMTkzLFxuICAyNTcsIDM4NSwgNTEzLCA3NjksIDEwMjUsIDE1MzcsIDIwNDksIDMwNzMsIDQwOTcsIDYxNDUsXG4gIDgxOTMsIDEyMjg5LCAxNjM4NSwgMjQ1NzcsIDAsIDBcbl0pO1xuXG5jb25zdCBkZXh0ID0gbmV3IFVpbnQ4QXJyYXkoWyAvKiBEaXN0YW5jZSBjb2RlcyAwLi4yOSBleHRyYSAqL1xuICAxNiwgMTYsIDE2LCAxNiwgMTcsIDE3LCAxOCwgMTgsIDE5LCAxOSwgMjAsIDIwLCAyMSwgMjEsIDIyLCAyMixcbiAgMjMsIDIzLCAyNCwgMjQsIDI1LCAyNSwgMjYsIDI2LCAyNywgMjcsXG4gIDI4LCAyOCwgMjksIDI5LCA2NCwgNjRcbl0pO1xuXG5jb25zdCBpbmZsYXRlX3RhYmxlID0gKHR5cGUsIGxlbnMsIGxlbnNfaW5kZXgsIGNvZGVzLCB0YWJsZSwgdGFibGVfaW5kZXgsIHdvcmssIG9wdHMpID0+XG57XG4gIGNvbnN0IGJpdHMgPSBvcHRzLmJpdHM7XG4gICAgICAvL2hlcmUgPSBvcHRzLmhlcmU7IC8qIHRhYmxlIGVudHJ5IGZvciBkdXBsaWNhdGlvbiAqL1xuXG4gIGxldCBsZW4gPSAwOyAgICAgICAgICAgICAgIC8qIGEgY29kZSdzIGxlbmd0aCBpbiBiaXRzICovXG4gIGxldCBzeW0gPSAwOyAgICAgICAgICAgICAgIC8qIGluZGV4IG9mIGNvZGUgc3ltYm9scyAqL1xuICBsZXQgbWluID0gMCwgbWF4ID0gMDsgICAgICAgICAgLyogbWluaW11bSBhbmQgbWF4aW11bSBjb2RlIGxlbmd0aHMgKi9cbiAgbGV0IHJvb3QgPSAwOyAgICAgICAgICAgICAgLyogbnVtYmVyIG9mIGluZGV4IGJpdHMgZm9yIHJvb3QgdGFibGUgKi9cbiAgbGV0IGN1cnIgPSAwOyAgICAgICAgICAgICAgLyogbnVtYmVyIG9mIGluZGV4IGJpdHMgZm9yIGN1cnJlbnQgdGFibGUgKi9cbiAgbGV0IGRyb3AgPSAwOyAgICAgICAgICAgICAgLyogY29kZSBiaXRzIHRvIGRyb3AgZm9yIHN1Yi10YWJsZSAqL1xuICBsZXQgbGVmdCA9IDA7ICAgICAgICAgICAgICAgICAgIC8qIG51bWJlciBvZiBwcmVmaXggY29kZXMgYXZhaWxhYmxlICovXG4gIGxldCB1c2VkID0gMDsgICAgICAgICAgICAgIC8qIGNvZGUgZW50cmllcyBpbiB0YWJsZSB1c2VkICovXG4gIGxldCBodWZmID0gMDsgICAgICAgICAgICAgIC8qIEh1ZmZtYW4gY29kZSAqL1xuICBsZXQgaW5jcjsgICAgICAgICAgICAgIC8qIGZvciBpbmNyZW1lbnRpbmcgY29kZSwgaW5kZXggKi9cbiAgbGV0IGZpbGw7ICAgICAgICAgICAgICAvKiBpbmRleCBmb3IgcmVwbGljYXRpbmcgZW50cmllcyAqL1xuICBsZXQgbG93OyAgICAgICAgICAgICAgIC8qIGxvdyBiaXRzIGZvciBjdXJyZW50IHJvb3QgZW50cnkgKi9cbiAgbGV0IG1hc2s7ICAgICAgICAgICAgICAvKiBtYXNrIGZvciBsb3cgcm9vdCBiaXRzICovXG4gIGxldCBuZXh0OyAgICAgICAgICAgICAvKiBuZXh0IGF2YWlsYWJsZSBzcGFjZSBpbiB0YWJsZSAqL1xuICBsZXQgYmFzZSA9IG51bGw7ICAgICAvKiBiYXNlIHZhbHVlIHRhYmxlIHRvIHVzZSAqL1xuLy8gIGxldCBzaG9leHRyYTsgICAgLyogZXh0cmEgYml0cyB0YWJsZSB0byB1c2UgKi9cbiAgbGV0IG1hdGNoOyAgICAgICAgICAgICAgICAgIC8qIHVzZSBiYXNlIGFuZCBleHRyYSBmb3Igc3ltYm9sID49IG1hdGNoICovXG4gIGNvbnN0IGNvdW50ID0gbmV3IFVpbnQxNkFycmF5KE1BWEJJVFMgKyAxKTsgLy9bTUFYQklUUysxXTsgICAgLyogbnVtYmVyIG9mIGNvZGVzIG9mIGVhY2ggbGVuZ3RoICovXG4gIGNvbnN0IG9mZnMgPSBuZXcgVWludDE2QXJyYXkoTUFYQklUUyArIDEpOyAvL1tNQVhCSVRTKzFdOyAgICAgLyogb2Zmc2V0cyBpbiB0YWJsZSBmb3IgZWFjaCBsZW5ndGggKi9cbiAgbGV0IGV4dHJhID0gbnVsbDtcblxuICBsZXQgaGVyZV9iaXRzLCBoZXJlX29wLCBoZXJlX3ZhbDtcblxuICAvKlxuICAgUHJvY2VzcyBhIHNldCBvZiBjb2RlIGxlbmd0aHMgdG8gY3JlYXRlIGEgY2Fub25pY2FsIEh1ZmZtYW4gY29kZS4gIFRoZVxuICAgY29kZSBsZW5ndGhzIGFyZSBsZW5zWzAuLmNvZGVzLTFdLiAgRWFjaCBsZW5ndGggY29ycmVzcG9uZHMgdG8gdGhlXG4gICBzeW1ib2xzIDAuLmNvZGVzLTEuICBUaGUgSHVmZm1hbiBjb2RlIGlzIGdlbmVyYXRlZCBieSBmaXJzdCBzb3J0aW5nIHRoZVxuICAgc3ltYm9scyBieSBsZW5ndGggZnJvbSBzaG9ydCB0byBsb25nLCBhbmQgcmV0YWluaW5nIHRoZSBzeW1ib2wgb3JkZXJcbiAgIGZvciBjb2RlcyB3aXRoIGVxdWFsIGxlbmd0aHMuICBUaGVuIHRoZSBjb2RlIHN0YXJ0cyB3aXRoIGFsbCB6ZXJvIGJpdHNcbiAgIGZvciB0aGUgZmlyc3QgY29kZSBvZiB0aGUgc2hvcnRlc3QgbGVuZ3RoLCBhbmQgdGhlIGNvZGVzIGFyZSBpbnRlZ2VyXG4gICBpbmNyZW1lbnRzIGZvciB0aGUgc2FtZSBsZW5ndGgsIGFuZCB6ZXJvcyBhcmUgYXBwZW5kZWQgYXMgdGhlIGxlbmd0aFxuICAgaW5jcmVhc2VzLiAgRm9yIHRoZSBkZWZsYXRlIGZvcm1hdCwgdGhlc2UgYml0cyBhcmUgc3RvcmVkIGJhY2t3YXJkc1xuICAgZnJvbSB0aGVpciBtb3JlIG5hdHVyYWwgaW50ZWdlciBpbmNyZW1lbnQgb3JkZXJpbmcsIGFuZCBzbyB3aGVuIHRoZVxuICAgZGVjb2RpbmcgdGFibGVzIGFyZSBidWlsdCBpbiB0aGUgbGFyZ2UgbG9vcCBiZWxvdywgdGhlIGludGVnZXIgY29kZXNcbiAgIGFyZSBpbmNyZW1lbnRlZCBiYWNrd2FyZHMuXG5cbiAgIFRoaXMgcm91dGluZSBhc3N1bWVzLCBidXQgZG9lcyBub3QgY2hlY2ssIHRoYXQgYWxsIG9mIHRoZSBlbnRyaWVzIGluXG4gICBsZW5zW10gYXJlIGluIHRoZSByYW5nZSAwLi5NQVhCSVRTLiAgVGhlIGNhbGxlciBtdXN0IGFzc3VyZSB0aGlzLlxuICAgMS4uTUFYQklUUyBpcyBpbnRlcnByZXRlZCBhcyB0aGF0IGNvZGUgbGVuZ3RoLiAgemVybyBtZWFucyB0aGF0IHRoYXRcbiAgIHN5bWJvbCBkb2VzIG5vdCBvY2N1ciBpbiB0aGlzIGNvZGUuXG5cbiAgIFRoZSBjb2RlcyBhcmUgc29ydGVkIGJ5IGNvbXB1dGluZyBhIGNvdW50IG9mIGNvZGVzIGZvciBlYWNoIGxlbmd0aCxcbiAgIGNyZWF0aW5nIGZyb20gdGhhdCBhIHRhYmxlIG9mIHN0YXJ0aW5nIGluZGljZXMgZm9yIGVhY2ggbGVuZ3RoIGluIHRoZVxuICAgc29ydGVkIHRhYmxlLCBhbmQgdGhlbiBlbnRlcmluZyB0aGUgc3ltYm9scyBpbiBvcmRlciBpbiB0aGUgc29ydGVkXG4gICB0YWJsZS4gIFRoZSBzb3J0ZWQgdGFibGUgaXMgd29ya1tdLCB3aXRoIHRoYXQgc3BhY2UgYmVpbmcgcHJvdmlkZWQgYnlcbiAgIHRoZSBjYWxsZXIuXG5cbiAgIFRoZSBsZW5ndGggY291bnRzIGFyZSB1c2VkIGZvciBvdGhlciBwdXJwb3NlcyBhcyB3ZWxsLCBpLmUuIGZpbmRpbmdcbiAgIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIGxlbmd0aCBjb2RlcywgZGV0ZXJtaW5pbmcgaWYgdGhlcmUgYXJlIGFueVxuICAgY29kZXMgYXQgYWxsLCBjaGVja2luZyBmb3IgYSB2YWxpZCBzZXQgb2YgbGVuZ3RocywgYW5kIGxvb2tpbmcgYWhlYWRcbiAgIGF0IGxlbmd0aCBjb3VudHMgdG8gZGV0ZXJtaW5lIHN1Yi10YWJsZSBzaXplcyB3aGVuIGJ1aWxkaW5nIHRoZVxuICAgZGVjb2RpbmcgdGFibGVzLlxuICAgKi9cblxuICAvKiBhY2N1bXVsYXRlIGxlbmd0aHMgZm9yIGNvZGVzIChhc3N1bWVzIGxlbnNbXSBhbGwgaW4gMC4uTUFYQklUUykgKi9cbiAgZm9yIChsZW4gPSAwOyBsZW4gPD0gTUFYQklUUzsgbGVuKyspIHtcbiAgICBjb3VudFtsZW5dID0gMDtcbiAgfVxuICBmb3IgKHN5bSA9IDA7IHN5bSA8IGNvZGVzOyBzeW0rKykge1xuICAgIGNvdW50W2xlbnNbbGVuc19pbmRleCArIHN5bV1dKys7XG4gIH1cblxuICAvKiBib3VuZCBjb2RlIGxlbmd0aHMsIGZvcmNlIHJvb3QgdG8gYmUgd2l0aGluIGNvZGUgbGVuZ3RocyAqL1xuICByb290ID0gYml0cztcbiAgZm9yIChtYXggPSBNQVhCSVRTOyBtYXggPj0gMTsgbWF4LS0pIHtcbiAgICBpZiAoY291bnRbbWF4XSAhPT0gMCkgeyBicmVhazsgfVxuICB9XG4gIGlmIChyb290ID4gbWF4KSB7XG4gICAgcm9vdCA9IG1heDtcbiAgfVxuICBpZiAobWF4ID09PSAwKSB7ICAgICAgICAgICAgICAgICAgICAgLyogbm8gc3ltYm9scyB0byBjb2RlIGF0IGFsbCAqL1xuICAgIC8vdGFibGUub3Bbb3B0cy50YWJsZV9pbmRleF0gPSA2NDsgIC8vaGVyZS5vcCA9ICh2YXIgY2hhcik2NDsgICAgLyogaW52YWxpZCBjb2RlIG1hcmtlciAqL1xuICAgIC8vdGFibGUuYml0c1tvcHRzLnRhYmxlX2luZGV4XSA9IDE7ICAgLy9oZXJlLmJpdHMgPSAodmFyIGNoYXIpMTtcbiAgICAvL3RhYmxlLnZhbFtvcHRzLnRhYmxlX2luZGV4KytdID0gMDsgICAvL2hlcmUudmFsID0gKHZhciBzaG9ydCkwO1xuICAgIHRhYmxlW3RhYmxlX2luZGV4KytdID0gKDEgPDwgMjQpIHwgKDY0IDw8IDE2KSB8IDA7XG5cblxuICAgIC8vdGFibGUub3Bbb3B0cy50YWJsZV9pbmRleF0gPSA2NDtcbiAgICAvL3RhYmxlLmJpdHNbb3B0cy50YWJsZV9pbmRleF0gPSAxO1xuICAgIC8vdGFibGUudmFsW29wdHMudGFibGVfaW5kZXgrK10gPSAwO1xuICAgIHRhYmxlW3RhYmxlX2luZGV4KytdID0gKDEgPDwgMjQpIHwgKDY0IDw8IDE2KSB8IDA7XG5cbiAgICBvcHRzLmJpdHMgPSAxO1xuICAgIHJldHVybiAwOyAgICAgLyogbm8gc3ltYm9scywgYnV0IHdhaXQgZm9yIGRlY29kaW5nIHRvIHJlcG9ydCBlcnJvciAqL1xuICB9XG4gIGZvciAobWluID0gMTsgbWluIDwgbWF4OyBtaW4rKykge1xuICAgIGlmIChjb3VudFttaW5dICE9PSAwKSB7IGJyZWFrOyB9XG4gIH1cbiAgaWYgKHJvb3QgPCBtaW4pIHtcbiAgICByb290ID0gbWluO1xuICB9XG5cbiAgLyogY2hlY2sgZm9yIGFuIG92ZXItc3Vic2NyaWJlZCBvciBpbmNvbXBsZXRlIHNldCBvZiBsZW5ndGhzICovXG4gIGxlZnQgPSAxO1xuICBmb3IgKGxlbiA9IDE7IGxlbiA8PSBNQVhCSVRTOyBsZW4rKykge1xuICAgIGxlZnQgPDw9IDE7XG4gICAgbGVmdCAtPSBjb3VudFtsZW5dO1xuICAgIGlmIChsZWZ0IDwgMCkge1xuICAgICAgcmV0dXJuIC0xO1xuICAgIH0gICAgICAgIC8qIG92ZXItc3Vic2NyaWJlZCAqL1xuICB9XG4gIGlmIChsZWZ0ID4gMCAmJiAodHlwZSA9PT0gQ09ERVMkMSB8fCBtYXggIT09IDEpKSB7XG4gICAgcmV0dXJuIC0xOyAgICAgICAgICAgICAgICAgICAgICAvKiBpbmNvbXBsZXRlIHNldCAqL1xuICB9XG5cbiAgLyogZ2VuZXJhdGUgb2Zmc2V0cyBpbnRvIHN5bWJvbCB0YWJsZSBmb3IgZWFjaCBsZW5ndGggZm9yIHNvcnRpbmcgKi9cbiAgb2Zmc1sxXSA9IDA7XG4gIGZvciAobGVuID0gMTsgbGVuIDwgTUFYQklUUzsgbGVuKyspIHtcbiAgICBvZmZzW2xlbiArIDFdID0gb2Zmc1tsZW5dICsgY291bnRbbGVuXTtcbiAgfVxuXG4gIC8qIHNvcnQgc3ltYm9scyBieSBsZW5ndGgsIGJ5IHN5bWJvbCBvcmRlciB3aXRoaW4gZWFjaCBsZW5ndGggKi9cbiAgZm9yIChzeW0gPSAwOyBzeW0gPCBjb2Rlczsgc3ltKyspIHtcbiAgICBpZiAobGVuc1tsZW5zX2luZGV4ICsgc3ltXSAhPT0gMCkge1xuICAgICAgd29ya1tvZmZzW2xlbnNbbGVuc19pbmRleCArIHN5bV1dKytdID0gc3ltO1xuICAgIH1cbiAgfVxuXG4gIC8qXG4gICBDcmVhdGUgYW5kIGZpbGwgaW4gZGVjb2RpbmcgdGFibGVzLiAgSW4gdGhpcyBsb29wLCB0aGUgdGFibGUgYmVpbmdcbiAgIGZpbGxlZCBpcyBhdCBuZXh0IGFuZCBoYXMgY3VyciBpbmRleCBiaXRzLiAgVGhlIGNvZGUgYmVpbmcgdXNlZCBpcyBodWZmXG4gICB3aXRoIGxlbmd0aCBsZW4uICBUaGF0IGNvZGUgaXMgY29udmVydGVkIHRvIGFuIGluZGV4IGJ5IGRyb3BwaW5nIGRyb3BcbiAgIGJpdHMgb2ZmIG9mIHRoZSBib3R0b20uICBGb3IgY29kZXMgd2hlcmUgbGVuIGlzIGxlc3MgdGhhbiBkcm9wICsgY3VycixcbiAgIHRob3NlIHRvcCBkcm9wICsgY3VyciAtIGxlbiBiaXRzIGFyZSBpbmNyZW1lbnRlZCB0aHJvdWdoIGFsbCB2YWx1ZXMgdG9cbiAgIGZpbGwgdGhlIHRhYmxlIHdpdGggcmVwbGljYXRlZCBlbnRyaWVzLlxuXG4gICByb290IGlzIHRoZSBudW1iZXIgb2YgaW5kZXggYml0cyBmb3IgdGhlIHJvb3QgdGFibGUuICBXaGVuIGxlbiBleGNlZWRzXG4gICByb290LCBzdWItdGFibGVzIGFyZSBjcmVhdGVkIHBvaW50ZWQgdG8gYnkgdGhlIHJvb3QgZW50cnkgd2l0aCBhbiBpbmRleFxuICAgb2YgdGhlIGxvdyByb290IGJpdHMgb2YgaHVmZi4gIFRoaXMgaXMgc2F2ZWQgaW4gbG93IHRvIGNoZWNrIGZvciB3aGVuIGFcbiAgIG5ldyBzdWItdGFibGUgc2hvdWxkIGJlIHN0YXJ0ZWQuICBkcm9wIGlzIHplcm8gd2hlbiB0aGUgcm9vdCB0YWJsZSBpc1xuICAgYmVpbmcgZmlsbGVkLCBhbmQgZHJvcCBpcyByb290IHdoZW4gc3ViLXRhYmxlcyBhcmUgYmVpbmcgZmlsbGVkLlxuXG4gICBXaGVuIGEgbmV3IHN1Yi10YWJsZSBpcyBuZWVkZWQsIGl0IGlzIG5lY2Vzc2FyeSB0byBsb29rIGFoZWFkIGluIHRoZVxuICAgY29kZSBsZW5ndGhzIHRvIGRldGVybWluZSB3aGF0IHNpemUgc3ViLXRhYmxlIGlzIG5lZWRlZC4gIFRoZSBsZW5ndGhcbiAgIGNvdW50cyBhcmUgdXNlZCBmb3IgdGhpcywgYW5kIHNvIGNvdW50W10gaXMgZGVjcmVtZW50ZWQgYXMgY29kZXMgYXJlXG4gICBlbnRlcmVkIGluIHRoZSB0YWJsZXMuXG5cbiAgIHVzZWQga2VlcHMgdHJhY2sgb2YgaG93IG1hbnkgdGFibGUgZW50cmllcyBoYXZlIGJlZW4gYWxsb2NhdGVkIGZyb20gdGhlXG4gICBwcm92aWRlZCAqdGFibGUgc3BhY2UuICBJdCBpcyBjaGVja2VkIGZvciBMRU5TIGFuZCBESVNUIHRhYmxlcyBhZ2FpbnN0XG4gICB0aGUgY29uc3RhbnRzIEVOT1VHSF9MRU5TIGFuZCBFTk9VR0hfRElTVFMgdG8gZ3VhcmQgYWdhaW5zdCBjaGFuZ2VzIGluXG4gICB0aGUgaW5pdGlhbCByb290IHRhYmxlIHNpemUgY29uc3RhbnRzLiAgU2VlIHRoZSBjb21tZW50cyBpbiBpbmZ0cmVlcy5oXG4gICBmb3IgbW9yZSBpbmZvcm1hdGlvbi5cblxuICAgc3ltIGluY3JlbWVudHMgdGhyb3VnaCBhbGwgc3ltYm9scywgYW5kIHRoZSBsb29wIHRlcm1pbmF0ZXMgd2hlblxuICAgYWxsIGNvZGVzIG9mIGxlbmd0aCBtYXgsIGkuZS4gYWxsIGNvZGVzLCBoYXZlIGJlZW4gcHJvY2Vzc2VkLiAgVGhpc1xuICAgcm91dGluZSBwZXJtaXRzIGluY29tcGxldGUgY29kZXMsIHNvIGFub3RoZXIgbG9vcCBhZnRlciB0aGlzIG9uZSBmaWxsc1xuICAgaW4gdGhlIHJlc3Qgb2YgdGhlIGRlY29kaW5nIHRhYmxlcyB3aXRoIGludmFsaWQgY29kZSBtYXJrZXJzLlxuICAgKi9cblxuICAvKiBzZXQgdXAgZm9yIGNvZGUgdHlwZSAqL1xuICAvLyBwb29yIG1hbiBvcHRpbWl6YXRpb24gLSB1c2UgaWYtZWxzZSBpbnN0ZWFkIG9mIHN3aXRjaCxcbiAgLy8gdG8gYXZvaWQgZGVvcHRzIGluIG9sZCB2OFxuICBpZiAodHlwZSA9PT0gQ09ERVMkMSkge1xuICAgIGJhc2UgPSBleHRyYSA9IHdvcms7ICAgIC8qIGR1bW15IHZhbHVlLS1ub3QgdXNlZCAqL1xuICAgIG1hdGNoID0gMjA7XG5cbiAgfSBlbHNlIGlmICh0eXBlID09PSBMRU5TJDEpIHtcbiAgICBiYXNlID0gbGJhc2U7XG4gICAgZXh0cmEgPSBsZXh0O1xuICAgIG1hdGNoID0gMjU3O1xuXG4gIH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgICAvKiBESVNUUyAqL1xuICAgIGJhc2UgPSBkYmFzZTtcbiAgICBleHRyYSA9IGRleHQ7XG4gICAgbWF0Y2ggPSAwO1xuICB9XG5cbiAgLyogaW5pdGlhbGl6ZSBvcHRzIGZvciBsb29wICovXG4gIGh1ZmYgPSAwOyAgICAgICAgICAgICAgICAgICAvKiBzdGFydGluZyBjb2RlICovXG4gIHN5bSA9IDA7ICAgICAgICAgICAgICAgICAgICAvKiBzdGFydGluZyBjb2RlIHN5bWJvbCAqL1xuICBsZW4gPSBtaW47ICAgICAgICAgICAgICAgICAgLyogc3RhcnRpbmcgY29kZSBsZW5ndGggKi9cbiAgbmV4dCA9IHRhYmxlX2luZGV4OyAgICAgICAgICAgICAgLyogY3VycmVudCB0YWJsZSB0byBmaWxsIGluICovXG4gIGN1cnIgPSByb290OyAgICAgICAgICAgICAgICAvKiBjdXJyZW50IHRhYmxlIGluZGV4IGJpdHMgKi9cbiAgZHJvcCA9IDA7ICAgICAgICAgICAgICAgICAgIC8qIGN1cnJlbnQgYml0cyB0byBkcm9wIGZyb20gY29kZSBmb3IgaW5kZXggKi9cbiAgbG93ID0gLTE7ICAgICAgICAgICAgICAgICAgIC8qIHRyaWdnZXIgbmV3IHN1Yi10YWJsZSB3aGVuIGxlbiA+IHJvb3QgKi9cbiAgdXNlZCA9IDEgPDwgcm9vdDsgICAgICAgICAgLyogdXNlIHJvb3QgdGFibGUgZW50cmllcyAqL1xuICBtYXNrID0gdXNlZCAtIDE7ICAgICAgICAgICAgLyogbWFzayBmb3IgY29tcGFyaW5nIGxvdyAqL1xuXG4gIC8qIGNoZWNrIGF2YWlsYWJsZSB0YWJsZSBzcGFjZSAqL1xuICBpZiAoKHR5cGUgPT09IExFTlMkMSAmJiB1c2VkID4gRU5PVUdIX0xFTlMkMSkgfHxcbiAgICAodHlwZSA9PT0gRElTVFMkMSAmJiB1c2VkID4gRU5PVUdIX0RJU1RTJDEpKSB7XG4gICAgcmV0dXJuIDE7XG4gIH1cblxuICAvKiBwcm9jZXNzIGFsbCBjb2RlcyBhbmQgbWFrZSB0YWJsZSBlbnRyaWVzICovXG4gIGZvciAoOzspIHtcbiAgICAvKiBjcmVhdGUgdGFibGUgZW50cnkgKi9cbiAgICBoZXJlX2JpdHMgPSBsZW4gLSBkcm9wO1xuICAgIGlmICh3b3JrW3N5bV0gKyAxIDwgbWF0Y2gpIHtcbiAgICAgIGhlcmVfb3AgPSAwO1xuICAgICAgaGVyZV92YWwgPSB3b3JrW3N5bV07XG4gICAgfVxuICAgIGVsc2UgaWYgKHdvcmtbc3ltXSA+PSBtYXRjaCkge1xuICAgICAgaGVyZV9vcCA9IGV4dHJhW3dvcmtbc3ltXSAtIG1hdGNoXTtcbiAgICAgIGhlcmVfdmFsID0gYmFzZVt3b3JrW3N5bV0gLSBtYXRjaF07XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgaGVyZV9vcCA9IDMyICsgNjQ7ICAgICAgICAgLyogZW5kIG9mIGJsb2NrICovXG4gICAgICBoZXJlX3ZhbCA9IDA7XG4gICAgfVxuXG4gICAgLyogcmVwbGljYXRlIGZvciB0aG9zZSBpbmRpY2VzIHdpdGggbG93IGxlbiBiaXRzIGVxdWFsIHRvIGh1ZmYgKi9cbiAgICBpbmNyID0gMSA8PCAobGVuIC0gZHJvcCk7XG4gICAgZmlsbCA9IDEgPDwgY3VycjtcbiAgICBtaW4gPSBmaWxsOyAgICAgICAgICAgICAgICAgLyogc2F2ZSBvZmZzZXQgdG8gbmV4dCB0YWJsZSAqL1xuICAgIGRvIHtcbiAgICAgIGZpbGwgLT0gaW5jcjtcbiAgICAgIHRhYmxlW25leHQgKyAoaHVmZiA+PiBkcm9wKSArIGZpbGxdID0gKGhlcmVfYml0cyA8PCAyNCkgfCAoaGVyZV9vcCA8PCAxNikgfCBoZXJlX3ZhbCB8MDtcbiAgICB9IHdoaWxlIChmaWxsICE9PSAwKTtcblxuICAgIC8qIGJhY2t3YXJkcyBpbmNyZW1lbnQgdGhlIGxlbi1iaXQgY29kZSBodWZmICovXG4gICAgaW5jciA9IDEgPDwgKGxlbiAtIDEpO1xuICAgIHdoaWxlIChodWZmICYgaW5jcikge1xuICAgICAgaW5jciA+Pj0gMTtcbiAgICB9XG4gICAgaWYgKGluY3IgIT09IDApIHtcbiAgICAgIGh1ZmYgJj0gaW5jciAtIDE7XG4gICAgICBodWZmICs9IGluY3I7XG4gICAgfSBlbHNlIHtcbiAgICAgIGh1ZmYgPSAwO1xuICAgIH1cblxuICAgIC8qIGdvIHRvIG5leHQgc3ltYm9sLCB1cGRhdGUgY291bnQsIGxlbiAqL1xuICAgIHN5bSsrO1xuICAgIGlmICgtLWNvdW50W2xlbl0gPT09IDApIHtcbiAgICAgIGlmIChsZW4gPT09IG1heCkgeyBicmVhazsgfVxuICAgICAgbGVuID0gbGVuc1tsZW5zX2luZGV4ICsgd29ya1tzeW1dXTtcbiAgICB9XG5cbiAgICAvKiBjcmVhdGUgbmV3IHN1Yi10YWJsZSBpZiBuZWVkZWQgKi9cbiAgICBpZiAobGVuID4gcm9vdCAmJiAoaHVmZiAmIG1hc2spICE9PSBsb3cpIHtcbiAgICAgIC8qIGlmIGZpcnN0IHRpbWUsIHRyYW5zaXRpb24gdG8gc3ViLXRhYmxlcyAqL1xuICAgICAgaWYgKGRyb3AgPT09IDApIHtcbiAgICAgICAgZHJvcCA9IHJvb3Q7XG4gICAgICB9XG5cbiAgICAgIC8qIGluY3JlbWVudCBwYXN0IGxhc3QgdGFibGUgKi9cbiAgICAgIG5leHQgKz0gbWluOyAgICAgICAgICAgIC8qIGhlcmUgbWluIGlzIDEgPDwgY3VyciAqL1xuXG4gICAgICAvKiBkZXRlcm1pbmUgbGVuZ3RoIG9mIG5leHQgdGFibGUgKi9cbiAgICAgIGN1cnIgPSBsZW4gLSBkcm9wO1xuICAgICAgbGVmdCA9IDEgPDwgY3VycjtcbiAgICAgIHdoaWxlIChjdXJyICsgZHJvcCA8IG1heCkge1xuICAgICAgICBsZWZ0IC09IGNvdW50W2N1cnIgKyBkcm9wXTtcbiAgICAgICAgaWYgKGxlZnQgPD0gMCkgeyBicmVhazsgfVxuICAgICAgICBjdXJyKys7XG4gICAgICAgIGxlZnQgPDw9IDE7XG4gICAgICB9XG5cbiAgICAgIC8qIGNoZWNrIGZvciBlbm91Z2ggc3BhY2UgKi9cbiAgICAgIHVzZWQgKz0gMSA8PCBjdXJyO1xuICAgICAgaWYgKCh0eXBlID09PSBMRU5TJDEgJiYgdXNlZCA+IEVOT1VHSF9MRU5TJDEpIHx8XG4gICAgICAgICh0eXBlID09PSBESVNUUyQxICYmIHVzZWQgPiBFTk9VR0hfRElTVFMkMSkpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIC8qIHBvaW50IGVudHJ5IGluIHJvb3QgdGFibGUgdG8gc3ViLXRhYmxlICovXG4gICAgICBsb3cgPSBodWZmICYgbWFzaztcbiAgICAgIC8qdGFibGUub3BbbG93XSA9IGN1cnI7XG4gICAgICB0YWJsZS5iaXRzW2xvd10gPSByb290O1xuICAgICAgdGFibGUudmFsW2xvd10gPSBuZXh0IC0gb3B0cy50YWJsZV9pbmRleDsqL1xuICAgICAgdGFibGVbbG93XSA9IChyb290IDw8IDI0KSB8IChjdXJyIDw8IDE2KSB8IChuZXh0IC0gdGFibGVfaW5kZXgpIHwwO1xuICAgIH1cbiAgfVxuXG4gIC8qIGZpbGwgaW4gcmVtYWluaW5nIHRhYmxlIGVudHJ5IGlmIGNvZGUgaXMgaW5jb21wbGV0ZSAoZ3VhcmFudGVlZCB0byBoYXZlXG4gICBhdCBtb3N0IG9uZSByZW1haW5pbmcgZW50cnksIHNpbmNlIGlmIHRoZSBjb2RlIGlzIGluY29tcGxldGUsIHRoZVxuICAgbWF4aW11bSBjb2RlIGxlbmd0aCB0aGF0IHdhcyBhbGxvd2VkIHRvIGdldCB0aGlzIGZhciBpcyBvbmUgYml0KSAqL1xuICBpZiAoaHVmZiAhPT0gMCkge1xuICAgIC8vdGFibGUub3BbbmV4dCArIGh1ZmZdID0gNjQ7ICAgICAgICAgICAgLyogaW52YWxpZCBjb2RlIG1hcmtlciAqL1xuICAgIC8vdGFibGUuYml0c1tuZXh0ICsgaHVmZl0gPSBsZW4gLSBkcm9wO1xuICAgIC8vdGFibGUudmFsW25leHQgKyBodWZmXSA9IDA7XG4gICAgdGFibGVbbmV4dCArIGh1ZmZdID0gKChsZW4gLSBkcm9wKSA8PCAyNCkgfCAoNjQgPDwgMTYpIHwwO1xuICB9XG5cbiAgLyogc2V0IHJldHVybiBwYXJhbWV0ZXJzICovXG4gIC8vb3B0cy50YWJsZV9pbmRleCArPSB1c2VkO1xuICBvcHRzLmJpdHMgPSByb290O1xuICByZXR1cm4gMDtcbn07XG5cblxudmFyIGluZnRyZWVzID0gaW5mbGF0ZV90YWJsZTtcblxuLy8gKEMpIDE5OTUtMjAxMyBKZWFuLWxvdXAgR2FpbGx5IGFuZCBNYXJrIEFkbGVyXG4vLyAoQykgMjAxNC0yMDE3IFZpdGFseSBQdXpyaW4gYW5kIEFuZHJleSBUdXBpdHNpblxuLy9cbi8vIFRoaXMgc29mdHdhcmUgaXMgcHJvdmlkZWQgJ2FzLWlzJywgd2l0aG91dCBhbnkgZXhwcmVzcyBvciBpbXBsaWVkXG4vLyB3YXJyYW50eS4gSW4gbm8gZXZlbnQgd2lsbCB0aGUgYXV0aG9ycyBiZSBoZWxkIGxpYWJsZSBmb3IgYW55IGRhbWFnZXNcbi8vIGFyaXNpbmcgZnJvbSB0aGUgdXNlIG9mIHRoaXMgc29mdHdhcmUuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBncmFudGVkIHRvIGFueW9uZSB0byB1c2UgdGhpcyBzb2Z0d2FyZSBmb3IgYW55IHB1cnBvc2UsXG4vLyBpbmNsdWRpbmcgY29tbWVyY2lhbCBhcHBsaWNhdGlvbnMsIGFuZCB0byBhbHRlciBpdCBhbmQgcmVkaXN0cmlidXRlIGl0XG4vLyBmcmVlbHksIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyByZXN0cmljdGlvbnM6XG4vL1xuLy8gMS4gVGhlIG9yaWdpbiBvZiB0aGlzIHNvZnR3YXJlIG11c3Qgbm90IGJlIG1pc3JlcHJlc2VudGVkOyB5b3UgbXVzdCBub3Rcbi8vICAgY2xhaW0gdGhhdCB5b3Ugd3JvdGUgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLiBJZiB5b3UgdXNlIHRoaXMgc29mdHdhcmVcbi8vICAgaW4gYSBwcm9kdWN0LCBhbiBhY2tub3dsZWRnbWVudCBpbiB0aGUgcHJvZHVjdCBkb2N1bWVudGF0aW9uIHdvdWxkIGJlXG4vLyAgIGFwcHJlY2lhdGVkIGJ1dCBpcyBub3QgcmVxdWlyZWQuXG4vLyAyLiBBbHRlcmVkIHNvdXJjZSB2ZXJzaW9ucyBtdXN0IGJlIHBsYWlubHkgbWFya2VkIGFzIHN1Y2gsIGFuZCBtdXN0IG5vdCBiZVxuLy8gICBtaXNyZXByZXNlbnRlZCBhcyBiZWluZyB0aGUgb3JpZ2luYWwgc29mdHdhcmUuXG4vLyAzLiBUaGlzIG5vdGljZSBtYXkgbm90IGJlIHJlbW92ZWQgb3IgYWx0ZXJlZCBmcm9tIGFueSBzb3VyY2UgZGlzdHJpYnV0aW9uLlxuXG5cblxuXG5cblxuY29uc3QgQ09ERVMgPSAwO1xuY29uc3QgTEVOUyA9IDE7XG5jb25zdCBESVNUUyA9IDI7XG5cbi8qIFB1YmxpYyBjb25zdGFudHMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qL1xuXG5jb25zdCB7XG4gIFpfRklOSVNIOiBaX0ZJTklTSCQxLCBaX0JMT0NLLCBaX1RSRUVTLFxuICBaX09LOiBaX09LJDEsIFpfU1RSRUFNX0VORDogWl9TVFJFQU1fRU5EJDEsIFpfTkVFRF9ESUNUOiBaX05FRURfRElDVCQxLCBaX1NUUkVBTV9FUlJPUjogWl9TVFJFQU1fRVJST1IkMSwgWl9EQVRBX0VSUk9SOiBaX0RBVEFfRVJST1IkMSwgWl9NRU1fRVJST1I6IFpfTUVNX0VSUk9SJDEsIFpfQlVGX0VSUk9SLFxuICBaX0RFRkxBVEVEXG59ID0gY29uc3RhbnRzJDI7XG5cblxuLyogU1RBVEVTID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki9cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovXG5cblxuY29uc3QgICAgSEVBRCA9IDE2MTgwOyAgICAgICAvKiBpOiB3YWl0aW5nIGZvciBtYWdpYyBoZWFkZXIgKi9cbmNvbnN0ICAgIEZMQUdTID0gMTYxODE7ICAgICAgLyogaTogd2FpdGluZyBmb3IgbWV0aG9kIGFuZCBmbGFncyAoZ3ppcCkgKi9cbmNvbnN0ICAgIFRJTUUgPSAxNjE4MjsgICAgICAgLyogaTogd2FpdGluZyBmb3IgbW9kaWZpY2F0aW9uIHRpbWUgKGd6aXApICovXG5jb25zdCAgICBPUyA9IDE2MTgzOyAgICAgICAgIC8qIGk6IHdhaXRpbmcgZm9yIGV4dHJhIGZsYWdzIGFuZCBvcGVyYXRpbmcgc3lzdGVtIChnemlwKSAqL1xuY29uc3QgICAgRVhMRU4gPSAxNjE4NDsgICAgICAvKiBpOiB3YWl0aW5nIGZvciBleHRyYSBsZW5ndGggKGd6aXApICovXG5jb25zdCAgICBFWFRSQSA9IDE2MTg1OyAgICAgIC8qIGk6IHdhaXRpbmcgZm9yIGV4dHJhIGJ5dGVzIChnemlwKSAqL1xuY29uc3QgICAgTkFNRSA9IDE2MTg2OyAgICAgICAvKiBpOiB3YWl0aW5nIGZvciBlbmQgb2YgZmlsZSBuYW1lIChnemlwKSAqL1xuY29uc3QgICAgQ09NTUVOVCA9IDE2MTg3OyAgICAvKiBpOiB3YWl0aW5nIGZvciBlbmQgb2YgY29tbWVudCAoZ3ppcCkgKi9cbmNvbnN0ICAgIEhDUkMgPSAxNjE4ODsgICAgICAgLyogaTogd2FpdGluZyBmb3IgaGVhZGVyIGNyYyAoZ3ppcCkgKi9cbmNvbnN0ICAgIERJQ1RJRCA9IDE2MTg5OyAgICAvKiBpOiB3YWl0aW5nIGZvciBkaWN0aW9uYXJ5IGNoZWNrIHZhbHVlICovXG5jb25zdCAgICBESUNUID0gMTYxOTA7ICAgICAgLyogd2FpdGluZyBmb3IgaW5mbGF0ZVNldERpY3Rpb25hcnkoKSBjYWxsICovXG5jb25zdCAgICAgICAgVFlQRSA9IDE2MTkxOyAgICAgIC8qIGk6IHdhaXRpbmcgZm9yIHR5cGUgYml0cywgaW5jbHVkaW5nIGxhc3QtZmxhZyBiaXQgKi9cbmNvbnN0ICAgICAgICBUWVBFRE8gPSAxNjE5MjsgICAgLyogaTogc2FtZSwgYnV0IHNraXAgY2hlY2sgdG8gZXhpdCBpbmZsYXRlIG9uIG5ldyBibG9jayAqL1xuY29uc3QgICAgICAgIFNUT1JFRCA9IDE2MTkzOyAgICAvKiBpOiB3YWl0aW5nIGZvciBzdG9yZWQgc2l6ZSAobGVuZ3RoIGFuZCBjb21wbGVtZW50KSAqL1xuY29uc3QgICAgICAgIENPUFlfID0gMTYxOTQ7ICAgICAvKiBpL286IHNhbWUgYXMgQ09QWSBiZWxvdywgYnV0IG9ubHkgZmlyc3QgdGltZSBpbiAqL1xuY29uc3QgICAgICAgIENPUFkgPSAxNjE5NTsgICAgICAvKiBpL286IHdhaXRpbmcgZm9yIGlucHV0IG9yIG91dHB1dCB0byBjb3B5IHN0b3JlZCBibG9jayAqL1xuY29uc3QgICAgICAgIFRBQkxFID0gMTYxOTY7ICAgICAvKiBpOiB3YWl0aW5nIGZvciBkeW5hbWljIGJsb2NrIHRhYmxlIGxlbmd0aHMgKi9cbmNvbnN0ICAgICAgICBMRU5MRU5TID0gMTYxOTc7ICAgLyogaTogd2FpdGluZyBmb3IgY29kZSBsZW5ndGggY29kZSBsZW5ndGhzICovXG5jb25zdCAgICAgICAgQ09ERUxFTlMgPSAxNjE5ODsgIC8qIGk6IHdhaXRpbmcgZm9yIGxlbmd0aC9saXQgYW5kIGRpc3RhbmNlIGNvZGUgbGVuZ3RocyAqL1xuY29uc3QgICAgICAgICAgICBMRU5fID0gMTYxOTk7ICAgICAgLyogaTogc2FtZSBhcyBMRU4gYmVsb3csIGJ1dCBvbmx5IGZpcnN0IHRpbWUgaW4gKi9cbmNvbnN0ICAgICAgICAgICAgTEVOID0gMTYyMDA7ICAgICAgIC8qIGk6IHdhaXRpbmcgZm9yIGxlbmd0aC9saXQvZW9iIGNvZGUgKi9cbmNvbnN0ICAgICAgICAgICAgTEVORVhUID0gMTYyMDE7ICAgIC8qIGk6IHdhaXRpbmcgZm9yIGxlbmd0aCBleHRyYSBiaXRzICovXG5jb25zdCAgICAgICAgICAgIERJU1QgPSAxNjIwMjsgICAgICAvKiBpOiB3YWl0aW5nIGZvciBkaXN0YW5jZSBjb2RlICovXG5jb25zdCAgICAgICAgICAgIERJU1RFWFQgPSAxNjIwMzsgICAvKiBpOiB3YWl0aW5nIGZvciBkaXN0YW5jZSBleHRyYSBiaXRzICovXG5jb25zdCAgICAgICAgICAgIE1BVENIID0gMTYyMDQ7ICAgICAvKiBvOiB3YWl0aW5nIGZvciBvdXRwdXQgc3BhY2UgdG8gY29weSBzdHJpbmcgKi9cbmNvbnN0ICAgICAgICAgICAgTElUID0gMTYyMDU7ICAgICAgIC8qIG86IHdhaXRpbmcgZm9yIG91dHB1dCBzcGFjZSB0byB3cml0ZSBsaXRlcmFsICovXG5jb25zdCAgICBDSEVDSyA9IDE2MjA2OyAgICAgLyogaTogd2FpdGluZyBmb3IgMzItYml0IGNoZWNrIHZhbHVlICovXG5jb25zdCAgICBMRU5HVEggPSAxNjIwNzsgICAgLyogaTogd2FpdGluZyBmb3IgMzItYml0IGxlbmd0aCAoZ3ppcCkgKi9cbmNvbnN0ICAgIERPTkUgPSAxNjIwODsgICAgICAvKiBmaW5pc2hlZCBjaGVjaywgZG9uZSAtLSByZW1haW4gaGVyZSB1bnRpbCByZXNldCAqL1xuY29uc3QgICAgQkFEID0gMTYyMDk7ICAgICAgIC8qIGdvdCBhIGRhdGEgZXJyb3IgLS0gcmVtYWluIGhlcmUgdW50aWwgcmVzZXQgKi9cbmNvbnN0ICAgIE1FTSA9IDE2MjEwOyAgICAgICAvKiBnb3QgYW4gaW5mbGF0ZSgpIG1lbW9yeSBlcnJvciAtLSByZW1haW4gaGVyZSB1bnRpbCByZXNldCAqL1xuY29uc3QgICAgU1lOQyA9IDE2MjExOyAgICAgIC8qIGxvb2tpbmcgZm9yIHN5bmNocm9uaXphdGlvbiBieXRlcyB0byByZXN0YXJ0IGluZmxhdGUoKSAqL1xuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qL1xuXG5cblxuY29uc3QgRU5PVUdIX0xFTlMgPSA4NTI7XG5jb25zdCBFTk9VR0hfRElTVFMgPSA1OTI7XG4vL2NvbnN0IEVOT1VHSCA9ICAoRU5PVUdIX0xFTlMrRU5PVUdIX0RJU1RTKTtcblxuY29uc3QgTUFYX1dCSVRTID0gMTU7XG4vKiAzMksgTFo3NyB3aW5kb3cgKi9cbmNvbnN0IERFRl9XQklUUyA9IE1BWF9XQklUUztcblxuXG5jb25zdCB6c3dhcDMyID0gKHEpID0+IHtcblxuICByZXR1cm4gICgoKHEgPj4+IDI0KSAmIDB4ZmYpICtcbiAgICAgICAgICAoKHEgPj4+IDgpICYgMHhmZjAwKSArXG4gICAgICAgICAgKChxICYgMHhmZjAwKSA8PCA4KSArXG4gICAgICAgICAgKChxICYgMHhmZikgPDwgMjQpKTtcbn07XG5cblxuZnVuY3Rpb24gSW5mbGF0ZVN0YXRlKCkge1xuICB0aGlzLnN0cm0gPSBudWxsOyAgICAgICAgICAgLyogcG9pbnRlciBiYWNrIHRvIHRoaXMgemxpYiBzdHJlYW0gKi9cbiAgdGhpcy5tb2RlID0gMDsgICAgICAgICAgICAgIC8qIGN1cnJlbnQgaW5mbGF0ZSBtb2RlICovXG4gIHRoaXMubGFzdCA9IGZhbHNlOyAgICAgICAgICAvKiB0cnVlIGlmIHByb2Nlc3NpbmcgbGFzdCBibG9jayAqL1xuICB0aGlzLndyYXAgPSAwOyAgICAgICAgICAgICAgLyogYml0IDAgdHJ1ZSBmb3IgemxpYiwgYml0IDEgdHJ1ZSBmb3IgZ3ppcCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpdCAyIHRydWUgdG8gdmFsaWRhdGUgY2hlY2sgdmFsdWUgKi9cbiAgdGhpcy5oYXZlZGljdCA9IGZhbHNlOyAgICAgIC8qIHRydWUgaWYgZGljdGlvbmFyeSBwcm92aWRlZCAqL1xuICB0aGlzLmZsYWdzID0gMDsgICAgICAgICAgICAgLyogZ3ppcCBoZWFkZXIgbWV0aG9kIGFuZCBmbGFncyAoMCBpZiB6bGliKSwgb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0xIGlmIHJhdyBvciBubyBoZWFkZXIgeWV0ICovXG4gIHRoaXMuZG1heCA9IDA7ICAgICAgICAgICAgICAvKiB6bGliIGhlYWRlciBtYXggZGlzdGFuY2UgKElORkxBVEVfU1RSSUNUKSAqL1xuICB0aGlzLmNoZWNrID0gMDsgICAgICAgICAgICAgLyogcHJvdGVjdGVkIGNvcHkgb2YgY2hlY2sgdmFsdWUgKi9cbiAgdGhpcy50b3RhbCA9IDA7ICAgICAgICAgICAgIC8qIHByb3RlY3RlZCBjb3B5IG9mIG91dHB1dCBjb3VudCAqL1xuICAvLyBUT0RPOiBtYXkgYmUge31cbiAgdGhpcy5oZWFkID0gbnVsbDsgICAgICAgICAgIC8qIHdoZXJlIHRvIHNhdmUgZ3ppcCBoZWFkZXIgaW5mb3JtYXRpb24gKi9cblxuICAvKiBzbGlkaW5nIHdpbmRvdyAqL1xuICB0aGlzLndiaXRzID0gMDsgICAgICAgICAgICAgLyogbG9nIGJhc2UgMiBvZiByZXF1ZXN0ZWQgd2luZG93IHNpemUgKi9cbiAgdGhpcy53c2l6ZSA9IDA7ICAgICAgICAgICAgIC8qIHdpbmRvdyBzaXplIG9yIHplcm8gaWYgbm90IHVzaW5nIHdpbmRvdyAqL1xuICB0aGlzLndoYXZlID0gMDsgICAgICAgICAgICAgLyogdmFsaWQgYnl0ZXMgaW4gdGhlIHdpbmRvdyAqL1xuICB0aGlzLnduZXh0ID0gMDsgICAgICAgICAgICAgLyogd2luZG93IHdyaXRlIGluZGV4ICovXG4gIHRoaXMud2luZG93ID0gbnVsbDsgICAgICAgICAvKiBhbGxvY2F0ZWQgc2xpZGluZyB3aW5kb3csIGlmIG5lZWRlZCAqL1xuXG4gIC8qIGJpdCBhY2N1bXVsYXRvciAqL1xuICB0aGlzLmhvbGQgPSAwOyAgICAgICAgICAgICAgLyogaW5wdXQgYml0IGFjY3VtdWxhdG9yICovXG4gIHRoaXMuYml0cyA9IDA7ICAgICAgICAgICAgICAvKiBudW1iZXIgb2YgYml0cyBpbiBcImluXCIgKi9cblxuICAvKiBmb3Igc3RyaW5nIGFuZCBzdG9yZWQgYmxvY2sgY29weWluZyAqL1xuICB0aGlzLmxlbmd0aCA9IDA7ICAgICAgICAgICAgLyogbGl0ZXJhbCBvciBsZW5ndGggb2YgZGF0YSB0byBjb3B5ICovXG4gIHRoaXMub2Zmc2V0ID0gMDsgICAgICAgICAgICAvKiBkaXN0YW5jZSBiYWNrIHRvIGNvcHkgc3RyaW5nIGZyb20gKi9cblxuICAvKiBmb3IgdGFibGUgYW5kIGNvZGUgZGVjb2RpbmcgKi9cbiAgdGhpcy5leHRyYSA9IDA7ICAgICAgICAgICAgIC8qIGV4dHJhIGJpdHMgbmVlZGVkICovXG5cbiAgLyogZml4ZWQgYW5kIGR5bmFtaWMgY29kZSB0YWJsZXMgKi9cbiAgdGhpcy5sZW5jb2RlID0gbnVsbDsgICAgICAgICAgLyogc3RhcnRpbmcgdGFibGUgZm9yIGxlbmd0aC9saXRlcmFsIGNvZGVzICovXG4gIHRoaXMuZGlzdGNvZGUgPSBudWxsOyAgICAgICAgIC8qIHN0YXJ0aW5nIHRhYmxlIGZvciBkaXN0YW5jZSBjb2RlcyAqL1xuICB0aGlzLmxlbmJpdHMgPSAwOyAgICAgICAgICAgLyogaW5kZXggYml0cyBmb3IgbGVuY29kZSAqL1xuICB0aGlzLmRpc3RiaXRzID0gMDsgICAgICAgICAgLyogaW5kZXggYml0cyBmb3IgZGlzdGNvZGUgKi9cblxuICAvKiBkeW5hbWljIHRhYmxlIGJ1aWxkaW5nICovXG4gIHRoaXMubmNvZGUgPSAwOyAgICAgICAgICAgICAvKiBudW1iZXIgb2YgY29kZSBsZW5ndGggY29kZSBsZW5ndGhzICovXG4gIHRoaXMubmxlbiA9IDA7ICAgICAgICAgICAgICAvKiBudW1iZXIgb2YgbGVuZ3RoIGNvZGUgbGVuZ3RocyAqL1xuICB0aGlzLm5kaXN0ID0gMDsgICAgICAgICAgICAgLyogbnVtYmVyIG9mIGRpc3RhbmNlIGNvZGUgbGVuZ3RocyAqL1xuICB0aGlzLmhhdmUgPSAwOyAgICAgICAgICAgICAgLyogbnVtYmVyIG9mIGNvZGUgbGVuZ3RocyBpbiBsZW5zW10gKi9cbiAgdGhpcy5uZXh0ID0gbnVsbDsgICAgICAgICAgICAgIC8qIG5leHQgYXZhaWxhYmxlIHNwYWNlIGluIGNvZGVzW10gKi9cblxuICB0aGlzLmxlbnMgPSBuZXcgVWludDE2QXJyYXkoMzIwKTsgLyogdGVtcG9yYXJ5IHN0b3JhZ2UgZm9yIGNvZGUgbGVuZ3RocyAqL1xuICB0aGlzLndvcmsgPSBuZXcgVWludDE2QXJyYXkoMjg4KTsgLyogd29yayBhcmVhIGZvciBjb2RlIHRhYmxlIGJ1aWxkaW5nICovXG5cbiAgLypcbiAgIGJlY2F1c2Ugd2UgZG9uJ3QgaGF2ZSBwb2ludGVycyBpbiBqcywgd2UgdXNlIGxlbmNvZGUgYW5kIGRpc3Rjb2RlIGRpcmVjdGx5XG4gICBhcyBidWZmZXJzIHNvIHdlIGRvbid0IG5lZWQgY29kZXNcbiAgKi9cbiAgLy90aGlzLmNvZGVzID0gbmV3IEludDMyQXJyYXkoRU5PVUdIKTsgICAgICAgLyogc3BhY2UgZm9yIGNvZGUgdGFibGVzICovXG4gIHRoaXMubGVuZHluID0gbnVsbDsgICAgICAgICAgICAgIC8qIGR5bmFtaWMgdGFibGUgZm9yIGxlbmd0aC9saXRlcmFsIGNvZGVzIChKUyBzcGVjaWZpYykgKi9cbiAgdGhpcy5kaXN0ZHluID0gbnVsbDsgICAgICAgICAgICAgLyogZHluYW1pYyB0YWJsZSBmb3IgZGlzdGFuY2UgY29kZXMgKEpTIHNwZWNpZmljKSAqL1xuICB0aGlzLnNhbmUgPSAwOyAgICAgICAgICAgICAgICAgICAvKiBpZiBmYWxzZSwgYWxsb3cgaW52YWxpZCBkaXN0YW5jZSB0b28gZmFyICovXG4gIHRoaXMuYmFjayA9IDA7ICAgICAgICAgICAgICAgICAgIC8qIGJpdHMgYmFjayBvZiBsYXN0IHVucHJvY2Vzc2VkIGxlbmd0aC9saXQgKi9cbiAgdGhpcy53YXMgPSAwOyAgICAgICAgICAgICAgICAgICAgLyogaW5pdGlhbCBsZW5ndGggb2YgbWF0Y2ggKi9cbn1cblxuXG5jb25zdCBpbmZsYXRlU3RhdGVDaGVjayA9IChzdHJtKSA9PiB7XG5cbiAgaWYgKCFzdHJtKSB7XG4gICAgcmV0dXJuIDE7XG4gIH1cbiAgY29uc3Qgc3RhdGUgPSBzdHJtLnN0YXRlO1xuICBpZiAoIXN0YXRlIHx8IHN0YXRlLnN0cm0gIT09IHN0cm0gfHxcbiAgICBzdGF0ZS5tb2RlIDwgSEVBRCB8fCBzdGF0ZS5tb2RlID4gU1lOQykge1xuICAgIHJldHVybiAxO1xuICB9XG4gIHJldHVybiAwO1xufTtcblxuXG5jb25zdCBpbmZsYXRlUmVzZXRLZWVwID0gKHN0cm0pID0+IHtcblxuICBpZiAoaW5mbGF0ZVN0YXRlQ2hlY2soc3RybSkpIHsgcmV0dXJuIFpfU1RSRUFNX0VSUk9SJDE7IH1cbiAgY29uc3Qgc3RhdGUgPSBzdHJtLnN0YXRlO1xuICBzdHJtLnRvdGFsX2luID0gc3RybS50b3RhbF9vdXQgPSBzdGF0ZS50b3RhbCA9IDA7XG4gIHN0cm0ubXNnID0gJyc7IC8qWl9OVUxMKi9cbiAgaWYgKHN0YXRlLndyYXApIHsgICAgICAgLyogdG8gc3VwcG9ydCBpbGwtY29uY2VpdmVkIEphdmEgdGVzdCBzdWl0ZSAqL1xuICAgIHN0cm0uYWRsZXIgPSBzdGF0ZS53cmFwICYgMTtcbiAgfVxuICBzdGF0ZS5tb2RlID0gSEVBRDtcbiAgc3RhdGUubGFzdCA9IDA7XG4gIHN0YXRlLmhhdmVkaWN0ID0gMDtcbiAgc3RhdGUuZmxhZ3MgPSAtMTtcbiAgc3RhdGUuZG1heCA9IDMyNzY4O1xuICBzdGF0ZS5oZWFkID0gbnVsbC8qWl9OVUxMKi87XG4gIHN0YXRlLmhvbGQgPSAwO1xuICBzdGF0ZS5iaXRzID0gMDtcbiAgLy9zdGF0ZS5sZW5jb2RlID0gc3RhdGUuZGlzdGNvZGUgPSBzdGF0ZS5uZXh0ID0gc3RhdGUuY29kZXM7XG4gIHN0YXRlLmxlbmNvZGUgPSBzdGF0ZS5sZW5keW4gPSBuZXcgSW50MzJBcnJheShFTk9VR0hfTEVOUyk7XG4gIHN0YXRlLmRpc3Rjb2RlID0gc3RhdGUuZGlzdGR5biA9IG5ldyBJbnQzMkFycmF5KEVOT1VHSF9ESVNUUyk7XG5cbiAgc3RhdGUuc2FuZSA9IDE7XG4gIHN0YXRlLmJhY2sgPSAtMTtcbiAgLy9UcmFjZXYoKHN0ZGVyciwgXCJpbmZsYXRlOiByZXNldFxcblwiKSk7XG4gIHJldHVybiBaX09LJDE7XG59O1xuXG5cbmNvbnN0IGluZmxhdGVSZXNldCA9IChzdHJtKSA9PiB7XG5cbiAgaWYgKGluZmxhdGVTdGF0ZUNoZWNrKHN0cm0pKSB7IHJldHVybiBaX1NUUkVBTV9FUlJPUiQxOyB9XG4gIGNvbnN0IHN0YXRlID0gc3RybS5zdGF0ZTtcbiAgc3RhdGUud3NpemUgPSAwO1xuICBzdGF0ZS53aGF2ZSA9IDA7XG4gIHN0YXRlLnduZXh0ID0gMDtcbiAgcmV0dXJuIGluZmxhdGVSZXNldEtlZXAoc3RybSk7XG5cbn07XG5cblxuY29uc3QgaW5mbGF0ZVJlc2V0MiA9IChzdHJtLCB3aW5kb3dCaXRzKSA9PiB7XG4gIGxldCB3cmFwO1xuXG4gIC8qIGdldCB0aGUgc3RhdGUgKi9cbiAgaWYgKGluZmxhdGVTdGF0ZUNoZWNrKHN0cm0pKSB7IHJldHVybiBaX1NUUkVBTV9FUlJPUiQxOyB9XG4gIGNvbnN0IHN0YXRlID0gc3RybS5zdGF0ZTtcblxuICAvKiBleHRyYWN0IHdyYXAgcmVxdWVzdCBmcm9tIHdpbmRvd0JpdHMgcGFyYW1ldGVyICovXG4gIGlmICh3aW5kb3dCaXRzIDwgMCkge1xuICAgIHdyYXAgPSAwO1xuICAgIHdpbmRvd0JpdHMgPSAtd2luZG93Qml0cztcbiAgfVxuICBlbHNlIHtcbiAgICB3cmFwID0gKHdpbmRvd0JpdHMgPj4gNCkgKyA1O1xuICAgIGlmICh3aW5kb3dCaXRzIDwgNDgpIHtcbiAgICAgIHdpbmRvd0JpdHMgJj0gMTU7XG4gICAgfVxuICB9XG5cbiAgLyogc2V0IG51bWJlciBvZiB3aW5kb3cgYml0cywgZnJlZSB3aW5kb3cgaWYgZGlmZmVyZW50ICovXG4gIGlmICh3aW5kb3dCaXRzICYmICh3aW5kb3dCaXRzIDwgOCB8fCB3aW5kb3dCaXRzID4gMTUpKSB7XG4gICAgcmV0dXJuIFpfU1RSRUFNX0VSUk9SJDE7XG4gIH1cbiAgaWYgKHN0YXRlLndpbmRvdyAhPT0gbnVsbCAmJiBzdGF0ZS53Yml0cyAhPT0gd2luZG93Qml0cykge1xuICAgIHN0YXRlLndpbmRvdyA9IG51bGw7XG4gIH1cblxuICAvKiB1cGRhdGUgc3RhdGUgYW5kIHJlc2V0IHRoZSByZXN0IG9mIGl0ICovXG4gIHN0YXRlLndyYXAgPSB3cmFwO1xuICBzdGF0ZS53Yml0cyA9IHdpbmRvd0JpdHM7XG4gIHJldHVybiBpbmZsYXRlUmVzZXQoc3RybSk7XG59O1xuXG5cbmNvbnN0IGluZmxhdGVJbml0MiA9IChzdHJtLCB3aW5kb3dCaXRzKSA9PiB7XG5cbiAgaWYgKCFzdHJtKSB7IHJldHVybiBaX1NUUkVBTV9FUlJPUiQxOyB9XG4gIC8vc3RybS5tc2cgPSBaX05VTEw7ICAgICAgICAgICAgICAgICAvKiBpbiBjYXNlIHdlIHJldHVybiBhbiBlcnJvciAqL1xuXG4gIGNvbnN0IHN0YXRlID0gbmV3IEluZmxhdGVTdGF0ZSgpO1xuXG4gIC8vaWYgKHN0YXRlID09PSBaX05VTEwpIHJldHVybiBaX01FTV9FUlJPUjtcbiAgLy9UcmFjZXYoKHN0ZGVyciwgXCJpbmZsYXRlOiBhbGxvY2F0ZWRcXG5cIikpO1xuICBzdHJtLnN0YXRlID0gc3RhdGU7XG4gIHN0YXRlLnN0cm0gPSBzdHJtO1xuICBzdGF0ZS53aW5kb3cgPSBudWxsLypaX05VTEwqLztcbiAgc3RhdGUubW9kZSA9IEhFQUQ7ICAgICAvKiB0byBwYXNzIHN0YXRlIHRlc3QgaW4gaW5mbGF0ZVJlc2V0MigpICovXG4gIGNvbnN0IHJldCA9IGluZmxhdGVSZXNldDIoc3RybSwgd2luZG93Qml0cyk7XG4gIGlmIChyZXQgIT09IFpfT0skMSkge1xuICAgIHN0cm0uc3RhdGUgPSBudWxsLypaX05VTEwqLztcbiAgfVxuICByZXR1cm4gcmV0O1xufTtcblxuXG5jb25zdCBpbmZsYXRlSW5pdCA9IChzdHJtKSA9PiB7XG5cbiAgcmV0dXJuIGluZmxhdGVJbml0MihzdHJtLCBERUZfV0JJVFMpO1xufTtcblxuXG4vKlxuIFJldHVybiBzdGF0ZSB3aXRoIGxlbmd0aCBhbmQgZGlzdGFuY2UgZGVjb2RpbmcgdGFibGVzIGFuZCBpbmRleCBzaXplcyBzZXQgdG9cbiBmaXhlZCBjb2RlIGRlY29kaW5nLiAgTm9ybWFsbHkgdGhpcyByZXR1cm5zIGZpeGVkIHRhYmxlcyBmcm9tIGluZmZpeGVkLmguXG4gSWYgQlVJTERGSVhFRCBpcyBkZWZpbmVkLCB0aGVuIGluc3RlYWQgdGhpcyByb3V0aW5lIGJ1aWxkcyB0aGUgdGFibGVzIHRoZVxuIGZpcnN0IHRpbWUgaXQncyBjYWxsZWQsIGFuZCByZXR1cm5zIHRob3NlIHRhYmxlcyB0aGUgZmlyc3QgdGltZSBhbmRcbiB0aGVyZWFmdGVyLiAgVGhpcyByZWR1Y2VzIHRoZSBzaXplIG9mIHRoZSBjb2RlIGJ5IGFib3V0IDJLIGJ5dGVzLCBpblxuIGV4Y2hhbmdlIGZvciBhIGxpdHRsZSBleGVjdXRpb24gdGltZS4gIEhvd2V2ZXIsIEJVSUxERklYRUQgc2hvdWxkIG5vdCBiZVxuIHVzZWQgZm9yIHRocmVhZGVkIGFwcGxpY2F0aW9ucywgc2luY2UgdGhlIHJld3JpdGluZyBvZiB0aGUgdGFibGVzIGFuZCB2aXJnaW5cbiBtYXkgbm90IGJlIHRocmVhZC1zYWZlLlxuICovXG5sZXQgdmlyZ2luID0gdHJ1ZTtcblxubGV0IGxlbmZpeCwgZGlzdGZpeDsgLy8gV2UgaGF2ZSBubyBwb2ludGVycyBpbiBKUywgc28ga2VlcCB0YWJsZXMgc2VwYXJhdGVcblxuXG5jb25zdCBmaXhlZHRhYmxlcyA9IChzdGF0ZSkgPT4ge1xuXG4gIC8qIGJ1aWxkIGZpeGVkIGh1ZmZtYW4gdGFibGVzIGlmIGZpcnN0IGNhbGwgKG1heSBub3QgYmUgdGhyZWFkIHNhZmUpICovXG4gIGlmICh2aXJnaW4pIHtcbiAgICBsZW5maXggPSBuZXcgSW50MzJBcnJheSg1MTIpO1xuICAgIGRpc3RmaXggPSBuZXcgSW50MzJBcnJheSgzMik7XG5cbiAgICAvKiBsaXRlcmFsL2xlbmd0aCB0YWJsZSAqL1xuICAgIGxldCBzeW0gPSAwO1xuICAgIHdoaWxlIChzeW0gPCAxNDQpIHsgc3RhdGUubGVuc1tzeW0rK10gPSA4OyB9XG4gICAgd2hpbGUgKHN5bSA8IDI1NikgeyBzdGF0ZS5sZW5zW3N5bSsrXSA9IDk7IH1cbiAgICB3aGlsZSAoc3ltIDwgMjgwKSB7IHN0YXRlLmxlbnNbc3ltKytdID0gNzsgfVxuICAgIHdoaWxlIChzeW0gPCAyODgpIHsgc3RhdGUubGVuc1tzeW0rK10gPSA4OyB9XG5cbiAgICBpbmZ0cmVlcyhMRU5TLCAgc3RhdGUubGVucywgMCwgMjg4LCBsZW5maXgsICAgMCwgc3RhdGUud29yaywgeyBiaXRzOiA5IH0pO1xuXG4gICAgLyogZGlzdGFuY2UgdGFibGUgKi9cbiAgICBzeW0gPSAwO1xuICAgIHdoaWxlIChzeW0gPCAzMikgeyBzdGF0ZS5sZW5zW3N5bSsrXSA9IDU7IH1cblxuICAgIGluZnRyZWVzKERJU1RTLCBzdGF0ZS5sZW5zLCAwLCAzMiwgICBkaXN0Zml4LCAwLCBzdGF0ZS53b3JrLCB7IGJpdHM6IDUgfSk7XG5cbiAgICAvKiBkbyB0aGlzIGp1c3Qgb25jZSAqL1xuICAgIHZpcmdpbiA9IGZhbHNlO1xuICB9XG5cbiAgc3RhdGUubGVuY29kZSA9IGxlbmZpeDtcbiAgc3RhdGUubGVuYml0cyA9IDk7XG4gIHN0YXRlLmRpc3Rjb2RlID0gZGlzdGZpeDtcbiAgc3RhdGUuZGlzdGJpdHMgPSA1O1xufTtcblxuXG4vKlxuIFVwZGF0ZSB0aGUgd2luZG93IHdpdGggdGhlIGxhc3Qgd3NpemUgKG5vcm1hbGx5IDMySykgYnl0ZXMgd3JpdHRlbiBiZWZvcmVcbiByZXR1cm5pbmcuICBJZiB3aW5kb3cgZG9lcyBub3QgZXhpc3QgeWV0LCBjcmVhdGUgaXQuICBUaGlzIGlzIG9ubHkgY2FsbGVkXG4gd2hlbiBhIHdpbmRvdyBpcyBhbHJlYWR5IGluIHVzZSwgb3Igd2hlbiBvdXRwdXQgaGFzIGJlZW4gd3JpdHRlbiBkdXJpbmcgdGhpc1xuIGluZmxhdGUgY2FsbCwgYnV0IHRoZSBlbmQgb2YgdGhlIGRlZmxhdGUgc3RyZWFtIGhhcyBub3QgYmVlbiByZWFjaGVkIHlldC5cbiBJdCBpcyBhbHNvIGNhbGxlZCB0byBjcmVhdGUgYSB3aW5kb3cgZm9yIGRpY3Rpb25hcnkgZGF0YSB3aGVuIGEgZGljdGlvbmFyeVxuIGlzIGxvYWRlZC5cblxuIFByb3ZpZGluZyBvdXRwdXQgYnVmZmVycyBsYXJnZXIgdGhhbiAzMksgdG8gaW5mbGF0ZSgpIHNob3VsZCBwcm92aWRlIGEgc3BlZWRcbiBhZHZhbnRhZ2UsIHNpbmNlIG9ubHkgdGhlIGxhc3QgMzJLIG9mIG91dHB1dCBpcyBjb3BpZWQgdG8gdGhlIHNsaWRpbmcgd2luZG93XG4gdXBvbiByZXR1cm4gZnJvbSBpbmZsYXRlKCksIGFuZCBzaW5jZSBhbGwgZGlzdGFuY2VzIGFmdGVyIHRoZSBmaXJzdCAzMksgb2ZcbiBvdXRwdXQgd2lsbCBmYWxsIGluIHRoZSBvdXRwdXQgZGF0YSwgbWFraW5nIG1hdGNoIGNvcGllcyBzaW1wbGVyIGFuZCBmYXN0ZXIuXG4gVGhlIGFkdmFudGFnZSBtYXkgYmUgZGVwZW5kZW50IG9uIHRoZSBzaXplIG9mIHRoZSBwcm9jZXNzb3IncyBkYXRhIGNhY2hlcy5cbiAqL1xuY29uc3QgdXBkYXRld2luZG93ID0gKHN0cm0sIHNyYywgZW5kLCBjb3B5KSA9PiB7XG5cbiAgbGV0IGRpc3Q7XG4gIGNvbnN0IHN0YXRlID0gc3RybS5zdGF0ZTtcblxuICAvKiBpZiBpdCBoYXNuJ3QgYmVlbiBkb25lIGFscmVhZHksIGFsbG9jYXRlIHNwYWNlIGZvciB0aGUgd2luZG93ICovXG4gIGlmIChzdGF0ZS53aW5kb3cgPT09IG51bGwpIHtcbiAgICBzdGF0ZS53c2l6ZSA9IDEgPDwgc3RhdGUud2JpdHM7XG4gICAgc3RhdGUud25leHQgPSAwO1xuICAgIHN0YXRlLndoYXZlID0gMDtcblxuICAgIHN0YXRlLndpbmRvdyA9IG5ldyBVaW50OEFycmF5KHN0YXRlLndzaXplKTtcbiAgfVxuXG4gIC8qIGNvcHkgc3RhdGUtPndzaXplIG9yIGxlc3Mgb3V0cHV0IGJ5dGVzIGludG8gdGhlIGNpcmN1bGFyIHdpbmRvdyAqL1xuICBpZiAoY29weSA+PSBzdGF0ZS53c2l6ZSkge1xuICAgIHN0YXRlLndpbmRvdy5zZXQoc3JjLnN1YmFycmF5KGVuZCAtIHN0YXRlLndzaXplLCBlbmQpLCAwKTtcbiAgICBzdGF0ZS53bmV4dCA9IDA7XG4gICAgc3RhdGUud2hhdmUgPSBzdGF0ZS53c2l6ZTtcbiAgfVxuICBlbHNlIHtcbiAgICBkaXN0ID0gc3RhdGUud3NpemUgLSBzdGF0ZS53bmV4dDtcbiAgICBpZiAoZGlzdCA+IGNvcHkpIHtcbiAgICAgIGRpc3QgPSBjb3B5O1xuICAgIH1cbiAgICAvL3ptZW1jcHkoc3RhdGUtPndpbmRvdyArIHN0YXRlLT53bmV4dCwgZW5kIC0gY29weSwgZGlzdCk7XG4gICAgc3RhdGUud2luZG93LnNldChzcmMuc3ViYXJyYXkoZW5kIC0gY29weSwgZW5kIC0gY29weSArIGRpc3QpLCBzdGF0ZS53bmV4dCk7XG4gICAgY29weSAtPSBkaXN0O1xuICAgIGlmIChjb3B5KSB7XG4gICAgICAvL3ptZW1jcHkoc3RhdGUtPndpbmRvdywgZW5kIC0gY29weSwgY29weSk7XG4gICAgICBzdGF0ZS53aW5kb3cuc2V0KHNyYy5zdWJhcnJheShlbmQgLSBjb3B5LCBlbmQpLCAwKTtcbiAgICAgIHN0YXRlLnduZXh0ID0gY29weTtcbiAgICAgIHN0YXRlLndoYXZlID0gc3RhdGUud3NpemU7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgc3RhdGUud25leHQgKz0gZGlzdDtcbiAgICAgIGlmIChzdGF0ZS53bmV4dCA9PT0gc3RhdGUud3NpemUpIHsgc3RhdGUud25leHQgPSAwOyB9XG4gICAgICBpZiAoc3RhdGUud2hhdmUgPCBzdGF0ZS53c2l6ZSkgeyBzdGF0ZS53aGF2ZSArPSBkaXN0OyB9XG4gICAgfVxuICB9XG4gIHJldHVybiAwO1xufTtcblxuXG5jb25zdCBpbmZsYXRlJDIgPSAoc3RybSwgZmx1c2gpID0+IHtcblxuICBsZXQgc3RhdGU7XG4gIGxldCBpbnB1dCwgb3V0cHV0OyAgICAgICAgICAvLyBpbnB1dC9vdXRwdXQgYnVmZmVyc1xuICBsZXQgbmV4dDsgICAgICAgICAgICAgICAgICAgLyogbmV4dCBpbnB1dCBJTkRFWCAqL1xuICBsZXQgcHV0OyAgICAgICAgICAgICAgICAgICAgLyogbmV4dCBvdXRwdXQgSU5ERVggKi9cbiAgbGV0IGhhdmUsIGxlZnQ7ICAgICAgICAgICAgIC8qIGF2YWlsYWJsZSBpbnB1dCBhbmQgb3V0cHV0ICovXG4gIGxldCBob2xkOyAgICAgICAgICAgICAgICAgICAvKiBiaXQgYnVmZmVyICovXG4gIGxldCBiaXRzOyAgICAgICAgICAgICAgICAgICAvKiBiaXRzIGluIGJpdCBidWZmZXIgKi9cbiAgbGV0IF9pbiwgX291dDsgICAgICAgICAgICAgIC8qIHNhdmUgc3RhcnRpbmcgYXZhaWxhYmxlIGlucHV0IGFuZCBvdXRwdXQgKi9cbiAgbGV0IGNvcHk7ICAgICAgICAgICAgICAgICAgIC8qIG51bWJlciBvZiBzdG9yZWQgb3IgbWF0Y2ggYnl0ZXMgdG8gY29weSAqL1xuICBsZXQgZnJvbTsgICAgICAgICAgICAgICAgICAgLyogd2hlcmUgdG8gY29weSBtYXRjaCBieXRlcyBmcm9tICovXG4gIGxldCBmcm9tX3NvdXJjZTtcbiAgbGV0IGhlcmUgPSAwOyAgICAgICAgICAgICAgIC8qIGN1cnJlbnQgZGVjb2RpbmcgdGFibGUgZW50cnkgKi9cbiAgbGV0IGhlcmVfYml0cywgaGVyZV9vcCwgaGVyZV92YWw7IC8vIHBha2VkIFwiaGVyZVwiIGRlbm9ybWFsaXplZCAoSlMgc3BlY2lmaWMpXG4gIC8vbGV0IGxhc3Q7ICAgICAgICAgICAgICAgICAgIC8qIHBhcmVudCB0YWJsZSBlbnRyeSAqL1xuICBsZXQgbGFzdF9iaXRzLCBsYXN0X29wLCBsYXN0X3ZhbDsgLy8gcGFrZWQgXCJsYXN0XCIgZGVub3JtYWxpemVkIChKUyBzcGVjaWZpYylcbiAgbGV0IGxlbjsgICAgICAgICAgICAgICAgICAgIC8qIGxlbmd0aCB0byBjb3B5IGZvciByZXBlYXRzLCBiaXRzIHRvIGRyb3AgKi9cbiAgbGV0IHJldDsgICAgICAgICAgICAgICAgICAgIC8qIHJldHVybiBjb2RlICovXG4gIGNvbnN0IGhidWYgPSBuZXcgVWludDhBcnJheSg0KTsgICAgLyogYnVmZmVyIGZvciBnemlwIGhlYWRlciBjcmMgY2FsY3VsYXRpb24gKi9cbiAgbGV0IG9wdHM7XG5cbiAgbGV0IG47IC8vIHRlbXBvcmFyeSB2YXJpYWJsZSBmb3IgTkVFRF9CSVRTXG5cbiAgY29uc3Qgb3JkZXIgPSAvKiBwZXJtdXRhdGlvbiBvZiBjb2RlIGxlbmd0aHMgKi9cbiAgICBuZXcgVWludDhBcnJheShbIDE2LCAxNywgMTgsIDAsIDgsIDcsIDksIDYsIDEwLCA1LCAxMSwgNCwgMTIsIDMsIDEzLCAyLCAxNCwgMSwgMTUgXSk7XG5cblxuICBpZiAoaW5mbGF0ZVN0YXRlQ2hlY2soc3RybSkgfHwgIXN0cm0ub3V0cHV0IHx8XG4gICAgICAoIXN0cm0uaW5wdXQgJiYgc3RybS5hdmFpbF9pbiAhPT0gMCkpIHtcbiAgICByZXR1cm4gWl9TVFJFQU1fRVJST1IkMTtcbiAgfVxuXG4gIHN0YXRlID0gc3RybS5zdGF0ZTtcbiAgaWYgKHN0YXRlLm1vZGUgPT09IFRZUEUpIHsgc3RhdGUubW9kZSA9IFRZUEVETzsgfSAgICAvKiBza2lwIGNoZWNrICovXG5cblxuICAvLy0tLSBMT0FEKCkgLS0tXG4gIHB1dCA9IHN0cm0ubmV4dF9vdXQ7XG4gIG91dHB1dCA9IHN0cm0ub3V0cHV0O1xuICBsZWZ0ID0gc3RybS5hdmFpbF9vdXQ7XG4gIG5leHQgPSBzdHJtLm5leHRfaW47XG4gIGlucHV0ID0gc3RybS5pbnB1dDtcbiAgaGF2ZSA9IHN0cm0uYXZhaWxfaW47XG4gIGhvbGQgPSBzdGF0ZS5ob2xkO1xuICBiaXRzID0gc3RhdGUuYml0cztcbiAgLy8tLS1cblxuICBfaW4gPSBoYXZlO1xuICBfb3V0ID0gbGVmdDtcbiAgcmV0ID0gWl9PSyQxO1xuXG4gIGluZl9sZWF2ZTogLy8gZ290byBlbXVsYXRpb25cbiAgZm9yICg7Oykge1xuICAgIHN3aXRjaCAoc3RhdGUubW9kZSkge1xuICAgICAgY2FzZSBIRUFEOlxuICAgICAgICBpZiAoc3RhdGUud3JhcCA9PT0gMCkge1xuICAgICAgICAgIHN0YXRlLm1vZGUgPSBUWVBFRE87XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgLy89PT0gTkVFREJJVFMoMTYpO1xuICAgICAgICB3aGlsZSAoYml0cyA8IDE2KSB7XG4gICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgaGF2ZS0tO1xuICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgfVxuICAgICAgICAvLz09PS8vXG4gICAgICAgIGlmICgoc3RhdGUud3JhcCAmIDIpICYmIGhvbGQgPT09IDB4OGIxZikgeyAgLyogZ3ppcCBoZWFkZXIgKi9cbiAgICAgICAgICBpZiAoc3RhdGUud2JpdHMgPT09IDApIHtcbiAgICAgICAgICAgIHN0YXRlLndiaXRzID0gMTU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHN0YXRlLmNoZWNrID0gMC8qY3JjMzIoMEwsIFpfTlVMTCwgMCkqLztcbiAgICAgICAgICAvLz09PSBDUkMyKHN0YXRlLmNoZWNrLCBob2xkKTtcbiAgICAgICAgICBoYnVmWzBdID0gaG9sZCAmIDB4ZmY7XG4gICAgICAgICAgaGJ1ZlsxXSA9IChob2xkID4+PiA4KSAmIDB4ZmY7XG4gICAgICAgICAgc3RhdGUuY2hlY2sgPSBjcmMzMl8xKHN0YXRlLmNoZWNrLCBoYnVmLCAyLCAwKTtcbiAgICAgICAgICAvLz09PS8vXG5cbiAgICAgICAgICAvLz09PSBJTklUQklUUygpO1xuICAgICAgICAgIGhvbGQgPSAwO1xuICAgICAgICAgIGJpdHMgPSAwO1xuICAgICAgICAgIC8vPT09Ly9cbiAgICAgICAgICBzdGF0ZS5tb2RlID0gRkxBR1M7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0YXRlLmhlYWQpIHtcbiAgICAgICAgICBzdGF0ZS5oZWFkLmRvbmUgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIShzdGF0ZS53cmFwICYgMSkgfHwgICAvKiBjaGVjayBpZiB6bGliIGhlYWRlciBhbGxvd2VkICovXG4gICAgICAgICAgKCgoaG9sZCAmIDB4ZmYpLypCSVRTKDgpKi8gPDwgOCkgKyAoaG9sZCA+PiA4KSkgJSAzMSkge1xuICAgICAgICAgIHN0cm0ubXNnID0gJ2luY29ycmVjdCBoZWFkZXIgY2hlY2snO1xuICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChob2xkICYgMHgwZikvKkJJVFMoNCkqLyAhPT0gWl9ERUZMQVRFRCkge1xuICAgICAgICAgIHN0cm0ubXNnID0gJ3Vua25vd24gY29tcHJlc3Npb24gbWV0aG9kJztcbiAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIC8vLS0tIERST1BCSVRTKDQpIC0tLS8vXG4gICAgICAgIGhvbGQgPj4+PSA0O1xuICAgICAgICBiaXRzIC09IDQ7XG4gICAgICAgIC8vLS0tLy9cbiAgICAgICAgbGVuID0gKGhvbGQgJiAweDBmKS8qQklUUyg0KSovICsgODtcbiAgICAgICAgaWYgKHN0YXRlLndiaXRzID09PSAwKSB7XG4gICAgICAgICAgc3RhdGUud2JpdHMgPSBsZW47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGxlbiA+IDE1IHx8IGxlbiA+IHN0YXRlLndiaXRzKSB7XG4gICAgICAgICAgc3RybS5tc2cgPSAnaW52YWxpZCB3aW5kb3cgc2l6ZSc7XG4gICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vICEhISBwYWtvIHBhdGNoLiBGb3JjZSB1c2UgYG9wdGlvbnMud2luZG93Qml0c2AgaWYgcGFzc2VkLlxuICAgICAgICAvLyBSZXF1aXJlZCB0byBhbHdheXMgdXNlIG1heCB3aW5kb3cgc2l6ZSBieSBkZWZhdWx0LlxuICAgICAgICBzdGF0ZS5kbWF4ID0gMSA8PCBzdGF0ZS53Yml0cztcbiAgICAgICAgLy9zdGF0ZS5kbWF4ID0gMSA8PCBsZW47XG5cbiAgICAgICAgc3RhdGUuZmxhZ3MgPSAwOyAgICAgICAgICAgICAgIC8qIGluZGljYXRlIHpsaWIgaGVhZGVyICovXG4gICAgICAgIC8vVHJhY2V2KChzdGRlcnIsIFwiaW5mbGF0ZTogICB6bGliIGhlYWRlciBva1xcblwiKSk7XG4gICAgICAgIHN0cm0uYWRsZXIgPSBzdGF0ZS5jaGVjayA9IDEvKmFkbGVyMzIoMEwsIFpfTlVMTCwgMCkqLztcbiAgICAgICAgc3RhdGUubW9kZSA9IGhvbGQgJiAweDIwMCA/IERJQ1RJRCA6IFRZUEU7XG4gICAgICAgIC8vPT09IElOSVRCSVRTKCk7XG4gICAgICAgIGhvbGQgPSAwO1xuICAgICAgICBiaXRzID0gMDtcbiAgICAgICAgLy89PT0vL1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgRkxBR1M6XG4gICAgICAgIC8vPT09IE5FRURCSVRTKDE2KTsgKi9cbiAgICAgICAgd2hpbGUgKGJpdHMgPCAxNikge1xuICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgIH1cbiAgICAgICAgLy89PT0vL1xuICAgICAgICBzdGF0ZS5mbGFncyA9IGhvbGQ7XG4gICAgICAgIGlmICgoc3RhdGUuZmxhZ3MgJiAweGZmKSAhPT0gWl9ERUZMQVRFRCkge1xuICAgICAgICAgIHN0cm0ubXNnID0gJ3Vua25vd24gY29tcHJlc3Npb24gbWV0aG9kJztcbiAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdGF0ZS5mbGFncyAmIDB4ZTAwMCkge1xuICAgICAgICAgIHN0cm0ubXNnID0gJ3Vua25vd24gaGVhZGVyIGZsYWdzIHNldCc7XG4gICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZiAoc3RhdGUuaGVhZCkge1xuICAgICAgICAgIHN0YXRlLmhlYWQudGV4dCA9ICgoaG9sZCA+PiA4KSAmIDEpO1xuICAgICAgICB9XG4gICAgICAgIGlmICgoc3RhdGUuZmxhZ3MgJiAweDAyMDApICYmIChzdGF0ZS53cmFwICYgNCkpIHtcbiAgICAgICAgICAvLz09PSBDUkMyKHN0YXRlLmNoZWNrLCBob2xkKTtcbiAgICAgICAgICBoYnVmWzBdID0gaG9sZCAmIDB4ZmY7XG4gICAgICAgICAgaGJ1ZlsxXSA9IChob2xkID4+PiA4KSAmIDB4ZmY7XG4gICAgICAgICAgc3RhdGUuY2hlY2sgPSBjcmMzMl8xKHN0YXRlLmNoZWNrLCBoYnVmLCAyLCAwKTtcbiAgICAgICAgICAvLz09PS8vXG4gICAgICAgIH1cbiAgICAgICAgLy89PT0gSU5JVEJJVFMoKTtcbiAgICAgICAgaG9sZCA9IDA7XG4gICAgICAgIGJpdHMgPSAwO1xuICAgICAgICAvLz09PS8vXG4gICAgICAgIHN0YXRlLm1vZGUgPSBUSU1FO1xuICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICBjYXNlIFRJTUU6XG4gICAgICAgIC8vPT09IE5FRURCSVRTKDMyKTsgKi9cbiAgICAgICAgd2hpbGUgKGJpdHMgPCAzMikge1xuICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgIH1cbiAgICAgICAgLy89PT0vL1xuICAgICAgICBpZiAoc3RhdGUuaGVhZCkge1xuICAgICAgICAgIHN0YXRlLmhlYWQudGltZSA9IGhvbGQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChzdGF0ZS5mbGFncyAmIDB4MDIwMCkgJiYgKHN0YXRlLndyYXAgJiA0KSkge1xuICAgICAgICAgIC8vPT09IENSQzQoc3RhdGUuY2hlY2ssIGhvbGQpXG4gICAgICAgICAgaGJ1ZlswXSA9IGhvbGQgJiAweGZmO1xuICAgICAgICAgIGhidWZbMV0gPSAoaG9sZCA+Pj4gOCkgJiAweGZmO1xuICAgICAgICAgIGhidWZbMl0gPSAoaG9sZCA+Pj4gMTYpICYgMHhmZjtcbiAgICAgICAgICBoYnVmWzNdID0gKGhvbGQgPj4+IDI0KSAmIDB4ZmY7XG4gICAgICAgICAgc3RhdGUuY2hlY2sgPSBjcmMzMl8xKHN0YXRlLmNoZWNrLCBoYnVmLCA0LCAwKTtcbiAgICAgICAgICAvLz09PVxuICAgICAgICB9XG4gICAgICAgIC8vPT09IElOSVRCSVRTKCk7XG4gICAgICAgIGhvbGQgPSAwO1xuICAgICAgICBiaXRzID0gMDtcbiAgICAgICAgLy89PT0vL1xuICAgICAgICBzdGF0ZS5tb2RlID0gT1M7XG4gICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgIGNhc2UgT1M6XG4gICAgICAgIC8vPT09IE5FRURCSVRTKDE2KTsgKi9cbiAgICAgICAgd2hpbGUgKGJpdHMgPCAxNikge1xuICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgIH1cbiAgICAgICAgLy89PT0vL1xuICAgICAgICBpZiAoc3RhdGUuaGVhZCkge1xuICAgICAgICAgIHN0YXRlLmhlYWQueGZsYWdzID0gKGhvbGQgJiAweGZmKTtcbiAgICAgICAgICBzdGF0ZS5oZWFkLm9zID0gKGhvbGQgPj4gOCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChzdGF0ZS5mbGFncyAmIDB4MDIwMCkgJiYgKHN0YXRlLndyYXAgJiA0KSkge1xuICAgICAgICAgIC8vPT09IENSQzIoc3RhdGUuY2hlY2ssIGhvbGQpO1xuICAgICAgICAgIGhidWZbMF0gPSBob2xkICYgMHhmZjtcbiAgICAgICAgICBoYnVmWzFdID0gKGhvbGQgPj4+IDgpICYgMHhmZjtcbiAgICAgICAgICBzdGF0ZS5jaGVjayA9IGNyYzMyXzEoc3RhdGUuY2hlY2ssIGhidWYsIDIsIDApO1xuICAgICAgICAgIC8vPT09Ly9cbiAgICAgICAgfVxuICAgICAgICAvLz09PSBJTklUQklUUygpO1xuICAgICAgICBob2xkID0gMDtcbiAgICAgICAgYml0cyA9IDA7XG4gICAgICAgIC8vPT09Ly9cbiAgICAgICAgc3RhdGUubW9kZSA9IEVYTEVOO1xuICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICBjYXNlIEVYTEVOOlxuICAgICAgICBpZiAoc3RhdGUuZmxhZ3MgJiAweDA0MDApIHtcbiAgICAgICAgICAvLz09PSBORUVEQklUUygxNik7ICovXG4gICAgICAgICAgd2hpbGUgKGJpdHMgPCAxNikge1xuICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgICBoYXZlLS07XG4gICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy89PT0vL1xuICAgICAgICAgIHN0YXRlLmxlbmd0aCA9IGhvbGQ7XG4gICAgICAgICAgaWYgKHN0YXRlLmhlYWQpIHtcbiAgICAgICAgICAgIHN0YXRlLmhlYWQuZXh0cmFfbGVuID0gaG9sZDtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKChzdGF0ZS5mbGFncyAmIDB4MDIwMCkgJiYgKHN0YXRlLndyYXAgJiA0KSkge1xuICAgICAgICAgICAgLy89PT0gQ1JDMihzdGF0ZS5jaGVjaywgaG9sZCk7XG4gICAgICAgICAgICBoYnVmWzBdID0gaG9sZCAmIDB4ZmY7XG4gICAgICAgICAgICBoYnVmWzFdID0gKGhvbGQgPj4+IDgpICYgMHhmZjtcbiAgICAgICAgICAgIHN0YXRlLmNoZWNrID0gY3JjMzJfMShzdGF0ZS5jaGVjaywgaGJ1ZiwgMiwgMCk7XG4gICAgICAgICAgICAvLz09PS8vXG4gICAgICAgICAgfVxuICAgICAgICAgIC8vPT09IElOSVRCSVRTKCk7XG4gICAgICAgICAgaG9sZCA9IDA7XG4gICAgICAgICAgYml0cyA9IDA7XG4gICAgICAgICAgLy89PT0vL1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHN0YXRlLmhlYWQpIHtcbiAgICAgICAgICBzdGF0ZS5oZWFkLmV4dHJhID0gbnVsbC8qWl9OVUxMKi87XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGUubW9kZSA9IEVYVFJBO1xuICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICBjYXNlIEVYVFJBOlxuICAgICAgICBpZiAoc3RhdGUuZmxhZ3MgJiAweDA0MDApIHtcbiAgICAgICAgICBjb3B5ID0gc3RhdGUubGVuZ3RoO1xuICAgICAgICAgIGlmIChjb3B5ID4gaGF2ZSkgeyBjb3B5ID0gaGF2ZTsgfVxuICAgICAgICAgIGlmIChjb3B5KSB7XG4gICAgICAgICAgICBpZiAoc3RhdGUuaGVhZCkge1xuICAgICAgICAgICAgICBsZW4gPSBzdGF0ZS5oZWFkLmV4dHJhX2xlbiAtIHN0YXRlLmxlbmd0aDtcbiAgICAgICAgICAgICAgaWYgKCFzdGF0ZS5oZWFkLmV4dHJhKSB7XG4gICAgICAgICAgICAgICAgLy8gVXNlIHVudHlwZWQgYXJyYXkgZm9yIG1vcmUgY29udmVuaWVudCBwcm9jZXNzaW5nIGxhdGVyXG4gICAgICAgICAgICAgICAgc3RhdGUuaGVhZC5leHRyYSA9IG5ldyBVaW50OEFycmF5KHN0YXRlLmhlYWQuZXh0cmFfbGVuKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBzdGF0ZS5oZWFkLmV4dHJhLnNldChcbiAgICAgICAgICAgICAgICBpbnB1dC5zdWJhcnJheShcbiAgICAgICAgICAgICAgICAgIG5leHQsXG4gICAgICAgICAgICAgICAgICAvLyBleHRyYSBmaWVsZCBpcyBsaW1pdGVkIHRvIDY1NTM2IGJ5dGVzXG4gICAgICAgICAgICAgICAgICAvLyAtIG5vIG5lZWQgZm9yIGFkZGl0aW9uYWwgc2l6ZSBjaGVja1xuICAgICAgICAgICAgICAgICAgbmV4dCArIGNvcHlcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIC8qbGVuICsgY29weSA+IHN0YXRlLmhlYWQuZXh0cmFfbWF4IC0gbGVuID8gc3RhdGUuaGVhZC5leHRyYV9tYXggOiBjb3B5LCovXG4gICAgICAgICAgICAgICAgbGVuXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIC8vem1lbWNweShzdGF0ZS5oZWFkLmV4dHJhICsgbGVuLCBuZXh0LFxuICAgICAgICAgICAgICAvLyAgICAgICAgbGVuICsgY29weSA+IHN0YXRlLmhlYWQuZXh0cmFfbWF4ID9cbiAgICAgICAgICAgICAgLy8gICAgICAgIHN0YXRlLmhlYWQuZXh0cmFfbWF4IC0gbGVuIDogY29weSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoKHN0YXRlLmZsYWdzICYgMHgwMjAwKSAmJiAoc3RhdGUud3JhcCAmIDQpKSB7XG4gICAgICAgICAgICAgIHN0YXRlLmNoZWNrID0gY3JjMzJfMShzdGF0ZS5jaGVjaywgaW5wdXQsIGNvcHksIG5leHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaGF2ZSAtPSBjb3B5O1xuICAgICAgICAgICAgbmV4dCArPSBjb3B5O1xuICAgICAgICAgICAgc3RhdGUubGVuZ3RoIC09IGNvcHk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzdGF0ZS5sZW5ndGgpIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGUubGVuZ3RoID0gMDtcbiAgICAgICAgc3RhdGUubW9kZSA9IE5BTUU7XG4gICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgIGNhc2UgTkFNRTpcbiAgICAgICAgaWYgKHN0YXRlLmZsYWdzICYgMHgwODAwKSB7XG4gICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgY29weSA9IDA7XG4gICAgICAgICAgZG8ge1xuICAgICAgICAgICAgLy8gVE9ETzogMiBvciAxIGJ5dGVzP1xuICAgICAgICAgICAgbGVuID0gaW5wdXRbbmV4dCArIGNvcHkrK107XG4gICAgICAgICAgICAvKiB1c2UgY29uc3RhbnQgbGltaXQgYmVjYXVzZSBpbiBqcyB3ZSBzaG91bGQgbm90IHByZWFsbG9jYXRlIG1lbW9yeSAqL1xuICAgICAgICAgICAgaWYgKHN0YXRlLmhlYWQgJiYgbGVuICYmXG4gICAgICAgICAgICAgICAgKHN0YXRlLmxlbmd0aCA8IDY1NTM2IC8qc3RhdGUuaGVhZC5uYW1lX21heCovKSkge1xuICAgICAgICAgICAgICBzdGF0ZS5oZWFkLm5hbWUgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShsZW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gd2hpbGUgKGxlbiAmJiBjb3B5IDwgaGF2ZSk7XG5cbiAgICAgICAgICBpZiAoKHN0YXRlLmZsYWdzICYgMHgwMjAwKSAmJiAoc3RhdGUud3JhcCAmIDQpKSB7XG4gICAgICAgICAgICBzdGF0ZS5jaGVjayA9IGNyYzMyXzEoc3RhdGUuY2hlY2ssIGlucHV0LCBjb3B5LCBuZXh0KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaGF2ZSAtPSBjb3B5O1xuICAgICAgICAgIG5leHQgKz0gY29weTtcbiAgICAgICAgICBpZiAobGVuKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHN0YXRlLmhlYWQpIHtcbiAgICAgICAgICBzdGF0ZS5oZWFkLm5hbWUgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRlLmxlbmd0aCA9IDA7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBDT01NRU5UO1xuICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICBjYXNlIENPTU1FTlQ6XG4gICAgICAgIGlmIChzdGF0ZS5mbGFncyAmIDB4MTAwMCkge1xuICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgIGNvcHkgPSAwO1xuICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgIGxlbiA9IGlucHV0W25leHQgKyBjb3B5KytdO1xuICAgICAgICAgICAgLyogdXNlIGNvbnN0YW50IGxpbWl0IGJlY2F1c2UgaW4ganMgd2Ugc2hvdWxkIG5vdCBwcmVhbGxvY2F0ZSBtZW1vcnkgKi9cbiAgICAgICAgICAgIGlmIChzdGF0ZS5oZWFkICYmIGxlbiAmJlxuICAgICAgICAgICAgICAgIChzdGF0ZS5sZW5ndGggPCA2NTUzNiAvKnN0YXRlLmhlYWQuY29tbV9tYXgqLykpIHtcbiAgICAgICAgICAgICAgc3RhdGUuaGVhZC5jb21tZW50ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUobGVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IHdoaWxlIChsZW4gJiYgY29weSA8IGhhdmUpO1xuICAgICAgICAgIGlmICgoc3RhdGUuZmxhZ3MgJiAweDAyMDApICYmIChzdGF0ZS53cmFwICYgNCkpIHtcbiAgICAgICAgICAgIHN0YXRlLmNoZWNrID0gY3JjMzJfMShzdGF0ZS5jaGVjaywgaW5wdXQsIGNvcHksIG5leHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBoYXZlIC09IGNvcHk7XG4gICAgICAgICAgbmV4dCArPSBjb3B5O1xuICAgICAgICAgIGlmIChsZW4pIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoc3RhdGUuaGVhZCkge1xuICAgICAgICAgIHN0YXRlLmhlYWQuY29tbWVudCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGUubW9kZSA9IEhDUkM7XG4gICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgIGNhc2UgSENSQzpcbiAgICAgICAgaWYgKHN0YXRlLmZsYWdzICYgMHgwMjAwKSB7XG4gICAgICAgICAgLy89PT0gTkVFREJJVFMoMTYpOyAqL1xuICAgICAgICAgIHdoaWxlIChiaXRzIDwgMTYpIHtcbiAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgICAgaGF2ZS0tO1xuICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vPT09Ly9cbiAgICAgICAgICBpZiAoKHN0YXRlLndyYXAgJiA0KSAmJiBob2xkICE9PSAoc3RhdGUuY2hlY2sgJiAweGZmZmYpKSB7XG4gICAgICAgICAgICBzdHJtLm1zZyA9ICdoZWFkZXIgY3JjIG1pc21hdGNoJztcbiAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgLy89PT0gSU5JVEJJVFMoKTtcbiAgICAgICAgICBob2xkID0gMDtcbiAgICAgICAgICBiaXRzID0gMDtcbiAgICAgICAgICAvLz09PS8vXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0YXRlLmhlYWQpIHtcbiAgICAgICAgICBzdGF0ZS5oZWFkLmhjcmMgPSAoKHN0YXRlLmZsYWdzID4+IDkpICYgMSk7XG4gICAgICAgICAgc3RhdGUuaGVhZC5kb25lID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBzdHJtLmFkbGVyID0gc3RhdGUuY2hlY2sgPSAwO1xuICAgICAgICBzdGF0ZS5tb2RlID0gVFlQRTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIERJQ1RJRDpcbiAgICAgICAgLy89PT0gTkVFREJJVFMoMzIpOyAqL1xuICAgICAgICB3aGlsZSAoYml0cyA8IDMyKSB7XG4gICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgaGF2ZS0tO1xuICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgfVxuICAgICAgICAvLz09PS8vXG4gICAgICAgIHN0cm0uYWRsZXIgPSBzdGF0ZS5jaGVjayA9IHpzd2FwMzIoaG9sZCk7XG4gICAgICAgIC8vPT09IElOSVRCSVRTKCk7XG4gICAgICAgIGhvbGQgPSAwO1xuICAgICAgICBiaXRzID0gMDtcbiAgICAgICAgLy89PT0vL1xuICAgICAgICBzdGF0ZS5tb2RlID0gRElDVDtcbiAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgY2FzZSBESUNUOlxuICAgICAgICBpZiAoc3RhdGUuaGF2ZWRpY3QgPT09IDApIHtcbiAgICAgICAgICAvLy0tLSBSRVNUT1JFKCkgLS0tXG4gICAgICAgICAgc3RybS5uZXh0X291dCA9IHB1dDtcbiAgICAgICAgICBzdHJtLmF2YWlsX291dCA9IGxlZnQ7XG4gICAgICAgICAgc3RybS5uZXh0X2luID0gbmV4dDtcbiAgICAgICAgICBzdHJtLmF2YWlsX2luID0gaGF2ZTtcbiAgICAgICAgICBzdGF0ZS5ob2xkID0gaG9sZDtcbiAgICAgICAgICBzdGF0ZS5iaXRzID0gYml0cztcbiAgICAgICAgICAvLy0tLVxuICAgICAgICAgIHJldHVybiBaX05FRURfRElDVCQxO1xuICAgICAgICB9XG4gICAgICAgIHN0cm0uYWRsZXIgPSBzdGF0ZS5jaGVjayA9IDEvKmFkbGVyMzIoMEwsIFpfTlVMTCwgMCkqLztcbiAgICAgICAgc3RhdGUubW9kZSA9IFRZUEU7XG4gICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgIGNhc2UgVFlQRTpcbiAgICAgICAgaWYgKGZsdXNoID09PSBaX0JMT0NLIHx8IGZsdXNoID09PSBaX1RSRUVTKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICBjYXNlIFRZUEVETzpcbiAgICAgICAgaWYgKHN0YXRlLmxhc3QpIHtcbiAgICAgICAgICAvLy0tLSBCWVRFQklUUygpIC0tLS8vXG4gICAgICAgICAgaG9sZCA+Pj49IGJpdHMgJiA3O1xuICAgICAgICAgIGJpdHMgLT0gYml0cyAmIDc7XG4gICAgICAgICAgLy8tLS0vL1xuICAgICAgICAgIHN0YXRlLm1vZGUgPSBDSEVDSztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICAvLz09PSBORUVEQklUUygzKTsgKi9cbiAgICAgICAgd2hpbGUgKGJpdHMgPCAzKSB7XG4gICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgaGF2ZS0tO1xuICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgfVxuICAgICAgICAvLz09PS8vXG4gICAgICAgIHN0YXRlLmxhc3QgPSAoaG9sZCAmIDB4MDEpLypCSVRTKDEpKi87XG4gICAgICAgIC8vLS0tIERST1BCSVRTKDEpIC0tLS8vXG4gICAgICAgIGhvbGQgPj4+PSAxO1xuICAgICAgICBiaXRzIC09IDE7XG4gICAgICAgIC8vLS0tLy9cblxuICAgICAgICBzd2l0Y2ggKChob2xkICYgMHgwMykvKkJJVFMoMikqLykge1xuICAgICAgICAgIGNhc2UgMDogICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIHN0b3JlZCBibG9jayAqL1xuICAgICAgICAgICAgLy9UcmFjZXYoKHN0ZGVyciwgXCJpbmZsYXRlOiAgICAgc3RvcmVkIGJsb2NrJXNcXG5cIixcbiAgICAgICAgICAgIC8vICAgICAgICBzdGF0ZS5sYXN0ID8gXCIgKGxhc3QpXCIgOiBcIlwiKSk7XG4gICAgICAgICAgICBzdGF0ZS5tb2RlID0gU1RPUkVEO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAxOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLyogZml4ZWQgYmxvY2sgKi9cbiAgICAgICAgICAgIGZpeGVkdGFibGVzKHN0YXRlKTtcbiAgICAgICAgICAgIC8vVHJhY2V2KChzdGRlcnIsIFwiaW5mbGF0ZTogICAgIGZpeGVkIGNvZGVzIGJsb2NrJXNcXG5cIixcbiAgICAgICAgICAgIC8vICAgICAgICBzdGF0ZS5sYXN0ID8gXCIgKGxhc3QpXCIgOiBcIlwiKSk7XG4gICAgICAgICAgICBzdGF0ZS5tb2RlID0gTEVOXzsgICAgICAgICAgICAgLyogZGVjb2RlIGNvZGVzICovXG4gICAgICAgICAgICBpZiAoZmx1c2ggPT09IFpfVFJFRVMpIHtcbiAgICAgICAgICAgICAgLy8tLS0gRFJPUEJJVFMoMikgLS0tLy9cbiAgICAgICAgICAgICAgaG9sZCA+Pj49IDI7XG4gICAgICAgICAgICAgIGJpdHMgLT0gMjtcbiAgICAgICAgICAgICAgLy8tLS0vL1xuICAgICAgICAgICAgICBicmVhayBpbmZfbGVhdmU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIDI6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvKiBkeW5hbWljIGJsb2NrICovXG4gICAgICAgICAgICAvL1RyYWNldigoc3RkZXJyLCBcImluZmxhdGU6ICAgICBkeW5hbWljIGNvZGVzIGJsb2NrJXNcXG5cIixcbiAgICAgICAgICAgIC8vICAgICAgICBzdGF0ZS5sYXN0ID8gXCIgKGxhc3QpXCIgOiBcIlwiKSk7XG4gICAgICAgICAgICBzdGF0ZS5tb2RlID0gVEFCTEU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICBzdHJtLm1zZyA9ICdpbnZhbGlkIGJsb2NrIHR5cGUnO1xuICAgICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDtcbiAgICAgICAgfVxuICAgICAgICAvLy0tLSBEUk9QQklUUygyKSAtLS0vL1xuICAgICAgICBob2xkID4+Pj0gMjtcbiAgICAgICAgYml0cyAtPSAyO1xuICAgICAgICAvLy0tLS8vXG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBTVE9SRUQ6XG4gICAgICAgIC8vLS0tIEJZVEVCSVRTKCkgLS0tLy8gLyogZ28gdG8gYnl0ZSBib3VuZGFyeSAqL1xuICAgICAgICBob2xkID4+Pj0gYml0cyAmIDc7XG4gICAgICAgIGJpdHMgLT0gYml0cyAmIDc7XG4gICAgICAgIC8vLS0tLy9cbiAgICAgICAgLy89PT0gTkVFREJJVFMoMzIpOyAqL1xuICAgICAgICB3aGlsZSAoYml0cyA8IDMyKSB7XG4gICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgaGF2ZS0tO1xuICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgfVxuICAgICAgICAvLz09PS8vXG4gICAgICAgIGlmICgoaG9sZCAmIDB4ZmZmZikgIT09ICgoaG9sZCA+Pj4gMTYpIF4gMHhmZmZmKSkge1xuICAgICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgc3RvcmVkIGJsb2NrIGxlbmd0aHMnO1xuICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGUubGVuZ3RoID0gaG9sZCAmIDB4ZmZmZjtcbiAgICAgICAgLy9UcmFjZXYoKHN0ZGVyciwgXCJpbmZsYXRlOiAgICAgICBzdG9yZWQgbGVuZ3RoICV1XFxuXCIsXG4gICAgICAgIC8vICAgICAgICBzdGF0ZS5sZW5ndGgpKTtcbiAgICAgICAgLy89PT0gSU5JVEJJVFMoKTtcbiAgICAgICAgaG9sZCA9IDA7XG4gICAgICAgIGJpdHMgPSAwO1xuICAgICAgICAvLz09PS8vXG4gICAgICAgIHN0YXRlLm1vZGUgPSBDT1BZXztcbiAgICAgICAgaWYgKGZsdXNoID09PSBaX1RSRUVTKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICBjYXNlIENPUFlfOlxuICAgICAgICBzdGF0ZS5tb2RlID0gQ09QWTtcbiAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgY2FzZSBDT1BZOlxuICAgICAgICBjb3B5ID0gc3RhdGUubGVuZ3RoO1xuICAgICAgICBpZiAoY29weSkge1xuICAgICAgICAgIGlmIChjb3B5ID4gaGF2ZSkgeyBjb3B5ID0gaGF2ZTsgfVxuICAgICAgICAgIGlmIChjb3B5ID4gbGVmdCkgeyBjb3B5ID0gbGVmdDsgfVxuICAgICAgICAgIGlmIChjb3B5ID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgIC8vLS0tIHptZW1jcHkocHV0LCBuZXh0LCBjb3B5KTsgLS0tXG4gICAgICAgICAgb3V0cHV0LnNldChpbnB1dC5zdWJhcnJheShuZXh0LCBuZXh0ICsgY29weSksIHB1dCk7XG4gICAgICAgICAgLy8tLS0vL1xuICAgICAgICAgIGhhdmUgLT0gY29weTtcbiAgICAgICAgICBuZXh0ICs9IGNvcHk7XG4gICAgICAgICAgbGVmdCAtPSBjb3B5O1xuICAgICAgICAgIHB1dCArPSBjb3B5O1xuICAgICAgICAgIHN0YXRlLmxlbmd0aCAtPSBjb3B5O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIC8vVHJhY2V2KChzdGRlcnIsIFwiaW5mbGF0ZTogICAgICAgc3RvcmVkIGVuZFxcblwiKSk7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBUWVBFO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgVEFCTEU6XG4gICAgICAgIC8vPT09IE5FRURCSVRTKDE0KTsgKi9cbiAgICAgICAgd2hpbGUgKGJpdHMgPCAxNCkge1xuICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgIH1cbiAgICAgICAgLy89PT0vL1xuICAgICAgICBzdGF0ZS5ubGVuID0gKGhvbGQgJiAweDFmKS8qQklUUyg1KSovICsgMjU3O1xuICAgICAgICAvLy0tLSBEUk9QQklUUyg1KSAtLS0vL1xuICAgICAgICBob2xkID4+Pj0gNTtcbiAgICAgICAgYml0cyAtPSA1O1xuICAgICAgICAvLy0tLS8vXG4gICAgICAgIHN0YXRlLm5kaXN0ID0gKGhvbGQgJiAweDFmKS8qQklUUyg1KSovICsgMTtcbiAgICAgICAgLy8tLS0gRFJPUEJJVFMoNSkgLS0tLy9cbiAgICAgICAgaG9sZCA+Pj49IDU7XG4gICAgICAgIGJpdHMgLT0gNTtcbiAgICAgICAgLy8tLS0vL1xuICAgICAgICBzdGF0ZS5uY29kZSA9IChob2xkICYgMHgwZikvKkJJVFMoNCkqLyArIDQ7XG4gICAgICAgIC8vLS0tIERST1BCSVRTKDQpIC0tLS8vXG4gICAgICAgIGhvbGQgPj4+PSA0O1xuICAgICAgICBiaXRzIC09IDQ7XG4gICAgICAgIC8vLS0tLy9cbi8vI2lmbmRlZiBQS1pJUF9CVUdfV09SS0FST1VORFxuICAgICAgICBpZiAoc3RhdGUubmxlbiA+IDI4NiB8fCBzdGF0ZS5uZGlzdCA+IDMwKSB7XG4gICAgICAgICAgc3RybS5tc2cgPSAndG9vIG1hbnkgbGVuZ3RoIG9yIGRpc3RhbmNlIHN5bWJvbHMnO1xuICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbi8vI2VuZGlmXG4gICAgICAgIC8vVHJhY2V2KChzdGRlcnIsIFwiaW5mbGF0ZTogICAgICAgdGFibGUgc2l6ZXMgb2tcXG5cIikpO1xuICAgICAgICBzdGF0ZS5oYXZlID0gMDtcbiAgICAgICAgc3RhdGUubW9kZSA9IExFTkxFTlM7XG4gICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgIGNhc2UgTEVOTEVOUzpcbiAgICAgICAgd2hpbGUgKHN0YXRlLmhhdmUgPCBzdGF0ZS5uY29kZSkge1xuICAgICAgICAgIC8vPT09IE5FRURCSVRTKDMpO1xuICAgICAgICAgIHdoaWxlIChiaXRzIDwgMykge1xuICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgICBoYXZlLS07XG4gICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy89PT0vL1xuICAgICAgICAgIHN0YXRlLmxlbnNbb3JkZXJbc3RhdGUuaGF2ZSsrXV0gPSAoaG9sZCAmIDB4MDcpOy8vQklUUygzKTtcbiAgICAgICAgICAvLy0tLSBEUk9QQklUUygzKSAtLS0vL1xuICAgICAgICAgIGhvbGQgPj4+PSAzO1xuICAgICAgICAgIGJpdHMgLT0gMztcbiAgICAgICAgICAvLy0tLS8vXG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUgKHN0YXRlLmhhdmUgPCAxOSkge1xuICAgICAgICAgIHN0YXRlLmxlbnNbb3JkZXJbc3RhdGUuaGF2ZSsrXV0gPSAwO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdlIGhhdmUgc2VwYXJhdGUgdGFibGVzICYgbm8gcG9pbnRlcnMuIDIgY29tbWVudGVkIGxpbmVzIGJlbG93IG5vdCBuZWVkZWQuXG4gICAgICAgIC8vc3RhdGUubmV4dCA9IHN0YXRlLmNvZGVzO1xuICAgICAgICAvL3N0YXRlLmxlbmNvZGUgPSBzdGF0ZS5uZXh0O1xuICAgICAgICAvLyBTd2l0Y2ggdG8gdXNlIGR5bmFtaWMgdGFibGVcbiAgICAgICAgc3RhdGUubGVuY29kZSA9IHN0YXRlLmxlbmR5bjtcbiAgICAgICAgc3RhdGUubGVuYml0cyA9IDc7XG5cbiAgICAgICAgb3B0cyA9IHsgYml0czogc3RhdGUubGVuYml0cyB9O1xuICAgICAgICByZXQgPSBpbmZ0cmVlcyhDT0RFUywgc3RhdGUubGVucywgMCwgMTksIHN0YXRlLmxlbmNvZGUsIDAsIHN0YXRlLndvcmssIG9wdHMpO1xuICAgICAgICBzdGF0ZS5sZW5iaXRzID0gb3B0cy5iaXRzO1xuXG4gICAgICAgIGlmIChyZXQpIHtcbiAgICAgICAgICBzdHJtLm1zZyA9ICdpbnZhbGlkIGNvZGUgbGVuZ3RocyBzZXQnO1xuICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgLy9UcmFjZXYoKHN0ZGVyciwgXCJpbmZsYXRlOiAgICAgICBjb2RlIGxlbmd0aHMgb2tcXG5cIikpO1xuICAgICAgICBzdGF0ZS5oYXZlID0gMDtcbiAgICAgICAgc3RhdGUubW9kZSA9IENPREVMRU5TO1xuICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICBjYXNlIENPREVMRU5TOlxuICAgICAgICB3aGlsZSAoc3RhdGUuaGF2ZSA8IHN0YXRlLm5sZW4gKyBzdGF0ZS5uZGlzdCkge1xuICAgICAgICAgIGZvciAoOzspIHtcbiAgICAgICAgICAgIGhlcmUgPSBzdGF0ZS5sZW5jb2RlW2hvbGQgJiAoKDEgPDwgc3RhdGUubGVuYml0cykgLSAxKV07LypCSVRTKHN0YXRlLmxlbmJpdHMpKi9cbiAgICAgICAgICAgIGhlcmVfYml0cyA9IGhlcmUgPj4+IDI0O1xuICAgICAgICAgICAgaGVyZV9vcCA9IChoZXJlID4+PiAxNikgJiAweGZmO1xuICAgICAgICAgICAgaGVyZV92YWwgPSBoZXJlICYgMHhmZmZmO1xuXG4gICAgICAgICAgICBpZiAoKGhlcmVfYml0cykgPD0gYml0cykgeyBicmVhazsgfVxuICAgICAgICAgICAgLy8tLS0gUFVMTEJZVEUoKSAtLS0vL1xuICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgICBoYXZlLS07XG4gICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgICAgIC8vLS0tLy9cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGhlcmVfdmFsIDwgMTYpIHtcbiAgICAgICAgICAgIC8vLS0tIERST1BCSVRTKGhlcmUuYml0cykgLS0tLy9cbiAgICAgICAgICAgIGhvbGQgPj4+PSBoZXJlX2JpdHM7XG4gICAgICAgICAgICBiaXRzIC09IGhlcmVfYml0cztcbiAgICAgICAgICAgIC8vLS0tLy9cbiAgICAgICAgICAgIHN0YXRlLmxlbnNbc3RhdGUuaGF2ZSsrXSA9IGhlcmVfdmFsO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlmIChoZXJlX3ZhbCA9PT0gMTYpIHtcbiAgICAgICAgICAgICAgLy89PT0gTkVFREJJVFMoaGVyZS5iaXRzICsgMik7XG4gICAgICAgICAgICAgIG4gPSBoZXJlX2JpdHMgKyAyO1xuICAgICAgICAgICAgICB3aGlsZSAoYml0cyA8IG4pIHtcbiAgICAgICAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgeyBicmVhayBpbmZfbGVhdmU7IH1cbiAgICAgICAgICAgICAgICBoYXZlLS07XG4gICAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgICAgICAgICAgYml0cyArPSA4O1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIC8vPT09Ly9cbiAgICAgICAgICAgICAgLy8tLS0gRFJPUEJJVFMoaGVyZS5iaXRzKSAtLS0vL1xuICAgICAgICAgICAgICBob2xkID4+Pj0gaGVyZV9iaXRzO1xuICAgICAgICAgICAgICBiaXRzIC09IGhlcmVfYml0cztcbiAgICAgICAgICAgICAgLy8tLS0vL1xuICAgICAgICAgICAgICBpZiAoc3RhdGUuaGF2ZSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgYml0IGxlbmd0aCByZXBlYXQnO1xuICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgbGVuID0gc3RhdGUubGVuc1tzdGF0ZS5oYXZlIC0gMV07XG4gICAgICAgICAgICAgIGNvcHkgPSAzICsgKGhvbGQgJiAweDAzKTsvL0JJVFMoMik7XG4gICAgICAgICAgICAgIC8vLS0tIERST1BCSVRTKDIpIC0tLS8vXG4gICAgICAgICAgICAgIGhvbGQgPj4+PSAyO1xuICAgICAgICAgICAgICBiaXRzIC09IDI7XG4gICAgICAgICAgICAgIC8vLS0tLy9cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGhlcmVfdmFsID09PSAxNykge1xuICAgICAgICAgICAgICAvLz09PSBORUVEQklUUyhoZXJlLmJpdHMgKyAzKTtcbiAgICAgICAgICAgICAgbiA9IGhlcmVfYml0cyArIDM7XG4gICAgICAgICAgICAgIHdoaWxlIChiaXRzIDwgbikge1xuICAgICAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgLy89PT0vL1xuICAgICAgICAgICAgICAvLy0tLSBEUk9QQklUUyhoZXJlLmJpdHMpIC0tLS8vXG4gICAgICAgICAgICAgIGhvbGQgPj4+PSBoZXJlX2JpdHM7XG4gICAgICAgICAgICAgIGJpdHMgLT0gaGVyZV9iaXRzO1xuICAgICAgICAgICAgICAvLy0tLS8vXG4gICAgICAgICAgICAgIGxlbiA9IDA7XG4gICAgICAgICAgICAgIGNvcHkgPSAzICsgKGhvbGQgJiAweDA3KTsvL0JJVFMoMyk7XG4gICAgICAgICAgICAgIC8vLS0tIERST1BCSVRTKDMpIC0tLS8vXG4gICAgICAgICAgICAgIGhvbGQgPj4+PSAzO1xuICAgICAgICAgICAgICBiaXRzIC09IDM7XG4gICAgICAgICAgICAgIC8vLS0tLy9cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAvLz09PSBORUVEQklUUyhoZXJlLmJpdHMgKyA3KTtcbiAgICAgICAgICAgICAgbiA9IGhlcmVfYml0cyArIDc7XG4gICAgICAgICAgICAgIHdoaWxlIChiaXRzIDwgbikge1xuICAgICAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgLy89PT0vL1xuICAgICAgICAgICAgICAvLy0tLSBEUk9QQklUUyhoZXJlLmJpdHMpIC0tLS8vXG4gICAgICAgICAgICAgIGhvbGQgPj4+PSBoZXJlX2JpdHM7XG4gICAgICAgICAgICAgIGJpdHMgLT0gaGVyZV9iaXRzO1xuICAgICAgICAgICAgICAvLy0tLS8vXG4gICAgICAgICAgICAgIGxlbiA9IDA7XG4gICAgICAgICAgICAgIGNvcHkgPSAxMSArIChob2xkICYgMHg3Zik7Ly9CSVRTKDcpO1xuICAgICAgICAgICAgICAvLy0tLSBEUk9QQklUUyg3KSAtLS0vL1xuICAgICAgICAgICAgICBob2xkID4+Pj0gNztcbiAgICAgICAgICAgICAgYml0cyAtPSA3O1xuICAgICAgICAgICAgICAvLy0tLS8vXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc3RhdGUuaGF2ZSArIGNvcHkgPiBzdGF0ZS5ubGVuICsgc3RhdGUubmRpc3QpIHtcbiAgICAgICAgICAgICAgc3RybS5tc2cgPSAnaW52YWxpZCBiaXQgbGVuZ3RoIHJlcGVhdCc7XG4gICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2hpbGUgKGNvcHktLSkge1xuICAgICAgICAgICAgICBzdGF0ZS5sZW5zW3N0YXRlLmhhdmUrK10gPSBsZW47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLyogaGFuZGxlIGVycm9yIGJyZWFrcyBpbiB3aGlsZSAqL1xuICAgICAgICBpZiAoc3RhdGUubW9kZSA9PT0gQkFEKSB7IGJyZWFrOyB9XG5cbiAgICAgICAgLyogY2hlY2sgZm9yIGVuZC1vZi1ibG9jayBjb2RlIChiZXR0ZXIgaGF2ZSBvbmUpICovXG4gICAgICAgIGlmIChzdGF0ZS5sZW5zWzI1Nl0gPT09IDApIHtcbiAgICAgICAgICBzdHJtLm1zZyA9ICdpbnZhbGlkIGNvZGUgLS0gbWlzc2luZyBlbmQtb2YtYmxvY2snO1xuICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICAvKiBidWlsZCBjb2RlIHRhYmxlcyAtLSBub3RlOiBkbyBub3QgY2hhbmdlIHRoZSBsZW5iaXRzIG9yIGRpc3RiaXRzXG4gICAgICAgICAgIHZhbHVlcyBoZXJlICg5IGFuZCA2KSB3aXRob3V0IHJlYWRpbmcgdGhlIGNvbW1lbnRzIGluIGluZnRyZWVzLmhcbiAgICAgICAgICAgY29uY2VybmluZyB0aGUgRU5PVUdIIGNvbnN0YW50cywgd2hpY2ggZGVwZW5kIG9uIHRob3NlIHZhbHVlcyAqL1xuICAgICAgICBzdGF0ZS5sZW5iaXRzID0gOTtcblxuICAgICAgICBvcHRzID0geyBiaXRzOiBzdGF0ZS5sZW5iaXRzIH07XG4gICAgICAgIHJldCA9IGluZnRyZWVzKExFTlMsIHN0YXRlLmxlbnMsIDAsIHN0YXRlLm5sZW4sIHN0YXRlLmxlbmNvZGUsIDAsIHN0YXRlLndvcmssIG9wdHMpO1xuICAgICAgICAvLyBXZSBoYXZlIHNlcGFyYXRlIHRhYmxlcyAmIG5vIHBvaW50ZXJzLiAyIGNvbW1lbnRlZCBsaW5lcyBiZWxvdyBub3QgbmVlZGVkLlxuICAgICAgICAvLyBzdGF0ZS5uZXh0X2luZGV4ID0gb3B0cy50YWJsZV9pbmRleDtcbiAgICAgICAgc3RhdGUubGVuYml0cyA9IG9wdHMuYml0cztcbiAgICAgICAgLy8gc3RhdGUubGVuY29kZSA9IHN0YXRlLm5leHQ7XG5cbiAgICAgICAgaWYgKHJldCkge1xuICAgICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgbGl0ZXJhbC9sZW5ndGhzIHNldCc7XG4gICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXRlLmRpc3RiaXRzID0gNjtcbiAgICAgICAgLy9zdGF0ZS5kaXN0Y29kZS5jb3B5KHN0YXRlLmNvZGVzKTtcbiAgICAgICAgLy8gU3dpdGNoIHRvIHVzZSBkeW5hbWljIHRhYmxlXG4gICAgICAgIHN0YXRlLmRpc3Rjb2RlID0gc3RhdGUuZGlzdGR5bjtcbiAgICAgICAgb3B0cyA9IHsgYml0czogc3RhdGUuZGlzdGJpdHMgfTtcbiAgICAgICAgcmV0ID0gaW5mdHJlZXMoRElTVFMsIHN0YXRlLmxlbnMsIHN0YXRlLm5sZW4sIHN0YXRlLm5kaXN0LCBzdGF0ZS5kaXN0Y29kZSwgMCwgc3RhdGUud29yaywgb3B0cyk7XG4gICAgICAgIC8vIFdlIGhhdmUgc2VwYXJhdGUgdGFibGVzICYgbm8gcG9pbnRlcnMuIDIgY29tbWVudGVkIGxpbmVzIGJlbG93IG5vdCBuZWVkZWQuXG4gICAgICAgIC8vIHN0YXRlLm5leHRfaW5kZXggPSBvcHRzLnRhYmxlX2luZGV4O1xuICAgICAgICBzdGF0ZS5kaXN0Yml0cyA9IG9wdHMuYml0cztcbiAgICAgICAgLy8gc3RhdGUuZGlzdGNvZGUgPSBzdGF0ZS5uZXh0O1xuXG4gICAgICAgIGlmIChyZXQpIHtcbiAgICAgICAgICBzdHJtLm1zZyA9ICdpbnZhbGlkIGRpc3RhbmNlcyBzZXQnO1xuICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgLy9UcmFjZXYoKHN0ZGVyciwgJ2luZmxhdGU6ICAgICAgIGNvZGVzIG9rXFxuJykpO1xuICAgICAgICBzdGF0ZS5tb2RlID0gTEVOXztcbiAgICAgICAgaWYgKGZsdXNoID09PSBaX1RSRUVTKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICBjYXNlIExFTl86XG4gICAgICAgIHN0YXRlLm1vZGUgPSBMRU47XG4gICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgIGNhc2UgTEVOOlxuICAgICAgICBpZiAoaGF2ZSA+PSA2ICYmIGxlZnQgPj0gMjU4KSB7XG4gICAgICAgICAgLy8tLS0gUkVTVE9SRSgpIC0tLVxuICAgICAgICAgIHN0cm0ubmV4dF9vdXQgPSBwdXQ7XG4gICAgICAgICAgc3RybS5hdmFpbF9vdXQgPSBsZWZ0O1xuICAgICAgICAgIHN0cm0ubmV4dF9pbiA9IG5leHQ7XG4gICAgICAgICAgc3RybS5hdmFpbF9pbiA9IGhhdmU7XG4gICAgICAgICAgc3RhdGUuaG9sZCA9IGhvbGQ7XG4gICAgICAgICAgc3RhdGUuYml0cyA9IGJpdHM7XG4gICAgICAgICAgLy8tLS1cbiAgICAgICAgICBpbmZmYXN0KHN0cm0sIF9vdXQpO1xuICAgICAgICAgIC8vLS0tIExPQUQoKSAtLS1cbiAgICAgICAgICBwdXQgPSBzdHJtLm5leHRfb3V0O1xuICAgICAgICAgIG91dHB1dCA9IHN0cm0ub3V0cHV0O1xuICAgICAgICAgIGxlZnQgPSBzdHJtLmF2YWlsX291dDtcbiAgICAgICAgICBuZXh0ID0gc3RybS5uZXh0X2luO1xuICAgICAgICAgIGlucHV0ID0gc3RybS5pbnB1dDtcbiAgICAgICAgICBoYXZlID0gc3RybS5hdmFpbF9pbjtcbiAgICAgICAgICBob2xkID0gc3RhdGUuaG9sZDtcbiAgICAgICAgICBiaXRzID0gc3RhdGUuYml0cztcbiAgICAgICAgICAvLy0tLVxuXG4gICAgICAgICAgaWYgKHN0YXRlLm1vZGUgPT09IFRZUEUpIHtcbiAgICAgICAgICAgIHN0YXRlLmJhY2sgPSAtMTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGUuYmFjayA9IDA7XG4gICAgICAgIGZvciAoOzspIHtcbiAgICAgICAgICBoZXJlID0gc3RhdGUubGVuY29kZVtob2xkICYgKCgxIDw8IHN0YXRlLmxlbmJpdHMpIC0gMSldOyAgLypCSVRTKHN0YXRlLmxlbmJpdHMpKi9cbiAgICAgICAgICBoZXJlX2JpdHMgPSBoZXJlID4+PiAyNDtcbiAgICAgICAgICBoZXJlX29wID0gKGhlcmUgPj4+IDE2KSAmIDB4ZmY7XG4gICAgICAgICAgaGVyZV92YWwgPSBoZXJlICYgMHhmZmZmO1xuXG4gICAgICAgICAgaWYgKGhlcmVfYml0cyA8PSBiaXRzKSB7IGJyZWFrOyB9XG4gICAgICAgICAgLy8tLS0gUFVMTEJZVEUoKSAtLS0vL1xuICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgLy8tLS0vL1xuICAgICAgICB9XG4gICAgICAgIGlmIChoZXJlX29wICYmIChoZXJlX29wICYgMHhmMCkgPT09IDApIHtcbiAgICAgICAgICBsYXN0X2JpdHMgPSBoZXJlX2JpdHM7XG4gICAgICAgICAgbGFzdF9vcCA9IGhlcmVfb3A7XG4gICAgICAgICAgbGFzdF92YWwgPSBoZXJlX3ZhbDtcbiAgICAgICAgICBmb3IgKDs7KSB7XG4gICAgICAgICAgICBoZXJlID0gc3RhdGUubGVuY29kZVtsYXN0X3ZhbCArXG4gICAgICAgICAgICAgICAgICAgICgoaG9sZCAmICgoMSA8PCAobGFzdF9iaXRzICsgbGFzdF9vcCkpIC0gMSkpLypCSVRTKGxhc3QuYml0cyArIGxhc3Qub3ApKi8gPj4gbGFzdF9iaXRzKV07XG4gICAgICAgICAgICBoZXJlX2JpdHMgPSBoZXJlID4+PiAyNDtcbiAgICAgICAgICAgIGhlcmVfb3AgPSAoaGVyZSA+Pj4gMTYpICYgMHhmZjtcbiAgICAgICAgICAgIGhlcmVfdmFsID0gaGVyZSAmIDB4ZmZmZjtcblxuICAgICAgICAgICAgaWYgKChsYXN0X2JpdHMgKyBoZXJlX2JpdHMpIDw9IGJpdHMpIHsgYnJlYWs7IH1cbiAgICAgICAgICAgIC8vLS0tIFBVTExCWVRFKCkgLS0tLy9cbiAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgICAgaGF2ZS0tO1xuICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgICAvLy0tLS8vXG4gICAgICAgICAgfVxuICAgICAgICAgIC8vLS0tIERST1BCSVRTKGxhc3QuYml0cykgLS0tLy9cbiAgICAgICAgICBob2xkID4+Pj0gbGFzdF9iaXRzO1xuICAgICAgICAgIGJpdHMgLT0gbGFzdF9iaXRzO1xuICAgICAgICAgIC8vLS0tLy9cbiAgICAgICAgICBzdGF0ZS5iYWNrICs9IGxhc3RfYml0cztcbiAgICAgICAgfVxuICAgICAgICAvLy0tLSBEUk9QQklUUyhoZXJlLmJpdHMpIC0tLS8vXG4gICAgICAgIGhvbGQgPj4+PSBoZXJlX2JpdHM7XG4gICAgICAgIGJpdHMgLT0gaGVyZV9iaXRzO1xuICAgICAgICAvLy0tLS8vXG4gICAgICAgIHN0YXRlLmJhY2sgKz0gaGVyZV9iaXRzO1xuICAgICAgICBzdGF0ZS5sZW5ndGggPSBoZXJlX3ZhbDtcbiAgICAgICAgaWYgKGhlcmVfb3AgPT09IDApIHtcbiAgICAgICAgICAvL1RyYWNldnYoKHN0ZGVyciwgaGVyZS52YWwgPj0gMHgyMCAmJiBoZXJlLnZhbCA8IDB4N2YgP1xuICAgICAgICAgIC8vICAgICAgICBcImluZmxhdGU6ICAgICAgICAgbGl0ZXJhbCAnJWMnXFxuXCIgOlxuICAgICAgICAgIC8vICAgICAgICBcImluZmxhdGU6ICAgICAgICAgbGl0ZXJhbCAweCUwMnhcXG5cIiwgaGVyZS52YWwpKTtcbiAgICAgICAgICBzdGF0ZS5tb2RlID0gTElUO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoZXJlX29wICYgMzIpIHtcbiAgICAgICAgICAvL1RyYWNldnYoKHN0ZGVyciwgXCJpbmZsYXRlOiAgICAgICAgIGVuZCBvZiBibG9ja1xcblwiKSk7XG4gICAgICAgICAgc3RhdGUuYmFjayA9IC0xO1xuICAgICAgICAgIHN0YXRlLm1vZGUgPSBUWVBFO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGlmIChoZXJlX29wICYgNjQpIHtcbiAgICAgICAgICBzdHJtLm1zZyA9ICdpbnZhbGlkIGxpdGVyYWwvbGVuZ3RoIGNvZGUnO1xuICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGUuZXh0cmEgPSBoZXJlX29wICYgMTU7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBMRU5FWFQ7XG4gICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgIGNhc2UgTEVORVhUOlxuICAgICAgICBpZiAoc3RhdGUuZXh0cmEpIHtcbiAgICAgICAgICAvLz09PSBORUVEQklUUyhzdGF0ZS5leHRyYSk7XG4gICAgICAgICAgbiA9IHN0YXRlLmV4dHJhO1xuICAgICAgICAgIHdoaWxlIChiaXRzIDwgbikge1xuICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgICBoYXZlLS07XG4gICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy89PT0vL1xuICAgICAgICAgIHN0YXRlLmxlbmd0aCArPSBob2xkICYgKCgxIDw8IHN0YXRlLmV4dHJhKSAtIDEpLypCSVRTKHN0YXRlLmV4dHJhKSovO1xuICAgICAgICAgIC8vLS0tIERST1BCSVRTKHN0YXRlLmV4dHJhKSAtLS0vL1xuICAgICAgICAgIGhvbGQgPj4+PSBzdGF0ZS5leHRyYTtcbiAgICAgICAgICBiaXRzIC09IHN0YXRlLmV4dHJhO1xuICAgICAgICAgIC8vLS0tLy9cbiAgICAgICAgICBzdGF0ZS5iYWNrICs9IHN0YXRlLmV4dHJhO1xuICAgICAgICB9XG4gICAgICAgIC8vVHJhY2V2digoc3RkZXJyLCBcImluZmxhdGU6ICAgICAgICAgbGVuZ3RoICV1XFxuXCIsIHN0YXRlLmxlbmd0aCkpO1xuICAgICAgICBzdGF0ZS53YXMgPSBzdGF0ZS5sZW5ndGg7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBESVNUO1xuICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICBjYXNlIERJU1Q6XG4gICAgICAgIGZvciAoOzspIHtcbiAgICAgICAgICBoZXJlID0gc3RhdGUuZGlzdGNvZGVbaG9sZCAmICgoMSA8PCBzdGF0ZS5kaXN0Yml0cykgLSAxKV07LypCSVRTKHN0YXRlLmRpc3RiaXRzKSovXG4gICAgICAgICAgaGVyZV9iaXRzID0gaGVyZSA+Pj4gMjQ7XG4gICAgICAgICAgaGVyZV9vcCA9IChoZXJlID4+PiAxNikgJiAweGZmO1xuICAgICAgICAgIGhlcmVfdmFsID0gaGVyZSAmIDB4ZmZmZjtcblxuICAgICAgICAgIGlmICgoaGVyZV9iaXRzKSA8PSBiaXRzKSB7IGJyZWFrOyB9XG4gICAgICAgICAgLy8tLS0gUFVMTEJZVEUoKSAtLS0vL1xuICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgLy8tLS0vL1xuICAgICAgICB9XG4gICAgICAgIGlmICgoaGVyZV9vcCAmIDB4ZjApID09PSAwKSB7XG4gICAgICAgICAgbGFzdF9iaXRzID0gaGVyZV9iaXRzO1xuICAgICAgICAgIGxhc3Rfb3AgPSBoZXJlX29wO1xuICAgICAgICAgIGxhc3RfdmFsID0gaGVyZV92YWw7XG4gICAgICAgICAgZm9yICg7Oykge1xuICAgICAgICAgICAgaGVyZSA9IHN0YXRlLmRpc3Rjb2RlW2xhc3RfdmFsICtcbiAgICAgICAgICAgICAgICAgICAgKChob2xkICYgKCgxIDw8IChsYXN0X2JpdHMgKyBsYXN0X29wKSkgLSAxKSkvKkJJVFMobGFzdC5iaXRzICsgbGFzdC5vcCkqLyA+PiBsYXN0X2JpdHMpXTtcbiAgICAgICAgICAgIGhlcmVfYml0cyA9IGhlcmUgPj4+IDI0O1xuICAgICAgICAgICAgaGVyZV9vcCA9IChoZXJlID4+PiAxNikgJiAweGZmO1xuICAgICAgICAgICAgaGVyZV92YWwgPSBoZXJlICYgMHhmZmZmO1xuXG4gICAgICAgICAgICBpZiAoKGxhc3RfYml0cyArIGhlcmVfYml0cykgPD0gYml0cykgeyBicmVhazsgfVxuICAgICAgICAgICAgLy8tLS0gUFVMTEJZVEUoKSAtLS0vL1xuICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgICBoYXZlLS07XG4gICAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgICAgIC8vLS0tLy9cbiAgICAgICAgICB9XG4gICAgICAgICAgLy8tLS0gRFJPUEJJVFMobGFzdC5iaXRzKSAtLS0vL1xuICAgICAgICAgIGhvbGQgPj4+PSBsYXN0X2JpdHM7XG4gICAgICAgICAgYml0cyAtPSBsYXN0X2JpdHM7XG4gICAgICAgICAgLy8tLS0vL1xuICAgICAgICAgIHN0YXRlLmJhY2sgKz0gbGFzdF9iaXRzO1xuICAgICAgICB9XG4gICAgICAgIC8vLS0tIERST1BCSVRTKGhlcmUuYml0cykgLS0tLy9cbiAgICAgICAgaG9sZCA+Pj49IGhlcmVfYml0cztcbiAgICAgICAgYml0cyAtPSBoZXJlX2JpdHM7XG4gICAgICAgIC8vLS0tLy9cbiAgICAgICAgc3RhdGUuYmFjayArPSBoZXJlX2JpdHM7XG4gICAgICAgIGlmIChoZXJlX29wICYgNjQpIHtcbiAgICAgICAgICBzdHJtLm1zZyA9ICdpbnZhbGlkIGRpc3RhbmNlIGNvZGUnO1xuICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGUub2Zmc2V0ID0gaGVyZV92YWw7XG4gICAgICAgIHN0YXRlLmV4dHJhID0gKGhlcmVfb3ApICYgMTU7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBESVNURVhUO1xuICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICBjYXNlIERJU1RFWFQ6XG4gICAgICAgIGlmIChzdGF0ZS5leHRyYSkge1xuICAgICAgICAgIC8vPT09IE5FRURCSVRTKHN0YXRlLmV4dHJhKTtcbiAgICAgICAgICBuID0gc3RhdGUuZXh0cmE7XG4gICAgICAgICAgd2hpbGUgKGJpdHMgPCBuKSB7XG4gICAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgeyBicmVhayBpbmZfbGVhdmU7IH1cbiAgICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICAgICAgYml0cyArPSA4O1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLz09PS8vXG4gICAgICAgICAgc3RhdGUub2Zmc2V0ICs9IGhvbGQgJiAoKDEgPDwgc3RhdGUuZXh0cmEpIC0gMSkvKkJJVFMoc3RhdGUuZXh0cmEpKi87XG4gICAgICAgICAgLy8tLS0gRFJPUEJJVFMoc3RhdGUuZXh0cmEpIC0tLS8vXG4gICAgICAgICAgaG9sZCA+Pj49IHN0YXRlLmV4dHJhO1xuICAgICAgICAgIGJpdHMgLT0gc3RhdGUuZXh0cmE7XG4gICAgICAgICAgLy8tLS0vL1xuICAgICAgICAgIHN0YXRlLmJhY2sgKz0gc3RhdGUuZXh0cmE7XG4gICAgICAgIH1cbi8vI2lmZGVmIElORkxBVEVfU1RSSUNUXG4gICAgICAgIGlmIChzdGF0ZS5vZmZzZXQgPiBzdGF0ZS5kbWF4KSB7XG4gICAgICAgICAgc3RybS5tc2cgPSAnaW52YWxpZCBkaXN0YW5jZSB0b28gZmFyIGJhY2snO1xuICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbi8vI2VuZGlmXG4gICAgICAgIC8vVHJhY2V2digoc3RkZXJyLCBcImluZmxhdGU6ICAgICAgICAgZGlzdGFuY2UgJXVcXG5cIiwgc3RhdGUub2Zmc2V0KSk7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBNQVRDSDtcbiAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgY2FzZSBNQVRDSDpcbiAgICAgICAgaWYgKGxlZnQgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIGNvcHkgPSBfb3V0IC0gbGVmdDtcbiAgICAgICAgaWYgKHN0YXRlLm9mZnNldCA+IGNvcHkpIHsgICAgICAgICAvKiBjb3B5IGZyb20gd2luZG93ICovXG4gICAgICAgICAgY29weSA9IHN0YXRlLm9mZnNldCAtIGNvcHk7XG4gICAgICAgICAgaWYgKGNvcHkgPiBzdGF0ZS53aGF2ZSkge1xuICAgICAgICAgICAgaWYgKHN0YXRlLnNhbmUpIHtcbiAgICAgICAgICAgICAgc3RybS5tc2cgPSAnaW52YWxpZCBkaXN0YW5jZSB0b28gZmFyIGJhY2snO1xuICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbi8vICghKSBUaGlzIGJsb2NrIGlzIGRpc2FibGVkIGluIHpsaWIgZGVmYXVsdHMsXG4vLyBkb24ndCBlbmFibGUgaXQgZm9yIGJpbmFyeSBjb21wYXRpYmlsaXR5XG4vLyNpZmRlZiBJTkZMQVRFX0FMTE9XX0lOVkFMSURfRElTVEFOQ0VfVE9PRkFSX0FSUlJcbi8vICAgICAgICAgIFRyYWNlKChzdGRlcnIsIFwiaW5mbGF0ZS5jIHRvbyBmYXJcXG5cIikpO1xuLy8gICAgICAgICAgY29weSAtPSBzdGF0ZS53aGF2ZTtcbi8vICAgICAgICAgIGlmIChjb3B5ID4gc3RhdGUubGVuZ3RoKSB7IGNvcHkgPSBzdGF0ZS5sZW5ndGg7IH1cbi8vICAgICAgICAgIGlmIChjb3B5ID4gbGVmdCkgeyBjb3B5ID0gbGVmdDsgfVxuLy8gICAgICAgICAgbGVmdCAtPSBjb3B5O1xuLy8gICAgICAgICAgc3RhdGUubGVuZ3RoIC09IGNvcHk7XG4vLyAgICAgICAgICBkbyB7XG4vLyAgICAgICAgICAgIG91dHB1dFtwdXQrK10gPSAwO1xuLy8gICAgICAgICAgfSB3aGlsZSAoLS1jb3B5KTtcbi8vICAgICAgICAgIGlmIChzdGF0ZS5sZW5ndGggPT09IDApIHsgc3RhdGUubW9kZSA9IExFTjsgfVxuLy8gICAgICAgICAgYnJlYWs7XG4vLyNlbmRpZlxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoY29weSA+IHN0YXRlLnduZXh0KSB7XG4gICAgICAgICAgICBjb3B5IC09IHN0YXRlLnduZXh0O1xuICAgICAgICAgICAgZnJvbSA9IHN0YXRlLndzaXplIC0gY29weTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBmcm9tID0gc3RhdGUud25leHQgLSBjb3B5O1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoY29weSA+IHN0YXRlLmxlbmd0aCkgeyBjb3B5ID0gc3RhdGUubGVuZ3RoOyB9XG4gICAgICAgICAgZnJvbV9zb3VyY2UgPSBzdGF0ZS53aW5kb3c7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLyogY29weSBmcm9tIG91dHB1dCAqL1xuICAgICAgICAgIGZyb21fc291cmNlID0gb3V0cHV0O1xuICAgICAgICAgIGZyb20gPSBwdXQgLSBzdGF0ZS5vZmZzZXQ7XG4gICAgICAgICAgY29weSA9IHN0YXRlLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29weSA+IGxlZnQpIHsgY29weSA9IGxlZnQ7IH1cbiAgICAgICAgbGVmdCAtPSBjb3B5O1xuICAgICAgICBzdGF0ZS5sZW5ndGggLT0gY29weTtcbiAgICAgICAgZG8ge1xuICAgICAgICAgIG91dHB1dFtwdXQrK10gPSBmcm9tX3NvdXJjZVtmcm9tKytdO1xuICAgICAgICB9IHdoaWxlICgtLWNvcHkpO1xuICAgICAgICBpZiAoc3RhdGUubGVuZ3RoID09PSAwKSB7IHN0YXRlLm1vZGUgPSBMRU47IH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIExJVDpcbiAgICAgICAgaWYgKGxlZnQgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIG91dHB1dFtwdXQrK10gPSBzdGF0ZS5sZW5ndGg7XG4gICAgICAgIGxlZnQtLTtcbiAgICAgICAgc3RhdGUubW9kZSA9IExFTjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENIRUNLOlxuICAgICAgICBpZiAoc3RhdGUud3JhcCkge1xuICAgICAgICAgIC8vPT09IE5FRURCSVRTKDMyKTtcbiAgICAgICAgICB3aGlsZSAoYml0cyA8IDMyKSB7XG4gICAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgeyBicmVhayBpbmZfbGVhdmU7IH1cbiAgICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICAgIC8vIFVzZSAnfCcgaW5zdGVhZCBvZiAnKycgdG8gbWFrZSBzdXJlIHRoYXQgcmVzdWx0IGlzIHNpZ25lZFxuICAgICAgICAgICAgaG9sZCB8PSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vPT09Ly9cbiAgICAgICAgICBfb3V0IC09IGxlZnQ7XG4gICAgICAgICAgc3RybS50b3RhbF9vdXQgKz0gX291dDtcbiAgICAgICAgICBzdGF0ZS50b3RhbCArPSBfb3V0O1xuICAgICAgICAgIGlmICgoc3RhdGUud3JhcCAmIDQpICYmIF9vdXQpIHtcbiAgICAgICAgICAgIHN0cm0uYWRsZXIgPSBzdGF0ZS5jaGVjayA9XG4gICAgICAgICAgICAgICAgLypVUERBVEVfQ0hFQ0soc3RhdGUuY2hlY2ssIHB1dCAtIF9vdXQsIF9vdXQpOyovXG4gICAgICAgICAgICAgICAgKHN0YXRlLmZsYWdzID8gY3JjMzJfMShzdGF0ZS5jaGVjaywgb3V0cHV0LCBfb3V0LCBwdXQgLSBfb3V0KSA6IGFkbGVyMzJfMShzdGF0ZS5jaGVjaywgb3V0cHV0LCBfb3V0LCBwdXQgLSBfb3V0KSk7XG5cbiAgICAgICAgICB9XG4gICAgICAgICAgX291dCA9IGxlZnQ7XG4gICAgICAgICAgLy8gTkI6IGNyYzMyIHN0b3JlZCBhcyBzaWduZWQgMzItYml0IGludCwgenN3YXAzMiByZXR1cm5zIHNpZ25lZCB0b29cbiAgICAgICAgICBpZiAoKHN0YXRlLndyYXAgJiA0KSAmJiAoc3RhdGUuZmxhZ3MgPyBob2xkIDogenN3YXAzMihob2xkKSkgIT09IHN0YXRlLmNoZWNrKSB7XG4gICAgICAgICAgICBzdHJtLm1zZyA9ICdpbmNvcnJlY3QgZGF0YSBjaGVjayc7XG4gICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vPT09IElOSVRCSVRTKCk7XG4gICAgICAgICAgaG9sZCA9IDA7XG4gICAgICAgICAgYml0cyA9IDA7XG4gICAgICAgICAgLy89PT0vL1xuICAgICAgICAgIC8vVHJhY2V2KChzdGRlcnIsIFwiaW5mbGF0ZTogICBjaGVjayBtYXRjaGVzIHRyYWlsZXJcXG5cIikpO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRlLm1vZGUgPSBMRU5HVEg7XG4gICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgIGNhc2UgTEVOR1RIOlxuICAgICAgICBpZiAoc3RhdGUud3JhcCAmJiBzdGF0ZS5mbGFncykge1xuICAgICAgICAgIC8vPT09IE5FRURCSVRTKDMyKTtcbiAgICAgICAgICB3aGlsZSAoYml0cyA8IDMyKSB7XG4gICAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgeyBicmVhayBpbmZfbGVhdmU7IH1cbiAgICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICAgICAgYml0cyArPSA4O1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLz09PS8vXG4gICAgICAgICAgaWYgKChzdGF0ZS53cmFwICYgNCkgJiYgaG9sZCAhPT0gKHN0YXRlLnRvdGFsICYgMHhmZmZmZmZmZikpIHtcbiAgICAgICAgICAgIHN0cm0ubXNnID0gJ2luY29ycmVjdCBsZW5ndGggY2hlY2snO1xuICAgICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLz09PSBJTklUQklUUygpO1xuICAgICAgICAgIGhvbGQgPSAwO1xuICAgICAgICAgIGJpdHMgPSAwO1xuICAgICAgICAgIC8vPT09Ly9cbiAgICAgICAgICAvL1RyYWNldigoc3RkZXJyLCBcImluZmxhdGU6ICAgbGVuZ3RoIG1hdGNoZXMgdHJhaWxlclxcblwiKSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGUubW9kZSA9IERPTkU7XG4gICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgIGNhc2UgRE9ORTpcbiAgICAgICAgcmV0ID0gWl9TVFJFQU1fRU5EJDE7XG4gICAgICAgIGJyZWFrIGluZl9sZWF2ZTtcbiAgICAgIGNhc2UgQkFEOlxuICAgICAgICByZXQgPSBaX0RBVEFfRVJST1IkMTtcbiAgICAgICAgYnJlYWsgaW5mX2xlYXZlO1xuICAgICAgY2FzZSBNRU06XG4gICAgICAgIHJldHVybiBaX01FTV9FUlJPUiQxO1xuICAgICAgY2FzZSBTWU5DOlxuICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gWl9TVFJFQU1fRVJST1IkMTtcbiAgICB9XG4gIH1cblxuICAvLyBpbmZfbGVhdmUgPC0gaGVyZSBpcyByZWFsIHBsYWNlIGZvciBcImdvdG8gaW5mX2xlYXZlXCIsIGVtdWxhdGVkIHZpYSBcImJyZWFrIGluZl9sZWF2ZVwiXG5cbiAgLypcbiAgICAgUmV0dXJuIGZyb20gaW5mbGF0ZSgpLCB1cGRhdGluZyB0aGUgdG90YWwgY291bnRzIGFuZCB0aGUgY2hlY2sgdmFsdWUuXG4gICAgIElmIHRoZXJlIHdhcyBubyBwcm9ncmVzcyBkdXJpbmcgdGhlIGluZmxhdGUoKSBjYWxsLCByZXR1cm4gYSBidWZmZXJcbiAgICAgZXJyb3IuICBDYWxsIHVwZGF0ZXdpbmRvdygpIHRvIGNyZWF0ZSBhbmQvb3IgdXBkYXRlIHRoZSB3aW5kb3cgc3RhdGUuXG4gICAgIE5vdGU6IGEgbWVtb3J5IGVycm9yIGZyb20gaW5mbGF0ZSgpIGlzIG5vbi1yZWNvdmVyYWJsZS5cbiAgICovXG5cbiAgLy8tLS0gUkVTVE9SRSgpIC0tLVxuICBzdHJtLm5leHRfb3V0ID0gcHV0O1xuICBzdHJtLmF2YWlsX291dCA9IGxlZnQ7XG4gIHN0cm0ubmV4dF9pbiA9IG5leHQ7XG4gIHN0cm0uYXZhaWxfaW4gPSBoYXZlO1xuICBzdGF0ZS5ob2xkID0gaG9sZDtcbiAgc3RhdGUuYml0cyA9IGJpdHM7XG4gIC8vLS0tXG5cbiAgaWYgKHN0YXRlLndzaXplIHx8IChfb3V0ICE9PSBzdHJtLmF2YWlsX291dCAmJiBzdGF0ZS5tb2RlIDwgQkFEICYmXG4gICAgICAgICAgICAgICAgICAgICAgKHN0YXRlLm1vZGUgPCBDSEVDSyB8fCBmbHVzaCAhPT0gWl9GSU5JU0gkMSkpKSB7XG4gICAgaWYgKHVwZGF0ZXdpbmRvdyhzdHJtLCBzdHJtLm91dHB1dCwgc3RybS5uZXh0X291dCwgX291dCAtIHN0cm0uYXZhaWxfb3V0KSkgO1xuICB9XG4gIF9pbiAtPSBzdHJtLmF2YWlsX2luO1xuICBfb3V0IC09IHN0cm0uYXZhaWxfb3V0O1xuICBzdHJtLnRvdGFsX2luICs9IF9pbjtcbiAgc3RybS50b3RhbF9vdXQgKz0gX291dDtcbiAgc3RhdGUudG90YWwgKz0gX291dDtcbiAgaWYgKChzdGF0ZS53cmFwICYgNCkgJiYgX291dCkge1xuICAgIHN0cm0uYWRsZXIgPSBzdGF0ZS5jaGVjayA9IC8qVVBEQVRFX0NIRUNLKHN0YXRlLmNoZWNrLCBzdHJtLm5leHRfb3V0IC0gX291dCwgX291dCk7Ki9cbiAgICAgIChzdGF0ZS5mbGFncyA/IGNyYzMyXzEoc3RhdGUuY2hlY2ssIG91dHB1dCwgX291dCwgc3RybS5uZXh0X291dCAtIF9vdXQpIDogYWRsZXIzMl8xKHN0YXRlLmNoZWNrLCBvdXRwdXQsIF9vdXQsIHN0cm0ubmV4dF9vdXQgLSBfb3V0KSk7XG4gIH1cbiAgc3RybS5kYXRhX3R5cGUgPSBzdGF0ZS5iaXRzICsgKHN0YXRlLmxhc3QgPyA2NCA6IDApICtcbiAgICAgICAgICAgICAgICAgICAgKHN0YXRlLm1vZGUgPT09IFRZUEUgPyAxMjggOiAwKSArXG4gICAgICAgICAgICAgICAgICAgIChzdGF0ZS5tb2RlID09PSBMRU5fIHx8IHN0YXRlLm1vZGUgPT09IENPUFlfID8gMjU2IDogMCk7XG4gIGlmICgoKF9pbiA9PT0gMCAmJiBfb3V0ID09PSAwKSB8fCBmbHVzaCA9PT0gWl9GSU5JU0gkMSkgJiYgcmV0ID09PSBaX09LJDEpIHtcbiAgICByZXQgPSBaX0JVRl9FUlJPUjtcbiAgfVxuICByZXR1cm4gcmV0O1xufTtcblxuXG5jb25zdCBpbmZsYXRlRW5kID0gKHN0cm0pID0+IHtcblxuICBpZiAoaW5mbGF0ZVN0YXRlQ2hlY2soc3RybSkpIHtcbiAgICByZXR1cm4gWl9TVFJFQU1fRVJST1IkMTtcbiAgfVxuXG4gIGxldCBzdGF0ZSA9IHN0cm0uc3RhdGU7XG4gIGlmIChzdGF0ZS53aW5kb3cpIHtcbiAgICBzdGF0ZS53aW5kb3cgPSBudWxsO1xuICB9XG4gIHN0cm0uc3RhdGUgPSBudWxsO1xuICByZXR1cm4gWl9PSyQxO1xufTtcblxuXG5jb25zdCBpbmZsYXRlR2V0SGVhZGVyID0gKHN0cm0sIGhlYWQpID0+IHtcblxuICAvKiBjaGVjayBzdGF0ZSAqL1xuICBpZiAoaW5mbGF0ZVN0YXRlQ2hlY2soc3RybSkpIHsgcmV0dXJuIFpfU1RSRUFNX0VSUk9SJDE7IH1cbiAgY29uc3Qgc3RhdGUgPSBzdHJtLnN0YXRlO1xuICBpZiAoKHN0YXRlLndyYXAgJiAyKSA9PT0gMCkgeyByZXR1cm4gWl9TVFJFQU1fRVJST1IkMTsgfVxuXG4gIC8qIHNhdmUgaGVhZGVyIHN0cnVjdHVyZSAqL1xuICBzdGF0ZS5oZWFkID0gaGVhZDtcbiAgaGVhZC5kb25lID0gZmFsc2U7XG4gIHJldHVybiBaX09LJDE7XG59O1xuXG5cbmNvbnN0IGluZmxhdGVTZXREaWN0aW9uYXJ5ID0gKHN0cm0sIGRpY3Rpb25hcnkpID0+IHtcbiAgY29uc3QgZGljdExlbmd0aCA9IGRpY3Rpb25hcnkubGVuZ3RoO1xuXG4gIGxldCBzdGF0ZTtcbiAgbGV0IGRpY3RpZDtcbiAgbGV0IHJldDtcblxuICAvKiBjaGVjayBzdGF0ZSAqL1xuICBpZiAoaW5mbGF0ZVN0YXRlQ2hlY2soc3RybSkpIHsgcmV0dXJuIFpfU1RSRUFNX0VSUk9SJDE7IH1cbiAgc3RhdGUgPSBzdHJtLnN0YXRlO1xuXG4gIGlmIChzdGF0ZS53cmFwICE9PSAwICYmIHN0YXRlLm1vZGUgIT09IERJQ1QpIHtcbiAgICByZXR1cm4gWl9TVFJFQU1fRVJST1IkMTtcbiAgfVxuXG4gIC8qIGNoZWNrIGZvciBjb3JyZWN0IGRpY3Rpb25hcnkgaWRlbnRpZmllciAqL1xuICBpZiAoc3RhdGUubW9kZSA9PT0gRElDVCkge1xuICAgIGRpY3RpZCA9IDE7IC8qIGFkbGVyMzIoMCwgbnVsbCwgMCkqL1xuICAgIC8qIGRpY3RpZCA9IGFkbGVyMzIoZGljdGlkLCBkaWN0aW9uYXJ5LCBkaWN0TGVuZ3RoKTsgKi9cbiAgICBkaWN0aWQgPSBhZGxlcjMyXzEoZGljdGlkLCBkaWN0aW9uYXJ5LCBkaWN0TGVuZ3RoLCAwKTtcbiAgICBpZiAoZGljdGlkICE9PSBzdGF0ZS5jaGVjaykge1xuICAgICAgcmV0dXJuIFpfREFUQV9FUlJPUiQxO1xuICAgIH1cbiAgfVxuICAvKiBjb3B5IGRpY3Rpb25hcnkgdG8gd2luZG93IHVzaW5nIHVwZGF0ZXdpbmRvdygpLCB3aGljaCB3aWxsIGFtZW5kIHRoZVxuICAgZXhpc3RpbmcgZGljdGlvbmFyeSBpZiBhcHByb3ByaWF0ZSAqL1xuICByZXQgPSB1cGRhdGV3aW5kb3coc3RybSwgZGljdGlvbmFyeSwgZGljdExlbmd0aCwgZGljdExlbmd0aCk7XG4gIGlmIChyZXQpIHtcbiAgICBzdGF0ZS5tb2RlID0gTUVNO1xuICAgIHJldHVybiBaX01FTV9FUlJPUiQxO1xuICB9XG4gIHN0YXRlLmhhdmVkaWN0ID0gMTtcbiAgLy8gVHJhY2V2KChzdGRlcnIsIFwiaW5mbGF0ZTogICBkaWN0aW9uYXJ5IHNldFxcblwiKSk7XG4gIHJldHVybiBaX09LJDE7XG59O1xuXG5cbnZhciBpbmZsYXRlUmVzZXRfMSA9IGluZmxhdGVSZXNldDtcbnZhciBpbmZsYXRlUmVzZXQyXzEgPSBpbmZsYXRlUmVzZXQyO1xudmFyIGluZmxhdGVSZXNldEtlZXBfMSA9IGluZmxhdGVSZXNldEtlZXA7XG52YXIgaW5mbGF0ZUluaXRfMSA9IGluZmxhdGVJbml0O1xudmFyIGluZmxhdGVJbml0Ml8xID0gaW5mbGF0ZUluaXQyO1xudmFyIGluZmxhdGVfMiQxID0gaW5mbGF0ZSQyO1xudmFyIGluZmxhdGVFbmRfMSA9IGluZmxhdGVFbmQ7XG52YXIgaW5mbGF0ZUdldEhlYWRlcl8xID0gaW5mbGF0ZUdldEhlYWRlcjtcbnZhciBpbmZsYXRlU2V0RGljdGlvbmFyeV8xID0gaW5mbGF0ZVNldERpY3Rpb25hcnk7XG52YXIgaW5mbGF0ZUluZm8gPSAncGFrbyBpbmZsYXRlIChmcm9tIE5vZGVjYSBwcm9qZWN0KSc7XG5cbi8qIE5vdCBpbXBsZW1lbnRlZFxubW9kdWxlLmV4cG9ydHMuaW5mbGF0ZUNvZGVzVXNlZCA9IGluZmxhdGVDb2Rlc1VzZWQ7XG5tb2R1bGUuZXhwb3J0cy5pbmZsYXRlQ29weSA9IGluZmxhdGVDb3B5O1xubW9kdWxlLmV4cG9ydHMuaW5mbGF0ZUdldERpY3Rpb25hcnkgPSBpbmZsYXRlR2V0RGljdGlvbmFyeTtcbm1vZHVsZS5leHBvcnRzLmluZmxhdGVNYXJrID0gaW5mbGF0ZU1hcms7XG5tb2R1bGUuZXhwb3J0cy5pbmZsYXRlUHJpbWUgPSBpbmZsYXRlUHJpbWU7XG5tb2R1bGUuZXhwb3J0cy5pbmZsYXRlU3luYyA9IGluZmxhdGVTeW5jO1xubW9kdWxlLmV4cG9ydHMuaW5mbGF0ZVN5bmNQb2ludCA9IGluZmxhdGVTeW5jUG9pbnQ7XG5tb2R1bGUuZXhwb3J0cy5pbmZsYXRlVW5kZXJtaW5lID0gaW5mbGF0ZVVuZGVybWluZTtcbm1vZHVsZS5leHBvcnRzLmluZmxhdGVWYWxpZGF0ZSA9IGluZmxhdGVWYWxpZGF0ZTtcbiovXG5cbnZhciBpbmZsYXRlXzEkMiA9IHtcblx0aW5mbGF0ZVJlc2V0OiBpbmZsYXRlUmVzZXRfMSxcblx0aW5mbGF0ZVJlc2V0MjogaW5mbGF0ZVJlc2V0Ml8xLFxuXHRpbmZsYXRlUmVzZXRLZWVwOiBpbmZsYXRlUmVzZXRLZWVwXzEsXG5cdGluZmxhdGVJbml0OiBpbmZsYXRlSW5pdF8xLFxuXHRpbmZsYXRlSW5pdDI6IGluZmxhdGVJbml0Ml8xLFxuXHRpbmZsYXRlOiBpbmZsYXRlXzIkMSxcblx0aW5mbGF0ZUVuZDogaW5mbGF0ZUVuZF8xLFxuXHRpbmZsYXRlR2V0SGVhZGVyOiBpbmZsYXRlR2V0SGVhZGVyXzEsXG5cdGluZmxhdGVTZXREaWN0aW9uYXJ5OiBpbmZsYXRlU2V0RGljdGlvbmFyeV8xLFxuXHRpbmZsYXRlSW5mbzogaW5mbGF0ZUluZm9cbn07XG5cbi8vIChDKSAxOTk1LTIwMTMgSmVhbi1sb3VwIEdhaWxseSBhbmQgTWFyayBBZGxlclxuLy8gKEMpIDIwMTQtMjAxNyBWaXRhbHkgUHV6cmluIGFuZCBBbmRyZXkgVHVwaXRzaW5cbi8vXG4vLyBUaGlzIHNvZnR3YXJlIGlzIHByb3ZpZGVkICdhcy1pcycsIHdpdGhvdXQgYW55IGV4cHJlc3Mgb3IgaW1wbGllZFxuLy8gd2FycmFudHkuIEluIG5vIGV2ZW50IHdpbGwgdGhlIGF1dGhvcnMgYmUgaGVsZCBsaWFibGUgZm9yIGFueSBkYW1hZ2VzXG4vLyBhcmlzaW5nIGZyb20gdGhlIHVzZSBvZiB0aGlzIHNvZnR3YXJlLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgZ3JhbnRlZCB0byBhbnlvbmUgdG8gdXNlIHRoaXMgc29mdHdhcmUgZm9yIGFueSBwdXJwb3NlLFxuLy8gaW5jbHVkaW5nIGNvbW1lcmNpYWwgYXBwbGljYXRpb25zLCBhbmQgdG8gYWx0ZXIgaXQgYW5kIHJlZGlzdHJpYnV0ZSBpdFxuLy8gZnJlZWx5LCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgcmVzdHJpY3Rpb25zOlxuLy9cbi8vIDEuIFRoZSBvcmlnaW4gb2YgdGhpcyBzb2Z0d2FyZSBtdXN0IG5vdCBiZSBtaXNyZXByZXNlbnRlZDsgeW91IG11c3Qgbm90XG4vLyAgIGNsYWltIHRoYXQgeW91IHdyb3RlIHRoZSBvcmlnaW5hbCBzb2Z0d2FyZS4gSWYgeW91IHVzZSB0aGlzIHNvZnR3YXJlXG4vLyAgIGluIGEgcHJvZHVjdCwgYW4gYWNrbm93bGVkZ21lbnQgaW4gdGhlIHByb2R1Y3QgZG9jdW1lbnRhdGlvbiB3b3VsZCBiZVxuLy8gICBhcHByZWNpYXRlZCBidXQgaXMgbm90IHJlcXVpcmVkLlxuLy8gMi4gQWx0ZXJlZCBzb3VyY2UgdmVyc2lvbnMgbXVzdCBiZSBwbGFpbmx5IG1hcmtlZCBhcyBzdWNoLCBhbmQgbXVzdCBub3QgYmVcbi8vICAgbWlzcmVwcmVzZW50ZWQgYXMgYmVpbmcgdGhlIG9yaWdpbmFsIHNvZnR3YXJlLlxuLy8gMy4gVGhpcyBub3RpY2UgbWF5IG5vdCBiZSByZW1vdmVkIG9yIGFsdGVyZWQgZnJvbSBhbnkgc291cmNlIGRpc3RyaWJ1dGlvbi5cblxuZnVuY3Rpb24gR1poZWFkZXIoKSB7XG4gIC8qIHRydWUgaWYgY29tcHJlc3NlZCBkYXRhIGJlbGlldmVkIHRvIGJlIHRleHQgKi9cbiAgdGhpcy50ZXh0ICAgICAgID0gMDtcbiAgLyogbW9kaWZpY2F0aW9uIHRpbWUgKi9cbiAgdGhpcy50aW1lICAgICAgID0gMDtcbiAgLyogZXh0cmEgZmxhZ3MgKG5vdCB1c2VkIHdoZW4gd3JpdGluZyBhIGd6aXAgZmlsZSkgKi9cbiAgdGhpcy54ZmxhZ3MgICAgID0gMDtcbiAgLyogb3BlcmF0aW5nIHN5c3RlbSAqL1xuICB0aGlzLm9zICAgICAgICAgPSAwO1xuICAvKiBwb2ludGVyIHRvIGV4dHJhIGZpZWxkIG9yIFpfTlVMTCBpZiBub25lICovXG4gIHRoaXMuZXh0cmEgICAgICA9IG51bGw7XG4gIC8qIGV4dHJhIGZpZWxkIGxlbmd0aCAodmFsaWQgaWYgZXh0cmEgIT0gWl9OVUxMKSAqL1xuICB0aGlzLmV4dHJhX2xlbiAgPSAwOyAvLyBBY3R1YWxseSwgd2UgZG9uJ3QgbmVlZCBpdCBpbiBKUyxcbiAgICAgICAgICAgICAgICAgICAgICAgLy8gYnV0IGxlYXZlIGZvciBmZXcgY29kZSBtb2RpZmljYXRpb25zXG5cbiAgLy9cbiAgLy8gU2V0dXAgbGltaXRzIGlzIG5vdCBuZWNlc3NhcnkgYmVjYXVzZSBpbiBqcyB3ZSBzaG91bGQgbm90IHByZWFsbG9jYXRlIG1lbW9yeVxuICAvLyBmb3IgaW5mbGF0ZSB1c2UgY29uc3RhbnQgbGltaXQgaW4gNjU1MzYgYnl0ZXNcbiAgLy9cblxuICAvKiBzcGFjZSBhdCBleHRyYSAob25seSB3aGVuIHJlYWRpbmcgaGVhZGVyKSAqL1xuICAvLyB0aGlzLmV4dHJhX21heCAgPSAwO1xuICAvKiBwb2ludGVyIHRvIHplcm8tdGVybWluYXRlZCBmaWxlIG5hbWUgb3IgWl9OVUxMICovXG4gIHRoaXMubmFtZSAgICAgICA9ICcnO1xuICAvKiBzcGFjZSBhdCBuYW1lIChvbmx5IHdoZW4gcmVhZGluZyBoZWFkZXIpICovXG4gIC8vIHRoaXMubmFtZV9tYXggICA9IDA7XG4gIC8qIHBvaW50ZXIgdG8gemVyby10ZXJtaW5hdGVkIGNvbW1lbnQgb3IgWl9OVUxMICovXG4gIHRoaXMuY29tbWVudCAgICA9ICcnO1xuICAvKiBzcGFjZSBhdCBjb21tZW50IChvbmx5IHdoZW4gcmVhZGluZyBoZWFkZXIpICovXG4gIC8vIHRoaXMuY29tbV9tYXggICA9IDA7XG4gIC8qIHRydWUgaWYgdGhlcmUgd2FzIG9yIHdpbGwgYmUgYSBoZWFkZXIgY3JjICovXG4gIHRoaXMuaGNyYyAgICAgICA9IDA7XG4gIC8qIHRydWUgd2hlbiBkb25lIHJlYWRpbmcgZ3ppcCBoZWFkZXIgKG5vdCB1c2VkIHdoZW4gd3JpdGluZyBhIGd6aXAgZmlsZSkgKi9cbiAgdGhpcy5kb25lICAgICAgID0gZmFsc2U7XG59XG5cbnZhciBnemhlYWRlciA9IEdaaGVhZGVyO1xuXG5jb25zdCB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbi8qIFB1YmxpYyBjb25zdGFudHMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qL1xuXG5jb25zdCB7XG4gIFpfTk9fRkxVU0gsIFpfRklOSVNILFxuICBaX09LLCBaX1NUUkVBTV9FTkQsIFpfTkVFRF9ESUNULCBaX1NUUkVBTV9FUlJPUiwgWl9EQVRBX0VSUk9SLCBaX01FTV9FUlJPUlxufSA9IGNvbnN0YW50cyQyO1xuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qL1xuXG5cbi8qKlxuICogY2xhc3MgSW5mbGF0ZVxuICpcbiAqIEdlbmVyaWMgSlMtc3R5bGUgd3JhcHBlciBmb3IgemxpYiBjYWxscy4gSWYgeW91IGRvbid0IG5lZWRcbiAqIHN0cmVhbWluZyBiZWhhdmlvdXIgLSB1c2UgbW9yZSBzaW1wbGUgZnVuY3Rpb25zOiBbW2luZmxhdGVdXVxuICogYW5kIFtbaW5mbGF0ZVJhd11dLlxuICoqL1xuXG4vKiBpbnRlcm5hbFxuICogaW5mbGF0ZS5jaHVua3MgLT4gQXJyYXlcbiAqXG4gKiBDaHVua3Mgb2Ygb3V0cHV0IGRhdGEsIGlmIFtbSW5mbGF0ZSNvbkRhdGFdXSBub3Qgb3ZlcnJpZGRlbi5cbiAqKi9cblxuLyoqXG4gKiBJbmZsYXRlLnJlc3VsdCAtPiBVaW50OEFycmF5fFN0cmluZ1xuICpcbiAqIFVuY29tcHJlc3NlZCByZXN1bHQsIGdlbmVyYXRlZCBieSBkZWZhdWx0IFtbSW5mbGF0ZSNvbkRhdGFdXVxuICogYW5kIFtbSW5mbGF0ZSNvbkVuZF1dIGhhbmRsZXJzLiBGaWxsZWQgYWZ0ZXIgeW91IHB1c2ggbGFzdCBjaHVua1xuICogKGNhbGwgW1tJbmZsYXRlI3B1c2hdXSB3aXRoIGBaX0ZJTklTSGAgLyBgdHJ1ZWAgcGFyYW0pLlxuICoqL1xuXG4vKipcbiAqIEluZmxhdGUuZXJyIC0+IE51bWJlclxuICpcbiAqIEVycm9yIGNvZGUgYWZ0ZXIgaW5mbGF0ZSBmaW5pc2hlZC4gMCAoWl9PSykgb24gc3VjY2Vzcy5cbiAqIFNob3VsZCBiZSBjaGVja2VkIGlmIGJyb2tlbiBkYXRhIHBvc3NpYmxlLlxuICoqL1xuXG4vKipcbiAqIEluZmxhdGUubXNnIC0+IFN0cmluZ1xuICpcbiAqIEVycm9yIG1lc3NhZ2UsIGlmIFtbSW5mbGF0ZS5lcnJdXSAhPSAwXG4gKiovXG5cblxuLyoqXG4gKiBuZXcgSW5mbGF0ZShvcHRpb25zKVxuICogLSBvcHRpb25zIChPYmplY3QpOiB6bGliIGluZmxhdGUgb3B0aW9ucy5cbiAqXG4gKiBDcmVhdGVzIG5ldyBpbmZsYXRvciBpbnN0YW5jZSB3aXRoIHNwZWNpZmllZCBwYXJhbXMuIFRocm93cyBleGNlcHRpb25cbiAqIG9uIGJhZCBwYXJhbXMuIFN1cHBvcnRlZCBvcHRpb25zOlxuICpcbiAqIC0gYHdpbmRvd0JpdHNgXG4gKiAtIGBkaWN0aW9uYXJ5YFxuICpcbiAqIFtodHRwOi8vemxpYi5uZXQvbWFudWFsLmh0bWwjQWR2YW5jZWRdKGh0dHA6Ly96bGliLm5ldC9tYW51YWwuaHRtbCNBZHZhbmNlZClcbiAqIGZvciBtb3JlIGluZm9ybWF0aW9uIG9uIHRoZXNlLlxuICpcbiAqIEFkZGl0aW9uYWwgb3B0aW9ucywgZm9yIGludGVybmFsIG5lZWRzOlxuICpcbiAqIC0gYGNodW5rU2l6ZWAgLSBzaXplIG9mIGdlbmVyYXRlZCBkYXRhIGNodW5rcyAoMTZLIGJ5IGRlZmF1bHQpXG4gKiAtIGByYXdgIChCb29sZWFuKSAtIGRvIHJhdyBpbmZsYXRlXG4gKiAtIGB0b2AgKFN0cmluZykgLSBpZiBlcXVhbCB0byAnc3RyaW5nJywgdGhlbiByZXN1bHQgd2lsbCBiZSBjb252ZXJ0ZWRcbiAqICAgZnJvbSB1dGY4IHRvIHV0ZjE2IChqYXZhc2NyaXB0KSBzdHJpbmcuIFdoZW4gc3RyaW5nIG91dHB1dCByZXF1ZXN0ZWQsXG4gKiAgIGNodW5rIGxlbmd0aCBjYW4gZGlmZmVyIGZyb20gYGNodW5rU2l6ZWAsIGRlcGVuZGluZyBvbiBjb250ZW50LlxuICpcbiAqIEJ5IGRlZmF1bHQsIHdoZW4gbm8gb3B0aW9ucyBzZXQsIGF1dG9kZXRlY3QgZGVmbGF0ZS9nemlwIGRhdGEgZm9ybWF0IHZpYVxuICogd3JhcHBlciBoZWFkZXIuXG4gKlxuICogIyMjIyMgRXhhbXBsZTpcbiAqXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBjb25zdCBwYWtvID0gcmVxdWlyZSgncGFrbycpXG4gKiBjb25zdCBjaHVuazEgPSBuZXcgVWludDhBcnJheShbMSwyLDMsNCw1LDYsNyw4LDldKVxuICogY29uc3QgY2h1bmsyID0gbmV3IFVpbnQ4QXJyYXkoWzEwLDExLDEyLDEzLDE0LDE1LDE2LDE3LDE4LDE5XSk7XG4gKlxuICogY29uc3QgaW5mbGF0ZSA9IG5ldyBwYWtvLkluZmxhdGUoeyBsZXZlbDogM30pO1xuICpcbiAqIGluZmxhdGUucHVzaChjaHVuazEsIGZhbHNlKTtcbiAqIGluZmxhdGUucHVzaChjaHVuazIsIHRydWUpOyAgLy8gdHJ1ZSAtPiBsYXN0IGNodW5rXG4gKlxuICogaWYgKGluZmxhdGUuZXJyKSB7IHRocm93IG5ldyBFcnJvcihpbmZsYXRlLmVycik7IH1cbiAqXG4gKiBjb25zb2xlLmxvZyhpbmZsYXRlLnJlc3VsdCk7XG4gKiBgYGBcbiAqKi9cbmZ1bmN0aW9uIEluZmxhdGUkMShvcHRpb25zKSB7XG4gIHRoaXMub3B0aW9ucyA9IGNvbW1vbi5hc3NpZ24oe1xuICAgIGNodW5rU2l6ZTogMTAyNCAqIDY0LFxuICAgIHdpbmRvd0JpdHM6IDE1LFxuICAgIHRvOiAnJ1xuICB9LCBvcHRpb25zIHx8IHt9KTtcblxuICBjb25zdCBvcHQgPSB0aGlzLm9wdGlvbnM7XG5cbiAgLy8gRm9yY2Ugd2luZG93IHNpemUgZm9yIGByYXdgIGRhdGEsIGlmIG5vdCBzZXQgZGlyZWN0bHksXG4gIC8vIGJlY2F1c2Ugd2UgaGF2ZSBubyBoZWFkZXIgZm9yIGF1dG9kZXRlY3QuXG4gIGlmIChvcHQucmF3ICYmIChvcHQud2luZG93Qml0cyA+PSAwKSAmJiAob3B0LndpbmRvd0JpdHMgPCAxNikpIHtcbiAgICBvcHQud2luZG93Qml0cyA9IC1vcHQud2luZG93Qml0cztcbiAgICBpZiAob3B0LndpbmRvd0JpdHMgPT09IDApIHsgb3B0LndpbmRvd0JpdHMgPSAtMTU7IH1cbiAgfVxuXG4gIC8vIElmIGB3aW5kb3dCaXRzYCBub3QgZGVmaW5lZCAoYW5kIG1vZGUgbm90IHJhdykgLSBzZXQgYXV0b2RldGVjdCBmbGFnIGZvciBnemlwL2RlZmxhdGVcbiAgaWYgKChvcHQud2luZG93Qml0cyA+PSAwKSAmJiAob3B0LndpbmRvd0JpdHMgPCAxNikgJiZcbiAgICAgICEob3B0aW9ucyAmJiBvcHRpb25zLndpbmRvd0JpdHMpKSB7XG4gICAgb3B0LndpbmRvd0JpdHMgKz0gMzI7XG4gIH1cblxuICAvLyBHemlwIGhlYWRlciBoYXMgbm8gaW5mbyBhYm91dCB3aW5kb3dzIHNpemUsIHdlIGNhbiBkbyBhdXRvZGV0ZWN0IG9ubHlcbiAgLy8gZm9yIGRlZmxhdGUuIFNvLCBpZiB3aW5kb3cgc2l6ZSBub3Qgc2V0LCBmb3JjZSBpdCB0byBtYXggd2hlbiBnemlwIHBvc3NpYmxlXG4gIGlmICgob3B0LndpbmRvd0JpdHMgPiAxNSkgJiYgKG9wdC53aW5kb3dCaXRzIDwgNDgpKSB7XG4gICAgLy8gYml0IDMgKDE2KSAtPiBnemlwcGVkIGRhdGFcbiAgICAvLyBiaXQgNCAoMzIpIC0+IGF1dG9kZXRlY3QgZ3ppcC9kZWZsYXRlXG4gICAgaWYgKChvcHQud2luZG93Qml0cyAmIDE1KSA9PT0gMCkge1xuICAgICAgb3B0LndpbmRvd0JpdHMgfD0gMTU7XG4gICAgfVxuICB9XG5cbiAgdGhpcy5lcnIgICAgPSAwOyAgICAgIC8vIGVycm9yIGNvZGUsIGlmIGhhcHBlbnMgKDAgPSBaX09LKVxuICB0aGlzLm1zZyAgICA9ICcnOyAgICAgLy8gZXJyb3IgbWVzc2FnZVxuICB0aGlzLmVuZGVkICA9IGZhbHNlOyAgLy8gdXNlZCB0byBhdm9pZCBtdWx0aXBsZSBvbkVuZCgpIGNhbGxzXG4gIHRoaXMuY2h1bmtzID0gW107ICAgICAvLyBjaHVua3Mgb2YgY29tcHJlc3NlZCBkYXRhXG5cbiAgdGhpcy5zdHJtICAgPSBuZXcgenN0cmVhbSgpO1xuICB0aGlzLnN0cm0uYXZhaWxfb3V0ID0gMDtcblxuICBsZXQgc3RhdHVzICA9IGluZmxhdGVfMSQyLmluZmxhdGVJbml0MihcbiAgICB0aGlzLnN0cm0sXG4gICAgb3B0LndpbmRvd0JpdHNcbiAgKTtcblxuICBpZiAoc3RhdHVzICE9PSBaX09LKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2VzW3N0YXR1c10pO1xuICB9XG5cbiAgdGhpcy5oZWFkZXIgPSBuZXcgZ3poZWFkZXIoKTtcblxuICBpbmZsYXRlXzEkMi5pbmZsYXRlR2V0SGVhZGVyKHRoaXMuc3RybSwgdGhpcy5oZWFkZXIpO1xuXG4gIC8vIFNldHVwIGRpY3Rpb25hcnlcbiAgaWYgKG9wdC5kaWN0aW9uYXJ5KSB7XG4gICAgLy8gQ29udmVydCBkYXRhIGlmIG5lZWRlZFxuICAgIGlmICh0eXBlb2Ygb3B0LmRpY3Rpb25hcnkgPT09ICdzdHJpbmcnKSB7XG4gICAgICBvcHQuZGljdGlvbmFyeSA9IHN0cmluZ3Muc3RyaW5nMmJ1ZihvcHQuZGljdGlvbmFyeSk7XG4gICAgfSBlbHNlIGlmICh0b1N0cmluZy5jYWxsKG9wdC5kaWN0aW9uYXJ5KSA9PT0gJ1tvYmplY3QgQXJyYXlCdWZmZXJdJykge1xuICAgICAgb3B0LmRpY3Rpb25hcnkgPSBuZXcgVWludDhBcnJheShvcHQuZGljdGlvbmFyeSk7XG4gICAgfVxuICAgIGlmIChvcHQucmF3KSB7IC8vSW4gcmF3IG1vZGUgd2UgbmVlZCB0byBzZXQgdGhlIGRpY3Rpb25hcnkgZWFybHlcbiAgICAgIHN0YXR1cyA9IGluZmxhdGVfMSQyLmluZmxhdGVTZXREaWN0aW9uYXJ5KHRoaXMuc3RybSwgb3B0LmRpY3Rpb25hcnkpO1xuICAgICAgaWYgKHN0YXR1cyAhPT0gWl9PSykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZXNbc3RhdHVzXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogSW5mbGF0ZSNwdXNoKGRhdGFbLCBmbHVzaF9tb2RlXSkgLT4gQm9vbGVhblxuICogLSBkYXRhIChVaW50OEFycmF5fEFycmF5QnVmZmVyKTogaW5wdXQgZGF0YVxuICogLSBmbHVzaF9tb2RlIChOdW1iZXJ8Qm9vbGVhbik6IDAuLjYgZm9yIGNvcnJlc3BvbmRpbmcgWl9OT19GTFVTSC4uWl9UUkVFXG4gKiAgIGZsdXNoIG1vZGVzLiBTZWUgY29uc3RhbnRzLiBTa2lwcGVkIG9yIGBmYWxzZWAgbWVhbnMgWl9OT19GTFVTSCxcbiAqICAgYHRydWVgIG1lYW5zIFpfRklOSVNILlxuICpcbiAqIFNlbmRzIGlucHV0IGRhdGEgdG8gaW5mbGF0ZSBwaXBlLCBnZW5lcmF0aW5nIFtbSW5mbGF0ZSNvbkRhdGFdXSBjYWxscyB3aXRoXG4gKiBuZXcgb3V0cHV0IGNodW5rcy4gUmV0dXJucyBgdHJ1ZWAgb24gc3VjY2Vzcy4gSWYgZW5kIG9mIHN0cmVhbSBkZXRlY3RlZCxcbiAqIFtbSW5mbGF0ZSNvbkVuZF1dIHdpbGwgYmUgY2FsbGVkLlxuICpcbiAqIGBmbHVzaF9tb2RlYCBpcyBub3QgbmVlZGVkIGZvciBub3JtYWwgb3BlcmF0aW9uLCBiZWNhdXNlIGVuZCBvZiBzdHJlYW1cbiAqIGRldGVjdGVkIGF1dG9tYXRpY2FsbHkuIFlvdSBtYXkgdHJ5IHRvIHVzZSBpdCBmb3IgYWR2YW5jZWQgdGhpbmdzLCBidXRcbiAqIHRoaXMgZnVuY3Rpb25hbGl0eSB3YXMgbm90IHRlc3RlZC5cbiAqXG4gKiBPbiBmYWlsIGNhbGwgW1tJbmZsYXRlI29uRW5kXV0gd2l0aCBlcnJvciBjb2RlIGFuZCByZXR1cm4gZmFsc2UuXG4gKlxuICogIyMjIyMgRXhhbXBsZVxuICpcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHB1c2goY2h1bmssIGZhbHNlKTsgLy8gcHVzaCBvbmUgb2YgZGF0YSBjaHVua3NcbiAqIC4uLlxuICogcHVzaChjaHVuaywgdHJ1ZSk7ICAvLyBwdXNoIGxhc3QgY2h1bmtcbiAqIGBgYFxuICoqL1xuSW5mbGF0ZSQxLnByb3RvdHlwZS5wdXNoID0gZnVuY3Rpb24gKGRhdGEsIGZsdXNoX21vZGUpIHtcbiAgY29uc3Qgc3RybSA9IHRoaXMuc3RybTtcbiAgY29uc3QgY2h1bmtTaXplID0gdGhpcy5vcHRpb25zLmNodW5rU2l6ZTtcbiAgY29uc3QgZGljdGlvbmFyeSA9IHRoaXMub3B0aW9ucy5kaWN0aW9uYXJ5O1xuICBsZXQgc3RhdHVzLCBfZmx1c2hfbW9kZSwgbGFzdF9hdmFpbF9vdXQ7XG5cbiAgaWYgKHRoaXMuZW5kZWQpIHJldHVybiBmYWxzZTtcblxuICBpZiAoZmx1c2hfbW9kZSA9PT0gfn5mbHVzaF9tb2RlKSBfZmx1c2hfbW9kZSA9IGZsdXNoX21vZGU7XG4gIGVsc2UgX2ZsdXNoX21vZGUgPSBmbHVzaF9tb2RlID09PSB0cnVlID8gWl9GSU5JU0ggOiBaX05PX0ZMVVNIO1xuXG4gIC8vIENvbnZlcnQgZGF0YSBpZiBuZWVkZWRcbiAgaWYgKHRvU3RyaW5nLmNhbGwoZGF0YSkgPT09ICdbb2JqZWN0IEFycmF5QnVmZmVyXScpIHtcbiAgICBzdHJtLmlucHV0ID0gbmV3IFVpbnQ4QXJyYXkoZGF0YSk7XG4gIH0gZWxzZSB7XG4gICAgc3RybS5pbnB1dCA9IGRhdGE7XG4gIH1cblxuICBzdHJtLm5leHRfaW4gPSAwO1xuICBzdHJtLmF2YWlsX2luID0gc3RybS5pbnB1dC5sZW5ndGg7XG5cbiAgZm9yICg7Oykge1xuICAgIGlmIChzdHJtLmF2YWlsX291dCA9PT0gMCkge1xuICAgICAgc3RybS5vdXRwdXQgPSBuZXcgVWludDhBcnJheShjaHVua1NpemUpO1xuICAgICAgc3RybS5uZXh0X291dCA9IDA7XG4gICAgICBzdHJtLmF2YWlsX291dCA9IGNodW5rU2l6ZTtcbiAgICB9XG5cbiAgICBzdGF0dXMgPSBpbmZsYXRlXzEkMi5pbmZsYXRlKHN0cm0sIF9mbHVzaF9tb2RlKTtcblxuICAgIGlmIChzdGF0dXMgPT09IFpfTkVFRF9ESUNUICYmIGRpY3Rpb25hcnkpIHtcbiAgICAgIHN0YXR1cyA9IGluZmxhdGVfMSQyLmluZmxhdGVTZXREaWN0aW9uYXJ5KHN0cm0sIGRpY3Rpb25hcnkpO1xuXG4gICAgICBpZiAoc3RhdHVzID09PSBaX09LKSB7XG4gICAgICAgIHN0YXR1cyA9IGluZmxhdGVfMSQyLmluZmxhdGUoc3RybSwgX2ZsdXNoX21vZGUpO1xuICAgICAgfSBlbHNlIGlmIChzdGF0dXMgPT09IFpfREFUQV9FUlJPUikge1xuICAgICAgICAvLyBSZXBsYWNlIGNvZGUgd2l0aCBtb3JlIHZlcmJvc2VcbiAgICAgICAgc3RhdHVzID0gWl9ORUVEX0RJQ1Q7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gU2tpcCBzbnljIG1hcmtlcnMgaWYgbW9yZSBkYXRhIGZvbGxvd3MgYW5kIG5vdCByYXcgbW9kZVxuICAgIHdoaWxlIChzdHJtLmF2YWlsX2luID4gMCAmJlxuICAgICAgICAgICBzdGF0dXMgPT09IFpfU1RSRUFNX0VORCAmJlxuICAgICAgICAgICBzdHJtLnN0YXRlLndyYXAgPiAwICYmXG4gICAgICAgICAgIGRhdGFbc3RybS5uZXh0X2luXSAhPT0gMClcbiAgICB7XG4gICAgICBpbmZsYXRlXzEkMi5pbmZsYXRlUmVzZXQoc3RybSk7XG4gICAgICBzdGF0dXMgPSBpbmZsYXRlXzEkMi5pbmZsYXRlKHN0cm0sIF9mbHVzaF9tb2RlKTtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKHN0YXR1cykge1xuICAgICAgY2FzZSBaX1NUUkVBTV9FUlJPUjpcbiAgICAgIGNhc2UgWl9EQVRBX0VSUk9SOlxuICAgICAgY2FzZSBaX05FRURfRElDVDpcbiAgICAgIGNhc2UgWl9NRU1fRVJST1I6XG4gICAgICAgIHRoaXMub25FbmQoc3RhdHVzKTtcbiAgICAgICAgdGhpcy5lbmRlZCA9IHRydWU7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBSZW1lbWJlciByZWFsIGBhdmFpbF9vdXRgIHZhbHVlLCBiZWNhdXNlIHdlIG1heSBwYXRjaCBvdXQgYnVmZmVyIGNvbnRlbnRcbiAgICAvLyB0byBhbGlnbiB1dGY4IHN0cmluZ3MgYm91bmRhcmllcy5cbiAgICBsYXN0X2F2YWlsX291dCA9IHN0cm0uYXZhaWxfb3V0O1xuXG4gICAgaWYgKHN0cm0ubmV4dF9vdXQpIHtcbiAgICAgIGlmIChzdHJtLmF2YWlsX291dCA9PT0gMCB8fCBzdGF0dXMgPT09IFpfU1RSRUFNX0VORCkge1xuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMudG8gPT09ICdzdHJpbmcnKSB7XG5cbiAgICAgICAgICBsZXQgbmV4dF9vdXRfdXRmOCA9IHN0cmluZ3MudXRmOGJvcmRlcihzdHJtLm91dHB1dCwgc3RybS5uZXh0X291dCk7XG5cbiAgICAgICAgICBsZXQgdGFpbCA9IHN0cm0ubmV4dF9vdXQgLSBuZXh0X291dF91dGY4O1xuICAgICAgICAgIGxldCB1dGY4c3RyID0gc3RyaW5ncy5idWYyc3RyaW5nKHN0cm0ub3V0cHV0LCBuZXh0X291dF91dGY4KTtcblxuICAgICAgICAgIC8vIG1vdmUgdGFpbCAmIHJlYWxpZ24gY291bnRlcnNcbiAgICAgICAgICBzdHJtLm5leHRfb3V0ID0gdGFpbDtcbiAgICAgICAgICBzdHJtLmF2YWlsX291dCA9IGNodW5rU2l6ZSAtIHRhaWw7XG4gICAgICAgICAgaWYgKHRhaWwpIHN0cm0ub3V0cHV0LnNldChzdHJtLm91dHB1dC5zdWJhcnJheShuZXh0X291dF91dGY4LCBuZXh0X291dF91dGY4ICsgdGFpbCksIDApO1xuXG4gICAgICAgICAgdGhpcy5vbkRhdGEodXRmOHN0cik7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLm9uRGF0YShzdHJtLm91dHB1dC5sZW5ndGggPT09IHN0cm0ubmV4dF9vdXQgPyBzdHJtLm91dHB1dCA6IHN0cm0ub3V0cHV0LnN1YmFycmF5KDAsIHN0cm0ubmV4dF9vdXQpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE11c3QgcmVwZWF0IGl0ZXJhdGlvbiBpZiBvdXQgYnVmZmVyIGlzIGZ1bGxcbiAgICBpZiAoc3RhdHVzID09PSBaX09LICYmIGxhc3RfYXZhaWxfb3V0ID09PSAwKSBjb250aW51ZTtcblxuICAgIC8vIEZpbmFsaXplIGlmIGVuZCBvZiBzdHJlYW0gcmVhY2hlZC5cbiAgICBpZiAoc3RhdHVzID09PSBaX1NUUkVBTV9FTkQpIHtcbiAgICAgIHN0YXR1cyA9IGluZmxhdGVfMSQyLmluZmxhdGVFbmQodGhpcy5zdHJtKTtcbiAgICAgIHRoaXMub25FbmQoc3RhdHVzKTtcbiAgICAgIHRoaXMuZW5kZWQgPSB0cnVlO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHN0cm0uYXZhaWxfaW4gPT09IDApIGJyZWFrO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5cbi8qKlxuICogSW5mbGF0ZSNvbkRhdGEoY2h1bmspIC0+IFZvaWRcbiAqIC0gY2h1bmsgKFVpbnQ4QXJyYXl8U3RyaW5nKTogb3V0cHV0IGRhdGEuIFdoZW4gc3RyaW5nIG91dHB1dCByZXF1ZXN0ZWQsXG4gKiAgIGVhY2ggY2h1bmsgd2lsbCBiZSBzdHJpbmcuXG4gKlxuICogQnkgZGVmYXVsdCwgc3RvcmVzIGRhdGEgYmxvY2tzIGluIGBjaHVua3NbXWAgcHJvcGVydHkgYW5kIGdsdWVcbiAqIHRob3NlIGluIGBvbkVuZGAuIE92ZXJyaWRlIHRoaXMgaGFuZGxlciwgaWYgeW91IG5lZWQgYW5vdGhlciBiZWhhdmlvdXIuXG4gKiovXG5JbmZsYXRlJDEucHJvdG90eXBlLm9uRGF0YSA9IGZ1bmN0aW9uIChjaHVuaykge1xuICB0aGlzLmNodW5rcy5wdXNoKGNodW5rKTtcbn07XG5cblxuLyoqXG4gKiBJbmZsYXRlI29uRW5kKHN0YXR1cykgLT4gVm9pZFxuICogLSBzdGF0dXMgKE51bWJlcik6IGluZmxhdGUgc3RhdHVzLiAwIChaX09LKSBvbiBzdWNjZXNzLFxuICogICBvdGhlciBpZiBub3QuXG4gKlxuICogQ2FsbGVkIGVpdGhlciBhZnRlciB5b3UgdGVsbCBpbmZsYXRlIHRoYXQgdGhlIGlucHV0IHN0cmVhbSBpc1xuICogY29tcGxldGUgKFpfRklOSVNIKS4gQnkgZGVmYXVsdCAtIGpvaW4gY29sbGVjdGVkIGNodW5rcyxcbiAqIGZyZWUgbWVtb3J5IGFuZCBmaWxsIGByZXN1bHRzYCAvIGBlcnJgIHByb3BlcnRpZXMuXG4gKiovXG5JbmZsYXRlJDEucHJvdG90eXBlLm9uRW5kID0gZnVuY3Rpb24gKHN0YXR1cykge1xuICAvLyBPbiBzdWNjZXNzIC0gam9pblxuICBpZiAoc3RhdHVzID09PSBaX09LKSB7XG4gICAgaWYgKHRoaXMub3B0aW9ucy50byA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRoaXMucmVzdWx0ID0gdGhpcy5jaHVua3Muam9pbignJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVzdWx0ID0gY29tbW9uLmZsYXR0ZW5DaHVua3ModGhpcy5jaHVua3MpO1xuICAgIH1cbiAgfVxuICB0aGlzLmNodW5rcyA9IFtdO1xuICB0aGlzLmVyciA9IHN0YXR1cztcbiAgdGhpcy5tc2cgPSB0aGlzLnN0cm0ubXNnO1xufTtcblxuXG4vKipcbiAqIGluZmxhdGUoZGF0YVssIG9wdGlvbnNdKSAtPiBVaW50OEFycmF5fFN0cmluZ1xuICogLSBkYXRhIChVaW50OEFycmF5fEFycmF5QnVmZmVyKTogaW5wdXQgZGF0YSB0byBkZWNvbXByZXNzLlxuICogLSBvcHRpb25zIChPYmplY3QpOiB6bGliIGluZmxhdGUgb3B0aW9ucy5cbiAqXG4gKiBEZWNvbXByZXNzIGBkYXRhYCB3aXRoIGluZmxhdGUvdW5nemlwIGFuZCBgb3B0aW9uc2AuIEF1dG9kZXRlY3RcbiAqIGZvcm1hdCB2aWEgd3JhcHBlciBoZWFkZXIgYnkgZGVmYXVsdC4gVGhhdCdzIHdoeSB3ZSBkb24ndCBwcm92aWRlXG4gKiBzZXBhcmF0ZSBgdW5nemlwYCBtZXRob2QuXG4gKlxuICogU3VwcG9ydGVkIG9wdGlvbnMgYXJlOlxuICpcbiAqIC0gd2luZG93Qml0c1xuICpcbiAqIFtodHRwOi8vemxpYi5uZXQvbWFudWFsLmh0bWwjQWR2YW5jZWRdKGh0dHA6Ly96bGliLm5ldC9tYW51YWwuaHRtbCNBZHZhbmNlZClcbiAqIGZvciBtb3JlIGluZm9ybWF0aW9uLlxuICpcbiAqIFN1Z2FyIChvcHRpb25zKTpcbiAqXG4gKiAtIGByYXdgIChCb29sZWFuKSAtIHNheSB0aGF0IHdlIHdvcmsgd2l0aCByYXcgc3RyZWFtLCBpZiB5b3UgZG9uJ3Qgd2lzaCB0byBzcGVjaWZ5XG4gKiAgIG5lZ2F0aXZlIHdpbmRvd0JpdHMgaW1wbGljaXRseS5cbiAqIC0gYHRvYCAoU3RyaW5nKSAtIGlmIGVxdWFsIHRvICdzdHJpbmcnLCB0aGVuIHJlc3VsdCB3aWxsIGJlIGNvbnZlcnRlZFxuICogICBmcm9tIHV0ZjggdG8gdXRmMTYgKGphdmFzY3JpcHQpIHN0cmluZy4gV2hlbiBzdHJpbmcgb3V0cHV0IHJlcXVlc3RlZCxcbiAqICAgY2h1bmsgbGVuZ3RoIGNhbiBkaWZmZXIgZnJvbSBgY2h1bmtTaXplYCwgZGVwZW5kaW5nIG9uIGNvbnRlbnQuXG4gKlxuICpcbiAqICMjIyMjIEV4YW1wbGU6XG4gKlxuICogYGBgamF2YXNjcmlwdFxuICogY29uc3QgcGFrbyA9IHJlcXVpcmUoJ3Bha28nKTtcbiAqIGNvbnN0IGlucHV0ID0gcGFrby5kZWZsYXRlKG5ldyBVaW50OEFycmF5KFsxLDIsMyw0LDUsNiw3LDgsOV0pKTtcbiAqIGxldCBvdXRwdXQ7XG4gKlxuICogdHJ5IHtcbiAqICAgb3V0cHV0ID0gcGFrby5pbmZsYXRlKGlucHV0KTtcbiAqIH0gY2F0Y2ggKGVycikge1xuICogICBjb25zb2xlLmxvZyhlcnIpO1xuICogfVxuICogYGBgXG4gKiovXG5mdW5jdGlvbiBpbmZsYXRlJDEoaW5wdXQsIG9wdGlvbnMpIHtcbiAgY29uc3QgaW5mbGF0b3IgPSBuZXcgSW5mbGF0ZSQxKG9wdGlvbnMpO1xuXG4gIGluZmxhdG9yLnB1c2goaW5wdXQpO1xuXG4gIC8vIFRoYXQgd2lsbCBuZXZlciBoYXBwZW5zLCBpZiB5b3UgZG9uJ3QgY2hlYXQgd2l0aCBvcHRpb25zIDopXG4gIGlmIChpbmZsYXRvci5lcnIpIHRocm93IGluZmxhdG9yLm1zZyB8fCBtZXNzYWdlc1tpbmZsYXRvci5lcnJdO1xuXG4gIHJldHVybiBpbmZsYXRvci5yZXN1bHQ7XG59XG5cblxuLyoqXG4gKiBpbmZsYXRlUmF3KGRhdGFbLCBvcHRpb25zXSkgLT4gVWludDhBcnJheXxTdHJpbmdcbiAqIC0gZGF0YSAoVWludDhBcnJheXxBcnJheUJ1ZmZlcik6IGlucHV0IGRhdGEgdG8gZGVjb21wcmVzcy5cbiAqIC0gb3B0aW9ucyAoT2JqZWN0KTogemxpYiBpbmZsYXRlIG9wdGlvbnMuXG4gKlxuICogVGhlIHNhbWUgYXMgW1tpbmZsYXRlXV0sIGJ1dCBjcmVhdGVzIHJhdyBkYXRhLCB3aXRob3V0IHdyYXBwZXJcbiAqIChoZWFkZXIgYW5kIGFkbGVyMzIgY3JjKS5cbiAqKi9cbmZ1bmN0aW9uIGluZmxhdGVSYXckMShpbnB1dCwgb3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgb3B0aW9ucy5yYXcgPSB0cnVlO1xuICByZXR1cm4gaW5mbGF0ZSQxKGlucHV0LCBvcHRpb25zKTtcbn1cblxuXG4vKipcbiAqIHVuZ3ppcChkYXRhWywgb3B0aW9uc10pIC0+IFVpbnQ4QXJyYXl8U3RyaW5nXG4gKiAtIGRhdGEgKFVpbnQ4QXJyYXl8QXJyYXlCdWZmZXIpOiBpbnB1dCBkYXRhIHRvIGRlY29tcHJlc3MuXG4gKiAtIG9wdGlvbnMgKE9iamVjdCk6IHpsaWIgaW5mbGF0ZSBvcHRpb25zLlxuICpcbiAqIEp1c3Qgc2hvcnRjdXQgdG8gW1tpbmZsYXRlXV0sIGJlY2F1c2UgaXQgYXV0b2RldGVjdHMgZm9ybWF0XG4gKiBieSBoZWFkZXIuY29udGVudC4gRG9uZSBmb3IgY29udmVuaWVuY2UuXG4gKiovXG5cblxudmFyIEluZmxhdGVfMSQxID0gSW5mbGF0ZSQxO1xudmFyIGluZmxhdGVfMiA9IGluZmxhdGUkMTtcbnZhciBpbmZsYXRlUmF3XzEkMSA9IGluZmxhdGVSYXckMTtcbnZhciB1bmd6aXAkMSA9IGluZmxhdGUkMTtcbnZhciBjb25zdGFudHMgPSBjb25zdGFudHMkMjtcblxudmFyIGluZmxhdGVfMSQxID0ge1xuXHRJbmZsYXRlOiBJbmZsYXRlXzEkMSxcblx0aW5mbGF0ZTogaW5mbGF0ZV8yLFxuXHRpbmZsYXRlUmF3OiBpbmZsYXRlUmF3XzEkMSxcblx0dW5nemlwOiB1bmd6aXAkMSxcblx0Y29uc3RhbnRzOiBjb25zdGFudHNcbn07XG5cbmNvbnN0IHsgRGVmbGF0ZSwgZGVmbGF0ZSwgZGVmbGF0ZVJhdywgZ3ppcCB9ID0gZGVmbGF0ZV8xJDE7XG5cbmNvbnN0IHsgSW5mbGF0ZSwgaW5mbGF0ZSwgaW5mbGF0ZVJhdywgdW5nemlwIH0gPSBpbmZsYXRlXzEkMTtcblxuXG5cbnZhciBEZWZsYXRlXzEgPSBEZWZsYXRlO1xudmFyIGRlZmxhdGVfMSA9IGRlZmxhdGU7XG52YXIgZGVmbGF0ZVJhd18xID0gZGVmbGF0ZVJhdztcbnZhciBnemlwXzEgPSBnemlwO1xudmFyIEluZmxhdGVfMSA9IEluZmxhdGU7XG52YXIgaW5mbGF0ZV8xID0gaW5mbGF0ZTtcbnZhciBpbmZsYXRlUmF3XzEgPSBpbmZsYXRlUmF3O1xudmFyIHVuZ3ppcF8xID0gdW5nemlwO1xudmFyIGNvbnN0YW50c18xID0gY29uc3RhbnRzJDI7XG5cbnZhciBwYWtvID0ge1xuXHREZWZsYXRlOiBEZWZsYXRlXzEsXG5cdGRlZmxhdGU6IGRlZmxhdGVfMSxcblx0ZGVmbGF0ZVJhdzogZGVmbGF0ZVJhd18xLFxuXHRnemlwOiBnemlwXzEsXG5cdEluZmxhdGU6IEluZmxhdGVfMSxcblx0aW5mbGF0ZTogaW5mbGF0ZV8xLFxuXHRpbmZsYXRlUmF3OiBpbmZsYXRlUmF3XzEsXG5cdHVuZ3ppcDogdW5nemlwXzEsXG5cdGNvbnN0YW50czogY29uc3RhbnRzXzFcbn07XG5cbmV4cG9ydCB7IERlZmxhdGVfMSBhcyBEZWZsYXRlLCBJbmZsYXRlXzEgYXMgSW5mbGF0ZSwgY29uc3RhbnRzXzEgYXMgY29uc3RhbnRzLCBwYWtvIGFzIGRlZmF1bHQsIGRlZmxhdGVfMSBhcyBkZWZsYXRlLCBkZWZsYXRlUmF3XzEgYXMgZGVmbGF0ZVJhdywgZ3ppcF8xIGFzIGd6aXAsIGluZmxhdGVfMSBhcyBpbmZsYXRlLCBpbmZsYXRlUmF3XzEgYXMgaW5mbGF0ZVJhdywgdW5nemlwXzEgYXMgdW5nemlwIH07XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=
\ No newline at end of file
diff --git a/docs/vendors-node_modules_esptool-js_lib_targets_esp32p4_js.bundle.js b/docs/vendors-node_modules_esptool-js_lib_targets_esp32p4_js.bundle.js
deleted file mode 100644
index 7fb9285..0000000
--- a/docs/vendors-node_modules_esptool-js_lib_targets_esp32p4_js.bundle.js
+++ /dev/null
@@ -1,401 +0,0 @@
-"use strict";
-(self["webpackChunkTactility_Web_Installer"] = self["webpackChunkTactility_Web_Installer"] || []).push([["vendors-node_modules_esptool-js_lib_targets_esp32p4_js"],{
-
-/***/ "./node_modules/esptool-js/lib/targets/esp32.js":
-/*!******************************************************!*\
- !*** ./node_modules/esptool-js/lib/targets/esp32.js ***!
- \******************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ ESP32ROM: () => (/* binding */ ESP32ROM)
-/* harmony export */ });
-/* harmony import */ var _rom_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./rom.js */ "./node_modules/esptool-js/lib/targets/rom.js");
-
-class ESP32ROM extends _rom_js__WEBPACK_IMPORTED_MODULE_0__.ROM {
- constructor() {
- super(...arguments);
- this.CHIP_NAME = "ESP32";
- this.IMAGE_CHIP_ID = 0;
- this.EFUSE_RD_REG_BASE = 0x3ff5a000;
- this.DR_REG_SYSCON_BASE = 0x3ff66000;
- this.UART_CLKDIV_REG = 0x3ff40014;
- this.UART_CLKDIV_MASK = 0xfffff;
- this.UART_DATE_REG_ADDR = 0x60000078;
- this.XTAL_CLK_DIVIDER = 1;
- this.FLASH_SIZES = {
- "1MB": 0x00,
- "2MB": 0x10,
- "4MB": 0x20,
- "8MB": 0x30,
- "16MB": 0x40,
- };
- this.FLASH_WRITE_SIZE = 0x400;
- this.BOOTLOADER_FLASH_OFFSET = 0x1000;
- this.SPI_REG_BASE = 0x3ff42000;
- this.SPI_USR_OFFS = 0x1c;
- this.SPI_USR1_OFFS = 0x20;
- this.SPI_USR2_OFFS = 0x24;
- this.SPI_W0_OFFS = 0x80;
- this.SPI_MOSI_DLEN_OFFS = 0x28;
- this.SPI_MISO_DLEN_OFFS = 0x2c;
- }
- async readEfuse(loader, offset) {
- const addr = this.EFUSE_RD_REG_BASE + 4 * offset;
- loader.debug("Read efuse " + addr);
- return await loader.readReg(addr);
- }
- async getPkgVersion(loader) {
- const word3 = await this.readEfuse(loader, 3);
- let pkgVersion = (word3 >> 9) & 0x07;
- pkgVersion += ((word3 >> 2) & 0x1) << 3;
- return pkgVersion;
- }
- async getChipRevision(loader) {
- const word3 = await this.readEfuse(loader, 3);
- const word5 = await this.readEfuse(loader, 5);
- const apbCtlDate = await loader.readReg(this.DR_REG_SYSCON_BASE + 0x7c);
- const revBit0 = (word3 >> 15) & 0x1;
- const revBit1 = (word5 >> 20) & 0x1;
- const revBit2 = (apbCtlDate >> 31) & 0x1;
- if (revBit0 != 0) {
- if (revBit1 != 0) {
- if (revBit2 != 0) {
- return 3;
- }
- else {
- return 2;
- }
- }
- else {
- return 1;
- }
- }
- return 0;
- }
- async getChipDescription(loader) {
- const chipDesc = [
- "ESP32-D0WDQ6",
- "ESP32-D0WD",
- "ESP32-D2WD",
- "",
- "ESP32-U4WDH",
- "ESP32-PICO-D4",
- "ESP32-PICO-V3-02",
- ];
- let chipName = "";
- const pkgVersion = await this.getPkgVersion(loader);
- const chipRevision = await this.getChipRevision(loader);
- const rev3 = chipRevision == 3;
- const single_core = (await this.readEfuse(loader, 3)) & (1 << 0);
- if (single_core != 0) {
- chipDesc[0] = "ESP32-S0WDQ6";
- chipDesc[1] = "ESP32-S0WD";
- }
- if (rev3) {
- chipDesc[5] = "ESP32-PICO-V3";
- }
- if (pkgVersion >= 0 && pkgVersion <= 6) {
- chipName = chipDesc[pkgVersion];
- }
- else {
- chipName = "Unknown ESP32";
- }
- if (rev3 && (pkgVersion === 0 || pkgVersion === 1)) {
- chipName += "-V3";
- }
- return chipName + " (revision " + chipRevision + ")";
- }
- async getChipFeatures(loader) {
- const features = ["Wi-Fi"];
- const word3 = await this.readEfuse(loader, 3);
- const chipVerDisBt = word3 & (1 << 1);
- if (chipVerDisBt === 0) {
- features.push(" BT");
- }
- const chipVerDisAppCpu = word3 & (1 << 0);
- if (chipVerDisAppCpu !== 0) {
- features.push(" Single Core");
- }
- else {
- features.push(" Dual Core");
- }
- const chipCpuFreqRated = word3 & (1 << 13);
- if (chipCpuFreqRated !== 0) {
- const chipCpuFreqLow = word3 & (1 << 12);
- if (chipCpuFreqLow !== 0) {
- features.push(" 160MHz");
- }
- else {
- features.push(" 240MHz");
- }
- }
- const pkgVersion = await this.getPkgVersion(loader);
- if ([2, 4, 5, 6].indexOf(pkgVersion) !== -1) {
- features.push(" Embedded Flash");
- }
- if (pkgVersion === 6) {
- features.push(" Embedded PSRAM");
- }
- const word4 = await this.readEfuse(loader, 4);
- const adcVref = (word4 >> 8) & 0x1f;
- if (adcVref !== 0) {
- features.push(" VRef calibration in efuse");
- }
- const blk3PartRes = (word3 >> 14) & 0x1;
- if (blk3PartRes !== 0) {
- features.push(" BLK3 partially reserved");
- }
- const word6 = await this.readEfuse(loader, 6);
- const codingScheme = word6 & 0x3;
- const codingSchemeArr = ["None", "3/4", "Repeat (UNSUPPORTED)", "Invalid"];
- features.push(" Coding Scheme " + codingSchemeArr[codingScheme]);
- return features;
- }
- async getCrystalFreq(loader) {
- const uartDiv = (await loader.readReg(this.UART_CLKDIV_REG)) & this.UART_CLKDIV_MASK;
- const etsXtal = (loader.transport.baudrate * uartDiv) / 1000000 / this.XTAL_CLK_DIVIDER;
- let normXtal;
- if (etsXtal > 33) {
- normXtal = 40;
- }
- else {
- normXtal = 26;
- }
- if (Math.abs(normXtal - etsXtal) > 1) {
- loader.info("WARNING: Unsupported crystal in use");
- }
- return normXtal;
- }
- _d2h(d) {
- const h = (+d).toString(16);
- return h.length === 1 ? "0" + h : h;
- }
- async readMac(loader) {
- let mac0 = await this.readEfuse(loader, 1);
- mac0 = mac0 >>> 0;
- let mac1 = await this.readEfuse(loader, 2);
- mac1 = mac1 >>> 0;
- const mac = new Uint8Array(6);
- mac[0] = (mac1 >> 8) & 0xff;
- mac[1] = mac1 & 0xff;
- mac[2] = (mac0 >> 24) & 0xff;
- mac[3] = (mac0 >> 16) & 0xff;
- mac[4] = (mac0 >> 8) & 0xff;
- mac[5] = mac0 & 0xff;
- return (this._d2h(mac[0]) +
- ":" +
- this._d2h(mac[1]) +
- ":" +
- this._d2h(mac[2]) +
- ":" +
- this._d2h(mac[3]) +
- ":" +
- this._d2h(mac[4]) +
- ":" +
- this._d2h(mac[5]));
- }
-}
-
-
-/***/ }),
-
-/***/ "./node_modules/esptool-js/lib/targets/esp32p4.js":
-/*!********************************************************!*\
- !*** ./node_modules/esptool-js/lib/targets/esp32p4.js ***!
- \********************************************************/
-/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
-
-__webpack_require__.r(__webpack_exports__);
-/* harmony export */ __webpack_require__.d(__webpack_exports__, {
-/* harmony export */ ESP32P4ROM: () => (/* binding */ ESP32P4ROM)
-/* harmony export */ });
-/* harmony import */ var _esp32_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./esp32.js */ "./node_modules/esptool-js/lib/targets/esp32.js");
-
-class ESP32P4ROM extends _esp32_js__WEBPACK_IMPORTED_MODULE_0__.ESP32ROM {
- constructor() {
- super(...arguments);
- this.CHIP_NAME = "ESP32-P4";
- this.IMAGE_CHIP_ID = 18;
- this.IROM_MAP_START = 0x40000000;
- this.IROM_MAP_END = 0x4c000000;
- this.DROM_MAP_START = 0x40000000;
- this.DROM_MAP_END = 0x4c000000;
- this.BOOTLOADER_FLASH_OFFSET = 0x2000; // First 2 sectors are reserved for FE purposes
- this.CHIP_DETECT_MAGIC_VALUE = [0x0, 0x0addbad0];
- this.UART_DATE_REG_ADDR = 0x500ca000 + 0x8c;
- this.EFUSE_BASE = 0x5012d000;
- this.EFUSE_BLOCK1_ADDR = this.EFUSE_BASE + 0x044;
- this.MAC_EFUSE_REG = this.EFUSE_BASE + 0x044;
- this.SPI_REG_BASE = 0x5008d000; // SPIMEM1
- this.SPI_USR_OFFS = 0x18;
- this.SPI_USR1_OFFS = 0x1c;
- this.SPI_USR2_OFFS = 0x20;
- this.SPI_MOSI_DLEN_OFFS = 0x24;
- this.SPI_MISO_DLEN_OFFS = 0x28;
- this.SPI_W0_OFFS = 0x58;
- this.EFUSE_RD_REG_BASE = this.EFUSE_BASE + 0x030; // BLOCK0 read base address
- this.EFUSE_PURPOSE_KEY0_REG = this.EFUSE_BASE + 0x34;
- this.EFUSE_PURPOSE_KEY0_SHIFT = 24;
- this.EFUSE_PURPOSE_KEY1_REG = this.EFUSE_BASE + 0x34;
- this.EFUSE_PURPOSE_KEY1_SHIFT = 28;
- this.EFUSE_PURPOSE_KEY2_REG = this.EFUSE_BASE + 0x38;
- this.EFUSE_PURPOSE_KEY2_SHIFT = 0;
- this.EFUSE_PURPOSE_KEY3_REG = this.EFUSE_BASE + 0x38;
- this.EFUSE_PURPOSE_KEY3_SHIFT = 4;
- this.EFUSE_PURPOSE_KEY4_REG = this.EFUSE_BASE + 0x38;
- this.EFUSE_PURPOSE_KEY4_SHIFT = 8;
- this.EFUSE_PURPOSE_KEY5_REG = this.EFUSE_BASE + 0x38;
- this.EFUSE_PURPOSE_KEY5_SHIFT = 12;
- this.EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG = this.EFUSE_RD_REG_BASE;
- this.EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT = 1 << 20;
- this.EFUSE_SPI_BOOT_CRYPT_CNT_REG = this.EFUSE_BASE + 0x034;
- this.EFUSE_SPI_BOOT_CRYPT_CNT_MASK = 0x7 << 18;
- this.EFUSE_SECURE_BOOT_EN_REG = this.EFUSE_BASE + 0x038;
- this.EFUSE_SECURE_BOOT_EN_MASK = 1 << 20;
- this.PURPOSE_VAL_XTS_AES256_KEY_1 = 2;
- this.PURPOSE_VAL_XTS_AES256_KEY_2 = 3;
- this.PURPOSE_VAL_XTS_AES128_KEY = 4;
- this.SUPPORTS_ENCRYPTED_FLASH = true;
- this.FLASH_ENCRYPTED_WRITE_ALIGN = 16;
- this.MEMORY_MAP = [
- [0x00000000, 0x00010000, "PADDING"],
- [0x40000000, 0x4c000000, "DROM"],
- [0x4ff00000, 0x4ffa0000, "DRAM"],
- [0x4ff00000, 0x4ffa0000, "BYTE_ACCESSIBLE"],
- [0x4fc00000, 0x4fc20000, "DROM_MASK"],
- [0x4fc00000, 0x4fc20000, "IROM_MASK"],
- [0x40000000, 0x4c000000, "IROM"],
- [0x4ff00000, 0x4ffa0000, "IRAM"],
- [0x50108000, 0x50110000, "RTC_IRAM"],
- [0x50108000, 0x50110000, "RTC_DRAM"],
- [0x600fe000, 0x60100000, "MEM_INTERNAL2"],
- ];
- this.UF2_FAMILY_ID = 0x3d308e94;
- this.EFUSE_MAX_KEY = 5;
- this.KEY_PURPOSES = {
- 0: "USER/EMPTY",
- 1: "ECDSA_KEY",
- 2: "XTS_AES_256_KEY_1",
- 3: "XTS_AES_256_KEY_2",
- 4: "XTS_AES_128_KEY",
- 5: "HMAC_DOWN_ALL",
- 6: "HMAC_DOWN_JTAG",
- 7: "HMAC_DOWN_DIGITAL_SIGNATURE",
- 8: "HMAC_UP",
- 9: "SECURE_BOOT_DIGEST0",
- 10: "SECURE_BOOT_DIGEST1",
- 11: "SECURE_BOOT_DIGEST2",
- 12: "KM_INIT_KEY",
- };
- }
- async getPkgVersion(loader) {
- const numWord = 2;
- const addr = this.EFUSE_BLOCK1_ADDR + 4 * numWord;
- const registerValue = await loader.readReg(addr);
- return (registerValue >> 27) & 0x07;
- }
- async getMinorChipVersion(loader) {
- const numWord = 2;
- const addr = this.EFUSE_BLOCK1_ADDR + 4 * numWord;
- const registerValue = await loader.readReg(addr);
- return (registerValue >> 0) & 0x0f;
- }
- async getMajorChipVersion(loader) {
- const numWord = 2;
- const addr = this.EFUSE_BLOCK1_ADDR + 4 * numWord;
- const registerValue = await loader.readReg(addr);
- return (registerValue >> 4) & 0x03;
- }
- async getChipDescription(loader) {
- const pkgVersion = await this.getPkgVersion(loader);
- const chipName = pkgVersion === 0 ? "ESP32-P4" : "unknown ESP32-P4";
- const majorRev = await this.getMajorChipVersion(loader);
- const minorRev = await this.getMinorChipVersion(loader);
- return `${chipName} (revision v${majorRev}.${minorRev})`;
- }
- async getChipFeatures(loader) {
- return ["High-Performance MCU"];
- }
- async getCrystalFreq(loader) {
- return 40; // ESP32P4 XTAL is fixed to 40MHz
- }
- async getFlashVoltage(loader) {
- return;
- }
- async overrideVddsdio(loader) {
- loader.debug("VDD_SDIO overrides are not supported for ESP32-P4");
- }
- async readMac(loader) {
- let mac0 = await loader.readReg(this.MAC_EFUSE_REG);
- mac0 = mac0 >>> 0;
- let mac1 = await loader.readReg(this.MAC_EFUSE_REG + 4);
- mac1 = (mac1 >>> 0) & 0x0000ffff;
- const mac = new Uint8Array(6);
- mac[0] = (mac1 >> 8) & 0xff;
- mac[1] = mac1 & 0xff;
- mac[2] = (mac0 >> 24) & 0xff;
- mac[3] = (mac0 >> 16) & 0xff;
- mac[4] = (mac0 >> 8) & 0xff;
- mac[5] = mac0 & 0xff;
- return (this._d2h(mac[0]) +
- ":" +
- this._d2h(mac[1]) +
- ":" +
- this._d2h(mac[2]) +
- ":" +
- this._d2h(mac[3]) +
- ":" +
- this._d2h(mac[4]) +
- ":" +
- this._d2h(mac[5]));
- }
- async getFlashCryptConfig(loader) {
- return; // doesn't exist on ESP32-P4
- }
- async getSecureBootEnabled(laoder) {
- const registerValue = await laoder.readReg(this.EFUSE_SECURE_BOOT_EN_REG);
- return registerValue & this.EFUSE_SECURE_BOOT_EN_MASK;
- }
- async getKeyBlockPurpose(loader, keyBlock) {
- if (keyBlock < 0 || keyBlock > this.EFUSE_MAX_KEY) {
- loader.debug(`Valid key block numbers must be in range 0-${this.EFUSE_MAX_KEY}`);
- return;
- }
- const regShiftDictionary = [
- [this.EFUSE_PURPOSE_KEY0_REG, this.EFUSE_PURPOSE_KEY0_SHIFT],
- [this.EFUSE_PURPOSE_KEY1_REG, this.EFUSE_PURPOSE_KEY1_SHIFT],
- [this.EFUSE_PURPOSE_KEY2_REG, this.EFUSE_PURPOSE_KEY2_SHIFT],
- [this.EFUSE_PURPOSE_KEY3_REG, this.EFUSE_PURPOSE_KEY3_SHIFT],
- [this.EFUSE_PURPOSE_KEY4_REG, this.EFUSE_PURPOSE_KEY4_SHIFT],
- [this.EFUSE_PURPOSE_KEY5_REG, this.EFUSE_PURPOSE_KEY5_SHIFT],
- ];
- const [reg, shift] = regShiftDictionary[keyBlock];
- const registerValue = await loader.readReg(reg);
- return (registerValue >> shift) & 0xf;
- }
- async isFlashEncryptionKeyValid(loader) {
- const purposes = [];
- for (let i = 0; i <= this.EFUSE_MAX_KEY; i++) {
- const purpose = await this.getKeyBlockPurpose(loader, i);
- purposes.push(purpose);
- }
- const isXtsAes128Key = purposes.find((p) => p === this.PURPOSE_VAL_XTS_AES128_KEY);
- if (typeof isXtsAes128Key !== undefined) {
- return true;
- }
- const isXtsAes256Key1 = purposes.find((p) => p === this.PURPOSE_VAL_XTS_AES256_KEY_1);
- const isXtsAes256Key2 = purposes.find((p) => p === this.PURPOSE_VAL_XTS_AES256_KEY_2);
- if (typeof isXtsAes256Key1 !== undefined && typeof isXtsAes256Key2 !== undefined) {
- return true;
- }
- return false;
- }
-}
-
-
-/***/ })
-
-}]);
-//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVuZG9ycy1ub2RlX21vZHVsZXNfZXNwdG9vbC1qc19saWJfdGFyZ2V0c19lc3AzMnA0X2pzLmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7OztBQUErQjtBQUN4Qix1QkFBdUIsd0NBQUc7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7O0FDeExzQztBQUMvQix5QkFBeUIsK0NBQVE7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQztBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBEQUEwRDtBQUMxRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLFVBQVUsYUFBYSxTQUFTLEdBQUcsU0FBUztBQUM5RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1RUFBdUUsbUJBQW1CO0FBQzFGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLHlCQUF5QjtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9UYWN0aWxpdHkgV2ViIEluc3RhbGxlci8uL25vZGVfbW9kdWxlcy9lc3B0b29sLWpzL2xpYi90YXJnZXRzL2VzcDMyLmpzIiwid2VicGFjazovL1RhY3RpbGl0eSBXZWIgSW5zdGFsbGVyLy4vbm9kZV9tb2R1bGVzL2VzcHRvb2wtanMvbGliL3RhcmdldHMvZXNwMzJwNC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBST00gfSBmcm9tIFwiLi9yb20uanNcIjtcbmV4cG9ydCBjbGFzcyBFU1AzMlJPTSBleHRlbmRzIFJPTSB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgIHRoaXMuQ0hJUF9OQU1FID0gXCJFU1AzMlwiO1xuICAgICAgICB0aGlzLklNQUdFX0NISVBfSUQgPSAwO1xuICAgICAgICB0aGlzLkVGVVNFX1JEX1JFR19CQVNFID0gMHgzZmY1YTAwMDtcbiAgICAgICAgdGhpcy5EUl9SRUdfU1lTQ09OX0JBU0UgPSAweDNmZjY2MDAwO1xuICAgICAgICB0aGlzLlVBUlRfQ0xLRElWX1JFRyA9IDB4M2ZmNDAwMTQ7XG4gICAgICAgIHRoaXMuVUFSVF9DTEtESVZfTUFTSyA9IDB4ZmZmZmY7XG4gICAgICAgIHRoaXMuVUFSVF9EQVRFX1JFR19BRERSID0gMHg2MDAwMDA3ODtcbiAgICAgICAgdGhpcy5YVEFMX0NMS19ESVZJREVSID0gMTtcbiAgICAgICAgdGhpcy5GTEFTSF9TSVpFUyA9IHtcbiAgICAgICAgICAgIFwiMU1CXCI6IDB4MDAsXG4gICAgICAgICAgICBcIjJNQlwiOiAweDEwLFxuICAgICAgICAgICAgXCI0TUJcIjogMHgyMCxcbiAgICAgICAgICAgIFwiOE1CXCI6IDB4MzAsXG4gICAgICAgICAgICBcIjE2TUJcIjogMHg0MCxcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5GTEFTSF9XUklURV9TSVpFID0gMHg0MDA7XG4gICAgICAgIHRoaXMuQk9PVExPQURFUl9GTEFTSF9PRkZTRVQgPSAweDEwMDA7XG4gICAgICAgIHRoaXMuU1BJX1JFR19CQVNFID0gMHgzZmY0MjAwMDtcbiAgICAgICAgdGhpcy5TUElfVVNSX09GRlMgPSAweDFjO1xuICAgICAgICB0aGlzLlNQSV9VU1IxX09GRlMgPSAweDIwO1xuICAgICAgICB0aGlzLlNQSV9VU1IyX09GRlMgPSAweDI0O1xuICAgICAgICB0aGlzLlNQSV9XMF9PRkZTID0gMHg4MDtcbiAgICAgICAgdGhpcy5TUElfTU9TSV9ETEVOX09GRlMgPSAweDI4O1xuICAgICAgICB0aGlzLlNQSV9NSVNPX0RMRU5fT0ZGUyA9IDB4MmM7XG4gICAgfVxuICAgIGFzeW5jIHJlYWRFZnVzZShsb2FkZXIsIG9mZnNldCkge1xuICAgICAgICBjb25zdCBhZGRyID0gdGhpcy5FRlVTRV9SRF9SRUdfQkFTRSArIDQgKiBvZmZzZXQ7XG4gICAgICAgIGxvYWRlci5kZWJ1ZyhcIlJlYWQgZWZ1c2UgXCIgKyBhZGRyKTtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGxvYWRlci5yZWFkUmVnKGFkZHIpO1xuICAgIH1cbiAgICBhc3luYyBnZXRQa2dWZXJzaW9uKGxvYWRlcikge1xuICAgICAgICBjb25zdCB3b3JkMyA9IGF3YWl0IHRoaXMucmVhZEVmdXNlKGxvYWRlciwgMyk7XG4gICAgICAgIGxldCBwa2dWZXJzaW9uID0gKHdvcmQzID4+IDkpICYgMHgwNztcbiAgICAgICAgcGtnVmVyc2lvbiArPSAoKHdvcmQzID4+IDIpICYgMHgxKSA8PCAzO1xuICAgICAgICByZXR1cm4gcGtnVmVyc2lvbjtcbiAgICB9XG4gICAgYXN5bmMgZ2V0Q2hpcFJldmlzaW9uKGxvYWRlcikge1xuICAgICAgICBjb25zdCB3b3JkMyA9IGF3YWl0IHRoaXMucmVhZEVmdXNlKGxvYWRlciwgMyk7XG4gICAgICAgIGNvbnN0IHdvcmQ1ID0gYXdhaXQgdGhpcy5yZWFkRWZ1c2UobG9hZGVyLCA1KTtcbiAgICAgICAgY29uc3QgYXBiQ3RsRGF0ZSA9IGF3YWl0IGxvYWRlci5yZWFkUmVnKHRoaXMuRFJfUkVHX1NZU0NPTl9CQVNFICsgMHg3Yyk7XG4gICAgICAgIGNvbnN0IHJldkJpdDAgPSAod29yZDMgPj4gMTUpICYgMHgxO1xuICAgICAgICBjb25zdCByZXZCaXQxID0gKHdvcmQ1ID4+IDIwKSAmIDB4MTtcbiAgICAgICAgY29uc3QgcmV2Qml0MiA9IChhcGJDdGxEYXRlID4+IDMxKSAmIDB4MTtcbiAgICAgICAgaWYgKHJldkJpdDAgIT0gMCkge1xuICAgICAgICAgICAgaWYgKHJldkJpdDEgIT0gMCkge1xuICAgICAgICAgICAgICAgIGlmIChyZXZCaXQyICE9IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gMjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgYXN5bmMgZ2V0Q2hpcERlc2NyaXB0aW9uKGxvYWRlcikge1xuICAgICAgICBjb25zdCBjaGlwRGVzYyA9IFtcbiAgICAgICAgICAgIFwiRVNQMzItRDBXRFE2XCIsXG4gICAgICAgICAgICBcIkVTUDMyLUQwV0RcIixcbiAgICAgICAgICAgIFwiRVNQMzItRDJXRFwiLFxuICAgICAgICAgICAgXCJcIixcbiAgICAgICAgICAgIFwiRVNQMzItVTRXREhcIixcbiAgICAgICAgICAgIFwiRVNQMzItUElDTy1ENFwiLFxuICAgICAgICAgICAgXCJFU1AzMi1QSUNPLVYzLTAyXCIsXG4gICAgICAgIF07XG4gICAgICAgIGxldCBjaGlwTmFtZSA9IFwiXCI7XG4gICAgICAgIGNvbnN0IHBrZ1ZlcnNpb24gPSBhd2FpdCB0aGlzLmdldFBrZ1ZlcnNpb24obG9hZGVyKTtcbiAgICAgICAgY29uc3QgY2hpcFJldmlzaW9uID0gYXdhaXQgdGhpcy5nZXRDaGlwUmV2aXNpb24obG9hZGVyKTtcbiAgICAgICAgY29uc3QgcmV2MyA9IGNoaXBSZXZpc2lvbiA9PSAzO1xuICAgICAgICBjb25zdCBzaW5nbGVfY29yZSA9IChhd2FpdCB0aGlzLnJlYWRFZnVzZShsb2FkZXIsIDMpKSAmICgxIDw8IDApO1xuICAgICAgICBpZiAoc2luZ2xlX2NvcmUgIT0gMCkge1xuICAgICAgICAgICAgY2hpcERlc2NbMF0gPSBcIkVTUDMyLVMwV0RRNlwiO1xuICAgICAgICAgICAgY2hpcERlc2NbMV0gPSBcIkVTUDMyLVMwV0RcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmV2Mykge1xuICAgICAgICAgICAgY2hpcERlc2NbNV0gPSBcIkVTUDMyLVBJQ08tVjNcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGtnVmVyc2lvbiA+PSAwICYmIHBrZ1ZlcnNpb24gPD0gNikge1xuICAgICAgICAgICAgY2hpcE5hbWUgPSBjaGlwRGVzY1twa2dWZXJzaW9uXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNoaXBOYW1lID0gXCJVbmtub3duIEVTUDMyXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJldjMgJiYgKHBrZ1ZlcnNpb24gPT09IDAgfHwgcGtnVmVyc2lvbiA9PT0gMSkpIHtcbiAgICAgICAgICAgIGNoaXBOYW1lICs9IFwiLVYzXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNoaXBOYW1lICsgXCIgKHJldmlzaW9uIFwiICsgY2hpcFJldmlzaW9uICsgXCIpXCI7XG4gICAgfVxuICAgIGFzeW5jIGdldENoaXBGZWF0dXJlcyhsb2FkZXIpIHtcbiAgICAgICAgY29uc3QgZmVhdHVyZXMgPSBbXCJXaS1GaVwiXTtcbiAgICAgICAgY29uc3Qgd29yZDMgPSBhd2FpdCB0aGlzLnJlYWRFZnVzZShsb2FkZXIsIDMpO1xuICAgICAgICBjb25zdCBjaGlwVmVyRGlzQnQgPSB3b3JkMyAmICgxIDw8IDEpO1xuICAgICAgICBpZiAoY2hpcFZlckRpc0J0ID09PSAwKSB7XG4gICAgICAgICAgICBmZWF0dXJlcy5wdXNoKFwiIEJUXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNoaXBWZXJEaXNBcHBDcHUgPSB3b3JkMyAmICgxIDw8IDApO1xuICAgICAgICBpZiAoY2hpcFZlckRpc0FwcENwdSAhPT0gMCkge1xuICAgICAgICAgICAgZmVhdHVyZXMucHVzaChcIiBTaW5nbGUgQ29yZVwiKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZlYXR1cmVzLnB1c2goXCIgRHVhbCBDb3JlXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNoaXBDcHVGcmVxUmF0ZWQgPSB3b3JkMyAmICgxIDw8IDEzKTtcbiAgICAgICAgaWYgKGNoaXBDcHVGcmVxUmF0ZWQgIT09IDApIHtcbiAgICAgICAgICAgIGNvbnN0IGNoaXBDcHVGcmVxTG93ID0gd29yZDMgJiAoMSA8PCAxMik7XG4gICAgICAgICAgICBpZiAoY2hpcENwdUZyZXFMb3cgIT09IDApIHtcbiAgICAgICAgICAgICAgICBmZWF0dXJlcy5wdXNoKFwiIDE2ME1IelwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGZlYXR1cmVzLnB1c2goXCIgMjQwTUh6XCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBrZ1ZlcnNpb24gPSBhd2FpdCB0aGlzLmdldFBrZ1ZlcnNpb24obG9hZGVyKTtcbiAgICAgICAgaWYgKFsyLCA0LCA1LCA2XS5pbmRleE9mKHBrZ1ZlcnNpb24pICE9PSAtMSkge1xuICAgICAgICAgICAgZmVhdHVyZXMucHVzaChcIiBFbWJlZGRlZCBGbGFzaFwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocGtnVmVyc2lvbiA9PT0gNikge1xuICAgICAgICAgICAgZmVhdHVyZXMucHVzaChcIiBFbWJlZGRlZCBQU1JBTVwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB3b3JkNCA9IGF3YWl0IHRoaXMucmVhZEVmdXNlKGxvYWRlciwgNCk7XG4gICAgICAgIGNvbnN0IGFkY1ZyZWYgPSAod29yZDQgPj4gOCkgJiAweDFmO1xuICAgICAgICBpZiAoYWRjVnJlZiAhPT0gMCkge1xuICAgICAgICAgICAgZmVhdHVyZXMucHVzaChcIiBWUmVmIGNhbGlicmF0aW9uIGluIGVmdXNlXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGJsazNQYXJ0UmVzID0gKHdvcmQzID4+IDE0KSAmIDB4MTtcbiAgICAgICAgaWYgKGJsazNQYXJ0UmVzICE9PSAwKSB7XG4gICAgICAgICAgICBmZWF0dXJlcy5wdXNoKFwiIEJMSzMgcGFydGlhbGx5IHJlc2VydmVkXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHdvcmQ2ID0gYXdhaXQgdGhpcy5yZWFkRWZ1c2UobG9hZGVyLCA2KTtcbiAgICAgICAgY29uc3QgY29kaW5nU2NoZW1lID0gd29yZDYgJiAweDM7XG4gICAgICAgIGNvbnN0IGNvZGluZ1NjaGVtZUFyciA9IFtcIk5vbmVcIiwgXCIzLzRcIiwgXCJSZXBlYXQgKFVOU1VQUE9SVEVEKVwiLCBcIkludmFsaWRcIl07XG4gICAgICAgIGZlYXR1cmVzLnB1c2goXCIgQ29kaW5nIFNjaGVtZSBcIiArIGNvZGluZ1NjaGVtZUFycltjb2RpbmdTY2hlbWVdKTtcbiAgICAgICAgcmV0dXJuIGZlYXR1cmVzO1xuICAgIH1cbiAgICBhc3luYyBnZXRDcnlzdGFsRnJlcShsb2FkZXIpIHtcbiAgICAgICAgY29uc3QgdWFydERpdiA9IChhd2FpdCBsb2FkZXIucmVhZFJlZyh0aGlzLlVBUlRfQ0xLRElWX1JFRykpICYgdGhpcy5VQVJUX0NMS0RJVl9NQVNLO1xuICAgICAgICBjb25zdCBldHNYdGFsID0gKGxvYWRlci50cmFuc3BvcnQuYmF1ZHJhdGUgKiB1YXJ0RGl2KSAvIDEwMDAwMDAgLyB0aGlzLlhUQUxfQ0xLX0RJVklERVI7XG4gICAgICAgIGxldCBub3JtWHRhbDtcbiAgICAgICAgaWYgKGV0c1h0YWwgPiAzMykge1xuICAgICAgICAgICAgbm9ybVh0YWwgPSA0MDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5vcm1YdGFsID0gMjY7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKE1hdGguYWJzKG5vcm1YdGFsIC0gZXRzWHRhbCkgPiAxKSB7XG4gICAgICAgICAgICBsb2FkZXIuaW5mbyhcIldBUk5JTkc6IFVuc3VwcG9ydGVkIGNyeXN0YWwgaW4gdXNlXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBub3JtWHRhbDtcbiAgICB9XG4gICAgX2QyaChkKSB7XG4gICAgICAgIGNvbnN0IGggPSAoK2QpLnRvU3RyaW5nKDE2KTtcbiAgICAgICAgcmV0dXJuIGgubGVuZ3RoID09PSAxID8gXCIwXCIgKyBoIDogaDtcbiAgICB9XG4gICAgYXN5bmMgcmVhZE1hYyhsb2FkZXIpIHtcbiAgICAgICAgbGV0IG1hYzAgPSBhd2FpdCB0aGlzLnJlYWRFZnVzZShsb2FkZXIsIDEpO1xuICAgICAgICBtYWMwID0gbWFjMCA+Pj4gMDtcbiAgICAgICAgbGV0IG1hYzEgPSBhd2FpdCB0aGlzLnJlYWRFZnVzZShsb2FkZXIsIDIpO1xuICAgICAgICBtYWMxID0gbWFjMSA+Pj4gMDtcbiAgICAgICAgY29uc3QgbWFjID0gbmV3IFVpbnQ4QXJyYXkoNik7XG4gICAgICAgIG1hY1swXSA9IChtYWMxID4+IDgpICYgMHhmZjtcbiAgICAgICAgbWFjWzFdID0gbWFjMSAmIDB4ZmY7XG4gICAgICAgIG1hY1syXSA9IChtYWMwID4+IDI0KSAmIDB4ZmY7XG4gICAgICAgIG1hY1szXSA9IChtYWMwID4+IDE2KSAmIDB4ZmY7XG4gICAgICAgIG1hY1s0XSA9IChtYWMwID4+IDgpICYgMHhmZjtcbiAgICAgICAgbWFjWzVdID0gbWFjMCAmIDB4ZmY7XG4gICAgICAgIHJldHVybiAodGhpcy5fZDJoKG1hY1swXSkgK1xuICAgICAgICAgICAgXCI6XCIgK1xuICAgICAgICAgICAgdGhpcy5fZDJoKG1hY1sxXSkgK1xuICAgICAgICAgICAgXCI6XCIgK1xuICAgICAgICAgICAgdGhpcy5fZDJoKG1hY1syXSkgK1xuICAgICAgICAgICAgXCI6XCIgK1xuICAgICAgICAgICAgdGhpcy5fZDJoKG1hY1szXSkgK1xuICAgICAgICAgICAgXCI6XCIgK1xuICAgICAgICAgICAgdGhpcy5fZDJoKG1hY1s0XSkgK1xuICAgICAgICAgICAgXCI6XCIgK1xuICAgICAgICAgICAgdGhpcy5fZDJoKG1hY1s1XSkpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IEVTUDMyUk9NIH0gZnJvbSBcIi4vZXNwMzIuanNcIjtcbmV4cG9ydCBjbGFzcyBFU1AzMlA0Uk9NIGV4dGVuZHMgRVNQMzJST00ge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLkNISVBfTkFNRSA9IFwiRVNQMzItUDRcIjtcbiAgICAgICAgdGhpcy5JTUFHRV9DSElQX0lEID0gMTg7XG4gICAgICAgIHRoaXMuSVJPTV9NQVBfU1RBUlQgPSAweDQwMDAwMDAwO1xuICAgICAgICB0aGlzLklST01fTUFQX0VORCA9IDB4NGMwMDAwMDA7XG4gICAgICAgIHRoaXMuRFJPTV9NQVBfU1RBUlQgPSAweDQwMDAwMDAwO1xuICAgICAgICB0aGlzLkRST01fTUFQX0VORCA9IDB4NGMwMDAwMDA7XG4gICAgICAgIHRoaXMuQk9PVExPQURFUl9GTEFTSF9PRkZTRVQgPSAweDIwMDA7IC8vIEZpcnN0IDIgc2VjdG9ycyBhcmUgcmVzZXJ2ZWQgZm9yIEZFIHB1cnBvc2VzXG4gICAgICAgIHRoaXMuQ0hJUF9ERVRFQ1RfTUFHSUNfVkFMVUUgPSBbMHgwLCAweDBhZGRiYWQwXTtcbiAgICAgICAgdGhpcy5VQVJUX0RBVEVfUkVHX0FERFIgPSAweDUwMGNhMDAwICsgMHg4YztcbiAgICAgICAgdGhpcy5FRlVTRV9CQVNFID0gMHg1MDEyZDAwMDtcbiAgICAgICAgdGhpcy5FRlVTRV9CTE9DSzFfQUREUiA9IHRoaXMuRUZVU0VfQkFTRSArIDB4MDQ0O1xuICAgICAgICB0aGlzLk1BQ19FRlVTRV9SRUcgPSB0aGlzLkVGVVNFX0JBU0UgKyAweDA0NDtcbiAgICAgICAgdGhpcy5TUElfUkVHX0JBU0UgPSAweDUwMDhkMDAwOyAvLyBTUElNRU0xXG4gICAgICAgIHRoaXMuU1BJX1VTUl9PRkZTID0gMHgxODtcbiAgICAgICAgdGhpcy5TUElfVVNSMV9PRkZTID0gMHgxYztcbiAgICAgICAgdGhpcy5TUElfVVNSMl9PRkZTID0gMHgyMDtcbiAgICAgICAgdGhpcy5TUElfTU9TSV9ETEVOX09GRlMgPSAweDI0O1xuICAgICAgICB0aGlzLlNQSV9NSVNPX0RMRU5fT0ZGUyA9IDB4Mjg7XG4gICAgICAgIHRoaXMuU1BJX1cwX09GRlMgPSAweDU4O1xuICAgICAgICB0aGlzLkVGVVNFX1JEX1JFR19CQVNFID0gdGhpcy5FRlVTRV9CQVNFICsgMHgwMzA7IC8vIEJMT0NLMCByZWFkIGJhc2UgYWRkcmVzc1xuICAgICAgICB0aGlzLkVGVVNFX1BVUlBPU0VfS0VZMF9SRUcgPSB0aGlzLkVGVVNFX0JBU0UgKyAweDM0O1xuICAgICAgICB0aGlzLkVGVVNFX1BVUlBPU0VfS0VZMF9TSElGVCA9IDI0O1xuICAgICAgICB0aGlzLkVGVVNFX1BVUlBPU0VfS0VZMV9SRUcgPSB0aGlzLkVGVVNFX0JBU0UgKyAweDM0O1xuICAgICAgICB0aGlzLkVGVVNFX1BVUlBPU0VfS0VZMV9TSElGVCA9IDI4O1xuICAgICAgICB0aGlzLkVGVVNFX1BVUlBPU0VfS0VZMl9SRUcgPSB0aGlzLkVGVVNFX0JBU0UgKyAweDM4O1xuICAgICAgICB0aGlzLkVGVVNFX1BVUlBPU0VfS0VZMl9TSElGVCA9IDA7XG4gICAgICAgIHRoaXMuRUZVU0VfUFVSUE9TRV9LRVkzX1JFRyA9IHRoaXMuRUZVU0VfQkFTRSArIDB4Mzg7XG4gICAgICAgIHRoaXMuRUZVU0VfUFVSUE9TRV9LRVkzX1NISUZUID0gNDtcbiAgICAgICAgdGhpcy5FRlVTRV9QVVJQT1NFX0tFWTRfUkVHID0gdGhpcy5FRlVTRV9CQVNFICsgMHgzODtcbiAgICAgICAgdGhpcy5FRlVTRV9QVVJQT1NFX0tFWTRfU0hJRlQgPSA4O1xuICAgICAgICB0aGlzLkVGVVNFX1BVUlBPU0VfS0VZNV9SRUcgPSB0aGlzLkVGVVNFX0JBU0UgKyAweDM4O1xuICAgICAgICB0aGlzLkVGVVNFX1BVUlBPU0VfS0VZNV9TSElGVCA9IDEyO1xuICAgICAgICB0aGlzLkVGVVNFX0RJU19ET1dOTE9BRF9NQU5VQUxfRU5DUllQVF9SRUcgPSB0aGlzLkVGVVNFX1JEX1JFR19CQVNFO1xuICAgICAgICB0aGlzLkVGVVNFX0RJU19ET1dOTE9BRF9NQU5VQUxfRU5DUllQVCA9IDEgPDwgMjA7XG4gICAgICAgIHRoaXMuRUZVU0VfU1BJX0JPT1RfQ1JZUFRfQ05UX1JFRyA9IHRoaXMuRUZVU0VfQkFTRSArIDB4MDM0O1xuICAgICAgICB0aGlzLkVGVVNFX1NQSV9CT09UX0NSWVBUX0NOVF9NQVNLID0gMHg3IDw8IDE4O1xuICAgICAgICB0aGlzLkVGVVNFX1NFQ1VSRV9CT09UX0VOX1JFRyA9IHRoaXMuRUZVU0VfQkFTRSArIDB4MDM4O1xuICAgICAgICB0aGlzLkVGVVNFX1NFQ1VSRV9CT09UX0VOX01BU0sgPSAxIDw8IDIwO1xuICAgICAgICB0aGlzLlBVUlBPU0VfVkFMX1hUU19BRVMyNTZfS0VZXzEgPSAyO1xuICAgICAgICB0aGlzLlBVUlBPU0VfVkFMX1hUU19BRVMyNTZfS0VZXzIgPSAzO1xuICAgICAgICB0aGlzLlBVUlBPU0VfVkFMX1hUU19BRVMxMjhfS0VZID0gNDtcbiAgICAgICAgdGhpcy5TVVBQT1JUU19FTkNSWVBURURfRkxBU0ggPSB0cnVlO1xuICAgICAgICB0aGlzLkZMQVNIX0VOQ1JZUFRFRF9XUklURV9BTElHTiA9IDE2O1xuICAgICAgICB0aGlzLk1FTU9SWV9NQVAgPSBbXG4gICAgICAgICAgICBbMHgwMDAwMDAwMCwgMHgwMDAxMDAwMCwgXCJQQURESU5HXCJdLFxuICAgICAgICAgICAgWzB4NDAwMDAwMDAsIDB4NGMwMDAwMDAsIFwiRFJPTVwiXSxcbiAgICAgICAgICAgIFsweDRmZjAwMDAwLCAweDRmZmEwMDAwLCBcIkRSQU1cIl0sXG4gICAgICAgICAgICBbMHg0ZmYwMDAwMCwgMHg0ZmZhMDAwMCwgXCJCWVRFX0FDQ0VTU0lCTEVcIl0sXG4gICAgICAgICAgICBbMHg0ZmMwMDAwMCwgMHg0ZmMyMDAwMCwgXCJEUk9NX01BU0tcIl0sXG4gICAgICAgICAgICBbMHg0ZmMwMDAwMCwgMHg0ZmMyMDAwMCwgXCJJUk9NX01BU0tcIl0sXG4gICAgICAgICAgICBbMHg0MDAwMDAwMCwgMHg0YzAwMDAwMCwgXCJJUk9NXCJdLFxuICAgICAgICAgICAgWzB4NGZmMDAwMDAsIDB4NGZmYTAwMDAsIFwiSVJBTVwiXSxcbiAgICAgICAgICAgIFsweDUwMTA4MDAwLCAweDUwMTEwMDAwLCBcIlJUQ19JUkFNXCJdLFxuICAgICAgICAgICAgWzB4NTAxMDgwMDAsIDB4NTAxMTAwMDAsIFwiUlRDX0RSQU1cIl0sXG4gICAgICAgICAgICBbMHg2MDBmZTAwMCwgMHg2MDEwMDAwMCwgXCJNRU1fSU5URVJOQUwyXCJdLFxuICAgICAgICBdO1xuICAgICAgICB0aGlzLlVGMl9GQU1JTFlfSUQgPSAweDNkMzA4ZTk0O1xuICAgICAgICB0aGlzLkVGVVNFX01BWF9LRVkgPSA1O1xuICAgICAgICB0aGlzLktFWV9QVVJQT1NFUyA9IHtcbiAgICAgICAgICAgIDA6IFwiVVNFUi9FTVBUWVwiLFxuICAgICAgICAgICAgMTogXCJFQ0RTQV9LRVlcIixcbiAgICAgICAgICAgIDI6IFwiWFRTX0FFU18yNTZfS0VZXzFcIixcbiAgICAgICAgICAgIDM6IFwiWFRTX0FFU18yNTZfS0VZXzJcIixcbiAgICAgICAgICAgIDQ6IFwiWFRTX0FFU18xMjhfS0VZXCIsXG4gICAgICAgICAgICA1OiBcIkhNQUNfRE9XTl9BTExcIixcbiAgICAgICAgICAgIDY6IFwiSE1BQ19ET1dOX0pUQUdcIixcbiAgICAgICAgICAgIDc6IFwiSE1BQ19ET1dOX0RJR0lUQUxfU0lHTkFUVVJFXCIsXG4gICAgICAgICAgICA4OiBcIkhNQUNfVVBcIixcbiAgICAgICAgICAgIDk6IFwiU0VDVVJFX0JPT1RfRElHRVNUMFwiLFxuICAgICAgICAgICAgMTA6IFwiU0VDVVJFX0JPT1RfRElHRVNUMVwiLFxuICAgICAgICAgICAgMTE6IFwiU0VDVVJFX0JPT1RfRElHRVNUMlwiLFxuICAgICAgICAgICAgMTI6IFwiS01fSU5JVF9LRVlcIixcbiAgICAgICAgfTtcbiAgICB9XG4gICAgYXN5bmMgZ2V0UGtnVmVyc2lvbihsb2FkZXIpIHtcbiAgICAgICAgY29uc3QgbnVtV29yZCA9IDI7XG4gICAgICAgIGNvbnN0IGFkZHIgPSB0aGlzLkVGVVNFX0JMT0NLMV9BRERSICsgNCAqIG51bVdvcmQ7XG4gICAgICAgIGNvbnN0IHJlZ2lzdGVyVmFsdWUgPSBhd2FpdCBsb2FkZXIucmVhZFJlZyhhZGRyKTtcbiAgICAgICAgcmV0dXJuIChyZWdpc3RlclZhbHVlID4+IDI3KSAmIDB4MDc7XG4gICAgfVxuICAgIGFzeW5jIGdldE1pbm9yQ2hpcFZlcnNpb24obG9hZGVyKSB7XG4gICAgICAgIGNvbnN0IG51bVdvcmQgPSAyO1xuICAgICAgICBjb25zdCBhZGRyID0gdGhpcy5FRlVTRV9CTE9DSzFfQUREUiArIDQgKiBudW1Xb3JkO1xuICAgICAgICBjb25zdCByZWdpc3RlclZhbHVlID0gYXdhaXQgbG9hZGVyLnJlYWRSZWcoYWRkcik7XG4gICAgICAgIHJldHVybiAocmVnaXN0ZXJWYWx1ZSA+PiAwKSAmIDB4MGY7XG4gICAgfVxuICAgIGFzeW5jIGdldE1ham9yQ2hpcFZlcnNpb24obG9hZGVyKSB7XG4gICAgICAgIGNvbnN0IG51bVdvcmQgPSAyO1xuICAgICAgICBjb25zdCBhZGRyID0gdGhpcy5FRlVTRV9CTE9DSzFfQUREUiArIDQgKiBudW1Xb3JkO1xuICAgICAgICBjb25zdCByZWdpc3RlclZhbHVlID0gYXdhaXQgbG9hZGVyLnJlYWRSZWcoYWRkcik7XG4gICAgICAgIHJldHVybiAocmVnaXN0ZXJWYWx1ZSA+PiA0KSAmIDB4MDM7XG4gICAgfVxuICAgIGFzeW5jIGdldENoaXBEZXNjcmlwdGlvbihsb2FkZXIpIHtcbiAgICAgICAgY29uc3QgcGtnVmVyc2lvbiA9IGF3YWl0IHRoaXMuZ2V0UGtnVmVyc2lvbihsb2FkZXIpO1xuICAgICAgICBjb25zdCBjaGlwTmFtZSA9IHBrZ1ZlcnNpb24gPT09IDAgPyBcIkVTUDMyLVA0XCIgOiBcInVua25vd24gRVNQMzItUDRcIjtcbiAgICAgICAgY29uc3QgbWFqb3JSZXYgPSBhd2FpdCB0aGlzLmdldE1ham9yQ2hpcFZlcnNpb24obG9hZGVyKTtcbiAgICAgICAgY29uc3QgbWlub3JSZXYgPSBhd2FpdCB0aGlzLmdldE1pbm9yQ2hpcFZlcnNpb24obG9hZGVyKTtcbiAgICAgICAgcmV0dXJuIGAke2NoaXBOYW1lfSAocmV2aXNpb24gdiR7bWFqb3JSZXZ9LiR7bWlub3JSZXZ9KWA7XG4gICAgfVxuICAgIGFzeW5jIGdldENoaXBGZWF0dXJlcyhsb2FkZXIpIHtcbiAgICAgICAgcmV0dXJuIFtcIkhpZ2gtUGVyZm9ybWFuY2UgTUNVXCJdO1xuICAgIH1cbiAgICBhc3luYyBnZXRDcnlzdGFsRnJlcShsb2FkZXIpIHtcbiAgICAgICAgcmV0dXJuIDQwOyAvLyBFU1AzMlA0IFhUQUwgaXMgZml4ZWQgdG8gNDBNSHpcbiAgICB9XG4gICAgYXN5bmMgZ2V0Rmxhc2hWb2x0YWdlKGxvYWRlcikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGFzeW5jIG92ZXJyaWRlVmRkc2Rpbyhsb2FkZXIpIHtcbiAgICAgICAgbG9hZGVyLmRlYnVnKFwiVkREX1NESU8gb3ZlcnJpZGVzIGFyZSBub3Qgc3VwcG9ydGVkIGZvciBFU1AzMi1QNFwiKTtcbiAgICB9XG4gICAgYXN5bmMgcmVhZE1hYyhsb2FkZXIpIHtcbiAgICAgICAgbGV0IG1hYzAgPSBhd2FpdCBsb2FkZXIucmVhZFJlZyh0aGlzLk1BQ19FRlVTRV9SRUcpO1xuICAgICAgICBtYWMwID0gbWFjMCA+Pj4gMDtcbiAgICAgICAgbGV0IG1hYzEgPSBhd2FpdCBsb2FkZXIucmVhZFJlZyh0aGlzLk1BQ19FRlVTRV9SRUcgKyA0KTtcbiAgICAgICAgbWFjMSA9IChtYWMxID4+PiAwKSAmIDB4MDAwMGZmZmY7XG4gICAgICAgIGNvbnN0IG1hYyA9IG5ldyBVaW50OEFycmF5KDYpO1xuICAgICAgICBtYWNbMF0gPSAobWFjMSA+PiA4KSAmIDB4ZmY7XG4gICAgICAgIG1hY1sxXSA9IG1hYzEgJiAweGZmO1xuICAgICAgICBtYWNbMl0gPSAobWFjMCA+PiAyNCkgJiAweGZmO1xuICAgICAgICBtYWNbM10gPSAobWFjMCA+PiAxNikgJiAweGZmO1xuICAgICAgICBtYWNbNF0gPSAobWFjMCA+PiA4KSAmIDB4ZmY7XG4gICAgICAgIG1hY1s1XSA9IG1hYzAgJiAweGZmO1xuICAgICAgICByZXR1cm4gKHRoaXMuX2QyaChtYWNbMF0pICtcbiAgICAgICAgICAgIFwiOlwiICtcbiAgICAgICAgICAgIHRoaXMuX2QyaChtYWNbMV0pICtcbiAgICAgICAgICAgIFwiOlwiICtcbiAgICAgICAgICAgIHRoaXMuX2QyaChtYWNbMl0pICtcbiAgICAgICAgICAgIFwiOlwiICtcbiAgICAgICAgICAgIHRoaXMuX2QyaChtYWNbM10pICtcbiAgICAgICAgICAgIFwiOlwiICtcbiAgICAgICAgICAgIHRoaXMuX2QyaChtYWNbNF0pICtcbiAgICAgICAgICAgIFwiOlwiICtcbiAgICAgICAgICAgIHRoaXMuX2QyaChtYWNbNV0pKTtcbiAgICB9XG4gICAgYXN5bmMgZ2V0Rmxhc2hDcnlwdENvbmZpZyhsb2FkZXIpIHtcbiAgICAgICAgcmV0dXJuOyAvLyBkb2Vzbid0IGV4aXN0IG9uIEVTUDMyLVA0XG4gICAgfVxuICAgIGFzeW5jIGdldFNlY3VyZUJvb3RFbmFibGVkKGxhb2Rlcikge1xuICAgICAgICBjb25zdCByZWdpc3RlclZhbHVlID0gYXdhaXQgbGFvZGVyLnJlYWRSZWcodGhpcy5FRlVTRV9TRUNVUkVfQk9PVF9FTl9SRUcpO1xuICAgICAgICByZXR1cm4gcmVnaXN0ZXJWYWx1ZSAmIHRoaXMuRUZVU0VfU0VDVVJFX0JPT1RfRU5fTUFTSztcbiAgICB9XG4gICAgYXN5bmMgZ2V0S2V5QmxvY2tQdXJwb3NlKGxvYWRlciwga2V5QmxvY2spIHtcbiAgICAgICAgaWYgKGtleUJsb2NrIDwgMCB8fCBrZXlCbG9jayA+IHRoaXMuRUZVU0VfTUFYX0tFWSkge1xuICAgICAgICAgICAgbG9hZGVyLmRlYnVnKGBWYWxpZCBrZXkgYmxvY2sgbnVtYmVycyBtdXN0IGJlIGluIHJhbmdlIDAtJHt0aGlzLkVGVVNFX01BWF9LRVl9YCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmVnU2hpZnREaWN0aW9uYXJ5ID0gW1xuICAgICAgICAgICAgW3RoaXMuRUZVU0VfUFVSUE9TRV9LRVkwX1JFRywgdGhpcy5FRlVTRV9QVVJQT1NFX0tFWTBfU0hJRlRdLFxuICAgICAgICAgICAgW3RoaXMuRUZVU0VfUFVSUE9TRV9LRVkxX1JFRywgdGhpcy5FRlVTRV9QVVJQT1NFX0tFWTFfU0hJRlRdLFxuICAgICAgICAgICAgW3RoaXMuRUZVU0VfUFVSUE9TRV9LRVkyX1JFRywgdGhpcy5FRlVTRV9QVVJQT1NFX0tFWTJfU0hJRlRdLFxuICAgICAgICAgICAgW3RoaXMuRUZVU0VfUFVSUE9TRV9LRVkzX1JFRywgdGhpcy5FRlVTRV9QVVJQT1NFX0tFWTNfU0hJRlRdLFxuICAgICAgICAgICAgW3RoaXMuRUZVU0VfUFVSUE9TRV9LRVk0X1JFRywgdGhpcy5FRlVTRV9QVVJQT1NFX0tFWTRfU0hJRlRdLFxuICAgICAgICAgICAgW3RoaXMuRUZVU0VfUFVSUE9TRV9LRVk1X1JFRywgdGhpcy5FRlVTRV9QVVJQT1NFX0tFWTVfU0hJRlRdLFxuICAgICAgICBdO1xuICAgICAgICBjb25zdCBbcmVnLCBzaGlmdF0gPSByZWdTaGlmdERpY3Rpb25hcnlba2V5QmxvY2tdO1xuICAgICAgICBjb25zdCByZWdpc3RlclZhbHVlID0gYXdhaXQgbG9hZGVyLnJlYWRSZWcocmVnKTtcbiAgICAgICAgcmV0dXJuIChyZWdpc3RlclZhbHVlID4+IHNoaWZ0KSAmIDB4ZjtcbiAgICB9XG4gICAgYXN5bmMgaXNGbGFzaEVuY3J5cHRpb25LZXlWYWxpZChsb2FkZXIpIHtcbiAgICAgICAgY29uc3QgcHVycG9zZXMgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gdGhpcy5FRlVTRV9NQVhfS0VZOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHB1cnBvc2UgPSBhd2FpdCB0aGlzLmdldEtleUJsb2NrUHVycG9zZShsb2FkZXIsIGkpO1xuICAgICAgICAgICAgcHVycG9zZXMucHVzaChwdXJwb3NlKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpc1h0c0FlczEyOEtleSA9IHB1cnBvc2VzLmZpbmQoKHApID0+IHAgPT09IHRoaXMuUFVSUE9TRV9WQUxfWFRTX0FFUzEyOF9LRVkpO1xuICAgICAgICBpZiAodHlwZW9mIGlzWHRzQWVzMTI4S2V5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGlzWHRzQWVzMjU2S2V5MSA9IHB1cnBvc2VzLmZpbmQoKHApID0+IHAgPT09IHRoaXMuUFVSUE9TRV9WQUxfWFRTX0FFUzI1Nl9LRVlfMSk7XG4gICAgICAgIGNvbnN0IGlzWHRzQWVzMjU2S2V5MiA9IHB1cnBvc2VzLmZpbmQoKHApID0+IHAgPT09IHRoaXMuUFVSUE9TRV9WQUxfWFRTX0FFUzI1Nl9LRVlfMik7XG4gICAgICAgIGlmICh0eXBlb2YgaXNYdHNBZXMyNTZLZXkxICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIGlzWHRzQWVzMjU2S2V5MiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufVxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9
\ No newline at end of file
diff --git a/docs/vendors-node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_8266_json.bundle.js b/docs/vendors-node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_8266_json.bundle.js
deleted file mode 100644
index 25a5961..0000000
--- a/docs/vendors-node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_8266_json.bundle.js
+++ /dev/null
@@ -1,14 +0,0 @@
-"use strict";
-(self["webpackChunkTactility_Web_Installer"] = self["webpackChunkTactility_Web_Installer"] || []).push([["vendors-node_modules_esptool-js_lib_targets_stub_flasher_stub_flasher_8266_json"],{
-
-/***/ "./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_8266.json":
-/*!*********************************************************************************!*\
- !*** ./node_modules/esptool-js/lib/targets/stub_flasher/stub_flasher_8266.json ***!
- \*********************************************************************************/
-/***/ ((module) => {
-
-module.exports = /*#__PURE__*/JSON.parse('{"entry":1074843652,"text":"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","text_start":1074843648,"data":"CIH+PwUFBAACAwcAAwMLANTXEEAL2BBAOdgQQNbYEECF5xBAOtkQQJDZEEDc2RBAhecQQKLaEEAf2xBA4NsQQIXnEECF5xBAeNwQQIXnEEBV3xBAHOAQQFfgEECF5xBAhecQQPPgEECF5xBA2+EQQIHiEEDA4xBAf+QQQFDlEECF5xBAhecQQIXnEECF5xBAfuYQQIXnEEB05xBAsN0QQKnYEEDC5RBAydoQQBvaEECF5xBACOcQQE/nEECF5xBAhecQQIXnEECF5xBAhecQQIXnEECF5xBAhecQQELaEEB/2hBA2uUQQAEAAAACAAAAAwAAAAQAAAAFAAAABwAAAAkAAAANAAAAEQAAABkAAAAhAAAAMQAAAEEAAABhAAAAgQAAAMEAAAABAQAAgQEAAAECAAABAwAAAQQAAAEGAAABCAAAAQwAAAEQAAABGAAAASAAAAEwAAABQAAAAWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAIAAAADAAAAAwAAAAQAAAAEAAAABQAAAAUAAAAGAAAABgAAAAcAAAAHAAAACAAAAAgAAAAJAAAACQAAAAoAAAAKAAAACwAAAAsAAAAMAAAADAAAAA0AAAANAAAAAAAAAAAAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAACgAAAAsAAAANAAAADwAAABEAAAATAAAAFwAAABsAAAAfAAAAIwAAACsAAAAzAAAAOwAAAEMAAABTAAAAYwAAAHMAAACDAAAAowAAAMMAAADjAAAAAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAgAAAAIAAAACAAAAAgAAAAMAAAADAAAAAwAAAAMAAAAEAAAABAAAAAQAAAAEAAAABQAAAAUAAAAFAAAABQAAAAAAAAAAAAAAAAAAABAREgAIBwkGCgULBAwDDQIOAQ8AAQEAAAEAAAAEAAAA","data_start":1073720488,"bss_start":1073643776}');
-
-/***/ })
-
-}]);
\ No newline at end of file
diff --git a/package.json b/package.json
index eba5688..ac335a8 100644
--- a/package.json
+++ b/package.json
@@ -12,16 +12,16 @@
"author": "",
"license": "",
"devDependencies": {
+ "copy-webpack-plugin": "^12.0.2",
"css-loader": "^7.1.2",
"exports-loader": "^5.0.0",
"html-webpack-plugin": "^5.6.3",
"style-loader": "^4.0.0",
"webpack": "^5.97.1",
"webpack-cli": "^6.0.1",
- "webpack-dev-server": "^5.2.0",
- "copy-webpack-plugin": "^12.0.2"
+ "webpack-dev-server": "^5.2.0"
},
"dependencies": {
- "esp-web-tools": "^10.1.1"
+ "esptool-js": "^0.7.1"
}
}
diff --git a/src/.nojekyll b/src/.nojekyll
deleted file mode 100644
index e69de29..0000000
diff --git a/src/CNAME b/src/CNAME
deleted file mode 100644
index 7e1e67d..0000000
--- a/src/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-install.tactilityproject.org
diff --git a/src/app.css b/src/app.css
index 755fbcd..bf92e8e 100644
--- a/src/app.css
+++ b/src/app.css
@@ -424,8 +424,7 @@ main > .notice {
/* Buttons */
-esp-web-install-button {
- display: block;
+#InstallButton {
margin-top: 18px;
}
@@ -449,6 +448,25 @@ esp-web-install-button {
transform: translateY(1px);
}
+.button-primary:disabled {
+ filter: none;
+ opacity: 0.45;
+ cursor: not-allowed;
+}
+
+.button-secondary {
+ padding: 12px 20px;
+ background: var(--surface-raised);
+ border: 1px solid var(--border);
+ border-radius: var(--radius-small);
+ font-weight: 650;
+ cursor: pointer;
+}
+
+.button-secondary:hover {
+ border-color: var(--text-muted);
+}
+
.button-link {
padding: 0;
background: none;
@@ -461,11 +479,96 @@ esp-web-install-button {
text-decoration: underline;
}
-.install-fallback {
+/* Install dialog */
+
+.dialog {
+ width: min(460px, calc(100vw - 32px));
+ padding: 24px;
+ background: var(--surface);
+ border: 1px solid var(--border);
+ border-radius: var(--radius);
+ box-shadow: var(--shadow);
+ color: var(--text);
+}
+
+.dialog::backdrop {
+ background: rgba(0, 0, 0, 0.55);
+}
+
+.dialog h2 {
+ margin: 0 0 10px;
+ font-size: 1.2rem;
+}
+
+.dialog p {
+ margin: 0 0 16px;
+ overflow-wrap: anywhere;
+}
+
+.dialog-actions {
+ display: flex;
+ gap: 10px;
+ margin-top: 20px;
+}
+
+.dialog-actions > * {
+ flex: 1;
+}
+
+.dialog-hint {
+ color: var(--text-muted);
+ font-size: 0.88rem;
+}
+
+.dialog progress {
+ display: block;
+ width: 100%;
+ height: 10px;
+ margin-bottom: 14px;
+ accent-color: var(--primary);
+}
+
+.check {
+ display: flex;
+ gap: 10px;
+ align-items: flex-start;
+ padding: 12px 14px;
+ border: 1px solid var(--border);
+ border-radius: var(--radius-small);
+ cursor: pointer;
+}
+
+.check input {
+ margin-top: 5px;
+ accent-color: var(--primary);
+}
+
+.check-sub {
display: block;
color: var(--text-muted);
- font-size: 0.92rem;
- text-align: center;
+ font-size: 0.88rem;
+}
+
+.install-log {
+ margin-top: 16px;
+ color: var(--text-muted);
+ font-size: 0.85rem;
+}
+
+.install-log summary {
+ cursor: pointer;
+}
+
+.install-log pre {
+ max-height: 180px;
+ margin: 8px 0 0;
+ padding: 10px;
+ overflow: auto;
+ background: var(--bg);
+ border-radius: var(--radius-small);
+ font-size: 0.78rem;
+ white-space: pre-wrap;
+ overflow-wrap: anywhere;
}
@media (max-width: 820px) {
diff --git a/src/index.html b/src/index.html
index 7efa576..284d6b9 100644
--- a/src/index.html
+++ b/src/index.html
@@ -36,6 +36,10 @@ Install Tactility on your device
or check the alternative install methods .
+
+ Installing only works when this page is opened over HTTPS or on localhost.
+
+
1 Choose your device
@@ -85,15 +89,50 @@ 2 Pick a version and install
-
- Install now
- Your browser is not supported.
- Installing is only possible over HTTPS.
-
+ Install now
+
+
+
Install Tactility
+
+
+
+
+ Erase the device first
+ Recommended when installing for the first time. Deletes all data on the device.
+
+
+
+ Cancel
+ Install
+
+
+
+
+
Installing
+
+
+
Keep the device connected and this page open.
+
+
+
+
+
+
+ Try again
+ Close
+
+
+
+
+ Log
+
+
+
+
diff --git a/src/install.js b/src/install.js
new file mode 100644
index 0000000..26dd75b
--- /dev/null
+++ b/src/install.js
@@ -0,0 +1,220 @@
+const BAUDRATE = 115200;
+
+const $ = (id) => document.getElementById(id);
+
+/** An error with a message that is fit to show to the user. */
+class InstallError extends Error {}
+
+/** The install that the dialog is currently showing: { port, manifestUrl, label } */
+let session = null;
+let busy = false;
+
+/** Why installing is impossible in this browser context, or null when it is possible. */
+export function getUnsupportedReason() {
+ if (!window.isSecureContext) {
+ return 'insecure';
+ }
+ return 'serial' in navigator ? null : 'browser';
+}
+
+function showStep(step) {
+ for (const element of $('InstallDialog').querySelectorAll('[data-step]')) {
+ element.hidden = element.dataset.step !== step;
+ }
+}
+
+/** @param {?number} fraction progress from 0 to 1, or null when it is unknown */
+function setStatus(text, fraction = null) {
+ $('InstallStatus').textContent = text;
+ const bar = $('InstallBar');
+ if (fraction === null) {
+ bar.removeAttribute('value');
+ } else {
+ bar.value = fraction;
+ }
+}
+
+function log(text) {
+ const output = $('InstallLog');
+ output.textContent += text;
+ output.scrollTop = output.scrollHeight;
+}
+
+const terminal = {
+ clean: () => { $('InstallLog').textContent = ''; },
+ write: (text) => log(text),
+ writeLine: (text) => log(`${text}\n`),
+};
+
+function showResult(title, text, canRetry) {
+ $('InstallResultTitle').textContent = title;
+ $('InstallResultText').textContent = text;
+ $('InstallRetry').hidden = !canRetry;
+ showStep('result');
+}
+
+async function fetchOk(url) {
+ let response;
+ try {
+ response = await fetch(url);
+ } catch (error) {
+ throw new InstallError(`Failed to download ${url}. Check your internet connection.`, { cause: error });
+ }
+ if (!response.ok) {
+ throw new InstallError(`Failed to download ${url} (HTTP ${response.status}).`);
+ }
+ return response;
+}
+
+const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
+
+/**
+ * Restart the chip by pulsing its EN pin through the RTS line, like esptool.py does.
+ * The hard reset of esptool-js only releases RTS, which doesn't restart boards with a USB-UART bridge.
+ */
+async function hardReset(transport) {
+ await transport.setRTS(true);
+ await sleep(100);
+ await transport.setRTS(false);
+ await sleep(50);
+}
+
+async function flash({ port, manifestUrl }, erase) {
+ setStatus('Preparing…');
+ const [{ ESPLoader, Transport }, manifest] = await Promise.all([
+ import('esptool-js'),
+ fetchOk(manifestUrl).then((response) => response.json()),
+ ]);
+
+ const transport = new Transport(port);
+ try {
+ const loader = new ESPLoader({
+ transport,
+ baudrate: BAUDRATE,
+ romBaudrate: BAUDRATE,
+ terminal,
+ resetConstructors: { hardReset: () => ({ reset: () => hardReset(transport) }) },
+ });
+
+ setStatus('Connecting to the device…');
+ try {
+ await loader.main();
+ } catch (error) {
+ throw new InstallError(
+ 'Failed to connect to the device. Make sure no other program is using it, '
+ + 'then try again while holding the BOOT button.',
+ { cause: error },
+ );
+ }
+
+ const chip = loader.chip.CHIP_NAME;
+ const build = manifest.builds.find((candidate) => candidate.chipFamily === chip);
+ if (!build) {
+ throw new InstallError(`The connected device has an ${chip} chip, which this firmware does not support. `
+ + 'Check that you selected the right device.');
+ }
+
+ setStatus('Downloading firmware…');
+ const baseUrl = new URL(manifestUrl, location.href);
+ const fileArray = await Promise.all(build.parts.map(async (part) => {
+ const response = await fetchOk(new URL(part.path, baseUrl));
+ return { address: part.offset, data: new Uint8Array(await response.arrayBuffer()) };
+ }));
+
+ if (erase) {
+ setStatus('Erasing the device. This can take a minute…');
+ await loader.eraseFlash();
+ }
+
+ const totalSize = fileArray.reduce((sum, file) => sum + file.data.length, 0);
+ let finishedSize = 0;
+ setStatus('Installing… 0%', 0);
+ await loader.writeFlash({
+ fileArray,
+ flashMode: 'keep',
+ flashFreq: 'keep',
+ flashSize: 'keep',
+ eraseAll: false,
+ compress: true,
+ // "written" and "total" count compressed bytes, so scale them to the size of the file
+ reportProgress: (fileIndex, written, total) => {
+ const fileSize = fileArray[fileIndex].data.length;
+ const fraction = (finishedSize + (written / total) * fileSize) / totalSize;
+ setStatus(`Installing… ${Math.floor(fraction * 100)}%`, fraction);
+ if (written === total) {
+ finishedSize += fileSize;
+ }
+ },
+ });
+
+ setStatus('Restarting the device…');
+ await loader.after('hard_reset');
+ } catch (error) {
+ // Don't leave the device stuck in its bootloader
+ await hardReset(transport).catch((resetError) => console.warn('Failed to reset the device', resetError));
+ throw error;
+ } finally {
+ await transport.disconnect().catch((error) => console.warn('Failed to close the serial port', error));
+ }
+}
+
+async function run() {
+ const erase = $('InstallErase').checked;
+ busy = true;
+ showStep('progress');
+ try {
+ await flash(session, erase);
+ showResult('Installation complete', `${session.label} is installed. Your device is restarting.`, false);
+ } catch (error) {
+ console.error(error);
+ log(`\nError: ${error.message}\n`);
+ const text = error instanceof InstallError
+ ? error.message
+ : `Installation failed: ${error.message} Reconnect the device and try again.`;
+ showResult('Installation failed', text, true);
+ } finally {
+ busy = false;
+ }
+}
+
+function showConfirm() {
+ $('InstallSummary').textContent = `${session.label} will be installed on the device you selected.`;
+ showStep('confirm');
+}
+
+/**
+ * Ask for a serial port and open the install dialog. Must be called from a user gesture.
+ * @param {string} manifestUrl URL of an ESP Web Tools manifest
+ * @param {string} label what is being installed, e.g. "Tactility 1.0.0 for LilyGO T-Deck"
+ */
+export async function startInstall(manifestUrl, label) {
+ let port;
+ try {
+ port = await navigator.serial.requestPort();
+ } catch (error) {
+ if (error.name === 'NotFoundError') {
+ return; // The user closed the port picker
+ }
+ throw error;
+ }
+ session = { port, manifestUrl, label };
+ $('InstallErase').checked = false;
+ $('InstallLog').textContent = '';
+ showConfirm();
+ $('InstallDialog').showModal();
+}
+
+export function initInstallDialog() {
+ const dialog = $('InstallDialog');
+ $('InstallConfirm').addEventListener('click', run);
+ $('InstallRetry').addEventListener('click', showConfirm);
+ for (const button of dialog.querySelectorAll('[data-close]')) {
+ button.addEventListener('click', () => dialog.close());
+ }
+ // Escape must not close the dialog halfway through an install
+ dialog.addEventListener('cancel', (event) => {
+ if (busy) {
+ event.preventDefault();
+ }
+ });
+}
diff --git a/src/main.js b/src/main.js
index f151300..f034b66 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,5 +1,5 @@
-import 'esp-web-tools';
import './app.css';
+import { getUnsupportedReason, initInstallDialog, startInstall } from './install';
import toolbarLogo from '../assets/images/toolbar-logo.svg';
import '../assets/images/favicon.svg';
@@ -20,7 +20,8 @@ const state = {
function getCdnUrl(version, path) {
const directory = version === 'unstable' ? 'snapshot' : version;
- return `https://cdn.tactilityproject.org/firmware/${directory}/${path}`;
+ // CDN_BASE_URL is injected by webpack: empty (dev server proxy) when serving
+ return `${CDN_BASE_URL}/firmware/${directory}/${path}`;
}
/** Lowercase and strip punctuation, so "tdeck" matches "T-Deck". */
@@ -232,8 +233,6 @@ function renderDetails() {
if (build.infoMessage) {
info.append(createNotice(build.infoMessage, 'info'));
}
-
- $('Installer').manifest = getCdnUrl(version, `${device.id}.json`);
}
function selectDevice(id) {
@@ -307,7 +306,24 @@ async function load() {
}
$('NavbarImage').src = toolbarLogo;
-$('UnsupportedNotice').hidden = 'serial' in navigator;
+const unsupportedReason = getUnsupportedReason();
+$('UnsupportedNotice').hidden = unsupportedReason !== 'browser';
+$('InsecureNotice').hidden = unsupportedReason !== 'insecure';
+$('InstallButton').disabled = unsupportedReason !== null;
+initInstallDialog();
+
+$('InstallButton').addEventListener('click', () => {
+ const device = getSelectedDevice();
+ if (device === null) {
+ return;
+ }
+ const version = getActiveVersion(device);
+ const label = `Tactility ${state.indexes[version].version} for ${device.label}`;
+ startInstall(getCdnUrl(version, `${device.id}.json`), label).catch((error) => {
+ console.error(error);
+ alert(`Failed to open the serial port: ${error.message}`);
+ });
+});
$('Search').addEventListener('input', (event) => {
state.query = event.target.value;
diff --git a/webpack.config.js b/webpack.config.js
index 033f139..707b012 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,33 +1,39 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
-const CopyPlugin = require("copy-webpack-plugin");
+const { DefinePlugin } = require('webpack');
-module.exports = {
+const CDN_ORIGIN = 'https://cdn.tactilityproject.org';
+
+// The CDN only allows CORS from the production origin, so the dev server
+// proxies /firmware and the app uses same-origin URLs while serving.
+module.exports = (env = {}) => ({
entry: './src/main.js',
- mode: 'development',
- devtool: 'inline-source-map',
+ mode: env.WEBPACK_SERVE ? 'development' : 'production',
+ devtool: env.WEBPACK_SERVE ? 'inline-source-map' : 'source-map',
output: {
filename: 'bundle.js',
- path: path.resolve(__dirname, 'docs'),
+ path: path.resolve(__dirname, 'dist'),
+ clean: true,
assetModuleFilename: 'assets/images/[name][ext]'
},
devServer: {
- static: {
- directory: path.join(__dirname, 'docs'),
- },
compress: false,
port: 8080,
+ proxy: [
+ {
+ context: ['/firmware'],
+ target: CDN_ORIGIN,
+ changeOrigin: true,
+ },
+ ],
},
plugins: [
+ new DefinePlugin({
+ CDN_BASE_URL: JSON.stringify(env.WEBPACK_SERVE ? '' : CDN_ORIGIN),
+ }),
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
- new CopyPlugin({
- patterns: [
- { from: "src/CNAME", to: "./" },
- { from: "src/.nojekyll", to: "./" }
- ],
- }),
],
module: {
rules: [
@@ -41,4 +47,4 @@ module.exports = {
}
]
}
-};
+});