Полезная информация

Список ответов на каверзные вопросы можно получить в FAQ-разделе форума.

№112622-09-2023 09:05:44

rubel
Участник
 
Группа: Members
Откуда: г.Самара
Зарегистрирован: 10-05-2005
Сообщений: 570
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

fuchsfan
Сделал

Выделить код

Код:

load: [ // По событию "load"
            // { path: "special_widgets.js", ucfobj: true, }, // <-- Special Widgets
			 { path: "WinFolders.js", ucfobj: true, },
			 { path: "favicon_in_urlbar.js", ucfobj: true, },
            // { path: "auto_hide_sidebar.js", ucfobj: true, }, // <-- Auto Hide Sidebar
        ],

Все равно кнопки нет, а вот иконка сайта в адресной строке появилась.
Может дадите папку chrome, попробую заменить.

Отсутствует

 

№112722-09-2023 09:21:18

fuchsfan
Участник
 
Группа: Members
Зарегистрирован: 07-08-2023
Сообщений: 130
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

В настройках панели инструментов смотрели? В гл. окне браузера мышкой медленно поводите там, где могла бы быть кнопка, может, кнопка есть, но без иконки, под мышкой это проявится. Я отошел от ucf, но смогу проверить ваш WinFolders.js на другом компе, если выложите код.

Отсутствует

 

№112822-09-2023 09:30:41

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1746
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

rubel пишет

Как и куда подключать ?

Я добавляю в файл -> custom_script.js
2023-09-22_102030.png

rubel пишет

UCF для FF 115-116 с правками от Dumby

Я спрашивал про версию UCF, а не про сделанные правки, кстати про правку для [firefox] 116 я в курсе, а что за правка для [firefox] 115 ?

Отредактировано kokoss (22-09-2023 10:23:21)


Win7

Отсутствует

 

№112922-09-2023 09:52:10

rubel
Участник
 
Группа: Members
Откуда: г.Самара
Зарегистрирован: 10-05-2005
Сообщений: 570
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

fuchsfan
Да, нашлась кнопка, но без иконки её не видно совсем.
57ad6731ba2b9982587c75fcbdeed577.png
Первая директория работает открывается, а вот вторая не появляется совсем.
Вот мой WinFolders.js

Выделить код

Код:

// Скрипт создает подмножество кнопок для запуска приложений, открытия папок и файлов
// Кнопка 1 (Открыть F:\\Firefox Backup)
try {
    CustomizableUI.createWidget({
        id: "add-openfolder1-app",
        label: "Открыть папку 1",
        tooltiptext: "Открыть D:\\1",
        defaultArea: CustomizableUI.AREA_NAVBAR,
	onCreated: btn => btn.image = "file:///D:/Portable Files/Firefox Portable/Profiles/Chrome/icons/folder1.png",
        onCommand: function(event) {
            var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
            file.initWithPath("D:\\1");
            if (file.exists()) file.launch();
        }
    });
} catch(e) {}

// Кнопка 2 (повторяем код с другим путем)
try {
    CustomizableUI.createWidget({
        id: "add-openfolder1-app",
        label: "Открыть папку 2",
        tooltiptext: "Открыть D:\\Downloads",
        defaultArea: CustomizableUI.AREA_NAVBAR,
	onCreated: btn => btn.image = "file:///D:/Portable Files/Firefox Portable/Profiles/Chrome/icons/folder1.png",
        onCommand: function(event) {
            var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
            file.initWithPath("D:\\Downloads");
            if (file.exists()) file.launch();
        }
    });
} catch(e) {}
// Следующая кнопка...

Что не правильно ?

Отсутствует

 

№113022-09-2023 09:56:26

fuchsfan
Участник
 
Группа: Members
Зарегистрирован: 07-08-2023
Сообщений: 130
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

rubel
Просто к сведению, существует расширение Async Run Applications 2021.9.7 by VitaliyV аналогичного функционала, создает кнопку с выпадающим меню, в котором пользовательские кнопки. Давненько не использовал.

Добавлено 22-09-2023 09:56:48
Ага, увидел, проверю.

Добавлено 22-09-2023 10:01:00

Выделить код

Код:

onCreated: btn => btn.image = "file:///D:/Portable Files/Firefox Portable/Profiles/Chrome/icons/folder1.png",

Измените путь на свой, в папке Chrome создайте папку icons, в нее положите иконку 16х16, 24х24 пикселя png, jpg с любым именем, в коде исправьте имя на свое. И иконка появится.

Добавлено 22-09-2023 10:03:41
Кнопки не должны иметь одинаковый ID, во втором коде измените ID кнопки на другой произвольный, хотя бы цифру 2 вместо 1

Выделить код

Код:

id: "add-openfolder1-app",

Добавлено 22-09-2023 10:11:12

rubel пишет

tooltiptext: "Открыть D:\\Downloads",

В этой строке измените всплывающую подсказку на свою

Отредактировано fuchsfan (22-09-2023 10:11:12)

Отсутствует

 

№113122-09-2023 10:23:01

rubel
Участник
 
Группа: Members
Откуда: г.Самара
Зарегистрирован: 10-05-2005
Сообщений: 570
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

fuchsfan
Все понял, работает. Просто добавляется еще одна кнопка. Спасибо. Но создавать множество кнопок я не хочу.
В том коде от Dumby создается кнопка с выпадающим списком директорий. Вот его хочу и применить.

Добавлено 22-09-2023 10:40:40
kokoss
Спасибо за скриншот. :beer: Нашел я эту кнопку невзрачную в настройках панели инструментов.
2a82117721666a6600498da51b4051f8.png 
Всем спасибо за внимание.

Отредактировано rubel (22-09-2023 10:40:40)

Отсутствует

 

№113222-09-2023 11:35:18

fuchsfan
Участник
 
Группа: Members
Зарегистрирован: 07-08-2023
Сообщений: 130
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

rubel пишет

кнопку невзрачную

Так можете заменить на любую свою взрачную, тем более. что эта ассоциируется с "сохранить" (стрелка вовнутрь), а не с "открыть" (стрелка наружу).

Отредактировано fuchsfan (22-09-2023 11:41:32)

Отсутствует

 

№113322-09-2023 13:21:23

rubel
Участник
 
Группа: Members
Откуда: г.Самара
Зарегистрирован: 10-05-2005
Сообщений: 570
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

fuchsfan
Эта кнопка была невзрачная от автора и она затерялась  в настройках панели инструментов. А теперь конечно могу её сделать на свой вкус. :)

Отсутствует

 

№113426-09-2023 00:05:15

6e73epo
Участник
 
Группа: Members
Зарегистрирован: 06-05-2022
Сообщений: 207
UA: Firefox 117.0

Re: UCF - ваши кнопки, скрипты…

fuchsfan, а чтобы кнопка открывала папку chrome в профиле, какой путь указать? Без всяких проверок на существование папки

Отсутствует

 

№113526-09-2023 03:52:26

rubel
Участник
 
Группа: Members
Откуда: г.Самара
Зарегистрирован: 10-05-2005
Сообщений: 570
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

Dumby
Вроде на форуме нет темы по скриптам, подключаемых по методам
метод Aris-t2   метод xiaoxiaoflood   метод Endor8
Может нужно создать тему по этим методам.
Поэтому попрошу Вас здесь посмотреть скрипт ucf-mem-indicator.js
Он перестал работать в 115. Применяю метод Endor8 для загрузки скриптов.

скрытый текст
ucf-mem-indicator.js

Выделить код

Код:

(async id => ({

  delay: 2e3,

  val: "",
  init(topic, mm) {
    Services.obs.addObserver(mm = this, topic);
    Services.obs.addObserver(function quit(s, t) {
      this.timer?.cancel();
      Services.obs.removeObserver(mm, topic);
      Services.obs.removeObserver(quit, t);
    }, "quit-application-granted");
  },
  observe(win) {
    var df = win.MozXULElement.parseXULToFragment(
      `<hbox id="${id}" tooltiptext="${
        "ЛКМ: Минимизировать потребление памяти&#xA;ПКМ: about:performance&#xA;Ctrl+ПКМ: about:debugging#/runtime/this-firefox"
      }" onclick="event.button || ${
        "memoryMinimizationButton.doMinimize(event)"
      }"><label id="${id += "-label"}"/></hbox>`
    );
    this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
    (this.observe = async win => {
      this.timer.cancel();
      await new Promise(ChromeUtils.idleDispatch);
      var clone = win.document.importNode(df, true);
      clone.firstChild.oncontextmenu = this.about;
      win.document.getElementById("star-button-box").after(clone);
      this.notify();
    })(win);
  },
  about(e) {
    var gb = e.view.gBrowser;
    gb.selectedTab = gb.addTrustedTab(`about:${
      e.ctrlKey ? "debugging#/runtime/this-firefox" : "performance"
    }`);
  },
  async notify() {
    var info = await ChromeUtils.requestProcInfo();
    var bytes = info.memory;
    for(var child of info.children) bytes += child.memory;
    this.timer.initWithCallback(this, this.delay, this.timer.TYPE_ONE_SHOT);

    var prev = this.val;
    if ((this.val = this.mgb(bytes)) != prev)
      for(var win of CustomizableUI.windows) {
        var lab = win.document.getElementById(id);
        if (lab) lab.value = this.val;
      }
  },
  mgb: bytes => bytes < 1073741824
    ? Math.round(bytes / 1048576) + "MB"
    : (bytes / 1073741824).toFixed(2) + "GB"
}).init("browser-delayed-startup-finished"))("ucf-mem-indicator");

Отсутствует

 

№113626-09-2023 04:41:59

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 475
UA: Firefox 97.0

Re: UCF - ваши кнопки, скрипты…

rubel пишет

Вроде на форуме нет темы по скриптам, подключаемых по методам Aris-t2

Насколько я понимаю, метод Aris-t2 не позволяет подключать скрипты «В фоне [System Principal]», поэтому UCF удобней и полезней…
кроме того, в подключении скриптов методом Aris-t2 нет ничего сложного.

Отсутствует

 

№113726-09-2023 06:59:52

fuchsfan
Участник
 
Группа: Members
Зарегистрирован: 07-08-2023
Сообщений: 130
UA: Firefox 118.0

Re: UCF - ваши кнопки, скрипты…

6e73epo пишет

а чтобы кнопка открывала папку chrome в профиле, какой путь указать?

Указать реальный путь к папке Chrome.

Выделить код

Код:

file.initWithPath("D:\\Portable Files\\Firefox Portable\\Profiles\\Chrome");
6e73epo пишет

Без всяких проверок на существование папки

Если браузер перемещен в другую директорию, чтобы скрипт сам определял путь к папке Chrome, такого не знаю, но есть кнопка для папки Profiles, а там останется один клик. И есть скрипт сложнее и побольше, который путь ко всем папкам Firefox и файлам userChrome.css, user.js определяет сам.

Отредактировано fuchsfan (26-09-2023 07:00:26)

Отсутствует

 

№113826-09-2023 07:58:50

6e73epo
Участник
 
Группа: Members
Зарегистрирован: 06-05-2022
Сообщений: 207
UA: Firefox 117.0

Re: UCF - ваши кнопки, скрипты…

fuchsfan, с пробелами не тестировал, у меня путь без пробелов. Завелось так

Выделить код

Код:

onCommand: function(event) {
	Services.dirsvc.get("UChrm", Ci.nsIFile).launch();
}

Отсутствует

 

№113926-09-2023 08:32:58

fuchsfan
Участник
 
Группа: Members
Зарегистрирован: 07-08-2023
Сообщений: 130
UA: Firefox 118.0

Re: UCF - ваши кнопки, скрипты…

rubel пишет

метод Aris-t2   метод xiaoxiaoflood   метод Endor8
Может нужно создать тему по этим методам.

Зато есть тема под названием userChrome.js https://forum.mozilla-russia.org/viewtopic.php?id=77354 и вашему посту как раз в ней место, а не в теме по ucf.

Отсутствует

 

№114026-09-2023 10:50:12

rubel
Участник
 
Группа: Members
Откуда: г.Самара
Зарегистрирован: 10-05-2005
Сообщений: 570
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

Dobrov пишет

кроме того, в подключении скриптов методом Aris-t2 нет ничего сложного.

Да и методом UCF тоже ничего сложного, когда его освоишь.
Дело только в том, что не все скрипты, работающие в UCF, работают методом Aris-t2.
Вот и хотелось бы их подправить по возможности. :/
fuchsfan
Запостил в той теме свой вопрос.

Отсутствует

 

№114126-09-2023 16:22:59

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 475
UA: Firefox 116.0

Re: UCF - ваши кнопки, скрипты…

rubel пишет

UCF для FF 115-116 с правками от Dumby. Как и куда подключать ?

ответ Всем… По этой инструкции. или читаем Шапку.
исправил версию UCF, совместимую с Firefox от 78 до 117, всё в папках Firefox, chrome/user_chrome_files

Отсутствует

 

№114227-09-2023 00:13:04

b0ttle
Участник
 
Группа: Members
Зарегистрирован: 22-10-2020
Сообщений: 182
UA: Firefox 117.0

Re: UCF - ваши кнопки, скрипты…

Может кому пригодится, спасибо dobrov. Кстати, тут есть и хоткей, и кнопки-папки, да много чего. Удобная штука, советую) По желанию, можно подвести под личные потребности. Не пропускает в тексте, скорее всего из-за каких-то символов... пришлось так. Вставить в адресную строку.
А да, настроен немного под себя. Если что поменяйте.

Выделить код

Код:

data:text/plain;charset=UTF-8;base64,KGFzeW5jKEZmLHRFeHApPT57IC8vIGhvb2sgTW91c2VLZXlzIMKpIER1bWJ5LCBtb2QgMi4wIERvYnJvdiDQutC90L7Qv9C60Lgg0LrQvtC80LDQvdC00Ysg0YHQutC40L3igKYKVGFnPXsKCiJkb3dubG9hZHMtYnV0dG9uIjoneycrIC8v0L3Rg9C20LXQvSBTaW5nbGVIVE1MLmpzbSwg0LfQsNCy0LjRgdC40LzRi9C5IHVjZl9RdWlja1RvZ2dsZQpg4peJ77yaICAgIOKsh++4jmZvbGRlciBbRG93bmxvYWRzXQril6jvvJogICAgICAgICAgIOKenFNhdmUgUGFnZQril4nvvJogICAgICAgICAgIG9uIFBob3RvIOKenFNhdmXvuLBgKyAvL9C00LXQudGB0YLQstC40Y8g0LrQu9Cw0LLQuNGIfNC80YvRiNC4LCDQv9C+0LTRgdC60LDQt9C60LgKYOKXpy1sb25n77yaIOKsh++4jmZvbGRlciBbRG93bmxvYWRzXVxuCuKXqO+8miAgICAgICAgICAgICAgIChBbHQrUykg4p6cU2F2ZQogICAgICAgICAgICAgICB0byBTaW5nbGVIVE1MIGFsbCAvaGlnaGxpZ2h0ZWQK4peJ77yaICAgICAgICAgICAgICAgJHtGZi5DdHIoIlN1cGVyIiwiQ3RybCtTaGlmdCIpfStTIOKenGFzIFRleHRcbgril6ctZG91Ymxl77yaIG9uIFBob3RvOiBmaW5kIFNpbWlsYXIK4penK1NoaWZ077yaICAgIEdyYXBoaWNzIG9uL29mZgril6crQWx077yaICAgICAgIFNlbGVjdGlvbiBkaWFsb2cgb24vb2ZmfWAsCgoiUGFuZWxVSS1tZW51LWJ1dHRvbiI6IC8v0YLQtdC60YHRgiDQn9GA0L7RgdGC0L7QuSDRgNC10LbQuNC877iw0K3QutGB0L/QtdGA0YIKYOKXp++8miAgICAgICAgICAgICAgICBtZW51IEZpcmVmb3ggJHtGZi52ZXJ9e1xu77iwCuKXpytTaGlmdO+8miAgICAg4p6/aGVscFxufQril6ctbG9uZ++8miAgICAgICDinJUgQ2xvc2UgYnJvd3NlclxuYCArYOKXpytBbHTvvJril4nvvJog4p2QTWF4aW1pemXilIJSZXN0b3JlCgril6jvvJogICAgICAgICAgICAgICAg4oeyTWluaW1pemUge++4sGAgLyrRjdC60YHQv9C10YDRgiovKyBgCuKXqCtBbHTvvJogICAgICAgICBhYm91dDpzdXBwb3J0fQrDmC1zY3JvbGzvvJog4oaRICDipL4gUmV0dXJuIHRhYmAsCgoiem9vbXBhZ2Utd2VfZHctZGV2LWJyb3dzZXItYWN0aW9uIjoKYFxuXG7il4krQWx077yaICAgIGNsb3NlIHRhYnMgb24gdGhlIHJpZ2h0CuKXiStTaGlmdO+8miBjbG9zZSBsZWZ0YCwKCiJ0YWJzLW5ld3RhYi1idXR0b24iOgpg4peo77yaICAgICDQstC10YDQvdGD0YLRjCDQstC60LvQsNC00LrRgwril6crQWx077yaINC+0YHRgtCw0LLQuNGC0YwgMSDRgtC10LrRg9GJ0YPRjmAsCgoiaWRlbnRpdHktYm94IjogLy9kZWJ1ZyDimJEg0LrQvtC80LDQvdC00Yt80LTQtdC50YHRgtCy0LjRjyDQsiDQutC+0L3RgdC+0LvRjApg4peo77yaICAgICAgICAgICAgICAgIENvcHkgYWRkcmVzcyB0byBjbGlwYm9hcmQK4penK0FsdO+8muKXie+8miBQcm94eSBzZXR0aW5ncwp777iwXG7il6crU2hpZnTvvJogICAgIG1lZGlhVGFifQrDmC1zY3JvbGzvvJogICAgIEJyaWdodG5lc3M6IGAsCgoiZmF2ZGlycy1idXR0b24iOiAvL9Cx0L7QutC+0LLQsNGPINC/0LDQvdC10LvRjCDQvtGC0LrRgNGL0YLQsDogZGVidWcg0JLQutC7CmDil6fvvJogICAgICAgICAgICAg4piFQm9va21hcmtzCuKXqO+8miAgICAgICAgICAgICDin7NIaXN0b3J5CuKXpytBbHTvvJogICAgICBGRgril6grQWx077yaICAgICAgSG9tZSBmb2xkZXJcbgril4nvvJogICAgICAgICAgICAg4qyH77iORG93bmxvYWRzCuKXiStBbHTvvJogICAgICBVc2VyQ2hyb21lRmlsZXNcbgrDmC1zY3JvbGzvvJogICDihpEgdXNlcl9jaHJvbWVfZmlsZXMKICAgICAgICAgICAgICAgICAgICDipL4gY3VzdG9tX3NjcmlwdHMK4penK1NoaWZ077yaICAgJUgudHh0CuKXqCtTaGlmdO+8miAgIHVjZl9ob29rQ2xpY2tzLmpzXG5cbgpNYWduaWZ5JkVtb2ppVzEwKFdpbisuKXxjaGFybWFwLG9zayxzbmR2b2xcbkFsdCtEICBBbHQr4oaQ4oaSL8OYXG5DdHJsK0IvSCAgICAgICAgICAgICAgLUJvb2ttYXJrcy9IICAoQWx0K0IvUylcbkN0cmwrRSAgICAgICAgICAgICAgICAgICAtU2VhcmNoXG5DdHJsK1NoaWZ0K1EvVyAtQ2xvc2VGRlxuQ3RybCtVICAgICAgICAgICAgICAgICAgLVBhZ2VTb3VyY2VcbkN0cmwrTyAgICAgICAgICAgICAgICAgIC1PcGVuIGEgZmlsZVxuQ3RybCtTaGlmdCtTICAgICAgICAtU2NyZWVuc2hvdFxuQ3RybCtBbHQrU2hpZnQrSSAtQnJvd3NlclRvb2xib3hcblxuQ3RybCtTaGlmdCtPL0ggQ3RybCtCL0ggQWx0K0IvU1xuQ3RybCtTaGlmdCtK4pWRQ3RybCtTaGlmdCtEZWzilZFDdHJsK1NoaWZ0K0RcbkN0cmwrU2hpZnQrQuKVkUN0cmwrSuKVkVNoaWZ0K8OY4pWRQ3RybCtTaGlmdCtFIEYxMmAsCgoiVG9nZ2xlQnV0dG9uIjoKYOKXpy1sb25n77yaICAg0LIg0YHRgtGA0L7QutC1INC80LXQvdGOLWFib3V0OmNvbmZpZwril6grQWx077yaICAgICDQv9C+0YHQuy4g0LfQsNC60LvQsNC00LrQsCDQvNC10L3Rjgril6fvvJogICAgICAgICAgICAtwqvQltGD0YDQvdCw0LvCu1xuCuKXqO+8miAgICAgICAgICAgINCc0LXQvdGOINCx0YvRgdGC0YDRi9GFINC90LDRgdGC0YDQvtC10LoK4peJ77yaICAgICAgICAgICAgLeKKntCd0L7QstCw0Y8g0LLQutC70LDQtNC60LAgKCR7RmYuQ3RyKCl9VClcbgril6crQWx077yaICAgICAt0JHQuNCx0LvQuNC+0YLQtdC60LAsINCW0YPRgNC90LDQuyB777iwCuKXpy1sb25n77yaICAg0J/QuNC/0LXRgtC60LAg0YbQstC10YLQsCwg0LvQuNC90LfQsFxuCuKXpytTaGlmdO+8miAg0LzQsNGB0YjRgtCw0LEg0KLQtdC60YHRgiAvINCS0YHRkX0Kw5gtc2Nyb2xs77yaICDQvNCw0YHRiNGC0LDQsSDQodGC0YDQsNC90LjRhtGLIMKxYCwKCiJSZWFkZXJWaWV3IjoKYNCa0LvQuNC6INC80YvRiNC4CdCn0YLQtdC90LjQtSDQsiBSZWFkZXJWaWV3CtCa0L7Qu9GR0YHQuNC60L4J0J/RgNC+0YHRgtC+0Lkg0YDQtdC20LjQvCDRh9GC0LXQvdC40Y9cbmAsCiJyZWFkZXItbW9kZS1idXR0b24iOgpg4peo77yaICAgICAgICAgINCQ0LTQsNC/0YLQuNCy0L3Ri9C5INC00LjQt9Cw0LnQvQril6grQWx077yaICDQktGL0LHQvtGAINGH0LDRgdGC0Lgg0YHRgtGA0LDQvdC40YbRiyBcbgrDmC1zY3LvvJogICDQr9GA0LrQvtGB0YLRjCDRgdGC0YDQsNC90LjRhjogYCwKCiJwcmludC1idXR0b24iOgpg0KDQsNGB0L/QtdGH0LDRgtCw0YLRjCDRgdGC0YDQsNC90LjRhtGDICgke0ZmLkN0cigpfVApXG4K4peo77yaICAgICAgICAgICAg0LHRi9GB0YLRgNCw0Y8g0J/QtdGH0LDRgtGMCuKXie+8miAgICAgICAgICAgINGA0LXQttC40Lwg0LrQvdC+0L/QvtC6CuKXpy1sb25n77yaICDinr/QutGA0LDRgtC60LDRjyDRgdC/0YDQsNCy0LrQsGAsCgoicmVsb2FkLWJ1dHRvbiI6CmDil6fvvJogICAgICAgICAgICDin7Mgbm8gY2FjaGUK4penLWxvbmfvvJogIOKtriBhbGwgdGFic2AsCgoidHJhY2tpbmctcHJvdGVjdGlvbi1pY29uLWNvbnRhaW5lciI6CmDil6fvvJogIFNpdGUgc2VjdXJpdHkgZGV0YWlscwril6jvvJogIExvZ2lucyBhbmQgUGFzc3dvcmRzCuKXie+8miAgYWJvdXQ6cHJvY2Vzc2VzCnvvuLBcbuKXpy1sb25n77yaICDih4YgV2ViLWZvbnRzCuKXpytTaGlmdO+8miAgYWJvdXQ6c2VydmljZXdvcmtlcnN9YCwKCiJ3aGVlbC1zdG9wIjoKYOKXie+8miAgICAgICAgICAgIOKclSBhbGwgcmVsb2Fkcwp777iw4peoLWxvbmfvvJogICBBbnRpemFwcmV0IOKHhiBObyBwcm94eX1cbmAsCgoidGl0bGViYXItYnV0dG9uLnRpdGxlYmFyLWNsb3NlIjogLy/QutGA0L7QvNC1IFdpbmRvd3MKYNCX0LDQutGA0YvRgtGMIEZpcmVmb3ggJHtGZi52ZXJ9XG4K4peJ77yaINCy0LXRgNC90YPRgtGMINCy0LrQu9Cw0LTQutGDCuKXpy1sb25n77yaIOKev9C60YDQsNGC0LrQsNGPINGB0L/RgNCw0LLQutCwCuKXqO+8miDih7LQodCy0LXRgNC90YPRgtGMYCwKCiJBdHRyaWJ1dGVzLUluc3BlY3RvciI6IC8vYXR0cnNJbnNwZWN0b3IuanMgfOKXqO+8miAgICAgICAgICAgINCd0LDRgdGC0YDQvtC50LrQuCBVc2VyQ2hyb21lRmlsZXN8QWx0ICsgeCAgICAgICDQt9Cw0L/Rg9GB0YLQuNGC0Ywg0YHQutGA0LjQv9GCIFVzZXIuanMKYOKXp++8miAgICAgICAgICAgIEF0dHJpYnV0ZXMtSW5zcGVjdG9yCuKXpy1sb25n77yaICDRgdC80LXQvdCwINGA0LXQttC40LzQsCDQutC90L7Qv9C+0LoK4penK0FsdO+8miAgICDQmNC90YHRgtGA0YPQvNC10L3RgtGLINCx0YDQsNGD0LfQtdGA0LAK4penK1NoaWZ077yaINCd0LDRgdGC0YDQvtC50LrQuCDQv9GA0L7RhNCw0LnQu9C10YDQsGAsCgoiQCI6IC8v0YLQtdC60YHRgtGLCmDQntGH0LjRgdGC0LjRgtGMINC/0LDQvdC10LvRjCDQutC+0LvRkdGB0LjQutC+0Lwg0LzRi9GI0Lh80JfQsNC/0YDQtdGJ0ZHQvdC90YvQtSDRgdCw0LnRgtGLINGH0LXRgNC10Lcg0JDQvdGC0LjQl9Cw0L/RgNC10YJ84piAIEJyaWdodG5lc3M6IHzwn5K+INC60Y3RiCwg0LTQsNC90L3Ri9C1INGB0LDQudGC0L7Qsiwg0LrRg9C60Lgg0LfQsNC90LjQvNCw0Y7RgiB80JfQsNGF0LLQsNGCINGG0LLQtdGC0LAg0LIg0JHRg9GE0LXRgCDQvtCx0LzQtdC90LAgKNC60YPRgNGB0L7RgCDQtNCy0LjQs9Cw0LXRgiDQvdCwIDEg0YLQvtGH0LrRgyl84pqh77iPINCX0LDQv9GA0LXRidC10L3QviDRgdC+0YXRgNCw0L3Rj9GC0Ywg0LvQvtCz0LjQvdGLINC4INC/0LDRgNC+0LvQuHzil6cg0LTQtdGA0LbQsNGC0Yw6IGFib3V0OmNvbmZpZywg4peoINC/0YAuINC60LvQuNC6INCh0LHRgNC+0YEsIOKfsyDQntCx0L3QvtCy0LjRgtGMLCDihq8g0J/QtdGA0LXQt9Cw0L/Rg9GB0Lp80JTQvtC70LPQuNC5INC60LvQuNC6INCyINGB0YLRgNC+0LrQtSDQvNC10L3Rjjog0J/RgNCw0LLQuNGC0Ywg0L7Qv9GG0LjRjiDilIIg0JrQvtC70ZHRgdC40LrQvjog0KHQtdGA0LLQuNGB0Yt80J7RiNC40LHQutCwINGB0LrRgNC40L/RgtCwIHzihq8g0J3QtSDQt9Cw0L/QvtC80LjQvdCw0YLRjCDQuNGB0YLQvtGA0LjRjiDQv9C+0YHQtdGJ0LXQvdC40Ll84oavINCj0LTQsNC70Y/RgtGMINC40YHRgtC+0YDQuNGOINC/0L7RgdC10YnQtdC90LjQuSwg0LfQsNC60YDRi9Cy0LDRjyDQsdGA0LDRg9C30LXRgHzQv9C10YDQuNC+0LQg0YHQvtGF0YDQsNC90LXQvdC40Y8g0YHQtdGB0YHQuNC5INC80LXQvdGP0LXRgtGB0Y8g0LIg0LzQtdC90Y4g0LrQvdC+0L/QutC4IMKr0JbRg9GA0L3QsNC7wrt8U2luZ2xlRmlsZSAoQWx0K0N0cmwrUylcbtCh0L7RhdGA0LDQvdC40YLRjCDRgdGC0YDQsNC90LjRhtGDINCyINC10LTQuNC90YvQuSBIdG1sfFZpZGVvIERvd25sb2FkSGVscGVyXG7QodC60LDRh9C40LLQsNC90LjQtSDQv9GA0L7QuNCz0YDRi9Cy0LDQtdC80L7Qs9C+INCy0LjQtNC10L58XG5cbuKXqO+8miDQndCw0YHRgtGA0L7QudC60LggVXNlckNocm9tZUZpbGVzXG7il4nvvJog0J/QtdGA0LXQt9Cw0L/Rg9GB0YLQuNGC0YwsINGD0LTQsNC70LjQsiDQutGN0YhcbkFsdCArIHgJ0LfQsNC/0YPRgdGC0LjRgtGMINGB0LrRgNC40L/RgiBVc2VyLmpzYH07IHZhciBUID0gVGFnWyJAIl0uc3BsaXQoJ3wnKSwgQiA9IFsuLi5PYmplY3Qua2V5cyhUYWcpLCJ2aWV3SGlzdG9yeVNpZGViYXIiXTsKCihhc3luYyAoaWQpID0+IEN1c3RvbWl6YWJsZVVJLmNyZWF0ZVdpZGdldCh7bGFiZWw6YNCf0LDQvdC10LvQuCwg0J/QsNC/0LrQuGAsaWQ6IGlkLHRvb2x0aXB0ZXh0OiBUYWdbaWRdLApvbkNyZWF0ZWQoYnRuKXtidG4uc3R5bGUuc2V0UHJvcGVydHkoImxpc3Qtc3R5bGUtaW1hZ2UiLCJ1cmwoY2hyb21lOi8vZGV2dG9vbHMvc2tpbi9pbWFnZXMvZm9sZGVyLnN2ZykiKTt9fSkKKShCWzVdKTsgLy8g0LrQvdC+0L/QutC4LdC/0L7QtNGB0LrQsNC30LrQuC3QutC70LjQutC4CgprbGFCYSA9IHsgLy/Qv9C10YDQtdGF0LLQsNGCLdC60LvQsNCy0LjRiCBLZXlBW19tb2RdW19PU10oZSx0KXvQutC+0LR9INC4IEtleUI6ICJLZXlBIgoJS2V5WF8xKGUsdCkge3VzZXJqcyhlKX0sICAgICAgLy8gQWx0K1gg0LfQsNC/0YPRgdC6INCy0L3QtdGI0L3QtdCz0L4gSlMt0LrQvtC00LAKCUtleVNfNigpICAgIHtzYXZlU2VsVG9UeHQoKX0sIC8qIEN0cmwrU2hpZnQrUyAqLyBLZXlTXzE1OiAiS2V5U182IiwKCUtleVNfMShlLHQpIHtzYXZlKCl9LCAgICAgICAgIC8vQWx0K1MgfCBlOiBFdmVudCwgdDogZ0Jyb3dzZXIuc2VsZWN0ZWRUYWIKLyoKCW1vZCA9IGUubWV0YUtleSo4ICsgZS5jdHJsS2V5KjQgKyBlLnNoaWZ0S2V5KjIgKyBlLmFsdEtleQoJbW9kICsgSSDQsiDQutC+0L3RhtC1OiDRgtC+0LvRjNC60L4g0LIg0L/QvtC70Y/RhSDQstCy0L7QtNCwLCDCq2nCuyDQutGA0L7QvNC1INC/0L7Qu9C10Lkg0LLQstC+0LTQsAoJMdGPINCx0YPQutCy0LAg0YHRgtGA0L7Rh9C90LDRjzog0L/QtdGA0LXQtNCw0LLQsNGC0Ywg0L3QsNC20LDRgtC40Y8sINC30LDQv9GA0LXRgiBwcmV2ZW50RGVmYXVsdAoJ0L7RgtC00LXQu9GP0YLRjCDCq1/CuyDQvtGCINC60L7QtNCwLCDQtdGB0LvQuCDQtdGB0YLRjCDQvNC+0LTQuNGE0LjQutCw0YLQvtGA0Ysg0Lgv0LjQu9C4IMKraUnCuy3RhNC70LDQswoJ0YLQvtC70YzQutC+INCyINGD0LrQsNC30LDQvdC90L7QuSBPUzogS2V5QV8xaV93aW4oZSx0KXvigKYgQWx0K0Eg0LTQu9GPINCy0LjQvdC00YsgKi8KCS8vPT09PT09PT09PT09CiBCYWNrcXVvdGVfaSgpe1BsYWNlc0NvbW1hbmRIb29rLnNob3dQbGFjZXNPcmdhbml6ZXIoIkJvb2ttYXJrc01lbnUiKS5jbGljaygpO30sCglEaWdpdDFfaSgpe2RvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ1bmlmaWVkLWV4dGVuc2lvbnMtYnV0dG9uIikuY2xpY2soKTt9LAoJRGlnaXQyX2koKXtCcm93c2VyT3BlbkFkZG9uc01ncigpO30sCglEaWdpdDNfaSgpe29wZW5QcmVmZXJlbmNlcygpO30sCglEaWdpdDRfaSgpe2R1cGxpY2F0ZVRhYkluKGdCcm93c2VyLnNlbGVjdGVkVGFiLCd0YWInKTt9LAoJRGlnaXQ1X2koKXt2YXIgcz1wcm9tcHQoJ0dvb2dsZV8gc2l0ZTouLiAuLicsJycpO2lmKHMubGVuZ3RoPjApZ0Jyb3dzZXIuYWRkVHJ1c3RlZFRhYignaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9zZWFyY2g/cT1zaXRlOicrZW5jb2RlVVJJQ29tcG9uZW50KGdCcm93c2VyLmN1cnJlbnRVUkkuaG9zdCkrJyAnK2VuY29kZVVSSUNvbXBvbmVudChzKSk7fSwKCURpZ2l0Nl9pKCl7dmFyIHA9U2VydmljZXMuZGlyc3ZjLmdldCgnR3JlRCcsQ2kubnNJRmlsZSk7cC5pbml0V2l0aFBhdGgocC5wYXRoKyJcXC4uXFwuLlxcLi5cXF9QaG90b1xcU2hhcmVYXFxTaGFyZVguZXhlIik7cC5sYXVuY2goKTt9LAovKglEaWdpdDdfaSgpe2dCcm93c2VyLmZpeHVwQW5kTG9hZFVSSVN0cmluZygiamF2YXNjcmlwdDooZnVuY3Rpb24oKXt2YXIgRW5SdVQ9W1sn0YknLCdzaGgnXSxbJ9CpJywnU2hoJ10sWyfQqScsJ1NISCddLFsn0YUnLCdoaCddLFsn0KUnLCdIaCddLFsn0KUnLCdISCddLFsn0LYnLCd6aCddLFsn0JYnLCdaaCddLFsn0JYnLCdaSCddLFsn0YYnLCdjeiddLFsn0KYnLCdDeiddLFsn0KYnLCdDWiddLFsn0Y4nLCd5dSddLFsn0K4nLCdZdSddLFsn0K4nLCdZVSddLFsn0ZEnLCd5byddLFsn0IEnLCdZbyddLFsn0IEnLCdZTyddLFsn0Y8nLCd5YSddLFsn0K8nLCdZYSddLFsn0K8nLCdZQSddLFsn0YcnLCdjaCddLFsn0KcnLCdDaCddLFsn0KcnLCdDSCddLFsn0YgnLCdzaCddLFsn0KgnLCdTaCddLFsn0KgnLCdTSCddLFsn0Y0nLCdlYCddLFsn0K0nLCdFYCddLFsn0YsnLCd5J10sWyfQqycsJ1knXSxbJ9GKJywnYGAnXSxbJ9GMJywnYCddLFsn0YAnLCdyJ10sWyfRgicsJ3QnXSxbJ9GDJywndSddLFsn0LgnLCdpJ10sWyfQvicsJ28nXSxbJ9C/JywncCddLFsn0LAnLCdhJ10sWyfRgScsJ3MnXSxbJ9C0JywnZCddLFsn0YQnLCdmJ10sWyfQsycsJ2cnXSxbJ9C5JywnaiddLFsn0LonLCdrJ10sWyfQuycsJ2wnXSxbJ9C3JywneiddLFsn0YUnLCd4J10sWyfRhicsJ2MnXSxbJ9CyJywndiddLFsn0LEnLCdiJ10sWyfQvScsJ24nXSxbJ9C8JywnbSddLFsn0KAnLCdSJ10sWyfQoicsJ1QnXSxbJ9CjJywnVSddLFsn0JgnLCdJJ10sWyfQnicsJ08nXSxbJ9CfJywnUCddLFsn0JAnLCdBJ10sWyfQoScsJ1MnXSxbJ9CUJywnRCddLFsn0KQnLCdGJ10sWyfQkycsJ0cnXSxbJ9CZJywnSiddLFsn0JonLCdLJ10sWyfQmycsJ0wnXSxbJ9CXJywnWiddLFsn0KUnLCdYJ10sWyfQpicsJ0MnXSxbJ9CSJywnViddLFsn0JEnLCdCJ10sWyfQnScsJ04nXSxbJ9CcJywnTSddLFsn0LUnLCdlJ10sWyfQlScsJ0UnXV0sQT1kb2N1bWVudC5hY3RpdmVFbGVtZW50O0Eub25rZXl1cD1mdW5jdGlvbiBmdHIoKXtmb3IodmFyIHM9QS52YWx1ZSxpPTA7aTxFblJ1VC5sZW5ndGg7aSsrKXtzPXMucmVwbGFjZShSZWdFeHAoRW5SdVRbaV1bMV0sJ2cnKSxFblJ1VFtpXVswXSl9O0EudmFsdWU9c319KSgpIix7dHJpZ2dlcmluZ1ByaW5jaXBhbDpnQnJvd3Nlci5jb250ZW50UHJpbmNpcGFsfSk7CgkJCSB9LC8vQXV0b1RyYW5zbGl0LSBodHRwczovL2ZvcnVtLnJ1LWJvYXJkLmNvbS90b3BpYy5jZ2k/Zm9ydW09NSZ0b3BpYz00Njc3OSZzdGFydD0zMjAjMTUgKi8KLyoJRGlnaXQ4X2koKXt2YXIgcD1TZXJ2aWNlcy5kaXJzdmMuZ2V0KCdIb21lJyxDaS5uc0lGaWxlKTtwLmluaXRXaXRoUGF0aChwLnBhdGgrIlxcLi5cXC4uXFwuLlxcX1Bob3RvXFxTaGFyZVhcXFNoYXJlWC5leGUiKTsKCQkJIGxldCBhcmd1bWVudHM9WyItbm8tcmVtb3RlIiwiLVAiLCJYWFgiLCAiLWZvcmVncm91bmQiXTsgLy/QktGL0LHQvtGAINC/0YDQvtGE0LjQu9GPLiDQktC80LXRgdGC0L4gVGVzdC1Vc2VyINCy0LXQtNC40YLQtSDQuNC80Y8g0L/RgNC+0YTQuNC70Y8g0YLQsNC6LCDQutCw0Log0L7QvdC+INC+0YLQvtCx0YDQsNC20LDQtdGC0YHRjyDQsiBhYm91dDpwcm9maWxlcwoJCQkgbGV0IHByb2Nlc3M9Q2NbIkBtb3ppbGxhLm9yZy9wcm9jZXNzL3V0aWw7MSJdLmNyZWF0ZUluc3RhbmNlKENpLm5zSVByb2Nlc3MpOwoJCQkgcHJvY2Vzcy5pbml0KHApO3Byb2Nlc3MucnVuKGZhbHNlLCBhcmd1bWVudHMsIGFyZ3VtZW50cy5sZW5ndGgpOyAvL9Cf0YDQvtGE0LjQu9GMINC/0L7QtNGC0LLQtdGA0LbQtNC10L0KCQkJIH0sLy8gaHR0cHM6Ly9mb3J1bS5ydS1ib2FyZC5jb20vdG9waWMuY2dpP2ZvcnVtPTUmdG9waWM9NTEyMDIjNCAqLwogICAJCUYxKCl7dmFyIHA9U2VydmljZXMuZGlyc3ZjLmdldCgnU3lzRCcsQ2kubnNJRmlsZSk7cC5pbml0V2l0aFBhdGgocC5wYXRoKyJcXHNuZHZvbC5leGUiKTtwLmxhdW5jaCgpO30sCgkJRjIoKXtnQnJvd3Nlci5maXh1cEFuZExvYWRVUklTdHJpbmcoImphdmFzY3JpcHQ6e2Q9ZG9jdW1lbnQ7Yj1kLmJvZHk7bz1kLmNyZWF0ZUVsZW1lbnQoJ3NjcmknKydwdCcpO28uc2V0QXR0cmlidXRlKCdzcmMnLCdodHRwczovL3RyYW5zbGF0ZS5nb29nbGUuY29tL3RyYW5zbGF0ZV9hL2VsZW1lbnQuanM/Y2I9Z29vZ2xlVHJhbnNsYXRlRWxlbWVudEluaXQnKTtvLnNldEF0dHJpYnV0ZSgndHlwZScsJ3RleHQvamF2YXNjcmlwdCcpO2IuYXBwZW5kQ2hpbGQobyk7dj1iLmluc2VydEJlZm9yZShkLmNyZWF0ZUVsZW1lbnQoJ2RpdicpLGIuZmlyc3RDaGlsZCk7di5pZD0nZ29vZ2xlX3RyYW5zbGF0ZV9lbGVtZW50Jzt2LnN0eWxlLmRpc3BsYXk9J25vbmUnO3A9ZC5jcmVhdGVFbGVtZW50KCdzY3JpJysncHQnKTtwLnRleHQ9J2Z1bmN0aW9uIGdvb2dsZVRyYW5zbGF0ZUVsZW1lbnRJbml0KCl7bmV3IGdvb2dsZS50cmFuc2xhdGUuVHJhbnNsYXRlRWxlbWVudCh7cGFnZUxhbmd1YWdlOiUyMiUyMn0sJTIyZ29vZ2xlX3RyYW5zbGF0ZV9lbGVtZW50JTIyKTt9JztwLnNldEF0dHJpYnV0ZSgndHlwZScsJ3RleHQvamF2YXNjcmlwdCcpO2IuYXBwZW5kQ2hpbGQocCk7fXZvaWQgMCIse3RyaWdnZXJpbmdQcmluY2lwYWw6Z0Jyb3dzZXIuY29udGVudFByaW5jaXBhbH0pOwoJCQkgfSwvL0VuYWJsZSB0cmFuc2xhdGlvbihodHRwczovL2ZvcnVtLm1vemlsbGEtcnVzc2lhLm9yZy92aWV3dG9waWMucGhwP3BpZD04MDU0MjIjcDgwNTQyMiB8fDgwNTQyNyNwODA1NDI3KQoJCUYzKCl7Z0Jyb3dzZXIuZml4dXBBbmRMb2FkVVJJU3RyaW5nKCJqYXZhc2NyaXB0OihmdW5jdGlvbigpe3ZhciBuaWdodD1mdW5jdGlvbih3KXsoZnVuY3Rpb24oZCl7dmFyIGNzcz0naHRtbHtvcGFjaXR5OjAuNiFpbXBvcnRhbnQ7YmFja2dyb3VuZDpibGFjayFpbXBvcnRhbnQ7fWJvZHl7YmFja2dyb3VuZDp3aGl0ZSFpbXBvcnRhbnQ7fSc7dmFyIHM9ZC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnc3R5bGUnKTtmb3IodmFyIGk9MCxzaTtzaT1zW2ldO2krKyl7aWYoc2kuaW5uZXJIVE1MPT1jc3Mpe3NpLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoc2kpO3JldHVybn19O3ZhciBoZWFkcz1kLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdoZWFkJyk7aWYoaGVhZHMubGVuZ3RoKXt2YXIgbm9kZT1kLmNyZWF0ZUVsZW1lbnQoJ3N0eWxlJyk7bm9kZS50eXBlPSd0ZXh0L2Nzcyc7bm9kZS5hcHBlbmRDaGlsZChkLmNyZWF0ZVRleHROb2RlKGNzcykpO2hlYWRzWzBdLmFwcGVuZENoaWxkKG5vZGUpfX0pKHcuZG9jdW1lbnQpO2Zvcih2YXIgaT0wLGY7Zj13LmZyYW1lc1tpXTtpKyspe3RyeXthcmd1bWVudHMuY2FsbGVlKGYpfWNhdGNoKGUpe319fTtuaWdodCh3aW5kb3cpfSkoKTsiLHt0cmlnZ2VyaW5nUHJpbmNpcGFsOmdCcm93c2VyLmNvbnRlbnRQcmluY2lwYWx9KTsKCQkJIH0sLy9OaWdodCBtb2RlKEZvY3VzIG1vZGUpCgkJRjQoKXt2YXIgdmVydD1gamF2YXNjcmlwdDp7Y29uc3Qgbz1bImNvbnRleHRtZW51Iiwic2VsZWN0c3RhcnQiLCJzZWxlY3QiLCJtb3VzZWRvd24iLCJtb3VzZXVwIiwiY3V0IiwiY29weSJdLHQ9WyItd2Via2l0IiwiLW1veiIsIi1tcyIsIi1raHRtbCIsIiJdLGU9d2luZG93LmpRdWVyeTtbZG9jdW1lbnQsZG9jdW1lbnQuYm9keSxkb2N1bWVudC5kb2N1bWVudEVsZW1lbnRdLmZvckVhY2gobj0+e2Zvcihjb25zdCB0IG9mIG8pblsib24iK3RdPW51bGwsZSYmZShuKS5vZmYodCk7aWYobi5zdHlsZSlmb3IoY29uc3QgbyBvZiB0KXtjb25zdCB0PVtvLCJ1c2VyLXNlbGVjdCJdLmpvaW4oIi0iKTtuLnN0eWxlW3RdPSJpbml0aWFsIn19KQoJCQkgfTt2b2lkKDApO2A7Z0Jyb3dzZXIubG9hZFVSSShTZXJ2aWNlcy5pby5uZXdVUkkodmVydCkse3RyaWdnZXJpbmdQcmluY2lwYWw6U2VydmljZXMuc2NyaXB0U2VjdXJpdHlNYW5hZ2VyLmdldFN5c3RlbVByaW5jaXBhbCgpfSk7CgkJCSB9LC8vUmUtZW5hYmxlIHNlbGVjdGluZyAmIGNvcHlpbmcgdGV4dCBbbWFwbGUzMTQyXSAoQm9va21hcmtsZXQpCglLZXlHXzQoKXt2YXIgYmFyPWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ1Y2YtYWRkaXRpb25hbC12ZXJ0aWNhbC1iYXIiKTtzZXRUb29sYmFyVmlzaWJpbGl0eShiYXIsYmFyLmNvbGxhcHNlZCk7fSwKCUtleVdfMSgpe2dCcm93c2VyLnJlbW92ZUFsbFRhYnNCdXQoZ0Jyb3dzZXIuc2VsZWN0ZWRUYWIpO30sCglLZXlWX2koKXtnQ2xpcGJvYXJkLndyaXRlKGdVUkxCYXIudmFsdWUpO2dsb2IuZmxhc2goMCwwLCdyZ2JhKDI0MCwxNzYsMCwwLjUpJywzMDApO30sLy8zMDAsIkNvcHlVUkw6ICIrZ1VSTEJhci52YWx1ZS5zbGljZSgwLDgwKSkKCUtleVZfMSgpe2xldCB1cmw9cmVhZEZyb21DbGlwYm9hcmQoKTt0cnl7c3dpdGNoVG9UYWJIYXZpbmdVUkkodXJsLHRydWUpO31jYXRjaChleCl7CgkJCSB2YXIgcmVnPS9bYS16QS1aMC05XVstYS16QS1aMC05XXswLDYyfShcLlthLXpBLVowLTldWy1hLXpBLVowLTldezAsNjJ9KStcLj8vOwoJCQkgaWYoIXJlZy50ZXN0KHVybCkpe3VybD0naHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9zZWFyY2g/cT0nK2VuY29kZVVSSUNvbXBvbmVudCh1cmwpOwoJCQkgfWVsc2V7aWYodXJsLnN1YnN0cmluZyg0LDApLnRvTG93ZXJDYXNlKCk9PSJodHRwIil7dXJsPWVuY29kZVVSSUNvbXBvbmVudCh1cmwpOwoJCQkgfWVsc2V7dXJsPSdodHRwOi8vJytlbmNvZGVVUklDb21wb25lbnQodXJsKTt9fXN3aXRjaFRvVGFiSGF2aW5nVVJJKHVybCx0cnVlKTt9fSwvL09wZW4gY2xpcGJvYXJkIGFkZHJlc3MKCUtleVFfNSgpe01vdXNlW0JbMTRdXVsxMjhdKCk7fSwKCUtleVVfNSgpe3ZhciBwPVNlcnZpY2VzLmRpcnN2Yy5nZXQoJ1VDaHJtJyxDaS5uc0lGaWxlKTtwLmluaXRXaXRoUGF0aChwLnBhdGgrIlxcdXNlcl9jaHJvbWVfZmlsZXNcXF9cXHUuZXhlIik7cC5sYXVuY2goKTt9LAoJS2V5QV81KCl7dmFyIHA9U2VydmljZXMuZGlyc3ZjLmdldCgnVUNocm0nLENpLm5zSUZpbGUpO3AuaW5pdFdpdGhQYXRoKHAucGF0aCsiXFx1c2VyX2Nocm9tZV9maWxlc1xcX1xcLkV2XFxFdmVyeXRoaW5nLmV4ZSIpO3AubGF1bmNoKCk7fSwKCUtleVFfNCgpe3ZhciBwPVNlcnZpY2VzLmRpcnN2Yy5nZXQoJ1VDaHJtJyxDaS5uc0lGaWxlKTtwLmluaXRXaXRoUGF0aChwLnBhdGgrIlxcdXNlcl9jaHJvbWVfZmlsZXNcXF9cXC5RVFxcUVRyYW5zbGF0ZS5leGUiKTtwLmxhdW5jaCgpO30sCgkvLz09PT09PT09PT09PQp9LApNb3VzZT17IC8vTWV0YSo2NCBDdHJsKjMyINCo0LjRhNGCKjE2IEFsdCo4IChXaCA/IDIgOiBCdXQqMTI4KSBsb25nKjEKCSJ1cmxiYXItaW5wdXQiOnsgLy9DYXBzTG9jayBPbjogc2tpcCBhY3Rpb24gbW91c2V8a2V5Ym9hcmQKCQkyKHRyZyxmb3J3YXJkKXt0cmcudmFsdWU9IiJ9fSwgLy/QvtGH0LjRgdGC0LjRgtGMCgkidGFiYnJvd3Nlci10YWJzIjp7IC8vPD4g0LLQutC70LDQtNC60Lgg0LrQvtC70ZHRgdC40LrQvtC8CgkJMih0cmcsZm9yd2FyZCl7Z0Jyb3dzZXIudGFiQ29udGFpbmVyLmFkdmFuY2VTZWxlY3RlZFRhYihmb3J3YXJkID8gLTEgOiAxLHRydWUpO30sCgkJOCgpe30sMTYoKXt9LDY0KCl7fSwgLy/QstGL0LHQvtGACgkJMTI4KGJ0bil7Z0Jyb3dzZXIucmVtb3ZlVGFiKFRhYkFjdChidG4pKX0sIC8v0JwgICAgICAgLSDQstC60LvQsNC00LrQsCDQv9C+0LQg0LzRi9GI0YzRjgoJCTEzNihidG4pe1RhYnNEZWwoMSxUYWJBY3QoYnRuKSl9LCAgICAgICAgICAvL9CcK0FsdCAgIC0g0LfQsNC60YDRi9GC0Ywg0LLQutC70LDQtNC60Lgg0YHQv9GA0LDQstCwCgkJMTQ0KGJ0bil7VGFic0RlbCgwLFRhYkFjdChidG4pKX19LCAgICAgICAgIC8v0JwrU2hpZnQgLSDigKYg0YHQu9C10LLQsAoJInN0b3AtYnV0dG9uIjp7CgkJMTI4KCl7Zm9yKHZhciBpPTA7aTxnQnJvd3Nlci50YWJzLmxlbmd0aDtpKyspIGdCcm93c2VyLmdldEJyb3dzZXJBdEluZGV4KGkpLnN0b3AoKX0sIC8vTQoJCTI1Nygpe3N3aXRjaFByb3h5KCl9fSwgICAgICAgICAgICAvL1ItbG9uZwoJInN0YXItYnV0dG9uLWJveCI6ewoJCTEoKXt0cmFuc2xhdGUoKX0sICAgICAgICAgICAgICAgICAvL0xvbmcKCQk4KCl7d2luZG93LlBsYWNlc0NvbW1hbmRIb29rLnNob3dQbGFjZXNPcmdhbml6ZXIoIkJvb2ttYXJrc1Rvb2xiYXIiKX0sIC8vTCtBbHQgLSDQsdC40LHQu9C40L7RgtC10LrQsAoJCTEyOCgpe3N3aXRjaFRhYihGYXZJdGVtKCkpfSwgICAgICAvL00KCQkxMjkoKXtzd2l0Y2hUYWIoRmF2SXRlbShmYWxzZSkpfSwgLy9NLWxvbmcKCQkyNTYoKXt0b0ZhdigpfX0sICAgICAgICAgICAgICAgICAgLy9SCgkiYXBwTWVudS1wcmludC1idXR0b24yIjp7IC8v0JzQtdC90Y46INCf0LXRh9Cw0YLRjOKApgoJCTEoKXtIZWxwKCl9LAoJCTEyOChidG4pe0V4cGVydCgpfSwKCQkyNTYoKXtNb3VzZVtCWzldXVsyNTZdKCl9fSwKCSJwYWdlQWN0aW9uLXVybGJhci1fMjQ5NWQyNTgtNDFlNy00Y2Q1LWJjN2QtYWMxNTk4MWYwNjRlXyI6eyAvL1JlYWRlclZpZXcKCQkyKHRyZyxmb3J3YXJkKXticmlnaHQodHJnLGZvcndhcmQsNSl9LCAvL9GP0YDQutC+0YHRgtGMINC/0L4gd2hlZWwgwrEKCQkxMjgoYnRuKXtidG4ub3duZXJEb2N1bWVudC5nZXRFbGVtZW50QnlJZCgia2V5X3RvZ2dsZVJlYWRlck1vZGUiKS5kb0NvbW1hbmQoKX0sIC8v0YjRgtCw0YLQvdGL0Lkg0KDQtdC20LjQvCDRh9GC0LXQvdC40Y8KCQkyNTYoYnRuKXtNb3VzZVtCWzhdXVsyNTZdKGJ0bil9fSwKCSJ1bmlmaWVkLWV4dGVuc2lvbnMtYnV0dG9uIjp7bW91c2Vkb3duVGFyZ2V0OnRydWUsIAoJCTEoKXtFeHBlcnQoKX0sCgkJMTI4KCl7TW91c2VbQlsxNF1dWzEyOF0oKX0sCgkJMjU2KCl7b3BlbkRpYWwoKX19LAoJW0JbMF1dOnttb3VzZWRvd25UYXJnZXQ6dHJ1ZSwgLy/QvdC1INC/0LXRgNC10LTQsNCy0LDRgtGMINC90LDQttCw0YLQuNGPINC00LDQu9GM0YjQtQoJCTEoKXtEb3dubG9hZHMuZ2V0U3lzdGVtRG93bmxvYWRzRGlyZWN0b3J5KCkudGhlbihwYXRoID0+IEZpbGVVdGlscy5GaWxlKHBhdGgpLmxhdW5jaCgpLEN1LnJlcG9ydEVycm9yKX0sIC8vTG9uZwoJCTgoKXt2YXIgcD0iYnJvd3Nlci5kb3dubG9hZC5pbXByb3ZlbWVudHNfdG9fZG93bmxvYWRfcGFuZWwiLG49Z2xvYi5wcmVmKHApOwoJCQlnbG9iLnByZWYocCwgIW4pOwoJCQlnbG9iLnRvU3RhdHVzKGDQn9C+0LTRgtCy0LXRgNC20LTQtdC90LjQtSDQt9Cw0LPRgNGD0LfQutC4ICR7biA/ICLiiJog0YDQsNC30YDQtdGIIiA6ICLinJgg0LfQsNC/0YDQtdGJIn3QtdC90L5gLDNlMyk7fSwgLy9MK0FsdAoJCTE2KCl7dmFyIG49Z2xvYi5wcmVmKEZmLmkpID09IDI7Z2xvYi5wcmVmKEZmLmksIG4gPyAxIDogMik7CgkJCWdsb2IubW9kZV9za2luKCk7IEJyb3dzZXJSZWxvYWQoKTsKCQkJZ2xvYi50b1N0YXR1cyhg0JfQsNCz0YDRg9C30LrQsCDQuNC30L7QsdGA0LDQttC10L3QuNC5ICR7biA/ICLiiJog0YDQsNC30YDQtdGIIiA6ICLinJgg0LfQsNC/0YDQtdGJIn3QtdC90L5gLDNlMyk7fSwgICAvL0wrU2hpZnQKCQkxMjgoKXtGZi5FeHAoKSAvL9GA0LXQttC40Lwg0J/RgNC+0YHRgtC+0Lkv0K3QutGB0L/QtdGA0YI6INGA0LDQt9C90YvQtSDQtNC10LnRgdGC0LLQuNGPCgkJCT8gc2F2ZVNlbFRvVHh0KCkgOiAvL9GB0L7RhdGA0LDQvdC40YLRjHzQstGL0LTQtdC70LXQvS4g0LrQsNC6IC50eHQKCQkJRG93bmxvYWRzLmdldFN5c3RlbURvd25sb2Fkc0RpcmVjdG9yeSgpLnRoZW4ocGF0aCA9PiBGaWxlVXRpbHMuRmlsZShwYXRoKS5sYXVuY2goKSxDdS5yZXBvcnRFcnJvcil9LAoJCTI1Nigpe3NhdmUoKX19LCAvL3dlYgoJW0JbMV1dOnttb3VzZWRvd25UYXJnZXQ6dHJ1ZSwKCQkxKGJ0bil7Z29RdWl0QXBwbGljYXRpb24oYnRuKX0sIC8vTG9uZwoJCTIodHJnLGZvcndhcmQpe2ZvcndhcmQgPyB0cmcub3duZXJHbG9iYWwudW5kb0Nsb3NlVGFiKCkgOiB0cmcub3duZXJHbG9iYWwuQnJvd3NlckNsb3NlVGFiT3JXaW5kb3coKX0sIC8v0LrRgNGD0YLQuNGC0YwgK9CX0LDQutGA0YvRgtGMINCy0LrQu9Cw0LTQutGDIC3QktC+0YHRgdGC0LDQvdC+0LLQuNGC0YwKCQk4KCl7d2luZG93U3RhdGUgIT0gU1RBVEVfTUFYSU1JWkVEID8gbWF4aW1pemUoKSA6IHJlc3RvcmUoKX0sICAgLy9MK0FsdAoJCTE2KCl7SGVscCgpfSwgICAgICAgICAgICAgICAgICAgLy9MK1NoaWZ0CgkJMTI4KCl7d2luZG93U3RhdGUgIT0gU1RBVEVfTUFYSU1JWkVEID8gbWF4aW1pemUoKSA6IHJlc3RvcmUoKX0sIC8vTQoJCTEyOSgpe0Jyb3dzZXJGdWxsU2NyZWVuKCl9LCAgICAgLy9NLWxvbmcKCQkxMzYoKXt0aGlzWzEyOV0oKX0sICAgICAgICAgICAgIC8vTStBbHQKCQkyNTYoKXttaW5pbWl6ZSgpfSwgICAgICAgICAgICAgIC8vUgoJCTI2NCgpe3N3aXRjaFRhYignYWJvdXQ6c3VwcG9ydCcpfSwgLy9SK0FsdAoJCTI3MihidG4pe2J0bi5vd25lckdsb2JhbC5QbGFjZXNDb21tYW5kSG9vay5zaG93UGxhY2VzT3JnYW5pemVyKCJIaXN0b3J5Iil9fSwgLy9SK1NoaWZ0CglbQlsyXV06ezIodHJnLGZvcndhcmQpe3pvb20oZm9yd2FyZCl9fSwgLy93aGVlbAoJW0JbM11dOnsKCQk4KCl7Z0Jyb3dzZXIucmVtb3ZlQWxsVGFic0J1dChnQnJvd3Nlci5zZWxlY3RlZFRhYil9LAoJCTI1NihidG4pe2J0bi5vd25lckdsb2JhbC51bmRvQ2xvc2VUYWIoKX19LAoJW0JbNF1dOnsgLy/Qt9Cw0LzQvtC6CgkJMih0cmcsZm9yd2FyZCl7YnJpZ2h0KHRyZyxmb3J3YXJkLDUpfSwgLy/Rj9GA0LrQvtGB0YLRjAoJCTgoKXtvcGVuUHJveHlXaW4oKX0sIC8vTCtBbHQKCQkxMCh0cmcsZm9yd2FyZCl7YnJpZ2h0KHRyZyxmb3J3YXJkKX0sCgkJMTYoYnRuKXtCcm93c2VyUGFnZUluZm8oYnRuLCJtZWRpYVRhYiIpfSwgLy9MK1NoaWZ0IC0gZmVlZFRhYiBwZXJtVGFiIHNlY3VyaXR5VGFiCgkJMTI4KCl7dGhpc1s4XSgpfSwKCQkyNTYoKXtnQ2xpcGJvYXJkLndyaXRlKGdVUkxCYXIudmFsdWUpO2dsb2IuZmxhc2goMCwwLCdyZ2JhKDI0MCwxNzYsMCwwLjUpJywzMDAsItCyINCx0YPRhNC10YDQtTogIitnVVJMQmFyLnZhbHVlLnNsaWNlKDAsODApKTt9fSwKCVtCWzVdXTp7IC8vQ3VzdG9taXphYmxlVUkg0LIg0YHQutGA0LjQv9GC0LUKCQkwKGJ0bil7YnRuLm93bmVyR2xvYmFsLlNpZGViYXJVSS50b2dnbGUoInZpZXdCb29rbWFya3NTaWRlYmFyIil9LCAvL0wKCQkyKHRyZyxmb3J3YXJkKXtmb3J3YXJkID8gZ2xvYi5kaXJzdmNnZXQoIlVDaHJtIiwidXNlcl9jaHJvbWVfZmlsZXMiKSA6IGdsb2IuZGlyc3ZjZ2V0KCJVQ2hybSIsInVzZXJfY2hyb21lX2ZpbGVzIiwiY3VzdG9tX3NjcmlwdHMiKX0sCgkJOCgpe2dsb2IuZGlyc3ZjZ2V0KCJIb21lIil9LCAgICAgICAgICAgICAgICAgICAgICAgICAgLy9MK0FsdAoJCTE2KCl7Z2xvYi5kaXJzdmNnZXQoIlVDaHJtIiwidXNlcl9jaHJvbWVfZmlsZXMiLCJjdXN0b21fc2NyaXB0cyIsIkNCIiwiJUgudHh0Iil9LCAvL0wrU2hpZnQKCQkxMjgoYnRuKXtidG4ub3duZXJHbG9iYWwuUGxhY2VzQ29tbWFuZEhvb2suc2hvd1BsYWNlc09yZ2FuaXplcigiRG93bmxvYWRzIil9LCAvL00gLSDQkdC40LHQu9C40L7RgtC10LrQsCDQl9Cw0LPRgNGD0LfQutC4CgkJMTM2KCl7Z2xvYi5kaXJzdmNnZXQoIlVDaHJtIiwidXNlcl9jaHJvbWVfZmlsZXMiKX0sICAgLy9NK0FsdAoJCTI1NihidG4pe2J0bi5vd25lckdsb2JhbC5TaWRlYmFyVUkudG9nZ2xlKEIuYXQoLTEpKX0sIC8vUgoJCTI2NCgpe2dsb2IuZGlyc3ZjZ2V0KCJHcmVEIil9LCAgICAgICAgICAgICAgICAgICAgICAgIC8vUitBbHQKCQkyNzIoKXtnbG9iLmRpcnN2Y2dldCgiVUNocm0iLCJ1c2VyX2Nocm9tZV9maWxlcyIsImN1c3RvbV9zY3JpcHRzIiwiZG9icm92IiwidWNmX2hvb2tDbGlja3MuanMiKX19LCAvL0wrU2hpZnQKCVtCWzZdXTp7bW91c2Vkb3duVGFyZ2V0OnRydWUsCgkJMChidG4pe2lmIChidG4uaWQgPT0gQls2XSkgewoJCQkJICAgdmFyIGJhciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJ1Y2YtYWRkaXRpb25hbC12ZXJ0aWNhbC1iYXIiKTsKCQkJCSAgIGlmIChiYXIpIHdpbmRvdy5zZXRUb29sYmFyVmlzaWJpbGl0eShiYXIsZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInNpZGViYXItYm94IikuaGlkZGVuKTsKCQkJCSAgIHdpbmRvdy5TaWRlYmFyVUkudG9nZ2xlKEIuYXQoLTEpKTsKCQkJICAgfSBlbHNlIGdsb2IubW9kZV9za2luKCk7fSwgLy9MIC0g0LzQtdC90Y4g0LrQvdC+0L/QutC4CgkJMShidG4peyAvL0xvbmcKCQkJaWYgKGJ0bi5pZCA9PSBCWzZdKXsgLy/Qu9C40L3Qt9CwCgkJCQlnbG9iLmZsYXNoKDAsMCwncmdiYSgxMDAsMCwyMjUsMC4xKScsNTAwLCBUWzRdKTsKCQkJCXZhciB1cmwgPSBgcmVzb3VyY2U6Ly9kZXZ0b29scy9zaGFyZWQvJHtwYXJzZUludChGZi52ZXIpID4gOTUgPyAibG9hZGVyLyIgOiAiIn1Mb2FkZXIuYDsKCQkJCXRyeSB7dmFyIGV4cCA9IENocm9tZVV0aWxzLmltcG9ydEVTTW9kdWxlKHVybCArICJzeXMubWpzIik7fSBjYXRjaCB7ZXhwID0gQ2hyb21lVXRpbHMuaW1wb3J0KHVybCArICJqc20iKTt9CgkJCQl2YXIgb2JqID0gZXhwLnJlcXVpcmUoImRldnRvb2xzL2NsaWVudC9tZW51cyIpLm1lbnVpdGVtcy5maW5kKG1lbnVpdGVtID0+IG1lbnVpdGVtLmlkID09ICJtZW51X2V5ZWRyb3BwZXIiKTsKCQkJCSh0ZXN0ID0gb2JqLm9uY29tbWFuZC5iaW5kKG51bGwsIHt0YXJnZXQ6YnRufSkpKCk7CgkJCX0gZWxzZSAvL9C60LvQuNC6INCyINC80LXQvdGOINCx0YvRgdGC0YDRi9GFINC90LDRgdGC0YDQvtC10LoKCQkJCWdsb2IuYWJvdXRfY29uZmlnKGJ0bi5wcmVmLnByZWYpLCAvL2dvINC/0LDRgNCw0LzQtdGC0YAgYWJvdXQ6Y29uZmlnCgkJCQlidG4ucGFyZW50Tm9kZS5wYXJlbnROb2RlLnNlY29uZGFyeVBvcHVwLmhpZGVQb3B1cCgpO30sCgkJMih0cmcsZm9yd2FyZCl7em9vbShmb3J3YXJkKX0sIC8vd2hlZWwKCQk4KCl7c3dpdGNoVGFiKCdjaHJvbWU6Ly9icm93c2VyL2NvbnRlbnQvcGxhY2VzL3BsYWNlcy54aHRtbCcpfSwgLy9MK0FsdAoJCTE2KGJ0bil7aWYgKGJ0bi5pZCA9PSBCWzZdKSB6b29tKDAsMSl9LCAgICAgICAgICAgICAgICAgICAgICAgICAvL0wrU2hpZnQKCQkxMjgoYnRuKXsgLy9NCgkJCWlmIChidG4uaWQgPT0gQls2XSkKCQkJCXN3aXRjaFRhYigiYWJvdXQ6bmV3dGFiIiwgdHJ1ZSkKCQkJZWxzZSAvL9C80LXQvdGOINCx0YvRgdGC0YDRi9GFINC90LDRgdGC0YDQvtC10LoKCQkJCXN3aXRjaFRhYigpLAoJCQkJYnRuLnBhcmVudE5vZGUucGFyZW50Tm9kZS5zZWNvbmRhcnlQb3B1cC5oaWRlUG9wdXAoKTt9LAoJCTEyOShidG4pe3VzZXJqcyhidG4sIiIpfSwgICAgICAgICAgICAgICAvL00tbG9uZyAtINC60L7QvdGB0L7Qu9GMCgkJMTM2KCl7dmFyIG49ImJyb3dzZXIuZGlzcGxheS51c2VfZG9jdW1lbnRfZm9udHMiLGY9Z2xvYi5wcmVmKG4pID8gMCA6IDE7CgkJCSAgZ2xvYi5wcmVmKG4sZik7em9vbSgwLDAsMCwoZj4wKSA/ICIgKyBXZWIt0YjRgNC40YTRgtGLIiA6ICIiKTtCcm93c2VyUmVsb2FkKCk7fSwgLy9NK0FsdAoJCTI1Nigpe30sICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL1IgLSBsb2NrCgkJMjY0KCl7c3dpdGNoVGFiKEZhdkl0ZW0oZmFsc2UpKX19LCAgICAgICAvL1IrQWx0CgkgIC8vMjcyKGJ0bil7aWYgKGJ0bi5pZD1CWzZdKSBvcGVuRGlhbCgpfX0sIC8vTCtTaGlmdCAtIFVDRiBQcmVmcwoJW0JbOF1dOnsgLy/inr8KCQkyKHRyZyxmb3J3YXJkKXticmlnaHQodHJnLGZvcndhcmQsNSl9LCAgLy/Rj9GA0LrQvtGB0YLRjAoJCTI1NihidG4pe2J0bi5vd25lckRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJrZXlfcmVzcG9uc2l2ZURlc2lnbk1vZGUiKS5kb0NvbW1hbmQoKTsKCQkJCSBpZihnQnJvd3Nlci5zZWxlY3RlZEJyb3dzZXIuYnJvd3NpbmdDb250ZXh0LmluUkRNUGFuZSlCcm93c2VyUmVsb2FkKCk7fX0sIC8vUiAtIE1vYmlsZSBWaWV3ICjQv9GD0L3QutGCINC80LXQvdGOINGBIEhvdEtleSkKCVtCWzldXTp7CgkJMSgpe0hlbHAoKX0sCgkJMTI4KCl7RXhwZXJ0KCl9LAoJCTI1Nigpe2RvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJtZW51X3ByaW50IikuZG9Db21tYW5kKCl9fSwKCVtCWzEwXV06ewoJCTEoKXt3aXRoIChnQnJvd3Nlcikgc2VsZWN0QWxsVGFicygpLHJlbG9hZE11bHRpU2VsZWN0ZWRUYWJzKCksY2xlYXJNdWx0aVNlbGVjdGVkVGFicygpO30sCgkJMTI4KCl7Zm9yICh2YXIgaT0wO2k8Z0Jyb3dzZXIudGFicy5sZW5ndGg7aSsrKSBnQnJvd3Nlci5nZXRCcm93c2VyQXRJbmRleChpKS5zdG9wKCl9LAoJCTI1Nigpe0Jyb3dzZXJSZWxvYWRTa2lwQ2FjaGUoKX0sCgkJMjU3KCl7c3dpdGNoUHJveHkoKX19LAoJW0JbMTFdXTp7CgkJMSgpe01vdXNlW0JbNl1dWzEzNl0oKX0sIC8vTG9uZyAtZm9udHMKCQkyKHRyZyxmb3J3YXJkKXticmlnaHQodHJnLGZvcndhcmQpfSwKCQkxNigpe3N3aXRjaFRhYigpfSwKCQkxMjgoKXtzd2l0Y2hUYWIoJ2Fib3V0OnBlcmZvcm1hbmNlJyl9LAoJCTI1NihidG4pe3ZhciBsb2dpbnM9YnRuLm93bmVyRG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInVjZi1sb2dpbnMtc2l0ZWRhdGEiKTtsb2dpbnMgPyBsb2dpbnMuY2xpY2soKSA6IHN3aXRjaFRhYignYWJvdXQ6bG9naW5zJyk7fX0sCglbQlsxM11dOnsKCQkxKCl7SGVscCgpfSwKCQkxMjgoYnRuKXtidG4ub3duZXJHbG9iYWwudW5kb0Nsb3NlVGFiKCl9LAoJCTI1Nigpe21pbmltaXplKCl9fSwKCVtCWzE0XV06eyAvL0F0dHJWaWV3CgkJMSgpe0V4cGVydCgpfSwKCQk4KCl7dmFyIGNocj0iZGV2dG9vbHMuY2hyb21lLmVuYWJsZWQiLHJlbT0iZGV2dG9vbHMuZGVidWdnZXIucmVtb3RlLWVuYWJsZWQiOwoJCQlpZiAoIWdsb2IucHJlZihjaHIpIHx8ICFnbG9iLnByZWYocmVtKSkge2dsb2IucHJlZihjaHIsdHJ1ZSk7IGdsb2IucHJlZihyZW0sdHJ1ZSk7fQoJCQl2YXIge0Jyb3dzZXJUb29sYm94TGF1bmNoZXJ9PUNocm9tZVV0aWxzLmltcG9ydCgicmVzb3VyY2U6Ly9kZXZ0b29scy9jbGllbnQvZnJhbWV3b3JrL2Jyb3dzZXItdG9vbGJveC9MYXVuY2hlci5qc20iKTsKCQkJQnJvd3NlclRvb2xib3hMYXVuY2hlci5pbml0KCk7fSwgLy/Rg9C0LtC+0YLQu9Cw0LTQutCwCgkJMTYoKXtzd2l0Y2hUYWIoJ2Fib3V0OnByb2ZpbGluZycpfSwKCQkxMjgoKXsgLy9NLCBRK0FsdCtDdHJsIENsZWFuQ2FjaGUgLSDQn9C10YDQtdC30LDQv9GD0YHRgtC40YLRjCwg0YPQtNCw0LvQuNCyINC60Y3RiAoJCQl2YXIgY2FuY2VsUXVpdCA9IENjWyJAbW96aWxsYS5vcmcvc3VwcG9ydHMtUFJCb29sOzEiXS5jcmVhdGVJbnN0YW5jZShDaS5uc0lTdXBwb3J0c1BSQm9vbCk7CgkJCVNlcnZpY2VzLm9icy5ub3RpZnlPYnNlcnZlcnMoY2FuY2VsUXVpdCwicXVpdC1hcHBsaWNhdGlvbi1yZXF1ZXN0ZWQiLCJyZXN0YXJ0Iik7CgkJCWlmIChjYW5jZWxRdWl0LmRhdGEpIHJldHVybiBmYWxzZTsKCQkJU2VydmljZXMuYXBwaW5mby5pbnZhbGlkYXRlQ2FjaGVzT25SZXN0YXJ0KCk7CgkJCXZhciByZXN0YXJ0ID0gU2VydmljZXMuc3RhcnR1cDsKCQkJcmVzdGFydC5xdWl0KHJlc3RhcnQuZUF0dGVtcHRRdWl0IHwgcmVzdGFydC5lUmVzdGFydCk7fSwKCQkyNTYoKXtvcGVuRGlhbCgpfSAvL1VDRnByZWZzCgl9fTsgdmFyIE0gPSBPYmplY3Qua2V5cyhNb3VzZSk7CgooYXN5bmMgKGlkKSA9PiBDdXN0b21pemFibGVVSS5jcmVhdGVXaWRnZXQoe2xhYmVsOmlkLnJlcGxhY2UoJy0nLCcgJyksIGlkOmlkLAoJb25DcmVhdGVkKGJ0bikgewoJCWJ0bi5zZXRBdHRyaWJ1dGUoImltYWdlIiwiZGF0YTppbWFnZS93ZWJwO2Jhc2U2NCxVa2xHUmp3QUFBQlhSVUpRVmxBNFRDOEFBQUF2RDhBREFBb0diU001T3Y2azc3NFhDUEZQLzAvMDMvOEpHUHh6cm9JenVPVzA2SWg2MEdlbm4xUy9nSGUrQmdBPSIpOwoJCWJ0bi5vbm1vdXNlZW50ZXIgPSBidG4ub25tb3VzZWxlYXZlID0gdGhpcy5vbm1vdXNlOwoJCWJ0bi5zZXRBdHRyaWJ1dGUoIm9uY29tbWFuZCIsImhhbmRsZUNvbW1hbmQodGhpcykiKTsgYnRuLmhhbmRsZUNvbW1hbmQgPSB0aGlzLmhhbmRsZUNvbW1hbmQ7Cgl9LAoJb25tb3VzZTogZSA9PiBlLnRhcmdldC5mb2N1c2VkV2luZG93ID0gZS50eXBlLmVuZHNXaXRoKCJyIikgJiYgU2VydmljZXMud20uZ2V0TW9zdFJlY2VudFdpbmRvdyhudWxsKSwKCWdldCBoYW5kbGVDb21tYW5kKCkge2RlbGV0ZSB0aGlzLmhhbmRsZUNvbW1hbmQ7CgkJcmV0dXJuIHRoaXMuaGFuZGxlQ29tbWFuZCA9IGJ0biA9PiB7KGJ0bi5oYW5kbGVDb21tYW5kID0gbmV3IGJ0bi5vd25lckdsb2JhbC5GdW5jdGlvbih0aGlzLmNvZGUpLmJpbmQoYnRuKSkoKTt9Cgl9LAoJZ2V0IGNvZGUoKSB7ZGVsZXRlIHRoaXMuY29kZTsgdmFyIHMgPSBGZi5jICsiY3VzdG9tX3NjcmlwdHMvIisgQlsxNF0gKyIuanMiOwoJCXRyeSB7aWQgPSAndGhpcy5mb2N1c2VkV2luZG93ICYmIHRoaXMuZm9jdXNlZFdpbmRvdy5mb2N1cygpO1xuJysKCQkJQ3UucmVhZFVURjhVUkkoU2VydmljZXMuaW8ubmV3VVJJKHMpKX0gY2F0Y2gge2lkID0gYGdsb2IudG9TdGF0dXMoIiR7VFs4XX0ke3N9Iiw3ZTMpYH0KCQlyZXR1cm4gdGhpcy5jb2RlID0gaWQ7fQp9KSkoQlsxNF0pOwoKdmFyIHtwcmVmc30gPSBTZXJ2aWNlcyxPdmVyID0geyAvL21vZGlmeSBUb29sdGlwcyDQv9C+0LQg0LzRi9GI0YzRjgpnZXQgW0JbMV1dKCkgeyAvLyBkZWxldGUgdGhpc1vigKZdOwoJZ2xvYi5tb2RlX3NraW4oKTsgaWYgKGdsb2IucHJlZigic2lnbm9uLnJlbWVtYmVyU2lnbm9ucyIpKQoJCVNlcnZpY2VzLmNhY2hlMi5hc3luY0dldERpc2tDb25zdW1wdGlvbih7b25OZXR3b3JrQ2FjaGVEaXNrQ29uc3VtcHRpb24oYnl0ZXMpIHsKCQkJZ2xvYi50b1N0YXR1cyhUWzNdICsgZ2xvYi5mb3JtYXRCeXRlcyhieXRlcyksM2UzKSAvLyDQstGL0LLQvtC0INC+0LHRitGR0LzQsCDQutGN0YjQsAoJCX0sIFF1ZXJ5SW50ZXJmYWNlOiBDaHJvbWVVdGlscy5nZW5lcmF0ZVFJKFsibnNJU3VwcG9ydHNXZWFrUmVmZXJlbmNlIiwibnNJQ2FjaGVTdG9yYWdlQ29uc3VtcHRpb25PYnNlcnZlciJdKX0pCgllbHNlIGdsb2IudG9TdGF0dXMoVFs1XSwyZTMpOyAvL9C90LUg0YXRgNCw0L3QuNGC0Ywg0L/QsNGA0L7Qu9C4CglyZXR1cm4gdEV4cChCWzFdKTsKfSwKZ2V0IFtCWzNdXSgpIHsKCXJldHVybiBHZXREeW5hbWljU2hvcnRjdXRUb29sdGlwVGV4dChCWzNdKSArIFRhZ1tCWzNdXTsKfSwKZ2V0IFtCWzBdXSgpIHt2YXIgZHcgPSBnbG9iLmRpcnN2Y2dldCgiIik7CglpZiAoZHcpIGdsb2IubW9kZV9za2luKGAke2dsb2IucHJlZihGZi5pKSA+IDEgPyAiXHV7MjZBMX0g0JPRgNCw0YTQuNC60LAg0L7RgtC60LvRjtGH0LXQvdCwLCIgOiAi8J+SviDQv9Cw0L/QutCwIn0gW9CX0LDQs9GA0YPQt9C60LhdIGArIGdsb2IuY3JvcChkdywgOTYsJycpKTsKCXJldHVybiBHZXREeW5hbWljU2hvcnRjdXRUb29sdGlwVGV4dChCWzBdKSArIlxuIisgdEV4cChCWzBdKTsKfSwKZ2V0ICJ0YWJicm93c2VyLXRhYiIoKSB7dmFyIHRyZyA9IHdpbmRvdy5ldmVudD8udGFyZ2V0OwoJdHJnLnRvb2x0aXBUZXh0ID0gdHJnLmxhYmVsICsgVGFnW0JbMl1dOwp9LApnZXQgW0JbMTBdXSgpIHtnbG9iLm1vZGVfc2tpbignJyk7CglyZXR1cm4gR2V0RHluYW1pY1Nob3J0Y3V0VG9vbHRpcFRleHQoQlsxMF0pICsiXG5cbiIrIFRhZ1tCWzEwXV0gKyJcbiIrIHRFeHAoQlsxMl0pOwp9LApnZXQgW01bMl1dKCkge3JldHVybiBHZXREeW5hbWljU2hvcnRjdXRUb29sdGlwVGV4dChbTVsyXV0pICsiXG4iKyB0RXhwKEJbMTJdKTsKfSwKZ2V0IFtNWzBdXSgpIHtnbG9iLnRvU3RhdHVzKFRbMF0sMjUwMCk7Cn0sCltCWzldXTogVGFnW0JbOV1dLApbTVs0XV06IFRhZ1tCWzldXSwKInRpdGxlYmFyLWJ1dHRvbiB0aXRsZWJhci1jbG9zZSI6IFRhZ1tCWzEzXV0sCmdldCBbTVszXV0oKSB7Cgl2YXIgdHh0ID0gYCR7Z2xvYi5wcmVmKCJkb20uZGlzYWJsZV9vcGVuX2R1cmluZ19sb2FkIikgPyAi0JfQsNC/0YDQtdGCIiA6ICLihq8g0KDQsNC30YDQtdGIIn3QuNGC0Ywg0LLRgdC/0LvRi9Cy0LDRjtGJ0LjQtSDQvtC60L3QsGA7CglpZiAoIWdsb2IucHJlZigicGxhY2VzLmhpc3RvcnkuZW5hYmxlZCIpKSB0eHQgPSBUWzldOwoJaWYgKGdsb2IucHJlZigicHJpdmFjeS5zYW5pdGl6ZS5zYW5pdGl6ZU9uU2h1dGRvd24iKSkgdHh0ID0gVFsxMF07CglnbG9iLnRvU3RhdHVzKHR4dCwzZTMpOwp9LApnZXQgW0JbMl1dKCkgeyAvL2N1c3RvbSBoaW50CglyZXR1cm4gdG9vbHRpcF94KHdpbmRvdy5ldmVudC50YXJnZXQsIuKpiSDQoNC+0LvQuNC6IMKxCdCY0LfQvNC10L3QuNGC0Ywg0LzQsNGB0YjRgtCw0LEiKTsKfSwKZ2V0IFtCWzE0XV0oKSB7cmV0dXJuIFRhZ1tCWzE0XV0gKyBUWzE0XTt9LApnZXQgImlkZW50aXR5LWljb24tYm94IigpIHsKCXJldHVybiB0b29sdGlwX3god2luZG93LmV2ZW50LnRhcmdldCwgdEV4cChCWzRdKSArIGJyX3ZhbCgpKTsKfSwKZ2V0IFtCWzRdXSgpIHtnbG9iLnRvU3RhdHVzKHRoaXMuYnJfZXhwKCksMjUwMCk7IC8v0YDQtdC20LjQvCDQutC90L7Qv9C+0LoKCXJldHVybiB0b29sdGlwX3god2luZG93LmV2ZW50LnRhcmdldCwgdEV4cChCWzRdKSArIGJyX3ZhbCgpKTsKfSwKZ2V0IFtCWzExXV0oKSB7Z2xvYi50b1N0YXR1cyh0aGlzLmJyX2V4cCgpLDI1MDApOwoJdmFyIHRyZyA9IHdpbmRvdy5ldmVudD8udGFyZ2V0OyAvL2N1c3RvbSBoaW50IDIKCXJldHVybiB0cmcuaWQuZW5kc1dpdGgoInIiKSAmJiB0cmcudGV4dENvbnRlbnQgKydcbicrIHRFeHAoQlsxMV0pOwp9LApnZXQgW0JbNl1dKCkgeyAvL0Zhdk1lbnUKCXZhciB0cmcgPSB3aW5kb3cuZXZlbnQ/LnRhcmdldDsKCWlmICh0cmcuaWQgPT0gQls2XSkgewoJCXRyeSB7dHJnLm1zdGF0ZSA9IHRyZy5zZWNvbmRhcnlQb3B1cC5zdGF0ZTt9IGNhdGNoe30gLy/QtNC70Y8gdWNmX1F1aWNrVG9nZ2xlLmpzCgkJem9vbSgwLDAsMCxgLCAke2dsb2IucHJlZigiYnJvd3Nlci50YWJzLmxvYWRJbkJhY2tncm91bmQiKSA/ICLQndC1INCy0YvQsdC40YDQsNGC0YwiIDogItCf0LXRgNC10LrQu9GO0YfQsNGC0YzRgdGPINCyIn0g0L3QvtCy0YvQtSDQstC60LvQsNC00LrQuGApOwoJfSBlbHNlIHsKCQl0cmcubXN0YXRlID0gdHJnLnN0YXRlOwoJCWdsb2IudG9TdGF0dXMoVFs2XSw5ZTMpOwoJfQoJaWYgKHRyZy5tc3RhdGUgIT0gIm9wZW4iKQoJCXJldHVybiB0RXhwKEJbNl0pCgllbHNlIHRyZy50b29sdGlwVGV4dCA9ICIiOwp9LApnZXQgW0JbOF1dKCkgeyAvL2dldCDQvNC+0LbQtdGCINCy0YvQv9C+0LvQvdGP0YLRjCDQutC+0LQKCXJldHVybiBHZXREeW5hbWljU2hvcnRjdXRUb29sdGlwVGV4dChCWzhdKSArIlxuIisgVGFnW0JbOF1dICsgYnJfdmFsKCk7Cn0sCmdldCBbTVs1XV0oKSB7CglyZXR1cm4gVGFnW0JbN11dICsgVGFnW0JbOF1dICsgYnJfdmFsKCk7Cn0sCmdldCAidWNmX1Nlc3Npb25NYW5hZ2VyIigpIHtnbG9iLnRvU3RhdHVzKFRbMTFdKTt9LApnZXQgInVuaWZpZWQtZXh0ZW5zaW9ucy1idXR0b24iKCl7cmV0dXJuICLQoNCw0YHRiNC40YDQtdC90LjRjyIrIFRbMTRdfSwKIl81MzE5MDZkMy1lMjJmLTRhNmMtYTEwMi04MDU3Yjg4YTFhNjNfLWJyb3dzZXItYWN0aW9uIjogVFsxMl0sIC8vU2luZ2xlRmlsZQoiXzUzMTkwNmQzLWUyMmYtNGE2Yy1hMTAyLTgwNTdiODhhMWE2M18tQkFQIjogVFsxMl0sCiJfYjlkYjE2YTQtNmVkYy00N2VjLWExZjQtYjg2MjkyZWQyMTFkXy1icm93c2VyLWFjdGlvbiI6IFRbMTNdLCAvL1ZESAoiX2I5ZGIxNmE0LTZlZGMtNDdlYy1hMWY0LWI4NjI5MmVkMjExZF8tQkFQIjogVFsxNF0sCmJyX2V4cCh0ID0gVFsyXSArIGJyX3ZhbCgpKXsKCXJldHVybiB0ICtgICR7RmYuRXhwKCkgPyAi0K3QutGB0L/QtdGA0YLQvdGL0LkiIDogItCf0YDQvtGB0YLQvtC5In0g0YDQtdC20LjQvCDQutC90L7Qv9C+0LpgfQp9OwoKd2luZG93Lmdsb2IgPSB7IC8vYWxsIFtDaHJvbWVPbmx5XS1zY3JpcHRzCglwcmVmKGtleSxzZXQsIHB0ID0ge2I6IkJvb2wiLG46IkludCIsczoiU3RyaW5nIn0pIHsgLy/QuNC70Lgga2V5ID0gW2tleSxkZWZhdWx0XQoJCWlmICh0eXBlb2Yga2V5ICE9ICJvYmplY3QiKSBrZXkgPSBba2V5XTsKCQl2YXIgdCA9IFNlcnZpY2VzLnByZWZzLmdldFByZWZUeXBlKGtleVswXSk7CgkJdCA9IHB0W3QgPT0gMTI4ID8gImIiIDogdCA9PSA2NCA/ICJuIiA6IHQgPT0gMzIgPyAicyIgOiAiIl07CgkJaWYgKCF0KSB0ID0gcHRbc2V0ICE9IHVuZGVmaW5lZCA/ICh0eXBlb2Ygc2V0KVswXSA6ICh0eXBlb2Yga2V5WzFdKVswXV07CgkJaWYgKCF0KSByZXR1cm47IGlmIChzZXQgIT0gdW5kZWZpbmVkKQoJCQlTZXJ2aWNlcy5wcmVmc1tgc2V0JHt0fVByZWZgXShrZXlbMF0sc2V0KQoJCWVsc2Ugc2V0ID0gU2VydmljZXMucHJlZnNbYGdldCR7dH1QcmVmYF0oLi4ua2V5KTsgcmV0dXJuIHNldDsKCX0sCgl1YShyZWFsID0gZmFsc2UsdWFfbXkgPSAiZ2VuZXJhbC51c2VyYWdlbnQub3ZlcnJpZGUiKSB7IC8v0YLQtdC60YPRidC40Lkg0LjQu9C4INCy0YjQuNGC0YvQuSDQrtC30LXRgNCQ0LPQtdC90YIKCQl0dHQgPSB0aGlzLnByZWYodWFfbXkpOyBTZXJ2aWNlcy5wcmVmcy5jbGVhclVzZXJQcmVmKHVhX215KTsKCQl1YSA9IENjWyJAbW96aWxsYS5vcmcvbmV0d29yay9wcm90b2NvbDsxP25hbWU9aHR0cCJdLmdldFNlcnZpY2UoQ2kubnNJSHR0cFByb3RvY29sSGFuZGxlcikudXNlckFnZW50OyAvLyDQutC+0YHRgtGL0LvRjAoJCXR0dCAmJiB0aGlzLnByZWYodWFfbXksdHR0KTsgaWYgKCF0dHQpIHR0dCA9IHVhOyBpZiAocmVhbCkgdHR0ID0gdWE7IHJldHVybiB0dHQ7Cgl9LAoJZGlyc3ZjZ2V0KCkgeyAvL9C60L7QvdGB0YLQsNC90YLQsCDQv9GD0YLQuCArIHN1YmRpcnMsINC10YHQu9C4INC/0L7RgdC7LiDQvtC/0YbQuNGPID0gIiIg0LLQtdGA0L3Rg9GC0Ywg0L/Rg9GC0YwsINC40L3QsNGH0LUg0L7RgtC60YDRi9GC0YwKCQl2YXIgZiwgZCA9IFsuLi5hcmd1bWVudHNdLCByID0gKGQuYXQoLTEpID09ICIiKTsgKHIpICYmIGQucG9wKCk7CgkJdHJ5IHtmID0gU2VydmljZXMuZGlyc3ZjLmdldChkWzBdIHx8ICJEZmx0RHdubGQiLENpLm5zSUZpbGUpO30gY2F0Y2gge2YgPSBTZXJ2aWNlcy5wcmVmcy5nZXRDb21wbGV4VmFsdWUoImJyb3dzZXIuZG93bmxvYWQuZGlyIixDaS5uc0lGaWxlKX0KCQlkLnNsaWNlKDEsIGQubGVuZ3RoKS5mb3JFYWNoKChjKT0+Zi5hcHBlbmQoYykpOwoJCWlmIChyKSByZXR1cm4gZi5wYXRoOyBmLmV4aXN0cygpICYmIGYubGF1bmNoKCk7Cgl9LAoJY3JvcChzLGN1dCA9IDMzLGNoID0gJ+KAplxuJykgeyAvL9GB0L7QutGA0LDRgtC40YLRjC/RgNCw0LfQsdC40YLRjCDRgdGC0YDQvtC60YMKCQlyZXR1cm4gcy5zdWJzdHJpbmcoMCxjdXQpICtgJHtzLmxlbmd0aCA+IGN1dCAtIDEgPyBgJHtjaH3igKYke3Muc3Vic3RyaW5nKHMubGVuZ3RoIC0gY3V0ICsgY2gubGVuZ3RoLHMubGVuZ3RoKX1gOiAnJ31gOwoJfSwKCWZvcm1hdEJ5dGVzKGIsZCA9IDEpIHsgLy/QvtCx0YrRkdC8INCx0LDQudGC4oCm0KLQsQoJCWxldCBpID0gTWF0aC5sb2cyKGIpLzEwfDA7IHJldHVybiBwYXJzZUZsb2F0KChiLzEwMjQqKihpPWk8PTA/MDppKSkudG9GaXhlZChkKSkrYCR7aT4wPydLTUdUJ1tpLTFdOicnfWJgOwoJfSwKCWFib3V0X2NvbmZpZyhmaWx0ZXIpIHsgLy/QvdCwINC+0L/RhtC40Y4KCQl2YXIgc2V0RmlsdGVyID0gKGUsaW5wdXQgPSAoZT8udGFyZ2V0IHx8IHdpbmRvdy5jb250ZW50LmRvY3VtZW50KS5nZXRFbGVtZW50QnlJZCgiYWJvdXQtY29uZmlnLXNlYXJjaCIpKSA9PiB7CgkJCWlmIChlIHx8IGlucHV0LnZhbHVlICE9IGZpbHRlcikgaW5wdXQuc2V0VXNlcklucHV0KGZpbHRlcik7fSwKCQlmb3VuZCA9IHdpbmRvdy5zd2l0Y2hUb1RhYkhhdmluZ1VSSSgiYWJvdXQ6Y29uZmlnIix0cnVlLCB7cmVsYXRlZFRvQ3VycmVudDogdHJ1ZSwKCQkJdHJpZ2dlcmluZ1ByaW5jaXBhbDogU2VydmljZXMuc2NyaXB0U2VjdXJpdHlNYW5hZ2VyLmdldFN5c3RlbVByaW5jaXBhbCgpfSk7CgkJaWYgKGZvdW5kKSBzZXRGaWx0ZXIobnVsbCx3aW5kb3cpOwoJCWVsc2UgZ0Jyb3dzZXIuc2VsZWN0ZWRCcm93c2VyLmFkZEV2ZW50TGlzdGVuZXIoInBhZ2VzaG93IixzZXRGaWx0ZXIsIHtvbmNlOiB0cnVlfSk7Cgl9LAoJdG9TdGF0dXModHh0LHRpbWUgPSA1ZTMsU3RhdHVzUGFuZWwgPSB3aW5kb3cuU3RhdHVzUGFuZWwpIHsKCQlpZiAoU3RhdHVzUGFuZWwudXBkYXRlLnRpZCkKCQkJY2xlYXJUaW1lb3V0KFN0YXR1c1BhbmVsLnVwZGF0ZS50aWQpCgkJZWxzZSB7CgkJCXZhciB7dXBkYXRlfSA9IFN0YXR1c1BhbmVsOwoJCQlTdGF0dXNQYW5lbC51cGRhdGUgPSAoKSA9PiB7fTsKCQkJU3RhdHVzUGFuZWwudXBkYXRlLnJldCA9ICgpID0+IHsKCQkJCVN0YXR1c1BhbmVsLnVwZGF0ZSA9IHVwZGF0ZSxTdGF0dXNQYW5lbC51cGRhdGUoKTsKCQl9fQoJCVN0YXR1c1BhbmVsLnVwZGF0ZS50aWQgPSBzZXRUaW1lb3V0KFN0YXR1c1BhbmVsLnVwZGF0ZS5yZXQsdGltZSk7CgkJU3RhdHVzUGFuZWwuX2xhYmVsID0gdHh0OwoJfSwKCWZsYXNoKGlkLHN0eWxlLGNvbG9yLG1zLHRleHQsdGltZSA9IDVlMykgeyAvL9GB0YLQsNGC0YPRgSwg0LzQuNCz0LDQvdC40LUKCQlpZCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkIHx8ICd1cmxiYXItaW5wdXQtY29udGFpbmVyJyk7IGlmICghaWQpIHJldHVybjsKCQlpZiAoc3R5bGUpIGlkLnN0eWxlLmZpbHRlciA9IHN0eWxlOyBpZiAoY29sb3IpIGlkLnN0eWxlLmJhY2tncm91bmQgPSBjb2xvcjsKCQlpZiAobXMpIHNldFRpbWVvdXQoKCkgPT4gewoJCQlpZC5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgnZmlsdGVyJyksaWQuc3R5bGUucmVtb3ZlUHJvcGVydHkoJ2JhY2tncm91bmQtY29sb3InKTt9LG1zKTsKCQlpZiAodGV4dCkgZ2xvYi50b1N0YXR1cyh0ZXh0LHRpbWUpOwoJfSwKCW1vZGVfc2tpbih0ZXh0LHAgPSB0aGlzLnByZWYoJ25ldHdvcmsucHJveHkudHlwZScpLHQscyA9ICd1bnNldCcsbyA9ICcnLHopIHt3aXRoKGdsb2IpewoJCWlmIChwcmVmKCJkb20uc2VjdXJpdHkuaHR0cHNfb25seV9tb2RlIikpCgkJCWZsYXNoKEJbMTBdLCJkcm9wLXNoYWRvdygwcHggMC41cHggMHB4ICNGOEYpIiksbyA9ICcsINGC0L7Qu9GM0LrQviBIVFRQUycKCQllbHNlIGZsYXNoKEJbMTBdLCJub25lIik7CgkJaWYgKHVhKCkgJiYgKHVhKCkgIT0gdWEodHJ1ZSkpKSBvID0gbyArJywg0YfRg9C20L7QuSDQrtC30LXRgNCQ0LPQtdC90YInOwoJCXogPSBwcmVmKCJuZXR3b3JrLnByb3h5Lm5vX3Byb3hpZXNfb24iKSA9PSAiIiA/ICIiIDogIiwg0JXRgdGC0Ywg0YHQsNC50YLRiy3QuNGB0LrQu9GO0YfQtdC90LjRjyI7CgkJaWYgKHAgPT0gMSkgdCA9IFsnc2VwaWEoMTAwJSkgc2F0dXJhdGUoMTUwJSkgYnJpZ2h0bmVzcygwLjkpJywgJ9Cg0YPRh9C90LDRjyDQvdCw0YHRgtGA0L7QudC60LAg0L/RgNC+0LrRgdC4Jysgel07CgkJZWxzZSBpZiAocCA9PSAyKSB0ID0gWydodWUtcm90YXRlKDEyMGRlZykgc2F0dXJhdGUoNzAlKScsVFsxXSArIHpdLHMgPSAnaHVlLXJvdGF0ZSgyNzBkZWcpIGJyaWdodG5lc3MoOTUlKSc7CgkJZWxzZSBpZiAocCA9PSA0KSB0ID0gWydodWUtcm90YXRlKDI1MGRlZykgYnJpZ2h0bmVzcygwLjk1KSBzYXR1cmF0ZSgxNTAlKScsJ9Ch0LXRgtGMIC0g0LDQstGC0L7QvdCw0YHRgtGA0L7QudC60LAg0L/RgNC+0LrRgdC4Jysgel07CgkJZWxzZSBpZiAocCA9PSAwKSB0ID0gWydzYXR1cmF0ZSgwJSkgYnJpZ2h0bmVzcygwLjk1KScsJ9Cd0LDRgdGC0YDQvtC50LrQuCDRgdC10YLQuCAtINGB0LjRgdGC0LXQvNC90YvQtScrIHpdCgkJZWxzZSB0ID0gW3MsJ9Ch0LXRgtGMINGA0LDQsdC+0YLQsNC10YIg0LHQtdC3INC/0YDQvtC60YHQuCddOyAvLyDRgdC10YDRi9C5INGE0L7QvSDQutC90L7Qv9C60LgKCQlmbGFzaChCWzBdLHByZWYoRmYuaSkgPiAxID8gImh1ZS1yb3RhdGUoMTgwZGVnKSBkcm9wLXNoYWRvdygwcHggMC41cHggMHB4ICNGNjgpIiA6ICJub25lIik7CgkJZmxhc2goQls2XSxzKTsgZmxhc2goQlsxXSx0WzBdKTsKCQl6ID0gdHlwZW9mKHRleHQpOyBpZiAoeiA9PSAnc3RyaW5nJykKCQkJdG9TdGF0dXModGV4dCA/IHRleHQgOiAiXHV7MjZBMX0iKyB0WzFdICsgbyw1ZTMpOyAvLyDRgdC40LzQstC+0Lsg0JLQvdC40LzQsNC90LjQtQoJfX0KfTsKKChvYmosZGVsLHJlLHJlb3MpID0+IHsgLy8g0L/QsNGA0YHQuNC90LMg0LHQu9C+0LrQsCDQutC70LDQstC40Ygg0YPRgdC60L7RgNGP0LXRgiDQvtCx0YDQsNCx0L7RgtC60YMg0L3QsNC20LDRgtC40LkKCXZhciBudW0gPSAtRmYub3MubGVuZ3RoIC0gMTsKCWZvcih2YXIgcCBpbiBrbGFCYSkgcmVvcy50ZXN0KHApICYmIGRlbC5hZGQoIHAuZW5kc1dpdGgocGxhdGZvcm0pID8gcC5zbGljZSgwLG51bSkgOiBwKTsKCWZvcih2YXIgcCBpbiBrbGFCYSkgZGVsLmhhcyhrbGFCYVtwXSkgJiYgZGVsLmFkZChwKTsKCWZvcih2YXIgZCBvZiBkZWwpIGRlbGV0ZSBrbGFCYVtkXTsgLy/QtdGB0YLRjCBLZXlfT1MgPyDRg9C00LDQu9C40YLRjCDQuNC80LXQvdCwLdC60LvQvtC90YsKCWZvcih2YXIgcCBpbiBrbGFCYSkgaWYgKHJlb3MudGVzdChwKSkKCQkJa2xhQmFbcC5yZXBsYWNlKHJlb3MsJycpXSA9IGtsYUJhW3BdLCBkZWxldGUga2xhQmFbcF07IC8v0YPQsdGA0LDRgtGMINC40LzRjyDQstCw0YjQtdC5INCe0KEg0LjQtyDRgdCy0L7QudGB0YLQstCwCglmb3IodmFyIHAgaW4ga2xhQmEpIHt2YXIgZnVuYyA9IGtsYUJhW3BdOyAvLygpe+KApn0sIGJvb2wsbnVtCgkJaWYgKHR5cGVvZiBmdW5jID09ICJzdHJpbmciKSBmdW5jID0ga2xhQmFbZnVuY107IC8v0YHRgdGL0LvQutCwINC90LAg0YTRg9C90LrRhtC40Y4KCQl2YXIgW2tleSxtb2RdID0gcC5zcGxpdCgiXyIpOyBtb2QgPSBtb2QgfHwgIiI7CgkJdmFyIHVwcGVyID0ga2V5WzBdLnRvVXBwZXJDYXNlKCk7IHZhciBwcmV2ZW50ID0ga2V5WzBdID09IHVwcGVyOwoJCXZhciBbLCBtLGldID0gbW9kLm1hdGNoKHJlKTsgbSA9IG0gfHwgMDsgLy9tb2RpZmllcnMgYml0bWFwCgkJdmFyIGFyciA9IFtmdW5jLHByZXZlbnQsIGkgPyBpID09ICJJIiA/IDAgOiAxIDogLTFdOyAvL3RleHRmaWVsZHMgZmxhZyDQmNC80Y9faSAxINC60YDQvtC80LUg0L/QvtC70LXQuSDQstCy0L7QtNCwCgkJdmFyIHByb3AgPSBwcmV2ZW50ID8ga2V5IDogdXBwZXIgKyBrZXkuc2xpY2UoMSk7IC8v0LjQvNGPINCx0LXQtyBtb2QKCQl2YXIgbyA9IG9ialtwcm9wXSB8fCAob2JqW3Byb3BdID0gT2JqZWN0LmNyZWF0ZShudWxsKSk7CgkJb1ttXSA/IG9bbV0ucHVzaChhcnIpIDogb1ttXSA9IFthcnJdOyAvL9C40LzRjyDRgdC+INGB0YLRgNC+0YfQvdC+0Lk6IFNraXAgcHJldmVudERlZmF1bHQKCX07IGtsYUJhID0gb2JqOyB9KShPYmplY3QuY3JlYXRlKG51bGwpLG5ldyBTZXQoKSwvKFxkKyk/KGkpPy9pLC9fKD86d2lufGxpbnV4fG1hY29zeCkkLyk7CmRhdGEgPSB7fTsgTS5mb3JFYWNoKChrKSA9PntkYXRhWyIjIisga10gPSBkYXRhWyIuIisga10gPSBNb3VzZVtrXX0pOwoKdmFyIERlYnVnID0gKGUsaWQgPSAic2lkZWJhci1ib3giKSA9PiB7CglpZiAoU2VydmljZXMucHJlZnMuZ2V0Qm9vbFByZWYoRmYucCArJ2RlYnVnJyxmYWxzZSkpIHJldHVybiB0cnVlOwoJcmV0dXJuICFkb2N1bWVudC5nZXRFbGVtZW50QnlJZChpZCkuaGlkZGVuOwp9LAprZXlkb3duX3dpbiA9IGUgPT4geyAvL9C/0LXRgNC10YXQstCw0YIg0LrQu9Cw0LLQuNGILCDRg9GH0LjRgtGL0LLQsNGPINC/0L7Qu9GPINCy0LLQvtC00LAKCWlmIChlLnJlcGVhdCkgcmV0dXJuOyAvLyDQstGL0LrQu9GO0YfQuNGC0YwgZS5nZXRNb2RpZmllclN0YXRlKCJDYXBzTG9jayIpCgl2YXIgZGF0YSA9IGtsYUJhW2UuY29kZV0/LltlLm1ldGFLZXkqOCArIGUuY3RybEtleSo0ICsgZS5zaGlmdEtleSoyICsgZS5hbHRLZXldOwoJaWYgKGRhdGEpIC8v0LXRgdGC0YwgSG90S2V5CgkJZm9yKHZhciBbZnVuYyxwLGldIG9mIGRhdGEpCgkJCWlmIChpIF4gZG9jU2hlbGwuaXNDb21tYW5kRW5hYmxlZCgiY21kX2luc2VydFRleHQiKSkKCQkJCXAgJiYgZS5wcmV2ZW50RGVmYXVsdCgpLCBmdW5jKGUsIGdCcm93c2VyLnNlbGVjdGVkVGFiKTsgLy/Qt9Cw0L/Rg9GB0Log0L/QviDRgdC+0YfQtdGC0LDQvdC40Y4KCWlmICghRGVidWcoKSkgcmV0dXJuOyAvL9C/0L7QutCw0Lcg0LrQu9Cw0LLQuNGICgljb25zb2xlLmxvZygn4pagIGtleSAnKyBlLmNvZGUgKyAoJ18nKyAoZS5tZXRhS2V5KjggKyBlLmN0cmxLZXkqNCArIGUuc2hpZnRLZXkqMiArIGUuYWx0S2V5KSkucmVwbGFjZSgnXzAnLCcnKSk7Cn07Cmxpc3RlbmVyID0geyAvL9C00LXQudGB0YLQstC40Y8g0LzRi9GI0LgsINC/0LXRgNC10YXQstCw0YIg0YHRg9GJ0LXRgdGC0LLRg9GO0YnQuNGFCgloYW5kbGVFdmVudChlKSB7CgkJaWYgKHRoaXMuc2tpcCB8fCBlLmRldGFpbCA+IDEpIHJldHVybjsKCQl2YXIgdHJnID0gZS50YXJnZXQsIGlkID0gdHJnLmlkIHx8IHRyZy5jbGFzc05hbWUgfHwgdHJnLnRhZ05hbWU7CgkJaWYgKGUudHlwZSA9PSAibW91c2VlbnRlciIpIHsKCQkJdmFyIGhpbnQgPSBPdmVyW2lkXSB8fCBPdmVyWyh0cmcgPSB0cmcucGFyZW50Tm9kZSkuaWRdOwoJCQlpZiAoaGludCkgdHJnLnRvb2x0aXBUZXh0ID0gaGludDsgcmV0dXJuOyAvL9C+0LHQvdC+0LLQuNGC0Ywg0L/QvtC00YHQutCw0LfQutGDCgkJfQoJCXZhciBzZWxzID0gdGhpcy5zZWxlY3RvcnMuZmlsdGVyKHRoaXMuZmlsdGVyLCB0cmcpOyAvLyNpZAoJCXZhciB7bGVuZ3RofSA9IHNlbHM7IGlmICghbGVuZ3RoKSByZXR1cm47CgkJdmFyIHdoZWVsID0gZS50eXBlLnN0YXJ0c1dpdGgoInciKTsKCQl2YXIgbnVtID0gZS5tZXRhS2V5KjY0ICsgZS5jdHJsS2V5KjMyICsgZS5zaGlmdEtleSoxNiArIGUuYWx0S2V5KjggKyAod2hlZWwgPyAyIDogZS5idXR0b24qMTI4KTsgLy9kYmwqNAoJCXZhciBvYmogPSBkYXRhWwoJCQlsZW5ndGggPiAxICYmIHNlbHMuZmluZCh0aGlzLmZpbmQsbnVtKSB8fCBzZWxzWzBdCgkJXTsKCQlEZWJ1ZygpICYmIGNvbnNvbGUubG9nKCfilqAgYnV0IMKrJysgaWQgKyfCuyBrZXkgJysgbnVtKTsgLy93aGVlbCDQtNCy0LDQttC00YsKCQlpZiAod2hlZWwpIHJldHVybiBvYmpbbnVtXT8uKHRyZywgZS5kZWx0YVkgPCAwKTsKLy8gbW91c2Vkb3duCgkJaWYgKGUudHlwZS5zdGFydHNXaXRoKCJtIikpIHsKCQkJb2JqLm1vdXNlZG93blRhcmdldCAmJiB0aGlzLnN0b3AoZSk7CgkJCXRoaXMubG9uZ1ByZXNzID0gZmFsc2U7IC8vKyDQt9Cw0LTQtdGA0LbQutCwINC/0YDQuCDQvtCx0YvRh9C90L7QvCDQutC70LjQutC1CgkJCWlmICgrK251bSBpbiBvYmopCgkJCQl0aGlzLm1vdXNlZG93blRJRCA9IHNldFRpbWVvdXQodGhpcy5vbkxvbmdQcmVzcyw2NDAsIHRyZyxvYmosbnVtKTsKCQkJaWYgKGUuYnV0dG9uID09IDIpCgkJCQl0aGlzLmN0eCA9IHRyZy5nZXRBdHRyaWJ1dGUoImNvbnRleHQiKSwgdHJnLnNldEF0dHJpYnV0ZSgiY29udGV4dCIsIiIpOwoJCQlyZXR1cm47CgkJfQoJCW9iai5tb3VzZWRvd25UYXJnZXQgfHwgdGhpcy5zdG9wKGUpOwkvL2NsaWNrCgkJaWYgKHRoaXMubG9uZ1ByZXNzKSByZXR1cm4gdGhpcy5sb25nUHJlc3MgPSBmYWxzZTsKCQl0aGlzLm1vdXNlZG93blRJRCAmJj0gY2xlYXJUaW1lb3V0KHRoaXMubW91c2Vkb3duVElEKTsKCQlpZiAoIW9ialtudW1dKSB7CgkJCWlmIChlLmJ1dHRvbiA9PSAxKSByZXR1cm47CgkJCWlmIChlLmJ1dHRvbikgewoJCQkJbnVtID0gImNvbnRleHQiOwoJCQkJZm9yKHZhciBwIGluIHRoaXMuYSkgdGhpcy5hW3BdID0gZVtwXTsKCQkJfSBlbHNlCgkJCQludW0gPSAiZGlzcGF0Y2giLCB0aGlzLm1kdCA9IG9iai5tb3VzZWRvd25UYXJnZXQ7CgkJCW9iaiA9IHRoaXM7CgkJfQoJCW9ialtudW1dKHRyZyk7IC8vcnVuCgl9LAoJZmluZChzZWwpIHsgLy/Rg9GB0LvQvtCy0LjRjyDQt9Cw0L/Rg9GB0LrQsCA/CgkJcmV0dXJuIGRhdGFbc2VsXVt0aGlzXSB8fCBkYXRhW3NlbF1bdGhpcyArIDFdOwoJfSwKCWZpbHRlcihzZWwpIHtyZXR1cm4gdGhpcy5jbG9zZXN0KHNlbCk7Cgl9LAoJZ2V0IHNlbGVjdG9ycygpIHsKCQl0aGlzLm9uTG9uZ1ByZXNzID0gKHRyZyxvYmosbnVtKSA9PiB7CgkJCXRoaXMubW91c2Vkb3duVElEID0gbnVsbDsKCQkJdGhpcy5sb25nUHJlc3MgPSB0cnVlOwoJCQlvYmpbbnVtXSh0cmcpOwoJCX0KCQlkZWxldGUgdGhpcy5zZWxlY3RvcnM7CgkJcmV0dXJuIHRoaXMuc2VsZWN0b3JzID0gT2JqZWN0LmtleXMoZGF0YSk7Cgl9LAoJZ2V0IG1kRXZlbnQoKSB7CgkJZGVsZXRlIHRoaXMubWRFdmVudDsKCQlyZXR1cm4gdGhpcy5tZEV2ZW50ID0gbmV3IE1vdXNlRXZlbnQoIm1vdXNlZG93biIsIHtidWJibGVzOiB0cnVlfSk7Cgl9LAoJY29udGV4dCh0cmcpIHsKCQl0aGlzLmN0eCA/IHRyZy5zZXRBdHRyaWJ1dGUoImNvbnRleHQiLHRoaXMuY3R4KSA6IHRyZy5yZW1vdmVBdHRyaWJ1dGUoImNvbnRleHQiKTsKCQl0cmcuZGlzcGF0Y2hFdmVudChuZXcgTW91c2VFdmVudCgiY29udGV4dG1lbnUiLHRoaXMuYSkpOwoJfSwKCWRpc3BhdGNoKHRyZykgewoJCXRoaXMuc2tpcCA9IHRydWU7CgkJdGhpcy5tZHQgPyB0cmcuZGlzcGF0Y2hFdmVudCh0aGlzLm1kRXZlbnQpIDogdHJnLmNsaWNrKCk7CgkJdGhpcy5za2lwID0gZmFsc2U7Cgl9LAoJc3RvcDogZSA9PiB7CgkJZS5wcmV2ZW50RGVmYXVsdCgpOyBlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpOwoJfSwKCWE6IHtfX3Byb3RvX186IG51bGwsYnViYmxlczogdHJ1ZSxzY3JlZW5YOiAwLHNjcmVlblk6IDB9Cn0sCmlkID0gInVjZl9ob29rRXhwZXJ0IixldmVudHMgPSBbImNsaWNrIiwibW91c2Vkb3duIiwid2hlZWwiLCJtb3VzZWVudGVyIl0sCmVscyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoIiNuYXZpZ2F0b3ItdG9vbGJveCwjdWNmLWFkZGl0aW9uYWwtdmVydGljYWwtYmFyLCNhcHBNZW51LXBvcHVwLCN3aWRnZXQtb3ZlcmZsb3ctbWFpblZpZXciKTsKZm9yKHZhciBlbCBvZiBlbHMpIGZvcih2YXIgdHlwZSBvZiBldmVudHMpCgkJZWwuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLGxpc3RlbmVyLHRydWUpOwp3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigia2V5ZG93biIsa2V5ZG93bl93aW4sdHJ1ZSk7CnVjZl9jdXN0b21fc2NyaXB0X3dpbi51bmxvYWRsaXN0ZW5lcnMucHVzaChpZCk7CnVjZl9jdXN0b21fc2NyaXB0X3dpbltpZF0gPSB7ZGVzdHJ1Y3RvcigpIHsKCXdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCJrZXlkb3duIixrZXlkb3duX3dpbik7Cglmb3IodmFyIGVsIG9mIGVscykgZm9yKHZhciB0eXBlIG9mIGV2ZW50cykKCQllbC5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsbGlzdGVuZXIsdHJ1ZSk7Cn19Owp2YXIgYWRkRGVzdHJ1Y3RvciA9IG5leHREZXN0cnVjdG9yID0+IHsgLy/QtNC70Y8gc2F2ZVNlbFRvVHh0Cgl2YXIge2Rlc3RydWN0b3J9ID0gdWNmX2N1c3RvbV9zY3JpcHRfd2luW2lkXTsKCXVjZl9jdXN0b21fc2NyaXB0X3dpbltpZF0uZGVzdHJ1Y3RvciA9ICgpID0+IHsKCQl0cnkge2Rlc3RydWN0b3IoKTt9IGNhdGNoKGV4KSB7Q3UucmVwb3J0RXJyb3IoZXgpO30KCQluZXh0RGVzdHJ1Y3RvcigpOwp9fTsKd2l0aCAoZG9jdW1lbnQpIGdldEVsZW1lbnRCeUlkKEJbMTFdKS5yZW1vdmVBdHRyaWJ1dGUoInRvb2x0aXAiKSwKCWdldEVsZW1lbnRCeUlkKCJuYXYtYmFyIikudG9vbHRpcCA9IGlkOyAvL9GE0LvQsNCzINGD0YHQv9C10YjQvdC+0Lkg0LfQsNCz0YDRg9C30LrQuAoKZ2xvYi5tb2RlX3NraW4oKTsgLy/Qv9C+0LTRgdCy0LXRgtC60LAg0LrQvdC+0L/QvtC6INC4INC/0L7QtNGB0LrQsNC30LrQuCDQvtGC0L7QsdGA0LDQttCw0Y7RgiDQvdCw0YHRgtGA0L7QudC60Lgg0LHRgNCw0YPQt9C10YDQsApnbG9iLnByZWYoJ3VpLnByZWZlcnNSZWR1Y2VkTW90aW9uJywwKTsJLy9Eb3dubG9hZEJ1dHRvbiBhbmltYXRpb24gRklYCnZhciB0YWJyID0gRmYucCArIm9wYWNpdHkiLHVybCA9IGByZXNvdXJjZTovLyR7dGFicn0vYCwgLy9icmlnaHQgdGFicwpnZXRJbnRQcmVmID0gKHApID0+IFNlcnZpY2VzLnByZWZzLmdldEludFByZWYocCwxMDApLApzc3MgPSBDY1siQG1vemlsbGEub3JnL2NvbnRlbnQvc3R5bGUtc2hlZXQtc2VydmljZTsxIl0uZ2V0U2VydmljZShDaS5uc0lTdHlsZVNoZWV0U2VydmljZSksCmNzcyA9IGBALW1vei1kb2N1bWVudCB1cmwoY2hyb21lOi8vYnJvd3Nlci9jb250ZW50L2Jyb3dzZXIueGh0bWwpIHsKCTppcygke2lkfSlbcnN0XSB7ZmlsdGVyOiBncmF5c2NhbGUoMSUpICFpbXBvcnRhbnR9Cgk6cm9vdDpub3QoW2Nocm9tZWhpZGRlbio9dG9vbGJhcl0pICN0YWJicm93c2VyLXRhYmJveCB7YmFja2dyb3VuZC1jb2xvcjogYmxhY2sgIWltcG9ydGFudH0KCTpyb290Om5vdChbY2hyb21laGlkZGVuKj10b29sYmFyXSkgI3RhYmJyb3dzZXItdGFicGFuZWxzIHtvcGFjaXR5OiR7Z2V0SW50UHJlZih0YWJyKS8xMDB9ICFpbXBvcnRhbnR9fWA7ClNlcnZpY2VzLmlvLmdldFByb3RvY29sSGFuZGxlcigicmVzb3VyY2UiKS5RdWVyeUludGVyZmFjZShDaS5uc0lSZXNQcm90b2NvbEhhbmRsZXIpCgkuc2V0U3Vic3RpdHV0aW9uKHRhYnIsU2VydmljZXMuaW8ubmV3VVJJKCJkYXRhOnRleHQvY3NzLCIrIGVuY29kZVVSSUNvbXBvbmVudChjc3MpKSk7CnNzcy5sb2FkQW5kUmVnaXN0ZXJTaGVldChTZXJ2aWNlcy5pby5uZXdVUkkodXJsKSxzc3MuVVNFUl9TSEVFVCk7CnZhciBzdCA9IEluc3BlY3RvclV0aWxzLmdldEFsbFN0eWxlU2hlZXRzKGRvY3VtZW50KS5maW5kKHMgPT4gcy5ocmVmID09IHVybCkuY3NzUnVsZXNbMF0uY3NzUnVsZXNbMl0uc3R5bGU7CnZhciBvYnNlcnZlciA9ICgpID0+IHN0LnNldFByb3BlcnR5KCJvcGFjaXR5IiwgZ2V0SW50UHJlZih0YWJyKS8xMDAsImltcG9ydGFudCIpOwpwcmVmcy5hZGRPYnNlcnZlcih0YWJyLG9ic2VydmVyKTsKdGhpcy5yZW1vdmVQcmVmT2JzID0gKCkgPT4gcHJlZnMucmVtb3ZlT2JzZXJ2ZXIodGFicixvYnNlcnZlcik7IC8vZW5kIGJyaWdodAoKdmFyIGNzc19VU0VSID0gKGNzcykgPT4geyAvL9C70L7QutCw0LvRjNC90YvQtSDRhNGD0L3QutGG0LjQuAoJdmFyIHN0eWxlID0gRmlsZUV4aXN0cyhjc3MpID8gU2VydmljZXMuaW8ubmV3VVJJKGNzcykgOiBtYWtlVVJJKCdkYXRhOnRleHQvY3NzO2NoYXJzZXQ9dXRmLTgsJysgZW5jb2RlVVJJQ29tcG9uZW50KGNzcykpOwoJdmFyIGFyZ3MgPSBbc3R5bGUsc3NzLlVTRVJfU0hFRVRdOyAvLyDRgdGC0LjQu9GMOiDRhNCw0LnQuyDQuNC70LggQ1NTCgkodGhpcy5jc3MgPSAhdGhpcy5jc3MpID8gc3NzLmxvYWRBbmRSZWdpc3RlclNoZWV0KC4uLmFyZ3MpIDogc3NzLnVucmVnaXN0ZXJTaGVldCguLi5hcmdzKTsKfSwKZ0NsaXBib2FyZCA9IHt3cml0ZShzdHIsY2ggPSBDY1siQG1vemlsbGEub3JnL3dpZGdldC9jbGlwYm9hcmRoZWxwZXI7MSJdLmdldFNlcnZpY2UoQ2kubnNJQ2xpcGJvYXJkSGVscGVyKSkgewoJCSh0aGlzLndyaXRlID0gc3RyID0+IGNoLmNvcHlTdHJpbmdUb0NsaXBib2FyZChzdHIsU2VydmljZXMuY2xpcGJvYXJkLmtHbG9iYWxDbGlwYm9hcmQpKShzdHIpO30KfSwKVGFiQWN0ID0gKGUpID0+IHtyZXR1cm4gZS5jbG9zZXN0KCIudGFiYnJvd3Nlci10YWIiKTsKfSwKc3dpdGNoVGFiID0gKHVybCA9ICdhYm91dDpzZXJ2aWNld29ya2VycycsZ28gPSBmYWxzZSkgPT4geyAvL9C+0YLQutGA0YvRgtGMINCy0LrQu9Cw0LTQutGDIHwg0LfQsNC60YDRi9GC0YwsINC10YHQu9C4INC+0YLQutGA0YvRgtCwIHwg0LLRi9Cx0YDQsNGC0YwKCWZvcih2YXIgdGFiIG9mIGdCcm93c2VyLnZpc2libGVUYWJzKQoJCWlmICh0YWIubGlua2VkQnJvd3Nlci5jdXJyZW50VVJJLnNwZWMgPT0gdXJsKQoJCQl7Z28gPyBnQnJvd3Nlci5zZWxlY3RlZFRhYiA9IHRhYiA6IGdCcm93c2VyLnJlbW92ZVRhYih0YWIpOyByZXR1cm47fQoJZ0Jyb3dzZXIuYWRkVHJ1c3RlZFRhYih1cmwpOyBnQnJvd3Nlci5zZWxlY3RlZFRhYiA9IGdCcm93c2VyLnZpc2libGVUYWJzW2dCcm93c2VyLnZpc2libGVUYWJzLmxlbmd0aCAtMV07Cn0sClRhYnNEZWwgPSAocmlnaHQgPSAwLGN1cnIgPSBnQnJvd3Nlci5zZWxlY3RlZFRhYikgPT4geyAvLyDQt9Cw0LrRgNGL0YLRjCDQstC60LvQsNC00LrQuCDRgdC70LXQstCwL9GB0L/RgNCw0LLQsCDQvtGCINCw0LrRgtC40LLQvdC+0LkKCXZhciB0YWJzID0gZ0Jyb3dzZXIudmlzaWJsZVRhYnMuZmlsdGVyKHRhYiA9PiAhdGFiLnBpbm5lZCksIGkgPSB0YWJzLmluZGV4T2YoY3Vycik7Cgl2YXIgYSA9IChpICE9IC0xKSwgYiA9IChhID8gaSArIHJpZ2h0IDogIXJpZ2h0ICogdGFicy5sZW5ndGgpOwoJYXJncyA9IHJpZ2h0ID8gW2IsIHRhYnMubGVuZ3RoXSA6IFswLGJdOwoJdGFicy5zbGljZSguLi5hcmdzKS5mb3JFYWNoKChpKSA9PiB7Z0Jyb3dzZXIucmVtb3ZlVGFiKGkpfSk7Cn0sCnN3aXRjaFByb3h5ID0gKHBhYyA9ICdodHRwczovL2FudGl6YXByZXQucHJvc3RvdnBuLm9yZy9wcm94eS5wYWMnKSA9PiB7Cgl2YXIgcG4gPSAnbmV0d29yay5wcm94eS50eXBlJyxwID0gJ25ldHdvcmsucHJveHkuYXV0b2NvbmZpZ191cmwnOwoJaWYgKGdsb2IucHJlZihwbikgIT0gMikgLy8g0LLRi9C60LvRjtGH0LjRgtGMCgkJZ2xvYi5wcmVmKHBuLDIpLCBnbG9iLnByZWYocCxwYWMpCgllbHNlCgkJZ2xvYi5wcmVmKHBuLDUpLCBnbG9iLnByZWYocCwibG9jYWxob3N0Iik7CglnbG9iLm1vZGVfc2tpbigpOyAvL9GA0LDQt9C90YvQuSDRhNC+0L0g0LfQsNC80LrQsCDQtNC70Y8g0J/RgNC+0LrRgdC4CglCcm93c2VyUmVsb2FkKCk7Cn0sClRpdGxlID0gKG1heCx0aXRsZSkgPT4geyAvL9C30LDQs9C+0LvQvtCy0L7Qui4g0LHQtdC3INC+0LHRgNC10LfQutC4OiBtYXgg0L3QtSDRg9C60LDQt9Cw0L0sINC00L7QvNC10L06IG1heCA8MCwgKyDQtNCw0YLQsDogbWF4PTAKCWlmICghdGl0bGUpIHZhciB0aXRsZSA9IGRvY3VtZW50LnRpdGxlIHx8IGdCcm93c2VyLnNlbGVjdGVkVGFiLmxhYmVsOwoJaWYgKG1heCA9PSB1bmRlZmluZWQpIHJldHVybiB0aXRsZTsgLy/QvtCz0YDQsNC90LjRh9C40YLRjCDQtNC70LjQvdGDLCDRg9Cx0YDQsNGC0Ywg0YHQu9GD0LbQtdCx0L3Ri9C1INGB0LjQvNCy0L7Qu9GLCgl0aXRsZSA9IHRpdGxlLnJlcGxhY2UoL1tcXFwvPypcIidgXSsvZywnJykucmVwbGFjZSgvXHMrL2csJyAnKS5yZXBsYWNlKC9bfDw+XSsvZywnXycpLnJlcGxhY2UoLzovZywn1oknKS50cmltKCk7CglpZiAoIG1heCA+IDAgKSByZXR1cm4gdGl0bGUuc2xpY2UoMCxtYXgpOwoJaWYgKCBtYXggPT0gMCkgcmV0dXJuIHRpdGxlLnNsaWNlKDAsMTAwKSArIl8iKyBuZXcgRGF0ZSgpLnRvTG9jYWxlRGF0ZVN0cmluZygncnUnLCB7ZGF5OidudW1lcmljJyxtb250aDonbnVtZXJpYycseWVhcjonMi1kaWdpdCd9KSArJy0nKyBuZXcgRGF0ZSgpLnRvTG9jYWxlVGltZVN0cmluZygnZW4tR0InKS5yZXBsYWNlKC86L2csItaJIik7IC8v0LTQsNGC0LAt0YfQsNGB0YsKCXZhciBob3N0ID0gZGVjb2RlVVJJQ29tcG9uZW50KGdVUkxCYXIudmFsdWUpOyAvL21heCA8IDAKCWlmICghL15maWxlOlwvXC8vLnRlc3QoaG9zdCkpIGhvc3QgPSBob3N0LnJlcGxhY2UoL14uKnVybD18aHR0cHM/OlwvXC98d3d3XC58XC8uKi9nLCcnKS5yZXBsYWNlKC9ecnVcLnxebVwufGZvcnVtXC4vLCcnKS5yZXBsYWNlKC9eY2x1YlwuZG5zLywnZG5zJyk7CglyZXR1cm4gaG9zdDsKfSwKc2F2ZSA9ICgpID0+IHsgLy/RhNGD0L3QutGG0LjRjyDQuNC3IFNpbmdsZUhUTUwuanNtCgl2YXIgYXJncyA9IFtnbG9iLmNyb3AoIuKImiDRgdGC0YDQsNC90LjRhtCwINC30LDQv9C40YHQsNC90LA6ICIrIFRpdGxlKDApLDQ4LCcnKSw3ZTNdOwoJdHJ5IHtDdS5nZXRHbG9iYWxGb3JPYmplY3QoQ3UpW1N5bWJvbC5mb3IoIlNpbmdsZUhUTUwiKV0odHJ1ZSx3aW5kb3cpOwoJCWdCcm93c2VyLnNlbGVjdGVkVGFiLnRleHRMYWJlbC5zdHlsZS50ZXh0RGVjb3JhdGlvbiA9ICJvdmVybGluZSI7IC8vIF7Qv9C+0LTRh9GR0YDQutC40LLQsNC90LjQtQoJfSBjYXRjaCB7YXJncyA9IFsn4pi5INCe0YjQuNCx0LrQsCDRhNGD0L3QutGG0LjQuCBTaW5nbGVIVE1MJywxZTRdfQoJZ2xvYi50b1N0YXR1cyguLi5hcmdzKTsKfSwKc2F2ZVNlbFRvVHh0ID0gYXN5bmMgKCkgPT4geyAvL9CyIC50eHQg0JLRgdGRINC40LvQuCDQktGL0LHRgNCw0L3QvdC+0LUKCXZhciB7bGVuZ3RofSA9IHNhdmVVUkwsIHNwbGljZSA9IGxlbmd0aCA+IDksIGwxMSA9IGxlbmd0aCA9PSAxMSwgbXNnTmFtZSA9IGlkICsgIjpTYXZlOkdldFNlbGVjdGlvbiI7IC8vRklYIEZGMTAzKwoJdmFyIHJlY2VpdmVyID0gbXNnID0+IHt2YXIgdHh0ID0gImRhdGE6dGV4dC9wbGFpbiwiKyBlbmNvZGVVUklDb21wb25lbnQoZ0Jyb3dzZXIuY3VycmVudFVSSS5zcGVjICsiXG5cbiIrIG1zZy5kYXRhKTsKCQl2YXIgYXJncyA9IFt0eHQsVGl0bGUoMCkgKycudHh0JyxudWxsLGZhbHNlLHRydWUsbnVsbCx3aW5kb3cuZG9jdW1lbnRdOwoJCXNwbGljZSAmJiBhcmdzLnNwbGljZSg1LDAsbnVsbCkgJiYgbDExICYmIGFyZ3Muc3BsaWNlKDEsMCxudWxsKTsKCQlzYXZlVVJMKC4uLmFyZ3MpOwoJCWdsb2IudG9TdGF0dXMoZ2xvYi5jcm9wKCLiiJog0YLQtdC60YHRgiDRgdC+0YXRgNCw0L3RkdC9OiAiKyBUaXRsZSgwKSw5NiwnJykpOwoJfQoJbWVzc2FnZU1hbmFnZXIuYWRkTWVzc2FnZUxpc3RlbmVyKG1zZ05hbWUscmVjZWl2ZXIpOwoJYWRkRGVzdHJ1Y3RvcigoKSA9PiBtZXNzYWdlTWFuYWdlci5yZW1vdmVNZXNzYWdlTGlzdGVuZXIobXNnTmFtZSxyZWNlaXZlcikpOwoJdmFyIHNmdW5jID0gZm0gPT4gewoJCXZhciByZXMsZmVkLHdpbiA9IHt9LGZlID0gZm0uZ2V0Rm9jdXNlZEVsZW1lbnRGb3JXaW5kb3coY29udGVudCx0cnVlLHdpbik7CgkJdmFyIHNlbCA9ICh3aW4gPSB3aW4udmFsdWUpLmdldFNlbGVjdGlvbigpOwoJCWlmIChzZWwuaXNDb2xsYXBzZWQpIHsKCQkJdmFyIGVkID0gZmUgJiYgZmUuZWRpdG9yOwoJCQlpZiAoZWQgJiYgZWQgaW5zdGFuY2VvZiBDaS5uc0lFZGl0b3IpCgkJCQlzZWwgPSBlZC5zZWxlY3Rpb24sIGZlZCA9IGZlOwoJCX0KCQlpZiAoc2VsLmlzQ29sbGFwc2VkKQoJCQlmZWQgJiYgZmVkLmJsdXIoKSxkb2NTaGVsbC5kb0NvbW1hbmQoImNtZF9zZWxlY3RBbGwiKSwKCQkJcmVzID0gd2luLmdldFNlbGVjdGlvbigpLnRvU3RyaW5nKCksZG9jU2hlbGwuZG9Db21tYW5kKCJjbWRfc2VsZWN0Tm9uZSIpLAoJCQlmZWQgJiYgZmVkLmZvY3VzKCk7CgkJcmVzID0gcmVzIHx8IHNlbC50b1N0cmluZygpOwoJCS9cUy8udGVzdChyZXMpICYmIHNlbmRBc3luY01lc3NhZ2UoInNhdmVTZWxUb1R4dCIscmVzKTsKCX0KCXZhciB1cmwgPSAiZGF0YTo7Y2hhcnNldD11dGYtOCwiKyBlbmNvZGVVUklDb21wb25lbnQoYCgke3NmdW5jfSlgLnJlcGxhY2UoInNhdmVTZWxUb1R4dCIsbXNnTmFtZSkpICsnKENjWyJAbW96aWxsYS5vcmcvZm9jdXMtbWFuYWdlcjsxIl0uZ2V0U2VydmljZShDaS5uc0lGb2N1c01hbmFnZXIpKTsnOwoJKHNhdmVTZWxUb1R4dCA9ICgpID0+IGdCcm93c2VyLnNlbGVjdGVkQnJvd3Nlci5tZXNzYWdlTWFuYWdlci5sb2FkRnJhbWVTY3JpcHQodXJsLGZhbHNlKSkoKTsKfSwKb3BlbkRpYWwgPSAoYXJncyA9IFtGZi5jICsib3B0aW9ucy9wcmVmc193aW4ueGh0bWwiLCJ1c2VyX2Nocm9tZV9wcmVmczp3aW5kb3ciLCJjZW50ZXJzY3JlZW4scmVzaXphYmxlLGRpYWxvZz1ubyJdKSA9PiB3aW5kb3cub3BlbkRpYWxvZyguLi5hcmdzKSwgLy/QuNC70LggYWJvdXQ6dXNlci1jaHJvbWUtZmlsZXMKdG9vbHRpcF94ID0gKHRyZyx0ZXh0ID0gIiIsIHR0dCA9ICIiKSA9PiB7CglpZiAoIXRyZy5pZC5lbmRzV2l0aCgieCIpKSB7IC8vYm94CgkJdHR0ID0gKHRyZy5oYXNBdHRyaWJ1dGUoInRvb2x0aXB0ZXh0IikpID8gdHJnLnR0dCA9IHRyZy50b29sdGlwVGV4dCA6IHRyZy50dHQ7CgkJaWYgKHR0dCAmJiB0dHQuaW5kZXhPZih0ZXh0KSA9PSAtMSkgdHR0ICs9ICJcblxuIjsKCQl0cmcucmVtb3ZlQXR0cmlidXRlKCJ0b29sdGlwdGV4dCIpOwoJfQoJcmV0dXJuICh0dHQuaW5kZXhPZih0ZXh0KSA9PSAtMSkgPyB0dHQgKyB0ZXh0IDogdHR0Owp9LApicmlnaHQgPSAodHJnLGZvcndhcmQsc3RlcCA9IDEsdmFsKSA9PiB7IC8vd2hlZWwKCWlmICghdmFsKSB2YXIgdmFsID0gZ2V0SW50UHJlZih0YWJyKSArIChmb3J3YXJkID8gc3RlcCA6IC1zdGVwKTsKCXZhbCA9IHZhbCA+IDEwMCA/IDEwMCA6IHZhbCA8IDE1ID8gMTUgOiB2YWw7CglnbG9iLnByZWYodGFicix2YWwpOyB0cmcudG9nZ2xlQXR0cmlidXRlKCJyc3QiKTsgZ2xvYi50b1N0YXR1cyhUWzJdICsgdmFsICsiJSIsMWUzKTsKfSwKYnJfdmFsID0gKCkgPT4gZ2xvYi5wcmVmKFt0YWJyLDEwMF0pICsiJSIsCnpvb20gPSAoZm9yd2FyZCx0b2dnbGUgPSBmYWxzZSwgY2hhbmdlID0gdHJ1ZSx0ZXh0ID0gJycpID0+IHsKCXRvZ2dsZSA/IFpvb21NYW5hZ2VyLnRvZ2dsZVpvb20oKSA6IGNoYW5nZSA/IGZvcndhcmQgPyBGdWxsWm9vbS5lbmxhcmdlKCkgOiBGdWxsWm9vbS5yZWR1Y2UoKSA6IDA7CglnbG9iLnRvU3RhdHVzKCLCsSDQnNCw0YHRiNGC0LDQsSAiKyBNYXRoLnJvdW5kKFpvb21NYW5hZ2VyLnpvb20qMTAwKSArYCUke2dsb2IucHJlZigiYnJvd3Nlci56b29tLmZ1bGwiKSA/ICIiIDogIiAo0YLQvtC70YzQutC+INGC0LXQutGB0YIpIn1gICsgdGV4dCwzZTMpOwp9LApFeHBlcnQgPSAobSA9IEJvb2xlYW4oRmYuRXhwKCkpLHAgPSBGZi5wICsnZXhwZXJ0JykgPT4gewoJZ2xvYi5wcmVmKHAsIW0pOyBnbG9iLnRvU3RhdHVzKE92ZXIuYnJfZXhwKCIiKSwzZTMpOwp9LApIZWxwID0gKGhlbHAgPSBGZi5jICsiaGVscC5odG1sIikgPT4geyAvL9C/0L7QvNC+0YnRjAoJKEZpbGVFeGlzdHMoaGVscCkpID8gc3dpdGNoVGFiKGhlbHApIDogc3dpdGNoVGFiKCd2aWN0b3ItZG9icm92Lm5hcm9kLnJ1L2hlbHAtRkYuaHRtbCcpOwp9LApGaWxlRXhpc3RzID0gKGZpbGUpID0+IHt0cnkgeyAvL9GE0LDQudC7fNC/0LDQv9C60LAg0YHRg9GJ0LXRgdGC0LLRg9C10YI/CglpZiAoIWZpbGUuc3RhcnRzV2l0aCgiY2hyb21lOi8vIikpCgkJcmV0dXJuIEZpbGVVdGlscy5GaWxlKFN0cmluZy5yYXdgJHtmaWxlfWApLmV4aXN0cygpCgllbHNlIHJldHVybiBDY1siQG1vemlsbGEub3JnL2Nocm9tZS9jaHJvbWUtcmVnaXN0cnk7MSJdLmdldFNlcnZpY2UoQ2kubnNJWFVMQ2hyb21lUmVnaXN0cnkpLmNvbnZlcnRDaHJvbWVVUkwoU2VydmljZXMuaW8ubmV3VVJJKGZpbGUpKS5RdWVyeUludGVyZmFjZShDaS5uc0lGaWxlVVJMKS5maWxlLmV4aXN0cygpOwoJfSBjYXRjaCB7fTsgcmV0dXJuIGZhbHNlOwp9LAp1c2VyanMgPSAoZSxteWpzID0gRmYuYyArImN1c3RvbV9zY3JpcHRzL1VzZXIuanMiKSA9PiB7CglEZWJ1ZygpICYmIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCJrZXlfYnJvd3NlckNvbnNvbGUiKS5kb0NvbW1hbmQoKTsgLy/RhNC+0LrRg9GBINC90LAg0LrQvtC90YHQvtC70YwKCUZpbGVFeGlzdHMobXlqcykgPyBldmFsKEN1LnJlYWRVVEY4VVJJKFNlcnZpY2VzLmlvLm5ld1VSSShteWpzKSkpIDogdCA9IG15anMgKyIg4oCUINGB0LrRgNC40L/RgiDQvdC1INC90LDQudC00LXQvSI7Cgljb25zb2xlLmxvZygi4pyFXHQiKyBNYXRoLnJhbmRvbSgpLCIiKTsgLy/QstCw0Ygg0YHQutGA0LjQv9GCCn0sCnRyYW5zbGF0ZSA9IChick1NID0gZ0Jyb3dzZXIuc2VsZWN0ZWRCcm93c2VyLm1lc3NhZ2VNYW5hZ2VyKSA9PiB7IC8vINC/0LXRgNC10LLQvtC0INGB0LDQudGCIHwg0LLRi9C00LXQuy4g0YLQtdC60YHRggoJYnJNTS5hZGRNZXNzYWdlTGlzdGVuZXIoJ2dldFNlbGVjdCcsbGlzdGVuZXIgPSAobXNnKSA9PnsKCQlpZiAobXNnLmRhdGEpIC8vINCf0LXRgNC10LLQvtC0INCy0YvQtNC10LvQtdC90L3QvtCz0L4KCQkJc3dpdGNoVGFiKCJodHRwczovL3RyYW5zbGF0ZS5nb29nbGUuY29tLyN2aWV3PWhvbWUmb3A9dHJhbnNsYXRlJnNsPWF1dG8mdGw9cnUmdGV4dD0iKyBtc2cuZGF0YSx0cnVlKQoJCWVsc2UgLy8g0JPRg9Cz0Lsg0LjQu9C4INCf0LXRgNC10LLQvtC0INGB0LDQudGC0LAg0LIg0K/QvdC00LXQutGBCgkJCXN3aXRjaFRhYigiaHR0cHM6Ly90cmFuc2xhdGUueWFuZGV4LmNvbS90cmFuc2xhdGU/dXJsPSIrIGdVUkxCYXIudmFsdWUgKyImZGlyPSZ1aT1ydSZsYW5nPWF1dG8tcnUiLHRydWUpOwoJYnJNTS5yZW1vdmVNZXNzYWdlTGlzdGVuZXIoJ2dldFNlbGVjdCcsbGlzdGVuZXIsdHJ1ZSk7Cgl9KTsKCWJyTU0ubG9hZEZyYW1lU2NyaXB0KCdkYXRhOixzZW5kQXN5bmNNZXNzYWdlKCJnZXRTZWxlY3QiLGNvbnRlbnQuZG9jdW1lbnQuZ2V0U2VsZWN0aW9uKCkudG9TdHJpbmcoKSknLGZhbHNlKTsKfSwKb3BlblByb3h5V2luID0gKF93aW4gPSBTZXJ2aWNlcy53bS5nZXRNb3N0UmVjZW50V2luZG93KCJhVGFCOlByb3h5V2luIikpID0+IHsKCWlmIChfd2luKSBfd2luLmZvY3VzKCkKCWVsc2UgewoJCV93aW4gPSBvcGVuRGlhbChbImNocm9tZTovL2Jyb3dzZXIvY29udGVudC9wcmVmZXJlbmNlcy9kaWFsb2dzL2Nvbm5lY3Rpb24ueGh0bWwiLCJfYmxhbmsiLCJjaHJvbWUsZGlhbG9nPW5vLGNlbnRlcnNjcmVlbixyZXNpemFibGUiXSk7CgkJX3dpbi5hZGRFdmVudExpc3RlbmVyKCJET01Db250ZW50TG9hZGVkIiwoKSA9PiB7CgkJCV93aW4uZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNldEF0dHJpYnV0ZSgid2luZG93dHlwZSIsImFUYUI6UHJveHlXaW4iKTsKCQl9LHtvbmNlOiB0cnVlfSk7CgkJX3dpbi5vcGVuZXIgPSB3aW5kb3c7IF93aW4ub3BlbmVyLmdTdWJEaWFsb2cgPSB7X2RpYWxvZ3M6IFtdfTt9Cn0sCkZhdkl0ZW0gPSAoZmlyc3QgPSB0cnVlLGRlZl91cmwgPSAndWEucnUnKSA9PiB7IC8v0L/QtdGA0LLRi9C5fNC/0L7RgdC7LiB1cmwg0JzQtdC90Y4g0LfQsNC60LvQsNC00L7QugoJdmFyIHF1ZXJ5ID0ge30sIG9wdGlvbnMgPSB7fSwgZm9sZGVyID0gUGxhY2VzVXRpbHMuaGlzdG9yeS5leGVjdXRlUXVlcnkocXVlcnkudmFsdWUsIG9wdGlvbnMudmFsdWUpLnJvb3Q7CglQbGFjZXNVdGlscy5oaXN0b3J5LnF1ZXJ5U3RyaW5nVG9RdWVyeShgcGxhY2U6cGFyZW50PSR7UGxhY2VzVXRpbHMuYm9va21hcmtzLm1lbnVHdWlkfSZleGNsdWRlUXVlcmllcz0xYCxxdWVyeSxvcHRpb25zKTsKCWZvbGRlci5jb250YWluZXJPcGVuID0gdHJ1ZTsKCXZhciBtYXggPSBmb2xkZXIuY2hpbGRDb3VudCAtIDEsIHR5cGUgPSBDaS5uc0lOYXZIaXN0b3J5UmVzdWx0Tm9kZS5SRVNVTFRfVFlQRV9VUkksIHVybDsKCWlmIChmaXJzdCkgZm9yKHZhciBpbmQgPSAwOyBpbmQgPD0gbWF4OyBpbmQrKykgeyAvLyBmaXJzdAoJCXZhciBub2RlID0gZm9sZGVyLmdldENoaWxkKGluZCk7CgkJaWYgKG5vZGUudHlwZSA9PSB0eXBlKSB7dXJsID0gbm9kZS51cmk7IGJyZWFrO30KCX0gZWxzZQkJZm9yKHZhciBpbmQgPSBtYXg7IDAgPD0gaW5kOyBpbmQtLSkgeyAvLyBsYXN0CgkJdmFyIG5vZGUgPSBmb2xkZXIuZ2V0Q2hpbGQoaW5kKTsKCQlpZiAobm9kZS50eXBlID09IHR5cGUpIHt1cmwgPSBub2RlLnVyaTsgYnJlYWs7fQoJfQoJaWYgKCF1cmwpIHVybCA9IGRlZl91cmw7IHJldHVybiB1cmw7Cn0sCnRvRmF2ID0gKCkgPT4ge3dpdGggKFBsYWNlc1V0aWxzLmJvb2ttYXJrcyl7IC8v0LHQtdC3INC00LjQsNC70L7Qs9CwCgl2YXIgdXJsID0gZ0Jyb3dzZXIuc2VsZWN0ZWRCcm93c2VyLmN1cnJlbnRVUkkuc3BlYzsKCXNlYXJjaCh7dXJsfSkudGhlbihhc3luYyBhcnJheSA9PiB7CgkJaWYgKGFycmF5Lmxlbmd0aCkKCQkJdHJ5IHthd2FpdCByZW1vdmUoYXJyYXkpO30gY2F0Y2gge30KCQllbHNlCgkJCXRyeSB7YXdhaXQgaW5zZXJ0KHsKCQkJCXVybDogU2VydmljZXMuaW8ubmV3VVJJKHVybCksCgkJCQl0aXRsZTogKGdCcm93c2VyLmNvbnRlbnRUaXRsZSB8fCBnQnJvd3Nlci5zZWxlY3RlZFRhYi5sYWJlbCB8fCB1cmwpLAoJCQkJcGFyZW50R3VpZDogWygpID0+IHRvb2xiYXJHdWlkLCAoKSA9PiBtZW51R3VpZCwgKCkgPT4gdW5maWxlZEd1aWRdW1NlcnZpY2VzLnByZWZzLmdldEludFByZWYoImJvb2ttYXJrc3BhcmVudGd1aWQiLDApXSgpLAoJCQkJaW5kZXg6IERFRkFVTFRfSU5ERVgKCQkJfSk7fSBjYXRjaCB7fQoJfSk7Cn19CmlmIChGZi5vcyA9PSAibWFjb3N4IikKCU9iamVjdC5rZXlzKFRhZykuZm9yRWFjaCgoayk9PnsgLy9pINGB0YfRkdGC0YfQuNC6LCDQt9Cw0LzQtdC90LAg0LHRg9C60LIKCQlbJ+KXiScsJ8OYJ10uZm9yRWFjaCgoYyxpKT0+e1RhZ1trXSA9IFRhZ1trXS5yZXBsYWNlKG5ldyBSZWdFeHAoYywnZycpLAoJCVsn4qa/Jywn4peOJ11baV0pfSl9KQplbHNlIGlmIChnbG9iLnByZWYoW0ZmLnAgKyd3aW5idXR0b25zJyxmYWxzZV0pKQoJCWNzc19VU0VSKCcudGl0bGViYXItYnV0dG9uYm94IHtkaXNwbGF5OiBub25lICFpbXBvcnRhbnR9JykKCWVsc2UgY3NzX1VTRVIoRmYuYyArImN1c3RvbV9zdHlsZXMvd2luX2J1dHRvbnMtdml0di5jc3MiKTsKCn0pKCAvL2luaXQt0LrQvtC0CkZmID0ge3A6J2V4dGVuc2lvbnMudXNlcl9jaHJvbWVfZmlsZXMuJywgYzonY2hyb21lOi8vdXNlcl9jaHJvbWVfZmlsZXMvY29udGVudC8nLCBpOidwZXJtaXNzaW9ucy5kZWZhdWx0LmltYWdlJywKCW9zOiBBcHBDb25zdGFudHMucGxhdGZvcm0sIHZlcjogU2VydmljZXMuYXBwaW5mby52ZXJzaW9uLnJlcGxhY2UoLy0uKi8sJycpLAoJQ3RyKG0gPSAi4oyYIiwgdyA9ICJDdHJsKyIpe3JldHVybiB0aGlzLm9zID09ICJtYWNvc3giID8gbSA6IHd9LAoJRXhwKCl7cmV0dXJuIE51bWJlcihTZXJ2aWNlcy5wcmVmcy5nZXRCb29sUHJlZih0aGlzLnAgKydleHBlcnQnLGZhbHNlKSl9Cn0sCihuYW1lLG0gPSBGZi5FeHAoKSwgdCx6KSA9PiB7IC8v4oCmIHvQntCx0YnQuNC577iw0K3QutGB0L/QtdGA0YIgKG0gPSAxKVvvuLDigKZdfQoJdCA9IFRhZ1tuYW1lXTsgeiA9IHQubWF0Y2goLyhceykoW1xzXFNdKj8pKFx9KS9nbSk7CglpZiAoeikgei5mb3JFYWNoKChrLGgpID0+eyAvL9GC0LXQutGB0YIg0LfQsNCy0LjRgdC40YIg0L7RgiDRgNC10LbQuNC80LAKCQloID0gay5zcGxpdCgn77iwJyk7IGlmIChoICYmIGgubGVuZ3RoID4gbSkKCQkJdCA9IHQucmVwbGFjZShrLGhbbV0ucmVwbGFjZSgvXHt8XH0vZywnJykpO30pCglyZXR1cm4gdDt9IC8v0YDQsNC30LTQtdC70LjRgtC10LvRjCDQuCDQvdGD0LbQvdCw0Y8g0YfQsNGB0YLRjCDihpEKKTs=

Отредактировано b0ttle (27-09-2023 00:17:44)

Отсутствует

 

№114327-09-2023 13:46:49

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 475
UA: Firefox 117.0

Re: UCF - ваши кнопки, скрипты…

для совместимости с Firefox 78-117 изменил UCF так (может, что-то можно сделать лучше…)

Выделить код

Код:

// фрагмент config.js для Firefox 78-117:
this.observe = (window, topic, data, icw) => {
	try {icw = (window instanceof Ci.nsIDOMChromeWindow);}
	catch {icw = (window .isChromeWindow)} //Ff116+
	if (!icw) return;
	var docElementInserted = e => {
		var win = e.target.defaultView;
		if (icw) user_chrome.initWindow(win);

// Services в jsm-скриптах для Firefox 78-117 подключается так:
if (typeof Services != "object")
	try{var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm")} catch{var {Services} = globalThis}

// Services в js-скриптах для Firefox 78-117:
if (typeof Services != "object")
	var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");

Отсутствует

 

№114427-09-2023 15:35:47

Farby
Участник
 
Группа: Members
Зарегистрирован: 21-11-2012
Сообщений: 311
UA: Google 2.1

Re: UCF - ваши кнопки, скрипты…

Dobrov
наверное можно так

скрытый текст

icw должна быть определена заранее

Выделить код

Код:

icw = window.isChromeWindow ? window.isChromeWindow : Ci.nsIDOMChromeWindow;
Выделить код

Код:

var Services = globalThis.Services || ChromeUtils.import("resource://gre/modules/Services.jsm").Services;


Жизнь иногда такое выкидывает, что хочется подобрать...

Отсутствует

 

№114527-09-2023 17:13:54

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 475
UA: Firefox 117.0

Re: UCF - ваши кнопки, скрипты…

Farby - значит, эти две строки создают одинаковый объект Services?


var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
var Services = ChromeUtils.import("resource://gre/modules/Services.jsm").Services;

Отсутствует

 

№114627-09-2023 17:47:21

Farby
Участник
 
Группа: Members
Зарегистрирован: 21-11-2012
Сообщений: 311
UA: Google 2.1

Re: UCF - ваши кнопки, скрипты…

Dobrov пишет

эти две строки создают одинаковый объект Services?

Да.

Кажется такая конструкция должна работать...

для config.js

Выделить код

Код:

if ((window.isChromeWindow) ? false : (window instanceof Ci.nsIDOMChromeWindow) ? false : true) return;

Добавлено 27-09-2023 18:02:12
Хотя проверил в [firefox] 58 конструкция window.isChromeWindow уже была...

Отредактировано Farby (27-09-2023 18:02:12)


Жизнь иногда такое выкидывает, что хочется подобрать...

Отсутствует

 

№114728-09-2023 05:03:04

rubel
Участник
 
Группа: Members
Откуда: г.Самара
Зарегистрирован: 10-05-2005
Сообщений: 570
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

Dumby
В 115 перестала нормально работать кнопка Восстановить.
В ней не раскрывается меню Недавно закрытые вкладки. В 91 все Ок.

скрытый текст

Выделить код

Код:

try {(() => {
    var id = "ucf-undo-tab",
    label = "Восстановить",
    tooltiptext = "ЛКМ: Восстановить вкладку\nПКМ: Восстановить окно",
    tooltiptextbtnmenu = "ЛКМ: Открыть меню\nПКМ: Показать весь журнал",
    img = "data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' height='16' width='16' viewBox='0 0 48 48'><g><rect x='0' y='0' width='48' height='48' rx='3' ry='3' style='fill:rgb(0, 120, 173);'/><path style='opacity:0.25;fill:black;' d='M 16,12 C 16,12 3,27 3,26.81 L 24.2,48 H 45 C 46.7,48 48,46.7 48,45 V 17.3 L 40,9.3 Z'/><path style='fill:white;' d='M 27.68,3.93 C 26.7,3.93 25.66,3.992 24.58,4.138 19.23,5.17 13.74,8.472 10.22,12.78 3.018,5.815 7.525,10.29 3.021,5.815 L 3,26.81 H 24.18 L 17.03,19.7 C 20.44,14.7 30.87,6.752 38.32,19.08 40.69,25.69 40.58,36.52 35.69,44 40.97,38.26 45.35,30.55 44.98,21.33 44.59,14.08 39.37,3.992 27.68,3.93' /></g></svg>",
    imgmenu = "data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' height='16' width='16' viewBox='0 0 48 48'><g><circle cy='24' cx='24' style='fill:rgb(0, 120, 173);' r='20'/><path style='opacity:0.25;fill:black;' d='M 33,41.8 22.3,31.1 36.7,17.9 44,25.2 C 43.5,30.6 41,37.7 33,41.8 Z'/><path style='fill:white;stroke:white;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;' d='M 35,19 H 13 L 24,30 35,19' /></g></svg>";

    CustomizableUI.createWidget({
        id: id,
        type: "custom",
        label: label,
        tooltiptext: tooltiptext,
        localized: false,
        defaultArea: CustomizableUI.AREA_NAVBAR,
        onBuild: function(document) {
            var win = document.defaultView, toolbaritem = document.createXULElement("toolbaritem");
            toolbaritem.id = id;
            toolbaritem.className = "chromeclass-toolbar-additional";
            toolbaritem.setAttribute("label", label);
            toolbaritem.setAttribute("type", "custom");
            var toolbarbutton_0 = document.createXULElement("toolbarbutton");
            toolbarbutton_0.id = `${id}-button`;
            toolbarbutton_0.className = "toolbarbutton-1";
            toolbarbutton_0.setAttribute("label", label);
            toolbarbutton_0.setAttribute("tooltiptext", tooltiptext);
            toolbarbutton_0.setAttribute("context", "false");
            toolbarbutton_0.addEventListener("click", function(event) {
                if (event.button == 0)
                    win.undoCloseTab();
                else if (event.button == 2) {
                    event.preventDefault();
                    event.stopPropagation();
                    win.undoCloseWindow();
                }
            });
            toolbaritem.append(toolbarbutton_0);
            var toolbarbutton_1 = document.createXULElement("toolbarbutton");
            toolbarbutton_1.id = `${id}-button-menu`;
            toolbarbutton_1.className = "toolbarbutton-1";
            toolbarbutton_1.setAttribute("type", "menu");
            toolbarbutton_1.setAttribute("label", "");
            toolbarbutton_1.setAttribute("tooltiptext", tooltiptextbtnmenu);
            toolbarbutton_1.setAttribute("context", "false");
            toolbarbutton_1.addEventListener("click", function(event) {
                if (event.button == 2) {
                    event.preventDefault();
                    event.stopPropagation();
                    win.PlacesCommandHook.showPlacesOrganizer("History");
                }
            });
            var menupopup_0 = document.createXULElement("menupopup");
            menupopup_0.id = `${id}-popup`;
            menupopup_0.setAttribute("tooltip", "bhTooltip");
            menupopup_0.setAttribute("popupsinherittooltip", true);
            menupopup_0.addEventListener("click", function(event) {
                event.stopPropagation();
            });
            menupopup_0.addEventListener("command", function(event) {
                event.stopPropagation();
            });
            var menu_0 = document.createXULElement("menu");
            menu_0.setAttribute("disabled", true);
            menu_0.setAttribute("label", "Недавно закрытые вкладки");
            var menupopup_1 = document.createXULElement("menupopup");
            menupopup_1.addEventListener("popupshowing", function(event) {
                while (menupopup_1.hasChildNodes())
                    menupopup_1.firstChild.remove();
                if (win == Services.appShell.hiddenDOMWindow || win.SessionStore.getClosedTabCount(win) == 0) {
                    menu_0.setAttribute("disabled", true);
                    return;
                }
                var tabsFragment = win.RecentlyClosedTabsAndWindowsMenuUtils.getTabsFragment(win, "menuitem");
                menupopup_1.append(tabsFragment);
                menu_0.removeAttribute("disabled");
            });
            menu_0.append(menupopup_1);
            menupopup_0.append(menu_0);
            var menu_1 = document.createXULElement("menu");
            menu_1.setAttribute("disabled", true);
            menu_1.setAttribute("label", "Недавно закрытые окна");
            var menupopup_2 = document.createXULElement("menupopup");
            menupopup_2.addEventListener("popupshowing", function(event) {
                while (menupopup_2.hasChildNodes())
                    menupopup_2.firstChild.remove();
                if (win.SessionStore.getClosedWindowCount() == 0) {
                    menu_1.setAttribute("disabled", true);
                    return;
                }
                var windowsFragment = win.RecentlyClosedTabsAndWindowsMenuUtils.getWindowsFragment(win, "menuitem");
                menupopup_2.append(windowsFragment);
                menu_1.removeAttribute("disabled");
            });
            menu_1.append(menupopup_2);
            menupopup_0.append(menu_1);
            menupopup_0.addEventListener("popupshowing", function(event) {
                if (win == Services.appShell.hiddenDOMWindow || win.SessionStore.getClosedTabCount(win) == 0)
                    menu_0.setAttribute("disabled", true);
                else
                    menu_0.removeAttribute("disabled");
                if (win.SessionStore.getClosedWindowCount() == 0)
                    menu_1.setAttribute("disabled", true);
                else
                    menu_1.removeAttribute("disabled");
            });
            var menuitem_0 = document.createXULElement("menuitem");
            menuitem_0.id = `${id}-all-history`;
            menuitem_0.setAttribute("label", "Показать весь журнал");
            menuitem_0.addEventListener("command", function(event) {
                event.stopPropagation();
                win.PlacesCommandHook.showPlacesOrganizer("History");
            });
            menupopup_0.append(menuitem_0);
            var menuitem_1 = document.createXULElement("menuitem");
            menuitem_1.setAttribute("label", "Удалить недавнюю историю…");
            menuitem_1.addEventListener("command", function(event) {
                event.stopPropagation();
                win.Sanitizer.showUI(win);
            });
            menupopup_0.append(menuitem_1);
            toolbarbutton_1.append(menupopup_0);
            toolbaritem.append(toolbarbutton_1);
            var btnstyle = "data:text/css;charset=utf-8," + encodeURIComponent(`
                #${id}-button {
                    list-style-image: url("${img}") !important;
                    -moz-image-region: rect(0px, 16px, 16px, 0px) !important;
                    margin-inline-end: 0 !important;
                }
                #${id}-button-menu {
                    list-style-image: url("${imgmenu}") !important;
                    -moz-image-region: rect(0px, 16px, 16px, 0px) !important;
                    margin-inline-start: 0px !important;
                }
                toolbarpaletteitem[place="palette"] #${id}-button-menu,
                #${id}-button-menu dropmarker {
                    display: none !important;
                }
                toolbarpaletteitem[place="palette"] #${id} {
                    -moz-box-orient: vertical !important;
                }
                #${id}-button-menu > .toolbarbutton-icon {
                    min-width: 0 !important;
                    max-width: none !important;
                    width: auto !important;
                    padding-left: 0 !important;
                    padding-right: 0 !important;
                }
            `);
            try {
                win.windowUtils.loadSheetUsingURIString(btnstyle, win.windowUtils.USER_SHEET);
            } catch (e) {}
            return toolbaritem;
        }
    });
})();} catch(e) {}

Отсутствует

 

№114828-09-2023 09:16:43

kokoss
Участник
 
Группа: Members
Зарегистрирован: 15-02-2018
Сообщений: 1746
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

rubel
Замените в коде -> getClosedTabCount -> в двух местах на ->  getClosedTabCountForWindow


Win7

Отсутствует

 

№114928-09-2023 09:42:03

rubel
Участник
 
Группа: Members
Откуда: г.Самара
Зарегистрирован: 10-05-2005
Сообщений: 570
UA: Firefox 115.0

Re: UCF - ваши кнопки, скрипты…

kokoss
Заменил, все прекрасно заработало. :)

Отсутствует

 

№115028-09-2023 15:32:00

Dobrov
Участник
 
Группа: Members
Зарегистрирован: 04-10-2011
Сообщений: 475
UA: Firefox 117.0

Re: UCF - ваши кнопки, скрипты…

rubel пишет

кнопка Восстановить – не раскрывается меню "Недавно закрытые вкладки"

У тебя старая версия. В новом коде строки Закрытых вкладок сразу в выпадающее меню кнопки добавляются.

Восстановить Закрытые вкладки/окна - модификация без dropmarker

Выделить код

Код:

try {(() => {
	var id = "ucf-undo-tab", label = "Закрытые вкладки/окна",
	tooltiptextbtnmenu = "ЛКМ: Открыть меню\nПКМ: Восстановить вкладку\nСКМ: Показать весь журнал";
	CustomizableUI.createWidget({
		id: id, label: label, type: "custom", localized: false,
		onBuild(doc) {
			var win = doc.defaultView, trim = doc.createXULElement("toolbaritem");
			trim.id = id;
			trim.className = "toolbaritem-combined-buttons ucf-toolbaritem-combined-buttons chromeclass-toolbar-additional";
			trim.setAttribute("label", label);
			trim.setAttribute("type", "custom");
			trim.style.setProperty("margin-inline","0");
			var trbn_1 = doc.createXULElement("toolbarbutton");
			trbn_1.id = `${id}-button-menu`;
			trbn_1.className = "toolbarbutton-1 ucf-toolbarbutton-combined-buttons-toolbarbutton";
			trbn_1.setAttribute("type", "menu");
			trbn_1.setAttribute("label", "");
			trbn_1.setAttribute("image", "data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' height='16' width='16' viewBox='0 0 48 48'><g><rect x='0' y='0' width='48' height='48' rx='3' ry='3' style='fill:rgb(0, 120, 173);'/><path style='opacity:0.25;fill:black;' d='M 16,12 C 16,12 3,27 3,26.81 L 24.2,48 H 45 C 46.7,48 48,46.7 48,45 V 17.3 L 40,9.3 Z'/><path style='fill:white;' d='M 27.68,3.93 C 26.7,3.93 25.66,3.992 24.58,4.138 19.23,5.17 13.74,8.472 10.22,12.78 3.018,5.815 7.525,10.29 3.021,5.815 L 3,26.81 H 24.18 L 17.03,19.7 C 20.44,14.7 30.87,6.752 38.32,19.08 40.69,25.69 40.58,36.52 35.69,44 40.97,38.26 45.35,30.55 44.98,21.33 44.59,14.08 39.37,3.992 27.68,3.93' /></g></svg>");
			trbn_1.setAttribute("tooltiptext", tooltiptextbtnmenu);
			trbn_1.setAttribute("context", "");
			trbn_1.addEventListener("click", e => {
				if (e.button == 1)
					win.PlacesCommandHook.showPlacesOrganizer("History");
				else if (e.button == 2) {
					e.preventDefault(); e.stopPropagation();
					win.undoCloseTab();
				}
			});
			var mupp_0 = doc.createXULElement("menupopup");
			mupp_0.id = `${id}-popup`;
			mupp_0.setAttribute("tooltip", "bhTooltip");
			mupp_0.setAttribute("popupsinherittooltip", true);
			mupp_0.addEventListener("click", e => {
				e.stopPropagation();
			});
			mupp_0.addEventListener("command", e => {
				e.stopPropagation();
			});
			var muim_0 = doc.createXULElement("menuitem");
			muim_0.id = `${id}-all-history`;
			muim_0.className = "ucf-menuitem";
			muim_0.setAttribute("label", "Показать весь журнал");
			muim_0.addEventListener("command", e => {
				e.stopPropagation();
				win.PlacesCommandHook.showPlacesOrganizer("History");
			});
			mupp_0.append(muim_0);
			var muim_1 = doc.createXULElement("menuitem");
			muim_1.id = `${id}-sanitize`;
			muim_1.className = "ucf-menuitem";
			muim_1.setAttribute("label", "Удалить недавнюю историю…");
			muim_1.addEventListener("command", e => {
				e.stopPropagation();
				win.Sanitizer.showUI(win);
			});
			mupp_0.append(muim_1);
			var muim_2 = doc.createXULElement("menuitem");
			muim_2.id = `${id}-session`;
			muim_2.className = "ucf-menuitem";
			muim_2.setAttribute("hidden", "true");
			muim_2.setAttribute("label", "Восстановить последнюю сессию");
			muim_2.addEventListener("command", e => {
				e.stopPropagation();
				win.SessionStore.restoreLastSession();
			});
			mupp_0.append(muim_2);
			var menu_0 = doc.createXULElement("menu");
			menu_0.id = `${id}-menu-closed-win`;
			menu_0.setAttribute("hidden", "true");
			menu_0.setAttribute("label", "Недавно закрытые окна");
			var mupp_1 = doc.createXULElement("menupopup");
			var muim_3 = doc.createXULElement("menuitem");
			muim_3.id = `${id}-item-closed-win`;
			muim_3.className = "ucf-menuitem";
			muim_3.setAttribute("hidden", "true");
			muim_3.setAttribute("label", "Забыть закрытые окна");
			muim_3.addEventListener("command", e => {
				e.stopPropagation();
				var sessionStore = win.SessionStore;
				var count = sessionStore.getClosedWindowCount();
				while(count--)
					sessionStore.forgetClosedWindow(0);
			});
			mupp_1.append(muim_3);
			var musr_0 = doc.createXULElement("menuseparator");
			musr_0.id = `${id}-sep-closed-win`;
			musr_0.className = "ucf-menuseparator";
			musr_0.setAttribute("hidden", "true");
			mupp_1.append(musr_0);
			mupp_1.addEventListener("popupshowing", e => {
				e.stopPropagation();
				for (let item of mupp_1.querySelectorAll(":scope > :is(menuitem:not(.ucf-menuitem), menuseparator:not(.ucf-menuseparator))"))
					item.remove();
				if (win.SessionStore.getClosedWindowCount() == 0) {
					muim_3.setAttribute("hidden", "true");
					musr_0.setAttribute("hidden", "true");
					return;
				}
				if ("RecentlyClosedTabsAndWindowsMenuUtils" in win) {
					muim_3.removeAttribute("hidden");
					musr_0.removeAttribute("hidden");
					var windowsFragment = win.RecentlyClosedTabsAndWindowsMenuUtils.getWindowsFragment(win, "menuitem");
					mupp_1.append(windowsFragment);
					menu_0.removeAttribute("hidden");
				}
			});
			menu_0.append(mupp_1);
			mupp_0.append(menu_0);
			var musr_1 = doc.createXULElement("menuseparator");
			musr_1.className = "ucf-menuseparator";
			musr_1.setAttribute("hidden", "true");
			mupp_0.append(musr_1);
			var muim_4 = doc.createXULElement("menuitem");
			muim_4.id = `${id}-item-closed-tabs`;
			muim_4.className = "ucf-menuitem";
			muim_4.setAttribute("hidden", "true");
			muim_4.setAttribute("label", "Забыть закрытые вкладки");
			muim_4.addEventListener("command", e => {
				e.stopPropagation();
				var sessionStore = win.SessionStore, count;
				try{count = sessionStore.getClosedTabCountForWindow(win);} catch(e){count = sessionStore.getClosedTabCount(win)}
				while(count--)
					sessionStore.forgetClosedTab(win, 0);
			});
			mupp_0.append(muim_4);
			var musr_2 = doc.createXULElement("menuseparator");
			musr_2.id = `${id}-sep-closed-tabs`;
			musr_2.className = "ucf-menuseparator";
			musr_2.setAttribute("hidden", "true");
			mupp_0.append(musr_2);
			mupp_0.addEventListener("popupshowing", e => {
				var sessionStore = win.SessionStore;
				if (sessionStore.getClosedWindowCount() == 0)
					menu_0.setAttribute("hidden", "true");
				else
					menu_0.removeAttribute("hidden");
				if (!sessionStore.canRestoreLastSession)
					muim_2.setAttribute("hidden", "true");
				else
					muim_2.removeAttribute("hidden");
				for (let item of mupp_0.querySelectorAll(":scope > :is(menuitem:not(.ucf-menuitem), menuseparator:not(.ucf-menuseparator))"))
					item.remove();
				try{var sSgCTC = sessionStore.getClosedTabCountForWindow(win);} catch(e){var sSgCTC = sessionStore.getClosedTabCount(win)}
				if (win == Services.appShell.hiddenDOMWindow || sSgCTC == 0) {
					musr_1.setAttribute("hidden", "true");
					muim_4.setAttribute("hidden", "true");
					musr_2.setAttribute("hidden", "true");
					return;
				}
				if ("RecentlyClosedTabsAndWindowsMenuUtils" in win) {
					musr_1.removeAttribute("hidden");
					muim_4.removeAttribute("hidden");
					musr_2.removeAttribute("hidden");
					var tabsFragment = win.RecentlyClosedTabsAndWindowsMenuUtils.getTabsFragment(win, "menuitem");
					mupp_0.append(tabsFragment);
				}
			});
			trbn_1.append(mupp_0);
			trim.append(trbn_1);
			return trim;
		}
	});
})()} catch(e){}

Ошибки исправлены, копка теперь пашет на версиях Firefox от 84 (может и меньше) до Firefox 118.
Напомню, что в Шапке есть  Ссылка на обновляемые скрипты

Отредактировано Dobrov (29-09-2023 03:49:02)

Отсутствует

 

Board footer

Powered by PunBB
Modified by Mozilla Russia
Copyright © 2004–2020 Mozilla Russia GitHub mark
Язык отображения форума: [Русский] [English]