quickwin 2.1.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +9 -9
- package/README.md +9 -9
- package/constants.ts +1063 -0
- package/enum_map.d.ts +129 -0
- package/examples/PdfCanvas.js +2 -2
- package/examples/PdfCanvas.tsx +3 -2
- package/examples/{exec_server.js → execd/main.js} +1114 -287
- package/examples/execd/tray.js +192 -0
- package/examples/execd/worker.js +122 -0
- package/examples/pdf_preview2.js +46 -46
- package/examples/pdf_preview2.ts +55 -54
- package/examples/pdf_viewer.js +134 -130
- package/examples/pdf_viewer.tsx +6 -5
- package/examples/test_gallery.js +135 -131
- package/examples/test_gallery.tsx +9 -8
- package/examples/test_react_lazy.js +130 -128
- package/examples/test_react_lazy.tsx +7 -6
- package/examples/test_react_listbox.js +130 -128
- package/examples/test_react_listbox.tsx +8 -7
- package/examples/test_root_window.js +130 -128
- package/examples/test_root_window.tsx +5 -5
- package/examples/test_tab.js +130 -128
- package/examples/test_tab.tsx +7 -6
- package/examples/tray_demo.js +8 -8
- package/examples/tray_demo.tsx +9 -8
- package/lib/dumpRects.js +2 -2
- package/lib/dumpRects.ts +3 -2
- package/lib/fetch.js +15 -15
- package/lib/fetch.ts +16 -15
- package/lib/ffi/bind.js +3 -3
- package/lib/ffi/bind.ts +3 -3
- package/lib/ffi/ctype.ts +3 -1
- package/lib/ffi/struct.js +23 -7
- package/lib/ffi/struct.ts +50 -23
- package/lib/http-server.js +5 -5
- package/lib/http-server.ts +6 -5
- package/lib/react-qw/components/Button.js +2 -2
- package/lib/react-qw/components/CheckBox.js +4 -4
- package/lib/react-qw/components/ComboBox.js +10 -10
- package/lib/react-qw/components/DateTimePicker.js +12 -12
- package/lib/react-qw/components/Input.js +7 -7
- package/lib/react-qw/components/Link.js +4 -4
- package/lib/react-qw/components/ListBox.js +12 -12
- package/lib/react-qw/components/ListView.js +35 -35
- package/lib/react-qw/components/PathPicker.js +3 -3
- package/lib/react-qw/components/ProgressBar.js +4 -4
- package/lib/react-qw/components/RadioButton.js +4 -4
- package/lib/react-qw/components/ScrollView.js +28 -28
- package/lib/react-qw/components/Slider.js +11 -11
- package/lib/react-qw/components/Tab.js +10 -10
- package/lib/react-qw/components/Tooltip.js +8 -8
- package/lib/react-qw/components/TreeView.js +20 -20
- package/lib/react-qw/index.js +5 -5
- package/lib/react-qw/index.ts +6 -5
- package/lib/react-qw/props.js +4 -4
- package/lib/react-qw/props.ts +5 -4
- package/lib/react-qw/reconciler.js +10 -10
- package/lib/react-qw/reconciler.ts +11 -10
- package/lib/text-measure.js +3 -3
- package/lib/text-measure.ts +4 -3
- package/lib/websocket.js +17 -17
- package/lib/websocket.ts +18 -17
- package/lib/windows/advapi32.js +7 -7
- package/lib/windows/advapi32.ts +7 -7
- package/lib/windows/gdi32.js +17 -17
- package/lib/windows/gdi32.ts +17 -17
- package/lib/windows/kernel32.js +41 -2
- package/lib/windows/kernel32.ts +45 -2
- package/lib/windows/shell32.js +24 -3
- package/lib/windows/shell32.ts +27 -4
- package/lib/windows/structs.js +230 -92
- package/lib/windows/structs.ts +278 -92
- package/lib/windows/user32.js +18 -6
- package/lib/windows/user32.ts +18 -6
- package/lib/windows/winspool.js +3 -3
- package/lib/windows/winspool.ts +3 -3
- package/package.json +4 -3
- package/quickwin.d.ts +32 -10
- package/qwin-nowasm-x86.exe +0 -0
- package/qwin-nowasm.exe +0 -0
- package/qwin-x86.exe +0 -0
- package/qwin.exe +0 -0
- package/test/test_ffi_bind.js +12 -10
- package/test/test_ffi_bind.ts +14 -12
- package/test/test_ffi_struct.js +60 -26
- package/test/test_ffi_struct.ts +58 -28
- package/test/test_ffi_windows.js +1 -1
- package/test/test_ffi_windows.ts +1 -1
- package/test/test_files.js +7 -7
- package/test/test_files.ts +8 -8
- package/test/test_gdi_draw.js +51 -51
- package/test/test_gdi_draw.ts +57 -57
- package/test/test_http_server.js +3 -3
- package/test/test_http_server.ts +4 -3
- package/test/test_ipv6.js +3 -3
- package/test/test_ipv6.ts +4 -3
- package/test/test_net_event.js +3 -3
- package/test/test_net_event.ts +4 -3
- package/test/test_printer.js +4 -4
- package/test/test_printer.ts +5 -5
- package/test/test_react_complex.js +132 -130
- package/test/test_react_counter.js +130 -128
- package/test/test_react_flex.js +132 -130
- package/test/test_react_hidden.js +130 -128
- package/test/test_react_listview_link.js +131 -129
- package/test/test_react_notify.js +148 -146
- package/test/test_react_render.js +130 -128
- package/test/test_registry.js +6 -6
- package/test/test_registry.ts +8 -8
- package/test/test_wolfssl_read.js +8 -8
- package/test/test_wolfssl_read.ts +9 -8
- package/examples/exec_server.tsx +0 -488
- package/examples/exec_server_worker.js +0 -395
- package/examples/exec_server_worker.ts +0 -417
- package/examples/setres.js +0 -79
- package/examples/setres.ts +0 -86
- package/quickwin_const.d.ts +0 -1037
|
@@ -1367,9 +1367,9 @@ var require_scheduler_development = __commonJS({
|
|
|
1367
1367
|
}
|
|
1368
1368
|
return first;
|
|
1369
1369
|
}
|
|
1370
|
-
function compare(a2,
|
|
1371
|
-
var diff = a2.sortIndex -
|
|
1372
|
-
return 0 !== diff ? diff : a2.id -
|
|
1370
|
+
function compare(a2, b8) {
|
|
1371
|
+
var diff = a2.sortIndex - b8.sortIndex;
|
|
1372
|
+
return 0 !== diff ? diff : a2.id - b8.id;
|
|
1373
1373
|
}
|
|
1374
1374
|
function advanceTimers(currentTime) {
|
|
1375
1375
|
for (var timer = peek(timerQueue); null !== timer; ) {
|
|
@@ -1667,14 +1667,14 @@ var require_react_reconciler_development = __commonJS({
|
|
|
1667
1667
|
throw Error("Unable to find node on an unmounted component.");
|
|
1668
1668
|
return alternate !== fiber ? null : fiber;
|
|
1669
1669
|
}
|
|
1670
|
-
for (var a2 = fiber,
|
|
1670
|
+
for (var a2 = fiber, b8 = alternate; ; ) {
|
|
1671
1671
|
var parentA = a2.return;
|
|
1672
1672
|
if (null === parentA) break;
|
|
1673
1673
|
var parentB = parentA.alternate;
|
|
1674
1674
|
if (null === parentB) {
|
|
1675
|
-
|
|
1676
|
-
if (null !==
|
|
1677
|
-
a2 =
|
|
1675
|
+
b8 = parentA.return;
|
|
1676
|
+
if (null !== b8) {
|
|
1677
|
+
a2 = b8;
|
|
1678
1678
|
continue;
|
|
1679
1679
|
}
|
|
1680
1680
|
break;
|
|
@@ -1682,23 +1682,23 @@ var require_react_reconciler_development = __commonJS({
|
|
|
1682
1682
|
if (parentA.child === parentB.child) {
|
|
1683
1683
|
for (parentB = parentA.child; parentB; ) {
|
|
1684
1684
|
if (parentB === a2) return assertIsMounted(parentA), fiber;
|
|
1685
|
-
if (parentB ===
|
|
1685
|
+
if (parentB === b8) return assertIsMounted(parentA), alternate;
|
|
1686
1686
|
parentB = parentB.sibling;
|
|
1687
1687
|
}
|
|
1688
1688
|
throw Error("Unable to find node on an unmounted component.");
|
|
1689
1689
|
}
|
|
1690
|
-
if (a2.return !==
|
|
1690
|
+
if (a2.return !== b8.return) a2 = parentA, b8 = parentB;
|
|
1691
1691
|
else {
|
|
1692
1692
|
for (var didFindChild = false, _child = parentA.child; _child; ) {
|
|
1693
1693
|
if (_child === a2) {
|
|
1694
1694
|
didFindChild = true;
|
|
1695
1695
|
a2 = parentA;
|
|
1696
|
-
|
|
1696
|
+
b8 = parentB;
|
|
1697
1697
|
break;
|
|
1698
1698
|
}
|
|
1699
|
-
if (_child ===
|
|
1699
|
+
if (_child === b8) {
|
|
1700
1700
|
didFindChild = true;
|
|
1701
|
-
|
|
1701
|
+
b8 = parentA;
|
|
1702
1702
|
a2 = parentB;
|
|
1703
1703
|
break;
|
|
1704
1704
|
}
|
|
@@ -1709,12 +1709,12 @@ var require_react_reconciler_development = __commonJS({
|
|
|
1709
1709
|
if (_child === a2) {
|
|
1710
1710
|
didFindChild = true;
|
|
1711
1711
|
a2 = parentB;
|
|
1712
|
-
|
|
1712
|
+
b8 = parentA;
|
|
1713
1713
|
break;
|
|
1714
1714
|
}
|
|
1715
|
-
if (_child ===
|
|
1715
|
+
if (_child === b8) {
|
|
1716
1716
|
didFindChild = true;
|
|
1717
|
-
|
|
1717
|
+
b8 = parentB;
|
|
1718
1718
|
a2 = parentA;
|
|
1719
1719
|
break;
|
|
1720
1720
|
}
|
|
@@ -1726,7 +1726,7 @@ var require_react_reconciler_development = __commonJS({
|
|
|
1726
1726
|
);
|
|
1727
1727
|
}
|
|
1728
1728
|
}
|
|
1729
|
-
if (a2.alternate !==
|
|
1729
|
+
if (a2.alternate !== b8)
|
|
1730
1730
|
throw Error(
|
|
1731
1731
|
"Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue."
|
|
1732
1732
|
);
|
|
@@ -15071,10 +15071,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
15071
15071
|
setCurrentUpdatePriority(previousPriority), ReactSharedInternals.T = prevTransition;
|
|
15072
15072
|
}
|
|
15073
15073
|
};
|
|
15074
|
-
exports2.discreteUpdates = function(fn, a2,
|
|
15074
|
+
exports2.discreteUpdates = function(fn, a2, b8, c2, d2) {
|
|
15075
15075
|
var prevTransition = ReactSharedInternals.T, previousPriority = getCurrentUpdatePriority();
|
|
15076
15076
|
try {
|
|
15077
|
-
return setCurrentUpdatePriority(2), ReactSharedInternals.T = null, fn(a2,
|
|
15077
|
+
return setCurrentUpdatePriority(2), ReactSharedInternals.T = null, fn(a2, b8, c2, d2);
|
|
15078
15078
|
} finally {
|
|
15079
15079
|
setCurrentUpdatePriority(previousPriority), ReactSharedInternals.T = prevTransition, executionContext === NoContext && (workInProgressRootRenderTargetTime = now$1() + RENDER_TIMEOUT_MS);
|
|
15080
15080
|
}
|
|
@@ -15353,7 +15353,7 @@ var require_constants = __commonJS({
|
|
|
15353
15353
|
}
|
|
15354
15354
|
});
|
|
15355
15355
|
|
|
15356
|
-
// _build/examples/
|
|
15356
|
+
// _build/examples/execd/main.js
|
|
15357
15357
|
var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
15358
15358
|
|
|
15359
15359
|
// _build/lib/polyfill.js
|
|
@@ -15514,7 +15514,7 @@ var URLSearchParamsImpl = class {
|
|
|
15514
15514
|
this._list.push([key, value]);
|
|
15515
15515
|
}
|
|
15516
15516
|
sort() {
|
|
15517
|
-
this._list.sort(([a2], [
|
|
15517
|
+
this._list.sort(([a2], [b8]) => a2 < b8 ? -1 : a2 > b8 ? 1 : 0);
|
|
15518
15518
|
}
|
|
15519
15519
|
forEach(fn) {
|
|
15520
15520
|
for (const [k2, v2] of this._list)
|
|
@@ -15564,43 +15564,43 @@ var URLImpl = class _URLImpl {
|
|
|
15564
15564
|
}
|
|
15565
15565
|
if (base === void 0)
|
|
15566
15566
|
throw new TypeError("Invalid URL");
|
|
15567
|
-
const
|
|
15567
|
+
const b8 = new _URLImpl(base);
|
|
15568
15568
|
if (p2.host) {
|
|
15569
|
-
p2.scheme =
|
|
15569
|
+
p2.scheme = b8._scheme;
|
|
15570
15570
|
this._apply(p2);
|
|
15571
15571
|
return;
|
|
15572
15572
|
}
|
|
15573
15573
|
if (!p2.path && !p2.query) {
|
|
15574
15574
|
this._apply({
|
|
15575
|
-
scheme:
|
|
15576
|
-
user:
|
|
15577
|
-
pass:
|
|
15578
|
-
host:
|
|
15579
|
-
port:
|
|
15580
|
-
path:
|
|
15581
|
-
query:
|
|
15575
|
+
scheme: b8._scheme,
|
|
15576
|
+
user: b8._username,
|
|
15577
|
+
pass: b8._password,
|
|
15578
|
+
host: b8._hostname,
|
|
15579
|
+
port: b8._port,
|
|
15580
|
+
path: b8._pathname,
|
|
15581
|
+
query: b8._query,
|
|
15582
15582
|
fragment: p2.fragment || ""
|
|
15583
15583
|
});
|
|
15584
15584
|
return;
|
|
15585
15585
|
}
|
|
15586
|
-
p2.scheme =
|
|
15586
|
+
p2.scheme = b8._scheme;
|
|
15587
15587
|
if (!p2.user)
|
|
15588
|
-
p2.user =
|
|
15588
|
+
p2.user = b8._username;
|
|
15589
15589
|
if (!p2.pass)
|
|
15590
|
-
p2.pass =
|
|
15590
|
+
p2.pass = b8._password;
|
|
15591
15591
|
if (!p2.host)
|
|
15592
|
-
p2.host =
|
|
15592
|
+
p2.host = b8._hostname;
|
|
15593
15593
|
if (!p2.port)
|
|
15594
|
-
p2.port =
|
|
15594
|
+
p2.port = b8._port;
|
|
15595
15595
|
if (!p2.fragment)
|
|
15596
15596
|
p2.fragment = "";
|
|
15597
15597
|
if (p2.path && !p2.path.startsWith("/")) {
|
|
15598
|
-
const bd =
|
|
15598
|
+
const bd = b8._pathname.substring(0, b8._pathname.lastIndexOf("/") + 1);
|
|
15599
15599
|
p2.path = _normalizePath(bd + p2.path);
|
|
15600
15600
|
} else if (!p2.path) {
|
|
15601
|
-
p2.path =
|
|
15601
|
+
p2.path = b8._pathname;
|
|
15602
15602
|
if (!p2.query)
|
|
15603
|
-
p2.query =
|
|
15603
|
+
p2.query = b8._query;
|
|
15604
15604
|
}
|
|
15605
15605
|
this._apply(p2);
|
|
15606
15606
|
}
|
|
@@ -15705,19 +15705,19 @@ function _normalizeLabel(label) {
|
|
|
15705
15705
|
function _decodeUTF8(buf, fatal) {
|
|
15706
15706
|
let out = "";
|
|
15707
15707
|
for (let i2 = 0; i2 < buf.length; ) {
|
|
15708
|
-
const
|
|
15709
|
-
if (
|
|
15710
|
-
out += String.fromCharCode(
|
|
15708
|
+
const b8 = buf[i2++];
|
|
15709
|
+
if (b8 < 128) {
|
|
15710
|
+
out += String.fromCharCode(b8);
|
|
15711
15711
|
continue;
|
|
15712
15712
|
}
|
|
15713
|
-
if (
|
|
15713
|
+
if (b8 < 192) {
|
|
15714
15714
|
out += fatal ? (() => {
|
|
15715
15715
|
throw new TypeError("unexpected continuation byte");
|
|
15716
15716
|
})() : "\uFFFD";
|
|
15717
15717
|
continue;
|
|
15718
15718
|
}
|
|
15719
15719
|
let c2, min;
|
|
15720
|
-
if (
|
|
15720
|
+
if (b8 < 224) {
|
|
15721
15721
|
if (i2 >= buf.length) {
|
|
15722
15722
|
out += fatal ? (() => {
|
|
15723
15723
|
throw new TypeError("incomplete utf-8");
|
|
@@ -15729,9 +15729,9 @@ function _decodeUTF8(buf, fatal) {
|
|
|
15729
15729
|
out += "\uFFFD";
|
|
15730
15730
|
continue;
|
|
15731
15731
|
}
|
|
15732
|
-
c2 = (
|
|
15732
|
+
c2 = (b8 & 31) << 6 | b22 & 63;
|
|
15733
15733
|
min = 128;
|
|
15734
|
-
} else if (
|
|
15734
|
+
} else if (b8 < 240) {
|
|
15735
15735
|
if (i2 + 1 >= buf.length) {
|
|
15736
15736
|
out += fatal ? (() => {
|
|
15737
15737
|
throw new TypeError("incomplete utf-8");
|
|
@@ -15744,9 +15744,9 @@ function _decodeUTF8(buf, fatal) {
|
|
|
15744
15744
|
out += "\uFFFD";
|
|
15745
15745
|
continue;
|
|
15746
15746
|
}
|
|
15747
|
-
c2 = (
|
|
15747
|
+
c2 = (b8 & 15) << 12 | (b22 & 63) << 6 | b32 & 63;
|
|
15748
15748
|
min = 2048;
|
|
15749
|
-
} else if (
|
|
15749
|
+
} else if (b8 < 248) {
|
|
15750
15750
|
if (i2 + 2 >= buf.length) {
|
|
15751
15751
|
out += fatal ? (() => {
|
|
15752
15752
|
throw new TypeError("incomplete utf-8");
|
|
@@ -15760,7 +15760,7 @@ function _decodeUTF8(buf, fatal) {
|
|
|
15760
15760
|
out += "\uFFFD";
|
|
15761
15761
|
continue;
|
|
15762
15762
|
}
|
|
15763
|
-
c2 = (
|
|
15763
|
+
c2 = (b8 & 7) << 18 | (b22 & 63) << 12 | (b32 & 63) << 6 | b42 & 63;
|
|
15764
15764
|
min = 65536;
|
|
15765
15765
|
} else {
|
|
15766
15766
|
out += fatal ? (() => {
|
|
@@ -15940,31 +15940,31 @@ function sha1Bytes(bytes) {
|
|
|
15940
15940
|
for (let t2 = 16; t2 < 80; t2++) {
|
|
15941
15941
|
w2[t2] = rotl(w2[t2 - 3] ^ w2[t2 - 8] ^ w2[t2 - 14] ^ w2[t2 - 16], 1);
|
|
15942
15942
|
}
|
|
15943
|
-
let a2 = h0,
|
|
15943
|
+
let a2 = h0, b8 = h1, c2 = h2, d2 = h3, e2 = h4;
|
|
15944
15944
|
for (let t2 = 0; t2 < 80; t2++) {
|
|
15945
15945
|
let f2, k2;
|
|
15946
15946
|
if (t2 < 20) {
|
|
15947
|
-
f2 =
|
|
15947
|
+
f2 = b8 & c2 | ~b8 & d2;
|
|
15948
15948
|
k2 = 1518500249;
|
|
15949
15949
|
} else if (t2 < 40) {
|
|
15950
|
-
f2 =
|
|
15950
|
+
f2 = b8 ^ c2 ^ d2;
|
|
15951
15951
|
k2 = 1859775393;
|
|
15952
15952
|
} else if (t2 < 60) {
|
|
15953
|
-
f2 =
|
|
15953
|
+
f2 = b8 & c2 | b8 & d2 | c2 & d2;
|
|
15954
15954
|
k2 = 2400959708;
|
|
15955
15955
|
} else {
|
|
15956
|
-
f2 =
|
|
15956
|
+
f2 = b8 ^ c2 ^ d2;
|
|
15957
15957
|
k2 = 3395469782;
|
|
15958
15958
|
}
|
|
15959
15959
|
const temp = rotl(a2, 5) + f2 + e2 + k2 + w2[t2] >>> 0;
|
|
15960
15960
|
e2 = d2;
|
|
15961
15961
|
d2 = c2;
|
|
15962
|
-
c2 = rotl(
|
|
15963
|
-
|
|
15962
|
+
c2 = rotl(b8, 30);
|
|
15963
|
+
b8 = a2;
|
|
15964
15964
|
a2 = temp;
|
|
15965
15965
|
}
|
|
15966
15966
|
h0 = h0 + a2 >>> 0;
|
|
15967
|
-
h1 = h1 +
|
|
15967
|
+
h1 = h1 + b8 >>> 0;
|
|
15968
15968
|
h2 = h2 + c2 >>> 0;
|
|
15969
15969
|
h3 = h3 + d2 >>> 0;
|
|
15970
15970
|
h4 = h4 + e2 >>> 0;
|
|
@@ -17513,7 +17513,7 @@ function Er(e2) {
|
|
|
17513
17513
|
function Wr(e2, t2) {
|
|
17514
17514
|
return Oe(e2._readableStreamController) ? (function(e3) {
|
|
17515
17515
|
let t3, r2, o2, n2, i2, a2 = V(e3), s2 = false, l2 = false, d2 = false, f2 = false, h2 = false;
|
|
17516
|
-
const
|
|
17516
|
+
const b8 = u((e4) => {
|
|
17517
17517
|
i2 = e4;
|
|
17518
17518
|
});
|
|
17519
17519
|
function m2(e4) {
|
|
@@ -17583,14 +17583,14 @@ function Wr(e2, t2) {
|
|
|
17583
17583
|
const o4 = le([t3, r2]), n3 = Mr(e3, o4);
|
|
17584
17584
|
i2(n3);
|
|
17585
17585
|
}
|
|
17586
|
-
return
|
|
17586
|
+
return b8;
|
|
17587
17587
|
}
|
|
17588
17588
|
function R2(o3) {
|
|
17589
17589
|
if (h2 = true, r2 = o3, f2) {
|
|
17590
17590
|
const o4 = le([t3, r2]), n3 = Mr(e3, o4);
|
|
17591
17591
|
i2(n3);
|
|
17592
17592
|
}
|
|
17593
|
-
return
|
|
17593
|
+
return b8;
|
|
17594
17594
|
}
|
|
17595
17595
|
function T2() {
|
|
17596
17596
|
}
|
|
@@ -17601,14 +17601,14 @@ function Wr(e2, t2) {
|
|
|
17601
17601
|
const h2 = u((e4) => {
|
|
17602
17602
|
a2 = e4;
|
|
17603
17603
|
});
|
|
17604
|
-
function
|
|
17604
|
+
function b8() {
|
|
17605
17605
|
if (s2) return l2 = true, c(void 0);
|
|
17606
17606
|
s2 = true;
|
|
17607
17607
|
return te(t3, { _chunkSteps: (e4) => {
|
|
17608
17608
|
y(() => {
|
|
17609
17609
|
l2 = false;
|
|
17610
17610
|
const t4 = e4, r3 = e4;
|
|
17611
|
-
d2 || Rr(n2._readableStreamController, t4), f2 || Rr(i2._readableStreamController, r3), s2 = false, l2 &&
|
|
17611
|
+
d2 || Rr(n2._readableStreamController, t4), f2 || Rr(i2._readableStreamController, r3), s2 = false, l2 && b8();
|
|
17612
17612
|
});
|
|
17613
17613
|
}, _closeSteps: () => {
|
|
17614
17614
|
s2 = false, d2 || wr(n2._readableStreamController), f2 || wr(i2._readableStreamController), d2 && f2 || a2(void 0);
|
|
@@ -17632,7 +17632,7 @@ function Wr(e2, t2) {
|
|
|
17632
17632
|
}
|
|
17633
17633
|
function S2() {
|
|
17634
17634
|
}
|
|
17635
|
-
return n2 = Dr(S2,
|
|
17635
|
+
return n2 = Dr(S2, b8, m2), i2 = Dr(S2, b8, p2), _(t3._closedPromise, (e4) => (Tr(n2._readableStreamController, e4), Tr(i2._readableStreamController, e4), d2 && f2 || a2(void 0), null)), [n2, i2];
|
|
17636
17636
|
})(e2);
|
|
17637
17637
|
}
|
|
17638
17638
|
function Or(r2) {
|
|
@@ -17941,7 +17941,7 @@ var TransformStream = class {
|
|
|
17941
17941
|
if (void 0 !== i2.readableType) throw new RangeError("Invalid readableType specified");
|
|
17942
17942
|
if (void 0 !== i2.writableType) throw new RangeError("Invalid writableType specified");
|
|
17943
17943
|
const a2 = mt(n2, 0), s2 = pt(n2), l2 = mt(o2, 1), f2 = pt(o2);
|
|
17944
|
-
let
|
|
17944
|
+
let b8;
|
|
17945
17945
|
!(function(e3, t3, r3, o3, n3, i3) {
|
|
17946
17946
|
function a3() {
|
|
17947
17947
|
return t3;
|
|
@@ -18005,7 +18005,7 @@ var TransformStream = class {
|
|
|
18005
18005
|
return Ct(a4), Nt(a4, Object.create(WritableStreamDefaultController.prototype), e4, t4, r4, o4, n4, i4), a4;
|
|
18006
18006
|
})(a3, s3, c2, l3, r3, o3), e3._readable = Dr(a3, d2, f3, n3, i3), e3._backpressure = void 0, e3._backpressureChangePromise = void 0, e3._backpressureChangePromise_resolve = void 0, ao(e3, true), e3._transformStreamController = void 0;
|
|
18007
18007
|
})(this, u((e3) => {
|
|
18008
|
-
|
|
18008
|
+
b8 = e3;
|
|
18009
18009
|
}), l2, f2, a2, s2), (function(e3, t3) {
|
|
18010
18010
|
const r3 = Object.create(TransformStreamDefaultController.prototype);
|
|
18011
18011
|
let o3, n3, i3;
|
|
@@ -18021,7 +18021,7 @@ var TransformStream = class {
|
|
|
18021
18021
|
!(function(e4, t4, r4, o4, n4) {
|
|
18022
18022
|
t4._controlledTransformStream = e4, e4._transformStreamController = t4, t4._transformAlgorithm = r4, t4._flushAlgorithm = o4, t4._cancelAlgorithm = n4, t4._finishPromise = void 0, t4._finishPromise_resolve = void 0, t4._finishPromise_reject = void 0;
|
|
18023
18023
|
})(e3, r3, o3, n3, i3);
|
|
18024
|
-
})(this, i2), void 0 !== i2.start ?
|
|
18024
|
+
})(this, i2), void 0 !== i2.start ? b8(i2.start(this._transformStreamController)) : b8(void 0);
|
|
18025
18025
|
}
|
|
18026
18026
|
get readable() {
|
|
18027
18027
|
if (!ro(this)) throw _o("readable");
|
|
@@ -19044,10 +19044,10 @@ async function sendResponse(c2, method, res) {
|
|
|
19044
19044
|
await writeStreamingBody(c2, res.body, chunked, chunked && trailerDeclared ? res.trailers : void 0);
|
|
19045
19045
|
}
|
|
19046
19046
|
|
|
19047
|
-
// _build/examples/
|
|
19048
|
-
import * as
|
|
19047
|
+
// _build/examples/execd/main.js
|
|
19048
|
+
import * as os7 from "os";
|
|
19049
19049
|
import * as std2 from "std";
|
|
19050
|
-
import * as
|
|
19050
|
+
import * as gui19 from "gui";
|
|
19051
19051
|
|
|
19052
19052
|
// _build/lib/exec-log.js
|
|
19053
19053
|
var RequestLog = class {
|
|
@@ -19466,6 +19466,75 @@ function bind2(dll, name, sig, encoders, decoders) {
|
|
|
19466
19466
|
var leakRegistry = new FinalizationRegistry((held) => {
|
|
19467
19467
|
std.printf('[ffi] closure leaked (GCed without dispose): sig="%s" ptr=0x%x\n', held.sig, held.ptr);
|
|
19468
19468
|
});
|
|
19469
|
+
function dispatchClosure(args, ret, fn, frameBuf, retBuf, sig) {
|
|
19470
|
+
const dv = new DataView(retBuf);
|
|
19471
|
+
const is64 = os3.arch === "x64";
|
|
19472
|
+
const fv = new DataView(frameBuf);
|
|
19473
|
+
const a2 = [];
|
|
19474
|
+
let off = 0;
|
|
19475
|
+
for (let i2 = 0; i2 < args.length; i2++) {
|
|
19476
|
+
const spec = args[i2];
|
|
19477
|
+
const k2 = spec.tok;
|
|
19478
|
+
let v2;
|
|
19479
|
+
if (is64) {
|
|
19480
|
+
const fp = k2 === "f32" || k2 === "f64";
|
|
19481
|
+
const base = fp ? i2 < 4 ? 128 + i2 * 8 : 32 + (i2 - 4) * 8 : i2 < 4 ? i2 * 8 : 32 + (i2 - 4) * 8;
|
|
19482
|
+
v2 = readScalar(fv, base, k2);
|
|
19483
|
+
} else {
|
|
19484
|
+
v2 = readScalar(fv, off, k2);
|
|
19485
|
+
off += IA32_ARG_SIZE[k2];
|
|
19486
|
+
}
|
|
19487
|
+
if (spec.nonnull && v2 === 0) {
|
|
19488
|
+
std.printf("[ffi] closure %s: arg#%d got 0 (! promise violated by caller), skipping callback\n", sig, i2 + 1);
|
|
19489
|
+
return;
|
|
19490
|
+
}
|
|
19491
|
+
a2.push(v2);
|
|
19492
|
+
}
|
|
19493
|
+
let r2;
|
|
19494
|
+
try {
|
|
19495
|
+
r2 = fn(...a2);
|
|
19496
|
+
} catch (err) {
|
|
19497
|
+
std.printf("[ffi] closure callback threw: %s\n", String(err));
|
|
19498
|
+
return;
|
|
19499
|
+
}
|
|
19500
|
+
if (ret.nonnull && r2 === 0) {
|
|
19501
|
+
std.printf("[ffi] closure %s: return got 0 (! promise violated by callback), leaving result slot 0\n", sig);
|
|
19502
|
+
return;
|
|
19503
|
+
}
|
|
19504
|
+
if (ret.tok !== "void") {
|
|
19505
|
+
writeSlot(dv, 0, { k: ret.tok, v: r2 });
|
|
19506
|
+
}
|
|
19507
|
+
}
|
|
19508
|
+
function closure(sig, fn, opts) {
|
|
19509
|
+
const { argTokens, retToken } = parseSig(sig);
|
|
19510
|
+
for (const t2 of argTokens)
|
|
19511
|
+
if (isCValToken(t2))
|
|
19512
|
+
throw new Error(`ffi-bind: closure signature cannot take a by-value struct (<${valName(t2)}>); by-value is bind-only \u2014 the C\u2192JS direction has no struct slot decoding (pass a pointer and decode on the JS side)`);
|
|
19513
|
+
const argSpecs = argTokens.map((t2) => ({ tok: cTokenToType(t2), nonnull: t2.endsWith("!") }));
|
|
19514
|
+
const retSpec = { tok: cTokenToType(retToken), nonnull: retToken.endsWith("!") };
|
|
19515
|
+
const is64 = os3.arch === "x64";
|
|
19516
|
+
const stackCapture = argSpecs.reduce((s2, x2) => s2 + IA32_ARG_SIZE[x2.tok], 0);
|
|
19517
|
+
if (is64 ? argSpecs.length > 16 : stackCapture > 64) {
|
|
19518
|
+
throw new Error(`ffi-bind: closure signature exceeds capture window (${is64 ? "max 16 params" : "max 64 stack bytes"}): ${sig}`);
|
|
19519
|
+
}
|
|
19520
|
+
const argBytes = opts?.stdcall === false || is64 ? 0 : stackCapture;
|
|
19521
|
+
const retKind = retSpec.tok === "f32" ? 1 : retSpec.tok === "f64" ? 2 : retSpec.tok === "u64" || retSpec.tok === "i64" ? 3 : 0;
|
|
19522
|
+
const wrapper = (frameBuf, retBuf) => {
|
|
19523
|
+
dispatchClosure(argSpecs, retSpec, fn, frameBuf, retBuf, sig);
|
|
19524
|
+
};
|
|
19525
|
+
const ptr = ffi.closureNew(argBytes, retKind, wrapper);
|
|
19526
|
+
let done = false;
|
|
19527
|
+
const dispose = () => {
|
|
19528
|
+
if (done)
|
|
19529
|
+
return;
|
|
19530
|
+
done = true;
|
|
19531
|
+
leakRegistry.unregister(dispose);
|
|
19532
|
+
ffi.closureFree(ptr);
|
|
19533
|
+
};
|
|
19534
|
+
const ret = { ptr, dispose };
|
|
19535
|
+
leakRegistry.register(dispose, { sig, ptr });
|
|
19536
|
+
return ret;
|
|
19537
|
+
}
|
|
19469
19538
|
|
|
19470
19539
|
// _build/lib/ffi/struct.js
|
|
19471
19540
|
import * as ffi2 from "ffi";
|
|
@@ -19497,13 +19566,13 @@ function lower(v2) {
|
|
|
19497
19566
|
type: { tag: "array", elementType: el.type, elementSize: el.size }
|
|
19498
19567
|
};
|
|
19499
19568
|
}
|
|
19500
|
-
const
|
|
19501
|
-
if (
|
|
19502
|
-
const rawUnit =
|
|
19569
|
+
const b8 = /^([A-Za-z_]\w*):(\d+)$/.exec(v2);
|
|
19570
|
+
if (b8) {
|
|
19571
|
+
const rawUnit = b8[1];
|
|
19503
19572
|
const unit = normToken(rawUnit);
|
|
19504
19573
|
if (!isCNumberToken(unit) || unit === "f32" || unit === "f64")
|
|
19505
19574
|
throw new Error(`ffi-struct: bitfield unit must be an integer type, got "${rawUnit}"`);
|
|
19506
|
-
const width = Number(
|
|
19575
|
+
const width = Number(b8[2]);
|
|
19507
19576
|
const s3 = SizeAlign[unit];
|
|
19508
19577
|
const cap = s3 * 8;
|
|
19509
19578
|
if (!Number.isInteger(width) || width < 1)
|
|
@@ -19774,7 +19843,7 @@ function doEncode(dv, base, fields, v2) {
|
|
|
19774
19843
|
function createStruct(t2) {
|
|
19775
19844
|
const { fields, size, maxEffectiveAlign } = computeStructLayout(t2);
|
|
19776
19845
|
return {
|
|
19777
|
-
|
|
19846
|
+
fields,
|
|
19778
19847
|
size,
|
|
19779
19848
|
structAlign: maxEffectiveAlign,
|
|
19780
19849
|
decode: (p2) => {
|
|
@@ -19803,6 +19872,14 @@ function createStruct(t2) {
|
|
|
19803
19872
|
};
|
|
19804
19873
|
}
|
|
19805
19874
|
function buildDecl(kind, member, pack) {
|
|
19875
|
+
const declKind = member["#"];
|
|
19876
|
+
if (declKind !== void 0 && declKind !== kind)
|
|
19877
|
+
throw new Error(`ffi-struct: ${kind}() received a '${String(declKind)}' declaration (kind mismatch \u2014 use ${declKind}() for it)`);
|
|
19878
|
+
const declPack = member["#pack"];
|
|
19879
|
+
if (pack === void 0 && declPack !== void 0)
|
|
19880
|
+
pack = declPack;
|
|
19881
|
+
else if (pack !== void 0 && declPack !== void 0 && pack !== declPack)
|
|
19882
|
+
throw new Error(`ffi-struct: #pack conflict: opts.pack=${pack} vs declaration ${String(declPack)}`);
|
|
19806
19883
|
const decl = { "#": kind };
|
|
19807
19884
|
if (pack !== void 0)
|
|
19808
19885
|
decl["#pack"] = pack;
|
|
@@ -19812,7 +19889,7 @@ function buildDecl(kind, member, pack) {
|
|
|
19812
19889
|
return decl;
|
|
19813
19890
|
}
|
|
19814
19891
|
function structArray(def) {
|
|
19815
|
-
const { fields, size } =
|
|
19892
|
+
const { fields, size } = def;
|
|
19816
19893
|
const readN = (dv, n2) => {
|
|
19817
19894
|
const out = [];
|
|
19818
19895
|
for (let i2 = 0; i2 < n2; i2++)
|
|
@@ -19854,29 +19931,36 @@ function structArray(def) {
|
|
|
19854
19931
|
})
|
|
19855
19932
|
};
|
|
19856
19933
|
}
|
|
19857
|
-
function struct(a2,
|
|
19934
|
+
function struct(a2, b8, c2) {
|
|
19858
19935
|
const isNamed = typeof a2 === "string";
|
|
19859
|
-
const raw = isNamed ?
|
|
19860
|
-
const opts = isNamed ? c2 :
|
|
19936
|
+
const raw = isNamed ? b8 : a2;
|
|
19937
|
+
const opts = isNamed ? c2 : b8;
|
|
19861
19938
|
return createStruct(buildDecl("struct", raw, opts?.pack));
|
|
19862
19939
|
}
|
|
19863
19940
|
|
|
19864
19941
|
// _build/lib/windows/structs.js
|
|
19865
|
-
var
|
|
19942
|
+
var RECT_DECL = {
|
|
19943
|
+
"#": "struct",
|
|
19866
19944
|
left: "i32",
|
|
19867
19945
|
top: "i32",
|
|
19868
19946
|
right: "i32",
|
|
19869
19947
|
bottom: "i32"
|
|
19870
|
-
}
|
|
19871
|
-
var
|
|
19948
|
+
};
|
|
19949
|
+
var RECT = /* @__PURE__ */ struct("RECT", RECT_DECL);
|
|
19950
|
+
var POINT_DECL = {
|
|
19951
|
+
"#": "struct",
|
|
19872
19952
|
x: "i32",
|
|
19873
19953
|
y: "i32"
|
|
19874
|
-
}
|
|
19875
|
-
var
|
|
19954
|
+
};
|
|
19955
|
+
var POINT = /* @__PURE__ */ struct("POINT", POINT_DECL);
|
|
19956
|
+
var SIZE_DECL = {
|
|
19957
|
+
"#": "struct",
|
|
19876
19958
|
cx: "i32",
|
|
19877
19959
|
cy: "i32"
|
|
19878
|
-
}
|
|
19879
|
-
var
|
|
19960
|
+
};
|
|
19961
|
+
var SIZE = /* @__PURE__ */ struct("SIZE", SIZE_DECL);
|
|
19962
|
+
var LOGFONTW_DECL = {
|
|
19963
|
+
"#": "struct",
|
|
19880
19964
|
lfHeight: "i32",
|
|
19881
19965
|
lfWidth: "i32",
|
|
19882
19966
|
lfEscapement: "i32",
|
|
@@ -19891,8 +19975,35 @@ var LOGFONTW = /* @__PURE__ */ struct("LOGFONTW", {
|
|
|
19891
19975
|
lfQuality: "u8",
|
|
19892
19976
|
lfPitchAndFamily: "u8",
|
|
19893
19977
|
lfFaceName: "u16[32]@utf-16le"
|
|
19894
|
-
}
|
|
19895
|
-
var
|
|
19978
|
+
};
|
|
19979
|
+
var LOGFONTW = /* @__PURE__ */ struct("LOGFONTW", LOGFONTW_DECL);
|
|
19980
|
+
var BITMAPINFOHEADER_DECL = {
|
|
19981
|
+
"#": "struct",
|
|
19982
|
+
biSize: "u32",
|
|
19983
|
+
biWidth: "i32",
|
|
19984
|
+
biHeight: "i32",
|
|
19985
|
+
biPlanes: "u16",
|
|
19986
|
+
biBitCount: "u16",
|
|
19987
|
+
biCompression: "u32",
|
|
19988
|
+
biSizeImage: "u32",
|
|
19989
|
+
biXPelsPerMeter: "i32",
|
|
19990
|
+
biYPelsPerMeter: "i32",
|
|
19991
|
+
biClrUsed: "u32",
|
|
19992
|
+
biClrImportant: "u32"
|
|
19993
|
+
};
|
|
19994
|
+
var BITMAPINFOHEADER = /* @__PURE__ */ struct("BITMAPINFOHEADER", BITMAPINFOHEADER_DECL);
|
|
19995
|
+
var BITMAPFILEHEADER_DECL = {
|
|
19996
|
+
"#": "struct",
|
|
19997
|
+
"#pack": 2,
|
|
19998
|
+
bfType: "u16",
|
|
19999
|
+
bfSize: "u32",
|
|
20000
|
+
bfReserved1: "u16",
|
|
20001
|
+
bfReserved2: "u16",
|
|
20002
|
+
bfOffBits: "u32"
|
|
20003
|
+
};
|
|
20004
|
+
var BITMAPFILEHEADER = /* @__PURE__ */ struct("BITMAPFILEHEADER", BITMAPFILEHEADER_DECL);
|
|
20005
|
+
var OPENFILENAMEW_DECL = {
|
|
20006
|
+
"#": "struct",
|
|
19896
20007
|
lStructSize: "u32",
|
|
19897
20008
|
hwndOwner: "<HWND>ptr",
|
|
19898
20009
|
hInstance: "<HMODULE>ptr",
|
|
@@ -19916,8 +20027,10 @@ var OPENFILENAMEW = /* @__PURE__ */ struct("OPENFILENAMEW", {
|
|
|
19916
20027
|
pvReserved: "<>ptr",
|
|
19917
20028
|
dwReserved: "u32",
|
|
19918
20029
|
FlagsEx: "u32"
|
|
19919
|
-
}
|
|
19920
|
-
var
|
|
20030
|
+
};
|
|
20031
|
+
var OPENFILENAMEW = /* @__PURE__ */ struct("OPENFILENAMEW", OPENFILENAMEW_DECL);
|
|
20032
|
+
var BROWSEINFOW_DECL = {
|
|
20033
|
+
"#": "struct",
|
|
19921
20034
|
hwndOwner: "<HWND>ptr",
|
|
19922
20035
|
pidlRoot: "<>ptr",
|
|
19923
20036
|
pszDisplayName: "<>ptr",
|
|
@@ -19926,13 +20039,17 @@ var BROWSEINFOW = /* @__PURE__ */ struct("BROWSEINFOW", {
|
|
|
19926
20039
|
lpfn: "<>ptr",
|
|
19927
20040
|
lParam: "<>ptr",
|
|
19928
20041
|
iImage: "i32"
|
|
19929
|
-
}
|
|
19930
|
-
var
|
|
20042
|
+
};
|
|
20043
|
+
var BROWSEINFOW = /* @__PURE__ */ struct("BROWSEINFOW", BROWSEINFOW_DECL);
|
|
20044
|
+
var NMHDR_DECL = {
|
|
20045
|
+
"#": "struct",
|
|
19931
20046
|
hwndFrom: "<HWND>ptr",
|
|
19932
20047
|
idFrom: "<>ptr",
|
|
19933
20048
|
code: "i32"
|
|
19934
|
-
}
|
|
19935
|
-
var
|
|
20049
|
+
};
|
|
20050
|
+
var NMHDR = /* @__PURE__ */ struct("NMHDR", NMHDR_DECL);
|
|
20051
|
+
var SYSTEMTIME_DECL = {
|
|
20052
|
+
"#": "struct",
|
|
19936
20053
|
wYear: "u16",
|
|
19937
20054
|
wMonth: "u16",
|
|
19938
20055
|
wDayOfWeek: "u16",
|
|
@@ -19941,35 +20058,44 @@ var SYSTEMTIME = /* @__PURE__ */ struct("SYSTEMTIME", {
|
|
|
19941
20058
|
wMinute: "u16",
|
|
19942
20059
|
wSecond: "u16",
|
|
19943
20060
|
wMilliseconds: "u16"
|
|
19944
|
-
}
|
|
19945
|
-
var
|
|
19946
|
-
|
|
20061
|
+
};
|
|
20062
|
+
var SYSTEMTIME = /* @__PURE__ */ struct("SYSTEMTIME", SYSTEMTIME_DECL);
|
|
20063
|
+
var NMDATETIMECHANGE_DECL = {
|
|
20064
|
+
"#": "struct",
|
|
20065
|
+
hdr: NMHDR_DECL,
|
|
19947
20066
|
dwFlags: "u32",
|
|
19948
|
-
st:
|
|
19949
|
-
}
|
|
19950
|
-
var
|
|
20067
|
+
st: SYSTEMTIME_DECL
|
|
20068
|
+
};
|
|
20069
|
+
var NMDATETIMECHANGE = /* @__PURE__ */ struct("NMDATETIMECHANGE", NMDATETIMECHANGE_DECL);
|
|
20070
|
+
var LITEM_DECL = {
|
|
20071
|
+
"#": "struct",
|
|
19951
20072
|
mask: "u32",
|
|
19952
20073
|
iLink: "i32",
|
|
19953
20074
|
state: "u32",
|
|
19954
20075
|
stateMask: "u32",
|
|
19955
20076
|
szID: "u16[48]@utf-16le",
|
|
19956
20077
|
szUrl: "u16[2084]@utf-16le"
|
|
19957
|
-
}
|
|
19958
|
-
var
|
|
19959
|
-
|
|
19960
|
-
|
|
19961
|
-
|
|
19962
|
-
|
|
19963
|
-
|
|
20078
|
+
};
|
|
20079
|
+
var NMLINK_DECL = {
|
|
20080
|
+
"#": "struct",
|
|
20081
|
+
hdr: NMHDR_DECL,
|
|
20082
|
+
item: LITEM_DECL
|
|
20083
|
+
};
|
|
20084
|
+
var NMLINK = /* @__PURE__ */ struct("NMLINK", NMLINK_DECL);
|
|
20085
|
+
var NMCUSTOMDRAW_DECL = {
|
|
20086
|
+
"#": "struct",
|
|
20087
|
+
hdr: NMHDR_DECL,
|
|
19964
20088
|
dwDrawStage: "u32",
|
|
19965
20089
|
hdc: "<HDC>ptr",
|
|
19966
20090
|
rc: "i32[4]",
|
|
19967
20091
|
dwItemSpec: "<>ptr",
|
|
19968
20092
|
uItemState: "u32",
|
|
19969
20093
|
lItemlParam: "<>ptr"
|
|
19970
|
-
}
|
|
19971
|
-
var
|
|
19972
|
-
|
|
20094
|
+
};
|
|
20095
|
+
var NMCUSTOMDRAW = /* @__PURE__ */ struct("NMCUSTOMDRAW", NMCUSTOMDRAW_DECL);
|
|
20096
|
+
var NMLVCUSTOMDRAW_DECL = {
|
|
20097
|
+
"#": "struct",
|
|
20098
|
+
hdr: NMHDR_DECL,
|
|
19973
20099
|
dwDrawStage: "u32",
|
|
19974
20100
|
hdc: "<HDC>ptr",
|
|
19975
20101
|
rc: "i32[4]",
|
|
@@ -19980,9 +20106,11 @@ var NMLVCUSTOMDRAW = /* @__PURE__ */ struct("NMLVCUSTOMDRAW", {
|
|
|
19980
20106
|
clrTextBk: "u32",
|
|
19981
20107
|
iSubItem: "i32",
|
|
19982
20108
|
dwItemType: "u32"
|
|
19983
|
-
}
|
|
19984
|
-
var
|
|
19985
|
-
|
|
20109
|
+
};
|
|
20110
|
+
var NMLVCUSTOMDRAW = /* @__PURE__ */ struct("NMLVCUSTOMDRAW", NMLVCUSTOMDRAW_DECL);
|
|
20111
|
+
var NMLISTVIEW_DECL = {
|
|
20112
|
+
"#": "struct",
|
|
20113
|
+
hdr: NMHDR_DECL,
|
|
19986
20114
|
iItem: "i32",
|
|
19987
20115
|
iSubItem: "i32",
|
|
19988
20116
|
uNewState: "u32",
|
|
@@ -19990,8 +20118,10 @@ var NMLISTVIEW = /* @__PURE__ */ struct("NMLISTVIEW", {
|
|
|
19990
20118
|
uChanged: "u32",
|
|
19991
20119
|
ptAction: "i32[2]",
|
|
19992
20120
|
lParam: "<>ptr"
|
|
19993
|
-
}
|
|
19994
|
-
var
|
|
20121
|
+
};
|
|
20122
|
+
var NMLISTVIEW = /* @__PURE__ */ struct("NMLISTVIEW", NMLISTVIEW_DECL);
|
|
20123
|
+
var TCITEMW_DECL = {
|
|
20124
|
+
"#": "struct",
|
|
19995
20125
|
mask: "u32",
|
|
19996
20126
|
dwState: "u32",
|
|
19997
20127
|
dwStateMask: "u32",
|
|
@@ -19999,8 +20129,10 @@ var TCITEMW = /* @__PURE__ */ struct("TCITEMW", {
|
|
|
19999
20129
|
cchTextMax: "i32",
|
|
20000
20130
|
iImage: "i32",
|
|
20001
20131
|
lParam: "<>ptr"
|
|
20002
|
-
}
|
|
20003
|
-
var
|
|
20132
|
+
};
|
|
20133
|
+
var TCITEMW = /* @__PURE__ */ struct("TCITEMW", TCITEMW_DECL);
|
|
20134
|
+
var TVITEM_DECL = {
|
|
20135
|
+
"#": "struct",
|
|
20004
20136
|
mask: "u32",
|
|
20005
20137
|
hItem: "<>ptr",
|
|
20006
20138
|
state: "u32",
|
|
@@ -20011,20 +20143,26 @@ var TVITEM = /* @__PURE__ */ struct("TVITEM", {
|
|
|
20011
20143
|
iSelectedImage: "i32",
|
|
20012
20144
|
cChildren: "i32",
|
|
20013
20145
|
lParam: "<>ptr"
|
|
20014
|
-
}
|
|
20015
|
-
var
|
|
20146
|
+
};
|
|
20147
|
+
var TVITEM = /* @__PURE__ */ struct("TVITEM", TVITEM_DECL);
|
|
20148
|
+
var TVINSERTSTRUCT_DECL = {
|
|
20149
|
+
"#": "struct",
|
|
20016
20150
|
hParent: "<>ptr",
|
|
20017
20151
|
hInsertAfter: "<>ptr",
|
|
20018
|
-
item:
|
|
20019
|
-
}
|
|
20020
|
-
var
|
|
20152
|
+
item: TVITEM_DECL
|
|
20153
|
+
};
|
|
20154
|
+
var TVINSERTSTRUCT = /* @__PURE__ */ struct("TVINSERTSTRUCT", TVINSERTSTRUCT_DECL);
|
|
20155
|
+
var LVHITTESTINFO_DECL = {
|
|
20156
|
+
"#": "struct",
|
|
20021
20157
|
pt: "i32[2]",
|
|
20022
20158
|
flags: "u32",
|
|
20023
20159
|
iItem: "i32",
|
|
20024
20160
|
iSubItem: "i32",
|
|
20025
20161
|
iGroup: "i32"
|
|
20026
|
-
}
|
|
20027
|
-
var
|
|
20162
|
+
};
|
|
20163
|
+
var LVHITTESTINFO = /* @__PURE__ */ struct("LVHITTESTINFO", LVHITTESTINFO_DECL);
|
|
20164
|
+
var LVITEMW_DECL = {
|
|
20165
|
+
"#": "struct",
|
|
20028
20166
|
mask: "u32",
|
|
20029
20167
|
iItem: "i32",
|
|
20030
20168
|
iSubItem: "i32",
|
|
@@ -20040,8 +20178,10 @@ var LVITEMW = /* @__PURE__ */ struct("LVITEMW", {
|
|
|
20040
20178
|
puColumns: "<>ptr",
|
|
20041
20179
|
piColFmt: "<>ptr",
|
|
20042
20180
|
iGroup: "i32"
|
|
20043
|
-
}
|
|
20044
|
-
var
|
|
20181
|
+
};
|
|
20182
|
+
var LVITEMW = /* @__PURE__ */ struct("LVITEMW", LVITEMW_DECL);
|
|
20183
|
+
var LVCOLUMNW_DECL = {
|
|
20184
|
+
"#": "struct",
|
|
20045
20185
|
mask: "u32",
|
|
20046
20186
|
fmt: "i32",
|
|
20047
20187
|
cx: "i32",
|
|
@@ -20053,46 +20193,116 @@ var LVCOLUMNW = /* @__PURE__ */ struct("LVCOLUMNW", {
|
|
|
20053
20193
|
cxMin: "i32",
|
|
20054
20194
|
cxDefault: "i32",
|
|
20055
20195
|
cxIdeal: "i32"
|
|
20056
|
-
}
|
|
20057
|
-
var
|
|
20058
|
-
|
|
20059
|
-
|
|
20060
|
-
|
|
20061
|
-
|
|
20196
|
+
};
|
|
20197
|
+
var LVCOLUMNW = /* @__PURE__ */ struct("LVCOLUMNW", LVCOLUMNW_DECL);
|
|
20198
|
+
var DEVMODEW_DECL = {
|
|
20199
|
+
"#": "struct",
|
|
20200
|
+
dmDeviceName: "u16[32]@utf-16le",
|
|
20201
|
+
dmSpecVersion: "u16",
|
|
20202
|
+
dmDriverVersion: "u16",
|
|
20203
|
+
dmSize: "u16",
|
|
20204
|
+
dmDriverExtra: "u16",
|
|
20205
|
+
dmFields: "u32",
|
|
20206
|
+
dmPosition: "i32[2]",
|
|
20207
|
+
dmDisplayOrientation: "u32",
|
|
20208
|
+
dmDisplayFixedOutput: "u32",
|
|
20209
|
+
dmColor: "i16",
|
|
20210
|
+
dmDuplex: "i16",
|
|
20211
|
+
dmYResolution: "i16",
|
|
20212
|
+
dmTTOption: "i16",
|
|
20213
|
+
dmCollate: "i16",
|
|
20214
|
+
dmFormName: "u16[32]@utf-16le",
|
|
20215
|
+
dmLogPixels: "u16",
|
|
20216
|
+
dmBitsPerPel: "u32",
|
|
20217
|
+
dmPelsWidth: "u32",
|
|
20218
|
+
dmPelsHeight: "u32",
|
|
20219
|
+
dmDisplayFlags: "u32",
|
|
20220
|
+
dmDisplayFrequency: "u32",
|
|
20221
|
+
dmICMMethod: "u32",
|
|
20222
|
+
dmICMIntent: "u32",
|
|
20223
|
+
dmMediaType: "u32",
|
|
20224
|
+
dmDitherType: "u32",
|
|
20225
|
+
dmReserved1: "u32",
|
|
20226
|
+
dmReserved2: "u32",
|
|
20227
|
+
dmPanningWidth: "u32",
|
|
20228
|
+
dmPanningHeight: "u32"
|
|
20229
|
+
};
|
|
20230
|
+
var DEVMODEW = /* @__PURE__ */ struct("DEVMODEW", DEVMODEW_DECL);
|
|
20231
|
+
var MOUSEINPUT_DECL = {
|
|
20232
|
+
"#": "struct",
|
|
20233
|
+
dx: "i32",
|
|
20234
|
+
dy: "i32",
|
|
20235
|
+
mouseData: "u32",
|
|
20236
|
+
dwFlags: "u32",
|
|
20062
20237
|
time: "u32",
|
|
20063
|
-
|
|
20064
|
-
}
|
|
20065
|
-
var
|
|
20066
|
-
|
|
20067
|
-
|
|
20068
|
-
|
|
20069
|
-
|
|
20070
|
-
|
|
20071
|
-
|
|
20072
|
-
}
|
|
20238
|
+
dwExtraInfo: "<>ptr"
|
|
20239
|
+
};
|
|
20240
|
+
var KEYBDINPUT_DECL = {
|
|
20241
|
+
"#": "struct",
|
|
20242
|
+
wVk: "u16",
|
|
20243
|
+
wScan: "u16",
|
|
20244
|
+
dwFlags: "u32",
|
|
20245
|
+
time: "u32",
|
|
20246
|
+
dwExtraInfo: "<>ptr"
|
|
20247
|
+
};
|
|
20248
|
+
var INPUT_DECL = {
|
|
20249
|
+
"#": "struct",
|
|
20250
|
+
type: "u32",
|
|
20251
|
+
data: {
|
|
20252
|
+
"#": "union",
|
|
20253
|
+
mi: MOUSEINPUT_DECL,
|
|
20254
|
+
ki: KEYBDINPUT_DECL
|
|
20255
|
+
}
|
|
20256
|
+
};
|
|
20257
|
+
var INPUT = /* @__PURE__ */ struct("INPUT", INPUT_DECL);
|
|
20258
|
+
var NOTIFYICONIDENTIFIER_DECL = {
|
|
20259
|
+
"#": "struct",
|
|
20260
|
+
cbSize: "u32",
|
|
20261
|
+
hWnd: "<HWND>ptr",
|
|
20262
|
+
uID: "u32",
|
|
20263
|
+
guidItem: "u32[4]"
|
|
20264
|
+
};
|
|
20265
|
+
var NOTIFYICONIDENTIFIER = /* @__PURE__ */ struct("NOTIFYICONIDENTIFIER", NOTIFYICONIDENTIFIER_DECL);
|
|
20073
20266
|
|
|
20074
20267
|
// _build/lib/windows/user32.js
|
|
20075
20268
|
var b2 = (name, sig, encoders) => bind2("user32.dll", name, sig, encoders);
|
|
20076
20269
|
var _bProbe = b2("GetDesktopWindow", " -> <HWND>ptr");
|
|
20077
20270
|
var LONG_PTR_SYM = os4.arch === "x64" ? "PtrW" : "W";
|
|
20078
20271
|
var SetWindowPos = /* @__PURE__ */ b2("SetWindowPos", "<HWND>ptr <>ptr@SetWindowPosHwnd i32 i32 i32 i32 u32 -> i32");
|
|
20272
|
+
var GetWindowRect = /* @__PURE__ */ b2("GetWindowRect", "<HWND>ptr <RECT>ptr -> i32");
|
|
20273
|
+
var GetClientRect = /* @__PURE__ */ b2("GetClientRect", "<HWND>ptr <RECT>ptr -> i32");
|
|
20274
|
+
var IsWindow = /* @__PURE__ */ b2("IsWindow", "<HWND>ptr -> i32");
|
|
20275
|
+
var IsWindowVisible = /* @__PURE__ */ b2("IsWindowVisible", "<HWND>ptr -> i32");
|
|
20276
|
+
var IsIconic = /* @__PURE__ */ b2("IsIconic", "<HWND>ptr -> i32");
|
|
20277
|
+
var FindWindow = /* @__PURE__ */ b2("FindWindowW", "<WCHAR>ptr <WCHAR>ptr -> <HWND>ptr");
|
|
20278
|
+
var FindWindowEx = /* @__PURE__ */ b2("FindWindowExW", "<HWND>ptr <HWND>ptr <WCHAR>ptr <WCHAR>ptr -> <HWND>ptr");
|
|
20279
|
+
var GetWindowText = /* @__PURE__ */ b2("GetWindowTextW", "<HWND>ptr <BYTE>ptr i32 -> i32");
|
|
20079
20280
|
var SetWindowText = /* @__PURE__ */ b2("SetWindowTextW", "<HWND>ptr <WCHAR>ptr -> i32");
|
|
20281
|
+
var GetClassName = /* @__PURE__ */ b2("GetClassNameW", "<HWND>ptr <BYTE>ptr i32 -> i32");
|
|
20080
20282
|
var GetWindowLongPtr = /* @__PURE__ */ b2("GetWindowLong" + LONG_PTR_SYM, "<HWND>ptr i32@Gwlp -> <>ptr");
|
|
20081
20283
|
var SetWindowLongPtr = /* @__PURE__ */ b2("SetWindowLong" + LONG_PTR_SYM, "<HWND>ptr i32@Gwlp <>ptr -> <>ptr");
|
|
20284
|
+
var GetWindowThreadProcessId = /* @__PURE__ */ b2("GetWindowThreadProcessId", "<HWND>ptr <BYTE>ptr -> u32");
|
|
20082
20285
|
var EnableWindow = /* @__PURE__ */ b2("EnableWindow", "<HWND>ptr i32 -> i32");
|
|
20083
20286
|
var SetParent = /* @__PURE__ */ b2("SetParent", "<HWND>ptr <HWND>ptr -> <HWND>ptr");
|
|
20084
20287
|
var DefWindowProc = /* @__PURE__ */ b2("DefWindowProcW", "<HWND>ptr u32@AnyMsg <>ptr <>ptr -> <>ptr");
|
|
20085
20288
|
var CallWindowProc = /* @__PURE__ */ b2("CallWindowProcW", "<>ptr <HWND>ptr u32@AnyMsg <>ptr <>ptr -> <>ptr");
|
|
20086
20289
|
var GetDC = /* @__PURE__ */ b2("GetDC", "<HWND>ptr -> <HDC>ptr");
|
|
20087
20290
|
var ReleaseDC = /* @__PURE__ */ b2("ReleaseDC", "<HWND>ptr <HDC>ptr! -> i32");
|
|
20291
|
+
var PrintWindow = /* @__PURE__ */ b2("PrintWindow", "<HWND>ptr <HDC>ptr! u32 -> i32");
|
|
20088
20292
|
var DrawText = /* @__PURE__ */ b2("DrawTextW", "<HDC>ptr! <WCHAR>ptr i32 <RECT>ptr i32 -> i32");
|
|
20089
20293
|
var InvalidateRect = /* @__PURE__ */ b2("InvalidateRect", "<HWND>ptr <RECT>ptr i32 -> i32", { RECT });
|
|
20090
20294
|
var SetCursor = /* @__PURE__ */ b2("SetCursor", "<HCURSOR>ptr -> <HCURSOR>ptr");
|
|
20091
20295
|
var LoadCursor = /* @__PURE__ */ b2("LoadCursorW", "<HMODULE>ptr <>ptr -> <HCURSOR>ptr");
|
|
20092
20296
|
var GetCursorPos = /* @__PURE__ */ b2("GetCursorPos", "<POINT>ptr -> i32");
|
|
20093
20297
|
var ScreenToClient = /* @__PURE__ */ b2("ScreenToClient", "<HWND>ptr <POINT>ptr -> i32");
|
|
20298
|
+
var ClientToScreen = /* @__PURE__ */ b2("ClientToScreen", "<HWND>ptr <POINT>ptr -> i32");
|
|
20299
|
+
var INPUTArr = /* @__PURE__ */ structArray(INPUT);
|
|
20300
|
+
var SendInput = /* @__PURE__ */ b2("SendInput", "u32 <INPUT>ptr i32 -> u32", { INPUT: INPUTArr });
|
|
20094
20301
|
var ShowScrollBar = /* @__PURE__ */ b2("ShowScrollBar", "<HWND>ptr u32 i32 -> i32");
|
|
20095
20302
|
var GetSystemMetrics = /* @__PURE__ */ b2("GetSystemMetrics", "i32 -> i32");
|
|
20303
|
+
var EnumWindows = /* @__PURE__ */ b2("EnumWindows", "<>ptr <>ptr -> i32");
|
|
20304
|
+
var EnumDisplaySettings = /* @__PURE__ */ b2("EnumDisplaySettingsW", "<WCHAR>ptr u32 <DEVMODEW>ptr -> i32");
|
|
20305
|
+
var ChangeDisplaySettings = /* @__PURE__ */ b2("ChangeDisplaySettingsW", "<DEVMODEW>ptr u32 -> i32");
|
|
20096
20306
|
|
|
20097
20307
|
// _build/lib/react-qw/reconciler.js
|
|
20098
20308
|
var import_react_reconciler = __toESM(require_react_reconciler(), 1);
|
|
@@ -20103,12 +20313,16 @@ import * as os5 from "os";
|
|
|
20103
20313
|
|
|
20104
20314
|
// _build/lib/windows/gdi32.js
|
|
20105
20315
|
var b3 = (name, sig, encoders) => bind2("gdi32.dll", name, sig, encoders);
|
|
20106
|
-
var POINTArr = structArray(POINT);
|
|
20107
20316
|
var DeleteObject = /* @__PURE__ */ b3("DeleteObject", "<HGDIOBJ>ptr -> i32");
|
|
20108
20317
|
var GetDeviceCaps = /* @__PURE__ */ b3("GetDeviceCaps", "<HDC>ptr! i32@DeviceCap -> i32");
|
|
20109
20318
|
var CreateFontIndirect = /* @__PURE__ */ b3("CreateFontIndirectW", "<LOGFONTW>ptr -> <HGDIOBJ>ptr", { LOGFONTW });
|
|
20319
|
+
var CreateCompatibleDC = /* @__PURE__ */ b3("CreateCompatibleDC", "<HDC>ptr -> <HDC>ptr");
|
|
20320
|
+
var CreateCompatibleBitmap = /* @__PURE__ */ b3("CreateCompatibleBitmap", "<HDC>ptr! i32 i32 -> <HGDIOBJ>ptr");
|
|
20110
20321
|
var SelectObject = /* @__PURE__ */ b3("SelectObject", "<HDC>ptr! <HGDIOBJ>ptr -> <HGDIOBJ>ptr");
|
|
20322
|
+
var BitBlt = /* @__PURE__ */ b3("BitBlt", "<HDC>ptr! i32 i32 i32 i32 <HDC>ptr i32 i32 u32@RasterOp -> i32");
|
|
20323
|
+
var GetDIBits = /* @__PURE__ */ b3("GetDIBits", "<HDC>ptr! <HGDIOBJ>ptr u32 u32 <BYTE>ptr <>ptr u32 -> i32");
|
|
20111
20324
|
var GetObject = /* @__PURE__ */ b3("GetObjectW", "<HGDIOBJ>ptr i32 <BYTE>ptr -> i32");
|
|
20325
|
+
var DeleteDC = /* @__PURE__ */ b3("DeleteDC", "<HDC>ptr! -> i32");
|
|
20112
20326
|
|
|
20113
20327
|
// _build/lib/react-qw/props.js
|
|
20114
20328
|
import * as gui from "gui";
|
|
@@ -20136,14 +20350,14 @@ function applyProps(instance, newProps, _oldProps) {
|
|
|
20136
20350
|
gui.ShowWindow(
|
|
20137
20351
|
hwnd,
|
|
20138
20352
|
newProps.hidden ? 0 : 5
|
|
20139
|
-
/*
|
|
20353
|
+
/* ShowWindowCmd.SHOW */
|
|
20140
20354
|
);
|
|
20141
20355
|
}
|
|
20142
20356
|
if ("visible" in newProps) {
|
|
20143
20357
|
gui.ShowWindow(
|
|
20144
20358
|
hwnd,
|
|
20145
20359
|
newProps.visible ? 5 : 0
|
|
20146
|
-
/*
|
|
20360
|
+
/* ShowWindowCmd.HIDE */
|
|
20147
20361
|
);
|
|
20148
20362
|
}
|
|
20149
20363
|
}
|
|
@@ -20239,7 +20453,7 @@ function measureText(hdc, text, maxWidth) {
|
|
|
20239
20453
|
-1,
|
|
20240
20454
|
r2.ptr,
|
|
20241
20455
|
1024
|
|
20242
|
-
/*
|
|
20456
|
+
/* DrawTextFlag.CALCRECT */
|
|
20243
20457
|
);
|
|
20244
20458
|
const { right, bottom } = RECT.decode(r2);
|
|
20245
20459
|
return { width: right, height: bottom };
|
|
@@ -20287,7 +20501,7 @@ function setupWindowProc(instance, hwnd) {
|
|
|
20287
20501
|
const oldProc = GetWindowLongPtr(
|
|
20288
20502
|
hwnd,
|
|
20289
20503
|
-4
|
|
20290
|
-
/*
|
|
20504
|
+
/* Gwlp.WNDPROC */
|
|
20291
20505
|
);
|
|
20292
20506
|
instancesByHwnd.set(hwnd, instance);
|
|
20293
20507
|
gui3.SetWindowProc(hwnd, (hwnd2, msg, wParam, lParam) => {
|
|
@@ -20375,7 +20589,7 @@ function runFlexLayout(inst) {
|
|
|
20375
20589
|
r2.width * scaleFactor,
|
|
20376
20590
|
r2.height * scaleFactor,
|
|
20377
20591
|
64
|
|
20378
|
-
/*
|
|
20592
|
+
/* SetWindowPosFlag.SWP_SHOWWINDOW */
|
|
20379
20593
|
);
|
|
20380
20594
|
InvalidateRect(child.hwnd, NULL, 1);
|
|
20381
20595
|
child.lastRect = { x: r2.x, y: r2.y, w: r2.width, h: r2.height };
|
|
@@ -20531,7 +20745,7 @@ var hostConfig = {
|
|
|
20531
20745
|
gui3.ShowWindow(
|
|
20532
20746
|
instance.hwnd,
|
|
20533
20747
|
0
|
|
20534
|
-
/*
|
|
20748
|
+
/* ShowWindowCmd.HIDE */
|
|
20535
20749
|
);
|
|
20536
20750
|
},
|
|
20537
20751
|
hideTextInstance(instance) {
|
|
@@ -20539,7 +20753,7 @@ var hostConfig = {
|
|
|
20539
20753
|
gui3.ShowWindow(
|
|
20540
20754
|
instance.hwnd,
|
|
20541
20755
|
0
|
|
20542
|
-
/*
|
|
20756
|
+
/* ShowWindowCmd.HIDE */
|
|
20543
20757
|
);
|
|
20544
20758
|
},
|
|
20545
20759
|
unhideInstance(instance, _props) {
|
|
@@ -20547,7 +20761,7 @@ var hostConfig = {
|
|
|
20547
20761
|
gui3.ShowWindow(
|
|
20548
20762
|
instance.hwnd,
|
|
20549
20763
|
5
|
|
20550
|
-
/*
|
|
20764
|
+
/* ShowWindowCmd.SHOW */
|
|
20551
20765
|
);
|
|
20552
20766
|
},
|
|
20553
20767
|
unhideTextInstance(instance, _text) {
|
|
@@ -20555,7 +20769,7 @@ var hostConfig = {
|
|
|
20555
20769
|
gui3.ShowWindow(
|
|
20556
20770
|
instance.hwnd,
|
|
20557
20771
|
5
|
|
20558
|
-
/*
|
|
20772
|
+
/* ShowWindowCmd.SHOW */
|
|
20559
20773
|
);
|
|
20560
20774
|
},
|
|
20561
20775
|
shouldSetTextContent(_type, props) {
|
|
@@ -20983,7 +21197,7 @@ function getCellFont(hwnd, style) {
|
|
|
20983
21197
|
...base,
|
|
20984
21198
|
...style.bold ? {
|
|
20985
21199
|
lfWeight: 700
|
|
20986
|
-
/*
|
|
21200
|
+
/* FontWeight.BOLD */
|
|
20987
21201
|
} : {},
|
|
20988
21202
|
...style.italic ? { lfItalic: 1 } : {},
|
|
20989
21203
|
...style.underline ? { lfUnderline: 1 } : {}
|
|
@@ -21041,7 +21255,7 @@ function resolveCellStyle(columns, data, row, colIndex) {
|
|
|
21041
21255
|
}
|
|
21042
21256
|
function makeLVItem(i2, sub, text, image) {
|
|
21043
21257
|
const textBuf = WCHAR.encode(text);
|
|
21044
|
-
const
|
|
21258
|
+
const b8 = LVITEMW.encode({
|
|
21045
21259
|
mask: 1 | (image !== void 0 ? 2 : 0),
|
|
21046
21260
|
iItem: i2,
|
|
21047
21261
|
iSubItem: sub,
|
|
@@ -21058,8 +21272,8 @@ function makeLVItem(i2, sub, text, image) {
|
|
|
21058
21272
|
piColFmt: 0,
|
|
21059
21273
|
iGroup: 0
|
|
21060
21274
|
});
|
|
21061
|
-
|
|
21062
|
-
return
|
|
21275
|
+
b8.__textBuf = textBuf;
|
|
21276
|
+
return b8;
|
|
21063
21277
|
}
|
|
21064
21278
|
var ListView = (0, import_react9.forwardRef)(function ListViewInner({ columns, data, style, icons, iconSize, getIcon }, ref) {
|
|
21065
21279
|
const lvRef = (0, import_react9.useRef)(null);
|
|
@@ -21105,7 +21319,7 @@ var ListView = (0, import_react9.forwardRef)(function ListViewInner({ columns, d
|
|
|
21105
21319
|
4150,
|
|
21106
21320
|
0,
|
|
21107
21321
|
32 | 1 | 65536
|
|
21108
|
-
/*
|
|
21322
|
+
/* LvExStyle.DOUBLEBUFFER */
|
|
21109
21323
|
);
|
|
21110
21324
|
const n2 = columns.length;
|
|
21111
21325
|
for (let j2 = 0; j2 < n2; j2++) {
|
|
@@ -21150,7 +21364,7 @@ var ListView = (0, import_react9.forwardRef)(function ListViewInner({ columns, d
|
|
|
21150
21364
|
4126,
|
|
21151
21365
|
j2,
|
|
21152
21366
|
-2
|
|
21153
|
-
/*
|
|
21367
|
+
/* LvColumnWidthCmd.AUTOSIZE_USEHEADER */
|
|
21154
21368
|
);
|
|
21155
21369
|
}
|
|
21156
21370
|
}
|
|
@@ -21292,7 +21506,7 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
|
|
|
21292
21506
|
natW,
|
|
21293
21507
|
natH,
|
|
21294
21508
|
4
|
|
21295
|
-
/*
|
|
21509
|
+
/* SetWindowPosFlag.SWP_NOZORDER */
|
|
21296
21510
|
);
|
|
21297
21511
|
forceFlexLayout(content);
|
|
21298
21512
|
if (natW > svW) {
|
|
@@ -21331,7 +21545,7 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
|
|
|
21331
21545
|
0,
|
|
21332
21546
|
0,
|
|
21333
21547
|
1 | 4
|
|
21334
|
-
/*
|
|
21548
|
+
/* SetWindowPosFlag.SWP_NOZORDER */
|
|
21335
21549
|
);
|
|
21336
21550
|
gui12.SetScrollInfo(sv, bar, { pos: newPos }, true);
|
|
21337
21551
|
}
|
|
@@ -21397,7 +21611,7 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
|
|
|
21397
21611
|
handleScroll(
|
|
21398
21612
|
e2,
|
|
21399
21613
|
1
|
|
21400
|
-
/*
|
|
21614
|
+
/* ScrollBar.VERT */
|
|
21401
21615
|
);
|
|
21402
21616
|
return 0;
|
|
21403
21617
|
}
|
|
@@ -21405,7 +21619,7 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
|
|
|
21405
21619
|
handleScroll(
|
|
21406
21620
|
e2,
|
|
21407
21621
|
0
|
|
21408
|
-
/*
|
|
21622
|
+
/* ScrollBar.HORZ */
|
|
21409
21623
|
);
|
|
21410
21624
|
return 0;
|
|
21411
21625
|
}
|
|
@@ -21569,7 +21783,7 @@ function deleteAllItems(hTree) {
|
|
|
21569
21783
|
4353,
|
|
21570
21784
|
1,
|
|
21571
21785
|
-65536
|
|
21572
|
-
/*
|
|
21786
|
+
/* TvInsertAfter.ROOT */
|
|
21573
21787
|
);
|
|
21574
21788
|
}
|
|
21575
21789
|
var TreeView = (0, import_react16.forwardRef)(function TreeViewInner({ data, onSelect, defaultSelectedKey, selectedKey: controlledKey, style }, ref) {
|
|
@@ -21601,7 +21815,7 @@ var TreeView = (0, import_react16.forwardRef)(function TreeViewInner({ data, onS
|
|
|
21601
21815
|
4396,
|
|
21602
21816
|
0,
|
|
21603
21817
|
4
|
|
21604
|
-
/*
|
|
21818
|
+
/* TvExStyle.DOUBLEBUFFER */
|
|
21605
21819
|
);
|
|
21606
21820
|
}, []);
|
|
21607
21821
|
(0, import_react16.useEffect)(() => {
|
|
@@ -21643,9 +21857,16 @@ var b4 = (name, sig) => bind2("comdlg32.dll", name, sig);
|
|
|
21643
21857
|
var GetOpenFileName = /* @__PURE__ */ b4("GetOpenFileNameW", "<OPENFILENAMEW>ptr -> u32");
|
|
21644
21858
|
|
|
21645
21859
|
// _build/lib/windows/shell32.js
|
|
21646
|
-
var b5 = (name, sig) => bind2("shell32.dll", name, sig);
|
|
21860
|
+
var b5 = (name, sig, encoders) => bind2("shell32.dll", name, sig, encoders);
|
|
21647
21861
|
var SHBrowseForFolder = /* @__PURE__ */ b5("SHBrowseForFolderW", "<BROWSEINFOW>ptr -> <>ptr");
|
|
21648
21862
|
var SHGetPathFromIDList = /* @__PURE__ */ b5("SHGetPathFromIDListW", "<>ptr <BYTE>ptr -> u32");
|
|
21863
|
+
var Shell_NotifyIconGetRect = (() => {
|
|
21864
|
+
try {
|
|
21865
|
+
return b5("Shell_NotifyIconGetRect", "<NOTIFYICONIDENTIFIER>ptr <RECT>ptr -> i32", { NOTIFYICONIDENTIFIER });
|
|
21866
|
+
} catch {
|
|
21867
|
+
return null;
|
|
21868
|
+
}
|
|
21869
|
+
})();
|
|
21649
21870
|
|
|
21650
21871
|
// _build/lib/windows/ole32.js
|
|
21651
21872
|
var b6 = (name, sig) => bind2("ole32.dll", name, sig);
|
|
@@ -21798,28 +22019,183 @@ function createRoot(container) {
|
|
|
21798
22019
|
};
|
|
21799
22020
|
}
|
|
21800
22021
|
|
|
21801
|
-
// _build/examples/
|
|
22022
|
+
// _build/examples/execd/main.js
|
|
21802
22023
|
var import_react18 = __toESM(require_react(), 1);
|
|
22024
|
+
|
|
22025
|
+
// _build/examples/execd/tray.js
|
|
22026
|
+
import * as os6 from "os";
|
|
22027
|
+
import * as gui18 from "gui";
|
|
22028
|
+
|
|
22029
|
+
// _build/lib/windows/kernel32.js
|
|
22030
|
+
var b7 = (name, sig, encoders) => bind2("kernel32.dll", name, sig, encoders);
|
|
22031
|
+
var CloseHandle = /* @__PURE__ */ b7("CloseHandle", "<>ptr -> i32");
|
|
22032
|
+
var OpenProcess = /* @__PURE__ */ b7("OpenProcess", "u32 i32 u32 -> <HPROCESS>ptr");
|
|
22033
|
+
var GetCurrentProcess = /* @__PURE__ */ b7("GetCurrentProcess", " -> <HPROCESS>ptr");
|
|
22034
|
+
var VirtualAllocEx = /* @__PURE__ */ b7("VirtualAllocEx", "<HPROCESS>ptr <>ptr <>ptr u32 u32 -> <>ptr");
|
|
22035
|
+
var VirtualFreeEx = /* @__PURE__ */ b7("VirtualFreeEx", "<HPROCESS>ptr <>ptr <>ptr u32 -> i32");
|
|
22036
|
+
var ReadProcessMemory = /* @__PURE__ */ b7("ReadProcessMemory", "<HPROCESS>ptr <>ptr <BYTE>ptr <>ptr <>ptr -> i32");
|
|
22037
|
+
var IsWow64Process = /* @__PURE__ */ b7("IsWow64Process", "<HPROCESS>ptr <BYTE>ptr -> i32");
|
|
22038
|
+
|
|
22039
|
+
// _build/examples/execd/tray.js
|
|
22040
|
+
var TB_GETBUTTON = 1047;
|
|
22041
|
+
var TB_BUTTONCOUNT = 1048;
|
|
22042
|
+
var TB_GETITEMRECT = 1053;
|
|
22043
|
+
var CLS_BUF = 512;
|
|
22044
|
+
var OS64 = os6.arch === "x64" || (() => {
|
|
22045
|
+
const wow = new PtrArrayBuffer(4);
|
|
22046
|
+
return IsWow64Process(GetCurrentProcess(), wow) !== 0 && new Uint32Array(wow)[0] !== 0;
|
|
22047
|
+
})();
|
|
22048
|
+
var TBBUTTON_DWDATA = OS64 ? 16 : 12;
|
|
22049
|
+
var TBBUTTON_ISTRING = OS64 ? 24 : 16;
|
|
22050
|
+
var TBBUTTON_SZ = OS64 ? 32 : 20;
|
|
22051
|
+
var TRAYDATA_UID = OS64 ? 8 : 4;
|
|
22052
|
+
var REMOTE_BUF = 256;
|
|
22053
|
+
function findToolbars(root) {
|
|
22054
|
+
const out = [];
|
|
22055
|
+
const cls = WCHAR.alloc(CLS_BUF);
|
|
22056
|
+
const walk = (parent) => {
|
|
22057
|
+
let child = FindWindowEx(parent, NULL, NULL, NULL);
|
|
22058
|
+
while (child) {
|
|
22059
|
+
const n2 = GetClassName(child, cls, CLS_BUF);
|
|
22060
|
+
if (n2 > 0 && WCHAR.decode(cls) === "ToolbarWindow32")
|
|
22061
|
+
out.push(child);
|
|
22062
|
+
walk(child);
|
|
22063
|
+
child = FindWindowEx(parent, child, NULL, NULL);
|
|
22064
|
+
}
|
|
22065
|
+
};
|
|
22066
|
+
walk(root);
|
|
22067
|
+
return out;
|
|
22068
|
+
}
|
|
22069
|
+
function readToolbar(tb, area, out) {
|
|
22070
|
+
const count = gui18.SendMessage(tb, TB_BUTTONCOUNT, 0, 0);
|
|
22071
|
+
if (!Number.isInteger(count) || count <= 0 || count > 512)
|
|
22072
|
+
return;
|
|
22073
|
+
const pidBuf = BYTE.alloc(4);
|
|
22074
|
+
if (GetWindowThreadProcessId(tb, pidBuf) === 0)
|
|
22075
|
+
return;
|
|
22076
|
+
const pid = new Uint32Array(pidBuf)[0];
|
|
22077
|
+
const proc = OpenProcess(56, 0, pid);
|
|
22078
|
+
if (!proc)
|
|
22079
|
+
throw new Error("OpenProcess(explorer " + pid + ") failed");
|
|
22080
|
+
const remote = VirtualAllocEx(proc, NULL, REMOTE_BUF, 12288, 4);
|
|
22081
|
+
if (!remote) {
|
|
22082
|
+
CloseHandle(proc);
|
|
22083
|
+
throw new Error("VirtualAllocEx failed");
|
|
22084
|
+
}
|
|
22085
|
+
try {
|
|
22086
|
+
const tbBuf = BYTE.alloc(REMOTE_BUF), trBuf = BYTE.alloc(REMOTE_BUF), tipBuf = BYTE.alloc(REMOTE_BUF);
|
|
22087
|
+
const dvTb = new DataView(tbBuf), dvTr = new DataView(trBuf);
|
|
22088
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
22089
|
+
if (!gui18.SendMessage(tb, TB_GETBUTTON, i2, remote))
|
|
22090
|
+
continue;
|
|
22091
|
+
if (!ReadProcessMemory(proc, remote, tbBuf, TBBUTTON_SZ, NULL))
|
|
22092
|
+
continue;
|
|
22093
|
+
const dwData = OS64 ? Number(dvTb.getBigUint64(TBBUTTON_DWDATA, true)) : dvTb.getUint32(TBBUTTON_DWDATA, true);
|
|
22094
|
+
if (dwData < 65536)
|
|
22095
|
+
continue;
|
|
22096
|
+
if (!ReadProcessMemory(proc, dwData, trBuf, TRAYDATA_UID + 4, NULL))
|
|
22097
|
+
continue;
|
|
22098
|
+
const hWnd = OS64 ? Number(dvTr.getBigUint64(0, true)) : dvTr.getUint32(0, true);
|
|
22099
|
+
const uID = dvTr.getUint32(TRAYDATA_UID, true);
|
|
22100
|
+
if (!hWnd || !IsWindow(hWnd))
|
|
22101
|
+
continue;
|
|
22102
|
+
let rect = null;
|
|
22103
|
+
if (gui18.SendMessage(tb, TB_GETITEMRECT, i2, remote) && ReadProcessMemory(proc, remote, trBuf, 16, NULL)) {
|
|
22104
|
+
const L2 = dvTr.getInt32(0, true), T2 = dvTr.getInt32(4, true);
|
|
22105
|
+
const R2 = dvTr.getInt32(8, true), B2 = dvTr.getInt32(12, true);
|
|
22106
|
+
if (!(L2 === 0 && T2 === 0 && R2 === 0 && B2 === 0)) {
|
|
22107
|
+
const tl = POINT.encode({ x: L2, y: T2 }), br2 = POINT.encode({ x: R2, y: B2 });
|
|
22108
|
+
if (ClientToScreen(tb, tl.ptr) && ClientToScreen(tb, br2.ptr)) {
|
|
22109
|
+
const a2 = POINT.decode(tl), b8 = POINT.decode(br2);
|
|
22110
|
+
rect = { left: a2.x, top: a2.y, right: b8.x, bottom: b8.y };
|
|
22111
|
+
}
|
|
22112
|
+
}
|
|
22113
|
+
}
|
|
22114
|
+
const iStr = OS64 ? Number(dvTb.getBigUint64(TBBUTTON_ISTRING, true)) : dvTb.getUint32(TBBUTTON_ISTRING, true);
|
|
22115
|
+
let tooltip = null;
|
|
22116
|
+
if (iStr >= 65536 && ReadProcessMemory(proc, iStr, tipBuf, 256, NULL)) {
|
|
22117
|
+
const dvTip = new DataView(tipBuf);
|
|
22118
|
+
let s2 = "";
|
|
22119
|
+
for (let off = 0; off < 256; off += 2) {
|
|
22120
|
+
const c2 = dvTip.getUint16(off, true);
|
|
22121
|
+
if (c2 === 0)
|
|
22122
|
+
break;
|
|
22123
|
+
s2 += String.fromCharCode(c2);
|
|
22124
|
+
}
|
|
22125
|
+
tooltip = s2 === "" ? null : s2;
|
|
22126
|
+
}
|
|
22127
|
+
out.push({ area, index: i2, hWnd, uID, tooltip, rect });
|
|
22128
|
+
}
|
|
22129
|
+
} finally {
|
|
22130
|
+
VirtualFreeEx(proc, remote, 0, 32768);
|
|
22131
|
+
CloseHandle(proc);
|
|
22132
|
+
}
|
|
22133
|
+
}
|
|
22134
|
+
function collectArea(root, area, out) {
|
|
22135
|
+
for (const tb of findToolbars(root))
|
|
22136
|
+
readToolbar(tb, area, out);
|
|
22137
|
+
}
|
|
22138
|
+
function collectVisible(root, out) {
|
|
22139
|
+
let main = null;
|
|
22140
|
+
let mainRight = -Infinity;
|
|
22141
|
+
for (const tb of findToolbars(root)) {
|
|
22142
|
+
const rc2 = RECT.alloc();
|
|
22143
|
+
if (!GetWindowRect(tb, rc2.ptr))
|
|
22144
|
+
continue;
|
|
22145
|
+
const right = RECT.decode(rc2).right;
|
|
22146
|
+
if (right > mainRight) {
|
|
22147
|
+
mainRight = right;
|
|
22148
|
+
main = tb;
|
|
22149
|
+
}
|
|
22150
|
+
}
|
|
22151
|
+
if (main)
|
|
22152
|
+
readToolbar(main, "visible", out);
|
|
22153
|
+
}
|
|
22154
|
+
function listTrayIcons() {
|
|
22155
|
+
const icons = [];
|
|
22156
|
+
const tray = FindWindow("Shell_TrayWnd", NULL);
|
|
22157
|
+
if (tray) {
|
|
22158
|
+
const notifyArea = FindWindowEx(tray, NULL, "TrayNotifyWnd", NULL);
|
|
22159
|
+
collectVisible(notifyArea ? notifyArea : tray, icons);
|
|
22160
|
+
}
|
|
22161
|
+
const overflow = FindWindow("NotifyIconOverflowWindow", NULL);
|
|
22162
|
+
if (overflow)
|
|
22163
|
+
collectArea(overflow, "overflow", icons);
|
|
22164
|
+
return icons;
|
|
22165
|
+
}
|
|
22166
|
+
function probeTrayIcon(hWnd, uID) {
|
|
22167
|
+
if (!Shell_NotifyIconGetRect)
|
|
22168
|
+
return { hr: -1, hrName: "unsupported", rect: null };
|
|
22169
|
+
const rc2 = RECT.alloc();
|
|
22170
|
+
const hr2 = Shell_NotifyIconGetRect({ cbSize: NOTIFYICONIDENTIFIER.size, hWnd, uID }, rc2.ptr);
|
|
22171
|
+
const hrName = hr2 === 0 ? "found" : hr2 === 1 ? "hidden" : hr2 === -2147467259 ? "not_found" : "hr=0x" + (hr2 >>> 0).toString(16);
|
|
22172
|
+
if (hr2 !== 0)
|
|
22173
|
+
return { hr: hr2, hrName, rect: null };
|
|
22174
|
+
const r2 = RECT.decode(rc2);
|
|
22175
|
+
return { hr: hr2, hrName, rect: { left: r2.left, top: r2.top, right: r2.right, bottom: r2.bottom } };
|
|
22176
|
+
}
|
|
22177
|
+
|
|
22178
|
+
// _build/examples/execd/main.js
|
|
21803
22179
|
function parseArgs() {
|
|
21804
|
-
let
|
|
22180
|
+
let gui20 = true;
|
|
21805
22181
|
let token = null;
|
|
21806
22182
|
const args = typeof scriptArgs === "undefined" ? [] : scriptArgs;
|
|
21807
22183
|
const normToken2 = (v2) => v2 === "" ? null : v2;
|
|
21808
22184
|
for (let i2 = 0; i2 < args.length; i2++) {
|
|
21809
22185
|
const a2 = args[i2] ?? "";
|
|
21810
22186
|
if (a2 === "--nogui") {
|
|
21811
|
-
|
|
22187
|
+
gui20 = false;
|
|
21812
22188
|
} else if (a2 === "--gui") {
|
|
21813
|
-
|
|
22189
|
+
gui20 = (args[++i2] ?? "") !== "0";
|
|
21814
22190
|
} else if (a2.startsWith("--gui=")) {
|
|
21815
|
-
|
|
22191
|
+
gui20 = a2.slice(6) !== "0";
|
|
21816
22192
|
} else if (a2 === "--token") {
|
|
21817
22193
|
token = normToken2(args[++i2] ?? "");
|
|
21818
22194
|
} else if (a2.startsWith("--token=")) {
|
|
21819
22195
|
token = normToken2(a2.slice(8));
|
|
21820
22196
|
}
|
|
21821
22197
|
}
|
|
21822
|
-
return { gui:
|
|
22198
|
+
return { gui: gui20, token };
|
|
21823
22199
|
}
|
|
21824
22200
|
var cfg = parseArgs();
|
|
21825
22201
|
var log = new RequestLog(100);
|
|
@@ -21840,8 +22216,6 @@ function formatLine(e2) {
|
|
|
21840
22216
|
res = e2.exit === null ? "ok" : e2.exit === 0 ? "exit 0" : "exit " + e2.exit;
|
|
21841
22217
|
} else if (e2.status === 401) {
|
|
21842
22218
|
res = "unauthorized";
|
|
21843
|
-
} else if (e2.status === 404) {
|
|
21844
|
-
res = "404";
|
|
21845
22219
|
} else if (e2.status === 504) {
|
|
21846
22220
|
res = "timeout";
|
|
21847
22221
|
} else {
|
|
@@ -21855,7 +22229,7 @@ function formatInfo() {
|
|
|
21855
22229
|
function refreshGui() {
|
|
21856
22230
|
if (!guiUpdater || guiTimer !== null)
|
|
21857
22231
|
return;
|
|
21858
|
-
guiTimer =
|
|
22232
|
+
guiTimer = os7.setTimeout(() => {
|
|
21859
22233
|
guiTimer = null;
|
|
21860
22234
|
const u2 = guiUpdater;
|
|
21861
22235
|
if (u2)
|
|
@@ -21866,6 +22240,9 @@ function appendLog(e2) {
|
|
|
21866
22240
|
log.push(e2);
|
|
21867
22241
|
refreshGui();
|
|
21868
22242
|
}
|
|
22243
|
+
function logReq(t0, cmd, status, note, exit = null) {
|
|
22244
|
+
appendLog({ ts: Date.now() / 1e3, cmd, status, exit, durMs: Date.now() - t0, note });
|
|
22245
|
+
}
|
|
21869
22246
|
function bumpWorkers(d2) {
|
|
21870
22247
|
activeWorkers += d2;
|
|
21871
22248
|
refreshGui();
|
|
@@ -21875,20 +22252,20 @@ function initGui() {
|
|
|
21875
22252
|
return;
|
|
21876
22253
|
try {
|
|
21877
22254
|
const root = createRoot({
|
|
21878
|
-
text: "
|
|
22255
|
+
text: "execd \xB7 :" + (boundPort || 8080),
|
|
21879
22256
|
x: 200,
|
|
21880
22257
|
y: 200,
|
|
21881
22258
|
width: 560,
|
|
21882
22259
|
height: 420
|
|
21883
22260
|
});
|
|
21884
22261
|
root.render((0, import_jsx_runtime16.jsx)(LogPanel, {}));
|
|
21885
|
-
|
|
22262
|
+
gui19.ShowWindow(
|
|
21886
22263
|
root.hwnd,
|
|
21887
22264
|
9
|
|
21888
|
-
/*
|
|
22265
|
+
/* ShowWindowCmd.RESTORE */
|
|
21889
22266
|
);
|
|
21890
22267
|
} catch (ex) {
|
|
21891
|
-
console.error("[
|
|
22268
|
+
console.error("[execd] gui init failed (fallback headless):", ex);
|
|
21892
22269
|
}
|
|
21893
22270
|
}
|
|
21894
22271
|
function LogPanel() {
|
|
@@ -21914,7 +22291,7 @@ function authCheck(req) {
|
|
|
21914
22291
|
}
|
|
21915
22292
|
function runInWorker(cmd, signal, timeoutMs) {
|
|
21916
22293
|
const spawnCmd = cmd;
|
|
21917
|
-
const worker = new os6.Worker("data:text/javascript;base64,aW1wb3J0KmFzIGZlIGZyb20ib3MiO2ltcG9ydCphcyB4ZSBmcm9tInN0ZCI7aW1wb3J0KmFzIHkgZnJvbSJmZmkiO2ltcG9ydCphcyBldCBmcm9tIm9zIjtpbXBvcnQqYXMgSyBmcm9tInN0ZCI7aW1wb3J0KmFzIHJ0IGZyb20id2luIjt2YXIgZ2U9eyJ1dGYtOCI6InV0Zi04Iix1dGY4OiJ1dGYtOCIsInVuaWNvZGUtMS0xLXV0Zi04IjoidXRmLTgiLCJ1dGYtMTYiOiJ1dGYtMTZsZSIsInV0Zi0xNmxlIjoidXRmLTE2bGUiLCJ1dGYtMTZiZSI6InV0Zi0xNmJlIn07ZnVuY3Rpb24gT3QodCl7aWYoIXQpcmV0dXJuInV0Zi04IjtsZXQgZT1nZVt0LnRyaW0oKS50b0xvd2VyQ2FzZSgpXTtpZihlKXJldHVybiBlO3Rocm93IG5ldyBSYW5nZUVycm9yKGBUaGUgZW5jb2RpbmcgbGFiZWwgIiR7dH0iIGlzIG5vdCBzdXBwb3J0ZWRgKX1mdW5jdGlvbiBEZSh0LGUpe2xldCByPSIiO2ZvcihsZXQgbz0wO288dC5sZW5ndGg7KXtsZXQgbj10W28rK107aWYobjwxMjgpe3IrPVN0cmluZy5mcm9tQ2hhckNvZGUobik7Y29udGludWV9aWYobjwxOTIpe3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigidW5leHBlY3RlZCBjb250aW51YXRpb24gYnl0ZSIpfSkoKToiXHVGRkZEIjtjb250aW51ZX1sZXQgaSxjO2lmKG48MjI0KXtpZihvPj10Lmxlbmd0aCl7cis9ZT8oKCk9Pnt0aHJvdyBuZXcgVHlwZUVycm9yKCJpbmNvbXBsZXRlIHV0Zi04Iil9KSgpOiJcdUZGRkQiO2JyZWFrfWxldCBzPXRbbysrXTtpZigocyYxOTIpIT09MTI4KXtyKz0iXHVGRkZEIjtjb250aW51ZX1pPShuJjMxKTw8NnxzJjYzLGM9MTI4fWVsc2UgaWYobjwyNDApe2lmKG8rMT49dC5sZW5ndGgpe3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW5jb21wbGV0ZSB1dGYtOCIpfSkoKToiXHVGRkZEIjticmVha31sZXQgcz10W28rK10scD10W28rK107aWYoKHMmMTkyKSE9PTEyOHx8KHAmMTkyKSE9PTEyOCl7cis9Ilx1RkZGRCI7Y29udGludWV9aT0obiYxNSk8PDEyfChzJjYzKTw8NnxwJjYzLGM9MjA0OH1lbHNlIGlmKG48MjQ4KXtpZihvKzI+PXQubGVuZ3RoKXtyKz1lPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoImluY29tcGxldGUgdXRmLTgiKX0pKCk6Ilx1RkZGRCI7YnJlYWt9bGV0IHM9dFtvKytdLHA9dFtvKytdLGE9dFtvKytdO2lmKChzJjE5MikhPT0xMjh8fChwJjE5MikhPT0xMjh8fChhJjE5MikhPT0xMjgpe3IrPSJcdUZGRkQiO2NvbnRpbnVlfWk9KG4mNyk8PDE4fChzJjYzKTw8MTJ8KHAmNjMpPDw2fGEmNjMsYz02NTUzNn1lbHNle3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW52YWxpZCB1dGYtOCBzdGFydCIpfSkoKToiXHVGRkZEIjtjb250aW51ZX1pZihpPGN8fGk+PTU1Mjk2JiZpPD01NzM0M3x8aT4xMTE0MTExKXtyKz1lPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoImludmFsaWQgdXRmLTggY29kZXBvaW50Iil9KSgpOiJcdUZGRkQiO2NvbnRpbnVlfWk8PTY1NTM1P3IrPVN0cmluZy5mcm9tQ2hhckNvZGUoaSk6KGktPTY1NTM2LHIrPVN0cmluZy5mcm9tQ2hhckNvZGUoNTUyOTZ8aT4+MTAsNTYzMjB8aSYxMDIzKSl9cmV0dXJuIHJ9ZnVuY3Rpb24gRWUodCxlLHIpe2xldCBvPW5ldyBEYXRhVmlldyh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQsdC5ieXRlTGVuZ3RoKSxuPSIiO2ZvcihsZXQgaT0wO2krMTx0Lmxlbmd0aDtpKz0yKXtsZXQgYz1vLmdldFVpbnQxNihpLGUpO2lmKGM+PTU1Mjk2JiZjPD01NjMxOSl7aWYoaSs9MixpKzE+PXQubGVuZ3RoKXtuKz1yPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoInRydW5jYXRlZCBzdXJyb2dhdGUgcGFpciIpfSkoKToiXHVGRkZEIjticmVha31sZXQgcz1vLmdldFVpbnQxNihpLGUpO3M+PTU2MzIwJiZzPD01NzM0Mz9uKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGMscyk6KG4rPXI/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW52YWxpZCBzdXJyb2dhdGUgcGFpciIpfSkoKToiXHVGRkZEIixpLT0yKX1lbHNlIGM+PTU2MzIwJiZjPD01NzM0Mz9uKz1yPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoInVuZXhwZWN0ZWQgdHJhaWxpbmcgc3Vycm9nYXRlIil9KSgpOiJcdUZGRkQiOm4rPVN0cmluZy5mcm9tQ2hhckNvZGUoYyl9cmV0dXJuIG59dmFyIHB0PWNsYXNze19lbmNvZGluZztfZmF0YWw7X2lnbm9yZUJPTTtjb25zdHJ1Y3RvcihlLHIpe3RoaXMuX2VuY29kaW5nPU90KGUpLHRoaXMuX2ZhdGFsPXI/LmZhdGFsPz8hMSx0aGlzLl9pZ25vcmVCT009cj8uaWdub3JlQk9NPz8hMX1nZXQgZW5jb2RpbmcoKXtyZXR1cm4gdGhpcy5fZW5jb2Rpbmd9Z2V0IGZhdGFsKCl7cmV0dXJuIHRoaXMuX2ZhdGFsfWdldCBpZ25vcmVCT00oKXtyZXR1cm4gdGhpcy5faWdub3JlQk9NfWRlY29kZShlKXtpZighZSlyZXR1cm4iIjtsZXQgcj1lIGluc3RhbmNlb2YgVWludDhBcnJheT9lOmUgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcj9uZXcgVWludDhBcnJheShlKTpuZXcgVWludDhBcnJheShlLmJ1ZmZlcixlLmJ5dGVPZmZzZXQsZS5ieXRlTGVuZ3RoKTtpZih0aGlzLl9lbmNvZGluZz09PSJ1dGYtOCIpcmV0dXJuIERlKHIsdGhpcy5fZmF0YWwpO2xldCBvPXRoaXMuX2VuY29kaW5nPT09InV0Zi0xNmxlIixuPTA7aWYoci5sZW5ndGg+PTImJiF0aGlzLl9pZ25vcmVCT00pe2xldCBpPW8/clswXTpyWzFdLHM9KG8/clsxXTpyWzBdKTw8OHxpOyhzPT09NjUyNzl8fHM9PT02NTUzNCkmJihuPTIpfXJldHVybiBFZShyLnNsaWNlKG4pLG8sdGhpcy5fZmF0YWwpfX0sYXQ9Y2xhc3N7X2VuY29kaW5nO2NvbnN0cnVjdG9yKGUpe3RoaXMuX2VuY29kaW5nPU90KGUpfWdldCBlbmNvZGluZygpe3JldHVybiB0aGlzLl9lbmNvZGluZ31lbmNvZGUoZSl7aWYoIWUpcmV0dXJuIG5ldyBVaW50OEFycmF5KDApO2lmKHRoaXMuX2VuY29kaW5nPT09InV0Zi04Iil7bGV0IGk9W107Zm9yKGxldCBjPTA7YzxlLmxlbmd0aDtjKyspe2xldCBzPWUuY2hhckNvZGVBdChjKTtpZihzPDEyOClpLnB1c2gocyk7ZWxzZSBpZihzPDIwNDgpaS5wdXNoKDE5MnxzPj42LDEyOHxzJjYzKTtlbHNlIGlmKHM8NTUyOTZ8fHM+PTU3MzQ0KWkucHVzaCgyMjR8cz4+MTIsMTI4fHM+PjYmNjMsMTI4fHMmNjMpO2Vsc2V7YysrO2xldCBwPWUuY2hhckNvZGVBdChjKTtzPTY1NTM2KygocyYxMDIzKTw8MTApfHAmMTAyMyxpLnB1c2goMjQwfHM+PjE4LDEyOHxzPj4xMiY2MywxMjh8cz4+NiY2MywxMjh8cyY2Myl9fXJldHVybiBuZXcgVWludDhBcnJheShpKX1sZXQgcj10aGlzLl9lbmNvZGluZz09PSJ1dGYtMTZsZSIsbz1uZXcgQXJyYXlCdWZmZXIoZS5sZW5ndGgqMiksbj1uZXcgRGF0YVZpZXcobyk7Zm9yKGxldCBpPTA7aTxlLmxlbmd0aDtpKyspbi5zZXRVaW50MTYoaSoyLGUuY2hhckNvZGVBdChpKSxyKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkobyl9fTt0eXBlb2YgZ2xvYmFsVGhpcy5UZXh0RGVjb2Rlcj4idSImJihnbG9iYWxUaGlzLlRleHREZWNvZGVyPXB0KTt0eXBlb2YgZ2xvYmFsVGhpcy5UZXh0RW5jb2Rlcj4idSImJihnbG9iYWxUaGlzLlRleHRFbmNvZGVyPWF0KTtpbXBvcnR7YnVmZmVyUHRyIGFzIFdlfWZyb20iZmZpIjtpbXBvcnQqYXMgUnQgZnJvbSJvcyI7dmFyIFRlPVsidm9pZCIsInU4IiwiaTgiLCJ1MTYiLCJpMTYiLCJ1MzIiLCJpMzIiLCJ1NjQiLCJpNjQiLCJmMzIiLCJmNjQiLCJwdHIiXSx1dD0vXjwoW0EtWmEtel9dXHcqfCk+cHRyKCF8QFtBLVphLXpfXVx3Kik/JC87ZnVuY3Rpb24gUih0KXtyZXR1cm4gdXQudGVzdCh0KX12YXIgQXQ9L148KFtBLVphLXpfXVx3Kik+JC87ZnVuY3Rpb24gTSh0KXtyZXR1cm4gQXQudGVzdCh0KX1mdW5jdGlvbiBrKHQpe3JldHVybiBBdC5leGVjKHQpPy5bMV18fCIifWZ1bmN0aW9uIGx0KHQpe3JldHVybiB1dC5leGVjKHQpPy5bMV18fCIifXZhciB0dD10PT57aWYoUih0KSlyZXR1cm4icHRyIjtpZihNKHQpKXRocm93IG5ldyBFcnJvcihgZmZpOiBjVG9rZW5Ub1R5cGU6IGJ5LXZhbHVlIHRva2VuICIke3R9IiBoYXMgbm8gc2NhbGFyIHNsb3QgdHlwZWApO3JldHVybiB0fSxBPVJ0LmFyY2g9PT0ieDY0Ij84OjQsJD17dTg6MSxpODoxLHUxNjoyLGkxNjoyLHUzMjo0LGkzMjo0LHU2NDo4LGk2NDo4LGYzMjo0LGY2NDo4fSxJPTA7ZnVuY3Rpb24gWSh0KXtpZihSKHQpKXtsZXQgbj11dC5leGVjKHQpLGk9bj8uWzFdfHwiIjtyZXR1cm4gbj8uWzJdPy5zdGFydHNXaXRoKCJAIik/YDwke2l9PnB0cmA6dH1pZihNKHQpKXJldHVybiB0O2xldCBlPXQuaW5kZXhPZigiQCIpLHI9ZT49MD90LnNsaWNlKDAsZSk6dDtpZigoZTwwfHwvXltBLVphLXpfXVx3KiQvLnRlc3QodC5zbGljZShlKzEpKSkmJnIhPT0icHRyIiYmVGUuaW5jbHVkZXMocikpcmV0dXJuIHI7dGhyb3cgbmV3IEVycm9yKCJVbmtub3duIHRva2VuOiAiK3QpfWZ1bmN0aW9uIFYodCxlLHIpe3N3aXRjaChyKXtjYXNlInU4IjpyZXR1cm4gdC5nZXRVaW50OChlKTtjYXNlImk4IjpyZXR1cm4gdC5nZXRJbnQ4KGUpO2Nhc2UidTE2IjpyZXR1cm4gdC5nZXRVaW50MTYoZSwhMCk7Y2FzZSJpMTYiOnJldHVybiB0LmdldEludDE2KGUsITApO2Nhc2UidTMyIjpyZXR1cm4gdC5nZXRVaW50MzIoZSwhMCk7Y2FzZSJpMzIiOnJldHVybiB0LmdldEludDMyKGUsITApO2Nhc2UidTY0IjpyZXR1cm4gdC5nZXRCaWdVaW50NjQoZSwhMCk7Y2FzZSJpNjQiOnJldHVybiB0LmdldEJpZ0ludDY0KGUsITApO2Nhc2UiZjMyIjpyZXR1cm4gdC5nZXRGbG9hdDMyKGUsITApO2Nhc2UiZjY0IjpyZXR1cm4gdC5nZXRGbG9hdDY0KGUsITApO2Nhc2UicHRyIjpyZXR1cm4gQT09PTg/TnVtYmVyKHQuZ2V0QmlnSW50NjQoZSwhMCkpOnQuZ2V0SW50MzIoZSwhMCl9fWZ1bmN0aW9uIGR0KHQsZSx7azpyLHY6b30pe3N3aXRjaChyKXtjYXNlInU4Ijp0LnNldFVpbnQ4KGUsTnVtYmVyKG8pKTticmVhaztjYXNlImk4Ijp0LnNldEludDgoZSxOdW1iZXIobykpO2JyZWFrO2Nhc2UidTE2Ijp0LnNldFVpbnQxNihlLE51bWJlcihvKSwhMCk7YnJlYWs7Y2FzZSJpMTYiOnQuc2V0SW50MTYoZSxOdW1iZXIobyksITApO2JyZWFrO2Nhc2UidTMyIjp0LnNldFVpbnQzMihlLG8+Pj4wLCEwKTticmVhaztjYXNlImkzMiI6dC5zZXRVaW50MzIoZSxvPj4+MCwhMCk7YnJlYWs7Y2FzZSJ1NjQiOnQuc2V0QmlnVWludDY0KGUsbywhMCk7YnJlYWs7Y2FzZSJpNjQiOnQuc2V0QmlnSW50NjQoZSxvLCEwKTticmVhaztjYXNlImYzMiI6dC5zZXRGbG9hdDMyKGUsbywhMCk7YnJlYWs7Y2FzZSJmNjQiOnQuc2V0RmxvYXQ2NChlLG8sITApO2JyZWFrO2Nhc2UicHRyIjp7aWYobz09bnVsbCl0aHJvdyBuZXcgRXJyb3IoImZmaTogZ290IG51bGwvdW5kZWZpbmVkIGZvciBhIHB0ciBzbG90OyBwYXNzIHRoZSBpbXBvcnRlZCBOVUxMIGNvbnN0YW50IGZvciBlbXB0eSIpO0E9PT04P3Quc2V0QmlnVWludDY0KGUsQmlnSW50LmFzVWludE4oNjQsQmlnSW50KG8pKSwhMCk6dC5zZXRVaW50MzIoZSxvPj4+MCwhMCk7YnJlYWt9fX1mdW5jdGlvbiB2KHQsZSxyKXtsZXR7azpvLHY6bn09cjtpZihvPT09InU4Inx8bz09PSJpOCJ8fG89PT0idTE2Inx8bz09PSJpMTYiKXt0LnNldFVpbnQzMihlLE51bWJlcihuKT4+PjAsITApO3JldHVybn1kdCh0LGUscil9dmFyIGI9Y2xhc3MgZXh0ZW5kcyBBcnJheUJ1ZmZlcntwdHI7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSksdGhpcy5wdHI9V2UodGhpcyl9fTtmdW5jdGlvbiBmdCh0LGUpe3JldHVybiBlW3RdfXZhciBCdD1uZXcgTWFwO2Z1bmN0aW9uIGJlKHQpe2xldCBlPUJ0LmdldCh0KTtpZihlIT09dm9pZCAwKXJldHVybiBlO2xldCByPXJ0LkxvYWRMaWJyYXJ5KHQpO2lmKCFyKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IExvYWRMaWJyYXJ5KCIke3R9IikgZmFpbGVkYCk7cmV0dXJuIEJ0LnNldCh0LHIpLHJ9ZnVuY3Rpb24gVXQodCl7bGV0IGU9dC5zcGxpdCgiIC0+ICIpO2lmKGUubGVuZ3RoIT09Mil0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiBpbnZhbGlkIHNpZ25hdHVyZSAiJHt0fSIgKGV4cGVjdGVkICJhcmcxIGFyZzIgLT4gcmV0IilgKTtsZXQgcj1lWzBdLnNwbGl0KCIgIikuZmlsdGVyKGk9PmkhPT0iIiksbz1bXTtmb3IobGV0IGkgb2Ygcil7bGV0IGM9WShpKTtpZihjPT09InZvaWQiKXRocm93IG5ldyBFcnJvcigiVm9pZCBjYW4gbm90IGluIGFyZ3MiKTtvLnB1c2goYyl9bGV0IG49WShlWzFdKTtpZihNKG4pKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICIke3R9IjogYnktdmFsdWUgc3RydWN0IGF0IHRoZSByZXR1cm4gcG9zaXRpb24gKDwke2sobil9PikgaXMgbm90IHN1cHBvcnRlZCBcdTIwMTQgYXJndW1lbnQgcG9zaXRpb25zIG9ubHk7IHBhc3MgYSBzdHJ1Y3Qgb3V0IHRocm91Z2ggYW4gb3V0LXBhcmFtIHNsb3QgaW5zdGVhZCAoPE4+cHRyICsgY2FsbGVyIGJ1ZmZlcilgKTtyZXR1cm57YXJnVG9rZW5zOm8scmV0VG9rZW46bixzaWc6dH19ZnVuY3Rpb24gTmUodCxlLHIsbyl7bGV0IG49VXQoZSk7Zm9yKGxldCBpIG9mIG4uYXJnVG9rZW5zKXtpZighTShpKSljb250aW51ZTtsZXQgYz1rKGkpLHM9ZnQoYyxyKTtpZighc3x8dHlwZW9mIHMuZW5jb2RlIT0iZnVuY3Rpb24iKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICR7ZX06IGJ5LXZhbHVlIHBvc2l0aW9uIDwke2N9PiBoYXMgbm8gcmVnaXN0ZXJlZCBsYXlvdXQgKGF2YWlsYWJsZTogJHtPYmplY3Qua2V5cyhyKS5qb2luKCIsICIpfHwibm9uZSJ9KWApO2lmKHR5cGVvZiBzLnNpemUhPSJudW1iZXIifHxzLnNpemU8MSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke2V9OiBieS12YWx1ZSBwb3NpdGlvbiA8JHtjfT4gcmVxdWlyZXMgYSBzdHJ1Y3QgbGF5b3V0IHdpdGggc2l6ZSA+PSAxIChnb3QgJHtzLnNpemV9OyBub24tc3RydWN0IGNvZGVjcyBleHBvc2Ugbm8gc2l6ZSlgKX1yZXR1cm4oLi4uaSk9PkllKHQsbixpLHIsbyl9dmFyIHh0PXt1ODo0LGk4OjQsdTE2OjQsaTE2OjQsdTMyOjQsaTMyOjQsdTY0OjgsaTY0OjgsZjMyOjQsZjY0OjgscHRyOkF9LEd0PTQ7ZnVuY3Rpb24gSWUodCx7YXJnVG9rZW5zOmUscmV0VG9rZW46cixzaWc6b30sbixpLGMpe2xldCBzPWV0LmFyY2g9PT0ieDY0IixwPShsLEQpPT57aWYoTShsKSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiBnZXRXaWR0aDogYnktdmFsdWUgdG9rZW4gIiR7bH0iIChkaXNwYXRjaGVkIGJ5IHdpZHRoT2YpYCk7cmV0dXJuIEQ/ODpSKGwpP0E6eHRbbF19LGE9bD0+e2lmKE0obCkpe2lmKHMpcmV0dXJuIDg7bGV0IEQ9ZnQoayhsKSxpKTtpZighRCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiA8JHtrKGwpfT4gYnktdmFsdWUgcG9zaXRpb24gaGFzIG5vIHJlZ2lzdGVyZWQgbGF5b3V0YCk7bGV0IEU9RC5zaXplO3JldHVybiBFJTQ9PT0wP0U6RSs0LUUlNH1yZXR1cm4gcChsLHMpfSx1PTA7Zm9yKGxldCBsIG9mIGUpdSs9YShsKTtzJiZlLmxlbmd0aDxHdCYmKHU9R3QqOCk7bGV0IHg9bmV3IEFycmF5QnVmZmVyKHUpLGQ9bmV3IERhdGFWaWV3KHgpLHc9W10sZj0wO2ZvcihsZXQgbD0wO2w8ZS5sZW5ndGg7bCsrKXtsZXQgRD1lW2xdLEU9RC5lbmRzV2l0aCgiISIpLEM9bltsXTtpZihSKEQpKXtsZXQgaD1sdChEKTtpZih0eXBlb2YgQz09Im51bWJlciIpe2lmKEUmJkM9PT0wKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICR7b306IGFyZyMke2wrMX0gPCR7aH0+cHRyISBnb3QgMCAobnVsbCBwb2ludGVyIGZvcmJpZGRlbiBoZXJlOyB0aGUgdG9rZW4gbWFya3MgdGhpcyBwb3NpdGlvbiBub24tbnVsbClgKTt2KGQsZix7azoicHRyIix2OkN9KX1lbHNle2lmKEM9PW51bGwpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogPCR7aH0+cHRyIGdvdCAke1N0cmluZyhDKX07IHBhc3MgdGhlIGltcG9ydGVkIE5VTEwgY29uc3RhbnQgZm9yIGFuIGVtcHR5IHBvaW50ZXJgKTtsZXQgVD1pW2hdO2lmKCFUKXRocm93IG5ldyBFcnJvcihoPT09IiI/YGZmaS1iaW5kOiA8PnB0ciBleHBlY3RzIG51bWJlciAoTlVMTCB8IFB0ciksIGdvdCAke3R5cGVvZiBDfTsgdXNlIDxCWVRFPnB0ciB3aXRoIGEgUHRyQXJyYXlCdWZmZXIgKG5ldyBQdHJBcnJheUJ1ZmZlcihuKSksIG9yIGZmaS5idWZmZXJQdHIoYnVmKSBmb3IgYW4gYWRkcmVzc2A6YGZmaS1iaW5kOiB1bmtub3duIGxheW91dCAiPCR7aH0+cHRyIiAoYXZhaWxhYmxlOiAke09iamVjdC5rZXlzKGkpLmpvaW4oIiwgIil8fCJub25lIn0pYCk7aWYoIVQuZW5jb2RlKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IDwke2h9PnB0ciBoYXMgbm8gZW5jb2RlciAob3V0LW9ubHkgY29kZWMpYCk7bGV0IEg9VC5lbmNvZGUoQyk7dy5wdXNoKEgpO2xldCBMPUgucHRyO2lmKHR5cGVvZiBMIT0ibnVtYmVyIil0aHJvdyBuZXcgRXJyb3IoImZmaS1iaW5kOiBjb2RlYy5lbmNvZGUgbXVzdCByZXR1cm4gYSBQdHJBcnJheUJ1ZmZlciwgZ290IHBsYWluIEFycmF5QnVmZmVyIik7aWYoRSYmTD09PTApdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogJHtvfTogYXJnIyR7bCsxfSA8JHtofT5wdHIhIGVuY29kZSBwcm9kdWNlZCAwIChudWxsIHBvaW50ZXIgZm9yYmlkZGVuIGhlcmUpYCk7dihkLGYse2s6InB0ciIsdjpMfSl9fWVsc2UgaWYoTShEKSl7bGV0IGg9ayhEKSxUPWZ0KGgsaSk7aWYoIVQpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogJHtvfTogYXJnIyR7bCsxfSA8JHtofT4gYnktdmFsdWUgcG9zaXRpb24gaGFzIG5vIHJlZ2lzdGVyZWQgbGF5b3V0YCk7aWYoQz09bnVsbCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiA8JHtofT4gdmFsdWUgcG9zaXRpb24gZ290ICR7U3RyaW5nKEMpfTsgcGFzcyBhIHN0cnVjdCBvYmplY3QgKHVzZSA8JHtofT5wdHIgdG8gcGFzcyBhIHBvaW50ZXIpYCk7bGV0IEg9VC5zaXplO2lmKCFzfHxIPD04JiYoSCZILTEpPT09MClULmVuY29kZShDLHgsZik7ZWxzZXtsZXQgTD1uZXcgQXJyYXlCdWZmZXIoSCsxNSksUHQ9eS5idWZmZXJQdHIoTCksTXQ9KDE2LVB0JTE2KSUxNjtULmVuY29kZShDLEwsTXQpLHcucHVzaChMKSx2KGQsZix7azoicHRyIix2OlB0K010fSl9fWVsc2UgdihkLGYse2s6RCx2OkN9KTtmKz1hKEQpfWxldCBTPW5ldyBBcnJheUJ1ZmZlcig4KTt5LmZmaUNhbGwodCx4LFMscj09PSJmMzIifHxyPT09ImY2NCI/MTowKTtsZXQgVz15ZSh0dChyKSxTKTtpZihyLmVuZHNXaXRoKCIhIikmJlc9PT0wKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICR7b306IHJldHVybiAke3J9IGdvdCAwICh0aGUgdG9rZW4gcHJvbWlzZXMgQyBuZXZlciByZXR1cm5zIG51bGwgaGVyZSlgKTtpZihSKHIpJiZXIT09MCl7bGV0IGw9bHQocik7aWYobCE9PSIiKXtsZXQgRD1jW2xdO2lmKEQ/LmRlY29kZSlyZXR1cm4gRC5kZWNvZGUoVyl9fXJldHVybiBXfWZ1bmN0aW9uIHllKHQsZSl7aWYodCE9PSJ2b2lkIilyZXR1cm4gVihuZXcgRGF0YVZpZXcoZSksMCx0KX12YXIgQj17ZW5jb2RlOnQ9PntsZXQgZT1uZXcgVGV4dEVuY29kZXIoInV0Zi0xNmxlIikuZW5jb2RlKHQrIlwwIikscj1uZXcgYihlLmJ5dGVMZW5ndGgpO3JldHVybiBuZXcgVWludDhBcnJheShyKS5zZXQoZSkscn0sZGVjb2RlOnQ9PntpZih0eXBlb2YgdD09Im51bWJlciIpe2xldCBuPSIiLGk9dCxjPWk7Zm9yKDs7KXtsZXQgcz15LnJlYWRCeXRlKGkpLHA9eS5yZWFkQnl0ZShpKzEpO2lmKHM9PT0wJiZwPT09MClyZXR1cm4gbjtpZihuKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHN8cDw8OCksaSs9MixpLWM+MTw8MjEpdGhyb3cgbmV3IEVycm9yKCJmZmktYmluZDogV0NIQVIgZGVjb2RlIGV4Y2VlZGVkIDRNaUIgd2l0aG91dCBOVUwiKX19bGV0IGU9bmV3IFVpbnQ4QXJyYXkodCkscj1lLmxlbmd0aCYtMixvPSIiO2ZvcihsZXQgbj0wO248cjtuKz0yKXtsZXQgaT1lW25dfGVbbisxXTw8ODtpZihpPT09MClyZXR1cm4gbztvKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGkpfXJldHVybiBvfSxhbGxvYzoodD0yNTYpPT5uZXcgYih0KjIpfSxGZT17ZW5jb2RlOnQ9PntpZighKHQgaW5zdGFuY2VvZiBiKSl0aHJvdyBuZXcgRXJyb3IoImZmaS1iaW5kOiA8QllURT5wdHIgd2FudHMgYSBQdHJBcnJheUJ1ZmZlciAobmV3IFB0ckFycmF5QnVmZmVyKG4pIC8gQllURS5hbGxvYyAvIHN0cnVjdC5lbmNvZGUpLCBub3QgYSBwbGFpbiBBcnJheUJ1ZmZlciIpO3JldHVybiB0fSxhbGxvYzp0PT5uZXcgYih0KX0sTHQ9e1dDSEFSOkIsQllURTpGZX07ZnVuY3Rpb24gRyh0LGUscixvLG4pe2xldCBpPXJ0LkdldFByb2NBZGRyZXNzKGJlKHQpLGUpO2lmKCFpKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IHByb2MgIiR7ZX0iIG5vdCBmb3VuZCBpbiAke3R9YCk7bGV0IGM9bj8/bztyZXR1cm4gTmUoaSxyLHsuLi5MdCwuLi5vfSx7Li4uTHQsLi4uYz8/e319KX12YXIga3Q9bmV3IEZpbmFsaXphdGlvblJlZ2lzdHJ5KHQ9PntLLnByaW50ZihgW2ZmaV0gY2xvc3VyZSBsZWFrZWQgKEdDZWQgd2l0aG91dCBkaXNwb3NlKTogc2lnPSIlcyIgcHRyPTB4JXgKYCx0LnNpZyx0LnB0cil9KTtmdW5jdGlvbiBIZSh0LGUscixvLG4saSl7bGV0IGM9bmV3IERhdGFWaWV3KG4pLHM9ZXQuYXJjaD09PSJ4NjQiLHA9bmV3IERhdGFWaWV3KG8pLGE9W10sdT0wO2ZvcihsZXQgZD0wO2Q8dC5sZW5ndGg7ZCsrKXtsZXQgdz10W2RdLGY9dy50b2ssUztpZihzKXtsZXQgVz1mPT09ImYzMiJ8fGY9PT0iZjY0Ij9kPDQ/MTI4K2QqODozMisoZC00KSo4OmQ8ND9kKjg6MzIrKGQtNCkqODtTPVYocCxXLGYpfWVsc2UgUz1WKHAsdSxmKSx1Kz14dFtmXTtpZih3Lm5vbm51bGwmJlM9PT0wKXtLLnByaW50ZihgW2ZmaV0gY2xvc3VyZSAlczogYXJnIyVkIGdvdCAwICghIHByb21pc2UgdmlvbGF0ZWQgYnkgY2FsbGVyKSwgc2tpcHBpbmcgY2FsbGJhY2sKYCxpLGQrMSk7cmV0dXJufWEucHVzaChTKX1sZXQgeDt0cnl7eD1yKC4uLmEpfWNhdGNoKGQpe0sucHJpbnRmKGBbZmZpXSBjbG9zdXJlIGNhbGxiYWNrIHRocmV3OiAlcwpgLFN0cmluZyhkKSk7cmV0dXJufWlmKGUubm9ubnVsbCYmeD09PTApe0sucHJpbnRmKGBbZmZpXSBjbG9zdXJlICVzOiByZXR1cm4gZ290IDAgKCEgcHJvbWlzZSB2aW9sYXRlZCBieSBjYWxsYmFjayksIGxlYXZpbmcgcmVzdWx0IHNsb3QgMApgLGkpO3JldHVybn1lLnRvayE9PSJ2b2lkIiYmdihjLDAse2s6ZS50b2ssdjp4fSl9ZnVuY3Rpb24gX3QodCxlLHIpe2xldHthcmdUb2tlbnM6byxyZXRUb2tlbjpufT1VdCh0KTtmb3IobGV0IG0gb2YgbylpZihNKG0pKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IGNsb3N1cmUgc2lnbmF0dXJlIGNhbm5vdCB0YWtlIGEgYnktdmFsdWUgc3RydWN0ICg8JHtrKG0pfT4pOyBieS12YWx1ZSBpcyBiaW5kLW9ubHkgXHUyMDE0IHRoZSBDXHUyMTkySlMgZGlyZWN0aW9uIGhhcyBubyBzdHJ1Y3Qgc2xvdCBkZWNvZGluZyAocGFzcyBhIHBvaW50ZXIgYW5kIGRlY29kZSBvbiB0aGUgSlMgc2lkZSlgKTtsZXQgaT1vLm1hcChtPT4oe3Rvazp0dChtKSxub25udWxsOm0uZW5kc1dpdGgoIiEiKX0pKSxjPXt0b2s6dHQobiksbm9ubnVsbDpuLmVuZHNXaXRoKCIhIil9LHM9ZXQuYXJjaD09PSJ4NjQiLHA9aS5yZWR1Y2UoKG0sVyk9Pm0reHRbVy50b2tdLDApO2lmKHM/aS5sZW5ndGg+MTY6cD42NCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiBjbG9zdXJlIHNpZ25hdHVyZSBleGNlZWRzIGNhcHR1cmUgd2luZG93ICgke3M/Im1heCAxNiBwYXJhbXMiOiJtYXggNjQgc3RhY2sgYnl0ZXMifSk6ICR7dH1gKTtsZXQgYT1yPy5zdGRjYWxsPT09ITF8fHM/MDpwLHU9Yy50b2s9PT0iZjMyIj8xOmMudG9rPT09ImY2NCI/MjpjLnRvaz09PSJ1NjQifHxjLnRvaz09PSJpNjQiPzM6MCxkPXkuY2xvc3VyZU5ldyhhLHUsKG0sVyk9PntIZShpLGMsZSxtLFcsdCl9KSx3PSExLGY9KCk9Pnt3fHwodz0hMCxrdC51bnJlZ2lzdGVyKGYpLHkuY2xvc3VyZUZyZWUoZCkpfSxTPXtwdHI6ZCxkaXNwb3NlOmZ9O3JldHVybiBrdC5yZWdpc3RlcihmLHtzaWc6dCxwdHI6ZH0pLFN9aW1wb3J0KmFzIHd0IGZyb20iZmZpIjtmdW5jdGlvbiBYKHQsZSl7cmV0dXJuIHQrZS0xJn4oZS0xKX12YXIgenQ9dD0+JFt0XSE9PXZvaWQgMDtmdW5jdGlvbiBtdCh0KXtpZih0eXBlb2YgdD09InN0cmluZyIpe2xldCBlPS9eKHU4fHUxNilcWyhcZCspXF1AKHV0Zi04fHV0Zi0xNmxlKSQvLmV4ZWModCk7aWYoZSl7bGV0IGM9TnVtYmVyKGVbMl0pO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKGMpfHxjPDEpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBzdHJpbmcgbGVuZ3RoIG11c3QgYmUgYW4gaW50ZWdlciA+PSAxLCBnb3QgJHtjfWApO2xldCBzPWVbMV09PT0idTgiPzE6MjtyZXR1cm57c2l6ZTpzKmMsYWxpZ246cyx0eXBlOnt0YWc6InN0cmluZyIsZW5jb2Rpbmc6ZVszXX19fWxldCByPS9eKFteXFtcXV0rKVxbKFxkKylcXSQvLmV4ZWModCk7aWYocil7bGV0IGM9TnVtYmVyKHJbMl0pO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKGMpfHxjPDEpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBhcnJheSBsZW5ndGggbXVzdCBiZSBhbiBpbnRlZ2VyID49IDEsIGdvdCAke2N9YCk7bGV0IHM9bXQoclsxXSk7aWYocy50eXBlLnRhZz09PSJiaXRmaWVsZCIpdGhyb3cgbmV3IEVycm9yKCJmZmktc3RydWN0OiBiaXRmaWVsZHMgY2Fubm90IGJlIGFycmF5IGVsZW1lbnRzIik7cmV0dXJue3NpemU6cy5zaXplKmMsYWxpZ246cy5hbGlnbix0eXBlOnt0YWc6ImFycmF5IixlbGVtZW50VHlwZTpzLnR5cGUsZWxlbWVudFNpemU6cy5zaXplfX19bGV0IG89L14oW0EtWmEtel9dXHcqKTooXGQrKSQvLmV4ZWModCk7aWYobyl7bGV0IGM9b1sxXSxzPVkoYyk7aWYoIXp0KHMpfHxzPT09ImYzMiJ8fHM9PT0iZjY0Iil0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IGJpdGZpZWxkIHVuaXQgbXVzdCBiZSBhbiBpbnRlZ2VyIHR5cGUsIGdvdCAiJHtjfSJgKTtsZXQgcD1OdW1iZXIob1syXSksYT0kW3NdLHU9YSo4O2lmKCFOdW1iZXIuaXNJbnRlZ2VyKHApfHxwPDEpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBiaXRmaWVsZCB3aWR0aCBtdXN0IGJlIGFuIGludGVnZXIgPj0gMSwgZ290ICR7cH1gKTtpZihwPnUpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBiaXRmaWVsZCB3aWR0aCAke3B9IGV4Y2VlZHMgdW5pdCB3aWR0aCAke3V9YCk7cmV0dXJue3NpemU6YSxhbGlnbjphLHR5cGU6e3RhZzoiYml0ZmllbGQiLHVuaXQ6cyxiaXQ6MCx3aWR0aDpwfX19bGV0IG49WSh0KTtpZihSKG4pKXJldHVybntzaXplOkEsYWxpZ246QSx0eXBlOnt0YWc6ImJhc2ljIixraW5kOiJwdHIifX07aWYoIXp0KG4pKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogdW5rbm93biBraW5kICIke3R9ImApO2xldCBpPSRbbl07cmV0dXJue3NpemU6aSxhbGlnbjppLHR5cGU6e3RhZzoiYmFzaWMiLGtpbmQ6bn19fWlmKHQmJnR5cGVvZiB0PT0ib2JqZWN0Iil7bGV0IGU9dCxyPWVbIiMiXTtpZihyPT09dm9pZCAwKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogbmVzdGVkIG9iamVjdCB2YWx1ZSByZXF1aXJlcyBhICcjJyBrZXkgKCdzdHJ1Y3QnIHwgJ3VuaW9uJyB8ICdhcnJheScpIik7aWYocj09PSJhcnJheSImJiIjcGFjayJpbiBlKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogJyNwYWNrJyBpcyBvbmx5IGFsbG93ZWQgb24gc3RydWN0L3VuaW9uLCBnb3QgJyR7cn0nYCk7aWYocj09PSJhcnJheSIpe2xldCBvPWUubGVuZ3RoO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKG8pfHxvPDEpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBhcnJheSBsZW5ndGggbXVzdCBiZSBhbiBpbnRlZ2VyID49IDEsIGdvdCAke1N0cmluZyhvKX1gKTtsZXQgbj1tdChlLmVsZW1lbnQpO2lmKG4udHlwZS50YWc9PT0iYml0ZmllbGQiKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYml0ZmllbGRzIGNhbm5vdCBiZSBhcnJheSBlbGVtZW50cyIpO3JldHVybntzaXplOm4uc2l6ZSpvLGFsaWduOm4uYWxpZ24sdHlwZTp7dGFnOiJhcnJheSIsZWxlbWVudFR5cGU6bi50eXBlLGVsZW1lbnRTaXplOm4uc2l6ZX19fWlmKHI9PT0ic3RydWN0Inx8cj09PSJ1bmlvbiIpe2xldCBvPWh0KHQpO3JldHVybntzaXplOm8uc2l6ZSxhbGlnbjpvLm1heEVmZmVjdGl2ZUFsaWduLHR5cGU6e3RhZzpyLGZpZWxkczpvLmZpZWxkc319fXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogdW5rbm93biAnIycgZGVjbGFyYXRpb24gJHtKU09OLnN0cmluZ2lmeShTdHJpbmcocikpfWApfXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogaW52YWxpZCBtZW1iZXIgdmFsdWU6ICR7U3RyaW5nKHQpfWApfWZ1bmN0aW9uIGh0KHQpe2xldCBlPXRbIiMiXT09PSJzdHJ1Y3QiLHI9dFsiI3BhY2siXT8/OCxvPTEsbj0wLGk9W10sYz0wLHM9LTEscD0wLGE9MCx1PSgpPT57czwwfHwoYz1YKHMrTWF0aC5jZWlsKHAvOCksYSkscz0tMSl9O2ZvcihsZXRbeCxkXW9mIE9iamVjdC5lbnRyaWVzKHQpKXtpZih4LnN0YXJ0c1dpdGgoIiMiKSljb250aW51ZTtsZXQgdz0vXihbXkBdKylAKFxkKykkLy5leGVjKHgpLGY9dz93WzFdOngsUz13P051bWJlcih3WzJdKTowLHtzaXplOm0sYWxpZ246Vyx0eXBlOmx9PW10KGQpLEQ9dHlwZW9mIGQ9PSJzdHJpbmciJiZkLmVuZHNXaXRoKCIhIiksRT1XO2lmKHI+MCYmKEU9TWF0aC5taW4ocixFKSksUyYmKEU9TWF0aC5tYXgoRSxTKSksbC50YWc9PT0iYml0ZmllbGQiKXtpZihmLnN0YXJ0c1dpdGgoIiQiKSl0aHJvdyBuZXcgRXJyb3IoImZmaS1zdHJ1Y3Q6IGJpdGZpZWxkIG1lbWJlcnMgbXVzdCBiZSBuYW1lZCIpO2lmKCFlKXtpLnB1c2goe25hbWU6ZixvZmZzZXQ6MCxzaXplOm0sdHlwZTp7Li4ubCxiaXQ6MH19KSxvPU1hdGgubWF4KG8sRSksbj1NYXRoLm1heChuLG0pO2NvbnRpbnVlfWxldCBoPWwud2lkdGg7KHM8MHx8bSE9PWF8fHAraD5hKjgpJiYocz49MCYmdSgpLHM9WChjLEUpLHA9MCxhPW0pLGkucHVzaCh7bmFtZTpmLG9mZnNldDpzLHNpemU6bSx0eXBlOnsuLi5sLGJpdDpwfX0pLHArPWgsbz1NYXRoLm1heChvLEUpLG49TWF0aC5tYXgobixtKTtjb250aW51ZX11KCk7bGV0IEM9WChjLEUpO2lmKCFmLnN0YXJ0c1dpdGgoIiQiKSlpLnB1c2goe25hbWU6ZixvZmZzZXQ6QyxzaXplOm0sdHlwZTpsLC4uLkQ/e25vbm51bGw6ITB9Ont9fSk7ZWxzZXtpZihsLnRhZyE9PSJzdHJ1Y3QiJiZsLnRhZyE9PSJ1bmlvbiIpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBhbm9ueW1vdXMgbWVtYmVyICIke2Z9IiBtdXN0IGJlIGEgc3RydWN0L3VuaW9uYCk7Zm9yKGxldCBoIG9mIGwuZmllbGRzKWkucHVzaCh7Li4uaCxvZmZzZXQ6aC5vZmZzZXQrQ30pfWUmJihjPUMrbSksbz1NYXRoLm1heChvLEUpLG49TWF0aC5tYXgobixtKX1yZXR1cm4gdSgpLHtzaXplOlgoZT9jOm4sbyksbWF4RWZmZWN0aXZlQWxpZ246byxmaWVsZHM6aX19ZnVuY3Rpb24gJHQodCxlLHIpe2xldCBvPSRbcl07cmV0dXJuIG89PT0xP0JpZ0ludCh0LmdldFVpbnQ4KGUpKTpvPT09Mj9CaWdJbnQodC5nZXRVaW50MTYoZSwhMCkpOm89PT00P0JpZ0ludCh0LmdldFVpbnQzMihlLCEwKSk6dC5nZXRCaWdVaW50NjQoZSwhMCl9ZnVuY3Rpb24gUGUodCxlLHIsbyl7bGV0IG49JFtyXTtpZihuPT09MSl7dC5zZXRVaW50OChlLE51bWJlcihvJjB4ZmZuKSk7cmV0dXJufWlmKG49PT0yKXt0LnNldFVpbnQxNihlLE51bWJlcihvJjB4ZmZmZm4pLCEwKTtyZXR1cm59aWYobj09PTQpe3Quc2V0VWludDMyKGUsTnVtYmVyKG8mMHhmZmZmZmZmZm4pLCEwKTtyZXR1cm59dC5zZXRCaWdVaW50NjQoZSxvJjB4ZmZmZmZmZmZmZmZmZmZmZm4sITApfWZ1bmN0aW9uIE1lKHQsZSxyKXtsZXQgbz1CaWdJbnQoci53aWR0aCksbj0kdCh0LGUsci51bml0KT4+QmlnSW50KHIuYml0KSYoMW48PG8pLTFuO3JldHVybiByLnVuaXRbMF09PT0iaSImJm4mMW48PG8tMW4mJihuLT0xbjw8byksci53aWR0aD41Mz9uOk51bWJlcihuKX1mdW5jdGlvbiBPZSh0LGUscixvKXtsZXQgbj1CaWdJbnQoci53aWR0aCksaT1CaWdJbnQoci5iaXQpLGM9KDFuPDxuKS0xbixzPWM8PGkscD0kdCh0LGUsci51bml0KSxhPSh0eXBlb2Ygbz09ImJpZ2ludCI/bzpCaWdJbnQoTWF0aC50cnVuYyhvKSkpJmM7UGUodCxlLHIudW5pdCxwJn5zfGE8PGkpfXZhciBSZT17InV0Zi04IjpuZXcgVGV4dEVuY29kZXIoInV0Zi04IiksInV0Zi0xNmxlIjpuZXcgVGV4dEVuY29kZXIoInV0Zi0xNmxlIil9LEFlPXsidXRmLTgiOm5ldyBUZXh0RGVjb2RlcigidXRmLTgiLHtpZ25vcmVCT006ITB9KSwidXRmLTE2bGUiOm5ldyBUZXh0RGVjb2RlcigidXRmLTE2bGUiLHtpZ25vcmVCT006ITB9KX07ZnVuY3Rpb24gQmUodCxlLHIsbyl7bGV0IG49bmV3IFVpbnQ4QXJyYXkodC5idWZmZXIsdC5ieXRlT2Zmc2V0K2UsciksaT1vPT09InV0Zi0xNmxlIj8yOjEsYz1yO2ZvcihsZXQgcz0wO3MraTw9cjtzKz1pKWlmKG5bc109PT0wJiYoaT09PTF8fG5bcysxXT09PTApKXtjPXM7YnJlYWt9cmV0dXJuIEFlW29dLmRlY29kZShuLnN1YmFycmF5KDAsYykpfWZ1bmN0aW9uIEdlKHQsZSxyLG8sbil7bGV0IGk9bmV3IFVpbnQ4QXJyYXkodC5idWZmZXIsdC5ieXRlT2Zmc2V0K2Uscik7aS5maWxsKDApO2xldCBzPXItKG89PT0idXRmLTE2bGUiPzI6MSk7aWYoczw9MClyZXR1cm47bGV0IHA9UmVbb10uZW5jb2RlKFN0cmluZyhuPz8iIikpO2kuc2V0KHAuc3ViYXJyYXkoMCxNYXRoLm1pbihwLmxlbmd0aCxzKSkpfWZ1bmN0aW9uIExlKHQsZSxyLG8pe2xldCBuPW8uZWxlbWVudFNpemU+MD9yL28uZWxlbWVudFNpemU6MCxpPVtdO2ZvcihsZXQgYz0wO2M8bjtjKyspaS5wdXNoKFl0KHQsZStjKm8uZWxlbWVudFNpemUsby5lbGVtZW50VHlwZSxvLmVsZW1lbnRTaXplKSk7cmV0dXJuIGl9ZnVuY3Rpb24ga2UodCxlLHIsbyxuKXtsZXQgaT1vLmVsZW1lbnRTaXplPjA/ci9vLmVsZW1lbnRTaXplOjAsYz1uPz9bXTtmb3IobGV0IHM9MDtzPGk7cysrKVZ0KHQsZStzKm8uZWxlbWVudFNpemUsby5lbGVtZW50VHlwZSxvLmVsZW1lbnRTaXplLGNbc10pfWZ1bmN0aW9uIFl0KHQsZSxyLG8pe3N3aXRjaChyLnRhZyl7Y2FzZSJiYXNpYyI6cmV0dXJuIFYodCxlLHIua2luZCk7Y2FzZSJiaXRmaWVsZCI6cmV0dXJuIE1lKHQsZSxyKTtjYXNlInN0cmluZyI6cmV0dXJuIEJlKHQsZSxvLHIuZW5jb2RpbmcpO2Nhc2Uic3RydWN0IjpjYXNlInVuaW9uIjpyZXR1cm4gb3QodCxlLHIuZmllbGRzKTtjYXNlImFycmF5IjpyZXR1cm4gTGUodCxlLG8scil9fWZ1bmN0aW9uIFZ0KHQsZSxyLG8sbil7c3dpdGNoKHIudGFnKXtjYXNlImJhc2ljIjpkdCh0LGUse2s6ci5raW5kLHY6bn0pO2JyZWFrO2Nhc2UiYml0ZmllbGQiOk9lKHQsZSxyLG4/PzApO2JyZWFrO2Nhc2Uic3RyaW5nIjpHZSh0LGUsbyxyLmVuY29kaW5nLG4pO2JyZWFrO2Nhc2Uic3RydWN0IjpjYXNlInVuaW9uIjp2dCh0LGUsci5maWVsZHMsbj8/e30pO2JyZWFrO2Nhc2UiYXJyYXkiOmtlKHQsZSxvLHIsbik7YnJlYWt9fWZ1bmN0aW9uIG90KHQsZSxyKXtsZXQgbz17fTtmb3IobGV0IG4gb2Ygcil7bGV0IGk9WXQodCxlK24ub2Zmc2V0LG4udHlwZSxuLnNpemUpO2lmKG4ubm9ubnVsbCYmaT09PTApdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBkZWNvZGU6ICchJyBmaWVsZCAiJHtuLm5hbWV9IiBnb3QgMCAoQyBkaWQgbm90IGZpbGwgaXQsIG9yIGRlY29kZSB3YXMgY2FsbGVkIG9uIGFuIHVuZmlsbGVkIHNsb3QpYCk7b1tuLm5hbWVdPWl9cmV0dXJuIG99ZnVuY3Rpb24gdnQodCxlLHIsbyl7Zm9yKGxldCBuIG9mIHIpb1tuLm5hbWVdIT09dm9pZCAwJiZWdCh0LGUrbi5vZmZzZXQsbi50eXBlLG4uc2l6ZSxvW24ubmFtZV0pfWZ1bmN0aW9uIFVlKHQpe2xldHtmaWVsZHM6ZSxzaXplOnIsbWF4RWZmZWN0aXZlQWxpZ246b309aHQodCk7cmV0dXJue19fc3RydWN0OnQsc2l6ZTpyLHN0cnVjdEFsaWduOm8sZGVjb2RlOm49Pm90KHR5cGVvZiBuPT0ibnVtYmVyIj9uZXcgRGF0YVZpZXcod3QucmVhZEJ5dGVzKG4scikpOm5ldyBEYXRhVmlldyhuKSwwLGUpLGFsbG9jOihuPT57aWYobiE9PXZvaWQgMCYmKCFOdW1iZXIuaXNJbnRlZ2VyKG4pfHxuPDEpKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYWxsb2MobikgcmVxdWlyZXMgYW4gaW50ZWdlciBuID49IDEgKFBBQigwKSBuZXZlciBlc2NhcGVzIFx1MjAxNCBwYXNzIE5VTEwgZm9yIGFuIGVtcHR5IHBvaW50ZXIgcG9zaXRpb24pIik7cmV0dXJuIG5ldyBiKHIqKG4/PzEpKX0pLGVuY29kZTooKG4saSxjKT0+e2lmKG49PW51bGwpdGhyb3cgbmV3IEVycm9yKCJmZmktc3RydWN0OiBlbmNvZGUodikgcmVxdWlyZXMgYW4gYXJndW1lbnQ7IHVzZSBhbGxvYygpIGZvciBhIHplcm9lZCBvdXQtcGFyYW0gc2xvdCIpO2xldCBzPWk/P25ldyBiKHIpO3JldHVybiB2dChuZXcgRGF0YVZpZXcocyksYz8/MCxlLG4pLHN9KSxvZmZzZXRPZjpuPT57Zm9yKGxldCBpIG9mIGUpaWYoaS5uYW1lPT09bilyZXR1cm4gaS5vZmZzZXQ7dGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBubyBmaWVsZCAiJHtufSJgKX19fWZ1bmN0aW9uIF9lKHQsZSxyKXtsZXQgbz17IiMiOnR9O3IhPT12b2lkIDAmJihvWyIjcGFjayJdPXIpO2ZvcihsZXRbbixpXW9mIE9iamVjdC5lbnRyaWVzKGUpKW4uc3RhcnRzV2l0aCgiIyIpfHwob1tuXT1pKTtyZXR1cm4gb31mdW5jdGlvbiBqdCh0KXtsZXR7ZmllbGRzOmUsc2l6ZTpyfT1odCh0Ll9fc3RydWN0KSxvPShuLGkpPT57bGV0IGM9W107Zm9yKGxldCBzPTA7czxpO3MrKyljLnB1c2gob3QobixzKnIsZSkpO3JldHVybiBjfTtyZXR1cm57ZW5jb2RlOm49PntpZighQXJyYXkuaXNBcnJheShuKXx8bi5sZW5ndGg9PT0wKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogc3RydWN0QXJyYXkoZGVmKS5lbmNvZGUoZWxzKSByZXF1aXJlcyBhIG5vbi1lbXB0eSBlbGVtZW50IGFycmF5IChwYXNzIE5VTEwgZm9yIGFuIGVtcHR5IHBvaW50ZXIgcG9zaXRpb24pIik7bGV0IGk9dC5hbGxvYyhuLmxlbmd0aCk7Zm9yKGxldCBjPTA7YzxuLmxlbmd0aDtjKyspdC5lbmNvZGUobltjXSxpLGMqdC5zaXplKTtyZXR1cm4gaX0sZGVjb2RlOigobixpKT0+e2lmKGkhPT12b2lkIDAmJighTnVtYmVyLmlzSW50ZWdlcihpKXx8aTwwKSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IHN0cnVjdEFycmF5LmRlY29kZShwLCBjb3VudCkgcmVxdWlyZXMgYSBub24tbmVnYXRpdmUgaW50ZWdlciBjb3VudCwgZ290ICR7aX1gKTtpZih0eXBlb2Ygbj09Im51bWJlciIpe2lmKGk9PT12b2lkIDApdGhyb3cgbmV3IEVycm9yKCJmZmktc3RydWN0OiBzdHJ1Y3RBcnJheS5kZWNvZGUoYWRkcmVzcywgY291bnQpIHJlcXVpcmVzIGFuIGV4cGxpY2l0IGNvdW50IChhIGJhcmUgYWRkcmVzcyBjYXJyaWVzIG5vIGxlbmd0aCkiKTtyZXR1cm4gaT09PTA/W106byhuZXcgRGF0YVZpZXcod3QucmVhZEJ5dGVzKG4saSpyKSksaSl9bGV0IGM7aWYoaSE9PXZvaWQgMCl7aWYoYz1pLGMqcj5uLmJ5dGVMZW5ndGgpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBzdHJ1Y3RBcnJheS5kZWNvZGU6IGNvdW50ICR7Y30gXHhENyBzaXplICR7cn0gPSAke2Mqcn0gZXhjZWVkcyBidWZmZXIgYnl0ZUxlbmd0aCAke24uYnl0ZUxlbmd0aH1gKX1lbHNle2lmKG4uYnl0ZUxlbmd0aCVyIT09MCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IHN0cnVjdEFycmF5LmRlY29kZTogYnl0ZUxlbmd0aCAke24uYnl0ZUxlbmd0aH0gaXMgbm90IGEgbXVsdGlwbGUgb2Ygc2l6ZSAke3J9IChtaXhlZCBidWZmZXI/IHBhc3MgY291bnQgZXhwbGljaXRseSlgKTtjPW4uYnl0ZUxlbmd0aC9yfXJldHVybiBjPT09MD9bXTpvKG5ldyBEYXRhVmlldyhuKSxjKX0pfX1mdW5jdGlvbiBnKHQsZSxyKXtsZXQgbz10eXBlb2YgdD09InN0cmluZyI7cmV0dXJuIFVlKF9lKCJzdHJ1Y3QiLG8/ZTp0LChvP3I6ZSk/LnBhY2spKX12YXIgUD1nKCJSRUNUIix7bGVmdDoiaTMyIix0b3A6ImkzMiIscmlnaHQ6ImkzMiIsYm90dG9tOiJpMzIifSksaj1nKCJQT0lOVCIse3g6ImkzMiIseToiaTMyIn0pO3ZhciBudD1nKCJTVEFSVFVQSU5GT1ciLHtjYjoidTMyIixscFJlc2VydmVkOiI8PnB0ciIsbHBEZXNrdG9wOiI8PnB0ciIsbHBUaXRsZToiPD5wdHIiLGR3WDoidTMyIixkd1k6InUzMiIsZHdYU2l6ZToidTMyIixkd1lTaXplOiJ1MzIiLGR3WENvdW50Q2hhcnM6InUzMiIsZHdZQ291bnRDaGFyczoidTMyIixkd0ZpbGxBdHRyaWJ1dGU6InUzMiIsZHdGbGFnczoidTMyIix3U2hvd1dpbmRvdzoidTE2QFNob3dXaW5kb3dDbWQiLGNiUmVzZXJ2ZWQyOiJ1MTYiLGxwUmVzZXJ2ZWQyOiI8PnB0ciIsaFN0ZElucHV0OiI8SEZJTEU+cHRyIixoU3RkT3V0cHV0OiI8SEZJTEU+cHRyIixoU3RkRXJyb3I6IjxIRklMRT5wdHIifSksQ3Q9ZygiUFJPQ0VTU19JTkZPUk1BVElPTiIse2hQcm9jZXNzOiI8SFBST0NFU1M+cHRyISIsaFRocmVhZDoiPEhUSFJFQUQ+cHRyISIsZHdQcm9jZXNzSWQ6InUzMiIsZHdUaHJlYWRJZDoidTMyIn0pLEo9ZygiQklUTUFQSU5GT0hFQURFUiIse2JpU2l6ZToidTMyIixiaVdpZHRoOiJpMzIiLGJpSGVpZ2h0OiJpMzIiLGJpUGxhbmVzOiJ1MTYiLGJpQml0Q291bnQ6InUxNiIsYmlDb21wcmVzc2lvbjoidTMyIixiaVNpemVJbWFnZToidTMyIixiaVhQZWxzUGVyTWV0ZXI6ImkzMiIsYmlZUGVsc1Blck1ldGVyOiJpMzIiLGJpQ2xyVXNlZDoidTMyIixiaUNsckltcG9ydGFudDoidTMyIn0pLGl0PWcoIkJJVE1BUEZJTEVIRUFERVIiLHtiZlR5cGU6InUxNiIsYmZTaXplOiJ1MzIiLGJmUmVzZXJ2ZWQxOiJ1MTYiLGJmUmVzZXJ2ZWQyOiJ1MTYiLGJmT2ZmQml0czoidTMyIn0se3BhY2s6Mn0pO3ZhciBaPWcoIk5NSERSIix7aHduZEZyb206IjxIV05EPnB0ciIsaWRGcm9tOiI8PnB0ciIsY29kZToiaTMyIn0pLHplPWcoIlNZU1RFTVRJTUUiLHt3WWVhcjoidTE2Iix3TW9udGg6InUxNiIsd0RheU9mV2VlazoidTE2Iix3RGF5OiJ1MTYiLHdIb3VyOiJ1MTYiLHdNaW51dGU6InUxNiIsd1NlY29uZDoidTE2Iix3TWlsbGlzZWNvbmRzOiJ1MTYifSksbXI9ZygiTk1EQVRFVElNRUNIQU5HRSIse2hkcjpaLl9fc3RydWN0LGR3RmxhZ3M6InUzMiIsc3Q6emUuX19zdHJ1Y3R9KSwkZT1nKCJMSVRFTSIse21hc2s6InUzMiIsaUxpbms6ImkzMiIsc3RhdGU6InUzMiIsc3RhdGVNYXNrOiJ1MzIiLHN6SUQ6InUxNls0OF1AdXRmLTE2bGUiLHN6VXJsOiJ1MTZbMjA4NF1AdXRmLTE2bGUifSksd3I9ZygiTk1MSU5LIix7aGRyOlouX19zdHJ1Y3QsaXRlbTokZS5fX3N0cnVjdH0pLGhyPWcoIk5NQ1VTVE9NRFJBVyIse2hkcjpaLl9fc3RydWN0LGR3RHJhd1N0YWdlOiJ1MzIiLGhkYzoiPEhEQz5wdHIiLHJjOiJpMzJbNF0iLGR3SXRlbVNwZWM6Ijw+cHRyIix1SXRlbVN0YXRlOiJ1MzIiLGxJdGVtbFBhcmFtOiI8PnB0ciJ9KSxDcj1nKCJOTUxWQ1VTVE9NRFJBVyIse2hkcjpaLl9fc3RydWN0LGR3RHJhd1N0YWdlOiJ1MzIiLGhkYzoiPEhEQz5wdHIiLHJjOiJpMzJbNF0iLGR3SXRlbVNwZWM6Ijw+cHRyIix1SXRlbVN0YXRlOiJ1MzIiLGxJdGVtbFBhcmFtOiI8PnB0ciIsY2xyVGV4dDoidTMyIixjbHJUZXh0Qms6InUzMiIsaVN1Ykl0ZW06ImkzMiIsZHdJdGVtVHlwZToidTMyIn0pLFNyPWcoIk5NTElTVFZJRVciLHtoZHI6Wi5fX3N0cnVjdCxpSXRlbToiaTMyIixpU3ViSXRlbToiaTMyIix1TmV3U3RhdGU6InUzMiIsdU9sZFN0YXRlOiJ1MzIiLHVDaGFuZ2VkOiJ1MzIiLHB0QWN0aW9uOiJpMzJbMl0iLGxQYXJhbToiPD5wdHIifSk7dmFyIFllPWcoIlRWSVRFTSIse21hc2s6InUzMiIsaEl0ZW06Ijw+cHRyIixzdGF0ZToidTMyIixzdGF0ZU1hc2s6InUzMiIscHN6VGV4dDoiPD5wdHIiLGNjaFRleHRNYXg6ImkzMiIsaUltYWdlOiJpMzIiLGlTZWxlY3RlZEltYWdlOiJpMzIiLGNDaGlsZHJlbjoiaTMyIixsUGFyYW06Ijw+cHRyIn0pLGdyPWcoIlRWSU5TRVJUU1RSVUNUIix7aFBhcmVudDoiPD5wdHIiLGhJbnNlcnRBZnRlcjoiPD5wdHIiLGl0ZW06WWUuX19zdHJ1Y3R9KTt2YXIgVmU9ZygiTVNHIix7aHduZDoiPEhXTkQ+cHRyIixtZXNzYWdlOiJ1MzIiLHdQYXJhbToiPD5wdHIiLGxQYXJhbToiPD5wdHIiLHRpbWU6InUzMiIscHQ6ai5fX3N0cnVjdH0pLERyPWcoIlBBSU5UU1RSVUNUIix7aGRjOiI8SERDPnB0ciIsZkVyYXNlOiJpMzIiLHJjUGFpbnQ6UC5fX3N0cnVjdCxmUmVzdG9yZToiaTMyIixmSW5jVXBkYXRlOiJpMzIiLHJnYlJlc2VydmVkOiJ1OFszMl0ifSk7dmFyIHN0PWcoIk9TVkVSU0lPTklORk9fMTQ4Iix7ZHdPU1ZlcnNpb25JbmZvU2l6ZToidTMyIixkd01ham9yVmVyc2lvbjoidTMyIixkd01pbm9yVmVyc2lvbjoidTMyIixkd0J1aWxkTnVtYmVyOiJ1MzIiLGR3UGxhdGZvcm1JZDoidTMyIixzekNTRFZlcnNpb246InU4WzEyOF0ifSk7dmFyIE89KHQsZSxyKT0+Rygia2VybmVsMzIuZGxsIix0LGUsciksSnQ9TygiQ3JlYXRlUGlwZSIsIjw+cHRyIDw+cHRyIDw+cHRyIHUzMiAtPiBpMzIiKSxTdD1PKCJTZXRIYW5kbGVJbmZvcm1hdGlvbiIsIjxIRklMRT5wdHIhIHUzMiB1MzIgLT4gaTMyIiksS3Q9TygiQ3JlYXRlUHJvY2Vzc1ciLCI8V0NIQVI+cHRyIDxXQ0hBUj5wdHIgPD5wdHIgPD5wdHIgaTMyIHUzMiA8PnB0ciA8V0NIQVI+cHRyIDxTVEFSVFVQSU5GT1c+cHRyIDxQUk9DRVNTX0lORk9STUFUSU9OPnB0ciAtPiBpMzIiLHtTVEFSVFVQSU5GT1c6bnR9KSxYdD1PKCJXYWl0Rm9yU2luZ2xlT2JqZWN0IiwiPD5wdHIgdTMyIC0+IHUzMiIpLFp0PU8oIkdldEV4aXRDb2RlUHJvY2VzcyIsIjxIUFJPQ0VTUz5wdHIhIDxCWVRFPnB0ciAtPiBpMzIiKSxVPU8oIkNsb3NlSGFuZGxlIiwiPD5wdHIgLT4gaTMyIik7dmFyIHF0PU8oIlJlYWRGaWxlIiwiPEhGSUxFPnB0ciEgPEJZVEU+cHRyIHUzMiA8QllURT5wdHIgPD5wdHIgLT4gaTMyIik7dmFyIGd0PU8oIkdldExhc3RFcnJvciIsIiAtPiB1MzIiKSxRdD1PKCJHZXRTeXN0ZW1EaXJlY3RvcnlXIiwiPEJZVEU+cHRyIHUzMiAtPiB1MzIiKTtpbXBvcnQqYXMgdGUgZnJvbSJvcyI7dmFyIE49KHQsZSxyKT0+RygidXNlcjMyLmRsbCIsdCxlLHIpLEhyPU4oIkdldERlc2t0b3BXaW5kb3ciLCIgLT4gPEhXTkQ+cHRyIiksZWU9dGUuYXJjaD09PSJ4NjQiPyJQdHJXIjoiVyI7dmFyIER0PU4oIkdldFdpbmRvd1JlY3QiLCI8SFdORD5wdHIgPFJFQ1Q+cHRyIC0+IGkzMiIpLHJlPU4oIkdldENsaWVudFJlY3QiLCI8SFdORD5wdHIgPFJFQ1Q+cHRyIC0+IGkzMiIpO3ZhciBvZT1OKCJJc1dpbmRvd1Zpc2libGUiLCI8SFdORD5wdHIgLT4gaTMyIiksRXQ9TigiSXNJY29uaWMiLCI8SFdORD5wdHIgLT4gaTMyIik7dmFyIG5lPU4oIkdldFdpbmRvd1RleHRXIiwiPEhXTkQ+cHRyIDxCWVRFPnB0ciBpMzIgLT4gaTMyIik7dmFyIGllPU4oIkdldENsYXNzTmFtZVciLCI8SFdORD5wdHIgPEJZVEU+cHRyIGkzMiAtPiBpMzIiKSxQcj1OKCJHZXRXaW5kb3dMb25nIitlZSwiPEhXTkQ+cHRyIGkzMkBHd2xwIC0+IDw+cHRyIiksTXI9TigiU2V0V2luZG93TG9uZyIrZWUsIjxIV05EPnB0ciBpMzJAR3dscCA8PnB0ciAtPiA8PnB0ciIpO3ZhciBzZT1OKCJHZXREQyIsIjxIV05EPnB0ciAtPiA8SERDPnB0ciIpLFd0PU4oIlJlbGVhc2VEQyIsIjxIV05EPnB0ciA8SERDPnB0ciEgLT4gaTMyIiksY2U9TigiUHJpbnRXaW5kb3ciLCI8SFdORD5wdHIgPEhEQz5wdHIhIHUzMiAtPiBpMzIiKTt2YXIgcGU9TigiQ2xpZW50VG9TY3JlZW4iLCI8SFdORD5wdHIgPFBPSU5UPnB0ciAtPiBpMzIiKTt2YXIgXz1OKCJHZXRTeXN0ZW1NZXRyaWNzIiwiaTMyIC0+IGkzMiIpO3ZhciBhZT1OKCJFbnVtV2luZG93cyIsIjw+cHRyIDw+cHRyIC0+IGkzMiIpO3ZhciB6PSh0LGUscik9PkcoImdkaTMyLmRsbCIsdCxlLHIpLExyPWp0KGopO3ZhciBUdD16KCJEZWxldGVPYmplY3QiLCI8SEdESU9CSj5wdHIgLT4gaTMyIik7dmFyIGJ0PXooIkNyZWF0ZUNvbXBhdGlibGVEQyIsIjxIREM+cHRyIC0+IDxIREM+cHRyIiksTnQ9eigiQ3JlYXRlQ29tcGF0aWJsZUJpdG1hcCIsIjxIREM+cHRyISBpMzIgaTMyIC0+IDxIR0RJT0JKPnB0ciIpO3ZhciBxPXooIlNlbGVjdE9iamVjdCIsIjxIREM+cHRyISA8SEdESU9CSj5wdHIgLT4gPEhHRElPQko+cHRyIiksSXQ9eigiQml0Qmx0IiwiPEhEQz5wdHIhIGkzMiBpMzIgaTMyIGkzMiA8SERDPnB0ciBpMzIgaTMyIHUzMkBSYXN0ZXJPcCAtPiBpMzIiKSx1ZT16KCJHZXRESUJpdHMiLCI8SERDPnB0ciEgPEhHRElPQko+cHRyIHUzMiB1MzIgPEJZVEU+cHRyIDw+cHRyIHUzMiAtPiBpMzIiKTt2YXIgUT16KCJEZWxldGVEQyIsIjxIREM+cHRyISAtPiBpMzIiKTt2YXIgdmU9KHQsZSk9PkcoIm50ZGxsLmRsbCIsdCxlKSxsZT12ZSgiUnRsR2V0VmVyc2lvbiIsIjxPU1ZFUlNJT05JTkZPXzE0OD5wdHIgLT4gaTMyIik7dmFyIG1lPXQ9Pnt0cnl7bGV0IGU9eGUub3BlbigiZGlhZy5sb2ciLCJhIik7ZSYmKGUucHV0cyhgJHtEYXRlLm5vdygpfSAke3R9CmApLGUuY2xvc2UoKSl9Y2F0Y2h7fX0seXQ9MSxqZT0yNTYsSmU9NDI5NDk2NzI5NSxGPWZlLldvcmtlci5wYXJlbnQsd2U9IkM6XFxXaW5kb3dzXFxTeXN0ZW0zMiI7dHJ5e2xldCB0PUIuYWxsb2MoMjU2KSxyPVF0KHQsMjU2KT4wP0IuZGVjb2RlKHQpOiIiO3ImJih3ZT1yKX1jYXRjaCh0KXttZSgiU1lTLURJUi1GQUlMOiAiK1N0cmluZyh0KSl9dmFyIGhlPSExO3RyeXtsZXQgdD1zdC5lbmNvZGUoe2R3T1NWZXJzaW9uSW5mb1NpemU6c3Quc2l6ZX0pO2xlKHQucHRyKT09PTAmJihoZT1zdC5kZWNvZGUodCkuZHdNYWpvclZlcnNpb24+PTEwKX1jYXRjaCh0KXttZSgiVkVSLUZBSUw6ICIrU3RyaW5nKHQpKX12YXIgRnQ9ZygiUElQRV9IQU5ETEVTIix7aFJlYWQ6IjxIRklMRT5wdHIhIixoV3JpdGU6IjxIRklMRT5wdHIhIn0pO2Z1bmN0aW9uIEtlKHQsZSl7bGV0IHI9RnQuYWxsb2MoKTtpZighSnQoci5wdHIsci5wdHIrRnQub2Zmc2V0T2YoImhXcml0ZSIpLEksMCkpdGhyb3cgbmV3IEVycm9yKCJDcmVhdGVQaXBlIGVycj0iK2d0KCkpO2xldHtoUmVhZDpvLGhXcml0ZTpufT1GdC5kZWNvZGUocik7U3Qobix5dCx5dCksU3Qobyx5dCwwKTtsZXQgaT1DdC5hbGxvYygpLHM9YCR7d2V9XFxjbWQuZXhlICR7aGU/Ii91ICI6IiJ9L2MgJHtlfWA7aWYoIUt0KEkscyxJLEksMSwwLEksSSx7Y2I6bnQuc2l6ZSxkd0ZsYWdzOmplLGhTdGRPdXRwdXQ6bixoU3RkRXJyb3I6bn0saS5wdHIpKXRocm93IFUobyksVShuKSxuZXcgRXJyb3IoIkNyZWF0ZVByb2Nlc3NXIGVycj0iK2d0KCkrIiBjbWQ9IitzKTtsZXR7aFByb2Nlc3M6cCxoVGhyZWFkOmEsZHdQcm9jZXNzSWQ6dX09Q3QuZGVjb2RlKGkpO1UoYSksVShuKSxGLnBvc3RNZXNzYWdlKHt0eXBlOiJpbmZvIixpZDp0LHBpZDp1fSk7bGV0IHg9bmV3IGIoNDA5NiksZD1uZXcgVWludDhBcnJheSh4KSx3PW5ldyBiKDQpLGY9bmV3IFVpbnQzMkFycmF5KHcpO2Zvcig7ZlswXT0wLCEhcXQobyx4LDQwOTYsdyxJKTspe2xldCBsPWZbMF07aWYobD09PTApYnJlYWs7Ri5wb3N0TWVzc2FnZSh7dHlwZToiZGF0YSIsaWQ6dCxjaHVuazpkLnNsaWNlKDAsbCl9KX1YdChwLEplKTtsZXQgUz1uZXcgYig0KSxtPW5ldyBJbnQzMkFycmF5KFMpO1p0KHAsUyk7bGV0IFc9bVswXTtyZXR1cm4gVShvKSxVKHApLFd9dmFyIENlPTEzMzY5Mzc2LFhlPTAsZGU9NjU1MzYsWmU9NGU3LGN0PTUxMixxZT0yZTQsSHQ9aXQuc2l6ZStKLnNpemU7ZnVuY3Rpb24gUWUodCxlLHIpe2xldCBvPWl0LmVuY29kZSh7YmZUeXBlOjE5Nzc4LGJmU2l6ZTpIdCt0LGJmT2ZmQml0czpIdH0pLG49Si5lbmNvZGUoe2JpU2l6ZTpKLnNpemUsYmlXaWR0aDplLGJpSGVpZ2h0Oi1yLGJpUGxhbmVzOjEsYmlCaXRDb3VudDozMixiaUNvbXByZXNzaW9uOjAsYmlTaXplSW1hZ2U6dCxiaVhQZWxzUGVyTWV0ZXI6MjgzNSxiaVlQZWxzUGVyTWV0ZXI6MjgzNX0pLGk9bmV3IFVpbnQ4QXJyYXkoSHQpO3JldHVybiBpLnNldChuZXcgVWludDhBcnJheShvKSwwKSxpLnNldChuZXcgVWludDhBcnJheShuKSxpdC5zaXplKSxpfWZ1bmN0aW9uIHRyKHQsZSxyLG8sbil7bGV0IGk9bmV3IGIobypuKjQpLGM9bmV3IFVpbnQ4QXJyYXkoaSkscz1KLmVuY29kZSh7YmlTaXplOkouc2l6ZSxiaVdpZHRoOm8sYmlIZWlnaHQ6LW4sYmlQbGFuZXM6MSxiaUJpdENvdW50OjMyLGJpU2l6ZUltYWdlOm8qbio0fSk7aWYodWUoZSxyLDAsbixpLHMucHRyLFhlKSE9PW4pcmV0dXJuITE7bGV0IGE9Yy5ieXRlTGVuZ3RoO0YucG9zdE1lc3NhZ2Uoe3R5cGU6ImRhdGEiLGlkOnQsY2h1bms6UWUoYSxvLG4pfSk7Zm9yKGxldCB1PTA7dTxhO3UrPWRlKUYucG9zdE1lc3NhZ2Uoe3R5cGU6ImRhdGEiLGlkOnQsY2h1bms6Yy5zbGljZSh1LE1hdGgubWluKHUrZGUsYSkpfSk7cmV0dXJuITB9ZnVuY3Rpb24gZXIodCxlLHIsbyxuLGksYyxzLHApe2xldCBhPWJ0KHQpLHU9YT9OdCh0LHIsbyk6MDtpZighYXx8IXUpcmV0dXJuIGEmJlEoYSksITE7bGV0IHg9cShhLHUpLHc9Y2UoZSxhLDApIT09MCYmSXQobiwwLDAscyxwLGEsaSxjLENlKSE9PTA7cmV0dXJuIHEoYSx4KSxUdCh1KSxRKGEpLHd9ZnVuY3Rpb24gU2UodCxlLHIsbyxuLGksYyxzLHAsYSl7aWYoIShzPjAmJnA+MCYmcypwPD1aZSkpdGhyb3cgbmV3IEVycm9yKCJjYXB0dXJlIHNpemUgaW52YWxpZCB3PSIrcysiIGg9IitwKTtpZihhIT09bnVsbCYmIShpPj0wJiZjPj0wJiZpK3M8PWUmJmMrcDw9cikpdGhyb3cgbmV3IEVycm9yKCJjYXB0dXJlIGNyb3Agb3V0IG9mIHJhbmdlIGNyb3A9KCIraSsiLCIrYysiLCIrcysieCIrcCsiKSBmcmFtZT0iK2UrIngiK3IpO2xldCB1PXNlKEkpO2lmKCF1KXRocm93IG5ldyBFcnJvcigiR2V0REMoTlVMTCk9MFx1RkYxQVx1NjVFMFx1OEY5M1x1NTE2NVx1Njg0Q1x1OTc2Mlx1RkYwOFx1Nzg2RVx1OEJBNFx1NTcyOFx1NEVBNFx1NEU5MiBzZXNzaW9uIFx1NTQyRlx1NTJBOFx1RkYwQ1x1ODAwQ1x1OTc1RSBzc2hkL3NlcnZpY2VcdUZGMDkiKTtsZXQgeD1idCh1KSxkPXg/TnQodSxzLHApOjA7aWYoIXh8fCFkKXRocm93IHgmJlEoeCksV3QoSSx1KSxuZXcgRXJyb3IoIkNyZWF0ZUNvbXBhdGlibGVEQy9CaXRtYXAgZmFpbGVkIik7bGV0IHc9cSh4LGQpLGY9YT09PW51bGw/SXQoeCwwLDAscyxwLHUsbyxuLENlKSE9PTA6ZXIodSxhLGUscix4LGksYyxzLHApO3EoeCx3KTtsZXQgUz1mJiZ0cih0LHgsZCxzLHApO2lmKFR0KGQpLFEoeCksV3QoSSx1KSwhZil0aHJvdyBuZXcgRXJyb3IoImNhcHR1cmUgZmFpbGVkIG91dD0iK3MrIngiK3ArKGE9PT1udWxsPyIgYXQ9KCIrbysiLCIrbisiKSI6IiBod25kPSIrYSsiIGNyb3A9KCIraSsiLCIrYysiKSBmcmFtZT0iK2UrIngiK3IpKTtpZighUyl0aHJvdyBuZXcgRXJyb3IoIkdldERJQml0cyBzaG9ydCByZWFkIG91dD0iK3MrIngiK3ApO3JldHVybnt3aWR0aDpzLGhlaWdodDpwfX1mdW5jdGlvbiBycih0KXtsZXQgZT1fKDApLHI9XygxKTtpZihlPD0wfHxyPD0wKXRocm93IG5ldyBFcnJvcigiR2V0U3lzdGVtTWV0cmljcyB3PSIrZSsiIGg9IityKTtyZXR1cm4gU2UodCxlLHIsMCwwLDAsMCxlLHIsbnVsbCl9ZnVuY3Rpb24gb3IodCxlLHIsbyl7aWYobz09PSJzY3JlZW4iJiZFdChlKSE9PTApdGhyb3cgbmV3IEVycm9yKCJ3aW5kb3cgbWluaW1pemVkXHVGRjFBbW9kZT1zY3JlZW4gXHU1M0VBXHU0RjFBXHU2MjJBXHU1MjMwXHU1QjgzXHU0RTBCXHU2NUI5XHU3Njg0XHU2ODRDXHU5NzYyXHVGRjBDXHU2NTM5XHU3NTI4IG1vZGU9cHJpbnQiKTtsZXQgbj1QLmFsbG9jKCk7aWYoIUR0KGUsbi5wdHIpKXRocm93IG5ldyBFcnJvcigiR2V0V2luZG93UmVjdChod25kPSIrZSsiKT0wXHVGRjFBXHU3QTk3XHU1M0UzXHU0RTBEXHU1QjU4XHU1NzI4XHU2MjE2XHU1REYyXHU5NTAwXHU2QkMxIik7bGV0e2xlZnQ6aSx0b3A6YyxyaWdodDpzLGJvdHRvbTpwfT1QLmRlY29kZShuKSxhPXMtaSx1PXAtYyx4PTAsZD0wLHc9YSxmPXU7aWYocj09PSJjbGllbnQiKXtsZXQgVz1QLmFsbG9jKCk7aWYoIXJlKGUsVy5wdHIpKXRocm93IG5ldyBFcnJvcigiR2V0Q2xpZW50UmVjdChod25kPSIrZSsiKT0wIik7bGV0e2xlZnQ6bCx0b3A6RCxyaWdodDpFLGJvdHRvbTpDfT1QLmRlY29kZShXKTt3PUUtbCxmPUMtRDtsZXQgaD1qLmVuY29kZSh7eDowLHk6MH0pO2lmKCFwZShlLGgucHRyKSl0aHJvdyBuZXcgRXJyb3IoIkNsaWVudFRvU2NyZWVuKGh3bmQ9IitlKyIpPTAiKTtsZXQgVD1qLmRlY29kZShoKTt4PVQueC1pLGQ9VC55LWN9bGV0IFM9bz09PSJwcmludCI/MDppK3gsbT1vPT09InByaW50Ij8wOmMrZDtpZihvPT09InNjcmVlbiIpe2xldCBXPV8oNzYpLGw9Xyg3NyksRD1fKDc4KSxFPV8oNzkpLEM9TWF0aC5tYXgoUyxXKSxoPU1hdGgubWF4KG0sbCksVD1NYXRoLm1pbihTK3csVytEKSxIPU1hdGgubWluKG0rZixsK0UpO2lmKFQ8PUN8fEg8PWgpdGhyb3cgbmV3IEVycm9yKCJjYXB0dXJlIGFyZWEgb3V0c2lkZSB2aXJ0dWFsIHNjcmVlbiBhdD0oIitTKyIsIittKyIsIit3KyJ4IitmKyIpIik7Uz1DLG09aCx3PVQtQyxmPUgtaH1yZXR1cm4gU2UodCxhLHUsUyxtLHgsZCx3LGYsbz09PSJwcmludCI/ZTpudWxsKX1mdW5jdGlvbiBucih0KXtsZXQgZT1bXSxyPV90KCI8SFdORD5wdHIgPD5wdHIgLT4gaTMyIixzPT4ocyYmZS5wdXNoKHMpLGUubGVuZ3RoPHFlPzE6MCkpO3RyeXthZShyLnB0cixJKX1maW5hbGx5e3IuZGlzcG9zZSgpfWxldCBvPVAuYWxsb2MoKSxuPUIuYWxsb2MoY3QpLGk9Qi5hbGxvYyhjdCksYz1bXTtmb3IobGV0IHMgb2YgZSlpZihEdChzLG8ucHRyKSl7bGV0IHA9UC5kZWNvZGUobyksYT1uZShzLG4sY3QpLHU9aWUocyxpLGN0KTtjLnB1c2goe2h3bmQ6cyx0aXRsZTphPjA/Qi5kZWNvZGUobik6IiIsY2xhc3NOYW1lOnU+MD9CLmRlY29kZShpKToiIixyZWN0OntsZWZ0OnAubGVmdCx0b3A6cC50b3AscmlnaHQ6cC5yaWdodCxib3R0b206cC5ib3R0b219LHZpc2libGU6b2UocykhPT0wLG1pbmltaXplZDpFdChzKSE9PTB9KX1GLnBvc3RNZXNzYWdlKHt0eXBlOiJyZXN1bHQiLGlkOnQsY29kZTowLGVycm9yOm51bGwsd2luZG93czpjfSl9ZnVuY3Rpb24gaXIodCl7aWYodC50eXBlPT09InJ1biIpe2lmKHR5cGVvZiB0LmNtZCE9InN0cmluZyIpcmV0dXJuO2xldCBlPS0xLHI9bnVsbDt0cnl7ZT1LZSh0LmlkLHQuY21kKX1jYXRjaChvKXtyPVN0cmluZyhvKX1GLnBvc3RNZXNzYWdlKHt0eXBlOiJyZXN1bHQiLGlkOnQuaWQsY29kZTplLGVycm9yOnJ9KTtyZXR1cm59aWYodC50eXBlPT09IndpbmRvd3MiKXt0cnl7bnIodC5pZCl9Y2F0Y2goZSl7Ri5wb3N0TWVzc2FnZSh7dHlwZToicmVzdWx0IixpZDp0LmlkLGNvZGU6LTEsZXJyb3I6U3RyaW5nKGUpfSl9cmV0dXJufWlmKHQudHlwZT09PSJzY3JlZW5zaG90Iil0cnl7bGV0IGU9dC5od25kPz9udWxsLHt3aWR0aDpyLGhlaWdodDpvfT1lPT09bnVsbD9ycih0LmlkKTpvcih0LmlkLGUsdC5hcmVhPz8id2luZG93Iix0Lm1vZGU/PyJzY3JlZW4iKTtGLnBvc3RNZXNzYWdlKHt0eXBlOiJyZXN1bHQiLGlkOnQuaWQsY29kZTowLGVycm9yOm51bGwsd2lkdGg6cixoZWlnaHQ6b30pfWNhdGNoKGUpe0YucG9zdE1lc3NhZ2Uoe3R5cGU6InJlc3VsdCIsaWQ6dC5pZCxjb2RlOi0xLGVycm9yOlN0cmluZyhlKX0pfX1GLm9ubWVzc2FnZT10PT57aXIodC5kYXRhKSxGLm9ubWVzc2FnZT1udWxsfTsK");
|
|
22294
|
+
const worker = new os7.Worker("data:text/javascript;base64,aW1wb3J0KmFzIE90IGZyb20ib3MiO2ltcG9ydCphcyBQdCBmcm9tInN0ZCI7aW1wb3J0KmFzIEMgZnJvbSJmZmkiO2ltcG9ydCphcyBkdCBmcm9tIm9zIjtpbXBvcnQqYXMgbXQgZnJvbSJzdGQiO2ltcG9ydCphcyAkIGZyb20id2luIjt2YXIgQXQ9eyJ1dGYtOCI6InV0Zi04Iix1dGY4OiJ1dGYtOCIsInVuaWNvZGUtMS0xLXV0Zi04IjoidXRmLTgiLCJ1dGYtMTYiOiJ1dGYtMTZsZSIsInV0Zi0xNmxlIjoidXRmLTE2bGUiLCJ1dGYtMTZiZSI6InV0Zi0xNmJlIn07ZnVuY3Rpb24gc3QodCl7aWYoIXQpcmV0dXJuInV0Zi04IjtsZXQgZT1BdFt0LnRyaW0oKS50b0xvd2VyQ2FzZSgpXTtpZihlKXJldHVybiBlO3Rocm93IG5ldyBSYW5nZUVycm9yKGBUaGUgZW5jb2RpbmcgbGFiZWwgIiR7dH0iIGlzIG5vdCBzdXBwb3J0ZWRgKX1mdW5jdGlvbiBNdCh0LGUpe2xldCByPSIiO2ZvcihsZXQgbj0wO248dC5sZW5ndGg7KXtsZXQgbz10W24rK107aWYobzwxMjgpe3IrPVN0cmluZy5mcm9tQ2hhckNvZGUobyk7Y29udGludWV9aWYobzwxOTIpe3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigidW5leHBlY3RlZCBjb250aW51YXRpb24gYnl0ZSIpfSkoKToiXHVGRkZEIjtjb250aW51ZX1sZXQgaSxjO2lmKG88MjI0KXtpZihuPj10Lmxlbmd0aCl7cis9ZT8oKCk9Pnt0aHJvdyBuZXcgVHlwZUVycm9yKCJpbmNvbXBsZXRlIHV0Zi04Iil9KSgpOiJcdUZGRkQiO2JyZWFrfWxldCBzPXRbbisrXTtpZigocyYxOTIpIT09MTI4KXtyKz0iXHVGRkZEIjtjb250aW51ZX1pPShvJjMxKTw8NnxzJjYzLGM9MTI4fWVsc2UgaWYobzwyNDApe2lmKG4rMT49dC5sZW5ndGgpe3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW5jb21wbGV0ZSB1dGYtOCIpfSkoKToiXHVGRkZEIjticmVha31sZXQgcz10W24rK10sdT10W24rK107aWYoKHMmMTkyKSE9PTEyOHx8KHUmMTkyKSE9PTEyOCl7cis9Ilx1RkZGRCI7Y29udGludWV9aT0obyYxNSk8PDEyfChzJjYzKTw8Nnx1JjYzLGM9MjA0OH1lbHNlIGlmKG88MjQ4KXtpZihuKzI+PXQubGVuZ3RoKXtyKz1lPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoImluY29tcGxldGUgdXRmLTgiKX0pKCk6Ilx1RkZGRCI7YnJlYWt9bGV0IHM9dFtuKytdLHU9dFtuKytdLHA9dFtuKytdO2lmKChzJjE5MikhPT0xMjh8fCh1JjE5MikhPT0xMjh8fChwJjE5MikhPT0xMjgpe3IrPSJcdUZGRkQiO2NvbnRpbnVlfWk9KG8mNyk8PDE4fChzJjYzKTw8MTJ8KHUmNjMpPDw2fHAmNjMsYz02NTUzNn1lbHNle3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW52YWxpZCB1dGYtOCBzdGFydCIpfSkoKToiXHVGRkZEIjtjb250aW51ZX1pZihpPGN8fGk+PTU1Mjk2JiZpPD01NzM0M3x8aT4xMTE0MTExKXtyKz1lPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoImludmFsaWQgdXRmLTggY29kZXBvaW50Iil9KSgpOiJcdUZGRkQiO2NvbnRpbnVlfWk8PTY1NTM1P3IrPVN0cmluZy5mcm9tQ2hhckNvZGUoaSk6KGktPTY1NTM2LHIrPVN0cmluZy5mcm9tQ2hhckNvZGUoNTUyOTZ8aT4+MTAsNTYzMjB8aSYxMDIzKSl9cmV0dXJuIHJ9ZnVuY3Rpb24gV3QodCxlLHIpe2xldCBuPW5ldyBEYXRhVmlldyh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQsdC5ieXRlTGVuZ3RoKSxvPSIiO2ZvcihsZXQgaT0wO2krMTx0Lmxlbmd0aDtpKz0yKXtsZXQgYz1uLmdldFVpbnQxNihpLGUpO2lmKGM+PTU1Mjk2JiZjPD01NjMxOSl7aWYoaSs9MixpKzE+PXQubGVuZ3RoKXtvKz1yPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoInRydW5jYXRlZCBzdXJyb2dhdGUgcGFpciIpfSkoKToiXHVGRkZEIjticmVha31sZXQgcz1uLmdldFVpbnQxNihpLGUpO3M+PTU2MzIwJiZzPD01NzM0Mz9vKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGMscyk6KG8rPXI/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW52YWxpZCBzdXJyb2dhdGUgcGFpciIpfSkoKToiXHVGRkZEIixpLT0yKX1lbHNlIGM+PTU2MzIwJiZjPD01NzM0Mz9vKz1yPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoInVuZXhwZWN0ZWQgdHJhaWxpbmcgc3Vycm9nYXRlIil9KSgpOiJcdUZGRkQiOm8rPVN0cmluZy5mcm9tQ2hhckNvZGUoYyl9cmV0dXJuIG99dmFyIFY9Y2xhc3N7X2VuY29kaW5nO19mYXRhbDtfaWdub3JlQk9NO2NvbnN0cnVjdG9yKGUscil7dGhpcy5fZW5jb2Rpbmc9c3QoZSksdGhpcy5fZmF0YWw9cj8uZmF0YWw/PyExLHRoaXMuX2lnbm9yZUJPTT1yPy5pZ25vcmVCT00/PyExfWdldCBlbmNvZGluZygpe3JldHVybiB0aGlzLl9lbmNvZGluZ31nZXQgZmF0YWwoKXtyZXR1cm4gdGhpcy5fZmF0YWx9Z2V0IGlnbm9yZUJPTSgpe3JldHVybiB0aGlzLl9pZ25vcmVCT019ZGVjb2RlKGUpe2lmKCFlKXJldHVybiIiO2xldCByPWUgaW5zdGFuY2VvZiBVaW50OEFycmF5P2U6ZSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyP25ldyBVaW50OEFycmF5KGUpOm5ldyBVaW50OEFycmF5KGUuYnVmZmVyLGUuYnl0ZU9mZnNldCxlLmJ5dGVMZW5ndGgpO2lmKHRoaXMuX2VuY29kaW5nPT09InV0Zi04IilyZXR1cm4gTXQocix0aGlzLl9mYXRhbCk7bGV0IG49dGhpcy5fZW5jb2Rpbmc9PT0idXRmLTE2bGUiLG89MDtpZihyLmxlbmd0aD49MiYmIXRoaXMuX2lnbm9yZUJPTSl7bGV0IGk9bj9yWzBdOnJbMV0scz0obj9yWzFdOnJbMF0pPDw4fGk7KHM9PT02NTI3OXx8cz09PTY1NTM0KSYmKG89Mil9cmV0dXJuIFd0KHIuc2xpY2Uobyksbix0aGlzLl9mYXRhbCl9fSx2PWNsYXNze19lbmNvZGluZztjb25zdHJ1Y3RvcihlKXt0aGlzLl9lbmNvZGluZz1zdChlKX1nZXQgZW5jb2RpbmcoKXtyZXR1cm4gdGhpcy5fZW5jb2Rpbmd9ZW5jb2RlKGUpe2lmKCFlKXJldHVybiBuZXcgVWludDhBcnJheSgwKTtpZih0aGlzLl9lbmNvZGluZz09PSJ1dGYtOCIpe2xldCBpPVtdO2ZvcihsZXQgYz0wO2M8ZS5sZW5ndGg7YysrKXtsZXQgcz1lLmNoYXJDb2RlQXQoYyk7aWYoczwxMjgpaS5wdXNoKHMpO2Vsc2UgaWYoczwyMDQ4KWkucHVzaCgxOTJ8cz4+NiwxMjh8cyY2Myk7ZWxzZSBpZihzPDU1Mjk2fHxzPj01NzM0NClpLnB1c2goMjI0fHM+PjEyLDEyOHxzPj42JjYzLDEyOHxzJjYzKTtlbHNle2MrKztsZXQgdT1lLmNoYXJDb2RlQXQoYyk7cz02NTUzNisoKHMmMTAyMyk8PDEwKXx1JjEwMjMsaS5wdXNoKDI0MHxzPj4xOCwxMjh8cz4+MTImNjMsMTI4fHM+PjYmNjMsMTI4fHMmNjMpfX1yZXR1cm4gbmV3IFVpbnQ4QXJyYXkoaSl9bGV0IHI9dGhpcy5fZW5jb2Rpbmc9PT0idXRmLTE2bGUiLG49bmV3IEFycmF5QnVmZmVyKGUubGVuZ3RoKjIpLG89bmV3IERhdGFWaWV3KG4pO2ZvcihsZXQgaT0wO2k8ZS5sZW5ndGg7aSsrKW8uc2V0VWludDE2KGkqMixlLmNoYXJDb2RlQXQoaSkscik7cmV0dXJuIG5ldyBVaW50OEFycmF5KG4pfX07dHlwZW9mIGdsb2JhbFRoaXMuVGV4dERlY29kZXI+InUiJiYoZ2xvYmFsVGhpcy5UZXh0RGVjb2Rlcj1WKTt0eXBlb2YgZ2xvYmFsVGhpcy5UZXh0RW5jb2Rlcj4idSImJihnbG9iYWxUaGlzLlRleHRFbmNvZGVyPXYpO2ltcG9ydHtidWZmZXJQdHIgYXMgUnR9ZnJvbSJmZmkiO2ltcG9ydCphcyBjdCBmcm9tIm9zIjt2YXIga3Q9WyJ2b2lkIiwidTgiLCJpOCIsInUxNiIsImkxNiIsInUzMiIsImkzMiIsInU2NCIsImk2NCIsImYzMiIsImY2NCIsInB0ciJdLGo9L148KFtBLVphLXpfXVx3KnwpPnB0cighfEBbQS1aYS16X11cdyopPyQvO2Z1bmN0aW9uIE4odCl7cmV0dXJuIGoudGVzdCh0KX12YXIgdXQ9L148KFtBLVphLXpfXVx3Kik+JC87ZnVuY3Rpb24geSh0KXtyZXR1cm4gdXQudGVzdCh0KX1mdW5jdGlvbiBXKHQpe3JldHVybiB1dC5leGVjKHQpPy5bMV18fCIifWZ1bmN0aW9uIFgodCl7cmV0dXJuIGouZXhlYyh0KT8uWzFdfHwiIn12YXIgYXQ9dD0+e2lmKE4odCkpcmV0dXJuInB0ciI7aWYoeSh0KSl0aHJvdyBuZXcgRXJyb3IoYGZmaTogY1Rva2VuVG9UeXBlOiBieS12YWx1ZSB0b2tlbiAiJHt0fSIgaGFzIG5vIHNjYWxhciBzbG90IHR5cGVgKTtyZXR1cm4gdH0sRD1jdC5hcmNoPT09Ing2NCI/ODo0LFI9e3U4OjEsaTg6MSx1MTY6MixpMTY6Mix1MzI6NCxpMzI6NCx1NjQ6OCxpNjQ6OCxmMzI6NCxmNjQ6OH0sTz0wO2Z1bmN0aW9uIGsodCl7aWYoTih0KSl7bGV0IG89ai5leGVjKHQpLGk9bz8uWzFdfHwiIjtyZXR1cm4gbz8uWzJdPy5zdGFydHNXaXRoKCJAIik/YDwke2l9PnB0cmA6dH1pZih5KHQpKXJldHVybiB0O2xldCBlPXQuaW5kZXhPZigiQCIpLHI9ZT49MD90LnNsaWNlKDAsZSk6dDtpZigoZTwwfHwvXltBLVphLXpfXVx3KiQvLnRlc3QodC5zbGljZShlKzEpKSkmJnIhPT0icHRyIiYma3QuaW5jbHVkZXMocikpcmV0dXJuIHI7dGhyb3cgbmV3IEVycm9yKCJVbmtub3duIHRva2VuOiAiK3QpfWZ1bmN0aW9uIHoodCxlLHIpe3N3aXRjaChyKXtjYXNlInU4IjpyZXR1cm4gdC5nZXRVaW50OChlKTtjYXNlImk4IjpyZXR1cm4gdC5nZXRJbnQ4KGUpO2Nhc2UidTE2IjpyZXR1cm4gdC5nZXRVaW50MTYoZSwhMCk7Y2FzZSJpMTYiOnJldHVybiB0LmdldEludDE2KGUsITApO2Nhc2UidTMyIjpyZXR1cm4gdC5nZXRVaW50MzIoZSwhMCk7Y2FzZSJpMzIiOnJldHVybiB0LmdldEludDMyKGUsITApO2Nhc2UidTY0IjpyZXR1cm4gdC5nZXRCaWdVaW50NjQoZSwhMCk7Y2FzZSJpNjQiOnJldHVybiB0LmdldEJpZ0ludDY0KGUsITApO2Nhc2UiZjMyIjpyZXR1cm4gdC5nZXRGbG9hdDMyKGUsITApO2Nhc2UiZjY0IjpyZXR1cm4gdC5nZXRGbG9hdDY0KGUsITApO2Nhc2UicHRyIjpyZXR1cm4gRD09PTg/TnVtYmVyKHQuZ2V0QmlnSW50NjQoZSwhMCkpOnQuZ2V0SW50MzIoZSwhMCl9fWZ1bmN0aW9uIFoodCxlLHtrOnIsdjpufSl7c3dpdGNoKHIpe2Nhc2UidTgiOnQuc2V0VWludDgoZSxOdW1iZXIobikpO2JyZWFrO2Nhc2UiaTgiOnQuc2V0SW50OChlLE51bWJlcihuKSk7YnJlYWs7Y2FzZSJ1MTYiOnQuc2V0VWludDE2KGUsTnVtYmVyKG4pLCEwKTticmVhaztjYXNlImkxNiI6dC5zZXRJbnQxNihlLE51bWJlcihuKSwhMCk7YnJlYWs7Y2FzZSJ1MzIiOnQuc2V0VWludDMyKGUsbj4+PjAsITApO2JyZWFrO2Nhc2UiaTMyIjp0LnNldFVpbnQzMihlLG4+Pj4wLCEwKTticmVhaztjYXNlInU2NCI6dC5zZXRCaWdVaW50NjQoZSxuLCEwKTticmVhaztjYXNlImk2NCI6dC5zZXRCaWdJbnQ2NChlLG4sITApO2JyZWFrO2Nhc2UiZjMyIjp0LnNldEZsb2F0MzIoZSxuLCEwKTticmVhaztjYXNlImY2NCI6dC5zZXRGbG9hdDY0KGUsbiwhMCk7YnJlYWs7Y2FzZSJwdHIiOntpZihuPT1udWxsKXRocm93IG5ldyBFcnJvcigiZmZpOiBnb3QgbnVsbC91bmRlZmluZWQgZm9yIGEgcHRyIHNsb3Q7IHBhc3MgdGhlIGltcG9ydGVkIE5VTEwgY29uc3RhbnQgZm9yIGVtcHR5Iik7RD09PTg/dC5zZXRCaWdVaW50NjQoZSxCaWdJbnQuYXNVaW50Tig2NCxCaWdJbnQobikpLCEwKTp0LnNldFVpbnQzMihlLG4+Pj4wLCEwKTticmVha319fWZ1bmN0aW9uIF8odCxlLHIpe2xldHtrOm4sdjpvfT1yO2lmKG49PT0idTgifHxuPT09Imk4Inx8bj09PSJ1MTYifHxuPT09ImkxNiIpe3Quc2V0VWludDMyKGUsTnVtYmVyKG8pPj4+MCwhMCk7cmV0dXJufVoodCxlLHIpfXZhciB4PWNsYXNzIGV4dGVuZHMgQXJyYXlCdWZmZXJ7cHRyO2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpLHRoaXMucHRyPVJ0KHRoaXMpfX07ZnVuY3Rpb24gcSh0LGUpe3JldHVybiBlW3RdfXZhciBwdD1uZXcgTWFwO2Z1bmN0aW9uIF90KHQpe2xldCBlPXB0LmdldCh0KTtpZihlIT09dm9pZCAwKXJldHVybiBlO2xldCByPSQuTG9hZExpYnJhcnkodCk7aWYoIXIpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogTG9hZExpYnJhcnkoIiR7dH0iKSBmYWlsZWRgKTtyZXR1cm4gcHQuc2V0KHQscikscn1mdW5jdGlvbiBVdCh0KXtsZXQgZT10LnNwbGl0KCIgLT4gIik7aWYoZS5sZW5ndGghPT0yKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IGludmFsaWQgc2lnbmF0dXJlICIke3R9IiAoZXhwZWN0ZWQgImFyZzEgYXJnMiAtPiByZXQiKWApO2xldCByPWVbMF0uc3BsaXQoIiAiKS5maWx0ZXIoaT0+aSE9PSIiKSxuPVtdO2ZvcihsZXQgaSBvZiByKXtsZXQgYz1rKGkpO2lmKGM9PT0idm9pZCIpdGhyb3cgbmV3IEVycm9yKCJWb2lkIGNhbiBub3QgaW4gYXJncyIpO24ucHVzaChjKX1sZXQgbz1rKGVbMV0pO2lmKHkobykpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogIiR7dH0iOiBieS12YWx1ZSBzdHJ1Y3QgYXQgdGhlIHJldHVybiBwb3NpdGlvbiAoPCR7VyhvKX0+KSBpcyBub3Qgc3VwcG9ydGVkIFx1MjAxNCBhcmd1bWVudCBwb3NpdGlvbnMgb25seTsgcGFzcyBhIHN0cnVjdCBvdXQgdGhyb3VnaCBhbiBvdXQtcGFyYW0gc2xvdCBpbnN0ZWFkICg8Tj5wdHIgKyBjYWxsZXIgYnVmZmVyKWApO3JldHVybnthcmdUb2tlbnM6bixyZXRUb2tlbjpvLHNpZzp0fX1mdW5jdGlvbiBCdCh0LGUscixuKXtsZXQgbz1VdChlKTtmb3IobGV0IGkgb2Ygby5hcmdUb2tlbnMpe2lmKCF5KGkpKWNvbnRpbnVlO2xldCBjPVcoaSkscz1xKGMscik7aWYoIXN8fHR5cGVvZiBzLmVuY29kZSE9ImZ1bmN0aW9uIil0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke2V9OiBieS12YWx1ZSBwb3NpdGlvbiA8JHtjfT4gaGFzIG5vIHJlZ2lzdGVyZWQgbGF5b3V0IChhdmFpbGFibGU6ICR7T2JqZWN0LmtleXMocikuam9pbigiLCAiKXx8Im5vbmUifSlgKTtpZih0eXBlb2Ygcy5zaXplIT0ibnVtYmVyInx8cy5zaXplPDEpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogJHtlfTogYnktdmFsdWUgcG9zaXRpb24gPCR7Y30+IHJlcXVpcmVzIGEgc3RydWN0IGxheW91dCB3aXRoIHNpemUgPj0gMSAoZ290ICR7cy5zaXplfTsgbm9uLXN0cnVjdCBjb2RlY3MgZXhwb3NlIG5vIHNpemUpYCl9cmV0dXJuKC4uLmkpPT56dCh0LG8saSxyLG4pfXZhciBIdD17dTg6NCxpODo0LHUxNjo0LGkxNjo0LHUzMjo0LGkzMjo0LHU2NDo4LGk2NDo4LGYzMjo0LGY2NDo4LHB0cjpEfSxmdD00O2Z1bmN0aW9uIHp0KHQse2FyZ1Rva2VuczplLHJldFRva2VuOnIsc2lnOm59LG8saSxjKXtsZXQgcz1kdC5hcmNoPT09Ing2NCIsdT0oYSxkKT0+e2lmKHkoYSkpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogZ2V0V2lkdGg6IGJ5LXZhbHVlIHRva2VuICIke2F9IiAoZGlzcGF0Y2hlZCBieSB3aWR0aE9mKWApO3JldHVybiBkPzg6TihhKT9EOkh0W2FdfSxwPWE9PntpZih5KGEpKXtpZihzKXJldHVybiA4O2xldCBkPXEoVyhhKSxpKTtpZighZCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiA8JHtXKGEpfT4gYnktdmFsdWUgcG9zaXRpb24gaGFzIG5vIHJlZ2lzdGVyZWQgbGF5b3V0YCk7bGV0IG09ZC5zaXplO3JldHVybiBtJTQ9PT0wP206bSs0LW0lNH1yZXR1cm4gdShhLHMpfSxoPTA7Zm9yKGxldCBhIG9mIGUpaCs9cChhKTtzJiZlLmxlbmd0aDxmdCYmKGg9ZnQqOCk7bGV0IEY9bmV3IEFycmF5QnVmZmVyKGgpLGc9bmV3IERhdGFWaWV3KEYpLFQ9W10sRT0wO2ZvcihsZXQgYT0wO2E8ZS5sZW5ndGg7YSsrKXtsZXQgZD1lW2FdLG09ZC5lbmRzV2l0aCgiISIpLGY9b1thXTtpZihOKGQpKXtsZXQgbD1YKGQpO2lmKHR5cGVvZiBmPT0ibnVtYmVyIil7aWYobSYmZj09PTApdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogJHtufTogYXJnIyR7YSsxfSA8JHtsfT5wdHIhIGdvdCAwIChudWxsIHBvaW50ZXIgZm9yYmlkZGVuIGhlcmU7IHRoZSB0b2tlbiBtYXJrcyB0aGlzIHBvc2l0aW9uIG5vbi1udWxsKWApO18oZyxFLHtrOiJwdHIiLHY6Zn0pfWVsc2V7aWYoZj09bnVsbCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiA8JHtsfT5wdHIgZ290ICR7U3RyaW5nKGYpfTsgcGFzcyB0aGUgaW1wb3J0ZWQgTlVMTCBjb25zdGFudCBmb3IgYW4gZW1wdHkgcG9pbnRlcmApO2xldCBJPWlbbF07aWYoIUkpdGhyb3cgbmV3IEVycm9yKGw9PT0iIj9gZmZpLWJpbmQ6IDw+cHRyIGV4cGVjdHMgbnVtYmVyIChOVUxMIHwgUHRyKSwgZ290ICR7dHlwZW9mIGZ9OyB1c2UgPEJZVEU+cHRyIHdpdGggYSBQdHJBcnJheUJ1ZmZlciAobmV3IFB0ckFycmF5QnVmZmVyKG4pKSwgb3IgZmZpLmJ1ZmZlclB0cihidWYpIGZvciBhbiBhZGRyZXNzYDpgZmZpLWJpbmQ6IHVua25vd24gbGF5b3V0ICI8JHtsfT5wdHIiIChhdmFpbGFibGU6ICR7T2JqZWN0LmtleXMoaSkuam9pbigiLCAiKXx8Im5vbmUifSlgKTtpZighSS5lbmNvZGUpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogPCR7bH0+cHRyIGhhcyBubyBlbmNvZGVyIChvdXQtb25seSBjb2RlYylgKTtsZXQgTD1JLmVuY29kZShmKTtULnB1c2goTCk7bGV0IEE9TC5wdHI7aWYodHlwZW9mIEEhPSJudW1iZXIiKXRocm93IG5ldyBFcnJvcigiZmZpLWJpbmQ6IGNvZGVjLmVuY29kZSBtdXN0IHJldHVybiBhIFB0ckFycmF5QnVmZmVyLCBnb3QgcGxhaW4gQXJyYXlCdWZmZXIiKTtpZihtJiZBPT09MCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke259OiBhcmcjJHthKzF9IDwke2x9PnB0ciEgZW5jb2RlIHByb2R1Y2VkIDAgKG51bGwgcG9pbnRlciBmb3JiaWRkZW4gaGVyZSlgKTtfKGcsRSx7azoicHRyIix2OkF9KX19ZWxzZSBpZih5KGQpKXtsZXQgbD1XKGQpLEk9cShsLGkpO2lmKCFJKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICR7bn06IGFyZyMke2ErMX0gPCR7bH0+IGJ5LXZhbHVlIHBvc2l0aW9uIGhhcyBubyByZWdpc3RlcmVkIGxheW91dGApO2lmKGY9PW51bGwpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogPCR7bH0+IHZhbHVlIHBvc2l0aW9uIGdvdCAke1N0cmluZyhmKX07IHBhc3MgYSBzdHJ1Y3Qgb2JqZWN0ICh1c2UgPCR7bH0+cHRyIHRvIHBhc3MgYSBwb2ludGVyKWApO2xldCBMPUkuc2l6ZTtpZighc3x8TDw9OCYmKEwmTC0xKT09PTApSS5lbmNvZGUoZixGLEUpO2Vsc2V7bGV0IEE9bmV3IEFycmF5QnVmZmVyKEwrMTUpLG90PUMuYnVmZmVyUHRyKEEpLGl0PSgxNi1vdCUxNiklMTY7SS5lbmNvZGUoZixBLGl0KSxULnB1c2goQSksXyhnLEUse2s6InB0ciIsdjpvdCtpdH0pfX1lbHNlIF8oZyxFLHtrOmQsdjpmfSk7RSs9cChkKX1sZXQgUD1uZXcgQXJyYXlCdWZmZXIoOCk7Qy5mZmlDYWxsKHQsRixQLHI9PT0iZjMyInx8cj09PSJmNjQiPzE6MCk7bGV0IFM9JHQoYXQociksUCk7aWYoci5lbmRzV2l0aCgiISIpJiZTPT09MCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke259OiByZXR1cm4gJHtyfSBnb3QgMCAodGhlIHRva2VuIHByb21pc2VzIEMgbmV2ZXIgcmV0dXJucyBudWxsIGhlcmUpYCk7aWYoTihyKSYmUyE9PTApe2xldCBhPVgocik7aWYoYSE9PSIiKXtsZXQgZD1jW2FdO2lmKGQ/LmRlY29kZSlyZXR1cm4gZC5kZWNvZGUoUyl9fXJldHVybiBTfWZ1bmN0aW9uICR0KHQsZSl7aWYodCE9PSJ2b2lkIilyZXR1cm4geihuZXcgRGF0YVZpZXcoZSksMCx0KX12YXIgRz17ZW5jb2RlOnQ9PntsZXQgZT1uZXcgVGV4dEVuY29kZXIoInV0Zi0xNmxlIikuZW5jb2RlKHQrIlwwIikscj1uZXcgeChlLmJ5dGVMZW5ndGgpO3JldHVybiBuZXcgVWludDhBcnJheShyKS5zZXQoZSkscn0sZGVjb2RlOnQ9PntpZih0eXBlb2YgdD09Im51bWJlciIpe2xldCBvPSIiLGk9dCxjPWk7Zm9yKDs7KXtsZXQgcz1DLnJlYWRCeXRlKGkpLHU9Qy5yZWFkQnl0ZShpKzEpO2lmKHM9PT0wJiZ1PT09MClyZXR1cm4gbztpZihvKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHN8dTw8OCksaSs9MixpLWM+MTw8MjEpdGhyb3cgbmV3IEVycm9yKCJmZmktYmluZDogV0NIQVIgZGVjb2RlIGV4Y2VlZGVkIDRNaUIgd2l0aG91dCBOVUwiKX19bGV0IGU9bmV3IFVpbnQ4QXJyYXkodCkscj1lLmxlbmd0aCYtMixuPSIiO2ZvcihsZXQgbz0wO288cjtvKz0yKXtsZXQgaT1lW29dfGVbbysxXTw8ODtpZihpPT09MClyZXR1cm4gbjtuKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGkpfXJldHVybiBufSxhbGxvYzoodD0yNTYpPT5uZXcgeCh0KjIpfSxHdD17ZW5jb2RlOnQ9PntpZighKHQgaW5zdGFuY2VvZiB4KSl0aHJvdyBuZXcgRXJyb3IoImZmaS1iaW5kOiA8QllURT5wdHIgd2FudHMgYSBQdHJBcnJheUJ1ZmZlciAobmV3IFB0ckFycmF5QnVmZmVyKG4pIC8gQllURS5hbGxvYyAvIHN0cnVjdC5lbmNvZGUpLCBub3QgYSBwbGFpbiBBcnJheUJ1ZmZlciIpO3JldHVybiB0fSxhbGxvYzp0PT5uZXcgeCh0KX0sbHQ9e1dDSEFSOkcsQllURTpHdH07ZnVuY3Rpb24gRXQodCxlLHIsbixvKXtsZXQgaT0kLkdldFByb2NBZGRyZXNzKF90KHQpLGUpO2lmKCFpKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IHByb2MgIiR7ZX0iIG5vdCBmb3VuZCBpbiAke3R9YCk7bGV0IGM9bz8/bjtyZXR1cm4gQnQoaSxyLHsuLi5sdCwuLi5ufSx7Li4ubHQsLi4uYz8/e319KX12YXIgZmU9bmV3IEZpbmFsaXphdGlvblJlZ2lzdHJ5KHQ9PnttdC5wcmludGYoYFtmZmldIGNsb3N1cmUgbGVha2VkIChHQ2VkIHdpdGhvdXQgZGlzcG9zZSk6IHNpZz0iJXMiIHB0cj0weCV4CmAsdC5zaWcsdC5wdHIpfSk7aW1wb3J0KmFzIGh0IGZyb20iZmZpIjtmdW5jdGlvbiBVKHQsZSl7cmV0dXJuIHQrZS0xJn4oZS0xKX12YXIgeHQ9dD0+Ult0XSE9PXZvaWQgMDtmdW5jdGlvbiBLKHQpe2lmKHR5cGVvZiB0PT0ic3RyaW5nIil7bGV0IGU9L14odTh8dTE2KVxbKFxkKylcXUAodXRmLTh8dXRmLTE2bGUpJC8uZXhlYyh0KTtpZihlKXtsZXQgYz1OdW1iZXIoZVsyXSk7aWYoIU51bWJlci5pc0ludGVnZXIoYyl8fGM8MSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IHN0cmluZyBsZW5ndGggbXVzdCBiZSBhbiBpbnRlZ2VyID49IDEsIGdvdCAke2N9YCk7bGV0IHM9ZVsxXT09PSJ1OCI/MToyO3JldHVybntzaXplOnMqYyxhbGlnbjpzLHR5cGU6e3RhZzoic3RyaW5nIixlbmNvZGluZzplWzNdfX19bGV0IHI9L14oW15cW1xdXSspXFsoXGQrKVxdJC8uZXhlYyh0KTtpZihyKXtsZXQgYz1OdW1iZXIoclsyXSk7aWYoIU51bWJlci5pc0ludGVnZXIoYyl8fGM8MSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IGFycmF5IGxlbmd0aCBtdXN0IGJlIGFuIGludGVnZXIgPj0gMSwgZ290ICR7Y31gKTtsZXQgcz1LKHJbMV0pO2lmKHMudHlwZS50YWc9PT0iYml0ZmllbGQiKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYml0ZmllbGRzIGNhbm5vdCBiZSBhcnJheSBlbGVtZW50cyIpO3JldHVybntzaXplOnMuc2l6ZSpjLGFsaWduOnMuYWxpZ24sdHlwZTp7dGFnOiJhcnJheSIsZWxlbWVudFR5cGU6cy50eXBlLGVsZW1lbnRTaXplOnMuc2l6ZX19fWxldCBuPS9eKFtBLVphLXpfXVx3Kik6KFxkKykkLy5leGVjKHQpO2lmKG4pe2xldCBjPW5bMV0scz1rKGMpO2lmKCF4dChzKXx8cz09PSJmMzIifHxzPT09ImY2NCIpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBiaXRmaWVsZCB1bml0IG11c3QgYmUgYW4gaW50ZWdlciB0eXBlLCBnb3QgIiR7Y30iYCk7bGV0IHU9TnVtYmVyKG5bMl0pLHA9UltzXSxoPXAqODtpZighTnVtYmVyLmlzSW50ZWdlcih1KXx8dTwxKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogYml0ZmllbGQgd2lkdGggbXVzdCBiZSBhbiBpbnRlZ2VyID49IDEsIGdvdCAke3V9YCk7aWYodT5oKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogYml0ZmllbGQgd2lkdGggJHt1fSBleGNlZWRzIHVuaXQgd2lkdGggJHtofWApO3JldHVybntzaXplOnAsYWxpZ246cCx0eXBlOnt0YWc6ImJpdGZpZWxkIix1bml0OnMsYml0OjAsd2lkdGg6dX19fWxldCBvPWsodCk7aWYoTihvKSlyZXR1cm57c2l6ZTpELGFsaWduOkQsdHlwZTp7dGFnOiJiYXNpYyIsa2luZDoicHRyIn19O2lmKCF4dChvKSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IHVua25vd24ga2luZCAiJHt0fSJgKTtsZXQgaT1SW29dO3JldHVybntzaXplOmksYWxpZ246aSx0eXBlOnt0YWc6ImJhc2ljIixraW5kOm99fX1pZih0JiZ0eXBlb2YgdD09Im9iamVjdCIpe2xldCBlPXQscj1lWyIjIl07aWYocj09PXZvaWQgMCl0aHJvdyBuZXcgRXJyb3IoImZmaS1zdHJ1Y3Q6IG5lc3RlZCBvYmplY3QgdmFsdWUgcmVxdWlyZXMgYSAnIycga2V5ICgnc3RydWN0JyB8ICd1bmlvbicgfCAnYXJyYXknKSIpO2lmKHI9PT0iYXJyYXkiJiYiI3BhY2siaW4gZSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6ICcjcGFjaycgaXMgb25seSBhbGxvd2VkIG9uIHN0cnVjdC91bmlvbiwgZ290ICcke3J9J2ApO2lmKHI9PT0iYXJyYXkiKXtsZXQgbj1lLmxlbmd0aDtpZighTnVtYmVyLmlzSW50ZWdlcihuKXx8bjwxKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogYXJyYXkgbGVuZ3RoIG11c3QgYmUgYW4gaW50ZWdlciA+PSAxLCBnb3QgJHtTdHJpbmcobil9YCk7bGV0IG89SyhlLmVsZW1lbnQpO2lmKG8udHlwZS50YWc9PT0iYml0ZmllbGQiKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYml0ZmllbGRzIGNhbm5vdCBiZSBhcnJheSBlbGVtZW50cyIpO3JldHVybntzaXplOm8uc2l6ZSpuLGFsaWduOm8uYWxpZ24sdHlwZTp7dGFnOiJhcnJheSIsZWxlbWVudFR5cGU6by50eXBlLGVsZW1lbnRTaXplOm8uc2l6ZX19fWlmKHI9PT0ic3RydWN0Inx8cj09PSJ1bmlvbiIpe2xldCBuPXd0KHQpO3JldHVybntzaXplOm4uc2l6ZSxhbGlnbjpuLm1heEVmZmVjdGl2ZUFsaWduLHR5cGU6e3RhZzpyLGZpZWxkczpuLmZpZWxkc319fXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogdW5rbm93biAnIycgZGVjbGFyYXRpb24gJHtKU09OLnN0cmluZ2lmeShTdHJpbmcocikpfWApfXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogaW52YWxpZCBtZW1iZXIgdmFsdWU6ICR7U3RyaW5nKHQpfWApfWZ1bmN0aW9uIHd0KHQpe2xldCBlPXRbIiMiXT09PSJzdHJ1Y3QiLHI9dFsiI3BhY2siXT8/OCxuPTEsbz0wLGk9W10sYz0wLHM9LTEsdT0wLHA9MCxoPSgpPT57czwwfHwoYz1VKHMrTWF0aC5jZWlsKHUvOCkscCkscz0tMSl9O2ZvcihsZXRbRixnXW9mIE9iamVjdC5lbnRyaWVzKHQpKXtpZihGLnN0YXJ0c1dpdGgoIiMiKSljb250aW51ZTtsZXQgVD0vXihbXkBdKylAKFxkKykkLy5leGVjKEYpLEU9VD9UWzFdOkYsUD1UP051bWJlcihUWzJdKTowLHtzaXplOncsYWxpZ246Uyx0eXBlOmF9PUsoZyksZD10eXBlb2YgZz09InN0cmluZyImJmcuZW5kc1dpdGgoIiEiKSxtPVM7aWYocj4wJiYobT1NYXRoLm1pbihyLG0pKSxQJiYobT1NYXRoLm1heChtLFApKSxhLnRhZz09PSJiaXRmaWVsZCIpe2lmKEUuc3RhcnRzV2l0aCgiJCIpKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYml0ZmllbGQgbWVtYmVycyBtdXN0IGJlIG5hbWVkIik7aWYoIWUpe2kucHVzaCh7bmFtZTpFLG9mZnNldDowLHNpemU6dyx0eXBlOnsuLi5hLGJpdDowfX0pLG49TWF0aC5tYXgobixtKSxvPU1hdGgubWF4KG8sdyk7Y29udGludWV9bGV0IGw9YS53aWR0aDsoczwwfHx3IT09cHx8dStsPnAqOCkmJihzPj0wJiZoKCkscz1VKGMsbSksdT0wLHA9dyksaS5wdXNoKHtuYW1lOkUsb2Zmc2V0OnMsc2l6ZTp3LHR5cGU6ey4uLmEsYml0OnV9fSksdSs9bCxuPU1hdGgubWF4KG4sbSksbz1NYXRoLm1heChvLHcpO2NvbnRpbnVlfWgoKTtsZXQgZj1VKGMsbSk7aWYoIUUuc3RhcnRzV2l0aCgiJCIpKWkucHVzaCh7bmFtZTpFLG9mZnNldDpmLHNpemU6dyx0eXBlOmEsLi4uZD97bm9ubnVsbDohMH06e319KTtlbHNle2lmKGEudGFnIT09InN0cnVjdCImJmEudGFnIT09InVuaW9uIil0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IGFub255bW91cyBtZW1iZXIgIiR7RX0iIG11c3QgYmUgYSBzdHJ1Y3QvdW5pb25gKTtmb3IobGV0IGwgb2YgYS5maWVsZHMpaS5wdXNoKHsuLi5sLG9mZnNldDpsLm9mZnNldCtmfSl9ZSYmKGM9Zit3KSxuPU1hdGgubWF4KG4sbSksbz1NYXRoLm1heChvLHcpfXJldHVybiBoKCkse3NpemU6VShlP2M6byxuKSxtYXhFZmZlY3RpdmVBbGlnbjpuLGZpZWxkczppfX1mdW5jdGlvbiBndCh0LGUscil7bGV0IG49UltyXTtyZXR1cm4gbj09PTE/QmlnSW50KHQuZ2V0VWludDgoZSkpOm49PT0yP0JpZ0ludCh0LmdldFVpbnQxNihlLCEwKSk6bj09PTQ/QmlnSW50KHQuZ2V0VWludDMyKGUsITApKTp0LmdldEJpZ1VpbnQ2NChlLCEwKX1mdW5jdGlvbiBZdCh0LGUscixuKXtsZXQgbz1SW3JdO2lmKG89PT0xKXt0LnNldFVpbnQ4KGUsTnVtYmVyKG4mMHhmZm4pKTtyZXR1cm59aWYobz09PTIpe3Quc2V0VWludDE2KGUsTnVtYmVyKG4mMHhmZmZmbiksITApO3JldHVybn1pZihvPT09NCl7dC5zZXRVaW50MzIoZSxOdW1iZXIobiYweGZmZmZmZmZmbiksITApO3JldHVybn10LnNldEJpZ1VpbnQ2NChlLG4mMHhmZmZmZmZmZmZmZmZmZmZmbiwhMCl9ZnVuY3Rpb24gVnQodCxlLHIpe2xldCBuPUJpZ0ludChyLndpZHRoKSxvPWd0KHQsZSxyLnVuaXQpPj5CaWdJbnQoci5iaXQpJigxbjw8biktMW47cmV0dXJuIHIudW5pdFswXT09PSJpIiYmbyYxbjw8bi0xbiYmKG8tPTFuPDxuKSxyLndpZHRoPjUzP286TnVtYmVyKG8pfWZ1bmN0aW9uIHZ0KHQsZSxyLG4pe2xldCBvPUJpZ0ludChyLndpZHRoKSxpPUJpZ0ludChyLmJpdCksYz0oMW48PG8pLTFuLHM9Yzw8aSx1PWd0KHQsZSxyLnVuaXQpLHA9KHR5cGVvZiBuPT0iYmlnaW50Ij9uOkJpZ0ludChNYXRoLnRydW5jKG4pKSkmYztZdCh0LGUsci51bml0LHUmfnN8cDw8aSl9dmFyIGp0PXsidXRmLTgiOm5ldyBUZXh0RW5jb2RlcigidXRmLTgiKSwidXRmLTE2bGUiOm5ldyBUZXh0RW5jb2RlcigidXRmLTE2bGUiKX0sWHQ9eyJ1dGYtOCI6bmV3IFRleHREZWNvZGVyKCJ1dGYtOCIse2lnbm9yZUJPTTohMH0pLCJ1dGYtMTZsZSI6bmV3IFRleHREZWNvZGVyKCJ1dGYtMTZsZSIse2lnbm9yZUJPTTohMH0pfTtmdW5jdGlvbiBadCh0LGUscixuKXtsZXQgbz1uZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQrZSxyKSxpPW49PT0idXRmLTE2bGUiPzI6MSxjPXI7Zm9yKGxldCBzPTA7cytpPD1yO3MrPWkpaWYob1tzXT09PTAmJihpPT09MXx8b1tzKzFdPT09MCkpe2M9czticmVha31yZXR1cm4gWHRbbl0uZGVjb2RlKG8uc3ViYXJyYXkoMCxjKSl9ZnVuY3Rpb24gcXQodCxlLHIsbixvKXtsZXQgaT1uZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQrZSxyKTtpLmZpbGwoMCk7bGV0IHM9ci0obj09PSJ1dGYtMTZsZSI/MjoxKTtpZihzPD0wKXJldHVybjtsZXQgdT1qdFtuXS5lbmNvZGUoU3RyaW5nKG8/PyIiKSk7aS5zZXQodS5zdWJhcnJheSgwLE1hdGgubWluKHUubGVuZ3RoLHMpKSl9ZnVuY3Rpb24gS3QodCxlLHIsbil7bGV0IG89bi5lbGVtZW50U2l6ZT4wP3Ivbi5lbGVtZW50U2l6ZTowLGk9W107Zm9yKGxldCBjPTA7YzxvO2MrKylpLnB1c2goVHQodCxlK2Mqbi5lbGVtZW50U2l6ZSxuLmVsZW1lbnRUeXBlLG4uZWxlbWVudFNpemUpKTtyZXR1cm4gaX1mdW5jdGlvbiBRdCh0LGUscixuLG8pe2xldCBpPW4uZWxlbWVudFNpemU+MD9yL24uZWxlbWVudFNpemU6MCxjPW8/P1tdO2ZvcihsZXQgcz0wO3M8aTtzKyspRnQodCxlK3Mqbi5lbGVtZW50U2l6ZSxuLmVsZW1lbnRUeXBlLG4uZWxlbWVudFNpemUsY1tzXSl9ZnVuY3Rpb24gVHQodCxlLHIsbil7c3dpdGNoKHIudGFnKXtjYXNlImJhc2ljIjpyZXR1cm4geih0LGUsci5raW5kKTtjYXNlImJpdGZpZWxkIjpyZXR1cm4gVnQodCxlLHIpO2Nhc2Uic3RyaW5nIjpyZXR1cm4gWnQodCxlLG4sci5lbmNvZGluZyk7Y2FzZSJzdHJ1Y3QiOmNhc2UidW5pb24iOnJldHVybiBRKHQsZSxyLmZpZWxkcyk7Y2FzZSJhcnJheSI6cmV0dXJuIEt0KHQsZSxuLHIpfX1mdW5jdGlvbiBGdCh0LGUscixuLG8pe3N3aXRjaChyLnRhZyl7Y2FzZSJiYXNpYyI6Wih0LGUse2s6ci5raW5kLHY6b30pO2JyZWFrO2Nhc2UiYml0ZmllbGQiOnZ0KHQsZSxyLG8/PzApO2JyZWFrO2Nhc2Uic3RyaW5nIjpxdCh0LGUsbixyLmVuY29kaW5nLG8pO2JyZWFrO2Nhc2Uic3RydWN0IjpjYXNlInVuaW9uIjpTdCh0LGUsci5maWVsZHMsbz8/e30pO2JyZWFrO2Nhc2UiYXJyYXkiOlF0KHQsZSxuLHIsbyk7YnJlYWt9fWZ1bmN0aW9uIFEodCxlLHIpe2xldCBuPXt9O2ZvcihsZXQgbyBvZiByKXtsZXQgaT1UdCh0LGUrby5vZmZzZXQsby50eXBlLG8uc2l6ZSk7aWYoby5ub25udWxsJiZpPT09MCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IGRlY29kZTogJyEnIGZpZWxkICIke28ubmFtZX0iIGdvdCAwIChDIGRpZCBub3QgZmlsbCBpdCwgb3IgZGVjb2RlIHdhcyBjYWxsZWQgb24gYW4gdW5maWxsZWQgc2xvdClgKTtuW28ubmFtZV09aX1yZXR1cm4gbn1mdW5jdGlvbiBTdCh0LGUscixuKXtmb3IobGV0IG8gb2YgciluW28ubmFtZV0hPT12b2lkIDAmJkZ0KHQsZStvLm9mZnNldCxvLnR5cGUsby5zaXplLG5bby5uYW1lXSl9ZnVuY3Rpb24gSnQodCl7bGV0e2ZpZWxkczplLHNpemU6cixtYXhFZmZlY3RpdmVBbGlnbjpufT13dCh0KTtyZXR1cm57ZmllbGRzOmUsc2l6ZTpyLHN0cnVjdEFsaWduOm4sZGVjb2RlOm89PlEodHlwZW9mIG89PSJudW1iZXIiP25ldyBEYXRhVmlldyhodC5yZWFkQnl0ZXMobyxyKSk6bmV3IERhdGFWaWV3KG8pLDAsZSksYWxsb2M6KG89PntpZihvIT09dm9pZCAwJiYoIU51bWJlci5pc0ludGVnZXIobyl8fG88MSkpdGhyb3cgbmV3IEVycm9yKCJmZmktc3RydWN0OiBhbGxvYyhuKSByZXF1aXJlcyBhbiBpbnRlZ2VyIG4gPj0gMSAoUEFCKDApIG5ldmVyIGVzY2FwZXMgXHUyMDE0IHBhc3MgTlVMTCBmb3IgYW4gZW1wdHkgcG9pbnRlciBwb3NpdGlvbikiKTtyZXR1cm4gbmV3IHgocioobz8/MSkpfSksZW5jb2RlOigobyxpLGMpPT57aWYobz09bnVsbCl0aHJvdyBuZXcgRXJyb3IoImZmaS1zdHJ1Y3Q6IGVuY29kZSh2KSByZXF1aXJlcyBhbiBhcmd1bWVudDsgdXNlIGFsbG9jKCkgZm9yIGEgemVyb2VkIG91dC1wYXJhbSBzbG90Iik7bGV0IHM9aT8/bmV3IHgocik7cmV0dXJuIFN0KG5ldyBEYXRhVmlldyhzKSxjPz8wLGUsbyksc30pLG9mZnNldE9mOm89Pntmb3IobGV0IGkgb2YgZSlpZihpLm5hbWU9PT1vKXJldHVybiBpLm9mZnNldDt0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IG5vIGZpZWxkICIke299ImApfX19ZnVuY3Rpb24gdGUodCxlLHIpe2xldCBuPWVbIiMiXTtpZihuIT09dm9pZCAwJiZuIT09dCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6ICR7dH0oKSByZWNlaXZlZCBhICcke1N0cmluZyhuKX0nIGRlY2xhcmF0aW9uIChraW5kIG1pc21hdGNoIFx1MjAxNCB1c2UgJHtufSgpIGZvciBpdClgKTtsZXQgbz1lWyIjcGFjayJdO2lmKHI9PT12b2lkIDAmJm8hPT12b2lkIDApcj1vO2Vsc2UgaWYociE9PXZvaWQgMCYmbyE9PXZvaWQgMCYmciE9PW8pdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiAjcGFjayBjb25mbGljdDogb3B0cy5wYWNrPSR7cn0gdnMgZGVjbGFyYXRpb24gJHtTdHJpbmcobyl9YCk7bGV0IGk9eyIjIjp0fTtyIT09dm9pZCAwJiYoaVsiI3BhY2siXT1yKTtmb3IobGV0W2Msc11vZiBPYmplY3QuZW50cmllcyhlKSljLnN0YXJ0c1dpdGgoIiMiKXx8KGlbY109cyk7cmV0dXJuIGl9ZnVuY3Rpb24gQih0LGUscil7bGV0IG49dHlwZW9mIHQ9PSJzdHJpbmciO3JldHVybiBKdCh0ZSgic3RydWN0IixuP2U6dCwobj9yOmUpPy5wYWNrKSl9dmFyIGVlPXsiIyI6InN0cnVjdCIsY2I6InUzMiIsbHBSZXNlcnZlZDoiPD5wdHIiLGxwRGVza3RvcDoiPD5wdHIiLGxwVGl0bGU6Ijw+cHRyIixkd1g6InUzMiIsZHdZOiJ1MzIiLGR3WFNpemU6InUzMiIsZHdZU2l6ZToidTMyIixkd1hDb3VudENoYXJzOiJ1MzIiLGR3WUNvdW50Q2hhcnM6InUzMiIsZHdGaWxsQXR0cmlidXRlOiJ1MzIiLGR3RmxhZ3M6InUzMiIsd1Nob3dXaW5kb3c6InUxNkBTaG93V2luZG93Q21kIixjYlJlc2VydmVkMjoidTE2IixscFJlc2VydmVkMjoiPD5wdHIiLGhTdGRJbnB1dDoiPEhGSUxFPnB0ciIsaFN0ZE91dHB1dDoiPEhGSUxFPnB0ciIsaFN0ZEVycm9yOiI8SEZJTEU+cHRyIn0sWT1CKCJTVEFSVFVQSU5GT1ciLGVlKSxyZT17IiMiOiJzdHJ1Y3QiLGhQcm9jZXNzOiI8SFBST0NFU1M+cHRyISIsaFRocmVhZDoiPEhUSFJFQUQ+cHRyISIsZHdQcm9jZXNzSWQ6InUzMiIsZHdUaHJlYWRJZDoidTMyIn0sSj1CKCJQUk9DRVNTX0lORk9STUFUSU9OIixyZSk7dmFyIGI9KHQsZSxyKT0+RXQoImtlcm5lbDMyLmRsbCIsdCxlLHIpLEl0PWIoIkNyZWF0ZVBpcGUiLCI8PnB0ciA8PnB0ciA8PnB0ciB1MzIgLT4gaTMyIiksdHQ9YigiU2V0SGFuZGxlSW5mb3JtYXRpb24iLCI8SEZJTEU+cHRyISB1MzIgdTMyIC0+IGkzMiIpLEN0PWIoIkNyZWF0ZVByb2Nlc3NXIiwiPFdDSEFSPnB0ciA8V0NIQVI+cHRyIDw+cHRyIDw+cHRyIGkzMiB1MzIgPD5wdHIgPFdDSEFSPnB0ciA8U1RBUlRVUElORk9XPnB0ciA8UFJPQ0VTU19JTkZPUk1BVElPTj5wdHIgLT4gaTMyIix7U1RBUlRVUElORk9XOll9KSxidD1iKCJXYWl0Rm9yU2luZ2xlT2JqZWN0IiwiPD5wdHIgdTMyIC0+IHUzMiIpLE50PWIoIkdldEV4aXRDb2RlUHJvY2VzcyIsIjxIUFJPQ0VTUz5wdHIhIDxCWVRFPnB0ciAtPiBpMzIiKSxNPWIoIkNsb3NlSGFuZGxlIiwiPD5wdHIgLT4gaTMyIik7dmFyIHl0PWIoIlJlYWRGaWxlIiwiPEhGSUxFPnB0ciEgPEJZVEU+cHRyIHUzMiA8QllURT5wdHIgPD5wdHIgLT4gaTMyIik7dmFyIGV0PWIoIkdldExhc3RFcnJvciIsIiAtPiB1MzIiKSxEdD1iKCJHZXRTeXN0ZW1EaXJlY3RvcnlXIiwiPEJZVEU+cHRyIHUzMiAtPiB1MzIiKTt2YXIgbmU9dD0+e3RyeXtsZXQgZT1QdC5vcGVuKCJkaWFnLmxvZyIsImEiKTtlJiYoZS5wdXRzKGAke0RhdGUubm93KCl9ICR7dH0KYCksZS5jbG9zZSgpKX1jYXRjaHt9fSxydD0xLG9lPTI1NixpZT00Mjk0OTY3Mjk1LEg9T3QuV29ya2VyLnBhcmVudCxMdD0iQzpcXFdpbmRvd3NcXFN5c3RlbTMyIjt0cnl7bGV0IHQ9Ry5hbGxvYygyNTYpLHI9RHQodCwyNTYpPjA/Ry5kZWNvZGUodCk6IiI7ciYmKEx0PXIpfWNhdGNoKHQpe25lKCJTWVMtRElSLUZBSUw6ICIrU3RyaW5nKHQpKX12YXIgbnQ9QigiUElQRV9IQU5ETEVTIix7aFJlYWQ6IjxIRklMRT5wdHIhIixoV3JpdGU6IjxIRklMRT5wdHIhIn0pO2Z1bmN0aW9uIHNlKHQsZSl7bGV0IHI9bnQuYWxsb2MoKTtpZighSXQoci5wdHIsci5wdHIrbnQub2Zmc2V0T2YoImhXcml0ZSIpLE8sMCkpdGhyb3cgbmV3IEVycm9yKCJDcmVhdGVQaXBlIGVycj0iK2V0KCkpO2xldHtoUmVhZDpuLGhXcml0ZTpvfT1udC5kZWNvZGUocik7dHQobyxydCxydCksdHQobixydCwwKTtsZXQgaT1KLmFsbG9jKCksYz1gJHtMdH1cXGNtZC5leGUgL3UgL2MgJHtlfWA7aWYoIUN0KE8sYyxPLE8sMSwwLE8sTyx7Y2I6WS5zaXplLGR3RmxhZ3M6b2UsaFN0ZE91dHB1dDpvLGhTdGRFcnJvcjpvfSxpLnB0cikpdGhyb3cgTShuKSxNKG8pLG5ldyBFcnJvcigiQ3JlYXRlUHJvY2Vzc1cgZXJyPSIrZXQoKSsiIGNtZD0iK2MpO2xldHtoUHJvY2VzczpzLGhUaHJlYWQ6dSxkd1Byb2Nlc3NJZDpwfT1KLmRlY29kZShpKTtNKHUpLE0obyksSC5wb3N0TWVzc2FnZSh7dHlwZToiaW5mbyIsaWQ6dCxwaWQ6cH0pO2xldCBoPW5ldyB4KDQwOTYpLEY9bmV3IFVpbnQ4QXJyYXkoaCksZz1uZXcgeCg0KSxUPW5ldyBVaW50MzJBcnJheShnKTtmb3IoO1RbMF09MCwhIXl0KG4saCw0MDk2LGcsTyk7KXtsZXQgUz1UWzBdO2lmKFM9PT0wKWJyZWFrO0gucG9zdE1lc3NhZ2Uoe3R5cGU6ImRhdGEiLGlkOnQsY2h1bms6Ri5zbGljZSgwLFMpfSl9YnQocyxpZSk7bGV0IEU9bmV3IHgoNCksUD1uZXcgSW50MzJBcnJheShFKTtOdChzLEUpO2xldCB3PVBbMF07cmV0dXJuIE0obiksTShzKSx3fUgub25tZXNzYWdlPXQ9PntsZXQgZT10LmRhdGE7aWYoZS50eXBlPT09InJ1biImJnR5cGVvZiBlLmNtZD09InN0cmluZyIpe2xldCByPS0xLG49bnVsbDt0cnl7cj1zZShlLmlkLGUuY21kKX1jYXRjaChvKXtuPVN0cmluZyhvKX1ILnBvc3RNZXNzYWdlKHt0eXBlOiJyZXN1bHQiLGlkOmUuaWQsY29kZTpyLGVycm9yOm59KX1ILm9ubWVzc2FnZT1udWxsfTsK");
|
|
21918
22295
|
bumpWorkers(1);
|
|
21919
22296
|
const id = 1;
|
|
21920
22297
|
let innerPid = null;
|
|
@@ -21945,7 +22322,7 @@ function runInWorker(cmd, signal, timeoutMs) {
|
|
|
21945
22322
|
return;
|
|
21946
22323
|
settled = true;
|
|
21947
22324
|
if (timer !== null)
|
|
21948
|
-
|
|
22325
|
+
os7.clearTimeout(timer);
|
|
21949
22326
|
worker.onmessage = null;
|
|
21950
22327
|
bumpWorkers(-1);
|
|
21951
22328
|
fn();
|
|
@@ -21958,9 +22335,9 @@ function runInWorker(cmd, signal, timeoutMs) {
|
|
|
21958
22335
|
if (p2)
|
|
21959
22336
|
p2.close();
|
|
21960
22337
|
else
|
|
21961
|
-
console.error("[
|
|
22338
|
+
console.error("[execd] taskkill spawn failed");
|
|
21962
22339
|
} catch (ex) {
|
|
21963
|
-
console.error("[
|
|
22340
|
+
console.error("[execd] kill error:", ex);
|
|
21964
22341
|
}
|
|
21965
22342
|
};
|
|
21966
22343
|
const killOnAbort = () => {
|
|
@@ -21972,7 +22349,7 @@ function runInWorker(cmd, signal, timeoutMs) {
|
|
|
21972
22349
|
killOnAbort();
|
|
21973
22350
|
}
|
|
21974
22351
|
if (timeoutMs != null && timeoutMs > 0) {
|
|
21975
|
-
timer =
|
|
22352
|
+
timer = os7.setTimeout(() => {
|
|
21976
22353
|
finish(() => {
|
|
21977
22354
|
kill();
|
|
21978
22355
|
resolveTrailers({ "X-Exit-Code": "-1" });
|
|
@@ -22031,45 +22408,6 @@ function runInWorker(cmd, signal, timeoutMs) {
|
|
|
22031
22408
|
}
|
|
22032
22409
|
return { stream, ready, trailers, kill };
|
|
22033
22410
|
}
|
|
22034
|
-
var SCREENSHOT_TIMEOUT_MS = 3e4;
|
|
22035
|
-
var WINDOWS_TIMEOUT_MS = 5e3;
|
|
22036
|
-
function withWorker(timeoutMs, onTimeout, post, onData, onResult) {
|
|
22037
|
-
return new Promise((resolve) => {
|
|
22038
|
-
const worker = new os6.Worker("data:text/javascript;base64,aW1wb3J0KmFzIGZlIGZyb20ib3MiO2ltcG9ydCphcyB4ZSBmcm9tInN0ZCI7aW1wb3J0KmFzIHkgZnJvbSJmZmkiO2ltcG9ydCphcyBldCBmcm9tIm9zIjtpbXBvcnQqYXMgSyBmcm9tInN0ZCI7aW1wb3J0KmFzIHJ0IGZyb20id2luIjt2YXIgZ2U9eyJ1dGYtOCI6InV0Zi04Iix1dGY4OiJ1dGYtOCIsInVuaWNvZGUtMS0xLXV0Zi04IjoidXRmLTgiLCJ1dGYtMTYiOiJ1dGYtMTZsZSIsInV0Zi0xNmxlIjoidXRmLTE2bGUiLCJ1dGYtMTZiZSI6InV0Zi0xNmJlIn07ZnVuY3Rpb24gT3QodCl7aWYoIXQpcmV0dXJuInV0Zi04IjtsZXQgZT1nZVt0LnRyaW0oKS50b0xvd2VyQ2FzZSgpXTtpZihlKXJldHVybiBlO3Rocm93IG5ldyBSYW5nZUVycm9yKGBUaGUgZW5jb2RpbmcgbGFiZWwgIiR7dH0iIGlzIG5vdCBzdXBwb3J0ZWRgKX1mdW5jdGlvbiBEZSh0LGUpe2xldCByPSIiO2ZvcihsZXQgbz0wO288dC5sZW5ndGg7KXtsZXQgbj10W28rK107aWYobjwxMjgpe3IrPVN0cmluZy5mcm9tQ2hhckNvZGUobik7Y29udGludWV9aWYobjwxOTIpe3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigidW5leHBlY3RlZCBjb250aW51YXRpb24gYnl0ZSIpfSkoKToiXHVGRkZEIjtjb250aW51ZX1sZXQgaSxjO2lmKG48MjI0KXtpZihvPj10Lmxlbmd0aCl7cis9ZT8oKCk9Pnt0aHJvdyBuZXcgVHlwZUVycm9yKCJpbmNvbXBsZXRlIHV0Zi04Iil9KSgpOiJcdUZGRkQiO2JyZWFrfWxldCBzPXRbbysrXTtpZigocyYxOTIpIT09MTI4KXtyKz0iXHVGRkZEIjtjb250aW51ZX1pPShuJjMxKTw8NnxzJjYzLGM9MTI4fWVsc2UgaWYobjwyNDApe2lmKG8rMT49dC5sZW5ndGgpe3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW5jb21wbGV0ZSB1dGYtOCIpfSkoKToiXHVGRkZEIjticmVha31sZXQgcz10W28rK10scD10W28rK107aWYoKHMmMTkyKSE9PTEyOHx8KHAmMTkyKSE9PTEyOCl7cis9Ilx1RkZGRCI7Y29udGludWV9aT0obiYxNSk8PDEyfChzJjYzKTw8NnxwJjYzLGM9MjA0OH1lbHNlIGlmKG48MjQ4KXtpZihvKzI+PXQubGVuZ3RoKXtyKz1lPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoImluY29tcGxldGUgdXRmLTgiKX0pKCk6Ilx1RkZGRCI7YnJlYWt9bGV0IHM9dFtvKytdLHA9dFtvKytdLGE9dFtvKytdO2lmKChzJjE5MikhPT0xMjh8fChwJjE5MikhPT0xMjh8fChhJjE5MikhPT0xMjgpe3IrPSJcdUZGRkQiO2NvbnRpbnVlfWk9KG4mNyk8PDE4fChzJjYzKTw8MTJ8KHAmNjMpPDw2fGEmNjMsYz02NTUzNn1lbHNle3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW52YWxpZCB1dGYtOCBzdGFydCIpfSkoKToiXHVGRkZEIjtjb250aW51ZX1pZihpPGN8fGk+PTU1Mjk2JiZpPD01NzM0M3x8aT4xMTE0MTExKXtyKz1lPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoImludmFsaWQgdXRmLTggY29kZXBvaW50Iil9KSgpOiJcdUZGRkQiO2NvbnRpbnVlfWk8PTY1NTM1P3IrPVN0cmluZy5mcm9tQ2hhckNvZGUoaSk6KGktPTY1NTM2LHIrPVN0cmluZy5mcm9tQ2hhckNvZGUoNTUyOTZ8aT4+MTAsNTYzMjB8aSYxMDIzKSl9cmV0dXJuIHJ9ZnVuY3Rpb24gRWUodCxlLHIpe2xldCBvPW5ldyBEYXRhVmlldyh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQsdC5ieXRlTGVuZ3RoKSxuPSIiO2ZvcihsZXQgaT0wO2krMTx0Lmxlbmd0aDtpKz0yKXtsZXQgYz1vLmdldFVpbnQxNihpLGUpO2lmKGM+PTU1Mjk2JiZjPD01NjMxOSl7aWYoaSs9MixpKzE+PXQubGVuZ3RoKXtuKz1yPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoInRydW5jYXRlZCBzdXJyb2dhdGUgcGFpciIpfSkoKToiXHVGRkZEIjticmVha31sZXQgcz1vLmdldFVpbnQxNihpLGUpO3M+PTU2MzIwJiZzPD01NzM0Mz9uKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGMscyk6KG4rPXI/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW52YWxpZCBzdXJyb2dhdGUgcGFpciIpfSkoKToiXHVGRkZEIixpLT0yKX1lbHNlIGM+PTU2MzIwJiZjPD01NzM0Mz9uKz1yPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoInVuZXhwZWN0ZWQgdHJhaWxpbmcgc3Vycm9nYXRlIil9KSgpOiJcdUZGRkQiOm4rPVN0cmluZy5mcm9tQ2hhckNvZGUoYyl9cmV0dXJuIG59dmFyIHB0PWNsYXNze19lbmNvZGluZztfZmF0YWw7X2lnbm9yZUJPTTtjb25zdHJ1Y3RvcihlLHIpe3RoaXMuX2VuY29kaW5nPU90KGUpLHRoaXMuX2ZhdGFsPXI/LmZhdGFsPz8hMSx0aGlzLl9pZ25vcmVCT009cj8uaWdub3JlQk9NPz8hMX1nZXQgZW5jb2RpbmcoKXtyZXR1cm4gdGhpcy5fZW5jb2Rpbmd9Z2V0IGZhdGFsKCl7cmV0dXJuIHRoaXMuX2ZhdGFsfWdldCBpZ25vcmVCT00oKXtyZXR1cm4gdGhpcy5faWdub3JlQk9NfWRlY29kZShlKXtpZighZSlyZXR1cm4iIjtsZXQgcj1lIGluc3RhbmNlb2YgVWludDhBcnJheT9lOmUgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcj9uZXcgVWludDhBcnJheShlKTpuZXcgVWludDhBcnJheShlLmJ1ZmZlcixlLmJ5dGVPZmZzZXQsZS5ieXRlTGVuZ3RoKTtpZih0aGlzLl9lbmNvZGluZz09PSJ1dGYtOCIpcmV0dXJuIERlKHIsdGhpcy5fZmF0YWwpO2xldCBvPXRoaXMuX2VuY29kaW5nPT09InV0Zi0xNmxlIixuPTA7aWYoci5sZW5ndGg+PTImJiF0aGlzLl9pZ25vcmVCT00pe2xldCBpPW8/clswXTpyWzFdLHM9KG8/clsxXTpyWzBdKTw8OHxpOyhzPT09NjUyNzl8fHM9PT02NTUzNCkmJihuPTIpfXJldHVybiBFZShyLnNsaWNlKG4pLG8sdGhpcy5fZmF0YWwpfX0sYXQ9Y2xhc3N7X2VuY29kaW5nO2NvbnN0cnVjdG9yKGUpe3RoaXMuX2VuY29kaW5nPU90KGUpfWdldCBlbmNvZGluZygpe3JldHVybiB0aGlzLl9lbmNvZGluZ31lbmNvZGUoZSl7aWYoIWUpcmV0dXJuIG5ldyBVaW50OEFycmF5KDApO2lmKHRoaXMuX2VuY29kaW5nPT09InV0Zi04Iil7bGV0IGk9W107Zm9yKGxldCBjPTA7YzxlLmxlbmd0aDtjKyspe2xldCBzPWUuY2hhckNvZGVBdChjKTtpZihzPDEyOClpLnB1c2gocyk7ZWxzZSBpZihzPDIwNDgpaS5wdXNoKDE5MnxzPj42LDEyOHxzJjYzKTtlbHNlIGlmKHM8NTUyOTZ8fHM+PTU3MzQ0KWkucHVzaCgyMjR8cz4+MTIsMTI4fHM+PjYmNjMsMTI4fHMmNjMpO2Vsc2V7YysrO2xldCBwPWUuY2hhckNvZGVBdChjKTtzPTY1NTM2KygocyYxMDIzKTw8MTApfHAmMTAyMyxpLnB1c2goMjQwfHM+PjE4LDEyOHxzPj4xMiY2MywxMjh8cz4+NiY2MywxMjh8cyY2Myl9fXJldHVybiBuZXcgVWludDhBcnJheShpKX1sZXQgcj10aGlzLl9lbmNvZGluZz09PSJ1dGYtMTZsZSIsbz1uZXcgQXJyYXlCdWZmZXIoZS5sZW5ndGgqMiksbj1uZXcgRGF0YVZpZXcobyk7Zm9yKGxldCBpPTA7aTxlLmxlbmd0aDtpKyspbi5zZXRVaW50MTYoaSoyLGUuY2hhckNvZGVBdChpKSxyKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkobyl9fTt0eXBlb2YgZ2xvYmFsVGhpcy5UZXh0RGVjb2Rlcj4idSImJihnbG9iYWxUaGlzLlRleHREZWNvZGVyPXB0KTt0eXBlb2YgZ2xvYmFsVGhpcy5UZXh0RW5jb2Rlcj4idSImJihnbG9iYWxUaGlzLlRleHRFbmNvZGVyPWF0KTtpbXBvcnR7YnVmZmVyUHRyIGFzIFdlfWZyb20iZmZpIjtpbXBvcnQqYXMgUnQgZnJvbSJvcyI7dmFyIFRlPVsidm9pZCIsInU4IiwiaTgiLCJ1MTYiLCJpMTYiLCJ1MzIiLCJpMzIiLCJ1NjQiLCJpNjQiLCJmMzIiLCJmNjQiLCJwdHIiXSx1dD0vXjwoW0EtWmEtel9dXHcqfCk+cHRyKCF8QFtBLVphLXpfXVx3Kik/JC87ZnVuY3Rpb24gUih0KXtyZXR1cm4gdXQudGVzdCh0KX12YXIgQXQ9L148KFtBLVphLXpfXVx3Kik+JC87ZnVuY3Rpb24gTSh0KXtyZXR1cm4gQXQudGVzdCh0KX1mdW5jdGlvbiBrKHQpe3JldHVybiBBdC5leGVjKHQpPy5bMV18fCIifWZ1bmN0aW9uIGx0KHQpe3JldHVybiB1dC5leGVjKHQpPy5bMV18fCIifXZhciB0dD10PT57aWYoUih0KSlyZXR1cm4icHRyIjtpZihNKHQpKXRocm93IG5ldyBFcnJvcihgZmZpOiBjVG9rZW5Ub1R5cGU6IGJ5LXZhbHVlIHRva2VuICIke3R9IiBoYXMgbm8gc2NhbGFyIHNsb3QgdHlwZWApO3JldHVybiB0fSxBPVJ0LmFyY2g9PT0ieDY0Ij84OjQsJD17dTg6MSxpODoxLHUxNjoyLGkxNjoyLHUzMjo0LGkzMjo0LHU2NDo4LGk2NDo4LGYzMjo0LGY2NDo4fSxJPTA7ZnVuY3Rpb24gWSh0KXtpZihSKHQpKXtsZXQgbj11dC5leGVjKHQpLGk9bj8uWzFdfHwiIjtyZXR1cm4gbj8uWzJdPy5zdGFydHNXaXRoKCJAIik/YDwke2l9PnB0cmA6dH1pZihNKHQpKXJldHVybiB0O2xldCBlPXQuaW5kZXhPZigiQCIpLHI9ZT49MD90LnNsaWNlKDAsZSk6dDtpZigoZTwwfHwvXltBLVphLXpfXVx3KiQvLnRlc3QodC5zbGljZShlKzEpKSkmJnIhPT0icHRyIiYmVGUuaW5jbHVkZXMocikpcmV0dXJuIHI7dGhyb3cgbmV3IEVycm9yKCJVbmtub3duIHRva2VuOiAiK3QpfWZ1bmN0aW9uIFYodCxlLHIpe3N3aXRjaChyKXtjYXNlInU4IjpyZXR1cm4gdC5nZXRVaW50OChlKTtjYXNlImk4IjpyZXR1cm4gdC5nZXRJbnQ4KGUpO2Nhc2UidTE2IjpyZXR1cm4gdC5nZXRVaW50MTYoZSwhMCk7Y2FzZSJpMTYiOnJldHVybiB0LmdldEludDE2KGUsITApO2Nhc2UidTMyIjpyZXR1cm4gdC5nZXRVaW50MzIoZSwhMCk7Y2FzZSJpMzIiOnJldHVybiB0LmdldEludDMyKGUsITApO2Nhc2UidTY0IjpyZXR1cm4gdC5nZXRCaWdVaW50NjQoZSwhMCk7Y2FzZSJpNjQiOnJldHVybiB0LmdldEJpZ0ludDY0KGUsITApO2Nhc2UiZjMyIjpyZXR1cm4gdC5nZXRGbG9hdDMyKGUsITApO2Nhc2UiZjY0IjpyZXR1cm4gdC5nZXRGbG9hdDY0KGUsITApO2Nhc2UicHRyIjpyZXR1cm4gQT09PTg/TnVtYmVyKHQuZ2V0QmlnSW50NjQoZSwhMCkpOnQuZ2V0SW50MzIoZSwhMCl9fWZ1bmN0aW9uIGR0KHQsZSx7azpyLHY6b30pe3N3aXRjaChyKXtjYXNlInU4Ijp0LnNldFVpbnQ4KGUsTnVtYmVyKG8pKTticmVhaztjYXNlImk4Ijp0LnNldEludDgoZSxOdW1iZXIobykpO2JyZWFrO2Nhc2UidTE2Ijp0LnNldFVpbnQxNihlLE51bWJlcihvKSwhMCk7YnJlYWs7Y2FzZSJpMTYiOnQuc2V0SW50MTYoZSxOdW1iZXIobyksITApO2JyZWFrO2Nhc2UidTMyIjp0LnNldFVpbnQzMihlLG8+Pj4wLCEwKTticmVhaztjYXNlImkzMiI6dC5zZXRVaW50MzIoZSxvPj4+MCwhMCk7YnJlYWs7Y2FzZSJ1NjQiOnQuc2V0QmlnVWludDY0KGUsbywhMCk7YnJlYWs7Y2FzZSJpNjQiOnQuc2V0QmlnSW50NjQoZSxvLCEwKTticmVhaztjYXNlImYzMiI6dC5zZXRGbG9hdDMyKGUsbywhMCk7YnJlYWs7Y2FzZSJmNjQiOnQuc2V0RmxvYXQ2NChlLG8sITApO2JyZWFrO2Nhc2UicHRyIjp7aWYobz09bnVsbCl0aHJvdyBuZXcgRXJyb3IoImZmaTogZ290IG51bGwvdW5kZWZpbmVkIGZvciBhIHB0ciBzbG90OyBwYXNzIHRoZSBpbXBvcnRlZCBOVUxMIGNvbnN0YW50IGZvciBlbXB0eSIpO0E9PT04P3Quc2V0QmlnVWludDY0KGUsQmlnSW50LmFzVWludE4oNjQsQmlnSW50KG8pKSwhMCk6dC5zZXRVaW50MzIoZSxvPj4+MCwhMCk7YnJlYWt9fX1mdW5jdGlvbiB2KHQsZSxyKXtsZXR7azpvLHY6bn09cjtpZihvPT09InU4Inx8bz09PSJpOCJ8fG89PT0idTE2Inx8bz09PSJpMTYiKXt0LnNldFVpbnQzMihlLE51bWJlcihuKT4+PjAsITApO3JldHVybn1kdCh0LGUscil9dmFyIGI9Y2xhc3MgZXh0ZW5kcyBBcnJheUJ1ZmZlcntwdHI7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSksdGhpcy5wdHI9V2UodGhpcyl9fTtmdW5jdGlvbiBmdCh0LGUpe3JldHVybiBlW3RdfXZhciBCdD1uZXcgTWFwO2Z1bmN0aW9uIGJlKHQpe2xldCBlPUJ0LmdldCh0KTtpZihlIT09dm9pZCAwKXJldHVybiBlO2xldCByPXJ0LkxvYWRMaWJyYXJ5KHQpO2lmKCFyKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IExvYWRMaWJyYXJ5KCIke3R9IikgZmFpbGVkYCk7cmV0dXJuIEJ0LnNldCh0LHIpLHJ9ZnVuY3Rpb24gVXQodCl7bGV0IGU9dC5zcGxpdCgiIC0+ICIpO2lmKGUubGVuZ3RoIT09Mil0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiBpbnZhbGlkIHNpZ25hdHVyZSAiJHt0fSIgKGV4cGVjdGVkICJhcmcxIGFyZzIgLT4gcmV0IilgKTtsZXQgcj1lWzBdLnNwbGl0KCIgIikuZmlsdGVyKGk9PmkhPT0iIiksbz1bXTtmb3IobGV0IGkgb2Ygcil7bGV0IGM9WShpKTtpZihjPT09InZvaWQiKXRocm93IG5ldyBFcnJvcigiVm9pZCBjYW4gbm90IGluIGFyZ3MiKTtvLnB1c2goYyl9bGV0IG49WShlWzFdKTtpZihNKG4pKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICIke3R9IjogYnktdmFsdWUgc3RydWN0IGF0IHRoZSByZXR1cm4gcG9zaXRpb24gKDwke2sobil9PikgaXMgbm90IHN1cHBvcnRlZCBcdTIwMTQgYXJndW1lbnQgcG9zaXRpb25zIG9ubHk7IHBhc3MgYSBzdHJ1Y3Qgb3V0IHRocm91Z2ggYW4gb3V0LXBhcmFtIHNsb3QgaW5zdGVhZCAoPE4+cHRyICsgY2FsbGVyIGJ1ZmZlcilgKTtyZXR1cm57YXJnVG9rZW5zOm8scmV0VG9rZW46bixzaWc6dH19ZnVuY3Rpb24gTmUodCxlLHIsbyl7bGV0IG49VXQoZSk7Zm9yKGxldCBpIG9mIG4uYXJnVG9rZW5zKXtpZighTShpKSljb250aW51ZTtsZXQgYz1rKGkpLHM9ZnQoYyxyKTtpZighc3x8dHlwZW9mIHMuZW5jb2RlIT0iZnVuY3Rpb24iKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICR7ZX06IGJ5LXZhbHVlIHBvc2l0aW9uIDwke2N9PiBoYXMgbm8gcmVnaXN0ZXJlZCBsYXlvdXQgKGF2YWlsYWJsZTogJHtPYmplY3Qua2V5cyhyKS5qb2luKCIsICIpfHwibm9uZSJ9KWApO2lmKHR5cGVvZiBzLnNpemUhPSJudW1iZXIifHxzLnNpemU8MSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke2V9OiBieS12YWx1ZSBwb3NpdGlvbiA8JHtjfT4gcmVxdWlyZXMgYSBzdHJ1Y3QgbGF5b3V0IHdpdGggc2l6ZSA+PSAxIChnb3QgJHtzLnNpemV9OyBub24tc3RydWN0IGNvZGVjcyBleHBvc2Ugbm8gc2l6ZSlgKX1yZXR1cm4oLi4uaSk9PkllKHQsbixpLHIsbyl9dmFyIHh0PXt1ODo0LGk4OjQsdTE2OjQsaTE2OjQsdTMyOjQsaTMyOjQsdTY0OjgsaTY0OjgsZjMyOjQsZjY0OjgscHRyOkF9LEd0PTQ7ZnVuY3Rpb24gSWUodCx7YXJnVG9rZW5zOmUscmV0VG9rZW46cixzaWc6b30sbixpLGMpe2xldCBzPWV0LmFyY2g9PT0ieDY0IixwPShsLEQpPT57aWYoTShsKSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiBnZXRXaWR0aDogYnktdmFsdWUgdG9rZW4gIiR7bH0iIChkaXNwYXRjaGVkIGJ5IHdpZHRoT2YpYCk7cmV0dXJuIEQ/ODpSKGwpP0E6eHRbbF19LGE9bD0+e2lmKE0obCkpe2lmKHMpcmV0dXJuIDg7bGV0IEQ9ZnQoayhsKSxpKTtpZighRCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiA8JHtrKGwpfT4gYnktdmFsdWUgcG9zaXRpb24gaGFzIG5vIHJlZ2lzdGVyZWQgbGF5b3V0YCk7bGV0IEU9RC5zaXplO3JldHVybiBFJTQ9PT0wP0U6RSs0LUUlNH1yZXR1cm4gcChsLHMpfSx1PTA7Zm9yKGxldCBsIG9mIGUpdSs9YShsKTtzJiZlLmxlbmd0aDxHdCYmKHU9R3QqOCk7bGV0IHg9bmV3IEFycmF5QnVmZmVyKHUpLGQ9bmV3IERhdGFWaWV3KHgpLHc9W10sZj0wO2ZvcihsZXQgbD0wO2w8ZS5sZW5ndGg7bCsrKXtsZXQgRD1lW2xdLEU9RC5lbmRzV2l0aCgiISIpLEM9bltsXTtpZihSKEQpKXtsZXQgaD1sdChEKTtpZih0eXBlb2YgQz09Im51bWJlciIpe2lmKEUmJkM9PT0wKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICR7b306IGFyZyMke2wrMX0gPCR7aH0+cHRyISBnb3QgMCAobnVsbCBwb2ludGVyIGZvcmJpZGRlbiBoZXJlOyB0aGUgdG9rZW4gbWFya3MgdGhpcyBwb3NpdGlvbiBub24tbnVsbClgKTt2KGQsZix7azoicHRyIix2OkN9KX1lbHNle2lmKEM9PW51bGwpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogPCR7aH0+cHRyIGdvdCAke1N0cmluZyhDKX07IHBhc3MgdGhlIGltcG9ydGVkIE5VTEwgY29uc3RhbnQgZm9yIGFuIGVtcHR5IHBvaW50ZXJgKTtsZXQgVD1pW2hdO2lmKCFUKXRocm93IG5ldyBFcnJvcihoPT09IiI/YGZmaS1iaW5kOiA8PnB0ciBleHBlY3RzIG51bWJlciAoTlVMTCB8IFB0ciksIGdvdCAke3R5cGVvZiBDfTsgdXNlIDxCWVRFPnB0ciB3aXRoIGEgUHRyQXJyYXlCdWZmZXIgKG5ldyBQdHJBcnJheUJ1ZmZlcihuKSksIG9yIGZmaS5idWZmZXJQdHIoYnVmKSBmb3IgYW4gYWRkcmVzc2A6YGZmaS1iaW5kOiB1bmtub3duIGxheW91dCAiPCR7aH0+cHRyIiAoYXZhaWxhYmxlOiAke09iamVjdC5rZXlzKGkpLmpvaW4oIiwgIil8fCJub25lIn0pYCk7aWYoIVQuZW5jb2RlKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IDwke2h9PnB0ciBoYXMgbm8gZW5jb2RlciAob3V0LW9ubHkgY29kZWMpYCk7bGV0IEg9VC5lbmNvZGUoQyk7dy5wdXNoKEgpO2xldCBMPUgucHRyO2lmKHR5cGVvZiBMIT0ibnVtYmVyIil0aHJvdyBuZXcgRXJyb3IoImZmaS1iaW5kOiBjb2RlYy5lbmNvZGUgbXVzdCByZXR1cm4gYSBQdHJBcnJheUJ1ZmZlciwgZ290IHBsYWluIEFycmF5QnVmZmVyIik7aWYoRSYmTD09PTApdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogJHtvfTogYXJnIyR7bCsxfSA8JHtofT5wdHIhIGVuY29kZSBwcm9kdWNlZCAwIChudWxsIHBvaW50ZXIgZm9yYmlkZGVuIGhlcmUpYCk7dihkLGYse2s6InB0ciIsdjpMfSl9fWVsc2UgaWYoTShEKSl7bGV0IGg9ayhEKSxUPWZ0KGgsaSk7aWYoIVQpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogJHtvfTogYXJnIyR7bCsxfSA8JHtofT4gYnktdmFsdWUgcG9zaXRpb24gaGFzIG5vIHJlZ2lzdGVyZWQgbGF5b3V0YCk7aWYoQz09bnVsbCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiA8JHtofT4gdmFsdWUgcG9zaXRpb24gZ290ICR7U3RyaW5nKEMpfTsgcGFzcyBhIHN0cnVjdCBvYmplY3QgKHVzZSA8JHtofT5wdHIgdG8gcGFzcyBhIHBvaW50ZXIpYCk7bGV0IEg9VC5zaXplO2lmKCFzfHxIPD04JiYoSCZILTEpPT09MClULmVuY29kZShDLHgsZik7ZWxzZXtsZXQgTD1uZXcgQXJyYXlCdWZmZXIoSCsxNSksUHQ9eS5idWZmZXJQdHIoTCksTXQ9KDE2LVB0JTE2KSUxNjtULmVuY29kZShDLEwsTXQpLHcucHVzaChMKSx2KGQsZix7azoicHRyIix2OlB0K010fSl9fWVsc2UgdihkLGYse2s6RCx2OkN9KTtmKz1hKEQpfWxldCBTPW5ldyBBcnJheUJ1ZmZlcig4KTt5LmZmaUNhbGwodCx4LFMscj09PSJmMzIifHxyPT09ImY2NCI/MTowKTtsZXQgVz15ZSh0dChyKSxTKTtpZihyLmVuZHNXaXRoKCIhIikmJlc9PT0wKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICR7b306IHJldHVybiAke3J9IGdvdCAwICh0aGUgdG9rZW4gcHJvbWlzZXMgQyBuZXZlciByZXR1cm5zIG51bGwgaGVyZSlgKTtpZihSKHIpJiZXIT09MCl7bGV0IGw9bHQocik7aWYobCE9PSIiKXtsZXQgRD1jW2xdO2lmKEQ/LmRlY29kZSlyZXR1cm4gRC5kZWNvZGUoVyl9fXJldHVybiBXfWZ1bmN0aW9uIHllKHQsZSl7aWYodCE9PSJ2b2lkIilyZXR1cm4gVihuZXcgRGF0YVZpZXcoZSksMCx0KX12YXIgQj17ZW5jb2RlOnQ9PntsZXQgZT1uZXcgVGV4dEVuY29kZXIoInV0Zi0xNmxlIikuZW5jb2RlKHQrIlwwIikscj1uZXcgYihlLmJ5dGVMZW5ndGgpO3JldHVybiBuZXcgVWludDhBcnJheShyKS5zZXQoZSkscn0sZGVjb2RlOnQ9PntpZih0eXBlb2YgdD09Im51bWJlciIpe2xldCBuPSIiLGk9dCxjPWk7Zm9yKDs7KXtsZXQgcz15LnJlYWRCeXRlKGkpLHA9eS5yZWFkQnl0ZShpKzEpO2lmKHM9PT0wJiZwPT09MClyZXR1cm4gbjtpZihuKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHN8cDw8OCksaSs9MixpLWM+MTw8MjEpdGhyb3cgbmV3IEVycm9yKCJmZmktYmluZDogV0NIQVIgZGVjb2RlIGV4Y2VlZGVkIDRNaUIgd2l0aG91dCBOVUwiKX19bGV0IGU9bmV3IFVpbnQ4QXJyYXkodCkscj1lLmxlbmd0aCYtMixvPSIiO2ZvcihsZXQgbj0wO248cjtuKz0yKXtsZXQgaT1lW25dfGVbbisxXTw8ODtpZihpPT09MClyZXR1cm4gbztvKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGkpfXJldHVybiBvfSxhbGxvYzoodD0yNTYpPT5uZXcgYih0KjIpfSxGZT17ZW5jb2RlOnQ9PntpZighKHQgaW5zdGFuY2VvZiBiKSl0aHJvdyBuZXcgRXJyb3IoImZmaS1iaW5kOiA8QllURT5wdHIgd2FudHMgYSBQdHJBcnJheUJ1ZmZlciAobmV3IFB0ckFycmF5QnVmZmVyKG4pIC8gQllURS5hbGxvYyAvIHN0cnVjdC5lbmNvZGUpLCBub3QgYSBwbGFpbiBBcnJheUJ1ZmZlciIpO3JldHVybiB0fSxhbGxvYzp0PT5uZXcgYih0KX0sTHQ9e1dDSEFSOkIsQllURTpGZX07ZnVuY3Rpb24gRyh0LGUscixvLG4pe2xldCBpPXJ0LkdldFByb2NBZGRyZXNzKGJlKHQpLGUpO2lmKCFpKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IHByb2MgIiR7ZX0iIG5vdCBmb3VuZCBpbiAke3R9YCk7bGV0IGM9bj8/bztyZXR1cm4gTmUoaSxyLHsuLi5MdCwuLi5vfSx7Li4uTHQsLi4uYz8/e319KX12YXIga3Q9bmV3IEZpbmFsaXphdGlvblJlZ2lzdHJ5KHQ9PntLLnByaW50ZihgW2ZmaV0gY2xvc3VyZSBsZWFrZWQgKEdDZWQgd2l0aG91dCBkaXNwb3NlKTogc2lnPSIlcyIgcHRyPTB4JXgKYCx0LnNpZyx0LnB0cil9KTtmdW5jdGlvbiBIZSh0LGUscixvLG4saSl7bGV0IGM9bmV3IERhdGFWaWV3KG4pLHM9ZXQuYXJjaD09PSJ4NjQiLHA9bmV3IERhdGFWaWV3KG8pLGE9W10sdT0wO2ZvcihsZXQgZD0wO2Q8dC5sZW5ndGg7ZCsrKXtsZXQgdz10W2RdLGY9dy50b2ssUztpZihzKXtsZXQgVz1mPT09ImYzMiJ8fGY9PT0iZjY0Ij9kPDQ/MTI4K2QqODozMisoZC00KSo4OmQ8ND9kKjg6MzIrKGQtNCkqODtTPVYocCxXLGYpfWVsc2UgUz1WKHAsdSxmKSx1Kz14dFtmXTtpZih3Lm5vbm51bGwmJlM9PT0wKXtLLnByaW50ZihgW2ZmaV0gY2xvc3VyZSAlczogYXJnIyVkIGdvdCAwICghIHByb21pc2UgdmlvbGF0ZWQgYnkgY2FsbGVyKSwgc2tpcHBpbmcgY2FsbGJhY2sKYCxpLGQrMSk7cmV0dXJufWEucHVzaChTKX1sZXQgeDt0cnl7eD1yKC4uLmEpfWNhdGNoKGQpe0sucHJpbnRmKGBbZmZpXSBjbG9zdXJlIGNhbGxiYWNrIHRocmV3OiAlcwpgLFN0cmluZyhkKSk7cmV0dXJufWlmKGUubm9ubnVsbCYmeD09PTApe0sucHJpbnRmKGBbZmZpXSBjbG9zdXJlICVzOiByZXR1cm4gZ290IDAgKCEgcHJvbWlzZSB2aW9sYXRlZCBieSBjYWxsYmFjayksIGxlYXZpbmcgcmVzdWx0IHNsb3QgMApgLGkpO3JldHVybn1lLnRvayE9PSJ2b2lkIiYmdihjLDAse2s6ZS50b2ssdjp4fSl9ZnVuY3Rpb24gX3QodCxlLHIpe2xldHthcmdUb2tlbnM6byxyZXRUb2tlbjpufT1VdCh0KTtmb3IobGV0IG0gb2YgbylpZihNKG0pKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IGNsb3N1cmUgc2lnbmF0dXJlIGNhbm5vdCB0YWtlIGEgYnktdmFsdWUgc3RydWN0ICg8JHtrKG0pfT4pOyBieS12YWx1ZSBpcyBiaW5kLW9ubHkgXHUyMDE0IHRoZSBDXHUyMTkySlMgZGlyZWN0aW9uIGhhcyBubyBzdHJ1Y3Qgc2xvdCBkZWNvZGluZyAocGFzcyBhIHBvaW50ZXIgYW5kIGRlY29kZSBvbiB0aGUgSlMgc2lkZSlgKTtsZXQgaT1vLm1hcChtPT4oe3Rvazp0dChtKSxub25udWxsOm0uZW5kc1dpdGgoIiEiKX0pKSxjPXt0b2s6dHQobiksbm9ubnVsbDpuLmVuZHNXaXRoKCIhIil9LHM9ZXQuYXJjaD09PSJ4NjQiLHA9aS5yZWR1Y2UoKG0sVyk9Pm0reHRbVy50b2tdLDApO2lmKHM/aS5sZW5ndGg+MTY6cD42NCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiBjbG9zdXJlIHNpZ25hdHVyZSBleGNlZWRzIGNhcHR1cmUgd2luZG93ICgke3M/Im1heCAxNiBwYXJhbXMiOiJtYXggNjQgc3RhY2sgYnl0ZXMifSk6ICR7dH1gKTtsZXQgYT1yPy5zdGRjYWxsPT09ITF8fHM/MDpwLHU9Yy50b2s9PT0iZjMyIj8xOmMudG9rPT09ImY2NCI/MjpjLnRvaz09PSJ1NjQifHxjLnRvaz09PSJpNjQiPzM6MCxkPXkuY2xvc3VyZU5ldyhhLHUsKG0sVyk9PntIZShpLGMsZSxtLFcsdCl9KSx3PSExLGY9KCk9Pnt3fHwodz0hMCxrdC51bnJlZ2lzdGVyKGYpLHkuY2xvc3VyZUZyZWUoZCkpfSxTPXtwdHI6ZCxkaXNwb3NlOmZ9O3JldHVybiBrdC5yZWdpc3RlcihmLHtzaWc6dCxwdHI6ZH0pLFN9aW1wb3J0KmFzIHd0IGZyb20iZmZpIjtmdW5jdGlvbiBYKHQsZSl7cmV0dXJuIHQrZS0xJn4oZS0xKX12YXIgenQ9dD0+JFt0XSE9PXZvaWQgMDtmdW5jdGlvbiBtdCh0KXtpZih0eXBlb2YgdD09InN0cmluZyIpe2xldCBlPS9eKHU4fHUxNilcWyhcZCspXF1AKHV0Zi04fHV0Zi0xNmxlKSQvLmV4ZWModCk7aWYoZSl7bGV0IGM9TnVtYmVyKGVbMl0pO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKGMpfHxjPDEpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBzdHJpbmcgbGVuZ3RoIG11c3QgYmUgYW4gaW50ZWdlciA+PSAxLCBnb3QgJHtjfWApO2xldCBzPWVbMV09PT0idTgiPzE6MjtyZXR1cm57c2l6ZTpzKmMsYWxpZ246cyx0eXBlOnt0YWc6InN0cmluZyIsZW5jb2Rpbmc6ZVszXX19fWxldCByPS9eKFteXFtcXV0rKVxbKFxkKylcXSQvLmV4ZWModCk7aWYocil7bGV0IGM9TnVtYmVyKHJbMl0pO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKGMpfHxjPDEpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBhcnJheSBsZW5ndGggbXVzdCBiZSBhbiBpbnRlZ2VyID49IDEsIGdvdCAke2N9YCk7bGV0IHM9bXQoclsxXSk7aWYocy50eXBlLnRhZz09PSJiaXRmaWVsZCIpdGhyb3cgbmV3IEVycm9yKCJmZmktc3RydWN0OiBiaXRmaWVsZHMgY2Fubm90IGJlIGFycmF5IGVsZW1lbnRzIik7cmV0dXJue3NpemU6cy5zaXplKmMsYWxpZ246cy5hbGlnbix0eXBlOnt0YWc6ImFycmF5IixlbGVtZW50VHlwZTpzLnR5cGUsZWxlbWVudFNpemU6cy5zaXplfX19bGV0IG89L14oW0EtWmEtel9dXHcqKTooXGQrKSQvLmV4ZWModCk7aWYobyl7bGV0IGM9b1sxXSxzPVkoYyk7aWYoIXp0KHMpfHxzPT09ImYzMiJ8fHM9PT0iZjY0Iil0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IGJpdGZpZWxkIHVuaXQgbXVzdCBiZSBhbiBpbnRlZ2VyIHR5cGUsIGdvdCAiJHtjfSJgKTtsZXQgcD1OdW1iZXIob1syXSksYT0kW3NdLHU9YSo4O2lmKCFOdW1iZXIuaXNJbnRlZ2VyKHApfHxwPDEpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBiaXRmaWVsZCB3aWR0aCBtdXN0IGJlIGFuIGludGVnZXIgPj0gMSwgZ290ICR7cH1gKTtpZihwPnUpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBiaXRmaWVsZCB3aWR0aCAke3B9IGV4Y2VlZHMgdW5pdCB3aWR0aCAke3V9YCk7cmV0dXJue3NpemU6YSxhbGlnbjphLHR5cGU6e3RhZzoiYml0ZmllbGQiLHVuaXQ6cyxiaXQ6MCx3aWR0aDpwfX19bGV0IG49WSh0KTtpZihSKG4pKXJldHVybntzaXplOkEsYWxpZ246QSx0eXBlOnt0YWc6ImJhc2ljIixraW5kOiJwdHIifX07aWYoIXp0KG4pKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogdW5rbm93biBraW5kICIke3R9ImApO2xldCBpPSRbbl07cmV0dXJue3NpemU6aSxhbGlnbjppLHR5cGU6e3RhZzoiYmFzaWMiLGtpbmQ6bn19fWlmKHQmJnR5cGVvZiB0PT0ib2JqZWN0Iil7bGV0IGU9dCxyPWVbIiMiXTtpZihyPT09dm9pZCAwKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogbmVzdGVkIG9iamVjdCB2YWx1ZSByZXF1aXJlcyBhICcjJyBrZXkgKCdzdHJ1Y3QnIHwgJ3VuaW9uJyB8ICdhcnJheScpIik7aWYocj09PSJhcnJheSImJiIjcGFjayJpbiBlKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogJyNwYWNrJyBpcyBvbmx5IGFsbG93ZWQgb24gc3RydWN0L3VuaW9uLCBnb3QgJyR7cn0nYCk7aWYocj09PSJhcnJheSIpe2xldCBvPWUubGVuZ3RoO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKG8pfHxvPDEpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBhcnJheSBsZW5ndGggbXVzdCBiZSBhbiBpbnRlZ2VyID49IDEsIGdvdCAke1N0cmluZyhvKX1gKTtsZXQgbj1tdChlLmVsZW1lbnQpO2lmKG4udHlwZS50YWc9PT0iYml0ZmllbGQiKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYml0ZmllbGRzIGNhbm5vdCBiZSBhcnJheSBlbGVtZW50cyIpO3JldHVybntzaXplOm4uc2l6ZSpvLGFsaWduOm4uYWxpZ24sdHlwZTp7dGFnOiJhcnJheSIsZWxlbWVudFR5cGU6bi50eXBlLGVsZW1lbnRTaXplOm4uc2l6ZX19fWlmKHI9PT0ic3RydWN0Inx8cj09PSJ1bmlvbiIpe2xldCBvPWh0KHQpO3JldHVybntzaXplOm8uc2l6ZSxhbGlnbjpvLm1heEVmZmVjdGl2ZUFsaWduLHR5cGU6e3RhZzpyLGZpZWxkczpvLmZpZWxkc319fXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogdW5rbm93biAnIycgZGVjbGFyYXRpb24gJHtKU09OLnN0cmluZ2lmeShTdHJpbmcocikpfWApfXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogaW52YWxpZCBtZW1iZXIgdmFsdWU6ICR7U3RyaW5nKHQpfWApfWZ1bmN0aW9uIGh0KHQpe2xldCBlPXRbIiMiXT09PSJzdHJ1Y3QiLHI9dFsiI3BhY2siXT8/OCxvPTEsbj0wLGk9W10sYz0wLHM9LTEscD0wLGE9MCx1PSgpPT57czwwfHwoYz1YKHMrTWF0aC5jZWlsKHAvOCksYSkscz0tMSl9O2ZvcihsZXRbeCxkXW9mIE9iamVjdC5lbnRyaWVzKHQpKXtpZih4LnN0YXJ0c1dpdGgoIiMiKSljb250aW51ZTtsZXQgdz0vXihbXkBdKylAKFxkKykkLy5leGVjKHgpLGY9dz93WzFdOngsUz13P051bWJlcih3WzJdKTowLHtzaXplOm0sYWxpZ246Vyx0eXBlOmx9PW10KGQpLEQ9dHlwZW9mIGQ9PSJzdHJpbmciJiZkLmVuZHNXaXRoKCIhIiksRT1XO2lmKHI+MCYmKEU9TWF0aC5taW4ocixFKSksUyYmKEU9TWF0aC5tYXgoRSxTKSksbC50YWc9PT0iYml0ZmllbGQiKXtpZihmLnN0YXJ0c1dpdGgoIiQiKSl0aHJvdyBuZXcgRXJyb3IoImZmaS1zdHJ1Y3Q6IGJpdGZpZWxkIG1lbWJlcnMgbXVzdCBiZSBuYW1lZCIpO2lmKCFlKXtpLnB1c2goe25hbWU6ZixvZmZzZXQ6MCxzaXplOm0sdHlwZTp7Li4ubCxiaXQ6MH19KSxvPU1hdGgubWF4KG8sRSksbj1NYXRoLm1heChuLG0pO2NvbnRpbnVlfWxldCBoPWwud2lkdGg7KHM8MHx8bSE9PWF8fHAraD5hKjgpJiYocz49MCYmdSgpLHM9WChjLEUpLHA9MCxhPW0pLGkucHVzaCh7bmFtZTpmLG9mZnNldDpzLHNpemU6bSx0eXBlOnsuLi5sLGJpdDpwfX0pLHArPWgsbz1NYXRoLm1heChvLEUpLG49TWF0aC5tYXgobixtKTtjb250aW51ZX11KCk7bGV0IEM9WChjLEUpO2lmKCFmLnN0YXJ0c1dpdGgoIiQiKSlpLnB1c2goe25hbWU6ZixvZmZzZXQ6QyxzaXplOm0sdHlwZTpsLC4uLkQ/e25vbm51bGw6ITB9Ont9fSk7ZWxzZXtpZihsLnRhZyE9PSJzdHJ1Y3QiJiZsLnRhZyE9PSJ1bmlvbiIpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBhbm9ueW1vdXMgbWVtYmVyICIke2Z9IiBtdXN0IGJlIGEgc3RydWN0L3VuaW9uYCk7Zm9yKGxldCBoIG9mIGwuZmllbGRzKWkucHVzaCh7Li4uaCxvZmZzZXQ6aC5vZmZzZXQrQ30pfWUmJihjPUMrbSksbz1NYXRoLm1heChvLEUpLG49TWF0aC5tYXgobixtKX1yZXR1cm4gdSgpLHtzaXplOlgoZT9jOm4sbyksbWF4RWZmZWN0aXZlQWxpZ246byxmaWVsZHM6aX19ZnVuY3Rpb24gJHQodCxlLHIpe2xldCBvPSRbcl07cmV0dXJuIG89PT0xP0JpZ0ludCh0LmdldFVpbnQ4KGUpKTpvPT09Mj9CaWdJbnQodC5nZXRVaW50MTYoZSwhMCkpOm89PT00P0JpZ0ludCh0LmdldFVpbnQzMihlLCEwKSk6dC5nZXRCaWdVaW50NjQoZSwhMCl9ZnVuY3Rpb24gUGUodCxlLHIsbyl7bGV0IG49JFtyXTtpZihuPT09MSl7dC5zZXRVaW50OChlLE51bWJlcihvJjB4ZmZuKSk7cmV0dXJufWlmKG49PT0yKXt0LnNldFVpbnQxNihlLE51bWJlcihvJjB4ZmZmZm4pLCEwKTtyZXR1cm59aWYobj09PTQpe3Quc2V0VWludDMyKGUsTnVtYmVyKG8mMHhmZmZmZmZmZm4pLCEwKTtyZXR1cm59dC5zZXRCaWdVaW50NjQoZSxvJjB4ZmZmZmZmZmZmZmZmZmZmZm4sITApfWZ1bmN0aW9uIE1lKHQsZSxyKXtsZXQgbz1CaWdJbnQoci53aWR0aCksbj0kdCh0LGUsci51bml0KT4+QmlnSW50KHIuYml0KSYoMW48PG8pLTFuO3JldHVybiByLnVuaXRbMF09PT0iaSImJm4mMW48PG8tMW4mJihuLT0xbjw8byksci53aWR0aD41Mz9uOk51bWJlcihuKX1mdW5jdGlvbiBPZSh0LGUscixvKXtsZXQgbj1CaWdJbnQoci53aWR0aCksaT1CaWdJbnQoci5iaXQpLGM9KDFuPDxuKS0xbixzPWM8PGkscD0kdCh0LGUsci51bml0KSxhPSh0eXBlb2Ygbz09ImJpZ2ludCI/bzpCaWdJbnQoTWF0aC50cnVuYyhvKSkpJmM7UGUodCxlLHIudW5pdCxwJn5zfGE8PGkpfXZhciBSZT17InV0Zi04IjpuZXcgVGV4dEVuY29kZXIoInV0Zi04IiksInV0Zi0xNmxlIjpuZXcgVGV4dEVuY29kZXIoInV0Zi0xNmxlIil9LEFlPXsidXRmLTgiOm5ldyBUZXh0RGVjb2RlcigidXRmLTgiLHtpZ25vcmVCT006ITB9KSwidXRmLTE2bGUiOm5ldyBUZXh0RGVjb2RlcigidXRmLTE2bGUiLHtpZ25vcmVCT006ITB9KX07ZnVuY3Rpb24gQmUodCxlLHIsbyl7bGV0IG49bmV3IFVpbnQ4QXJyYXkodC5idWZmZXIsdC5ieXRlT2Zmc2V0K2UsciksaT1vPT09InV0Zi0xNmxlIj8yOjEsYz1yO2ZvcihsZXQgcz0wO3MraTw9cjtzKz1pKWlmKG5bc109PT0wJiYoaT09PTF8fG5bcysxXT09PTApKXtjPXM7YnJlYWt9cmV0dXJuIEFlW29dLmRlY29kZShuLnN1YmFycmF5KDAsYykpfWZ1bmN0aW9uIEdlKHQsZSxyLG8sbil7bGV0IGk9bmV3IFVpbnQ4QXJyYXkodC5idWZmZXIsdC5ieXRlT2Zmc2V0K2Uscik7aS5maWxsKDApO2xldCBzPXItKG89PT0idXRmLTE2bGUiPzI6MSk7aWYoczw9MClyZXR1cm47bGV0IHA9UmVbb10uZW5jb2RlKFN0cmluZyhuPz8iIikpO2kuc2V0KHAuc3ViYXJyYXkoMCxNYXRoLm1pbihwLmxlbmd0aCxzKSkpfWZ1bmN0aW9uIExlKHQsZSxyLG8pe2xldCBuPW8uZWxlbWVudFNpemU+MD9yL28uZWxlbWVudFNpemU6MCxpPVtdO2ZvcihsZXQgYz0wO2M8bjtjKyspaS5wdXNoKFl0KHQsZStjKm8uZWxlbWVudFNpemUsby5lbGVtZW50VHlwZSxvLmVsZW1lbnRTaXplKSk7cmV0dXJuIGl9ZnVuY3Rpb24ga2UodCxlLHIsbyxuKXtsZXQgaT1vLmVsZW1lbnRTaXplPjA/ci9vLmVsZW1lbnRTaXplOjAsYz1uPz9bXTtmb3IobGV0IHM9MDtzPGk7cysrKVZ0KHQsZStzKm8uZWxlbWVudFNpemUsby5lbGVtZW50VHlwZSxvLmVsZW1lbnRTaXplLGNbc10pfWZ1bmN0aW9uIFl0KHQsZSxyLG8pe3N3aXRjaChyLnRhZyl7Y2FzZSJiYXNpYyI6cmV0dXJuIFYodCxlLHIua2luZCk7Y2FzZSJiaXRmaWVsZCI6cmV0dXJuIE1lKHQsZSxyKTtjYXNlInN0cmluZyI6cmV0dXJuIEJlKHQsZSxvLHIuZW5jb2RpbmcpO2Nhc2Uic3RydWN0IjpjYXNlInVuaW9uIjpyZXR1cm4gb3QodCxlLHIuZmllbGRzKTtjYXNlImFycmF5IjpyZXR1cm4gTGUodCxlLG8scil9fWZ1bmN0aW9uIFZ0KHQsZSxyLG8sbil7c3dpdGNoKHIudGFnKXtjYXNlImJhc2ljIjpkdCh0LGUse2s6ci5raW5kLHY6bn0pO2JyZWFrO2Nhc2UiYml0ZmllbGQiOk9lKHQsZSxyLG4/PzApO2JyZWFrO2Nhc2Uic3RyaW5nIjpHZSh0LGUsbyxyLmVuY29kaW5nLG4pO2JyZWFrO2Nhc2Uic3RydWN0IjpjYXNlInVuaW9uIjp2dCh0LGUsci5maWVsZHMsbj8/e30pO2JyZWFrO2Nhc2UiYXJyYXkiOmtlKHQsZSxvLHIsbik7YnJlYWt9fWZ1bmN0aW9uIG90KHQsZSxyKXtsZXQgbz17fTtmb3IobGV0IG4gb2Ygcil7bGV0IGk9WXQodCxlK24ub2Zmc2V0LG4udHlwZSxuLnNpemUpO2lmKG4ubm9ubnVsbCYmaT09PTApdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBkZWNvZGU6ICchJyBmaWVsZCAiJHtuLm5hbWV9IiBnb3QgMCAoQyBkaWQgbm90IGZpbGwgaXQsIG9yIGRlY29kZSB3YXMgY2FsbGVkIG9uIGFuIHVuZmlsbGVkIHNsb3QpYCk7b1tuLm5hbWVdPWl9cmV0dXJuIG99ZnVuY3Rpb24gdnQodCxlLHIsbyl7Zm9yKGxldCBuIG9mIHIpb1tuLm5hbWVdIT09dm9pZCAwJiZWdCh0LGUrbi5vZmZzZXQsbi50eXBlLG4uc2l6ZSxvW24ubmFtZV0pfWZ1bmN0aW9uIFVlKHQpe2xldHtmaWVsZHM6ZSxzaXplOnIsbWF4RWZmZWN0aXZlQWxpZ246b309aHQodCk7cmV0dXJue19fc3RydWN0OnQsc2l6ZTpyLHN0cnVjdEFsaWduOm8sZGVjb2RlOm49Pm90KHR5cGVvZiBuPT0ibnVtYmVyIj9uZXcgRGF0YVZpZXcod3QucmVhZEJ5dGVzKG4scikpOm5ldyBEYXRhVmlldyhuKSwwLGUpLGFsbG9jOihuPT57aWYobiE9PXZvaWQgMCYmKCFOdW1iZXIuaXNJbnRlZ2VyKG4pfHxuPDEpKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYWxsb2MobikgcmVxdWlyZXMgYW4gaW50ZWdlciBuID49IDEgKFBBQigwKSBuZXZlciBlc2NhcGVzIFx1MjAxNCBwYXNzIE5VTEwgZm9yIGFuIGVtcHR5IHBvaW50ZXIgcG9zaXRpb24pIik7cmV0dXJuIG5ldyBiKHIqKG4/PzEpKX0pLGVuY29kZTooKG4saSxjKT0+e2lmKG49PW51bGwpdGhyb3cgbmV3IEVycm9yKCJmZmktc3RydWN0OiBlbmNvZGUodikgcmVxdWlyZXMgYW4gYXJndW1lbnQ7IHVzZSBhbGxvYygpIGZvciBhIHplcm9lZCBvdXQtcGFyYW0gc2xvdCIpO2xldCBzPWk/P25ldyBiKHIpO3JldHVybiB2dChuZXcgRGF0YVZpZXcocyksYz8/MCxlLG4pLHN9KSxvZmZzZXRPZjpuPT57Zm9yKGxldCBpIG9mIGUpaWYoaS5uYW1lPT09bilyZXR1cm4gaS5vZmZzZXQ7dGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBubyBmaWVsZCAiJHtufSJgKX19fWZ1bmN0aW9uIF9lKHQsZSxyKXtsZXQgbz17IiMiOnR9O3IhPT12b2lkIDAmJihvWyIjcGFjayJdPXIpO2ZvcihsZXRbbixpXW9mIE9iamVjdC5lbnRyaWVzKGUpKW4uc3RhcnRzV2l0aCgiIyIpfHwob1tuXT1pKTtyZXR1cm4gb31mdW5jdGlvbiBqdCh0KXtsZXR7ZmllbGRzOmUsc2l6ZTpyfT1odCh0Ll9fc3RydWN0KSxvPShuLGkpPT57bGV0IGM9W107Zm9yKGxldCBzPTA7czxpO3MrKyljLnB1c2gob3QobixzKnIsZSkpO3JldHVybiBjfTtyZXR1cm57ZW5jb2RlOm49PntpZighQXJyYXkuaXNBcnJheShuKXx8bi5sZW5ndGg9PT0wKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogc3RydWN0QXJyYXkoZGVmKS5lbmNvZGUoZWxzKSByZXF1aXJlcyBhIG5vbi1lbXB0eSBlbGVtZW50IGFycmF5IChwYXNzIE5VTEwgZm9yIGFuIGVtcHR5IHBvaW50ZXIgcG9zaXRpb24pIik7bGV0IGk9dC5hbGxvYyhuLmxlbmd0aCk7Zm9yKGxldCBjPTA7YzxuLmxlbmd0aDtjKyspdC5lbmNvZGUobltjXSxpLGMqdC5zaXplKTtyZXR1cm4gaX0sZGVjb2RlOigobixpKT0+e2lmKGkhPT12b2lkIDAmJighTnVtYmVyLmlzSW50ZWdlcihpKXx8aTwwKSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IHN0cnVjdEFycmF5LmRlY29kZShwLCBjb3VudCkgcmVxdWlyZXMgYSBub24tbmVnYXRpdmUgaW50ZWdlciBjb3VudCwgZ290ICR7aX1gKTtpZih0eXBlb2Ygbj09Im51bWJlciIpe2lmKGk9PT12b2lkIDApdGhyb3cgbmV3IEVycm9yKCJmZmktc3RydWN0OiBzdHJ1Y3RBcnJheS5kZWNvZGUoYWRkcmVzcywgY291bnQpIHJlcXVpcmVzIGFuIGV4cGxpY2l0IGNvdW50IChhIGJhcmUgYWRkcmVzcyBjYXJyaWVzIG5vIGxlbmd0aCkiKTtyZXR1cm4gaT09PTA/W106byhuZXcgRGF0YVZpZXcod3QucmVhZEJ5dGVzKG4saSpyKSksaSl9bGV0IGM7aWYoaSE9PXZvaWQgMCl7aWYoYz1pLGMqcj5uLmJ5dGVMZW5ndGgpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBzdHJ1Y3RBcnJheS5kZWNvZGU6IGNvdW50ICR7Y30gXHhENyBzaXplICR7cn0gPSAke2Mqcn0gZXhjZWVkcyBidWZmZXIgYnl0ZUxlbmd0aCAke24uYnl0ZUxlbmd0aH1gKX1lbHNle2lmKG4uYnl0ZUxlbmd0aCVyIT09MCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IHN0cnVjdEFycmF5LmRlY29kZTogYnl0ZUxlbmd0aCAke24uYnl0ZUxlbmd0aH0gaXMgbm90IGEgbXVsdGlwbGUgb2Ygc2l6ZSAke3J9IChtaXhlZCBidWZmZXI/IHBhc3MgY291bnQgZXhwbGljaXRseSlgKTtjPW4uYnl0ZUxlbmd0aC9yfXJldHVybiBjPT09MD9bXTpvKG5ldyBEYXRhVmlldyhuKSxjKX0pfX1mdW5jdGlvbiBnKHQsZSxyKXtsZXQgbz10eXBlb2YgdD09InN0cmluZyI7cmV0dXJuIFVlKF9lKCJzdHJ1Y3QiLG8/ZTp0LChvP3I6ZSk/LnBhY2spKX12YXIgUD1nKCJSRUNUIix7bGVmdDoiaTMyIix0b3A6ImkzMiIscmlnaHQ6ImkzMiIsYm90dG9tOiJpMzIifSksaj1nKCJQT0lOVCIse3g6ImkzMiIseToiaTMyIn0pO3ZhciBudD1nKCJTVEFSVFVQSU5GT1ciLHtjYjoidTMyIixscFJlc2VydmVkOiI8PnB0ciIsbHBEZXNrdG9wOiI8PnB0ciIsbHBUaXRsZToiPD5wdHIiLGR3WDoidTMyIixkd1k6InUzMiIsZHdYU2l6ZToidTMyIixkd1lTaXplOiJ1MzIiLGR3WENvdW50Q2hhcnM6InUzMiIsZHdZQ291bnRDaGFyczoidTMyIixkd0ZpbGxBdHRyaWJ1dGU6InUzMiIsZHdGbGFnczoidTMyIix3U2hvd1dpbmRvdzoidTE2QFNob3dXaW5kb3dDbWQiLGNiUmVzZXJ2ZWQyOiJ1MTYiLGxwUmVzZXJ2ZWQyOiI8PnB0ciIsaFN0ZElucHV0OiI8SEZJTEU+cHRyIixoU3RkT3V0cHV0OiI8SEZJTEU+cHRyIixoU3RkRXJyb3I6IjxIRklMRT5wdHIifSksQ3Q9ZygiUFJPQ0VTU19JTkZPUk1BVElPTiIse2hQcm9jZXNzOiI8SFBST0NFU1M+cHRyISIsaFRocmVhZDoiPEhUSFJFQUQ+cHRyISIsZHdQcm9jZXNzSWQ6InUzMiIsZHdUaHJlYWRJZDoidTMyIn0pLEo9ZygiQklUTUFQSU5GT0hFQURFUiIse2JpU2l6ZToidTMyIixiaVdpZHRoOiJpMzIiLGJpSGVpZ2h0OiJpMzIiLGJpUGxhbmVzOiJ1MTYiLGJpQml0Q291bnQ6InUxNiIsYmlDb21wcmVzc2lvbjoidTMyIixiaVNpemVJbWFnZToidTMyIixiaVhQZWxzUGVyTWV0ZXI6ImkzMiIsYmlZUGVsc1Blck1ldGVyOiJpMzIiLGJpQ2xyVXNlZDoidTMyIixiaUNsckltcG9ydGFudDoidTMyIn0pLGl0PWcoIkJJVE1BUEZJTEVIRUFERVIiLHtiZlR5cGU6InUxNiIsYmZTaXplOiJ1MzIiLGJmUmVzZXJ2ZWQxOiJ1MTYiLGJmUmVzZXJ2ZWQyOiJ1MTYiLGJmT2ZmQml0czoidTMyIn0se3BhY2s6Mn0pO3ZhciBaPWcoIk5NSERSIix7aHduZEZyb206IjxIV05EPnB0ciIsaWRGcm9tOiI8PnB0ciIsY29kZToiaTMyIn0pLHplPWcoIlNZU1RFTVRJTUUiLHt3WWVhcjoidTE2Iix3TW9udGg6InUxNiIsd0RheU9mV2VlazoidTE2Iix3RGF5OiJ1MTYiLHdIb3VyOiJ1MTYiLHdNaW51dGU6InUxNiIsd1NlY29uZDoidTE2Iix3TWlsbGlzZWNvbmRzOiJ1MTYifSksbXI9ZygiTk1EQVRFVElNRUNIQU5HRSIse2hkcjpaLl9fc3RydWN0LGR3RmxhZ3M6InUzMiIsc3Q6emUuX19zdHJ1Y3R9KSwkZT1nKCJMSVRFTSIse21hc2s6InUzMiIsaUxpbms6ImkzMiIsc3RhdGU6InUzMiIsc3RhdGVNYXNrOiJ1MzIiLHN6SUQ6InUxNls0OF1AdXRmLTE2bGUiLHN6VXJsOiJ1MTZbMjA4NF1AdXRmLTE2bGUifSksd3I9ZygiTk1MSU5LIix7aGRyOlouX19zdHJ1Y3QsaXRlbTokZS5fX3N0cnVjdH0pLGhyPWcoIk5NQ1VTVE9NRFJBVyIse2hkcjpaLl9fc3RydWN0LGR3RHJhd1N0YWdlOiJ1MzIiLGhkYzoiPEhEQz5wdHIiLHJjOiJpMzJbNF0iLGR3SXRlbVNwZWM6Ijw+cHRyIix1SXRlbVN0YXRlOiJ1MzIiLGxJdGVtbFBhcmFtOiI8PnB0ciJ9KSxDcj1nKCJOTUxWQ1VTVE9NRFJBVyIse2hkcjpaLl9fc3RydWN0LGR3RHJhd1N0YWdlOiJ1MzIiLGhkYzoiPEhEQz5wdHIiLHJjOiJpMzJbNF0iLGR3SXRlbVNwZWM6Ijw+cHRyIix1SXRlbVN0YXRlOiJ1MzIiLGxJdGVtbFBhcmFtOiI8PnB0ciIsY2xyVGV4dDoidTMyIixjbHJUZXh0Qms6InUzMiIsaVN1Ykl0ZW06ImkzMiIsZHdJdGVtVHlwZToidTMyIn0pLFNyPWcoIk5NTElTVFZJRVciLHtoZHI6Wi5fX3N0cnVjdCxpSXRlbToiaTMyIixpU3ViSXRlbToiaTMyIix1TmV3U3RhdGU6InUzMiIsdU9sZFN0YXRlOiJ1MzIiLHVDaGFuZ2VkOiJ1MzIiLHB0QWN0aW9uOiJpMzJbMl0iLGxQYXJhbToiPD5wdHIifSk7dmFyIFllPWcoIlRWSVRFTSIse21hc2s6InUzMiIsaEl0ZW06Ijw+cHRyIixzdGF0ZToidTMyIixzdGF0ZU1hc2s6InUzMiIscHN6VGV4dDoiPD5wdHIiLGNjaFRleHRNYXg6ImkzMiIsaUltYWdlOiJpMzIiLGlTZWxlY3RlZEltYWdlOiJpMzIiLGNDaGlsZHJlbjoiaTMyIixsUGFyYW06Ijw+cHRyIn0pLGdyPWcoIlRWSU5TRVJUU1RSVUNUIix7aFBhcmVudDoiPD5wdHIiLGhJbnNlcnRBZnRlcjoiPD5wdHIiLGl0ZW06WWUuX19zdHJ1Y3R9KTt2YXIgVmU9ZygiTVNHIix7aHduZDoiPEhXTkQ+cHRyIixtZXNzYWdlOiJ1MzIiLHdQYXJhbToiPD5wdHIiLGxQYXJhbToiPD5wdHIiLHRpbWU6InUzMiIscHQ6ai5fX3N0cnVjdH0pLERyPWcoIlBBSU5UU1RSVUNUIix7aGRjOiI8SERDPnB0ciIsZkVyYXNlOiJpMzIiLHJjUGFpbnQ6UC5fX3N0cnVjdCxmUmVzdG9yZToiaTMyIixmSW5jVXBkYXRlOiJpMzIiLHJnYlJlc2VydmVkOiJ1OFszMl0ifSk7dmFyIHN0PWcoIk9TVkVSU0lPTklORk9fMTQ4Iix7ZHdPU1ZlcnNpb25JbmZvU2l6ZToidTMyIixkd01ham9yVmVyc2lvbjoidTMyIixkd01pbm9yVmVyc2lvbjoidTMyIixkd0J1aWxkTnVtYmVyOiJ1MzIiLGR3UGxhdGZvcm1JZDoidTMyIixzekNTRFZlcnNpb246InU4WzEyOF0ifSk7dmFyIE89KHQsZSxyKT0+Rygia2VybmVsMzIuZGxsIix0LGUsciksSnQ9TygiQ3JlYXRlUGlwZSIsIjw+cHRyIDw+cHRyIDw+cHRyIHUzMiAtPiBpMzIiKSxTdD1PKCJTZXRIYW5kbGVJbmZvcm1hdGlvbiIsIjxIRklMRT5wdHIhIHUzMiB1MzIgLT4gaTMyIiksS3Q9TygiQ3JlYXRlUHJvY2Vzc1ciLCI8V0NIQVI+cHRyIDxXQ0hBUj5wdHIgPD5wdHIgPD5wdHIgaTMyIHUzMiA8PnB0ciA8V0NIQVI+cHRyIDxTVEFSVFVQSU5GT1c+cHRyIDxQUk9DRVNTX0lORk9STUFUSU9OPnB0ciAtPiBpMzIiLHtTVEFSVFVQSU5GT1c6bnR9KSxYdD1PKCJXYWl0Rm9yU2luZ2xlT2JqZWN0IiwiPD5wdHIgdTMyIC0+IHUzMiIpLFp0PU8oIkdldEV4aXRDb2RlUHJvY2VzcyIsIjxIUFJPQ0VTUz5wdHIhIDxCWVRFPnB0ciAtPiBpMzIiKSxVPU8oIkNsb3NlSGFuZGxlIiwiPD5wdHIgLT4gaTMyIik7dmFyIHF0PU8oIlJlYWRGaWxlIiwiPEhGSUxFPnB0ciEgPEJZVEU+cHRyIHUzMiA8QllURT5wdHIgPD5wdHIgLT4gaTMyIik7dmFyIGd0PU8oIkdldExhc3RFcnJvciIsIiAtPiB1MzIiKSxRdD1PKCJHZXRTeXN0ZW1EaXJlY3RvcnlXIiwiPEJZVEU+cHRyIHUzMiAtPiB1MzIiKTtpbXBvcnQqYXMgdGUgZnJvbSJvcyI7dmFyIE49KHQsZSxyKT0+RygidXNlcjMyLmRsbCIsdCxlLHIpLEhyPU4oIkdldERlc2t0b3BXaW5kb3ciLCIgLT4gPEhXTkQ+cHRyIiksZWU9dGUuYXJjaD09PSJ4NjQiPyJQdHJXIjoiVyI7dmFyIER0PU4oIkdldFdpbmRvd1JlY3QiLCI8SFdORD5wdHIgPFJFQ1Q+cHRyIC0+IGkzMiIpLHJlPU4oIkdldENsaWVudFJlY3QiLCI8SFdORD5wdHIgPFJFQ1Q+cHRyIC0+IGkzMiIpO3ZhciBvZT1OKCJJc1dpbmRvd1Zpc2libGUiLCI8SFdORD5wdHIgLT4gaTMyIiksRXQ9TigiSXNJY29uaWMiLCI8SFdORD5wdHIgLT4gaTMyIik7dmFyIG5lPU4oIkdldFdpbmRvd1RleHRXIiwiPEhXTkQ+cHRyIDxCWVRFPnB0ciBpMzIgLT4gaTMyIik7dmFyIGllPU4oIkdldENsYXNzTmFtZVciLCI8SFdORD5wdHIgPEJZVEU+cHRyIGkzMiAtPiBpMzIiKSxQcj1OKCJHZXRXaW5kb3dMb25nIitlZSwiPEhXTkQ+cHRyIGkzMkBHd2xwIC0+IDw+cHRyIiksTXI9TigiU2V0V2luZG93TG9uZyIrZWUsIjxIV05EPnB0ciBpMzJAR3dscCA8PnB0ciAtPiA8PnB0ciIpO3ZhciBzZT1OKCJHZXREQyIsIjxIV05EPnB0ciAtPiA8SERDPnB0ciIpLFd0PU4oIlJlbGVhc2VEQyIsIjxIV05EPnB0ciA8SERDPnB0ciEgLT4gaTMyIiksY2U9TigiUHJpbnRXaW5kb3ciLCI8SFdORD5wdHIgPEhEQz5wdHIhIHUzMiAtPiBpMzIiKTt2YXIgcGU9TigiQ2xpZW50VG9TY3JlZW4iLCI8SFdORD5wdHIgPFBPSU5UPnB0ciAtPiBpMzIiKTt2YXIgXz1OKCJHZXRTeXN0ZW1NZXRyaWNzIiwiaTMyIC0+IGkzMiIpO3ZhciBhZT1OKCJFbnVtV2luZG93cyIsIjw+cHRyIDw+cHRyIC0+IGkzMiIpO3ZhciB6PSh0LGUscik9PkcoImdkaTMyLmRsbCIsdCxlLHIpLExyPWp0KGopO3ZhciBUdD16KCJEZWxldGVPYmplY3QiLCI8SEdESU9CSj5wdHIgLT4gaTMyIik7dmFyIGJ0PXooIkNyZWF0ZUNvbXBhdGlibGVEQyIsIjxIREM+cHRyIC0+IDxIREM+cHRyIiksTnQ9eigiQ3JlYXRlQ29tcGF0aWJsZUJpdG1hcCIsIjxIREM+cHRyISBpMzIgaTMyIC0+IDxIR0RJT0JKPnB0ciIpO3ZhciBxPXooIlNlbGVjdE9iamVjdCIsIjxIREM+cHRyISA8SEdESU9CSj5wdHIgLT4gPEhHRElPQko+cHRyIiksSXQ9eigiQml0Qmx0IiwiPEhEQz5wdHIhIGkzMiBpMzIgaTMyIGkzMiA8SERDPnB0ciBpMzIgaTMyIHUzMkBSYXN0ZXJPcCAtPiBpMzIiKSx1ZT16KCJHZXRESUJpdHMiLCI8SERDPnB0ciEgPEhHRElPQko+cHRyIHUzMiB1MzIgPEJZVEU+cHRyIDw+cHRyIHUzMiAtPiBpMzIiKTt2YXIgUT16KCJEZWxldGVEQyIsIjxIREM+cHRyISAtPiBpMzIiKTt2YXIgdmU9KHQsZSk9PkcoIm50ZGxsLmRsbCIsdCxlKSxsZT12ZSgiUnRsR2V0VmVyc2lvbiIsIjxPU1ZFUlNJT05JTkZPXzE0OD5wdHIgLT4gaTMyIik7dmFyIG1lPXQ9Pnt0cnl7bGV0IGU9eGUub3BlbigiZGlhZy5sb2ciLCJhIik7ZSYmKGUucHV0cyhgJHtEYXRlLm5vdygpfSAke3R9CmApLGUuY2xvc2UoKSl9Y2F0Y2h7fX0seXQ9MSxqZT0yNTYsSmU9NDI5NDk2NzI5NSxGPWZlLldvcmtlci5wYXJlbnQsd2U9IkM6XFxXaW5kb3dzXFxTeXN0ZW0zMiI7dHJ5e2xldCB0PUIuYWxsb2MoMjU2KSxyPVF0KHQsMjU2KT4wP0IuZGVjb2RlKHQpOiIiO3ImJih3ZT1yKX1jYXRjaCh0KXttZSgiU1lTLURJUi1GQUlMOiAiK1N0cmluZyh0KSl9dmFyIGhlPSExO3RyeXtsZXQgdD1zdC5lbmNvZGUoe2R3T1NWZXJzaW9uSW5mb1NpemU6c3Quc2l6ZX0pO2xlKHQucHRyKT09PTAmJihoZT1zdC5kZWNvZGUodCkuZHdNYWpvclZlcnNpb24+PTEwKX1jYXRjaCh0KXttZSgiVkVSLUZBSUw6ICIrU3RyaW5nKHQpKX12YXIgRnQ9ZygiUElQRV9IQU5ETEVTIix7aFJlYWQ6IjxIRklMRT5wdHIhIixoV3JpdGU6IjxIRklMRT5wdHIhIn0pO2Z1bmN0aW9uIEtlKHQsZSl7bGV0IHI9RnQuYWxsb2MoKTtpZighSnQoci5wdHIsci5wdHIrRnQub2Zmc2V0T2YoImhXcml0ZSIpLEksMCkpdGhyb3cgbmV3IEVycm9yKCJDcmVhdGVQaXBlIGVycj0iK2d0KCkpO2xldHtoUmVhZDpvLGhXcml0ZTpufT1GdC5kZWNvZGUocik7U3Qobix5dCx5dCksU3Qobyx5dCwwKTtsZXQgaT1DdC5hbGxvYygpLHM9YCR7d2V9XFxjbWQuZXhlICR7aGU/Ii91ICI6IiJ9L2MgJHtlfWA7aWYoIUt0KEkscyxJLEksMSwwLEksSSx7Y2I6bnQuc2l6ZSxkd0ZsYWdzOmplLGhTdGRPdXRwdXQ6bixoU3RkRXJyb3I6bn0saS5wdHIpKXRocm93IFUobyksVShuKSxuZXcgRXJyb3IoIkNyZWF0ZVByb2Nlc3NXIGVycj0iK2d0KCkrIiBjbWQ9IitzKTtsZXR7aFByb2Nlc3M6cCxoVGhyZWFkOmEsZHdQcm9jZXNzSWQ6dX09Q3QuZGVjb2RlKGkpO1UoYSksVShuKSxGLnBvc3RNZXNzYWdlKHt0eXBlOiJpbmZvIixpZDp0LHBpZDp1fSk7bGV0IHg9bmV3IGIoNDA5NiksZD1uZXcgVWludDhBcnJheSh4KSx3PW5ldyBiKDQpLGY9bmV3IFVpbnQzMkFycmF5KHcpO2Zvcig7ZlswXT0wLCEhcXQobyx4LDQwOTYsdyxJKTspe2xldCBsPWZbMF07aWYobD09PTApYnJlYWs7Ri5wb3N0TWVzc2FnZSh7dHlwZToiZGF0YSIsaWQ6dCxjaHVuazpkLnNsaWNlKDAsbCl9KX1YdChwLEplKTtsZXQgUz1uZXcgYig0KSxtPW5ldyBJbnQzMkFycmF5KFMpO1p0KHAsUyk7bGV0IFc9bVswXTtyZXR1cm4gVShvKSxVKHApLFd9dmFyIENlPTEzMzY5Mzc2LFhlPTAsZGU9NjU1MzYsWmU9NGU3LGN0PTUxMixxZT0yZTQsSHQ9aXQuc2l6ZStKLnNpemU7ZnVuY3Rpb24gUWUodCxlLHIpe2xldCBvPWl0LmVuY29kZSh7YmZUeXBlOjE5Nzc4LGJmU2l6ZTpIdCt0LGJmT2ZmQml0czpIdH0pLG49Si5lbmNvZGUoe2JpU2l6ZTpKLnNpemUsYmlXaWR0aDplLGJpSGVpZ2h0Oi1yLGJpUGxhbmVzOjEsYmlCaXRDb3VudDozMixiaUNvbXByZXNzaW9uOjAsYmlTaXplSW1hZ2U6dCxiaVhQZWxzUGVyTWV0ZXI6MjgzNSxiaVlQZWxzUGVyTWV0ZXI6MjgzNX0pLGk9bmV3IFVpbnQ4QXJyYXkoSHQpO3JldHVybiBpLnNldChuZXcgVWludDhBcnJheShvKSwwKSxpLnNldChuZXcgVWludDhBcnJheShuKSxpdC5zaXplKSxpfWZ1bmN0aW9uIHRyKHQsZSxyLG8sbil7bGV0IGk9bmV3IGIobypuKjQpLGM9bmV3IFVpbnQ4QXJyYXkoaSkscz1KLmVuY29kZSh7YmlTaXplOkouc2l6ZSxiaVdpZHRoOm8sYmlIZWlnaHQ6LW4sYmlQbGFuZXM6MSxiaUJpdENvdW50OjMyLGJpU2l6ZUltYWdlOm8qbio0fSk7aWYodWUoZSxyLDAsbixpLHMucHRyLFhlKSE9PW4pcmV0dXJuITE7bGV0IGE9Yy5ieXRlTGVuZ3RoO0YucG9zdE1lc3NhZ2Uoe3R5cGU6ImRhdGEiLGlkOnQsY2h1bms6UWUoYSxvLG4pfSk7Zm9yKGxldCB1PTA7dTxhO3UrPWRlKUYucG9zdE1lc3NhZ2Uoe3R5cGU6ImRhdGEiLGlkOnQsY2h1bms6Yy5zbGljZSh1LE1hdGgubWluKHUrZGUsYSkpfSk7cmV0dXJuITB9ZnVuY3Rpb24gZXIodCxlLHIsbyxuLGksYyxzLHApe2xldCBhPWJ0KHQpLHU9YT9OdCh0LHIsbyk6MDtpZighYXx8IXUpcmV0dXJuIGEmJlEoYSksITE7bGV0IHg9cShhLHUpLHc9Y2UoZSxhLDApIT09MCYmSXQobiwwLDAscyxwLGEsaSxjLENlKSE9PTA7cmV0dXJuIHEoYSx4KSxUdCh1KSxRKGEpLHd9ZnVuY3Rpb24gU2UodCxlLHIsbyxuLGksYyxzLHAsYSl7aWYoIShzPjAmJnA+MCYmcypwPD1aZSkpdGhyb3cgbmV3IEVycm9yKCJjYXB0dXJlIHNpemUgaW52YWxpZCB3PSIrcysiIGg9IitwKTtpZihhIT09bnVsbCYmIShpPj0wJiZjPj0wJiZpK3M8PWUmJmMrcDw9cikpdGhyb3cgbmV3IEVycm9yKCJjYXB0dXJlIGNyb3Agb3V0IG9mIHJhbmdlIGNyb3A9KCIraSsiLCIrYysiLCIrcysieCIrcCsiKSBmcmFtZT0iK2UrIngiK3IpO2xldCB1PXNlKEkpO2lmKCF1KXRocm93IG5ldyBFcnJvcigiR2V0REMoTlVMTCk9MFx1RkYxQVx1NjVFMFx1OEY5M1x1NTE2NVx1Njg0Q1x1OTc2Mlx1RkYwOFx1Nzg2RVx1OEJBNFx1NTcyOFx1NEVBNFx1NEU5MiBzZXNzaW9uIFx1NTQyRlx1NTJBOFx1RkYwQ1x1ODAwQ1x1OTc1RSBzc2hkL3NlcnZpY2VcdUZGMDkiKTtsZXQgeD1idCh1KSxkPXg/TnQodSxzLHApOjA7aWYoIXh8fCFkKXRocm93IHgmJlEoeCksV3QoSSx1KSxuZXcgRXJyb3IoIkNyZWF0ZUNvbXBhdGlibGVEQy9CaXRtYXAgZmFpbGVkIik7bGV0IHc9cSh4LGQpLGY9YT09PW51bGw/SXQoeCwwLDAscyxwLHUsbyxuLENlKSE9PTA6ZXIodSxhLGUscix4LGksYyxzLHApO3EoeCx3KTtsZXQgUz1mJiZ0cih0LHgsZCxzLHApO2lmKFR0KGQpLFEoeCksV3QoSSx1KSwhZil0aHJvdyBuZXcgRXJyb3IoImNhcHR1cmUgZmFpbGVkIG91dD0iK3MrIngiK3ArKGE9PT1udWxsPyIgYXQ9KCIrbysiLCIrbisiKSI6IiBod25kPSIrYSsiIGNyb3A9KCIraSsiLCIrYysiKSBmcmFtZT0iK2UrIngiK3IpKTtpZighUyl0aHJvdyBuZXcgRXJyb3IoIkdldERJQml0cyBzaG9ydCByZWFkIG91dD0iK3MrIngiK3ApO3JldHVybnt3aWR0aDpzLGhlaWdodDpwfX1mdW5jdGlvbiBycih0KXtsZXQgZT1fKDApLHI9XygxKTtpZihlPD0wfHxyPD0wKXRocm93IG5ldyBFcnJvcigiR2V0U3lzdGVtTWV0cmljcyB3PSIrZSsiIGg9IityKTtyZXR1cm4gU2UodCxlLHIsMCwwLDAsMCxlLHIsbnVsbCl9ZnVuY3Rpb24gb3IodCxlLHIsbyl7aWYobz09PSJzY3JlZW4iJiZFdChlKSE9PTApdGhyb3cgbmV3IEVycm9yKCJ3aW5kb3cgbWluaW1pemVkXHVGRjFBbW9kZT1zY3JlZW4gXHU1M0VBXHU0RjFBXHU2MjJBXHU1MjMwXHU1QjgzXHU0RTBCXHU2NUI5XHU3Njg0XHU2ODRDXHU5NzYyXHVGRjBDXHU2NTM5XHU3NTI4IG1vZGU9cHJpbnQiKTtsZXQgbj1QLmFsbG9jKCk7aWYoIUR0KGUsbi5wdHIpKXRocm93IG5ldyBFcnJvcigiR2V0V2luZG93UmVjdChod25kPSIrZSsiKT0wXHVGRjFBXHU3QTk3XHU1M0UzXHU0RTBEXHU1QjU4XHU1NzI4XHU2MjE2XHU1REYyXHU5NTAwXHU2QkMxIik7bGV0e2xlZnQ6aSx0b3A6YyxyaWdodDpzLGJvdHRvbTpwfT1QLmRlY29kZShuKSxhPXMtaSx1PXAtYyx4PTAsZD0wLHc9YSxmPXU7aWYocj09PSJjbGllbnQiKXtsZXQgVz1QLmFsbG9jKCk7aWYoIXJlKGUsVy5wdHIpKXRocm93IG5ldyBFcnJvcigiR2V0Q2xpZW50UmVjdChod25kPSIrZSsiKT0wIik7bGV0e2xlZnQ6bCx0b3A6RCxyaWdodDpFLGJvdHRvbTpDfT1QLmRlY29kZShXKTt3PUUtbCxmPUMtRDtsZXQgaD1qLmVuY29kZSh7eDowLHk6MH0pO2lmKCFwZShlLGgucHRyKSl0aHJvdyBuZXcgRXJyb3IoIkNsaWVudFRvU2NyZWVuKGh3bmQ9IitlKyIpPTAiKTtsZXQgVD1qLmRlY29kZShoKTt4PVQueC1pLGQ9VC55LWN9bGV0IFM9bz09PSJwcmludCI/MDppK3gsbT1vPT09InByaW50Ij8wOmMrZDtpZihvPT09InNjcmVlbiIpe2xldCBXPV8oNzYpLGw9Xyg3NyksRD1fKDc4KSxFPV8oNzkpLEM9TWF0aC5tYXgoUyxXKSxoPU1hdGgubWF4KG0sbCksVD1NYXRoLm1pbihTK3csVytEKSxIPU1hdGgubWluKG0rZixsK0UpO2lmKFQ8PUN8fEg8PWgpdGhyb3cgbmV3IEVycm9yKCJjYXB0dXJlIGFyZWEgb3V0c2lkZSB2aXJ0dWFsIHNjcmVlbiBhdD0oIitTKyIsIittKyIsIit3KyJ4IitmKyIpIik7Uz1DLG09aCx3PVQtQyxmPUgtaH1yZXR1cm4gU2UodCxhLHUsUyxtLHgsZCx3LGYsbz09PSJwcmludCI/ZTpudWxsKX1mdW5jdGlvbiBucih0KXtsZXQgZT1bXSxyPV90KCI8SFdORD5wdHIgPD5wdHIgLT4gaTMyIixzPT4ocyYmZS5wdXNoKHMpLGUubGVuZ3RoPHFlPzE6MCkpO3RyeXthZShyLnB0cixJKX1maW5hbGx5e3IuZGlzcG9zZSgpfWxldCBvPVAuYWxsb2MoKSxuPUIuYWxsb2MoY3QpLGk9Qi5hbGxvYyhjdCksYz1bXTtmb3IobGV0IHMgb2YgZSlpZihEdChzLG8ucHRyKSl7bGV0IHA9UC5kZWNvZGUobyksYT1uZShzLG4sY3QpLHU9aWUocyxpLGN0KTtjLnB1c2goe2h3bmQ6cyx0aXRsZTphPjA/Qi5kZWNvZGUobik6IiIsY2xhc3NOYW1lOnU+MD9CLmRlY29kZShpKToiIixyZWN0OntsZWZ0OnAubGVmdCx0b3A6cC50b3AscmlnaHQ6cC5yaWdodCxib3R0b206cC5ib3R0b219LHZpc2libGU6b2UocykhPT0wLG1pbmltaXplZDpFdChzKSE9PTB9KX1GLnBvc3RNZXNzYWdlKHt0eXBlOiJyZXN1bHQiLGlkOnQsY29kZTowLGVycm9yOm51bGwsd2luZG93czpjfSl9ZnVuY3Rpb24gaXIodCl7aWYodC50eXBlPT09InJ1biIpe2lmKHR5cGVvZiB0LmNtZCE9InN0cmluZyIpcmV0dXJuO2xldCBlPS0xLHI9bnVsbDt0cnl7ZT1LZSh0LmlkLHQuY21kKX1jYXRjaChvKXtyPVN0cmluZyhvKX1GLnBvc3RNZXNzYWdlKHt0eXBlOiJyZXN1bHQiLGlkOnQuaWQsY29kZTplLGVycm9yOnJ9KTtyZXR1cm59aWYodC50eXBlPT09IndpbmRvd3MiKXt0cnl7bnIodC5pZCl9Y2F0Y2goZSl7Ri5wb3N0TWVzc2FnZSh7dHlwZToicmVzdWx0IixpZDp0LmlkLGNvZGU6LTEsZXJyb3I6U3RyaW5nKGUpfSl9cmV0dXJufWlmKHQudHlwZT09PSJzY3JlZW5zaG90Iil0cnl7bGV0IGU9dC5od25kPz9udWxsLHt3aWR0aDpyLGhlaWdodDpvfT1lPT09bnVsbD9ycih0LmlkKTpvcih0LmlkLGUsdC5hcmVhPz8id2luZG93Iix0Lm1vZGU/PyJzY3JlZW4iKTtGLnBvc3RNZXNzYWdlKHt0eXBlOiJyZXN1bHQiLGlkOnQuaWQsY29kZTowLGVycm9yOm51bGwsd2lkdGg6cixoZWlnaHQ6b30pfWNhdGNoKGUpe0YucG9zdE1lc3NhZ2Uoe3R5cGU6InJlc3VsdCIsaWQ6dC5pZCxjb2RlOi0xLGVycm9yOlN0cmluZyhlKX0pfX1GLm9ubWVzc2FnZT10PT57aXIodC5kYXRhKSxGLm9ubWVzc2FnZT1udWxsfTsK");
|
|
22039
|
-
bumpWorkers(1);
|
|
22040
|
-
const id = 1;
|
|
22041
|
-
let settled = false;
|
|
22042
|
-
let timer = null;
|
|
22043
|
-
const settle = (r2) => {
|
|
22044
|
-
if (settled)
|
|
22045
|
-
return;
|
|
22046
|
-
settled = true;
|
|
22047
|
-
if (timer !== null)
|
|
22048
|
-
os6.clearTimeout(timer);
|
|
22049
|
-
worker.onmessage = null;
|
|
22050
|
-
bumpWorkers(-1);
|
|
22051
|
-
resolve(r2);
|
|
22052
|
-
};
|
|
22053
|
-
timer = os6.setTimeout(() => settle(onTimeout()), timeoutMs);
|
|
22054
|
-
worker.onmessage = (e2) => {
|
|
22055
|
-
const msg = e2.data;
|
|
22056
|
-
if (msg.id !== void 0 && msg.id !== id)
|
|
22057
|
-
return;
|
|
22058
|
-
if (msg.type === "data") {
|
|
22059
|
-
onData(msg.chunk);
|
|
22060
|
-
return;
|
|
22061
|
-
}
|
|
22062
|
-
if (msg.type !== "result")
|
|
22063
|
-
return;
|
|
22064
|
-
settle(onResult(msg));
|
|
22065
|
-
};
|
|
22066
|
-
try {
|
|
22067
|
-
worker.postMessage(post);
|
|
22068
|
-
} catch (ex) {
|
|
22069
|
-
settle(onResult({ type: "error", error: "spawn: " + String(ex) }));
|
|
22070
|
-
}
|
|
22071
|
-
});
|
|
22072
|
-
}
|
|
22073
22411
|
function jsonError(status, msg) {
|
|
22074
22412
|
return new Response(JSON.stringify({ error: msg }), {
|
|
22075
22413
|
status,
|
|
@@ -22078,81 +22416,586 @@ function jsonError(status, msg) {
|
|
|
22078
22416
|
}
|
|
22079
22417
|
function parseShotOpts(params) {
|
|
22080
22418
|
const area = params.get("area") ?? "window";
|
|
22081
|
-
const mode = params.get("mode") ?? "screen";
|
|
22082
22419
|
if (area !== "window" && area !== "client")
|
|
22083
22420
|
throw new Error('area must be "window" or "client"');
|
|
22084
|
-
|
|
22421
|
+
const rawMode = params.get("mode");
|
|
22422
|
+
if (rawMode !== null && rawMode !== "screen" && rawMode !== "print") {
|
|
22085
22423
|
throw new Error('mode must be "screen" or "print"');
|
|
22424
|
+
}
|
|
22086
22425
|
const raw = params.get("hwnd");
|
|
22087
|
-
|
|
22088
|
-
|
|
22089
|
-
const hwnd = Number(raw);
|
|
22090
|
-
if (!Number.isInteger(hwnd) || hwnd <= 0)
|
|
22426
|
+
const hwnd = raw === null || raw === "" ? null : Number(raw);
|
|
22427
|
+
if (hwnd !== null && (!Number.isInteger(hwnd) || hwnd <= 0)) {
|
|
22091
22428
|
throw new Error("hwnd must be a positive integer");
|
|
22429
|
+
}
|
|
22430
|
+
const mode = rawMode ?? (hwnd === null ? "screen" : "print");
|
|
22092
22431
|
return { hwnd, area, mode };
|
|
22093
22432
|
}
|
|
22094
|
-
|
|
22095
|
-
|
|
22096
|
-
|
|
22433
|
+
var SRCCOPY = 13369376;
|
|
22434
|
+
var DIB_RGB_COLORS = 0;
|
|
22435
|
+
var MAX_CAPTURE_PX = 4e7;
|
|
22436
|
+
var WIDE_BUF_CHARS = 512;
|
|
22437
|
+
var MAX_WINDOWS = 2e4;
|
|
22438
|
+
var BMP_HEADERS_SIZE = BITMAPFILEHEADER.size + BITMAPINFOHEADER.size;
|
|
22439
|
+
function bmpHeader(size, w2, h2) {
|
|
22440
|
+
const fileHdr = BITMAPFILEHEADER.encode({
|
|
22441
|
+
bfType: 19778,
|
|
22442
|
+
// 'BM'
|
|
22443
|
+
bfSize: BMP_HEADERS_SIZE + size,
|
|
22444
|
+
// 文件总长 = 头 + 像素
|
|
22445
|
+
bfOffBits: BMP_HEADERS_SIZE
|
|
22446
|
+
// 像素数据偏移
|
|
22447
|
+
});
|
|
22448
|
+
const infoHdr = BITMAPINFOHEADER.encode({
|
|
22449
|
+
biSize: BITMAPINFOHEADER.size,
|
|
22450
|
+
biWidth: w2,
|
|
22451
|
+
biHeight: -h2,
|
|
22452
|
+
// 负 = 顶向下
|
|
22453
|
+
biPlanes: 1,
|
|
22454
|
+
biBitCount: 32,
|
|
22455
|
+
biCompression: 0,
|
|
22456
|
+
// BI_RGB
|
|
22457
|
+
biSizeImage: size,
|
|
22458
|
+
biXPelsPerMeter: 2835,
|
|
22459
|
+
// 72dpi
|
|
22460
|
+
biYPelsPerMeter: 2835
|
|
22461
|
+
});
|
|
22462
|
+
const out = new Uint8Array(BMP_HEADERS_SIZE);
|
|
22463
|
+
out.set(new Uint8Array(fileHdr), 0);
|
|
22464
|
+
out.set(new Uint8Array(infoHdr), BITMAPFILEHEADER.size);
|
|
22465
|
+
return out;
|
|
22097
22466
|
}
|
|
22098
|
-
function
|
|
22099
|
-
const
|
|
22100
|
-
|
|
22101
|
-
const
|
|
22102
|
-
|
|
22103
|
-
|
|
22104
|
-
|
|
22105
|
-
|
|
22106
|
-
|
|
22107
|
-
|
|
22108
|
-
|
|
22109
|
-
|
|
22110
|
-
}
|
|
22111
|
-
|
|
22112
|
-
|
|
22113
|
-
|
|
22114
|
-
|
|
22115
|
-
|
|
22116
|
-
|
|
22117
|
-
|
|
22118
|
-
|
|
22119
|
-
|
|
22467
|
+
function emitDib(hdc, hbm, w2, h2) {
|
|
22468
|
+
const pxB = new PtrArrayBuffer(w2 * h2 * 4);
|
|
22469
|
+
const px = new Uint8Array(pxB);
|
|
22470
|
+
const bmi = BITMAPINFOHEADER.encode({
|
|
22471
|
+
biSize: BITMAPINFOHEADER.size,
|
|
22472
|
+
biWidth: w2,
|
|
22473
|
+
biHeight: -h2,
|
|
22474
|
+
// 负 = 顶向下
|
|
22475
|
+
biPlanes: 1,
|
|
22476
|
+
biBitCount: 32,
|
|
22477
|
+
// biCompression 缺省 0 = BI_RGB
|
|
22478
|
+
biSizeImage: w2 * h2 * 4
|
|
22479
|
+
});
|
|
22480
|
+
const got = GetDIBits(hdc, hbm, 0, h2, pxB, bmi.ptr, DIB_RGB_COLORS);
|
|
22481
|
+
if (got !== h2)
|
|
22482
|
+
return null;
|
|
22483
|
+
const out = new Uint8Array(BMP_HEADERS_SIZE + px.byteLength);
|
|
22484
|
+
out.set(bmpHeader(px.byteLength, w2, h2), 0);
|
|
22485
|
+
out.set(px, BMP_HEADERS_SIZE);
|
|
22486
|
+
return out;
|
|
22487
|
+
}
|
|
22488
|
+
function printAndCrop(hdcScreen, hwnd, frameW, frameH, hdcOut, cropX, cropY, outW, outH) {
|
|
22489
|
+
const hdcTmp = CreateCompatibleDC(hdcScreen);
|
|
22490
|
+
const hbmTmp = hdcTmp ? CreateCompatibleBitmap(hdcScreen, frameW, frameH) : 0;
|
|
22491
|
+
if (!hdcTmp || !hbmTmp) {
|
|
22492
|
+
if (hdcTmp)
|
|
22493
|
+
DeleteDC(hdcTmp);
|
|
22494
|
+
return false;
|
|
22495
|
+
}
|
|
22496
|
+
const oldTmp = SelectObject(hdcTmp, hbmTmp);
|
|
22497
|
+
const printed = PrintWindow(hwnd, hdcTmp, 0) !== 0;
|
|
22498
|
+
const cropped = printed && BitBlt(hdcOut, 0, 0, outW, outH, hdcTmp, cropX, cropY, SRCCOPY) !== 0;
|
|
22499
|
+
SelectObject(hdcTmp, oldTmp);
|
|
22500
|
+
DeleteObject(hbmTmp);
|
|
22501
|
+
DeleteDC(hdcTmp);
|
|
22502
|
+
return cropped;
|
|
22503
|
+
}
|
|
22504
|
+
function captureRect(frameW, frameH, srcX, srcY, cropX, cropY, outW, outH, hwnd) {
|
|
22505
|
+
if (!(outW > 0 && outH > 0 && outW * outH <= MAX_CAPTURE_PX)) {
|
|
22506
|
+
throw new Error("capture size invalid w=" + outW + " h=" + outH);
|
|
22507
|
+
}
|
|
22508
|
+
if (hwnd !== null && !(cropX >= 0 && cropY >= 0 && cropX + outW <= frameW && cropY + outH <= frameH)) {
|
|
22509
|
+
throw new Error("capture crop out of range crop=(" + cropX + "," + cropY + "," + outW + "x" + outH + ") frame=" + frameW + "x" + frameH);
|
|
22510
|
+
}
|
|
22511
|
+
const hdcScreen = GetDC(NULL);
|
|
22512
|
+
if (!hdcScreen) {
|
|
22513
|
+
throw new Error("GetDC(NULL)=0\uFF1A\u65E0\u8F93\u5165\u684C\u9762\uFF08\u786E\u8BA4\u5728\u4EA4\u4E92 session \u542F\u52A8\uFF0C\u800C\u975E sshd/service\uFF09");
|
|
22514
|
+
}
|
|
22515
|
+
const hdcOut = CreateCompatibleDC(hdcScreen);
|
|
22516
|
+
const hbmOut = hdcOut ? CreateCompatibleBitmap(hdcScreen, outW, outH) : 0;
|
|
22517
|
+
if (!hdcOut || !hbmOut) {
|
|
22518
|
+
if (hdcOut)
|
|
22519
|
+
DeleteDC(hdcOut);
|
|
22520
|
+
ReleaseDC(NULL, hdcScreen);
|
|
22521
|
+
throw new Error("CreateCompatibleDC/Bitmap failed");
|
|
22522
|
+
}
|
|
22523
|
+
const oldOut = SelectObject(hdcOut, hbmOut);
|
|
22524
|
+
const ok = hwnd === null ? BitBlt(hdcOut, 0, 0, outW, outH, hdcScreen, srcX, srcY, SRCCOPY) !== 0 : printAndCrop(hdcScreen, hwnd, frameW, frameH, hdcOut, cropX, cropY, outW, outH);
|
|
22525
|
+
SelectObject(hdcOut, oldOut);
|
|
22526
|
+
const bmp = ok ? emitDib(hdcOut, hbmOut, outW, outH) : null;
|
|
22527
|
+
DeleteObject(hbmOut);
|
|
22528
|
+
DeleteDC(hdcOut);
|
|
22529
|
+
ReleaseDC(NULL, hdcScreen);
|
|
22530
|
+
if (!ok) {
|
|
22531
|
+
throw new Error("capture failed out=" + outW + "x" + outH + (hwnd === null ? " at=(" + srcX + "," + srcY + ")" : " hwnd=" + hwnd + " crop=(" + cropX + "," + cropY + ") frame=" + frameW + "x" + frameH));
|
|
22532
|
+
}
|
|
22533
|
+
if (!bmp)
|
|
22534
|
+
throw new Error("GetDIBits short read out=" + outW + "x" + outH);
|
|
22535
|
+
return { bmp, width: outW, height: outH };
|
|
22536
|
+
}
|
|
22537
|
+
function captureScreen() {
|
|
22538
|
+
const w2 = GetSystemMetrics(0);
|
|
22539
|
+
const h2 = GetSystemMetrics(1);
|
|
22540
|
+
if (w2 <= 0 || h2 <= 0)
|
|
22541
|
+
throw new Error("GetSystemMetrics w=" + w2 + " h=" + h2);
|
|
22542
|
+
return captureRect(w2, h2, 0, 0, 0, 0, w2, h2, null);
|
|
22543
|
+
}
|
|
22544
|
+
function captureWindow(hwnd, area, mode) {
|
|
22545
|
+
if (mode === "screen" && IsIconic(hwnd) !== 0) {
|
|
22546
|
+
throw new Error("window minimized\uFF1Amode=screen \u53EA\u4F1A\u622A\u5230\u5B83\u4E0B\u65B9\u7684\u684C\u9762\uFF0C\u53BB\u6389 mode=screen \u8BA9\u9ED8\u8BA4 print \u751F\u6548");
|
|
22547
|
+
}
|
|
22548
|
+
const wRect = RECT.alloc();
|
|
22549
|
+
if (!GetWindowRect(hwnd, wRect.ptr)) {
|
|
22550
|
+
throw new Error("GetWindowRect(hwnd=" + hwnd + ")=0\uFF1A\u7A97\u53E3\u4E0D\u5B58\u5728\u6216\u5DF2\u9500\u6BC1");
|
|
22551
|
+
}
|
|
22552
|
+
const { left: wl, top: wt2, right: wr2, bottom: wbot } = RECT.decode(wRect);
|
|
22553
|
+
const ww = wr2 - wl;
|
|
22554
|
+
const wh = wbot - wt2;
|
|
22555
|
+
let cropX = 0;
|
|
22556
|
+
let cropY = 0;
|
|
22557
|
+
let cw = ww;
|
|
22558
|
+
let ch = wh;
|
|
22559
|
+
if (area === "client") {
|
|
22560
|
+
const cRect = RECT.alloc();
|
|
22561
|
+
if (!GetClientRect(hwnd, cRect.ptr))
|
|
22562
|
+
throw new Error("GetClientRect(hwnd=" + hwnd + ")=0");
|
|
22563
|
+
const { left: cl, top: ct2, right: cr2, bottom: cbot } = RECT.decode(cRect);
|
|
22564
|
+
cw = cr2 - cl;
|
|
22565
|
+
ch = cbot - ct2;
|
|
22566
|
+
const origin = POINT.encode({ x: 0, y: 0 });
|
|
22567
|
+
if (!ClientToScreen(hwnd, origin.ptr))
|
|
22568
|
+
throw new Error("ClientToScreen(hwnd=" + hwnd + ")=0");
|
|
22569
|
+
const org = POINT.decode(origin);
|
|
22570
|
+
cropX = org.x - wl;
|
|
22571
|
+
cropY = org.y - wt2;
|
|
22572
|
+
}
|
|
22573
|
+
let sx = mode === "print" ? 0 : wl + cropX;
|
|
22574
|
+
let sy = mode === "print" ? 0 : wt2 + cropY;
|
|
22575
|
+
if (mode === "screen") {
|
|
22576
|
+
const vsX = GetSystemMetrics(76);
|
|
22577
|
+
const vsY = GetSystemMetrics(77);
|
|
22578
|
+
const vsW = GetSystemMetrics(78);
|
|
22579
|
+
const vsH = GetSystemMetrics(79);
|
|
22580
|
+
const ax = Math.max(sx, vsX);
|
|
22581
|
+
const ay = Math.max(sy, vsY);
|
|
22582
|
+
const ax2 = Math.min(sx + cw, vsX + vsW);
|
|
22583
|
+
const ay2 = Math.min(sy + ch, vsY + vsH);
|
|
22584
|
+
if (ax2 <= ax || ay2 <= ay) {
|
|
22585
|
+
throw new Error("capture area outside virtual screen at=(" + sx + "," + sy + "," + cw + "x" + ch + ")");
|
|
22120
22586
|
}
|
|
22121
|
-
|
|
22122
|
-
|
|
22123
|
-
|
|
22124
|
-
|
|
22587
|
+
sx = ax;
|
|
22588
|
+
sy = ay;
|
|
22589
|
+
cw = ax2 - ax;
|
|
22590
|
+
ch = ay2 - ay;
|
|
22591
|
+
}
|
|
22592
|
+
return captureRect(ww, wh, sx, sy, cropX, cropY, cw, ch, mode === "print" ? hwnd : null);
|
|
22593
|
+
}
|
|
22594
|
+
function listWindows() {
|
|
22595
|
+
const handles = [];
|
|
22596
|
+
const collect = closure("<HWND>ptr <>ptr -> i32", (h2) => {
|
|
22597
|
+
if (h2)
|
|
22598
|
+
handles.push(h2);
|
|
22599
|
+
return handles.length < MAX_WINDOWS ? 1 : 0;
|
|
22125
22600
|
});
|
|
22601
|
+
try {
|
|
22602
|
+
EnumWindows(collect.ptr, NULL);
|
|
22603
|
+
} finally {
|
|
22604
|
+
collect.dispose();
|
|
22605
|
+
}
|
|
22606
|
+
const wRect = RECT.alloc();
|
|
22607
|
+
const tb = WCHAR.alloc(WIDE_BUF_CHARS);
|
|
22608
|
+
const cb = WCHAR.alloc(WIDE_BUF_CHARS);
|
|
22609
|
+
const out = [];
|
|
22610
|
+
for (const hwnd of handles) {
|
|
22611
|
+
if (GetWindowRect(hwnd, wRect.ptr)) {
|
|
22612
|
+
const rc2 = RECT.decode(wRect);
|
|
22613
|
+
const tl = GetWindowText(hwnd, tb, WIDE_BUF_CHARS);
|
|
22614
|
+
const cl = GetClassName(hwnd, cb, WIDE_BUF_CHARS);
|
|
22615
|
+
out.push({
|
|
22616
|
+
hwnd,
|
|
22617
|
+
// 缓冲跨窗口复用:长度 0 时 API 不保证写回终止符,不能 decode 残留内容
|
|
22618
|
+
title: tl > 0 ? WCHAR.decode(tb) : "",
|
|
22619
|
+
className: cl > 0 ? WCHAR.decode(cb) : "",
|
|
22620
|
+
rect: { left: rc2.left, top: rc2.top, right: rc2.right, bottom: rc2.bottom },
|
|
22621
|
+
visible: IsWindowVisible(hwnd) !== 0,
|
|
22622
|
+
minimized: IsIconic(hwnd) !== 0
|
|
22623
|
+
});
|
|
22624
|
+
}
|
|
22625
|
+
}
|
|
22626
|
+
return out;
|
|
22627
|
+
}
|
|
22628
|
+
var DISP_CHANGE_NAME = {
|
|
22629
|
+
[
|
|
22630
|
+
0
|
|
22631
|
+
/* DisplayChangeResult.SUCCESSFUL */
|
|
22632
|
+
]: "SUCCESSFUL",
|
|
22633
|
+
[
|
|
22634
|
+
1
|
|
22635
|
+
/* DisplayChangeResult.RESTART */
|
|
22636
|
+
]: "RESTART",
|
|
22637
|
+
[
|
|
22638
|
+
-1
|
|
22639
|
+
/* DisplayChangeResult.FAILED */
|
|
22640
|
+
]: "FAILED",
|
|
22641
|
+
[
|
|
22642
|
+
-2
|
|
22643
|
+
/* DisplayChangeResult.BADMODE */
|
|
22644
|
+
]: "BADMODE",
|
|
22645
|
+
[
|
|
22646
|
+
-3
|
|
22647
|
+
/* DisplayChangeResult.NOTUPDATED */
|
|
22648
|
+
]: "NOTUPDATED",
|
|
22649
|
+
[
|
|
22650
|
+
-4
|
|
22651
|
+
/* DisplayChangeResult.BADFLAGS */
|
|
22652
|
+
]: "BADFLAGS",
|
|
22653
|
+
[
|
|
22654
|
+
-5
|
|
22655
|
+
/* DisplayChangeResult.BADPARAM */
|
|
22656
|
+
]: "BADPARAM",
|
|
22657
|
+
[
|
|
22658
|
+
-6
|
|
22659
|
+
/* DisplayChangeResult.BADDUALVIEW */
|
|
22660
|
+
]: "BADDUALVIEW"
|
|
22661
|
+
};
|
|
22662
|
+
function dispChangeName(ret) {
|
|
22663
|
+
return DISP_CHANGE_NAME[ret] ?? "?";
|
|
22664
|
+
}
|
|
22665
|
+
function currentScreen() {
|
|
22666
|
+
return GetSystemMetrics(
|
|
22667
|
+
0
|
|
22668
|
+
/* SysMetrics.CXSCREEN */
|
|
22669
|
+
) + "x" + GetSystemMetrics(
|
|
22670
|
+
1
|
|
22671
|
+
/* SysMetrics.CYSCREEN */
|
|
22672
|
+
);
|
|
22673
|
+
}
|
|
22674
|
+
function listModes32() {
|
|
22675
|
+
const probe = DEVMODEW.encode({ dmSize: DEVMODEW.size });
|
|
22676
|
+
const out = [];
|
|
22677
|
+
for (let i2 = 0; i2 < 200; i2++) {
|
|
22678
|
+
if (!EnumDisplaySettings(NULL, i2, probe.ptr))
|
|
22679
|
+
break;
|
|
22680
|
+
const dm = DEVMODEW.decode(probe);
|
|
22681
|
+
if (dm.dmBitsPerPel !== 32)
|
|
22682
|
+
continue;
|
|
22683
|
+
out.push(dm.dmPelsWidth + "x" + dm.dmPelsHeight + "@" + dm.dmDisplayFrequency);
|
|
22684
|
+
}
|
|
22685
|
+
return out;
|
|
22686
|
+
}
|
|
22687
|
+
function applyDisplayMode(w2, h2, persist) {
|
|
22688
|
+
if (!Number.isInteger(w2) || w2 <= 0 || !Number.isInteger(h2) || h2 <= 0) {
|
|
22689
|
+
throw new Error("applyDisplayMode: w/h must be positive integers, got " + w2 + "x" + h2);
|
|
22690
|
+
}
|
|
22691
|
+
const dm = DEVMODEW.encode({ dmSize: DEVMODEW.size });
|
|
22692
|
+
if (!EnumDisplaySettings(NULL, -1, dm.ptr)) {
|
|
22693
|
+
throw new Error("applyDisplayMode: EnumDisplaySettings CURRENT failed");
|
|
22694
|
+
}
|
|
22695
|
+
const cur = DEVMODEW.decode(dm);
|
|
22696
|
+
const before = cur.dmPelsWidth + "x" + cur.dmPelsHeight;
|
|
22697
|
+
DEVMODEW.encode({
|
|
22698
|
+
dmFields: cur.dmFields | 524288 | 1048576,
|
|
22699
|
+
dmPelsWidth: w2,
|
|
22700
|
+
dmPelsHeight: h2
|
|
22701
|
+
}, dm);
|
|
22702
|
+
const testRet = ChangeDisplaySettings(
|
|
22703
|
+
dm.ptr,
|
|
22704
|
+
2
|
|
22705
|
+
/* ChangeDisplayFlag.TEST */
|
|
22706
|
+
);
|
|
22707
|
+
if (testRet !== 0) {
|
|
22708
|
+
return {
|
|
22709
|
+
before,
|
|
22710
|
+
after: currentScreen(),
|
|
22711
|
+
testRet,
|
|
22712
|
+
ret: testRet,
|
|
22713
|
+
retName: dispChangeName(testRet),
|
|
22714
|
+
modes32: listModes32()
|
|
22715
|
+
};
|
|
22716
|
+
}
|
|
22717
|
+
let ret = ChangeDisplaySettings(dm.ptr, 0);
|
|
22718
|
+
if (ret === 0 && persist) {
|
|
22719
|
+
ret = ChangeDisplaySettings(
|
|
22720
|
+
dm.ptr,
|
|
22721
|
+
1
|
|
22722
|
+
/* ChangeDisplayFlag.UPDATEREGISTRY */
|
|
22723
|
+
);
|
|
22724
|
+
}
|
|
22725
|
+
return { before, after: currentScreen(), testRet, ret, retName: dispChangeName(ret), modes32: listModes32() };
|
|
22726
|
+
}
|
|
22727
|
+
var USAGE = `quickwin execd \u2014\u2014 \u672C\u9875\u5373\u7528\u6CD5\uFF08API \u4E4B\u5916\u4EFB\u610F\u8DEF\u5F84\u5747\u8FD4\u56DE\uFF0CHTTP 200\uFF09
|
|
22728
|
+
|
|
22729
|
+
API\uFF08\u914D\u7F6E token \u540E\u9700 Authorization: Bearer <token>\uFF0C\u672A\u914D\u7F6E\u5219\u653E\u884C\uFF09\uFF1A
|
|
22730
|
+
POST /exec JSON {"cmd":"\u547D\u4EE4","timeout":\u6BEB\u79D2?} \u2192 \u6D41\u5F0F\u8F93\u51FA\uFF0CTrailer X-Exit-Code
|
|
22731
|
+
GET /screenshot ?hwnd=<\u5341\u8FDB\u5236>&area=window|client&mode=screen|print \u2192 image/bmp
|
|
22732
|
+
\uFF08X-Dimensions\uFF1B\u4E0D\u5E26 hwnd = \u6574\u5C4F BitBlt\uFF1B\u5E26 hwnd \u9ED8\u8BA4 mode=print
|
|
22733
|
+
\u8BA9\u7A97\u53E3\u81EA\u7ED8\u2014\u2014\u906E\u6321/\u6700\u5C0F\u5316/\u8D85\u5C4F\u4E5F\u62FF\u5B8C\u6574\u50CF\u7D20\uFF0Cscreen \u53EA\u622A\u53EF\u89C1\u90E8\u5206\uFF09
|
|
22734
|
+
GET /window_list \u2192 JSON \u7A97\u53E3\u5217\u8868 [{hwnd,title,className,...}]
|
|
22735
|
+
GET /tray_list \u2192 JSON {icons:[{area,index,hWnd,uID,tooltip,rect}]}\uFF08\u8DE8\u8FDB\u7A0B\u679A\u4E3E
|
|
22736
|
+
explorer toolbar\uFF1A\u53EF\u89C1\u533A Shell_TrayWnd + \u6298\u53E0\u533A NotifyIconOverflowWindow\uFF1B
|
|
22737
|
+
rect \u5C4F\u5E55\u7269\u7406\u50CF\u7D20\uFF0C\u5168 0 \u2192 null\uFF1B\u6298\u53E0\u9762\u677F\u672A\u5C55\u5F00\u65F6 overflow \u533A rect
|
|
22738
|
+
\u4EC5\u5F53\u5C55\u5F00\u540E\u53EF\u9760\uFF09\uFF1B?probe=<hwnd>&uid=<n> \u2192 \u9644 probe {hr,hrName,rect}
|
|
22739
|
+
\uFF08\u5355\u56FE\u6807 Shell_NotifyIconGetRect\uFF0CWin7+\uFF1A0=found \u9644\u5BB9\u5668 rect / 1=hidden
|
|
22740
|
+
/ E_FAIL=\u4E0D\u5B58\u5728\u6216 GUID \u56FE\u6807\uFF1BXP \u65E0\u6B64 API \u2192 unsupported\uFF09
|
|
22741
|
+
POST /set_resolution ?w=<px>&h=<px>&persist=0|1\uFF08\u9ED8\u8BA4 1 = \u5199\u6CE8\u518C\u8868\u8DE8\u91CD\u542F\uFF09\u2192 JSON
|
|
22742
|
+
{before,after,testRet,ret,retName,modes32}\uFF1Bmodes32 \u6052\u5E26 32bpp
|
|
22743
|
+
\u53EF\u7528\u6A21\u5F0F\uFF08\u975E\u6CD5\u5BBD\u9AD8\u4F1A\u4EE5 BADMODE \u62D2\u7EDD\u5E76\u7ED9\u672C\u5217\u8868\uFF09
|
|
22744
|
+
POST /input body = JSON \u6570\u7EC4\uFF08\u6279\u91CF\u6CE8\u5165\uFF1Bx/y \u7269\u7406\u50CF\u7D20\uFF09\uFF1A
|
|
22745
|
+
{"t":"move","x":,"y":} | {"t":"down|up","btn":"left|right|middle|x1|x2","x":,"y":?} |
|
|
22746
|
+
{"t":"key","key":"a|enter|0x41","up":true?} | {"t":"sleep","ms":0..5000}
|
|
22747
|
+
\u2192 JSON {sent,expected}\uFF1B\u6309 sleep \u5207\u6BB5\uFF0C\u6BB5\u5185\u4E00\u6B21 SendInput \u539F\u5B50\u6CE8\u5165`;
|
|
22748
|
+
function usageResponse() {
|
|
22749
|
+
return new Response(USAGE, { headers: { "Content-Type": "text/plain; charset=utf-8" } });
|
|
22750
|
+
}
|
|
22751
|
+
var INPUT_MOUSE = 0;
|
|
22752
|
+
var INPUT_KEYBOARD = 1;
|
|
22753
|
+
var MOUSEEVENTF_MOVE = 1;
|
|
22754
|
+
var MOUSEEVENTF_ABSOLUTE = 32768;
|
|
22755
|
+
var KEYEVENTF_KEYUP = 2;
|
|
22756
|
+
var MOUSE_BTNS = {
|
|
22757
|
+
left: [2, 4, 0],
|
|
22758
|
+
right: [8, 16, 0],
|
|
22759
|
+
middle: [32, 64, 0],
|
|
22760
|
+
x1: [128, 256, 1],
|
|
22761
|
+
x2: [128, 256, 2]
|
|
22762
|
+
};
|
|
22763
|
+
var VK_NAMES = {
|
|
22764
|
+
backspace: 8,
|
|
22765
|
+
tab: 9,
|
|
22766
|
+
enter: 13,
|
|
22767
|
+
shift: 16,
|
|
22768
|
+
ctrl: 17,
|
|
22769
|
+
alt: 18,
|
|
22770
|
+
caps: 20,
|
|
22771
|
+
esc: 27,
|
|
22772
|
+
space: 32,
|
|
22773
|
+
pageup: 33,
|
|
22774
|
+
pagedown: 34,
|
|
22775
|
+
end: 35,
|
|
22776
|
+
home: 36,
|
|
22777
|
+
left: 37,
|
|
22778
|
+
up: 38,
|
|
22779
|
+
right: 39,
|
|
22780
|
+
down: 40,
|
|
22781
|
+
insert: 45,
|
|
22782
|
+
delete: 46,
|
|
22783
|
+
win: 91,
|
|
22784
|
+
f1: 112,
|
|
22785
|
+
f2: 113,
|
|
22786
|
+
f3: 114,
|
|
22787
|
+
f4: 115,
|
|
22788
|
+
f5: 116,
|
|
22789
|
+
f6: 117,
|
|
22790
|
+
f7: 118,
|
|
22791
|
+
f8: 119,
|
|
22792
|
+
f9: 120,
|
|
22793
|
+
f10: 121,
|
|
22794
|
+
f11: 122,
|
|
22795
|
+
f12: 123
|
|
22796
|
+
};
|
|
22797
|
+
function vkOf(key) {
|
|
22798
|
+
if (typeof key === "number" && Number.isInteger(key) && key >= 0 && key <= 65535)
|
|
22799
|
+
return key;
|
|
22800
|
+
if (typeof key === "string") {
|
|
22801
|
+
if (key.length === 1) {
|
|
22802
|
+
const c2 = key.toUpperCase().charCodeAt(0);
|
|
22803
|
+
if (c2 >= 48 && c2 <= 57 || c2 >= 65 && c2 <= 90)
|
|
22804
|
+
return c2;
|
|
22805
|
+
}
|
|
22806
|
+
const vk = VK_NAMES[key.toLowerCase()];
|
|
22807
|
+
if (vk !== void 0)
|
|
22808
|
+
return vk;
|
|
22809
|
+
}
|
|
22810
|
+
throw new Error("bad key: " + JSON.stringify(key) + " (a-z/0-9|name|0..0xFFFF)");
|
|
22126
22811
|
}
|
|
22127
22812
|
var server = createServer(async (req) => {
|
|
22128
22813
|
const t0 = Date.now();
|
|
22129
22814
|
const path = new URL(req.url).pathname;
|
|
22130
|
-
|
|
22131
|
-
|
|
22132
|
-
|
|
22815
|
+
const isApi = req.method === "POST" && (path === "/exec" || path === "/set_resolution" || path === "/input") || req.method === "GET" && (path === "/window_list" || path === "/screenshot" || path === "/tray_list");
|
|
22816
|
+
if (!isApi)
|
|
22817
|
+
return usageResponse();
|
|
22133
22818
|
const denied = authCheck(req);
|
|
22134
22819
|
if (denied !== null) {
|
|
22135
|
-
|
|
22820
|
+
logReq(t0, req.method + " " + path, 401, "missing/invalid token");
|
|
22136
22821
|
return denied;
|
|
22137
22822
|
}
|
|
22138
22823
|
if (req.method === "GET" && path === "/window_list") {
|
|
22139
|
-
|
|
22140
|
-
|
|
22141
|
-
|
|
22824
|
+
try {
|
|
22825
|
+
const wins = listWindows();
|
|
22826
|
+
const resp = new Response(JSON.stringify(wins), { headers: { "Content-Type": "application/json" } });
|
|
22827
|
+
logReq(t0, "GET /window_list", 200);
|
|
22828
|
+
return resp;
|
|
22829
|
+
} catch (ex) {
|
|
22830
|
+
logReq(t0, "GET /window_list", 500, String(ex));
|
|
22831
|
+
return jsonError(500, String(ex));
|
|
22832
|
+
}
|
|
22833
|
+
}
|
|
22834
|
+
if (req.method === "GET" && path === "/tray_list") {
|
|
22835
|
+
const params = new URL(req.url).searchParams;
|
|
22836
|
+
let probe = null;
|
|
22837
|
+
const ph = params.get("probe");
|
|
22838
|
+
if (ph !== null) {
|
|
22839
|
+
const hh = Number(ph), uid = Number(params.get("uid") ?? "");
|
|
22840
|
+
if (!Number.isInteger(hh) || hh <= 0 || !Number.isInteger(uid) || uid < 0) {
|
|
22841
|
+
logReq(t0, "GET /tray_list", 400, "probe=<hwnd>&uid=<n>");
|
|
22842
|
+
return jsonError(400, "probe needs integer hwnd>0 and uid>=0");
|
|
22843
|
+
}
|
|
22844
|
+
probe = { hWnd: hh, uID: uid };
|
|
22845
|
+
}
|
|
22846
|
+
try {
|
|
22847
|
+
const icons = listTrayIcons();
|
|
22848
|
+
const body = { icons };
|
|
22849
|
+
if (probe)
|
|
22850
|
+
body.probe = probeTrayIcon(probe.hWnd, probe.uID);
|
|
22851
|
+
const nOv = icons.reduce((n2, e2) => n2 + (e2.area === "overflow" ? 1 : 0), 0);
|
|
22852
|
+
logReq(t0, "GET /tray_list", 200, icons.length + " icons \xB7 overflow " + nOv);
|
|
22853
|
+
return new Response(JSON.stringify(body), { headers: { "Content-Type": "application/json" } });
|
|
22854
|
+
} catch (ex) {
|
|
22855
|
+
logReq(t0, "GET /tray_list", 500, String(ex));
|
|
22856
|
+
return jsonError(500, String(ex));
|
|
22857
|
+
}
|
|
22142
22858
|
}
|
|
22143
22859
|
if (req.method === "GET" && path === "/screenshot") {
|
|
22144
22860
|
let opts;
|
|
22145
22861
|
try {
|
|
22146
22862
|
opts = parseShotOpts(new URL(req.url).searchParams);
|
|
22147
22863
|
} catch (ex) {
|
|
22148
|
-
|
|
22864
|
+
logReq(t0, "GET /screenshot", 400, String(ex));
|
|
22149
22865
|
return jsonError(400, String(ex));
|
|
22150
22866
|
}
|
|
22151
|
-
|
|
22867
|
+
let cap;
|
|
22868
|
+
try {
|
|
22869
|
+
cap = opts.hwnd === null ? captureScreen() : captureWindow(opts.hwnd, opts.area, opts.mode);
|
|
22870
|
+
} catch (ex) {
|
|
22871
|
+
logReq(t0, "GET /screenshot", 500, String(ex));
|
|
22872
|
+
return jsonError(500, String(ex));
|
|
22873
|
+
}
|
|
22152
22874
|
const target = opts.hwnd !== null ? " hwnd=" + opts.hwnd + " " + opts.area + "/" + opts.mode : " screen";
|
|
22153
|
-
|
|
22875
|
+
logReq(t0, "GET /screenshot" + target, 200);
|
|
22876
|
+
return new Response(cap.bmp, {
|
|
22877
|
+
headers: { "Content-Type": "image/bmp", "X-Dimensions": cap.width + "x" + cap.height }
|
|
22878
|
+
});
|
|
22879
|
+
}
|
|
22880
|
+
if (req.method === "POST" && path === "/set_resolution") {
|
|
22881
|
+
let result;
|
|
22882
|
+
let w2 = 0, h2 = 0, persist = true;
|
|
22883
|
+
try {
|
|
22884
|
+
const params = new URL(req.url).searchParams;
|
|
22885
|
+
w2 = Number(params.get("w"));
|
|
22886
|
+
h2 = Number(params.get("h"));
|
|
22887
|
+
if (!Number.isInteger(w2) || w2 <= 0 || !Number.isInteger(h2) || h2 <= 0) {
|
|
22888
|
+
throw new Error("w/h must be positive integers");
|
|
22889
|
+
}
|
|
22890
|
+
persist = params.get("persist") !== "0";
|
|
22891
|
+
result = applyDisplayMode(w2, h2, persist);
|
|
22892
|
+
} catch (ex) {
|
|
22893
|
+
logReq(t0, "POST /set_resolution", 400, String(ex));
|
|
22894
|
+
return jsonError(400, String(ex));
|
|
22895
|
+
}
|
|
22896
|
+
const resp = new Response(JSON.stringify(result), { headers: { "Content-Type": "application/json" } });
|
|
22897
|
+
logReq(t0, "POST /set_resolution " + w2 + "x" + h2 + (persist ? "" : " persist=0"), 200, result.ret !== 0 ? result.retName : void 0);
|
|
22154
22898
|
return resp;
|
|
22155
22899
|
}
|
|
22900
|
+
if (req.method === "POST" && path === "/input") {
|
|
22901
|
+
const bad = (msg) => {
|
|
22902
|
+
logReq(t0, "POST /input", 400, msg);
|
|
22903
|
+
return jsonError(400, msg);
|
|
22904
|
+
};
|
|
22905
|
+
let raw;
|
|
22906
|
+
try {
|
|
22907
|
+
raw = await req.json();
|
|
22908
|
+
} catch (ex) {
|
|
22909
|
+
return bad("bad json: " + String(ex));
|
|
22910
|
+
}
|
|
22911
|
+
if (!Array.isArray(raw) || raw.length === 0)
|
|
22912
|
+
return bad("body must be a non-empty JSON array");
|
|
22913
|
+
if (raw.length > 1e3)
|
|
22914
|
+
return bad("too many events: " + raw.length + " (max 1000)");
|
|
22915
|
+
const sw = GetSystemMetrics(0), sh = GetSystemMetrics(1);
|
|
22916
|
+
const segs = [{ els: [], sleep: 0 }];
|
|
22917
|
+
const cur = () => segs[segs.length - 1];
|
|
22918
|
+
try {
|
|
22919
|
+
for (const e2 of raw) {
|
|
22920
|
+
if (typeof e2 !== "object" || e2 === null || Array.isArray(e2))
|
|
22921
|
+
throw new Error("event must be an object: " + JSON.stringify(e2));
|
|
22922
|
+
const ev = e2;
|
|
22923
|
+
const abs = (required) => {
|
|
22924
|
+
if (ev.x === void 0 && ev.y === void 0) {
|
|
22925
|
+
if (required)
|
|
22926
|
+
throw new Error("x/y required for move");
|
|
22927
|
+
return [0, 0, 0];
|
|
22928
|
+
}
|
|
22929
|
+
const x2 = ev.x, y2 = ev.y;
|
|
22930
|
+
if (typeof x2 !== "number" || typeof y2 !== "number" || !Number.isInteger(x2) || !Number.isInteger(y2))
|
|
22931
|
+
throw new Error("x/y must be integers (physical px)");
|
|
22932
|
+
if (x2 < 0 || x2 >= sw || y2 < 0 || y2 >= sh)
|
|
22933
|
+
throw new Error("x/y out of screen: 0.." + (sw - 1) + " / 0.." + (sh - 1));
|
|
22934
|
+
return [
|
|
22935
|
+
Math.round(x2 * 65535 / (sw - 1)),
|
|
22936
|
+
Math.round(y2 * 65535 / (sh - 1)),
|
|
22937
|
+
MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE
|
|
22938
|
+
];
|
|
22939
|
+
};
|
|
22940
|
+
switch (ev.t) {
|
|
22941
|
+
case "move": {
|
|
22942
|
+
const [dx, dy, f2] = abs(true);
|
|
22943
|
+
cur().els.push({ type: INPUT_MOUSE, data: { mi: { dx, dy, dwFlags: f2 } } });
|
|
22944
|
+
break;
|
|
22945
|
+
}
|
|
22946
|
+
case "down":
|
|
22947
|
+
case "up": {
|
|
22948
|
+
const btn = typeof ev.btn === "string" ? MOUSE_BTNS[ev.btn] : void 0;
|
|
22949
|
+
if (!btn)
|
|
22950
|
+
throw new Error("bad btn: " + JSON.stringify(ev.btn) + " (left|right|middle|x1|x2)");
|
|
22951
|
+
const [downF, upF, mData] = btn;
|
|
22952
|
+
const [dx, dy, f2] = abs(false);
|
|
22953
|
+
const flag = ev.t === "down" ? downF : upF;
|
|
22954
|
+
cur().els.push({ type: INPUT_MOUSE, data: { mi: { dx, dy, mouseData: mData, dwFlags: f2 | flag } } });
|
|
22955
|
+
break;
|
|
22956
|
+
}
|
|
22957
|
+
case "key": {
|
|
22958
|
+
const up = ev.up === true;
|
|
22959
|
+
cur().els.push({ type: INPUT_KEYBOARD, data: { ki: { wVk: vkOf(ev.key), dwFlags: up ? KEYEVENTF_KEYUP : 0 } } });
|
|
22960
|
+
break;
|
|
22961
|
+
}
|
|
22962
|
+
case "sleep": {
|
|
22963
|
+
const ms = ev.ms;
|
|
22964
|
+
if (typeof ms !== "number" || !Number.isFinite(ms) || ms < 0 || ms > 5e3)
|
|
22965
|
+
throw new Error("sleep ms must be a number in 0..5000");
|
|
22966
|
+
segs.push({ els: [], sleep: ms });
|
|
22967
|
+
break;
|
|
22968
|
+
}
|
|
22969
|
+
default:
|
|
22970
|
+
throw new Error("bad t: " + JSON.stringify(ev.t) + " (move|down|up|key|sleep)");
|
|
22971
|
+
}
|
|
22972
|
+
}
|
|
22973
|
+
} catch (ex) {
|
|
22974
|
+
return bad(ex instanceof Error ? ex.message : String(ex));
|
|
22975
|
+
}
|
|
22976
|
+
let expected = 0, sent = 0;
|
|
22977
|
+
for (const s2 of segs)
|
|
22978
|
+
expected += s2.els.length;
|
|
22979
|
+
try {
|
|
22980
|
+
for (const seg of segs) {
|
|
22981
|
+
if (seg.sleep > 0)
|
|
22982
|
+
await new Promise((r2) => {
|
|
22983
|
+
os7.setTimeout(r2, seg.sleep);
|
|
22984
|
+
});
|
|
22985
|
+
if (seg.els.length === 0)
|
|
22986
|
+
continue;
|
|
22987
|
+
const n2 = SendInput(seg.els.length, seg.els, INPUT.size);
|
|
22988
|
+
sent += n2;
|
|
22989
|
+
if (n2 < seg.els.length)
|
|
22990
|
+
break;
|
|
22991
|
+
}
|
|
22992
|
+
} catch (ex) {
|
|
22993
|
+
logReq(t0, "POST /input", 500, String(ex));
|
|
22994
|
+
return jsonError(500, String(ex));
|
|
22995
|
+
}
|
|
22996
|
+
logReq(t0, "POST /input " + raw.length + "ev", 200, sent < expected ? "sent " + sent + "/" + expected : void 0);
|
|
22997
|
+
return new Response(JSON.stringify({ sent, expected }), { headers: { "Content-Type": "application/json" } });
|
|
22998
|
+
}
|
|
22156
22999
|
if (req.method === "POST" && path === "/exec") {
|
|
22157
23000
|
let out;
|
|
22158
23001
|
let cmd;
|
|
@@ -22163,29 +23006,17 @@ var server = createServer(async (req) => {
|
|
|
22163
23006
|
cmd = body.cmd;
|
|
22164
23007
|
out = runInWorker(body.cmd, req.signal, timeoutMs);
|
|
22165
23008
|
} catch (ex) {
|
|
22166
|
-
return
|
|
22167
|
-
status: 500,
|
|
22168
|
-
headers: { "Content-Type": "application/json" }
|
|
22169
|
-
});
|
|
23009
|
+
return jsonError(500, "setup: " + String(ex));
|
|
22170
23010
|
}
|
|
22171
23011
|
try {
|
|
22172
23012
|
const rd = await out.ready;
|
|
22173
23013
|
if (!rd.ok) {
|
|
22174
|
-
|
|
22175
|
-
return
|
|
22176
|
-
status: 500,
|
|
22177
|
-
headers: { "Content-Type": "application/json" }
|
|
22178
|
-
});
|
|
23014
|
+
logReq(t0, cmd, 500, rd.error);
|
|
23015
|
+
return jsonError(500, rd.error ?? "exec failed");
|
|
22179
23016
|
}
|
|
22180
23017
|
out.trailers.then((h2) => {
|
|
22181
23018
|
const code = h2["X-Exit-Code"];
|
|
22182
|
-
|
|
22183
|
-
ts: Date.now() / 1e3,
|
|
22184
|
-
cmd,
|
|
22185
|
-
status: 200,
|
|
22186
|
-
exit: code === void 0 ? null : Number(code),
|
|
22187
|
-
durMs: Date.now() - t0
|
|
22188
|
-
});
|
|
23019
|
+
logReq(t0, cmd, 200, void 0, code === void 0 ? null : Number(code));
|
|
22189
23020
|
}).catch(() => {
|
|
22190
23021
|
});
|
|
22191
23022
|
return new Response(out.stream, {
|
|
@@ -22196,15 +23027,11 @@ var server = createServer(async (req) => {
|
|
|
22196
23027
|
trailers: out.trailers
|
|
22197
23028
|
});
|
|
22198
23029
|
} catch (ex) {
|
|
22199
|
-
|
|
22200
|
-
return
|
|
22201
|
-
status: 504,
|
|
22202
|
-
headers: { "Content-Type": "application/json" }
|
|
22203
|
-
});
|
|
23030
|
+
logReq(t0, cmd, 504, "exec timeout");
|
|
23031
|
+
return jsonError(504, String(ex));
|
|
22204
23032
|
}
|
|
22205
23033
|
}
|
|
22206
|
-
|
|
22207
|
-
return new Response("Not Found", { status: 404 });
|
|
23034
|
+
return usageResponse();
|
|
22208
23035
|
});
|
|
22209
23036
|
var rc = server.listen(8080, "0.0.0.0");
|
|
22210
23037
|
console.log("listen rc=" + rc + " addr=" + JSON.stringify(server.address()));
|