local-operator-ui 0.22.7 → 0.23.1
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/out/main/index.js +958 -791
- package/out/renderer/assets/{_basePickBy-DhQNxtlD.js → _basePickBy-mmFlh3ho.js} +1 -1
- package/out/renderer/assets/{_baseUniq-CX_YBd6Y.js → _baseUniq-DAWnt4WG.js} +1 -1
- package/out/renderer/assets/{agent-details-page-o4gHsKUa.js → agent-details-page-CO72YkSX.js} +2 -2
- package/out/renderer/assets/{agent-hub-page-BzDj9IWf.js → agent-hub-page-DhYc5_gP.js} +2 -2
- package/out/renderer/assets/{agents-page-fMYF44vi.js → agents-page-BopOzax_.js} +2 -2
- package/out/renderer/assets/arc-BgHsUFIt.js +1 -0
- package/out/renderer/assets/architectureDiagram-IEHRJDOE-BWxIiACo.js +36 -0
- package/out/renderer/assets/{blockDiagram-JOT3LUYC-Djo9sUfE.js → blockDiagram-JOT3LUYC-CoJDUfWc.js} +2 -2
- package/out/renderer/assets/{c4Diagram-VJAJSXHY-Uw8QTBf1.js → c4Diagram-VJAJSXHY-B8vXmmLx.js} +2 -2
- package/out/renderer/assets/channel-DAvIgUhZ.js +1 -0
- package/out/renderer/assets/{chunk-4BMEZGHF-BIOsyZUb.js → chunk-4BMEZGHF-rO5ve7XY.js} +1 -1
- package/out/renderer/assets/{chunk-A2AXSNBT-DgGsJjzO.js → chunk-A2AXSNBT-CTPb1xgY.js} +1 -1
- package/out/renderer/assets/{chunk-AEK57VVT-BIKbqRlZ.js → chunk-AEK57VVT-5VpTdLBm.js} +1 -1
- package/out/renderer/assets/{chunk-D6G4REZN-67ezHJSD.js → chunk-D6G4REZN-C3CEf0kC.js} +1 -1
- package/out/renderer/assets/{chunk-RZ5BOZE2-DcomjUhS.js → chunk-RZ5BOZE2-B7nn7Euk.js} +1 -1
- package/out/renderer/assets/{chunk-XZIHB7SX-BUmWwWrV.js → chunk-XZIHB7SX-CnPH3vBT.js} +1 -1
- package/out/renderer/assets/classDiagram-GIVACNV2-CP5aSNYY.js +1 -0
- package/out/renderer/assets/classDiagram-v2-COTLJTTW-CP5aSNYY.js +1 -0
- package/out/renderer/assets/clone-CeahOD_w.js +1 -0
- package/out/renderer/assets/{compact-pagination-DKIAGx25.js → compact-pagination-Bu8vshU-.js} +1 -1
- package/out/renderer/assets/dagre-OKDRZEBW-DUX1RPbJ.js +4 -0
- package/out/renderer/assets/diagram-SSKATNLV-Cpv42kzr.js +43 -0
- package/out/renderer/assets/diagram-VNBRO52H-CGkUnKEL.js +24 -0
- package/out/renderer/assets/{erDiagram-Q7BY3M3F-leIAVVl8.js → erDiagram-Q7BY3M3F-iBbJbyJZ.js} +2 -2
- package/out/renderer/assets/{flowDiagram-4HSFHLVR-BR2OLvUd.js → flowDiagram-4HSFHLVR-B569Tv1u.js} +2 -2
- package/out/renderer/assets/ganttDiagram-APWFNJXF-nGbcgsgD.js +257 -0
- package/out/renderer/assets/gitGraphDiagram-7IBYFJ6S-vv_MhteL.js +65 -0
- package/out/renderer/assets/{graph-4LKx2VDu.js → graph-krOMwYSa.js} +1 -1
- package/out/renderer/assets/icon-DC3rStnR.css +1 -0
- package/out/renderer/assets/{icon-fSzO-fSj.js → icon-mKHwnRNs.js} +33 -33
- package/out/renderer/assets/index-BgGl2-0g.js +1 -0
- package/out/renderer/assets/index-BqWgqUKZ.js +1424 -0
- package/out/renderer/assets/index-CT6w0yXj.js +7 -0
- package/out/renderer/assets/infoDiagram-PH2N3AL5-DHDA5253.js +2 -0
- package/out/renderer/assets/{installer-CJwdaurY.js → installer-DcKqSMWJ.js} +1 -1
- package/out/renderer/assets/{journeyDiagram-U35MCT3I-_X3MTxbJ.js → journeyDiagram-U35MCT3I-CIrQ218m.js} +2 -2
- package/out/renderer/assets/{kanban-definition-NDS4AKOZ-hUWYLG65.js → kanban-definition-NDS4AKOZ-DG_YsZbL.js} +2 -2
- package/out/renderer/assets/{layout-vfaUtLsA.js → layout-CB5zJSjt.js} +1 -1
- package/out/renderer/assets/{legacy-agents-page-iWsZC-8m.js → legacy-agents-page-B8pvrWy_.js} +5 -5
- package/out/renderer/assets/{mermaid.core-DNwsi5g_.js → mermaid.core-CYc-R2hQ.js} +35 -35
- package/out/renderer/assets/mindmap-definition-ALO5MXBD-C22fFThl.js +95 -0
- package/out/renderer/assets/{page-header-qm7Wt7L1.js → page-header-DmGvvMe3.js} +1 -1
- package/out/renderer/assets/parseISO-vr2fT-wq.js +6 -0
- package/out/renderer/assets/pieDiagram-IB7DONF6-DKRytw7K.js +30 -0
- package/out/renderer/assets/{quadrantDiagram-7GDLP6J5-BOaducXa.js → quadrantDiagram-7GDLP6J5-CWdnqGKr.js} +2 -2
- package/out/renderer/assets/{radar-MK3ICKWK-BI7fIfLl.js → radar-MK3ICKWK-B0XgopGa.js} +1 -1
- package/out/renderer/assets/{radient-auth-buttons-DL7NotAd.js → radient-auth-buttons-RrBw8fkd.js} +1 -1
- package/out/renderer/assets/{requirementDiagram-KVF5MWMF-gVZyn5do.js → requirementDiagram-KVF5MWMF-CXL8GuIo.js} +2 -2
- package/out/renderer/assets/sankeyDiagram-QLVOVGJD-BQKCHfmN.js +10 -0
- package/out/renderer/assets/{schedules-page-DI3d_Jms.js → schedules-page-DtNhlycC.js} +11 -11
- package/out/renderer/assets/{sequenceDiagram-X6HHIX6F-COMD731i.js → sequenceDiagram-X6HHIX6F-awR0fjHu.js} +2 -2
- package/out/renderer/assets/settings-page-DCLaspsn.js +91 -0
- package/out/renderer/assets/{square-pen-Cy0qQPr_.js → square-pen-717nTWtU.js} +1 -1
- package/out/renderer/assets/stateDiagram-DGXRK772-BjhA_mJe.js +1 -0
- package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-nAxLNCrm.js +1 -0
- package/out/renderer/assets/{timeline-definition-BDJGKUSR-CCZIm-XN.js → timeline-definition-BDJGKUSR-BFEDYBl8.js} +2 -2
- package/out/renderer/assets/use-agent-like-mutation-Bxx_WHvo.js +1 -0
- package/out/renderer/assets/{xychartDiagram-VJFVF3MP-Cl5zMzgu.js → xychartDiagram-VJFVF3MP-CwLeRa1a.js} +6 -6
- package/out/renderer/index.html +3 -3
- package/out/renderer/installer.html +3 -3
- package/package.json +2 -2
- package/out/renderer/assets/arc-C1_J1TYO.js +0 -1
- package/out/renderer/assets/architectureDiagram-IEHRJDOE-LYdT4n0-.js +0 -36
- package/out/renderer/assets/band-CquvqAHh.js +0 -1
- package/out/renderer/assets/channel-CcIHiTMf.js +0 -1
- package/out/renderer/assets/classDiagram-GIVACNV2-Doib00-b.js +0 -1
- package/out/renderer/assets/classDiagram-v2-COTLJTTW-Doib00-b.js +0 -1
- package/out/renderer/assets/clone-B0pGWNff.js +0 -1
- package/out/renderer/assets/dagre-OKDRZEBW-D5JBej5q.js +0 -4
- package/out/renderer/assets/diagram-SSKATNLV-roVanCAj.js +0 -43
- package/out/renderer/assets/diagram-VNBRO52H-mWjYHL69.js +0 -24
- package/out/renderer/assets/ganttDiagram-APWFNJXF-BxJlkxvE.js +0 -257
- package/out/renderer/assets/gitGraphDiagram-7IBYFJ6S-CGUHtfkZ.js +0 -65
- package/out/renderer/assets/icon-DzTfuNUy.css +0 -1
- package/out/renderer/assets/index-B-nr8aEh.js +0 -7
- package/out/renderer/assets/index-BpIvhA0p.js +0 -1351
- package/out/renderer/assets/index-CD9V9hPM.js +0 -1
- package/out/renderer/assets/infoDiagram-PH2N3AL5-CeUS0GfM.js +0 -2
- package/out/renderer/assets/init-Dmth1JHB.js +0 -1
- package/out/renderer/assets/linear-BfLTrHPc.js +0 -1
- package/out/renderer/assets/mindmap-definition-ALO5MXBD-DMokx6cp.js +0 -95
- package/out/renderer/assets/ordinal-DILIJJjt.js +0 -1
- package/out/renderer/assets/parseISO-C2gtJ6YV.js +0 -6
- package/out/renderer/assets/pieDiagram-IB7DONF6-C6Cy5b3h.js +0 -30
- package/out/renderer/assets/sankeyDiagram-QLVOVGJD-BUG1W9hs.js +0 -10
- package/out/renderer/assets/settings-page-CvFjZpKU.js +0 -159
- package/out/renderer/assets/stateDiagram-DGXRK772-BOfqY0wc.js +0 -1
- package/out/renderer/assets/stateDiagram-v2-YXO3MK2T-Chyd_KPN.js +0 -1
- package/out/renderer/assets/step-DMJAOHzS.js +0 -1
- package/out/renderer/assets/time-BOTM2Tp0.js +0 -1
- package/out/renderer/assets/use-agent-like-mutation-BSnvivNQ.js +0 -1
package/out/main/index.js
CHANGED
|
@@ -55,6 +55,11 @@ const profileName = zod.z.string().min(1).max(128).refine(
|
|
|
55
55
|
)
|
|
56
56
|
);
|
|
57
57
|
const target = zod.z.object({ kind: zod.z.enum(["agent", "team"]), name: profileName }).strict();
|
|
58
|
+
const modelSelection = zod.z.object({
|
|
59
|
+
provider: zod.z.string().min(1).max(128),
|
|
60
|
+
model_id: zod.z.string().min(1).max(512),
|
|
61
|
+
reasoning_effort: zod.z.string().min(1).max(64).nullable()
|
|
62
|
+
}).strict();
|
|
58
63
|
const profileFields = zod.z.object({
|
|
59
64
|
kind: zod.z.enum(["role", "specialist"]).optional(),
|
|
60
65
|
description: zod.z.string().max(8e3).optional(),
|
|
@@ -151,7 +156,14 @@ const desktopRequestSchema = zod.z.discriminatedUnion("op", [
|
|
|
151
156
|
op: zod.z.literal("sessions.create"),
|
|
152
157
|
requestId,
|
|
153
158
|
cwd: zod.z.string().min(1).max(4096),
|
|
154
|
-
target: target.optional()
|
|
159
|
+
target: target.optional(),
|
|
160
|
+
/*
|
|
161
|
+
* OMITTED when the user never picked anything, so the body is the one
|
|
162
|
+
* this op sent before the draft's chips could open: making them
|
|
163
|
+
* actionable is strictly additive, and a `null` here would be a
|
|
164
|
+
* different request for every caller that never asked.
|
|
165
|
+
*/
|
|
166
|
+
model: modelSelection.optional()
|
|
155
167
|
}).strict(),
|
|
156
168
|
/*
|
|
157
169
|
* What a NEW conversation's readings would be, without creating anything.
|
|
@@ -168,7 +180,9 @@ const desktopRequestSchema = zod.z.discriminatedUnion("op", [
|
|
|
168
180
|
* disagree with the session the first send creates.
|
|
169
181
|
*
|
|
170
182
|
* Body and response mirror `sessions.create` deliberately: same `cwd`, same
|
|
171
|
-
* optional `target`, same 422 for an unresolvable profile
|
|
183
|
+
* optional `target`, same `model` and same 422 for an unresolvable profile —
|
|
184
|
+
* the pane is asking the question it will ask for real on the first send, so
|
|
185
|
+
* the two bodies are derived from one selection. The response is a
|
|
172
186
|
* `CanonicalFrontendSync` — the wire shape `sessions.watch` streams — whose
|
|
173
187
|
* `snapshot.session_id` is EMPTY, because there is no session. The renderer
|
|
174
188
|
* passes it to the strip and never into the canonical sessions store.
|
|
@@ -177,7 +191,11 @@ const desktopRequestSchema = zod.z.discriminatedUnion("op", [
|
|
|
177
191
|
op: zod.z.literal("sessions.preview"),
|
|
178
192
|
requestId,
|
|
179
193
|
cwd: zod.z.string().min(1).max(4096),
|
|
180
|
-
target: target.optional()
|
|
194
|
+
target: target.optional(),
|
|
195
|
+
/* Present only when the pane's chips were used: the preview then answers
|
|
196
|
+
the reading the CHOSEN model gives, which is the ladder and window the
|
|
197
|
+
first turn will actually get. */
|
|
198
|
+
model: modelSelection.optional()
|
|
181
199
|
}).strict(),
|
|
182
200
|
zod.z.object({ op: zod.z.literal("sessions.get"), sessionId }).strict(),
|
|
183
201
|
zod.z.object({
|
|
@@ -410,6 +428,22 @@ const desktopRequestSchema = zod.z.discriminatedUnion("op", [
|
|
|
410
428
|
untilMs: zod.z.number().int().nonnegative().optional(),
|
|
411
429
|
days: zod.z.number().int().min(1).max(366).optional()
|
|
412
430
|
}).strict(),
|
|
431
|
+
/*
|
|
432
|
+
* The two diagnostics reads. They ride their own capability key
|
|
433
|
+
* (`diagnostics`) rather than the catalogue one, because `/analytics` and
|
|
434
|
+
* `/failovers` must keep working against a backend that lacks these routes.
|
|
435
|
+
*/
|
|
436
|
+
zod.z.object({ op: zod.z.literal("info.get") }).strict(),
|
|
437
|
+
zod.z.object({
|
|
438
|
+
op: zod.z.literal("sessions.report"),
|
|
439
|
+
sessionId,
|
|
440
|
+
/*
|
|
441
|
+
* 0..50, matching the route's own clamp. The client always sends it:
|
|
442
|
+
* the number of rows the panel draws is a design decision made here, and
|
|
443
|
+
* inheriting the route's default would let the two drift apart.
|
|
444
|
+
*/
|
|
445
|
+
recentLimit: zod.z.number().int().min(0).max(50).optional()
|
|
446
|
+
}).strict(),
|
|
413
447
|
zod.z.object({ op: zod.z.literal("skills.list"), sessionId, name: id$1.optional() }).strict(),
|
|
414
448
|
zod.z.object({ op: zod.z.literal("sessions.failovers"), sessionId }).strict(),
|
|
415
449
|
zod.z.object({
|
|
@@ -665,7 +699,8 @@ function desktopEndpoint(request) {
|
|
|
665
699
|
body: {
|
|
666
700
|
request_id: request.requestId,
|
|
667
701
|
cwd: request.cwd,
|
|
668
|
-
...request.target ? { target: request.target } : {}
|
|
702
|
+
...request.target ? { target: request.target } : {},
|
|
703
|
+
...request.model ? { model: request.model } : {}
|
|
669
704
|
}
|
|
670
705
|
};
|
|
671
706
|
case "sessions.preview":
|
|
@@ -675,7 +710,8 @@ function desktopEndpoint(request) {
|
|
|
675
710
|
body: {
|
|
676
711
|
request_id: request.requestId,
|
|
677
712
|
cwd: request.cwd,
|
|
678
|
-
...request.target ? { target: request.target } : {}
|
|
713
|
+
...request.target ? { target: request.target } : {},
|
|
714
|
+
...request.model ? { model: request.model } : {}
|
|
679
715
|
}
|
|
680
716
|
};
|
|
681
717
|
case "sessions.get":
|
|
@@ -940,6 +976,17 @@ function desktopEndpoint(request) {
|
|
|
940
976
|
query.set("until_ms", String(request.untilMs));
|
|
941
977
|
return { path: `/v1/desktop/analytics?${query}`, method: "GET" };
|
|
942
978
|
}
|
|
979
|
+
case "info.get":
|
|
980
|
+
return { path: "/v1/desktop/info", method: "GET" };
|
|
981
|
+
case "sessions.report": {
|
|
982
|
+
const query = new URLSearchParams({
|
|
983
|
+
recent_limit: String(request.recentLimit ?? 12)
|
|
984
|
+
});
|
|
985
|
+
return {
|
|
986
|
+
path: `/v1/desktop/sessions/${request.sessionId}/report?${query}`,
|
|
987
|
+
method: "GET"
|
|
988
|
+
};
|
|
989
|
+
}
|
|
943
990
|
case "skills.list":
|
|
944
991
|
return {
|
|
945
992
|
path: `/v1/desktop/skills?session_id=${request.sessionId}${request.name ? `&name=${encodeURIComponent(request.name)}` : ""}`,
|
|
@@ -1801,6 +1848,268 @@ const backendConfig = loadConfig();
|
|
|
1801
1848
|
const apiConfig = {
|
|
1802
1849
|
baseUrl: backendConfig.VITE_LOCAL_OPERATOR_API_URL
|
|
1803
1850
|
};
|
|
1851
|
+
const SHEBANG = /^#!([^\r\n]+)\r?\n/;
|
|
1852
|
+
const PYTHON_NAME = /[/\\]python(?:\d+(?:\.\d+)*)?$/;
|
|
1853
|
+
const SERVE_ENTRYPOINT = "from local_operator.cli import main; main()";
|
|
1854
|
+
const PROBE_SCRIPT = "import json, sys; from local_operator.cli import main; print(json.dumps([sys.executable, getattr(sys, '_base_executable', None) or sys.executable, callable(main), [p for p in sys.path if p and p.startswith(sys.prefix)]]))";
|
|
1855
|
+
const DEFAULT_BUDGET = {
|
|
1856
|
+
totalMs: 45e3,
|
|
1857
|
+
attemptMs: 3e4,
|
|
1858
|
+
graceMs: 2e3,
|
|
1859
|
+
slackMs: 2e3
|
|
1860
|
+
};
|
|
1861
|
+
const DISCOVERY_TIMEOUT_MS = 5e3;
|
|
1862
|
+
const INTERPRETER_RESOLUTION_WORST_MS = DEFAULT_BUDGET.totalMs + 2 * (DISCOVERY_TIMEOUT_MS + DEFAULT_BUDGET.graceMs + DEFAULT_BUDGET.slackMs);
|
|
1863
|
+
class ProbeTimeout extends Error {
|
|
1864
|
+
constructor(interpreter, timeoutMs) {
|
|
1865
|
+
super(
|
|
1866
|
+
`${interpreter} did not answer an identity probe within ${timeoutMs} ms`
|
|
1867
|
+
);
|
|
1868
|
+
this.name = "ProbeTimeout";
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
const describe = (error) => error instanceof Error ? error.message : String(error);
|
|
1872
|
+
function runBounded(command, args, env, bounds) {
|
|
1873
|
+
return new Promise((resolve, reject) => {
|
|
1874
|
+
const child = node_child_process.spawn(command, args, {
|
|
1875
|
+
env,
|
|
1876
|
+
// Piped, so the answer is read rather than inherited by the app.
|
|
1877
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1878
|
+
windowsHide: true
|
|
1879
|
+
});
|
|
1880
|
+
let stdout = "";
|
|
1881
|
+
let stderr = "";
|
|
1882
|
+
child.stdout?.on("data", (chunk) => {
|
|
1883
|
+
stdout += chunk.toString();
|
|
1884
|
+
});
|
|
1885
|
+
child.stderr?.on("data", (chunk) => {
|
|
1886
|
+
stderr += chunk.toString();
|
|
1887
|
+
});
|
|
1888
|
+
let settled = false;
|
|
1889
|
+
let timedOut = false;
|
|
1890
|
+
const timers = [];
|
|
1891
|
+
const settle2 = (finish) => {
|
|
1892
|
+
if (settled) return;
|
|
1893
|
+
settled = true;
|
|
1894
|
+
for (const timer of timers) clearTimeout(timer);
|
|
1895
|
+
timers.length = 0;
|
|
1896
|
+
finish();
|
|
1897
|
+
};
|
|
1898
|
+
timers.push(
|
|
1899
|
+
setTimeout(() => {
|
|
1900
|
+
timedOut = true;
|
|
1901
|
+
child.kill("SIGTERM");
|
|
1902
|
+
timers.push(setTimeout(() => child.kill("SIGKILL"), bounds.graceMs));
|
|
1903
|
+
timers.push(
|
|
1904
|
+
setTimeout(
|
|
1905
|
+
() => settle2(() => reject(new ProbeTimeout(command, bounds.timeoutMs))),
|
|
1906
|
+
bounds.graceMs + bounds.slackMs
|
|
1907
|
+
)
|
|
1908
|
+
);
|
|
1909
|
+
}, bounds.timeoutMs)
|
|
1910
|
+
);
|
|
1911
|
+
child.on("error", (error) => settle2(() => reject(error)));
|
|
1912
|
+
child.on(
|
|
1913
|
+
"close",
|
|
1914
|
+
(code, signal) => settle2(() => {
|
|
1915
|
+
if (timedOut) {
|
|
1916
|
+
reject(new ProbeTimeout(command, bounds.timeoutMs));
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
if (code === 0) {
|
|
1920
|
+
resolve(stdout);
|
|
1921
|
+
return;
|
|
1922
|
+
}
|
|
1923
|
+
const detail = errorTail(stderr);
|
|
1924
|
+
reject(
|
|
1925
|
+
new Error(
|
|
1926
|
+
`exited with code ${code ?? "null"}${signal ? ` (${signal})` : ""}${detail ? `: ${detail}` : ""}`
|
|
1927
|
+
)
|
|
1928
|
+
);
|
|
1929
|
+
})
|
|
1930
|
+
);
|
|
1931
|
+
});
|
|
1932
|
+
}
|
|
1933
|
+
const errorTail = (text, lines = 3) => {
|
|
1934
|
+
const kept = text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
1935
|
+
if (kept.length === 0) return "";
|
|
1936
|
+
const tail = kept.slice(-lines).join(" | ");
|
|
1937
|
+
return kept.length > lines ? `… ${tail}` : tail;
|
|
1938
|
+
};
|
|
1939
|
+
function parseIdentity(stdout, interpreter) {
|
|
1940
|
+
const parsed = JSON.parse(stdout.trim());
|
|
1941
|
+
const [executable, baseExecutable, callable, prefixPaths] = parsed;
|
|
1942
|
+
if (typeof executable !== "string" || typeof callable !== "boolean")
|
|
1943
|
+
throw new Error(`${interpreter} reported no usable identity`);
|
|
1944
|
+
return {
|
|
1945
|
+
executable,
|
|
1946
|
+
baseExecutable: baseExecutable || executable,
|
|
1947
|
+
callable,
|
|
1948
|
+
prefixPaths: Array.isArray(prefixPaths) ? prefixPaths : []
|
|
1949
|
+
};
|
|
1950
|
+
}
|
|
1951
|
+
async function probeOnce(interpreter, env, timeoutMs, bounds) {
|
|
1952
|
+
return parseIdentity(
|
|
1953
|
+
await runBounded(interpreter, ["-c", PROBE_SCRIPT], env, {
|
|
1954
|
+
...bounds,
|
|
1955
|
+
timeoutMs
|
|
1956
|
+
}),
|
|
1957
|
+
interpreter
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
async function probeWithin(interpreter, env, deadline2, bounds) {
|
|
1961
|
+
let lastTimeout = null;
|
|
1962
|
+
for (let attempt = 1; ; attempt++) {
|
|
1963
|
+
const remaining = deadline2 - Date.now() - bounds.graceMs - bounds.slackMs;
|
|
1964
|
+
if (remaining <= 0) {
|
|
1965
|
+
if (lastTimeout) throw lastTimeout;
|
|
1966
|
+
throw new Error(
|
|
1967
|
+
`the ${bounds.totalMs} ms interpreter-probe budget ran out before ${interpreter} answered`
|
|
1968
|
+
);
|
|
1969
|
+
}
|
|
1970
|
+
try {
|
|
1971
|
+
return await probeOnce(
|
|
1972
|
+
interpreter,
|
|
1973
|
+
env,
|
|
1974
|
+
Math.min(bounds.attemptMs, remaining),
|
|
1975
|
+
bounds
|
|
1976
|
+
);
|
|
1977
|
+
} catch (error) {
|
|
1978
|
+
if (error instanceof ProbeTimeout) {
|
|
1979
|
+
lastTimeout = error;
|
|
1980
|
+
if (attempt < PROBE_ATTEMPTS && Date.now() < deadline2) continue;
|
|
1981
|
+
}
|
|
1982
|
+
throw error;
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
const PROBE_ATTEMPTS = 2;
|
|
1987
|
+
async function planFor(identity, interpreter, port, env, platform, deadline2, bounds) {
|
|
1988
|
+
if (!identity.callable || !path$1.isAbsolute(identity.executable))
|
|
1989
|
+
throw new Error(
|
|
1990
|
+
`the CLI entrypoint does not import in ${identity.executable || interpreter}`
|
|
1991
|
+
);
|
|
1992
|
+
const args = ["-c", SERVE_ENTRYPOINT, "serve", "--port", String(port)];
|
|
1993
|
+
if (platform !== "win32")
|
|
1994
|
+
return {
|
|
1995
|
+
command: "bash",
|
|
1996
|
+
args: ["-c", 'exec "$@"', "owned-serve", identity.executable, ...args],
|
|
1997
|
+
env
|
|
1998
|
+
};
|
|
1999
|
+
if (identity.executable.toLowerCase() === identity.baseExecutable.toLowerCase())
|
|
2000
|
+
return { command: identity.executable, args, env };
|
|
2001
|
+
if (!path$1.isAbsolute(identity.baseExecutable))
|
|
2002
|
+
throw new Error(
|
|
2003
|
+
`it is a venv redirector whose base interpreter is not an absolute path (${identity.baseExecutable || "nothing"})`
|
|
2004
|
+
);
|
|
2005
|
+
const baseEnv = {
|
|
2006
|
+
...env,
|
|
2007
|
+
// Windows' own separator, deliberately independent of the host evaluating
|
|
2008
|
+
// the plan: the plan describes the Windows launch, not the machine that
|
|
2009
|
+
// built it, and the test host is not Windows.
|
|
2010
|
+
PYTHONPATH: [...identity.prefixPaths, env.PYTHONPATH].filter(Boolean).join(";")
|
|
2011
|
+
};
|
|
2012
|
+
const base = await probeWithin(
|
|
2013
|
+
identity.baseExecutable,
|
|
2014
|
+
baseEnv,
|
|
2015
|
+
deadline2,
|
|
2016
|
+
bounds
|
|
2017
|
+
);
|
|
2018
|
+
if (!base.callable || base.executable.toLowerCase() !== identity.baseExecutable.toLowerCase())
|
|
2019
|
+
throw new Error(
|
|
2020
|
+
`its base interpreter ${identity.baseExecutable} is not the serving process (${base.callable ? `it reported itself as ${base.executable || "nothing"}` : "it cannot import local_operator.cli even with the venv's own import paths"})`
|
|
2021
|
+
);
|
|
2022
|
+
return { command: identity.baseExecutable, args, env: baseEnv };
|
|
2023
|
+
}
|
|
2024
|
+
async function ownedServeLaunch(interpreters, port, env, platform = process.platform, budget = {}, fallbackClaims) {
|
|
2025
|
+
const bounds = {
|
|
2026
|
+
...DEFAULT_BUDGET,
|
|
2027
|
+
...budget
|
|
2028
|
+
};
|
|
2029
|
+
const deadline2 = Date.now() + bounds.totalMs;
|
|
2030
|
+
const rejected = [];
|
|
2031
|
+
const attempt = async (claims) => {
|
|
2032
|
+
for (const interpreter of [...new Set(claims)]) {
|
|
2033
|
+
if (!path$1.isAbsolute(interpreter)) {
|
|
2034
|
+
rejected.push(`${interpreter || "(empty)"}: not an absolute path`);
|
|
2035
|
+
continue;
|
|
2036
|
+
}
|
|
2037
|
+
try {
|
|
2038
|
+
const identity = await probeWithin(interpreter, env, deadline2, bounds);
|
|
2039
|
+
return await planFor(
|
|
2040
|
+
identity,
|
|
2041
|
+
interpreter,
|
|
2042
|
+
port,
|
|
2043
|
+
env,
|
|
2044
|
+
platform,
|
|
2045
|
+
deadline2,
|
|
2046
|
+
bounds
|
|
2047
|
+
);
|
|
2048
|
+
} catch (error) {
|
|
2049
|
+
rejected.push(`${interpreter}: ${describe(error)}`);
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
return null;
|
|
2053
|
+
};
|
|
2054
|
+
if (interpreters.length === 0 && !fallbackClaims)
|
|
2055
|
+
throw new Error(
|
|
2056
|
+
"No backend interpreter was resolved. Install the Local Operator backend (`uv tool install local-operator`) or pair an external backend."
|
|
2057
|
+
);
|
|
2058
|
+
const planned = await attempt(interpreters) ?? (fallbackClaims ? await attempt(await fallbackClaims()) : null);
|
|
2059
|
+
if (planned) return planned;
|
|
2060
|
+
throw new Error(
|
|
2061
|
+
`No backend interpreter could be proven. Tried ${rejected.length}: ${rejected.join("; ")}. Install the backend with a supported installer (\`uv tool install local-operator\`) or pair an external backend.`
|
|
2062
|
+
);
|
|
2063
|
+
}
|
|
2064
|
+
async function firstLine(command, args, env) {
|
|
2065
|
+
try {
|
|
2066
|
+
const stdout = await runBounded(command, args, env, {
|
|
2067
|
+
...DEFAULT_BUDGET,
|
|
2068
|
+
timeoutMs: DISCOVERY_TIMEOUT_MS
|
|
2069
|
+
});
|
|
2070
|
+
const line = stdout.trim().split(/\r?\n/)[0]?.trim();
|
|
2071
|
+
return line ? line : null;
|
|
2072
|
+
} catch {
|
|
2073
|
+
return null;
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
async function windowsInterpreterCandidates(consolePath, env) {
|
|
2077
|
+
const directory = path$1.dirname(consolePath);
|
|
2078
|
+
const tool = path$1.basename(consolePath).replace(/\.(exe|cmd|bat)$/i, "");
|
|
2079
|
+
const candidates = [path$1.join(directory, "python.exe")];
|
|
2080
|
+
const uvTools = env.UV_TOOL_DIR ?? (env.APPDATA ? path$1.join(env.APPDATA, "uv", "tools") : null);
|
|
2081
|
+
if (uvTools) candidates.push(path$1.join(uvTools, tool, "Scripts", "python.exe"));
|
|
2082
|
+
const pipxHome = env.PIPX_HOME ?? (env.LOCALAPPDATA ? path$1.join(env.LOCALAPPDATA, "pipx") : null) ?? (env.USERPROFILE ? path$1.join(env.USERPROFILE, "pipx") : null);
|
|
2083
|
+
if (pipxHome)
|
|
2084
|
+
candidates.push(path$1.join(pipxHome, "venvs", tool, "Scripts", "python.exe"));
|
|
2085
|
+
return [...new Set(candidates)].filter(
|
|
2086
|
+
(candidate) => path$1.isAbsolute(candidate) && fs.existsSync(candidate)
|
|
2087
|
+
);
|
|
2088
|
+
}
|
|
2089
|
+
async function windowsPathInterpreterCandidates(env) {
|
|
2090
|
+
const found = [];
|
|
2091
|
+
const onPath = await firstLine("where", ["python.exe"], env);
|
|
2092
|
+
if (onPath) found.push(onPath);
|
|
2093
|
+
const viaLauncher = await firstLine(
|
|
2094
|
+
"py",
|
|
2095
|
+
["-3", "-c", "import sys; print(sys.executable)"],
|
|
2096
|
+
env
|
|
2097
|
+
);
|
|
2098
|
+
if (viaLauncher) found.push(viaLauncher);
|
|
2099
|
+
return [...new Set(found)].filter(
|
|
2100
|
+
(candidate) => path$1.isAbsolute(candidate) && fs.existsSync(candidate)
|
|
2101
|
+
);
|
|
2102
|
+
}
|
|
2103
|
+
function consoleInterpreter(consolePath) {
|
|
2104
|
+
const script = fs.readFileSync(consolePath, "utf8");
|
|
2105
|
+
const shebang = SHEBANG.exec(script)?.[1];
|
|
2106
|
+
if (!shebang || !path$1.isAbsolute(shebang) || !PYTHON_NAME.test(shebang) || !script.includes("from local_operator.cli import main")) {
|
|
2107
|
+
throw new Error(
|
|
2108
|
+
"Cannot safely own this backend launcher; use a directly paired external backend"
|
|
2109
|
+
);
|
|
2110
|
+
}
|
|
2111
|
+
return shebang;
|
|
2112
|
+
}
|
|
1804
2113
|
var LocalOperatorStartupMode = /* @__PURE__ */ ((LocalOperatorStartupMode2) => {
|
|
1805
2114
|
LocalOperatorStartupMode2["EXISTING_SERVER"] = "EXISTING_SERVER";
|
|
1806
2115
|
LocalOperatorStartupMode2["GLOBAL_INSTALL"] = "GLOBAL_INSTALL";
|
|
@@ -1808,8 +2117,21 @@ var LocalOperatorStartupMode = /* @__PURE__ */ ((LocalOperatorStartupMode2) => {
|
|
|
1808
2117
|
LocalOperatorStartupMode2["NOT_STARTED"] = "NOT_STARTED";
|
|
1809
2118
|
return LocalOperatorStartupMode2;
|
|
1810
2119
|
})(LocalOperatorStartupMode || {});
|
|
2120
|
+
const CONSOLE_DISCOVERY_TIMEOUT_MS = 5e3;
|
|
2121
|
+
const CONSOLE_RESOLUTION_WORST_MS = 2 * CONSOLE_DISCOVERY_TIMEOUT_MS;
|
|
2122
|
+
const SHUTDOWN_TIMEOUT_DEFAULTS = {
|
|
2123
|
+
restart: 1e4,
|
|
2124
|
+
// 10 seconds for restart operations
|
|
2125
|
+
normal: 5e3,
|
|
2126
|
+
// 5 seconds for normal shutdowns
|
|
2127
|
+
force: 3e3
|
|
2128
|
+
// 3 seconds before force killing after SIGKILL
|
|
2129
|
+
};
|
|
2130
|
+
const OWNED_STOP_WORST_MS = SHUTDOWN_TIMEOUT_DEFAULTS.normal + SHUTDOWN_TIMEOUT_DEFAULTS.force;
|
|
2131
|
+
const READINESS_POLL_INTERVAL_MS = 1e3;
|
|
1811
2132
|
const execPromise = node_util.promisify(node_child_process.exec);
|
|
1812
2133
|
const ENV_VAR_REGEX = /^([^=]+)=(.*)$/;
|
|
2134
|
+
const LINE_BREAK = /\r?\n/;
|
|
1813
2135
|
class BackendServiceManager {
|
|
1814
2136
|
process = null;
|
|
1815
2137
|
isRunning = false;
|
|
@@ -1821,8 +2143,18 @@ class BackendServiceManager {
|
|
|
1821
2143
|
appDataPath = electron.app.getPath("userData");
|
|
1822
2144
|
venvPath;
|
|
1823
2145
|
healthCheckInterval = null;
|
|
1824
|
-
|
|
1825
|
-
|
|
2146
|
+
/** The only process this manager may terminate. Null means it owns nothing,
|
|
2147
|
+
* which is a reason to report "nothing to stop" - never to go looking. */
|
|
2148
|
+
ownedServe = null;
|
|
2149
|
+
/** In-flight start, so a stop can await the resolver/readiness work that has
|
|
2150
|
+
* not yet produced a child. Without it, cleanup can return before a spawn
|
|
2151
|
+
* that was already committed, and the caller installs over a live serve. */
|
|
2152
|
+
startPromise = null;
|
|
2153
|
+
restartPromise = null;
|
|
2154
|
+
/** Bumped by every stop. A start that began under an older epoch cannot
|
|
2155
|
+
* report success or adopt its child: the cancellation happened after it
|
|
2156
|
+
* checked, and this is what it re-checks across each await. */
|
|
2157
|
+
startEpoch = 0;
|
|
1826
2158
|
shellEnv = {};
|
|
1827
2159
|
// External/dev backends may be explicitly paired through main's environment.
|
|
1828
2160
|
// Managed starts always rotate this; it is never exposed by preload or logs.
|
|
@@ -1925,14 +2257,7 @@ class BackendServiceManager {
|
|
|
1925
2257
|
// Flag to track when the app is being closed
|
|
1926
2258
|
isAutoUpdating = false;
|
|
1927
2259
|
// Flag to track when an autoupdate is in progress
|
|
1928
|
-
shutdownTimeoutMs = {
|
|
1929
|
-
restart: 1e4,
|
|
1930
|
-
// 10 seconds for restart operations
|
|
1931
|
-
normal: 5e3,
|
|
1932
|
-
// 5 seconds for normal shutdowns
|
|
1933
|
-
force: 3e3
|
|
1934
|
-
// 3 seconds before force killing after SIGKILL
|
|
1935
|
-
};
|
|
2260
|
+
shutdownTimeoutMs = { ...SHUTDOWN_TIMEOUT_DEFAULTS };
|
|
1936
2261
|
// Configurable timeouts for different shutdown scenarios
|
|
1937
2262
|
/**
|
|
1938
2263
|
* Constructor
|
|
@@ -2219,7 +2544,12 @@ class BackendServiceManager {
|
|
|
2219
2544
|
`Checking if local-operator command exists: ${command}`,
|
|
2220
2545
|
LogFileType.BACKEND
|
|
2221
2546
|
);
|
|
2222
|
-
const { stdout } = await execPromise(command
|
|
2547
|
+
const { stdout } = await execPromise(command, {
|
|
2548
|
+
// Bounded: a quit that arrives mid-start waits on this same path, and an
|
|
2549
|
+
// unbounded child here is a wait with nothing underneath it.
|
|
2550
|
+
timeout: CONSOLE_DISCOVERY_TIMEOUT_MS,
|
|
2551
|
+
windowsHide: true
|
|
2552
|
+
});
|
|
2223
2553
|
if (stdout.trim()) {
|
|
2224
2554
|
logger.info(
|
|
2225
2555
|
`local-operator command found at: ${stdout.trim()}`,
|
|
@@ -2347,12 +2677,30 @@ class BackendServiceManager {
|
|
|
2347
2677
|
}
|
|
2348
2678
|
return false;
|
|
2349
2679
|
}
|
|
2680
|
+
/** Keep PATH discovery authoritative; `ownedServeLaunch` proves the identity
|
|
2681
|
+
* of what it found rather than trusting the name it was resolved under. */
|
|
2682
|
+
async resolveGlobalConsole(env) {
|
|
2683
|
+
const { stdout } = await execPromise(
|
|
2684
|
+
process.platform === "win32" ? "where local-operator" : "which local-operator",
|
|
2685
|
+
{ env, timeout: CONSOLE_DISCOVERY_TIMEOUT_MS }
|
|
2686
|
+
);
|
|
2687
|
+
return stdout.trim().split(LINE_BREAK)[0];
|
|
2688
|
+
}
|
|
2350
2689
|
/**
|
|
2351
2690
|
* Start the backend service
|
|
2352
2691
|
* @returns Promise resolving to true if the backend was started successfully, false otherwise
|
|
2353
2692
|
*/
|
|
2354
|
-
|
|
2355
|
-
this.isAppClosing
|
|
2693
|
+
start() {
|
|
2694
|
+
if (this.isAppClosing) return Promise.resolve(false);
|
|
2695
|
+
if (this.startPromise) return this.startPromise;
|
|
2696
|
+
this.startPromise = this.startOwned(this.startEpoch).finally(() => {
|
|
2697
|
+
this.startPromise = null;
|
|
2698
|
+
});
|
|
2699
|
+
return this.startPromise;
|
|
2700
|
+
}
|
|
2701
|
+
async startOwned(epoch) {
|
|
2702
|
+
if (this.ownedServe?.stop) return false;
|
|
2703
|
+
if (this.ownedServe) return this.isRunning;
|
|
2356
2704
|
if (this.isDisabled) {
|
|
2357
2705
|
logger.info(
|
|
2358
2706
|
"Backend Service Manager is disabled. Skipping backend start.",
|
|
@@ -2361,155 +2709,114 @@ class BackendServiceManager {
|
|
|
2361
2709
|
this.notifyBackendReady();
|
|
2362
2710
|
return true;
|
|
2363
2711
|
}
|
|
2364
|
-
|
|
2712
|
+
const existing = await this.checkExistingBackend();
|
|
2713
|
+
if (epoch !== this.startEpoch || this.isAppClosing) return false;
|
|
2714
|
+
if (existing) {
|
|
2365
2715
|
this.isRunning = true;
|
|
2366
2716
|
this.startupMode = "EXISTING_SERVER";
|
|
2367
2717
|
this.startHealthCheck();
|
|
2368
2718
|
return true;
|
|
2369
2719
|
}
|
|
2370
2720
|
this.desktopToken = node_crypto.randomBytes(32).toString("hex");
|
|
2721
|
+
let captured = null;
|
|
2371
2722
|
try {
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
);
|
|
2723
|
+
const globalInstall = await this.checkLocalOperatorExists();
|
|
2724
|
+
const env = this.backendSpawnEnv();
|
|
2725
|
+
let interpreters;
|
|
2726
|
+
if (globalInstall) {
|
|
2377
2727
|
this.startupMode = "GLOBAL_INSTALL";
|
|
2378
|
-
const
|
|
2379
|
-
|
|
2380
|
-
logger.info(
|
|
2381
|
-
`Starting backend service with global command: ${cmd} ${args.join(" ")}`,
|
|
2382
|
-
LogFileType.BACKEND
|
|
2383
|
-
);
|
|
2384
|
-
this.process = node_child_process.spawn(cmd, args, {
|
|
2385
|
-
detached: false,
|
|
2386
|
-
// Ensure process is not detached from parent
|
|
2387
|
-
stdio: "pipe",
|
|
2388
|
-
env: this.backendSpawnEnv(),
|
|
2389
|
-
// On Windows, we need to create a new process group to ensure proper termination
|
|
2390
|
-
...process.platform === "win32" ? { windowsHide: true } : {}
|
|
2391
|
-
});
|
|
2728
|
+
const executable = await this.resolveGlobalConsole(env);
|
|
2729
|
+
interpreters = process.platform === "win32" ? await windowsInterpreterCandidates(executable, env) : [consoleInterpreter(executable)];
|
|
2392
2730
|
} else {
|
|
2393
|
-
logger.info(
|
|
2394
|
-
"Global local-operator not found, using virtual environment",
|
|
2395
|
-
LogFileType.BACKEND
|
|
2396
|
-
);
|
|
2397
2731
|
this.startupMode = "APP_BUNDLED_VENV";
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
const localOperatorExe = path$1.join(
|
|
2402
|
-
this.venvPath,
|
|
2403
|
-
"Scripts",
|
|
2404
|
-
"local-operator.exe"
|
|
2405
|
-
);
|
|
2406
|
-
if (fs.existsSync(localOperatorExe)) {
|
|
2407
|
-
cmd = localOperatorExe;
|
|
2408
|
-
args = ["serve", "--port", this.port.toString()];
|
|
2409
|
-
} else {
|
|
2410
|
-
const pythonExe = path$1.join(this.venvPath, "Scripts", "python.exe");
|
|
2411
|
-
if (fs.existsSync(pythonExe)) {
|
|
2412
|
-
cmd = pythonExe;
|
|
2413
|
-
args = [
|
|
2414
|
-
"-m",
|
|
2415
|
-
"local_operator",
|
|
2416
|
-
"serve",
|
|
2417
|
-
"--port",
|
|
2418
|
-
this.port.toString()
|
|
2419
|
-
];
|
|
2420
|
-
} else {
|
|
2421
|
-
const activateScript = path$1.join(
|
|
2422
|
-
this.venvPath,
|
|
2423
|
-
"Scripts",
|
|
2424
|
-
"Activate.ps1"
|
|
2425
|
-
);
|
|
2426
|
-
cmd = "powershell.exe";
|
|
2427
|
-
args = [
|
|
2428
|
-
"-ExecutionPolicy",
|
|
2429
|
-
"Bypass",
|
|
2430
|
-
"-Command",
|
|
2431
|
-
`"& '${activateScript}'; local-operator serve --port ${this.port}"`
|
|
2432
|
-
];
|
|
2433
|
-
}
|
|
2434
|
-
}
|
|
2435
|
-
} else {
|
|
2436
|
-
const activateScript = path$1.join(this.venvPath, "bin", "activate");
|
|
2437
|
-
cmd = "bash";
|
|
2438
|
-
args = [
|
|
2439
|
-
"-c",
|
|
2440
|
-
`. "${activateScript}" && local-operator serve --port ${this.port}`
|
|
2441
|
-
];
|
|
2442
|
-
}
|
|
2443
|
-
logger.info(
|
|
2444
|
-
`Starting backend service with venv: ${cmd} ${args.join(" ")}`,
|
|
2445
|
-
LogFileType.BACKEND
|
|
2732
|
+
const bin = path$1.join(
|
|
2733
|
+
this.venvPath,
|
|
2734
|
+
process.platform === "win32" ? "Scripts" : "bin"
|
|
2446
2735
|
);
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2736
|
+
interpreters = [
|
|
2737
|
+
path$1.join(bin, process.platform === "win32" ? "python.exe" : "python")
|
|
2738
|
+
];
|
|
2739
|
+
env.VIRTUAL_ENV = this.venvPath;
|
|
2740
|
+
env.PATH = `${bin}${process.platform === "win32" ? ";" : ":"}${env.PATH ?? ""}`;
|
|
2741
|
+
env.PYTHONHOME = void 0;
|
|
2742
|
+
}
|
|
2743
|
+
const launch = await ownedServeLaunch(
|
|
2744
|
+
interpreters,
|
|
2745
|
+
this.port,
|
|
2746
|
+
env,
|
|
2747
|
+
process.platform,
|
|
2748
|
+
{},
|
|
2749
|
+
// The PATH-side claims spawn discovery children, so they are offered
|
|
2750
|
+
// only after the claims above have all failed (round 3, F14).
|
|
2751
|
+
process.platform === "win32" ? () => windowsPathInterpreterCandidates(env) : void 0
|
|
2752
|
+
);
|
|
2753
|
+
if (epoch !== this.startEpoch || this.isAppClosing) return false;
|
|
2754
|
+
const child = node_child_process.spawn(launch.command, launch.args, {
|
|
2755
|
+
detached: false,
|
|
2756
|
+
stdio: "pipe",
|
|
2757
|
+
// The plan owns the environment it proved: a Windows venv's base
|
|
2758
|
+
// interpreter needs the venv's import paths, added there and not here.
|
|
2759
|
+
env: launch.env,
|
|
2760
|
+
windowsHide: true
|
|
2761
|
+
});
|
|
2762
|
+
const generation = this.captureServe(child);
|
|
2763
|
+
captured = generation;
|
|
2764
|
+
if (child.stdout) {
|
|
2765
|
+
child.stdout.on("data", (data) => {
|
|
2458
2766
|
logger.info(`Backend stdout: ${data}`, LogFileType.BACKEND);
|
|
2459
2767
|
});
|
|
2460
2768
|
}
|
|
2461
|
-
if (
|
|
2462
|
-
|
|
2769
|
+
if (child.stderr) {
|
|
2770
|
+
child.stderr.on("data", (data) => {
|
|
2463
2771
|
logger.error(`Backend stderr: ${data}`, LogFileType.BACKEND);
|
|
2464
2772
|
});
|
|
2465
2773
|
}
|
|
2466
|
-
this.process.on("exit", (code) => {
|
|
2467
|
-
logger.info(
|
|
2468
|
-
`Backend process exited with code ${code}`,
|
|
2469
|
-
LogFileType.BACKEND
|
|
2470
|
-
);
|
|
2471
|
-
this.isRunning = false;
|
|
2472
|
-
this.process = null;
|
|
2473
|
-
if (this.exitResolve) {
|
|
2474
|
-
this.exitResolve();
|
|
2475
|
-
this.exitResolve = null;
|
|
2476
|
-
}
|
|
2477
|
-
const isExpectedWindowsExit = process.platform === "win32" && (this.isAppClosing || this.isAutoUpdating) && code === 1;
|
|
2478
|
-
if (code !== 0 && code !== null && !isExpectedWindowsExit) {
|
|
2479
|
-
electron.dialog.showErrorBox(
|
|
2480
|
-
"Backend Error",
|
|
2481
|
-
`The Local Operator backend service exited unexpectedly with code ${code}. Please restart the application.`
|
|
2482
|
-
);
|
|
2483
|
-
}
|
|
2484
|
-
});
|
|
2485
2774
|
let attempts = 0;
|
|
2486
2775
|
const maxAttempts = 30;
|
|
2487
2776
|
while (attempts < maxAttempts) {
|
|
2488
|
-
|
|
2777
|
+
const healthy = await this.checkHealth();
|
|
2778
|
+
if (epoch !== this.startEpoch || generation.exited || generation.stop)
|
|
2779
|
+
break;
|
|
2780
|
+
if (healthy) {
|
|
2489
2781
|
this.isRunning = true;
|
|
2490
2782
|
this.startHealthCheck();
|
|
2491
2783
|
this.notifyBackendReady();
|
|
2492
2784
|
return true;
|
|
2493
2785
|
}
|
|
2494
|
-
await new Promise(
|
|
2786
|
+
await new Promise(
|
|
2787
|
+
(resolve) => setTimeout(resolve, READINESS_POLL_INTERVAL_MS)
|
|
2788
|
+
);
|
|
2495
2789
|
attempts++;
|
|
2496
2790
|
}
|
|
2791
|
+
await this.stopGeneration(generation, false);
|
|
2792
|
+
if (epoch !== this.startEpoch) return false;
|
|
2497
2793
|
logger.error(
|
|
2498
2794
|
"Failed to start backend service after multiple attempts",
|
|
2499
2795
|
LogFileType.BACKEND
|
|
2500
2796
|
);
|
|
2501
|
-
|
|
2797
|
+
this.reportStartFailure(
|
|
2502
2798
|
"Backend Error",
|
|
2503
2799
|
"Failed to start the Local Operator backend service. Please check the logs for more information."
|
|
2504
2800
|
);
|
|
2505
2801
|
return false;
|
|
2506
2802
|
} catch (error) {
|
|
2803
|
+
if (captured) {
|
|
2804
|
+
try {
|
|
2805
|
+
await this.stopGeneration(captured, false);
|
|
2806
|
+
} catch (cleanupError) {
|
|
2807
|
+
logger.error(
|
|
2808
|
+
"Owned backend cleanup after a failed start did not confirm exit",
|
|
2809
|
+
LogFileType.BACKEND,
|
|
2810
|
+
cleanupError
|
|
2811
|
+
);
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2507
2814
|
logger.error(
|
|
2508
2815
|
"Error starting backend service:",
|
|
2509
2816
|
LogFileType.BACKEND,
|
|
2510
2817
|
error
|
|
2511
2818
|
);
|
|
2512
|
-
|
|
2819
|
+
this.reportStartFailure(
|
|
2513
2820
|
"Backend Error",
|
|
2514
2821
|
`Error starting the Local Operator backend service: ${error}`
|
|
2515
2822
|
);
|
|
@@ -2517,232 +2824,156 @@ class BackendServiceManager {
|
|
|
2517
2824
|
}
|
|
2518
2825
|
}
|
|
2519
2826
|
/**
|
|
2520
|
-
* Stop the
|
|
2521
|
-
*
|
|
2522
|
-
* @returns Promise resolving when the backend has been stopped
|
|
2827
|
+
* Stop only the captured serve generation, including failed startups. A port
|
|
2828
|
+
* or process name is not ownership. Unconfirmed exit blocks replacement.
|
|
2523
2829
|
*/
|
|
2524
2830
|
async stop(isRestart = false) {
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
}
|
|
2831
|
+
this.startEpoch++;
|
|
2832
|
+
if (!isRestart) this.isAppClosing = true;
|
|
2528
2833
|
this.disposeStreamRelay();
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2834
|
+
this.stopHealthCheck();
|
|
2835
|
+
const generation = this.ownedServe;
|
|
2836
|
+
if (generation) await this.stopGeneration(generation, isRestart);
|
|
2837
|
+
await this.startPromise;
|
|
2838
|
+
}
|
|
2839
|
+
captureServe(child) {
|
|
2840
|
+
let resolveExit = () => {
|
|
2841
|
+
};
|
|
2842
|
+
const generation = {
|
|
2843
|
+
child,
|
|
2844
|
+
exited: false,
|
|
2845
|
+
exit: new Promise((resolve) => {
|
|
2846
|
+
resolveExit = resolve;
|
|
2847
|
+
}),
|
|
2848
|
+
resolveExit: () => resolveExit(),
|
|
2849
|
+
stop: null,
|
|
2850
|
+
timers: /* @__PURE__ */ new Set()
|
|
2851
|
+
};
|
|
2852
|
+
this.ownedServe = generation;
|
|
2853
|
+
this.process = child;
|
|
2854
|
+
const exited = (code) => {
|
|
2855
|
+
if (generation.exited) return;
|
|
2856
|
+
generation.exited = true;
|
|
2857
|
+
for (const timer of generation.timers) clearTimeout(timer);
|
|
2858
|
+
generation.timers.clear();
|
|
2859
|
+
generation.resolveExit();
|
|
2860
|
+
if (this.ownedServe !== generation) return;
|
|
2861
|
+
this.ownedServe = null;
|
|
2862
|
+
this.process = null;
|
|
2863
|
+
this.isRunning = false;
|
|
2864
|
+
if (code != null && code !== 0 && !generation.stop && !this.isAppClosing && !this.isAutoUpdating) {
|
|
2865
|
+
electron.dialog.showErrorBox(
|
|
2866
|
+
"Backend Error",
|
|
2867
|
+
`The Local Operator backend service exited unexpectedly with code ${code}. Please restart the application.`
|
|
2868
|
+
);
|
|
2869
|
+
}
|
|
2870
|
+
};
|
|
2871
|
+
child.once("exit", exited);
|
|
2872
|
+
child.on("error", (error) => {
|
|
2873
|
+
logger.error("Owned backend process error", LogFileType.BACKEND, error);
|
|
2874
|
+
if (child.pid === void 0) exited();
|
|
2875
|
+
});
|
|
2876
|
+
return generation;
|
|
2877
|
+
}
|
|
2878
|
+
/** Signals may only be sent while the handle itself still reports a live
|
|
2879
|
+
* process. Node keeps `kill()` callable on a reaped child, and on a PID the
|
|
2880
|
+
* OS has since recycled that call reaches whatever now holds the number. */
|
|
2881
|
+
canSignal(generation) {
|
|
2882
|
+
return !generation.exited && generation.child.exitCode === null && generation.child.signalCode === null;
|
|
2883
|
+
}
|
|
2884
|
+
/**
|
|
2885
|
+
* The one termination sequence: SIGTERM, wait out the grace, SIGKILL, wait
|
|
2886
|
+
* again, and throw if the process never reported exit.
|
|
2887
|
+
*
|
|
2888
|
+
* Failing rather than returning is the point. Callers use a resolved stop as
|
|
2889
|
+
* permission to replace the backend - install over it, spawn a successor - so
|
|
2890
|
+
* "we signalled it and moved on" would authorise exactly the double-serve
|
|
2891
|
+
* this class exists to prevent. An unconfirmed exit keeps ownership, and the
|
|
2892
|
+
* caller reports failure instead of proceeding.
|
|
2893
|
+
*/
|
|
2894
|
+
stopGeneration(generation, isRestart) {
|
|
2895
|
+
if (generation.stop) return generation.stop;
|
|
2896
|
+
generation.stop = (async () => {
|
|
2897
|
+
const waitForExit = (ms) => new Promise((resolve) => {
|
|
2898
|
+
if (generation.exited) {
|
|
2899
|
+
resolve(true);
|
|
2552
2900
|
return;
|
|
2553
2901
|
}
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2902
|
+
const timer = setTimeout(() => {
|
|
2903
|
+
generation.timers.delete(timer);
|
|
2904
|
+
resolve(false);
|
|
2905
|
+
}, ms);
|
|
2906
|
+
generation.timers.add(timer);
|
|
2907
|
+
void generation.exit.then(() => {
|
|
2908
|
+
clearTimeout(timer);
|
|
2909
|
+
generation.timers.delete(timer);
|
|
2910
|
+
resolve(true);
|
|
2562
2911
|
});
|
|
2563
2912
|
});
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
);
|
|
2572
|
-
node_child_process.spawn("taskkill", ["/pid", pid.toString(), "/t"]);
|
|
2573
|
-
}
|
|
2574
|
-
} else {
|
|
2575
|
-
logger.info(
|
|
2576
|
-
"Sending SIGTERM to backend process",
|
|
2577
|
-
LogFileType.BACKEND
|
|
2578
|
-
);
|
|
2579
|
-
this.process.kill("SIGTERM");
|
|
2580
|
-
}
|
|
2581
|
-
let forceKillTimeoutId = null;
|
|
2582
|
-
const timeoutPromise = new Promise((resolve) => {
|
|
2583
|
-
const timeoutMs = isRestart ? this.shutdownTimeoutMs.restart : this.shutdownTimeoutMs.normal;
|
|
2584
|
-
logger.info(
|
|
2585
|
-
`Setting shutdown timeout to ${timeoutMs}ms for ${isRestart ? "restart" : "normal"} operation`,
|
|
2586
|
-
LogFileType.BACKEND
|
|
2587
|
-
);
|
|
2588
|
-
forceKillTimeoutId = setTimeout(() => {
|
|
2589
|
-
if (this.process) {
|
|
2590
|
-
logger.info(
|
|
2591
|
-
`Backend process did not exit within ${timeoutMs}ms, force killing`,
|
|
2592
|
-
LogFileType.BACKEND
|
|
2593
|
-
);
|
|
2594
|
-
try {
|
|
2595
|
-
if (process.platform === "win32" && this.process.pid) {
|
|
2596
|
-
node_child_process.spawn("taskkill", [
|
|
2597
|
-
"/pid",
|
|
2598
|
-
this.process.pid.toString(),
|
|
2599
|
-
"/f",
|
|
2600
|
-
"/t"
|
|
2601
|
-
]);
|
|
2602
|
-
try {
|
|
2603
|
-
execPromise(
|
|
2604
|
-
'taskkill /f /im python.exe /fi "WINDOWTITLE eq *local-operator*" /t'
|
|
2605
|
-
).catch((error) => {
|
|
2606
|
-
logger.warn(
|
|
2607
|
-
"Error terminating python processes:",
|
|
2608
|
-
LogFileType.BACKEND,
|
|
2609
|
-
error
|
|
2610
|
-
);
|
|
2611
|
-
});
|
|
2612
|
-
execPromise("taskkill /f /im local-operator.exe /t").catch(
|
|
2613
|
-
(error) => {
|
|
2614
|
-
logger.warn(
|
|
2615
|
-
"Error terminating local-operator processes:",
|
|
2616
|
-
LogFileType.BACKEND,
|
|
2617
|
-
error
|
|
2618
|
-
);
|
|
2619
|
-
}
|
|
2620
|
-
);
|
|
2621
|
-
} catch (taskkillError) {
|
|
2622
|
-
logger.warn(
|
|
2623
|
-
"Error executing taskkill command:",
|
|
2624
|
-
LogFileType.BACKEND,
|
|
2625
|
-
taskkillError
|
|
2626
|
-
);
|
|
2627
|
-
}
|
|
2628
|
-
} else if (this.process) {
|
|
2629
|
-
this.process.kill("SIGKILL");
|
|
2630
|
-
if (!isRestart) {
|
|
2631
|
-
try {
|
|
2632
|
-
execPromise('pkill -f "local-operator serve"').catch(
|
|
2633
|
-
(error) => {
|
|
2634
|
-
logger.warn(
|
|
2635
|
-
"Error killing processes by pattern:",
|
|
2636
|
-
LogFileType.BACKEND,
|
|
2637
|
-
error
|
|
2638
|
-
);
|
|
2639
|
-
}
|
|
2640
|
-
);
|
|
2641
|
-
} catch (pkillError) {
|
|
2642
|
-
logger.warn(
|
|
2643
|
-
"Error executing pkill command:",
|
|
2644
|
-
LogFileType.BACKEND,
|
|
2645
|
-
pkillError
|
|
2646
|
-
);
|
|
2647
|
-
}
|
|
2648
|
-
}
|
|
2649
|
-
setTimeout(() => {
|
|
2650
|
-
if (this.process) {
|
|
2651
|
-
logger.warn(
|
|
2652
|
-
`Process still exists after SIGKILL, attempting more aggressive termination after ${this.shutdownTimeoutMs.force}ms`,
|
|
2653
|
-
LogFileType.BACKEND
|
|
2654
|
-
);
|
|
2655
|
-
try {
|
|
2656
|
-
if (!isRestart) {
|
|
2657
|
-
execPromise(
|
|
2658
|
-
'pkill -9 -f "local-operator serve"'
|
|
2659
|
-
).catch(() => {
|
|
2660
|
-
});
|
|
2661
|
-
}
|
|
2662
|
-
this.process = null;
|
|
2663
|
-
this.isRunning = false;
|
|
2664
|
-
if (this.exitResolve) {
|
|
2665
|
-
this.exitResolve();
|
|
2666
|
-
this.exitResolve = null;
|
|
2667
|
-
}
|
|
2668
|
-
} catch (finalError) {
|
|
2669
|
-
logger.error(
|
|
2670
|
-
"Error during final force kill attempt:",
|
|
2671
|
-
LogFileType.BACKEND,
|
|
2672
|
-
finalError
|
|
2673
|
-
);
|
|
2674
|
-
}
|
|
2675
|
-
}
|
|
2676
|
-
}, this.shutdownTimeoutMs.force);
|
|
2677
|
-
}
|
|
2678
|
-
} catch (error) {
|
|
2679
|
-
logger.error(
|
|
2680
|
-
"Error force killing process:",
|
|
2681
|
-
LogFileType.BACKEND,
|
|
2682
|
-
error
|
|
2683
|
-
);
|
|
2684
|
-
}
|
|
2685
|
-
this.process = null;
|
|
2686
|
-
this.isRunning = false;
|
|
2687
|
-
if (this.exitResolve) {
|
|
2688
|
-
this.exitResolve();
|
|
2689
|
-
this.exitResolve = null;
|
|
2690
|
-
}
|
|
2691
|
-
}
|
|
2692
|
-
resolve();
|
|
2693
|
-
}, timeoutMs);
|
|
2694
|
-
});
|
|
2695
|
-
await Promise.race([this.exitPromise, timeoutPromise]);
|
|
2696
|
-
if (forceKillTimeoutId) {
|
|
2697
|
-
clearTimeout(forceKillTimeoutId);
|
|
2698
|
-
forceKillTimeoutId = null;
|
|
2699
|
-
}
|
|
2700
|
-
if (!isRestart) {
|
|
2701
|
-
logger.info(
|
|
2702
|
-
"Performing additional cleanup for final shutdown",
|
|
2703
|
-
LogFileType.BACKEND
|
|
2913
|
+
if (this.canSignal(generation)) generation.child.kill("SIGTERM");
|
|
2914
|
+
const grace = isRestart ? this.shutdownTimeoutMs.restart : this.shutdownTimeoutMs.normal;
|
|
2915
|
+
if (!await waitForExit(grace)) {
|
|
2916
|
+
if (this.canSignal(generation)) generation.child.kill("SIGKILL");
|
|
2917
|
+
if (!await waitForExit(this.shutdownTimeoutMs.force)) {
|
|
2918
|
+
throw new Error(
|
|
2919
|
+
"Owned backend exit is unconfirmed; refusing replacement"
|
|
2704
2920
|
);
|
|
2705
|
-
try {
|
|
2706
|
-
if (process.platform === "win32") {
|
|
2707
|
-
await execPromise(
|
|
2708
|
-
'taskkill /f /im python.exe /fi "WINDOWTITLE eq *local-operator*" /t'
|
|
2709
|
-
).catch(() => {
|
|
2710
|
-
});
|
|
2711
|
-
await execPromise("taskkill /f /im local-operator.exe /t").catch(
|
|
2712
|
-
() => {
|
|
2713
|
-
}
|
|
2714
|
-
);
|
|
2715
|
-
} else {
|
|
2716
|
-
await execPromise('pkill -f "local-operator serve"').catch(() => {
|
|
2717
|
-
});
|
|
2718
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
2719
|
-
await execPromise('pkill -9 -f "local-operator serve"').catch(
|
|
2720
|
-
() => {
|
|
2721
|
-
}
|
|
2722
|
-
);
|
|
2723
|
-
}
|
|
2724
|
-
} catch (cleanupError) {
|
|
2725
|
-
logger.warn(
|
|
2726
|
-
"Error during additional cleanup (this may be normal if processes were already terminated):",
|
|
2727
|
-
LogFileType.BACKEND,
|
|
2728
|
-
cleanupError
|
|
2729
|
-
);
|
|
2730
|
-
}
|
|
2731
|
-
}
|
|
2732
|
-
} catch (error) {
|
|
2733
|
-
logger.error(
|
|
2734
|
-
"Error stopping backend process:",
|
|
2735
|
-
LogFileType.BACKEND,
|
|
2736
|
-
error
|
|
2737
|
-
);
|
|
2738
|
-
this.process = null;
|
|
2739
|
-
this.isRunning = false;
|
|
2740
|
-
if (this.exitResolve) {
|
|
2741
|
-
this.exitResolve();
|
|
2742
|
-
this.exitResolve = null;
|
|
2743
2921
|
}
|
|
2744
2922
|
}
|
|
2745
|
-
|
|
2923
|
+
if (!isRestart && !this.ownedServe)
|
|
2924
|
+
this.startupMode = "NOT_STARTED";
|
|
2925
|
+
logger.info("Owned backend generation stopped", LogFileType.BACKEND);
|
|
2926
|
+
})();
|
|
2927
|
+
return generation.stop;
|
|
2928
|
+
}
|
|
2929
|
+
stopHealthCheck() {
|
|
2930
|
+
if (this.healthCheckInterval) clearInterval(this.healthCheckInterval);
|
|
2931
|
+
this.healthCheckInterval = null;
|
|
2932
|
+
}
|
|
2933
|
+
/** Whether a quit may proceed. `will-quit` cannot await a listener, so it
|
|
2934
|
+
* prevents the first quit, runs cleanup, and asks this on the retry. */
|
|
2935
|
+
/** Whether a shutdown is in flight.
|
|
2936
|
+
*
|
|
2937
|
+
* `stop(false)` is terminal and is what the quit path calls, so this is the
|
|
2938
|
+
* state a caller checks before raising blocking UI it would never be able to
|
|
2939
|
+
* dismiss - `index.ts`'s start-failure paths are the callers. */
|
|
2940
|
+
isShuttingDown() {
|
|
2941
|
+
return this.isAppClosing;
|
|
2942
|
+
}
|
|
2943
|
+
/**
|
|
2944
|
+
* Report a start failure to the user - unless the app is on its way out.
|
|
2945
|
+
*
|
|
2946
|
+
* `showErrorBox` is a native modal: it parks the main thread until somebody
|
|
2947
|
+
* dismisses it, and Electron cannot run the quit it was asked for past a
|
|
2948
|
+
* parked thread. On the quit path that is not a message, it is a deadlock -
|
|
2949
|
+
* the quit has already prevented itself, the owned cleanup it waits on can
|
|
2950
|
+
* never finish, and the quit's own failsafe cannot even fire, because that is
|
|
2951
|
+
* a timer on the thread the dialog holds (review round 4, Q-20: a SIGTERM
|
|
2952
|
+
* during the first start left the app alive 50 s later with the failsafe line
|
|
2953
|
+
* never logged). A shutdown in flight logs the failure instead, where the
|
|
2954
|
+
* post-mortem finds it without the process still being up.
|
|
2955
|
+
*/
|
|
2956
|
+
reportStartFailure(title, message) {
|
|
2957
|
+
if (this.isAppClosing) {
|
|
2958
|
+
logger.error(
|
|
2959
|
+
`${title} (not shown; the app is shutting down): ${message}`,
|
|
2960
|
+
LogFileType.BACKEND
|
|
2961
|
+
);
|
|
2962
|
+
return;
|
|
2963
|
+
}
|
|
2964
|
+
electron.dialog.showErrorBox(title, message);
|
|
2965
|
+
}
|
|
2966
|
+
isOwnedCleanupComplete() {
|
|
2967
|
+
return this.isAppClosing && !this.ownedServe && !this.startPromise;
|
|
2968
|
+
}
|
|
2969
|
+
/** Synchronous exit cannot await cleanup. Canonical runtimes deliberately
|
|
2970
|
+
* outlive their HTTP server, so neither PID rediscovery nor descent is safe. */
|
|
2971
|
+
emergencyStopOwned() {
|
|
2972
|
+
this.startEpoch++;
|
|
2973
|
+
this.isAppClosing = true;
|
|
2974
|
+
const generation = this.ownedServe;
|
|
2975
|
+
if (generation && !generation.exited && generation.child.exitCode === null && generation.child.signalCode === null) {
|
|
2976
|
+
generation.child.kill("SIGKILL");
|
|
2746
2977
|
}
|
|
2747
2978
|
}
|
|
2748
2979
|
/**
|
|
@@ -2787,7 +3018,10 @@ class BackendServiceManager {
|
|
|
2787
3018
|
* assertable without waiting out a 30s interval.
|
|
2788
3019
|
*/
|
|
2789
3020
|
async checkUnhealthyBackend() {
|
|
3021
|
+
const epoch = this.startEpoch;
|
|
2790
3022
|
const isHealthy = await this.checkHealth();
|
|
3023
|
+
if (epoch !== this.startEpoch || this.isAppClosing || this.isAutoUpdating || this.isDisabled)
|
|
3024
|
+
return;
|
|
2791
3025
|
if (isHealthy) return;
|
|
2792
3026
|
logger.info("Backend health check failed", LogFileType.BACKEND);
|
|
2793
3027
|
if (this.isExternalBackend) {
|
|
@@ -2805,8 +3039,7 @@ class BackendServiceManager {
|
|
|
2805
3039
|
await this.start();
|
|
2806
3040
|
return;
|
|
2807
3041
|
}
|
|
2808
|
-
await this.
|
|
2809
|
-
await this.start();
|
|
3042
|
+
await this.restart();
|
|
2810
3043
|
}
|
|
2811
3044
|
/**
|
|
2812
3045
|
* Get the port number used by the backend service
|
|
@@ -2856,52 +3089,21 @@ class BackendServiceManager {
|
|
|
2856
3089
|
* timeouts from the stop operation don't affect the newly started process
|
|
2857
3090
|
* @returns Promise resolving to true if the restart was successful, false otherwise
|
|
2858
3091
|
*/
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
this.
|
|
2862
|
-
await this.stop(true);
|
|
2863
|
-
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
2864
|
-
if (this.process) {
|
|
2865
|
-
logger.warn(
|
|
2866
|
-
"Process still exists after stop, attempting to force terminate",
|
|
2867
|
-
LogFileType.BACKEND
|
|
2868
|
-
);
|
|
3092
|
+
restart() {
|
|
3093
|
+
if (this.restartPromise) return this.restartPromise;
|
|
3094
|
+
this.restartPromise = (async () => {
|
|
2869
3095
|
try {
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
this.process.kill("SIGKILL");
|
|
2874
|
-
}
|
|
2875
|
-
await new Promise((resolve) => {
|
|
2876
|
-
if (!this.process) {
|
|
2877
|
-
resolve(null);
|
|
2878
|
-
return;
|
|
2879
|
-
}
|
|
2880
|
-
this.process.once("exit", () => {
|
|
2881
|
-
resolve(null);
|
|
2882
|
-
});
|
|
2883
|
-
setTimeout(resolve, 1e3);
|
|
2884
|
-
});
|
|
2885
|
-
this.process = null;
|
|
2886
|
-
this.isRunning = false;
|
|
3096
|
+
await this.stop(true);
|
|
3097
|
+
if (this.isAppClosing) return false;
|
|
3098
|
+
return await this.start();
|
|
2887
3099
|
} catch (error) {
|
|
2888
|
-
logger.error(
|
|
2889
|
-
|
|
2890
|
-
LogFileType.BACKEND,
|
|
2891
|
-
error
|
|
2892
|
-
);
|
|
3100
|
+
logger.error("Backend restart refused", LogFileType.BACKEND, error);
|
|
3101
|
+
return false;
|
|
2893
3102
|
}
|
|
2894
|
-
}
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
"Backend service restarted successfully",
|
|
2899
|
-
LogFileType.BACKEND
|
|
2900
|
-
);
|
|
2901
|
-
} else {
|
|
2902
|
-
logger.error("Failed to restart backend service", LogFileType.BACKEND);
|
|
2903
|
-
}
|
|
2904
|
-
return success;
|
|
3103
|
+
})().finally(() => {
|
|
3104
|
+
this.restartPromise = null;
|
|
3105
|
+
});
|
|
3106
|
+
return this.restartPromise;
|
|
2905
3107
|
}
|
|
2906
3108
|
}
|
|
2907
3109
|
const linuxInstallScriptRaw = '#!/bin/bash\n# Local Operator Backend Installation Script for Linux\n# This script sets up a virtual environment for the Local Operator backend\n# without requiring sudo or admin privileges.\n\n# Exit on error, undefined variables, and failed pipe commands\nset -e # Exit immediately if a command exits with a non-zero status\nset -u # Error on unset variables\nset -o pipefail # Fail if any command in a pipe fails\n\n# Configuration\n# Variables APP_NAME and MIN_PYTHON_VERSION removed as they were unused\nVENV_NAME="local-operator-venv"\nAPP_DATA_DIR="${HOME}/.config/local-operator"\nVENV_PATH="${APP_DATA_DIR}/${VENV_NAME}"\nLOG_FILE="${APP_DATA_DIR}/backend-install.log"\nTIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")\n\n# Keep CPython\'s bytecode cache out of the application directory.\n#\n# Same reason as the macOS script: an interpreter writing __pycache__/*.pyc\n# beside its own stdlib sources writes into the installed tree. Linux does not\n# code-seal the app the way macOS does, so this is uniformity and hygiene here\n# rather than the load-bearing fix it is on macOS - but it is also the value a\n# standalone run of this script has to agree with, because the app and the\n# script must not disagree about where bytecode goes.\n: "${PYTHONPYCACHEPREFIX:=${APP_DATA_DIR}/python-bytecode-cache}"\nexport PYTHONPYCACHEPREFIX\n\n# Create app data directory if it doesn\'t exist\nif ! mkdir -p "${APP_DATA_DIR}"; then\n echo "ERROR: Unable to create app data directory at ${APP_DATA_DIR}"\n echo "Please check permissions and try again."\n exit 1\nfi\n\n# Handle cleanup on script exit\ncleanup() {\n # Remove any temporary files created during execution\n if [ -f "${APP_DATA_DIR}/get-pip.py" ]; then\n rm -f "${APP_DATA_DIR}/get-pip.py"\n fi\n if [ -n "${FFMPEG_TEMP_ARCHIVE:-}" ] && [ -f "${FFMPEG_TEMP_ARCHIVE}" ]; then\n log "Removing temporary FFmpeg archive: ${FFMPEG_TEMP_ARCHIVE}"\n rm -f "${FFMPEG_TEMP_ARCHIVE}"\n fi\n echo "$(date): Cleanup completed."\n}\n\n# Set trap only for manual interruption (SIGINT, SIGTERM), not normal exits\ntrap cleanup SIGINT SIGTERM\n\n\n# Start logging\nexec > >(tee -a "${LOG_FILE}") 2>&1\necho "[${TIMESTAMP}]: Starting Local Operator backend installation..."\necho "[${TIMESTAMP}]: System information: $(uname -a)"\n\n# Function to log messages with timestamp (defined later, but used by FFmpeg section)\n_log_internal() {\n local internal_timestamp\n internal_timestamp=$(date +"%Y-%m-%d %H:%M:%S")\n echo "[${internal_timestamp}] $1"\n}\n\n# --- FFmpeg Installation ---\nBIN_DIR="${APP_DATA_DIR}/bin"\nFFMPEG_BIN="${BIN_DIR}/ffmpeg" # Path to ffmpeg binary\n\n_log_internal "Ensuring bin directory exists: ${BIN_DIR}"\nif ! mkdir -p "${BIN_DIR}"; then\n _log_internal "ERROR: Unable to create bin directory at ${BIN_DIR}"\n exit 1\nfi\n\n# Check if FFmpeg is already installed and executable\nif [ -f "${FFMPEG_BIN}" ] && [ -x "${FFMPEG_BIN}" ]; then\n _log_internal "FFmpeg already installed at ${FFMPEG_BIN}. Skipping download."\nelse\n _log_internal "FFmpeg not found or not executable. Attempting to download and install FFmpeg..."\n\n FFMPEG_DOWNLOAD_URL=""\n\n LINUX_ARCH=$(uname -m)\n if [[ "${LINUX_ARCH}" == "x86_64" ]]; then\n FFMPEG_DOWNLOAD_URL="https://github.com/eugeneware/ffmpeg-static/releases/download/b6.0/ffmpeg-linux-x64"\n elif [[ "${LINUX_ARCH}" == "aarch64" ]] || [[ "${LINUX_ARCH}" == "arm64" ]]; then\n FFMPEG_DOWNLOAD_URL="https://github.com/eugeneware/ffmpeg-static/releases/download/b6.0/ffmpeg-linux-arm64"\n else\n _log_internal "Error: Unsupported CPU architecture for FFmpeg download: ${LINUX_ARCH}"\n exit 1\n fi\n\n _log_internal "Downloading FFmpeg from: ${FFMPEG_DOWNLOAD_URL}"\n if command -v curl >/dev/null 2>&1; then\n if ! curl -L "${FFMPEG_DOWNLOAD_URL}" -o "${FFMPEG_BIN}"; then\n _log_internal "Error: Failed to download FFmpeg using curl from ${FFMPEG_DOWNLOAD_URL}"\n exit 1\n fi\n elif command -v wget >/dev/null 2>&1; then\n if ! wget -O "${FFMPEG_BIN}" "${FFMPEG_DOWNLOAD_URL}"; then\n _log_internal "Error: Failed to download FFmpeg using wget from ${FFMPEG_DOWNLOAD_URL}"\n exit 1\n fi\n else\n _log_internal "Error: Neither curl nor wget found. Cannot download FFmpeg."\n exit 1\n fi\n _log_internal "FFmpeg binary downloaded successfully to ${FFMPEG_BIN}"\n\n chmod +x "${FFMPEG_BIN}"\n _log_internal "Set executable permissions for ${FFMPEG_BIN}"\n\n # Verify FFmpeg is executable after download\n if [ ! -f "${FFMPEG_BIN}" ] || [ ! -x "${FFMPEG_BIN}" ]; then\n _log_internal "Error: FFmpeg binary not found or not executable after download."\n exit 1\n fi\nfi\n\n_log_internal "FFmpeg installation complete. FFmpeg binary is at: ${FFMPEG_BIN}"\n\n# Function to check if a command exists\ncommand_exists() {\n command -v "$1" >/dev/null 2>&1\n}\n\n# Function to log messages with timestamp\nlog() {\n local timestamp\n timestamp=$(date +"%Y-%m-%d %H:%M:%S")\n echo "[${timestamp}] $1"\n}\n\n# Function to display error messages and exit\nerror_exit() {\n log "ERROR: $1" >&2\n exit "${2:-1}"\n}\n\n# Function to check if Python binary is valid for current architecture\nis_valid_python_binary() {\n local python_path="$1"\n \n # First check if file exists and is executable\n if [ ! -f "${python_path}" ] || [ ! -x "${python_path}" ]; then\n return 1\n fi\n \n # Try to run a simple Python command to verify it works on current architecture\n "${python_path}" -c "print(\'Testing Python executable\')" >/dev/null 2>&1\n return $?\n}\n\n# Check for network connectivity to key servers\ncheck_connectivity() {\n log "Checking network connectivity..."\n local servers=("pypi.org" "bootstrap.pypa.io")\n local has_connectivity=false\n \n for server in "${servers[@]}"; do\n if command_exists curl; then\n if curl --connect-timeout 5 -s "https://${server}" -o /dev/null; then\n has_connectivity=true\n break\n fi\n elif command_exists wget; then\n if wget --timeout=5 -q --spider "https://${server}"; then\n has_connectivity=true\n break\n fi\n fi\n done\n \n if [ "$has_connectivity" = false ]; then\n log "WARNING: Network connectivity issues detected. This may affect installation."\n else\n log "Network connectivity confirmed."\n fi\n}\n\n# Call connectivity check\ncheck_connectivity\n\n# Check if PYTHON_BIN is already set by the installer\nif [ -n "${PYTHON_BIN:-}" ]; then\n log "Using Python executable provided by installer: ${PYTHON_BIN}"\n # Verify the provided Python binary works on this architecture\n if ! is_valid_python_binary "${PYTHON_BIN}"; then\n log "Warning: The provided Python binary is not compatible with this system architecture."\n log "Will attempt to find a system Python installation instead."\n PYTHON_BIN=""\n fi\nfi\n\n# If PYTHON_BIN is empty or invalid, try to find a suitable Python installation\nif [ -z "${PYTHON_BIN:-}" ] || ! is_valid_python_binary "${PYTHON_BIN:-}"; then\n # Try to find a suitable Python installation\n log "Looking for a suitable Python installation..."\n \n # Try multiple possible locations to find Python\n POSSIBLE_PYTHON_PATHS=(\n # System paths first (more likely to be compatible with current architecture)\n "/usr/local/bin/python3.12"\n "/usr/bin/python3.12"\n "/usr/local/bin/python3"\n "/usr/bin/python3"\n # From environment variable (set by the installer)\n "${ELECTRON_RESOURCE_PATH:-}/python/bin/python3"\n # Development paths\n "$(dirname "$0")/../../../resources/python/bin/python3"\n "$(pwd)/resources/python/bin/python3"\n )\n\n # Find the first Python that exists and is version 3.12+ and works on this architecture\n PYTHON_BIN=""\n for path in "${POSSIBLE_PYTHON_PATHS[@]}"; do\n # Skip empty paths that might come from unset environment variables\n if [ -z "${path}" ]; then\n continue\n fi\n \n if is_valid_python_binary "${path}"; then\n # Check Python version\n if PY_VERSION=$("${path}" -c "import sys; print(f\'{sys.version_info.major}.{sys.version_info.minor}\')" 2>/dev/null); then\n MAJOR=$(echo "${PY_VERSION}" | cut -d. -f1)\n MINOR=$(echo "${PY_VERSION}" | cut -d. -f2)\n if [ "${MAJOR}" -eq 3 ] && [ "${MINOR}" -ge 12 ]; then\n PYTHON_BIN="${path}"\n log "Found suitable Python ${PY_VERSION} at ${path}"\n break\n else\n log "Python at ${path} is version ${PY_VERSION}, which is below the required 3.12+"\n fi\n fi\n else\n if [ -f "${path}" ]; then\n log "Python at ${path} exists but is not compatible with this system architecture"\n fi\n fi\n done\n\n # If we couldn\'t find a suitable Python, exit with error\n if [ -z "${PYTHON_BIN:-}" ]; then\n error_exit "No suitable Python installation found (version 3.12 or higher required).\\nPlease install Python 3.12 or higher before running this script.\\nYou can install Python from https://www.python.org/downloads/"\n fi\nfi\n\necho "Using Python: $PYTHON_BIN"\n"$PYTHON_BIN" --version || {\n echo "Error: Failed to run Python. Please ensure it is executable and accessible."\n echo "System architecture: $(uname -m)"\n echo "Python binary architecture: $(file "$PYTHON_BIN" 2>/dev/null || echo \'Unable to determine\')"\n exit 1\n}\n\n# Detect the Linux distribution to provide specific instructions\nif command_exists lsb_release; then\n DISTRO=$(lsb_release -is)\n DISTRO_VERSION=$(lsb_release -rs)\n echo "Detected Linux distribution: $DISTRO $DISTRO_VERSION"\nelif [ -f /etc/os-release ]; then\n DISTRO=$(grep -oP \'(?<=^ID=).+\' /etc/os-release | tr -d \'"\')\n DISTRO_VERSION=$(grep -oP \'(?<=^VERSION_ID=).+\' /etc/os-release | tr -d \'"\')\n echo "Detected Linux distribution: $DISTRO $DISTRO_VERSION"\nelse\n DISTRO="unknown"\n echo "Unable to detect Linux distribution"\nfi\n\n# Check if Python has venv module and ensurepip available\nlog "Checking for venv module and ensurepip availability..."\nVENV_AVAILABLE=0\nENSUREPIP_AVAILABLE=0\n\n"${PYTHON_BIN}" -c "import venv" > /dev/null 2>&1 || VENV_AVAILABLE=1\n"${PYTHON_BIN}" -c "import ensurepip" > /dev/null 2>&1 || ENSUREPIP_AVAILABLE=1\n\n# If venv is still not available, try to use virtualenv as a fallback\nif [ $VENV_AVAILABLE -ne 0 ]; then\n echo "venv module is not available. Checking for virtualenv as an alternative..."\n \n # Check if virtualenv is already installed\n if "$PYTHON_BIN" -c "import virtualenv" > /dev/null 2>&1; then\n echo "virtualenv is available, will use it instead of venv"\n else\n echo "ERROR: Neither venv nor virtualenv is available."\n echo "Python 3.12 and venv should be installed as package dependencies."\n echo "Please ensure Python 3.12 and venv are properly installed on your system."\n exit 1\n fi\nfi\n\n# Create virtual environment if it doesn\'t exist\nif [ ! -d "$VENV_PATH" ]; then\n echo "Creating virtual environment at $VENV_PATH..."\n # Remove any potentially corrupted virtual environment\n if [ -e "$VENV_PATH" ]; then\n echo "Removing existing but potentially corrupted venv directory..."\n rm -rf "$VENV_PATH"\n fi\n \n # Make sure parent directory exists and is writable\n mkdir -p "$(dirname "$VENV_PATH")"\n \n # Try different methods to create a virtual environment\n VENV_CREATE_STATUS=1\n \n # First try with venv if available\n if [ $VENV_AVAILABLE -eq 0 ] && [ $ENSUREPIP_AVAILABLE -eq 0 ]; then\n echo "Creating virtual environment using venv module..."\n "$PYTHON_BIN" -m venv "$VENV_PATH"\n VENV_CREATE_STATUS=$?\n fi\n \n # If venv failed, try virtualenv\n if [ $VENV_CREATE_STATUS -ne 0 ]; then\n echo "venv creation failed with status $VENV_CREATE_STATUS. Falling back to virtualenv..."\n if command_exists virtualenv; then\n virtualenv -p "$PYTHON_BIN" "$VENV_PATH"\n VENV_CREATE_STATUS=$?\n elif "$PYTHON_BIN" -m pip list | grep -q virtualenv; then\n "$PYTHON_BIN" -m virtualenv -p "$PYTHON_BIN" "$VENV_PATH"\n VENV_CREATE_STATUS=$?\n else\n echo "ERROR: Both venv and virtualenv are unavailable or failed."\n echo "Python 3.12 and venv should be installed as package dependencies."\n echo "Please ensure Python 3.12 and venv are properly installed on your system."\n echo "You can install Python 3.12 from https://www.python.org/downloads/"\n exit 1\n fi\n fi\n \n # Check if virtual environment creation was successful\n if [ $VENV_CREATE_STATUS -ne 0 ]; then\n log "ERROR: Failed to create virtual environment. Exit code: $VENV_CREATE_STATUS"\n log "Virtual environment path: $VENV_PATH"\n log "Python binary used: $PYTHON_BIN"\n ls -la "$(dirname "$VENV_PATH")" || true\n log "Python executable permissions:"\n ls -la "$PYTHON_BIN" || true\n \n # Check for common issues\n log "Checking for common virtual environment creation issues..."\n \n # Check disk space\n df -h "$(dirname "$VENV_PATH")" || true\n \n # Check if directory is writable\n if [ ! -w "$(dirname "$VENV_PATH")" ]; then\n log "ERROR: Directory $(dirname "$VENV_PATH") is not writable"\n fi\n \n # Try to create a minimal virtual environment manually as a last resort\n log "Attempting to create a minimal virtual environment manually..."\n mkdir -p "$VENV_PATH/bin" || error_exit "Could not create directory $VENV_PATH/bin"\n echo "#!/bin/bash" > "$VENV_PATH/bin/activate"\n echo "export VIRTUAL_ENV=\\"$VENV_PATH\\"" >> "$VENV_PATH/bin/activate"\n echo "export PATH=\\"$VENV_PATH/bin:\\$PATH\\"" >> "$VENV_PATH/bin/activate"\n echo "unset PYTHONHOME" >> "$VENV_PATH/bin/activate"\n chmod +x "$VENV_PATH/bin/activate" || error_exit "Could not set execute permissions on activate script"\n \n # Create symlinks to the system Python\n ln -sf "$PYTHON_BIN" "$VENV_PATH/bin/python" || log "WARNING: Failed to create symlink for python"\n ln -sf "$PYTHON_BIN" "$VENV_PATH/bin/python3" || log "WARNING: Failed to create symlink for python3"\n \n # Try to bootstrap pip\n log "Bootstrapping pip in the minimal virtual environment..."\n if command_exists curl; then\n curl -s https://bootstrap.pypa.io/get-pip.py -o "$APP_DATA_DIR/get-pip.py" || log "WARNING: Failed to download get-pip.py"\n elif command_exists wget; then\n wget -q -O "$APP_DATA_DIR/get-pip.py" https://bootstrap.pypa.io/get-pip.py || log "WARNING: Failed to download get-pip.py"\n else\n log "ERROR: Neither curl nor wget available to download get-pip.py"\n error_exit "Installation cannot continue without being able to download pip"\n fi\n \n # shellcheck disable=SC1090\n source "$VENV_PATH/bin/activate" && python "$APP_DATA_DIR/get-pip.py" --no-warn-script-location\n \n if [ ! -f "$VENV_PATH/bin/pip" ]; then\n error_exit "Failed to create even a minimal virtual environment."\n else\n log "Created a minimal virtual environment as a fallback."\n fi\n else\n log "Successfully created virtual environment"\n fi\nfi\n\n# Verify the virtual environment structure\necho "Verifying virtual environment structure..."\nif [ ! -f "$VENV_PATH/bin/python" ]; then\n echo "Python executable missing in virtual environment, creating symlink..."\n ln -sf "$PYTHON_BIN" "$VENV_PATH/bin/python"\nfi\n\nif [ ! -f "$VENV_PATH/bin/pip" ]; then\n echo "pip missing in virtual environment, attempting to bootstrap it..."\n curl -s https://bootstrap.pypa.io/get-pip.py -o "$APP_DATA_DIR/get-pip.py"\n "$VENV_PATH/bin/python" "$APP_DATA_DIR/get-pip.py" --no-warn-script-location\n \n if [ ! -f "$VENV_PATH/bin/pip" ]; then\n echo "ERROR: Failed to bootstrap pip in the virtual environment"\n exit 1\n fi\nfi\n\necho "Virtual environment structure verified"\n\n# Activate virtual environment and install local-operator\necho "Installing local-operator in virtual environment..."\nsource "$VENV_PATH/bin/activate"\n\necho "Upgrading pip..."\npython -m pip install --upgrade pip || {\n echo "WARNING: Failed to upgrade pip. Will try to continue with existing pip version."\n pip --version\n}\n\n# Check network connectivity to PyPI\necho "Checking network connectivity to PyPI..."\nif command_exists curl; then\n curl -s https://pypi.org/pypi/local-operator/json -o /dev/null || {\n echo "WARNING: Could not reach PyPI. Network connectivity issues might prevent installation."\n }\nelif command_exists wget; then\n wget -q --spider https://pypi.org/pypi/local-operator/json || {\n echo "WARNING: Could not reach PyPI. Network connectivity issues might prevent installation."\n }\nfi\n\necho "Installing local-operator package..."\npython -m pip install --verbose local-operator || {\n echo "ERROR: Failed to install local-operator package. Exit code: $?"\n echo "Python version:"\n python --version\n echo "pip version:"\n pip --version\n echo "Available pip packages:"\n pip list\n exit 1\n}\necho "local-operator installation successful"\n\n# Verify installation\nif [ -f "$VENV_PATH/bin/local-operator" ]; then\n log "Local Operator backend installed successfully!"\n \n # Show more information about the installed binary\n ls -la "$VENV_PATH/bin/local-operator" || true\n file "$VENV_PATH/bin/local-operator" 2>/dev/null || log "Note: \'file\' command not available"\n \n # Try to run the version command with full error output\n log "Testing local-operator binary..."\n "$VENV_PATH/bin/local-operator" --version || {\n log "ERROR: local-operator binary exists but failed to execute. Exit code: $?"\n log "Binary details:"\n file "$VENV_PATH/bin/local-operator" 2>/dev/null || log "Note: \'file\' command not available"\n log "Binary permissions:"\n ls -la "$VENV_PATH/bin/local-operator" || true\n log ""\n log "This could be due to missing dependencies or architecture incompatibility."\n log "Try running the binary manually to see specific errors."\n \n # Don\'t exit here - just warn the user\n log "WARNING: Installation completed but binary verification failed."\n }\n \n # Create a summary of the installation\n SUMMARY_FILE="${APP_DATA_DIR}/installation-summary-${TIMESTAMP}.txt"\n {\n echo "=== Local Operator Backend Installation Summary ==="\n echo "Timestamp: $(date)"\n echo "Python Version: $("${PYTHON_BIN}" --version 2>&1)"\n echo "Virtual Environment: ${VENV_PATH}"\n echo "Binary Location: ${VENV_PATH}/bin/local-operator"\n echo "To activate the virtual environment, run: source ${VENV_PATH}/bin/activate"\n echo "To test the installation, run: ${VENV_PATH}/bin/local-operator --version"\n echo "Log file: ${LOG_FILE}"\n echo "=================================================="\n } > "${SUMMARY_FILE}"\n \n log "Installation summary saved to: ${SUMMARY_FILE}"\nelse\n log "Error: Failed to install Local Operator backend. Binary not found."\n log "Contents of bin directory:"\n ls -la "$VENV_PATH/bin/" || true\n log "Check the log file for details: ${LOG_FILE}"\n error_exit "Installation failed. Binary not installed properly."\nfi\n\nlog "Installation completed successfully at $(date)"\n\n# Clean up temporary files now that installation is complete\ncleanup\n\n# Print final instructions\nlog ""\nlog "=== INSTALLATION COMPLETE ==="\nlog "You can now use the Local Operator backend by running: ${VENV_PATH}/bin/local-operator"\nlog "Installation directory: ${VENV_PATH}"\nlog "Log file: ${LOG_FILE}"\nlog "================================"\n';
|
|
@@ -4126,7 +4328,7 @@ function displayAuthority(url) {
|
|
|
4126
4328
|
}
|
|
4127
4329
|
let pslRules = null;
|
|
4128
4330
|
function configurePslRules(rules2) {
|
|
4129
|
-
pslRules =
|
|
4331
|
+
pslRules = new Set(rules2.split("\n"));
|
|
4130
4332
|
}
|
|
4131
4333
|
function domainScopeAvailable() {
|
|
4132
4334
|
return pslRules !== null;
|
|
@@ -4262,6 +4464,10 @@ class ApprovalStore {
|
|
|
4262
4464
|
onceGrants = {};
|
|
4263
4465
|
/** Receipts for displaced requesters (see `access-flow.ts`). */
|
|
4264
4466
|
tombstones = {};
|
|
4467
|
+
/** Consumed once grants authorize one committed document, not every future
|
|
4468
|
+
* document on that origin. Revocation invalidates in-flight admissions too. */
|
|
4469
|
+
revision = 0;
|
|
4470
|
+
documents = /* @__PURE__ */ new Map();
|
|
4265
4471
|
constructor(options) {
|
|
4266
4472
|
this.path = path$1.join(options.dir, APPROVALS_FILENAME);
|
|
4267
4473
|
this.now = options.now ?? Date.now;
|
|
@@ -4346,6 +4552,41 @@ class ApprovalStore {
|
|
|
4346
4552
|
}
|
|
4347
4553
|
);
|
|
4348
4554
|
}
|
|
4555
|
+
/** Admission is captured once, but revocation remains authoritative while an
|
|
4556
|
+
* asynchronous navigation is in flight. A receipt is never transferable. */
|
|
4557
|
+
admit(url, requester) {
|
|
4558
|
+
const { viaOnceGrant } = this.ensureTopLevelAccess(url, requester);
|
|
4559
|
+
const revision = this.revision;
|
|
4560
|
+
return {
|
|
4561
|
+
viaOnceGrant,
|
|
4562
|
+
approved: (candidate) => this.originAllowed(candidate) || viaOnceGrant && revision === this.revision && candidate.origin === url.origin
|
|
4563
|
+
};
|
|
4564
|
+
}
|
|
4565
|
+
rememberDocument(token, url, requester, epoch, admitted) {
|
|
4566
|
+
if (!admitted(url)) this.refuseDocument(url);
|
|
4567
|
+
this.documents.set(token, {
|
|
4568
|
+
origin: url.origin,
|
|
4569
|
+
requester,
|
|
4570
|
+
epoch,
|
|
4571
|
+
revision: this.revision
|
|
4572
|
+
});
|
|
4573
|
+
}
|
|
4574
|
+
documentAllowed(token, url, requester, epoch) {
|
|
4575
|
+
if (this.store.origins[url.origin] === "deny") return false;
|
|
4576
|
+
if (this.originAllowed(url)) return true;
|
|
4577
|
+
const receipt = this.documents.get(token);
|
|
4578
|
+
return !!receipt && receipt.origin === url.origin && receipt.requester === requester && receipt.epoch === epoch && receipt.revision === this.revision;
|
|
4579
|
+
}
|
|
4580
|
+
forgetDocument(token) {
|
|
4581
|
+
this.documents.delete(token);
|
|
4582
|
+
}
|
|
4583
|
+
refuseDocument(url) {
|
|
4584
|
+
throw new BridgeCommandError(
|
|
4585
|
+
"origin_not_allowed",
|
|
4586
|
+
`the user has not approved ${url.origin} for this document; request access before driving it`,
|
|
4587
|
+
{ origin: url.origin, reason: this.refusalReason(url) }
|
|
4588
|
+
);
|
|
4589
|
+
}
|
|
4349
4590
|
// ---- request_access / await_access / cancel_access -----------------------
|
|
4350
4591
|
/** The live entry for an exact origin, if any: what a consent surface renders. */
|
|
4351
4592
|
pendingEntry() {
|
|
@@ -4594,6 +4835,7 @@ class ApprovalStore {
|
|
|
4594
4835
|
this.store.origins = {};
|
|
4595
4836
|
this.store.siteGrants = { version: 1, grants: {} };
|
|
4596
4837
|
this.store.records = [];
|
|
4838
|
+
this.resetPending();
|
|
4597
4839
|
this.persist();
|
|
4598
4840
|
this.onChanged();
|
|
4599
4841
|
return removed;
|
|
@@ -4601,6 +4843,8 @@ class ApprovalStore {
|
|
|
4601
4843
|
/** Drop everything about the pending flow. Used by the host-off toggle, which
|
|
4602
4844
|
* tears the state file down so discovery is honest. */
|
|
4603
4845
|
resetPending() {
|
|
4846
|
+
this.revision += 1;
|
|
4847
|
+
this.documents.clear();
|
|
4604
4848
|
this.queue = [];
|
|
4605
4849
|
this.results = {};
|
|
4606
4850
|
this.onceGrants = {};
|
|
@@ -4939,11 +5183,16 @@ class CdpPool {
|
|
|
4939
5183
|
contents.debugger.on("detach", detachListener);
|
|
4940
5184
|
if (!hasLogCapture(contents.id)) startLogCapture(contents.id);
|
|
4941
5185
|
try {
|
|
4942
|
-
await this.sendTo(contents, "Runtime.enable", {});
|
|
4943
|
-
await this.sendTo(contents, "Log.enable", {});
|
|
4944
|
-
await this.sendTo(
|
|
4945
|
-
|
|
4946
|
-
|
|
5186
|
+
await this.sendTo(contents, "Runtime.enable", {}, CDP_DEADLINE_MS);
|
|
5187
|
+
await this.sendTo(contents, "Log.enable", {}, CDP_DEADLINE_MS);
|
|
5188
|
+
await this.sendTo(
|
|
5189
|
+
contents,
|
|
5190
|
+
"Emulation.setFocusEmulationEnabled",
|
|
5191
|
+
{
|
|
5192
|
+
enabled: true
|
|
5193
|
+
},
|
|
5194
|
+
CDP_DEADLINE_MS
|
|
5195
|
+
);
|
|
4947
5196
|
} catch (error) {
|
|
4948
5197
|
this.forget(contents.id);
|
|
4949
5198
|
throw error;
|
|
@@ -4971,7 +5220,7 @@ class CdpPool {
|
|
|
4971
5220
|
* `tab_closed` too — an action that skipped `attach` is a bug in this host, and
|
|
4972
5221
|
* reporting it as anything the agent could act on would be a lie.
|
|
4973
5222
|
*/
|
|
4974
|
-
async send(contents, method, params = {}) {
|
|
5223
|
+
async send(contents, method, params = {}, options = {}) {
|
|
4975
5224
|
if (contents.isDestroyed()) {
|
|
4976
5225
|
this.forget(contents.id);
|
|
4977
5226
|
throw new BridgeCommandError(
|
|
@@ -4979,9 +5228,14 @@ class CdpPool {
|
|
|
4979
5228
|
"that browser tab is gone; dropped the handle. Use 'open' with a URL to get a new tab"
|
|
4980
5229
|
);
|
|
4981
5230
|
}
|
|
4982
|
-
return this.sendTo(
|
|
5231
|
+
return this.sendTo(
|
|
5232
|
+
contents,
|
|
5233
|
+
method,
|
|
5234
|
+
params,
|
|
5235
|
+
options.deadlineMs ?? CDP_DEADLINE_MS
|
|
5236
|
+
);
|
|
4983
5237
|
}
|
|
4984
|
-
async sendTo(contents, method, params) {
|
|
5238
|
+
async sendTo(contents, method, params, deadlineMs) {
|
|
4985
5239
|
const attachment = this.attachments.get(contents.id);
|
|
4986
5240
|
if (!attachment) {
|
|
4987
5241
|
throw new BridgeCommandError(
|
|
@@ -4999,7 +5253,7 @@ class CdpPool {
|
|
|
4999
5253
|
}
|
|
5000
5254
|
return deadline(
|
|
5001
5255
|
contents.debugger.sendCommand(method, params),
|
|
5002
|
-
|
|
5256
|
+
deadlineMs,
|
|
5003
5257
|
method
|
|
5004
5258
|
);
|
|
5005
5259
|
}
|
|
@@ -5447,11 +5701,38 @@ async function screenshot(ctx, params) {
|
|
|
5447
5701
|
);
|
|
5448
5702
|
}
|
|
5449
5703
|
await ctx.cdp.attach(contents);
|
|
5450
|
-
const
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5704
|
+
const beyondViewport = !record.presented;
|
|
5705
|
+
const viewportBounds = record.view.getBounds?.();
|
|
5706
|
+
const clip2 = beyondViewport && viewportBounds ? { ...viewportBounds, scale: 1 } : void 0;
|
|
5707
|
+
const attempts = beyondViewport ? 3 : 1;
|
|
5708
|
+
let lastError;
|
|
5709
|
+
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
5710
|
+
try {
|
|
5711
|
+
const attemptShot = await ctx.cdp.send(
|
|
5712
|
+
contents,
|
|
5713
|
+
"Page.captureScreenshot",
|
|
5714
|
+
{
|
|
5715
|
+
format: "png",
|
|
5716
|
+
captureBeyondViewport: beyondViewport,
|
|
5717
|
+
...clip2 ? { clip: clip2 } : {}
|
|
5718
|
+
},
|
|
5719
|
+
{
|
|
5720
|
+
deadlineMs: beyondViewport ? BACKGROUND_CAPTURE_ATTEMPT_MS : void 0
|
|
5721
|
+
}
|
|
5722
|
+
);
|
|
5723
|
+
return finishCapture(ctx, record, attemptShot);
|
|
5724
|
+
} catch (error) {
|
|
5725
|
+
if (!isStall(error) || attempt === attempts - 1) throw error;
|
|
5726
|
+
lastError = error;
|
|
5727
|
+
}
|
|
5728
|
+
}
|
|
5729
|
+
throw lastError;
|
|
5730
|
+
}
|
|
5731
|
+
const BACKGROUND_CAPTURE_ATTEMPT_MS = 5e3;
|
|
5732
|
+
function isStall(error) {
|
|
5733
|
+
return typeof error === "object" && error !== null && typeof error.data?.stalled === "string";
|
|
5734
|
+
}
|
|
5735
|
+
function finishCapture(ctx, record, shot) {
|
|
5455
5736
|
const data = shot?.data;
|
|
5456
5737
|
if (!data) {
|
|
5457
5738
|
throw new BridgeCommandError(
|
|
@@ -5666,6 +5947,12 @@ async function conversationReadBack(ctx, objectId, contents) {
|
|
|
5666
5947
|
return String(out?.result?.value ?? "");
|
|
5667
5948
|
}
|
|
5668
5949
|
const MAX_AGENT_TABS = 8;
|
|
5950
|
+
const BACKGROUND_VIEWPORT = {
|
|
5951
|
+
x: 0,
|
|
5952
|
+
y: 0,
|
|
5953
|
+
width: 1280,
|
|
5954
|
+
height: 720
|
|
5955
|
+
};
|
|
5669
5956
|
const REDACTED_NONCE_CHARS = 6;
|
|
5670
5957
|
const SURFACE_PREFIX = "ui";
|
|
5671
5958
|
function surfaceToken(record) {
|
|
@@ -5730,12 +6017,13 @@ class TabRegistry {
|
|
|
5730
6017
|
createdAt: Date.now(),
|
|
5731
6018
|
lastUsedAt: Date.now(),
|
|
5732
6019
|
epoch: 0,
|
|
6020
|
+
documentEpoch: 0,
|
|
6021
|
+
presented: false,
|
|
5733
6022
|
refs: {},
|
|
5734
6023
|
allocationId: options.allocationId ?? ""
|
|
5735
6024
|
};
|
|
5736
6025
|
this.tabs.set(tabId, record);
|
|
5737
|
-
if (
|
|
5738
|
-
if (this.activeTabId === null) this.activeTabId = tabId;
|
|
6026
|
+
if (record.owner === "user") this.activeTabId = tabId;
|
|
5739
6027
|
this.applyLayout();
|
|
5740
6028
|
this.onChanged();
|
|
5741
6029
|
return record;
|
|
@@ -5840,8 +6128,8 @@ class TabRegistry {
|
|
|
5840
6128
|
record.sessionId = sessionId2;
|
|
5841
6129
|
record.handedTo = sessionId2;
|
|
5842
6130
|
record.nonce = mintNonce();
|
|
5843
|
-
record.
|
|
5844
|
-
record.
|
|
6131
|
+
record.allocationId = "";
|
|
6132
|
+
this.bumpEpoch(record.tabId);
|
|
5845
6133
|
this.onChanged();
|
|
5846
6134
|
}
|
|
5847
6135
|
/** Revoke a hand-over: nulls the nonce, so the session's next action on that
|
|
@@ -5853,6 +6141,8 @@ class TabRegistry {
|
|
|
5853
6141
|
record.owner = "user";
|
|
5854
6142
|
record.sessionId = null;
|
|
5855
6143
|
record.handedTo = null;
|
|
6144
|
+
record.allocationId = "";
|
|
6145
|
+
this.bumpEpoch(record.tabId);
|
|
5856
6146
|
this.onChanged();
|
|
5857
6147
|
}
|
|
5858
6148
|
/** Whether a session may drive this tab: its own agent tab, or one handed to
|
|
@@ -5871,10 +6161,11 @@ class TabRegistry {
|
|
|
5871
6161
|
* `element_not_found` instead of clicking whatever now occupies that
|
|
5872
6162
|
* position.
|
|
5873
6163
|
*/
|
|
5874
|
-
bumpEpoch(tabId) {
|
|
6164
|
+
bumpEpoch(tabId, newDocument = true) {
|
|
5875
6165
|
const record = this.tabs.get(tabId);
|
|
5876
6166
|
if (!record) return;
|
|
5877
6167
|
record.epoch += 1;
|
|
6168
|
+
if (newDocument) record.documentEpoch += 1;
|
|
5878
6169
|
for (const listener of this.epochListeners) listener(tabId, record.epoch);
|
|
5879
6170
|
}
|
|
5880
6171
|
/** Observe epoch changes (the CDP driver uses one to re-arm per-navigation
|
|
@@ -5909,9 +6200,9 @@ class TabRegistry {
|
|
|
5909
6200
|
}
|
|
5910
6201
|
}
|
|
5911
6202
|
// ---- layout, visibility, activation --------------------------------------
|
|
5912
|
-
/** The renderer owns
|
|
5913
|
-
*
|
|
5914
|
-
*
|
|
6203
|
+
/** The renderer owns presentation geometry, not whether a background renderer
|
|
6204
|
+
* has a viewport. Inactive views keep bounded default dimensions independently
|
|
6205
|
+
* of this rectangle, so agent actions never require a route or focus change. */
|
|
5915
6206
|
setContentRect(rect) {
|
|
5916
6207
|
this.contentRect = rect;
|
|
5917
6208
|
this.applyLayout();
|
|
@@ -5932,8 +6223,11 @@ class TabRegistry {
|
|
|
5932
6223
|
const active = this.activeTabId === null ? null : this.tabs.get(this.activeTabId);
|
|
5933
6224
|
for (const record of this.tabs.values()) {
|
|
5934
6225
|
const isActive = record === active;
|
|
5935
|
-
record.
|
|
5936
|
-
|
|
6226
|
+
record.presented = isActive && this.visible && this.contentRect !== null;
|
|
6227
|
+
record.view.setBounds(
|
|
6228
|
+
isActive && this.contentRect ? this.contentRect : BACKGROUND_VIEWPORT
|
|
6229
|
+
);
|
|
6230
|
+
record.view.setVisible(record.presented);
|
|
5937
6231
|
}
|
|
5938
6232
|
}
|
|
5939
6233
|
// ---- removal -------------------------------------------------------------
|
|
@@ -5950,8 +6244,9 @@ class TabRegistry {
|
|
|
5950
6244
|
if (!record) return void 0;
|
|
5951
6245
|
this.tabs.delete(tabId);
|
|
5952
6246
|
if (this.activeTabId === tabId) {
|
|
5953
|
-
this.activeTabId = this.list().at(-1)?.tabId ?? null;
|
|
6247
|
+
this.activeTabId = this.list().filter((candidate) => candidate.owner === "user").at(-1)?.tabId ?? null;
|
|
5954
6248
|
}
|
|
6249
|
+
this.applyLayout();
|
|
5955
6250
|
this.onChanged();
|
|
5956
6251
|
return record;
|
|
5957
6252
|
}
|
|
@@ -6004,12 +6299,45 @@ async function open(ctx, params, requestId2) {
|
|
|
6004
6299
|
const handle2 = stringParam(params, "tab");
|
|
6005
6300
|
const rawUrl = stringParam(params, "url");
|
|
6006
6301
|
const url = rawUrl ? safeHttpUrl(rawUrl) : null;
|
|
6007
|
-
const admission = url ? ctx.approvals.
|
|
6008
|
-
const approved = (candidate) =>
|
|
6302
|
+
const admission = url ? ctx.approvals.admit(url, requester) : null;
|
|
6303
|
+
const approved = admission?.approved ?? ((candidate) => ctx.approvals.originAllowed(candidate));
|
|
6009
6304
|
if (handle2) {
|
|
6010
6305
|
const record2 = ctx.registry.requireSurface(handle2);
|
|
6306
|
+
record2.allocationId = stringParam(params, "allocation_id") || record2.allocationId;
|
|
6307
|
+
if (!url) {
|
|
6308
|
+
const current = safeHttpUrl(record2.view.webContents.getURL());
|
|
6309
|
+
if (!current)
|
|
6310
|
+
throw new BridgeCommandError(
|
|
6311
|
+
"origin_not_allowed",
|
|
6312
|
+
"the handed-over tab has no approved HTTP document"
|
|
6313
|
+
);
|
|
6314
|
+
const token = surfaceToken(record2) ?? "";
|
|
6315
|
+
if (!ctx.approvals.documentAllowed(
|
|
6316
|
+
token,
|
|
6317
|
+
current,
|
|
6318
|
+
requester,
|
|
6319
|
+
record2.documentEpoch
|
|
6320
|
+
)) {
|
|
6321
|
+
const permission = ctx.approvals.admit(current, requester);
|
|
6322
|
+
ctx.approvals.rememberDocument(
|
|
6323
|
+
token,
|
|
6324
|
+
current,
|
|
6325
|
+
requester,
|
|
6326
|
+
record2.documentEpoch,
|
|
6327
|
+
permission.approved
|
|
6328
|
+
);
|
|
6329
|
+
}
|
|
6330
|
+
}
|
|
6011
6331
|
await ctx.cdp.attach(record2.view.webContents);
|
|
6012
6332
|
const page = url ? await navigateView(ctx, record2.view, url, requester, approved) : pageOf(record2.view);
|
|
6333
|
+
if (url)
|
|
6334
|
+
ctx.approvals.rememberDocument(
|
|
6335
|
+
surfaceToken(record2) ?? "",
|
|
6336
|
+
new URL(page.url),
|
|
6337
|
+
requester,
|
|
6338
|
+
record2.documentEpoch,
|
|
6339
|
+
approved
|
|
6340
|
+
);
|
|
6013
6341
|
ctx.registry.touch(record2);
|
|
6014
6342
|
ctx.onChanged();
|
|
6015
6343
|
return openResult(record2, {
|
|
@@ -6022,9 +6350,22 @@ async function open(ctx, params, requestId2) {
|
|
|
6022
6350
|
sessionId: sessionIdOf$1(requester) || requester,
|
|
6023
6351
|
allocationId: stringParam(params, "allocation_id")
|
|
6024
6352
|
});
|
|
6353
|
+
ctx.ownership.recordAllocation(
|
|
6354
|
+
params,
|
|
6355
|
+
surfaceToken(record) ?? "",
|
|
6356
|
+
"allocated"
|
|
6357
|
+
);
|
|
6025
6358
|
try {
|
|
6026
6359
|
await ctx.cdp.attach(record.view.webContents);
|
|
6027
6360
|
const page = url ? await navigateView(ctx, record.view, url, requester, approved) : pageOf(record.view);
|
|
6361
|
+
if (url)
|
|
6362
|
+
ctx.approvals.rememberDocument(
|
|
6363
|
+
surfaceToken(record) ?? "",
|
|
6364
|
+
new URL(page.url),
|
|
6365
|
+
requester,
|
|
6366
|
+
record.documentEpoch,
|
|
6367
|
+
approved
|
|
6368
|
+
);
|
|
6028
6369
|
ctx.registry.touch(record);
|
|
6029
6370
|
ctx.onChanged();
|
|
6030
6371
|
return openResult(record, {
|
|
@@ -6033,6 +6374,7 @@ async function open(ctx, params, requestId2) {
|
|
|
6033
6374
|
});
|
|
6034
6375
|
} catch (error) {
|
|
6035
6376
|
ctx.registry.destroy(record.tabId);
|
|
6377
|
+
ctx.ownership.recordAllocation(params, "", "closed");
|
|
6036
6378
|
throw error;
|
|
6037
6379
|
}
|
|
6038
6380
|
}
|
|
@@ -6040,10 +6382,17 @@ async function goto(ctx, params, requestId2) {
|
|
|
6040
6382
|
const requester = requesterOf(params, requestId2);
|
|
6041
6383
|
const record = ctx.registry.requireSurface(params.tab);
|
|
6042
6384
|
const url = safeHttpUrl(stringParam(params, "url"));
|
|
6043
|
-
const admission = ctx.approvals.
|
|
6044
|
-
const approved =
|
|
6385
|
+
const admission = ctx.approvals.admit(url, requester);
|
|
6386
|
+
const approved = admission.approved;
|
|
6045
6387
|
await ctx.cdp.attach(record.view.webContents);
|
|
6046
6388
|
const page = await navigateView(ctx, record.view, url, requester, approved);
|
|
6389
|
+
ctx.approvals.rememberDocument(
|
|
6390
|
+
surfaceToken(record) ?? "",
|
|
6391
|
+
new URL(page.url),
|
|
6392
|
+
requester,
|
|
6393
|
+
record.documentEpoch,
|
|
6394
|
+
approved
|
|
6395
|
+
);
|
|
6047
6396
|
ctx.registry.touch(record);
|
|
6048
6397
|
ctx.onChanged();
|
|
6049
6398
|
return {
|
|
@@ -6057,6 +6406,7 @@ async function close(ctx, params) {
|
|
|
6057
6406
|
if (handle2) {
|
|
6058
6407
|
const record2 = ctx.registry.requireSurface(handle2);
|
|
6059
6408
|
const closed2 = surfaceToken(record2) ?? handle2;
|
|
6409
|
+
ctx.approvals.forgetDocument(closed2);
|
|
6060
6410
|
ctx.registry.destroy(record2.tabId);
|
|
6061
6411
|
ctx.onChanged();
|
|
6062
6412
|
return { closed: closed2 };
|
|
@@ -6194,6 +6544,16 @@ const ERROR_CODES = [
|
|
|
6194
6544
|
"extension_unresponsive",
|
|
6195
6545
|
"internal"
|
|
6196
6546
|
];
|
|
6547
|
+
const DOCUMENT_SCOPED = /* @__PURE__ */ new Set([
|
|
6548
|
+
"read",
|
|
6549
|
+
"snapshot",
|
|
6550
|
+
"screenshot",
|
|
6551
|
+
"click",
|
|
6552
|
+
"type",
|
|
6553
|
+
"scroll",
|
|
6554
|
+
"logs"
|
|
6555
|
+
]);
|
|
6556
|
+
const NAVIGATION_ACTIONS = /* @__PURE__ */ new Set(["click", "type"]);
|
|
6197
6557
|
const TAB_SCOPED = /* @__PURE__ */ new Set([
|
|
6198
6558
|
"goto",
|
|
6199
6559
|
"read",
|
|
@@ -6228,7 +6588,7 @@ class BrowserHost {
|
|
|
6228
6588
|
const run = () => this.ownership.withOwnership(
|
|
6229
6589
|
method,
|
|
6230
6590
|
params,
|
|
6231
|
-
() => this.
|
|
6591
|
+
() => this.authorizedPerform(method, params, requestId2)
|
|
6232
6592
|
);
|
|
6233
6593
|
if (TAB_SCOPED.has(method) && typeof params.tab === "string" && params.tab) {
|
|
6234
6594
|
const record = this.registry.requireSurface(params.tab);
|
|
@@ -6236,6 +6596,53 @@ class BrowserHost {
|
|
|
6236
6596
|
}
|
|
6237
6597
|
return run();
|
|
6238
6598
|
}
|
|
6599
|
+
async authorizedPerform(method, params, requestId2) {
|
|
6600
|
+
if (!DOCUMENT_SCOPED.has(method))
|
|
6601
|
+
return this.perform(method, params, requestId2);
|
|
6602
|
+
const token = String(params.tab ?? "");
|
|
6603
|
+
const record = this.registry.requireSurface(token);
|
|
6604
|
+
const requester = requesterOf(params, requestId2);
|
|
6605
|
+
let authorizedOn = record.documentEpoch;
|
|
6606
|
+
const assertDocument = () => {
|
|
6607
|
+
const url = new URL(record.view.webContents.getURL() || "about:blank");
|
|
6608
|
+
if (record.documentEpoch !== authorizedOn) {
|
|
6609
|
+
if (!NAVIGATION_ACTIONS.has(method)) {
|
|
6610
|
+
this.registry.bumpEpoch(record.tabId);
|
|
6611
|
+
throw new BridgeCommandError(
|
|
6612
|
+
"origin_not_allowed",
|
|
6613
|
+
"the page navigated while this action was running; its result was discarded",
|
|
6614
|
+
{ origin: url.origin, url: url.href, reason: "changed" }
|
|
6615
|
+
);
|
|
6616
|
+
}
|
|
6617
|
+
authorizedOn = record.documentEpoch;
|
|
6618
|
+
}
|
|
6619
|
+
if (!permittedScheme(url) || !this.approvals.documentAllowed(token, url, requester, authorizedOn)) {
|
|
6620
|
+
this.registry.bumpEpoch(record.tabId);
|
|
6621
|
+
this.approvals.refuseDocument(url);
|
|
6622
|
+
}
|
|
6623
|
+
return url;
|
|
6624
|
+
};
|
|
6625
|
+
assertDocument();
|
|
6626
|
+
const operation = async () => {
|
|
6627
|
+
assertDocument();
|
|
6628
|
+
const result = await this.perform(method, params, requestId2);
|
|
6629
|
+
assertDocument();
|
|
6630
|
+
return result;
|
|
6631
|
+
};
|
|
6632
|
+
if (!NAVIGATION_ACTIONS.has(method)) return operation();
|
|
6633
|
+
return withOriginGate(
|
|
6634
|
+
this,
|
|
6635
|
+
record.view,
|
|
6636
|
+
requester,
|
|
6637
|
+
(url) => this.approvals.documentAllowed(
|
|
6638
|
+
token,
|
|
6639
|
+
url,
|
|
6640
|
+
requester,
|
|
6641
|
+
record.documentEpoch
|
|
6642
|
+
),
|
|
6643
|
+
operation
|
|
6644
|
+
);
|
|
6645
|
+
}
|
|
6239
6646
|
async perform(method, params, requestId2) {
|
|
6240
6647
|
switch (method) {
|
|
6241
6648
|
case "open":
|
|
@@ -6369,6 +6776,7 @@ class BrowserHost {
|
|
|
6369
6776
|
return this.chromeState();
|
|
6370
6777
|
}
|
|
6371
6778
|
closeTab(tabId) {
|
|
6779
|
+
this.dropReceipt(tabId);
|
|
6372
6780
|
this.registry.destroy(tabId);
|
|
6373
6781
|
this.onChanged();
|
|
6374
6782
|
return this.chromeState();
|
|
@@ -6442,15 +6850,34 @@ class BrowserHost {
|
|
|
6442
6850
|
* sees the nonce: it travels to the session through `tabs`, which is what keeps
|
|
6443
6851
|
* this the one authority transfer rather than an exposure (design 6.3, 11.7). */
|
|
6444
6852
|
handOver(tabId, sessionId2) {
|
|
6853
|
+
this.dropReceipt(tabId);
|
|
6445
6854
|
this.registry.handOver(tabId, sessionId2);
|
|
6446
6855
|
this.onChanged();
|
|
6447
6856
|
return this.chromeState();
|
|
6448
6857
|
}
|
|
6449
6858
|
revokeHandOver(tabId) {
|
|
6859
|
+
this.dropReceipt(tabId);
|
|
6450
6860
|
this.registry.revokeHandOver(tabId);
|
|
6451
6861
|
this.onChanged();
|
|
6452
6862
|
return this.chromeState();
|
|
6453
6863
|
}
|
|
6864
|
+
/**
|
|
6865
|
+
* Forget whatever document receipt this tab's handle was granted.
|
|
6866
|
+
*
|
|
6867
|
+
* A receipt is bounded by the life of its TOKEN, so every path that ends a
|
|
6868
|
+
* token has to drop it or the store grows for the life of the app. Three paths
|
|
6869
|
+
* end one: an ownership `close`, the chrome's close button, and a webContents
|
|
6870
|
+
* that dies on its own; the two nonce re-mints (hand-over and its revocation)
|
|
6871
|
+
* orphan one the same way. A stale receipt is inert — a new token can never
|
|
6872
|
+
* match it — which is why this is hygiene rather than a leak of authority
|
|
6873
|
+
* (review round 1, N1), and it runs BEFORE the token changes so the entry it
|
|
6874
|
+
* drops is the one that was live.
|
|
6875
|
+
*/
|
|
6876
|
+
dropReceipt(tabId) {
|
|
6877
|
+
const record = this.registry.get(tabId);
|
|
6878
|
+
const token = record ? surfaceToken(record) : null;
|
|
6879
|
+
if (token) this.approvals.forgetDocument(token);
|
|
6880
|
+
}
|
|
6454
6881
|
/** Answer a pending consent prompt. Reached only from the renderer IPC, whose
|
|
6455
6882
|
* handler checks the sender first. */
|
|
6456
6883
|
respondToConsent(entryId, decision) {
|
|
@@ -6727,12 +7154,13 @@ class OwnershipLedger {
|
|
|
6727
7154
|
true
|
|
6728
7155
|
);
|
|
6729
7156
|
if (params.tab) {
|
|
6730
|
-
if (existing?.tab !== params.tab) {
|
|
7157
|
+
if (existing?.tab !== params.tab && (existing || this.scopeOwning(String(params.tab)) || !this.hooks.mayAdopt?.(String(params.tab), session))) {
|
|
6731
7158
|
throw new BridgeCommandError(
|
|
6732
7159
|
"owner_refused",
|
|
6733
7160
|
"tab does not belong to allocation"
|
|
6734
7161
|
);
|
|
6735
7162
|
}
|
|
7163
|
+
this.recordAllocation(params, String(params.tab), "allocated");
|
|
6736
7164
|
return handler();
|
|
6737
7165
|
}
|
|
6738
7166
|
if (existing?.tab && this.hooks.isLive(existing.tab)) {
|
|
@@ -6748,7 +7176,24 @@ class OwnershipLedger {
|
|
|
6748
7176
|
});
|
|
6749
7177
|
}
|
|
6750
7178
|
this.recordAllocation(params, "", "allocating");
|
|
6751
|
-
|
|
7179
|
+
try {
|
|
7180
|
+
const result2 = await handler();
|
|
7181
|
+
if (typeof result2.tab !== "string" || !this.hooks.isLive(result2.tab)) {
|
|
7182
|
+
throw new BridgeCommandError(
|
|
7183
|
+
"owner_refused",
|
|
7184
|
+
"allocation did not return a live browser capability"
|
|
7185
|
+
);
|
|
7186
|
+
}
|
|
7187
|
+
this.recordAllocation(params, result2.tab, "allocated");
|
|
7188
|
+
return result2;
|
|
7189
|
+
} catch (error) {
|
|
7190
|
+
this.mutate(params, (scope2) => {
|
|
7191
|
+
const allocation = scope2.allocations[String(params.allocation_id)];
|
|
7192
|
+
if (allocation && (!allocation.tab || !this.hooks.isLive(allocation.tab)))
|
|
7193
|
+
allocation.state = "closed";
|
|
7194
|
+
});
|
|
7195
|
+
throw error;
|
|
7196
|
+
}
|
|
6752
7197
|
}
|
|
6753
7198
|
const scope = this.mutate(
|
|
6754
7199
|
params,
|
|
@@ -6791,6 +7236,7 @@ class OwnershipLedger {
|
|
|
6791
7236
|
let pending = false;
|
|
6792
7237
|
for (const allocation of Object.values(scope.allocations)) {
|
|
6793
7238
|
if (!allocation.tab || !this.hooks.isLive(allocation.tab)) {
|
|
7239
|
+
if (allocation.tab) allocation.state = "closed";
|
|
6794
7240
|
if (["allocating", "allocated", "cleanup_pending"].includes(
|
|
6795
7241
|
allocation.state
|
|
6796
7242
|
)) {
|
|
@@ -6799,6 +7245,7 @@ class OwnershipLedger {
|
|
|
6799
7245
|
continue;
|
|
6800
7246
|
}
|
|
6801
7247
|
const closed = await this.hooks.closeTab(allocation.tab);
|
|
7248
|
+
allocation.state = closed ? "closed" : "cleanup_pending";
|
|
6802
7249
|
if (!closed) pending = true;
|
|
6803
7250
|
}
|
|
6804
7251
|
return { state: pending ? "pending" : "closed" };
|
|
@@ -6814,7 +7261,14 @@ class OwnershipLedger {
|
|
|
6814
7261
|
"tab does not belong to this browser owner"
|
|
6815
7262
|
);
|
|
6816
7263
|
}
|
|
6817
|
-
|
|
7264
|
+
const result = await handler();
|
|
7265
|
+
if (method === "close" && params.tab) {
|
|
7266
|
+
for (const allocation of Object.values(scope.allocations)) {
|
|
7267
|
+
if (allocation.tab === params.tab && !this.hooks.isLive(allocation.tab))
|
|
7268
|
+
allocation.state = "closed";
|
|
7269
|
+
}
|
|
7270
|
+
}
|
|
7271
|
+
return result;
|
|
6818
7272
|
};
|
|
6819
7273
|
const run = previous.catch(() => {
|
|
6820
7274
|
}).then(operate);
|
|
@@ -7219,6 +7673,7 @@ async function handle(req, res, options) {
|
|
|
7219
7673
|
}
|
|
7220
7674
|
}
|
|
7221
7675
|
}
|
|
7676
|
+
const PSL_RULES = "ac\ncom.ac\nedu.ac\ngov.ac\nmil.ac\nnet.ac\norg.ac\nad\nae\nac.ae\nco.ae\ngov.ae\nmil.ae\nnet.ae\norg.ae\nsch.ae\naero\nairline.aero\nairport.aero\naccident-investigation.aero\naccident-prevention.aero\naerobatic.aero\naeroclub.aero\naerodrome.aero\nagents.aero\nair-surveillance.aero\nair-traffic-control.aero\naircraft.aero\nairtraffic.aero\nambulance.aero\nassociation.aero\nauthor.aero\nballooning.aero\nbroker.aero\ncaa.aero\ncargo.aero\ncatering.aero\ncertification.aero\nchampionship.aero\ncharter.aero\ncivilaviation.aero\nclub.aero\nconference.aero\nconsultant.aero\nconsulting.aero\ncontrol.aero\ncouncil.aero\ncrew.aero\ndesign.aero\ndgca.aero\neducator.aero\nemergency.aero\nengine.aero\nengineer.aero\nentertainment.aero\nequipment.aero\nexchange.aero\nexpress.aero\nfederation.aero\nflight.aero\nfreight.aero\nfuel.aero\ngliding.aero\ngovernment.aero\ngroundhandling.aero\ngroup.aero\nhanggliding.aero\nhomebuilt.aero\ninsurance.aero\njournal.aero\njournalist.aero\nleasing.aero\nlogistics.aero\nmagazine.aero\nmaintenance.aero\nmarketplace.aero\nmedia.aero\nmicrolight.aero\nmodelling.aero\nnavigation.aero\nparachuting.aero\nparagliding.aero\npassenger-association.aero\npilot.aero\npress.aero\nproduction.aero\nrecreation.aero\nrepbody.aero\nres.aero\nresearch.aero\nrotorcraft.aero\nsafety.aero\nscientist.aero\nservices.aero\nshow.aero\nskydiving.aero\nsoftware.aero\nstudent.aero\ntaxi.aero\ntrader.aero\ntrading.aero\ntrainer.aero\nunion.aero\nworkinggroup.aero\nworks.aero\naf\ncom.af\nedu.af\ngov.af\nnet.af\norg.af\nag\nco.ag\ncom.ag\nnet.ag\nnom.ag\norg.ag\nai\ncom.ai\nnet.ai\noff.ai\norg.ai\nal\ncom.al\nedu.al\ngov.al\nmil.al\nnet.al\norg.al\nam\nco.am\ncom.am\ncommune.am\nnet.am\norg.am\nao\nco.ao\ned.ao\nedu.ao\ngov.ao\ngv.ao\nit.ao\nog.ao\norg.ao\npb.ao\naq\nar\nbet.ar\ncom.ar\ncoop.ar\nedu.ar\ngob.ar\ngov.ar\nint.ar\nmil.ar\nmusica.ar\nmutual.ar\nnet.ar\norg.ar\nseg.ar\nsenasa.ar\ntur.ar\narpa\ne164.arpa\nhome.arpa\nin-addr.arpa\nip6.arpa\niris.arpa\nuri.arpa\nurn.arpa\nas\ngov.as\nasia\nat\nac.at\nsth.ac.at\nco.at\ngv.at\nor.at\nau\nasn.au\ncom.au\nedu.au\ngov.au\nid.au\nnet.au\norg.au\nconf.au\noz.au\nact.au\nnsw.au\nnt.au\nqld.au\nsa.au\ntas.au\nvic.au\nwa.au\nact.edu.au\ncatholic.edu.au\nnsw.edu.au\nnt.edu.au\nqld.edu.au\nsa.edu.au\ntas.edu.au\nvic.edu.au\nwa.edu.au\nqld.gov.au\nsa.gov.au\ntas.gov.au\nvic.gov.au\nwa.gov.au\naw\ncom.aw\nax\naz\nbiz.az\nco.az\ncom.az\nedu.az\ngov.az\ninfo.az\nint.az\nmil.az\nname.az\nnet.az\norg.az\npp.az\npro.az\nba\ncom.ba\nedu.ba\ngov.ba\nmil.ba\nnet.ba\norg.ba\nbb\nbiz.bb\nco.bb\ncom.bb\nedu.bb\ngov.bb\ninfo.bb\nnet.bb\norg.bb\nstore.bb\ntv.bb\nbd\nac.bd\nai.bd\nco.bd\ncom.bd\nedu.bd\ngov.bd\nid.bd\ninfo.bd\nit.bd\nmil.bd\nnet.bd\norg.bd\nsch.bd\ntv.bd\nbe\nac.be\nbf\ngov.bf\nbg\n0.bg\n1.bg\n2.bg\n3.bg\n4.bg\n5.bg\n6.bg\n7.bg\n8.bg\n9.bg\na.bg\nb.bg\nc.bg\nd.bg\ne.bg\nf.bg\ng.bg\nh.bg\ni.bg\nj.bg\nk.bg\nl.bg\nm.bg\nn.bg\no.bg\np.bg\nq.bg\nr.bg\ns.bg\nt.bg\nu.bg\nv.bg\nw.bg\nx.bg\ny.bg\nz.bg\nbh\ncom.bh\nedu.bh\ngov.bh\nnet.bh\norg.bh\nbi\nco.bi\ncom.bi\nedu.bi\nor.bi\norg.bi\nbiz\nbj\nafrica.bj\nagro.bj\narchitectes.bj\nassur.bj\navocats.bj\nco.bj\ncom.bj\neco.bj\necono.bj\nedu.bj\ninfo.bj\nloisirs.bj\nmoney.bj\nnet.bj\norg.bj\note.bj\nrestaurant.bj\nresto.bj\ntourism.bj\nuniv.bj\nbm\ncom.bm\nedu.bm\ngov.bm\nnet.bm\norg.bm\nbn\ncom.bn\nedu.bn\ngov.bn\nnet.bn\norg.bn\nbo\ncom.bo\nedu.bo\ngob.bo\nint.bo\nmil.bo\nnet.bo\norg.bo\ntv.bo\nweb.bo\nacademia.bo\nagro.bo\narte.bo\nblog.bo\nbolivia.bo\nciencia.bo\ncooperativa.bo\ndemocracia.bo\ndeporte.bo\necologia.bo\neconomia.bo\nempresa.bo\nia.bo\nindigena.bo\nindustria.bo\ninfo.bo\nmedicina.bo\nmovimiento.bo\nmusica.bo\nnatural.bo\nnombre.bo\nnoticias.bo\npatria.bo\nplurinacional.bo\npolitica.bo\nprofesional.bo\npueblo.bo\nrevista.bo\nsalud.bo\ntecnologia.bo\ntksat.bo\ntransporte.bo\nwiki.bo\nbr\n9guacu.br\nabc.br\nadm.br\nadv.br\nagr.br\naju.br\nam.br\nanani.br\naparecida.br\napi.br\napp.br\narq.br\nart.br\nato.br\nb.br\nbarueri.br\nbelem.br\nbet.br\nbhz.br\nbib.br\nbio.br\nblog.br\nbmd.br\nboavista.br\nbsb.br\ncampinagrande.br\ncampinas.br\ncaxias.br\ncim.br\ncng.br\ncnt.br\ncom.br\ncontagem.br\ncoop.br\ncoz.br\ncri.br\ncuiaba.br\ncuritiba.br\ndef.br\ndes.br\ndet.br\ndev.br\necn.br\neco.br\nedu.br\nemp.br\nenf.br\neng.br\nesp.br\netc.br\neti.br\nfar.br\nfeira.br\nflog.br\nfloripa.br\nfm.br\nfnd.br\nfortal.br\nfot.br\nfoz.br\nfst.br\ng12.br\ngeo.br\nggf.br\ngoiania.br\ngov.br\nac.gov.br\nal.gov.br\nam.gov.br\nap.gov.br\nba.gov.br\nce.gov.br\ndf.gov.br\nes.gov.br\ngo.gov.br\nma.gov.br\nmg.gov.br\nms.gov.br\nmt.gov.br\npa.gov.br\npb.gov.br\npe.gov.br\npi.gov.br\npr.gov.br\nrj.gov.br\nrn.gov.br\nro.gov.br\nrr.gov.br\nrs.gov.br\nsc.gov.br\nse.gov.br\nsp.gov.br\nto.gov.br\ngru.br\nia.br\nimb.br\nind.br\ninf.br\njab.br\njampa.br\njdf.br\njoinville.br\njor.br\njus.br\nleg.br\nleilao.br\nlel.br\nlog.br\nlondrina.br\nmacapa.br\nmaceio.br\nmanaus.br\nmaringa.br\nmat.br\nmed.br\nmil.br\nmorena.br\nmp.br\nmus.br\nnatal.br\nnet.br\nniteroi.br\n*.nom.br\nnot.br\nntr.br\nodo.br\nong.br\norg.br\nosasco.br\npalmas.br\npoa.br\nppg.br\npro.br\npsc.br\npsi.br\npvh.br\nqsl.br\nradio.br\nrec.br\nrecife.br\nrep.br\nribeirao.br\nrio.br\nriobranco.br\nriopreto.br\nsalvador.br\nsampa.br\nsantamaria.br\nsantoandre.br\nsaobernardo.br\nsaogonca.br\nseg.br\nsjc.br\nslg.br\nslz.br\nsocial.br\nsorocaba.br\nsrv.br\ntaxi.br\ntc.br\ntec.br\nteo.br\nthe.br\ntmp.br\ntrd.br\ntur.br\ntv.br\nudi.br\nvet.br\nvix.br\nvlog.br\nwiki.br\nxyz.br\nzlg.br\nbs\ncom.bs\nedu.bs\ngov.bs\nnet.bs\norg.bs\nbt\ncom.bt\nedu.bt\ngov.bt\nnet.bt\norg.bt\nbv\nbw\nac.bw\nco.bw\ngov.bw\nnet.bw\norg.bw\nby\ngov.by\nmil.by\ncom.by\nof.by\nbz\nco.bz\ncom.bz\nedu.bz\ngov.bz\nnet.bz\norg.bz\nca\nab.ca\nbc.ca\nmb.ca\nnb.ca\nnf.ca\nnl.ca\nns.ca\nnt.ca\nnu.ca\non.ca\npe.ca\nqc.ca\nsk.ca\nyk.ca\ngc.ca\ncat\ncc\ncd\ngov.cd\ncf\ncg\nch\nci\nac.ci\nxn--aroport-bya.ci\nasso.ci\nco.ci\ncom.ci\ned.ci\nedu.ci\ngo.ci\ngouv.ci\nint.ci\nnet.ci\nor.ci\norg.ci\n*.ck\n!www.ck\ncl\nco.cl\ngob.cl\ngov.cl\nmil.cl\ncm\nco.cm\ncom.cm\ngov.cm\nnet.cm\ncn\nac.cn\ncom.cn\nedu.cn\ngov.cn\nmil.cn\nnet.cn\norg.cn\nxn--55qx5d.cn\nxn--od0alg.cn\nxn--io0a7i.cn\nah.cn\nbj.cn\ncq.cn\nfj.cn\ngd.cn\ngs.cn\ngx.cn\ngz.cn\nha.cn\nhb.cn\nhe.cn\nhi.cn\nhk.cn\nhl.cn\nhn.cn\njl.cn\njs.cn\njx.cn\nln.cn\nmo.cn\nnm.cn\nnx.cn\nqh.cn\nsc.cn\nsd.cn\nsh.cn\nsn.cn\nsx.cn\ntj.cn\ntw.cn\nxj.cn\nxz.cn\nyn.cn\nzj.cn\nco\ncom.co\nedu.co\ngov.co\nmil.co\nnet.co\nnom.co\norg.co\ncom\ncoop\ncr\nac.cr\nco.cr\ned.cr\nfi.cr\ngo.cr\nor.cr\nsa.cr\ncu\ncom.cu\nedu.cu\ngob.cu\ninf.cu\nnat.cu\nnet.cu\norg.cu\ncv\ncom.cv\nedu.cv\nid.cv\nint.cv\nnet.cv\nnome.cv\norg.cv\npubl.cv\ncw\ncom.cw\nedu.cw\nnet.cw\norg.cw\ncx\ngov.cx\ncy\nac.cy\nbiz.cy\ncom.cy\nekloges.cy\ngov.cy\nltd.cy\nmil.cy\nnet.cy\norg.cy\npress.cy\npro.cy\ntm.cy\ncz\ngov.cz\nde\ndj\ndk\ndm\nco.dm\ncom.dm\nedu.dm\ngov.dm\nnet.dm\norg.dm\ndo\nart.do\ncom.do\nedu.do\ngob.do\ngov.do\nmil.do\nnet.do\norg.do\nsld.do\nweb.do\ndz\nart.dz\nasso.dz\ncom.dz\nedu.dz\ngov.dz\nnet.dz\norg.dz\npol.dz\nsoc.dz\ntm.dz\nec\nabg.ec\nadm.ec\nagron.ec\narqt.ec\nart.ec\nbar.ec\nchef.ec\ncom.ec\ncont.ec\ncpa.ec\ncue.ec\ndent.ec\ndgn.ec\ndisco.ec\ndoc.ec\nedu.ec\neng.ec\nesm.ec\nfin.ec\nfot.ec\ngal.ec\ngob.ec\ngov.ec\ngye.ec\nibr.ec\ninfo.ec\nk12.ec\nlat.ec\nloj.ec\nmed.ec\nmil.ec\nmktg.ec\nmon.ec\nnet.ec\nntr.ec\nodont.ec\norg.ec\npro.ec\nprof.ec\npsic.ec\npsiq.ec\npub.ec\nrio.ec\nrrpp.ec\nsal.ec\ntech.ec\ntul.ec\ntur.ec\nuio.ec\nvet.ec\nxxx.ec\nedu\nee\naip.ee\ncom.ee\nedu.ee\nfie.ee\ngov.ee\nlib.ee\nmed.ee\norg.ee\npri.ee\nriik.ee\neg\nac.eg\ncom.eg\nedu.eg\neun.eg\ngov.eg\ninfo.eg\nme.eg\nmil.eg\nname.eg\nnet.eg\norg.eg\nsci.eg\nsport.eg\ntv.eg\n*.er\nes\ncom.es\nedu.es\ngob.es\nnom.es\norg.es\net\nbiz.et\ncom.et\nedu.et\ngov.et\ninfo.et\nname.et\nnet.et\norg.et\neu\nfi\naland.fi\nfj\nac.fj\nbiz.fj\ncom.fj\nedu.fj\ngov.fj\nid.fj\ninfo.fj\nmil.fj\nname.fj\nnet.fj\norg.fj\npro.fj\n*.fk\nfm\ncom.fm\nedu.fm\nnet.fm\norg.fm\nfo\nfr\nasso.fr\ncom.fr\ngouv.fr\nnom.fr\nprd.fr\ntm.fr\navoues.fr\ncci.fr\ngreta.fr\nhuissier-justice.fr\nga\ngb\ngd\nedu.gd\ngov.gd\nge\ncom.ge\ncyb.ge\nedu.ge\ngov.ge\nllc.ge\nnet.ge\nonline.ge\norg.ge\npvt.ge\nschool.ge\ntnx.ge\ngf\ngg\nco.gg\nnet.gg\norg.gg\ngh\nbiz.gh\ncom.gh\nedu.gh\ngov.gh\nmil.gh\nnet.gh\norg.gh\ngi\ncom.gi\nedu.gi\ngov.gi\nltd.gi\nmod.gi\norg.gi\ngl\nco.gl\ncom.gl\nedu.gl\nnet.gl\norg.gl\ngm\ngn\nac.gn\ncom.gn\nedu.gn\ngov.gn\nnet.gn\norg.gn\ngov\ngp\nasso.gp\ncom.gp\nedu.gp\nmobi.gp\nnet.gp\norg.gp\ngq\ngr\ncom.gr\nedu.gr\ngov.gr\nnet.gr\norg.gr\ngs\ngt\ncom.gt\nedu.gt\ngob.gt\nind.gt\nmil.gt\nnet.gt\norg.gt\ngu\ncom.gu\nedu.gu\ngov.gu\nguam.gu\ninfo.gu\nnet.gu\norg.gu\nweb.gu\ngw\ngy\nco.gy\ncom.gy\nedu.gy\ngov.gy\nnet.gy\norg.gy\nhk\ncom.hk\nedu.hk\ngov.hk\nidv.hk\nnet.hk\norg.hk\nxn--ciqpn.hk\nxn--gmqw5a.hk\nxn--55qx5d.hk\nxn--mxtq1m.hk\nxn--lcvr32d.hk\nxn--wcvs22d.hk\nxn--gmq050i.hk\nxn--uc0atv.hk\nxn--uc0ay4a.hk\nxn--od0alg.hk\nxn--zf0avx.hk\nxn--mk0axi.hk\nxn--tn0ag.hk\nxn--od0aq3b.hk\nxn--io0a7i.hk\nhm\nhn\ncom.hn\nedu.hn\ngob.hn\nmil.hn\nnet.hn\norg.hn\nhr\ncom.hr\nfrom.hr\niz.hr\nname.hr\nht\nadult.ht\nart.ht\nasso.ht\ncom.ht\ncoop.ht\nedu.ht\nfirm.ht\ngouv.ht\ninfo.ht\nmed.ht\nnet.ht\norg.ht\nperso.ht\npol.ht\npro.ht\nrel.ht\nshop.ht\nhu\n2000.hu\nagrar.hu\nbolt.hu\ncasino.hu\ncity.hu\nco.hu\nerotica.hu\nerotika.hu\nfilm.hu\nforum.hu\ngames.hu\nhotel.hu\ninfo.hu\ningatlan.hu\njogasz.hu\nkonyvelo.hu\nlakas.hu\nmedia.hu\nnews.hu\norg.hu\npriv.hu\nreklam.hu\nsex.hu\nshop.hu\nsport.hu\nsuli.hu\nszex.hu\ntm.hu\ntozsde.hu\nutazas.hu\nvideo.hu\nid\nac.id\nai.id\nbiz.id\nco.id\ndesa.id\ngo.id\nkop.id\nmil.id\nmy.id\nnet.id\nor.id\nponpes.id\nsch.id\nweb.id\nxn--9tfky.id\nie\ngov.ie\nil\nac.il\nco.il\ngov.il\nidf.il\nk12.il\nmuni.il\nnet.il\norg.il\nxn--4dbrk0ce\nxn--4dbgdty6c.xn--4dbrk0ce\nxn--5dbhl8d.xn--4dbrk0ce\nxn--8dbq2a.xn--4dbrk0ce\nxn--hebda8b.xn--4dbrk0ce\nim\nac.im\nco.im\nltd.co.im\nplc.co.im\ncom.im\nnet.im\norg.im\ntt.im\ntv.im\nin\n5g.in\n6g.in\nac.in\naero.in\nai.in\nalumni.in\nam.in\nbank.in\nbihar.in\nbiz.in\nbusiness.in\nca.in\ncn.in\nco.in\ncom.in\ncoop.in\ncs.in\ndelhi.in\ndr.in\nedu.in\ner.in\nfin.in\nfirm.in\ngen.in\ngov.in\ngujarat.in\nind.in\ninfo.in\nint.in\ninternet.in\nio.in\nme.in\nmil.in\nnet.in\nnic.in\norg.in\npg.in\npost.in\npro.in\nres.in\nschool.in\ntravel.in\ntv.in\nub.in\nuk.in\nup.in\nus.in\ninfo\nint\neu.int\nio\nco.io\ncom.io\nedu.io\ngov.io\nmil.io\nnet.io\nnom.io\norg.io\niq\ncom.iq\nedu.iq\ngov.iq\nmil.iq\nnet.iq\norg.iq\nir\nac.ir\nco.ir\ngov.ir\nid.ir\nnet.ir\norg.ir\nsch.ir\nxn--mgba3a4f16a.ir\nxn--mgba3a4fra.ir\nis\nit\nedu.it\ngov.it\nabr.it\nabruzzo.it\naosta-valley.it\naostavalley.it\nbas.it\nbasilicata.it\ncal.it\ncalabria.it\ncam.it\ncampania.it\nemilia-romagna.it\nemiliaromagna.it\nemr.it\nfriuli-v-giulia.it\nfriuli-ve-giulia.it\nfriuli-vegiulia.it\nfriuli-venezia-giulia.it\nfriuli-veneziagiulia.it\nfriuli-vgiulia.it\nfriuliv-giulia.it\nfriulive-giulia.it\nfriulivegiulia.it\nfriulivenezia-giulia.it\nfriuliveneziagiulia.it\nfriulivgiulia.it\nfvg.it\nlaz.it\nlazio.it\nlig.it\nliguria.it\nlom.it\nlombardia.it\nlombardy.it\nlucania.it\nmar.it\nmarche.it\nmol.it\nmolise.it\npiedmont.it\npiemonte.it\npmn.it\npug.it\npuglia.it\nsar.it\nsardegna.it\nsardinia.it\nsic.it\nsicilia.it\nsicily.it\ntaa.it\ntos.it\ntoscana.it\ntrentin-sud-tirol.it\nxn--trentin-sd-tirol-rzb.it\ntrentin-sudtirol.it\nxn--trentin-sdtirol-7vb.it\ntrentin-sued-tirol.it\ntrentin-suedtirol.it\ntrentino-a-adige.it\ntrentino-aadige.it\ntrentino-alto-adige.it\ntrentino-altoadige.it\ntrentino-s-tirol.it\ntrentino-stirol.it\ntrentino-sud-tirol.it\nxn--trentino-sd-tirol-c3b.it\ntrentino-sudtirol.it\nxn--trentino-sdtirol-szb.it\ntrentino-sued-tirol.it\ntrentino-suedtirol.it\ntrentinoa-adige.it\ntrentinoaadige.it\ntrentinoalto-adige.it\ntrentinoaltoadige.it\ntrentinos-tirol.it\ntrentinostirol.it\ntrentinosud-tirol.it\nxn--trentinosd-tirol-rzb.it\nxn--trentinosdtirol-7vb.it\ntrentinosued-tirol.it\ntrentinosuedtirol.it\ntrentinsud-tirol.it\nxn--trentinsd-tirol-6vb.it\ntrentinsudtirol.it\nxn--trentinsdtirol-nsb.it\ntrentinsued-tirol.it\ntrentinsuedtirol.it\ntuscany.it\numb.it\numbria.it\nval-d-aosta.it\nval-daosta.it\nvald-aosta.it\nvalle-aosta.it\nvalle-d-aosta.it\nvalle-daosta.it\nvalleaosta.it\nvalled-aosta.it\nvalledaosta.it\nvallee-aoste.it\nxn--valle-aoste-ebb.it\nvallee-d-aoste.it\nxn--valle-d-aoste-ehb.it\nvalleeaoste.it\nxn--valleaoste-e7a.it\nvalleedaoste.it\nxn--valledaoste-ebb.it\nvao.it\nvda.it\nven.it\nveneto.it\nag.it\nagrigento.it\nal.it\nalessandria.it\nalto-adige.it\naltoadige.it\nan.it\nancona.it\nandria-barletta-trani.it\nandria-trani-barletta.it\nandriabarlettatrani.it\nandriatranibarletta.it\nao.it\naosta.it\naoste.it\nap.it\naq.it\nar.it\narezzo.it\nascoli-piceno.it\nascolipiceno.it\nasti.it\nat.it\nav.it\navellino.it\nba.it\nbalsan.it\nbalsan-sudtirol.it\nxn--balsan-sdtirol-nsb.it\nbalsan-suedtirol.it\nbari.it\nbarletta-trani-andria.it\nbarlettatraniandria.it\nbelluno.it\nbenevento.it\nbergamo.it\nbg.it\nbi.it\nbiella.it\nbl.it\nbn.it\nbo.it\nbologna.it\nbolzano.it\nbolzano-altoadige.it\nbozen.it\nbozen-sudtirol.it\nxn--bozen-sdtirol-2ob.it\nbozen-suedtirol.it\nbr.it\nbrescia.it\nbrindisi.it\nbs.it\nbt.it\nbulsan.it\nbulsan-sudtirol.it\nxn--bulsan-sdtirol-nsb.it\nbulsan-suedtirol.it\nbz.it\nca.it\ncagliari.it\ncaltanissetta.it\ncampidano-medio.it\ncampidanomedio.it\ncampobasso.it\ncarbonia-iglesias.it\ncarboniaiglesias.it\ncarrara-massa.it\ncarraramassa.it\ncaserta.it\ncatania.it\ncatanzaro.it\ncb.it\nce.it\ncesena-forli.it\nxn--cesena-forl-mcb.it\ncesenaforli.it\nxn--cesenaforl-i8a.it\nch.it\nchieti.it\nci.it\ncl.it\ncn.it\nco.it\ncomo.it\ncosenza.it\ncr.it\ncremona.it\ncrotone.it\ncs.it\nct.it\ncuneo.it\ncz.it\ndell-ogliastra.it\ndellogliastra.it\nen.it\nenna.it\nfc.it\nfe.it\nfermo.it\nferrara.it\nfg.it\nfi.it\nfirenze.it\nflorence.it\nfm.it\nfoggia.it\nforli-cesena.it\nxn--forl-cesena-fcb.it\nforlicesena.it\nxn--forlcesena-c8a.it\nfr.it\nfrosinone.it\nge.it\ngenoa.it\ngenova.it\ngo.it\ngorizia.it\ngr.it\ngrosseto.it\niglesias-carbonia.it\niglesiascarbonia.it\nim.it\nimperia.it\nis.it\nisernia.it\nkr.it\nla-spezia.it\nlaquila.it\nlaspezia.it\nlatina.it\nlc.it\nle.it\nlecce.it\nlecco.it\nli.it\nlivorno.it\nlo.it\nlodi.it\nlt.it\nlu.it\nlucca.it\nmacerata.it\nmantova.it\nmassa-carrara.it\nmassacarrara.it\nmatera.it\nmb.it\nmc.it\nme.it\nmedio-campidano.it\nmediocampidano.it\nmessina.it\nmi.it\nmilan.it\nmilano.it\nmn.it\nmo.it\nmodena.it\nmonza.it\nmonza-brianza.it\nmonza-e-della-brianza.it\nmonzabrianza.it\nmonzaebrianza.it\nmonzaedellabrianza.it\nms.it\nmt.it\nna.it\nnaples.it\nnapoli.it\nno.it\nnovara.it\nnu.it\nnuoro.it\nog.it\nogliastra.it\nolbia-tempio.it\nolbiatempio.it\nor.it\noristano.it\not.it\npa.it\npadova.it\npadua.it\npalermo.it\nparma.it\npavia.it\npc.it\npd.it\npe.it\nperugia.it\npesaro-urbino.it\npesarourbino.it\npescara.it\npg.it\npi.it\npiacenza.it\npisa.it\npistoia.it\npn.it\npo.it\npordenone.it\npotenza.it\npr.it\nprato.it\npt.it\npu.it\npv.it\npz.it\nra.it\nragusa.it\nravenna.it\nrc.it\nre.it\nreggio-calabria.it\nreggio-emilia.it\nreggiocalabria.it\nreggioemilia.it\nrg.it\nri.it\nrieti.it\nrimini.it\nrm.it\nrn.it\nro.it\nroma.it\nrome.it\nrovigo.it\nsa.it\nsalerno.it\nsassari.it\nsavona.it\nsi.it\nsiena.it\nsiracusa.it\nso.it\nsondrio.it\nsp.it\nsr.it\nss.it\nsu.it\nsud-sardegna.it\nsudsardegna.it\nxn--sdtirol-n2a.it\nsuedtirol.it\nsv.it\nta.it\ntaranto.it\nte.it\ntempio-olbia.it\ntempioolbia.it\nteramo.it\nterni.it\ntn.it\nto.it\ntorino.it\ntp.it\ntr.it\ntrani-andria-barletta.it\ntrani-barletta-andria.it\ntraniandriabarletta.it\ntranibarlettaandria.it\ntrapani.it\ntrentino.it\ntrento.it\ntreviso.it\ntrieste.it\nts.it\nturin.it\ntv.it\nud.it\nudine.it\nurbino-pesaro.it\nurbinopesaro.it\nva.it\nvarese.it\nvb.it\nvc.it\nve.it\nvenezia.it\nvenice.it\nverbania.it\nverbano-cusio-ossola.it\nvercelli.it\nverona.it\nvi.it\nvibo-valentia.it\nvibovalentia.it\nvicenza.it\nviterbo.it\nvr.it\nvs.it\nvt.it\nvv.it\nje\nco.je\nnet.je\norg.je\n*.jm\njo\nagri.jo\nai.jo\ncom.jo\nedu.jo\neng.jo\nfm.jo\ngov.jo\nmil.jo\nnet.jo\norg.jo\nper.jo\nphd.jo\nsch.jo\ntv.jo\njobs\njp\nac.jp\nad.jp\nco.jp\ned.jp\ngo.jp\ngr.jp\nlg.jp\nne.jp\nor.jp\naichi.jp\nakita.jp\naomori.jp\nchiba.jp\nehime.jp\nfukui.jp\nfukuoka.jp\nfukushima.jp\ngifu.jp\ngunma.jp\nhiroshima.jp\nhokkaido.jp\nhyogo.jp\nibaraki.jp\nishikawa.jp\niwate.jp\nkagawa.jp\nkagoshima.jp\nkanagawa.jp\nkochi.jp\nkumamoto.jp\nkyoto.jp\nmie.jp\nmiyagi.jp\nmiyazaki.jp\nnagano.jp\nnagasaki.jp\nnara.jp\nniigata.jp\noita.jp\nokayama.jp\nokinawa.jp\nosaka.jp\nsaga.jp\nsaitama.jp\nshiga.jp\nshimane.jp\nshizuoka.jp\ntochigi.jp\ntokushima.jp\ntokyo.jp\ntottori.jp\ntoyama.jp\nwakayama.jp\nyamagata.jp\nyamaguchi.jp\nyamanashi.jp\nxn--ehqz56n.jp\nxn--1lqs03n.jp\nxn--qqqt11m.jp\nxn--f6qx53a.jp\nxn--djrs72d6uy.jp\nxn--mkru45i.jp\nxn--0trq7p7nn.jp\nxn--5js045d.jp\nxn--kbrq7o.jp\nxn--pssu33l.jp\nxn--ntsq17g.jp\nxn--uisz3g.jp\nxn--6btw5a.jp\nxn--1ctwo.jp\nxn--6orx2r.jp\nxn--rht61e.jp\nxn--rht27z.jp\nxn--nit225k.jp\nxn--rht3d.jp\nxn--djty4k.jp\nxn--klty5x.jp\nxn--kltx9a.jp\nxn--kltp7d.jp\nxn--c3s14m.jp\nxn--vgu402c.jp\nxn--efvn9s.jp\nxn--1lqs71d.jp\nxn--4pvxs.jp\nxn--uuwu58a.jp\nxn--zbx025d.jp\nxn--8pvr4u.jp\nxn--5rtp49c.jp\nxn--ntso0iqx3a.jp\nxn--elqq16h.jp\nxn--4it168d.jp\nxn--klt787d.jp\nxn--rny31h.jp\nxn--7t0a264c.jp\nxn--uist22h.jp\nxn--8ltr62k.jp\nxn--2m4a15e.jp\nxn--32vp30h.jp\nxn--4it797k.jp\nxn--5rtq34k.jp\nxn--k7yn95e.jp\nxn--tor131o.jp\nxn--d5qv7z876c.jp\n*.kawasaki.jp\n!city.kawasaki.jp\n*.kitakyushu.jp\n!city.kitakyushu.jp\n*.kobe.jp\n!city.kobe.jp\n*.nagoya.jp\n!city.nagoya.jp\n*.sapporo.jp\n!city.sapporo.jp\n*.sendai.jp\n!city.sendai.jp\n*.yokohama.jp\n!city.yokohama.jp\naisai.aichi.jp\nama.aichi.jp\nanjo.aichi.jp\nasuke.aichi.jp\nchiryu.aichi.jp\nchita.aichi.jp\nfuso.aichi.jp\ngamagori.aichi.jp\nhanda.aichi.jp\nhazu.aichi.jp\nhekinan.aichi.jp\nhigashiura.aichi.jp\nichinomiya.aichi.jp\ninazawa.aichi.jp\ninuyama.aichi.jp\nisshiki.aichi.jp\niwakura.aichi.jp\nkanie.aichi.jp\nkariya.aichi.jp\nkasugai.aichi.jp\nkira.aichi.jp\nkiyosu.aichi.jp\nkomaki.aichi.jp\nkonan.aichi.jp\nkota.aichi.jp\nmihama.aichi.jp\nmiyoshi.aichi.jp\nnishio.aichi.jp\nnisshin.aichi.jp\nobu.aichi.jp\noguchi.aichi.jp\noharu.aichi.jp\nokazaki.aichi.jp\nowariasahi.aichi.jp\nseto.aichi.jp\nshikatsu.aichi.jp\nshinshiro.aichi.jp\nshitara.aichi.jp\ntahara.aichi.jp\ntakahama.aichi.jp\ntobishima.aichi.jp\ntoei.aichi.jp\ntogo.aichi.jp\ntokai.aichi.jp\ntokoname.aichi.jp\ntoyoake.aichi.jp\ntoyohashi.aichi.jp\ntoyokawa.aichi.jp\ntoyone.aichi.jp\ntoyota.aichi.jp\ntsushima.aichi.jp\nyatomi.aichi.jp\nakita.akita.jp\ndaisen.akita.jp\nfujisato.akita.jp\ngojome.akita.jp\nhachirogata.akita.jp\nhappou.akita.jp\nhigashinaruse.akita.jp\nhonjo.akita.jp\nhonjyo.akita.jp\nikawa.akita.jp\nkamikoani.akita.jp\nkamioka.akita.jp\nkatagami.akita.jp\nkazuno.akita.jp\nkitaakita.akita.jp\nkosaka.akita.jp\nkyowa.akita.jp\nmisato.akita.jp\nmitane.akita.jp\nmoriyoshi.akita.jp\nnikaho.akita.jp\nnoshiro.akita.jp\nodate.akita.jp\noga.akita.jp\nogata.akita.jp\nsemboku.akita.jp\nyokote.akita.jp\nyurihonjo.akita.jp\naomori.aomori.jp\ngonohe.aomori.jp\nhachinohe.aomori.jp\nhashikami.aomori.jp\nhiranai.aomori.jp\nhirosaki.aomori.jp\nitayanagi.aomori.jp\nkuroishi.aomori.jp\nmisawa.aomori.jp\nmutsu.aomori.jp\nnakadomari.aomori.jp\nnoheji.aomori.jp\noirase.aomori.jp\nowani.aomori.jp\nrokunohe.aomori.jp\nsannohe.aomori.jp\nshichinohe.aomori.jp\nshingo.aomori.jp\ntakko.aomori.jp\ntowada.aomori.jp\ntsugaru.aomori.jp\ntsuruta.aomori.jp\nabiko.chiba.jp\nasahi.chiba.jp\nchonan.chiba.jp\nchosei.chiba.jp\nchoshi.chiba.jp\nchuo.chiba.jp\nfunabashi.chiba.jp\nfuttsu.chiba.jp\nhanamigawa.chiba.jp\nichihara.chiba.jp\nichikawa.chiba.jp\nichinomiya.chiba.jp\ninzai.chiba.jp\nisumi.chiba.jp\nkamagaya.chiba.jp\nkamogawa.chiba.jp\nkashiwa.chiba.jp\nkatori.chiba.jp\nkatsuura.chiba.jp\nkimitsu.chiba.jp\nkisarazu.chiba.jp\nkozaki.chiba.jp\nkujukuri.chiba.jp\nkyonan.chiba.jp\nmatsudo.chiba.jp\nmidori.chiba.jp\nmihama.chiba.jp\nminamiboso.chiba.jp\nmobara.chiba.jp\nmutsuzawa.chiba.jp\nnagara.chiba.jp\nnagareyama.chiba.jp\nnarashino.chiba.jp\nnarita.chiba.jp\nnoda.chiba.jp\noamishirasato.chiba.jp\nomigawa.chiba.jp\nonjuku.chiba.jp\notaki.chiba.jp\nsakae.chiba.jp\nsakura.chiba.jp\nshimofusa.chiba.jp\nshirako.chiba.jp\nshiroi.chiba.jp\nshisui.chiba.jp\nsodegaura.chiba.jp\nsosa.chiba.jp\ntako.chiba.jp\ntateyama.chiba.jp\ntogane.chiba.jp\ntohnosho.chiba.jp\ntomisato.chiba.jp\nurayasu.chiba.jp\nyachimata.chiba.jp\nyachiyo.chiba.jp\nyokaichiba.chiba.jp\nyokoshibahikari.chiba.jp\nyotsukaido.chiba.jp\nainan.ehime.jp\nhonai.ehime.jp\nikata.ehime.jp\nimabari.ehime.jp\niyo.ehime.jp\nkamijima.ehime.jp\nkihoku.ehime.jp\nkumakogen.ehime.jp\nmasaki.ehime.jp\nmatsuno.ehime.jp\nmatsuyama.ehime.jp\nnamikata.ehime.jp\nniihama.ehime.jp\nozu.ehime.jp\nsaijo.ehime.jp\nseiyo.ehime.jp\nshikokuchuo.ehime.jp\ntobe.ehime.jp\ntoon.ehime.jp\nuchiko.ehime.jp\nuwajima.ehime.jp\nyawatahama.ehime.jp\nechizen.fukui.jp\neiheiji.fukui.jp\nfukui.fukui.jp\nikeda.fukui.jp\nkatsuyama.fukui.jp\nmihama.fukui.jp\nminamiechizen.fukui.jp\nobama.fukui.jp\nohi.fukui.jp\nono.fukui.jp\nsabae.fukui.jp\nsakai.fukui.jp\ntakahama.fukui.jp\ntsuruga.fukui.jp\nwakasa.fukui.jp\nashiya.fukuoka.jp\nbuzen.fukuoka.jp\nchikugo.fukuoka.jp\nchikuho.fukuoka.jp\nchikujo.fukuoka.jp\nchikushino.fukuoka.jp\nchikuzen.fukuoka.jp\nchuo.fukuoka.jp\ndazaifu.fukuoka.jp\nfukuchi.fukuoka.jp\nhakata.fukuoka.jp\nhigashi.fukuoka.jp\nhirokawa.fukuoka.jp\nhisayama.fukuoka.jp\niizuka.fukuoka.jp\ninatsuki.fukuoka.jp\nkaho.fukuoka.jp\nkasuga.fukuoka.jp\nkasuya.fukuoka.jp\nkawara.fukuoka.jp\nkeisen.fukuoka.jp\nkoga.fukuoka.jp\nkurate.fukuoka.jp\nkurogi.fukuoka.jp\nkurume.fukuoka.jp\nminami.fukuoka.jp\nmiyako.fukuoka.jp\nmiyama.fukuoka.jp\nmiyawaka.fukuoka.jp\nmizumaki.fukuoka.jp\nmunakata.fukuoka.jp\nnakagawa.fukuoka.jp\nnakama.fukuoka.jp\nnishi.fukuoka.jp\nnogata.fukuoka.jp\nogori.fukuoka.jp\nokagaki.fukuoka.jp\nokawa.fukuoka.jp\noki.fukuoka.jp\nomuta.fukuoka.jp\nonga.fukuoka.jp\nonojo.fukuoka.jp\noto.fukuoka.jp\nsaigawa.fukuoka.jp\nsasaguri.fukuoka.jp\nshingu.fukuoka.jp\nshinyoshitomi.fukuoka.jp\nshonai.fukuoka.jp\nsoeda.fukuoka.jp\nsue.fukuoka.jp\ntachiarai.fukuoka.jp\ntagawa.fukuoka.jp\ntakata.fukuoka.jp\ntoho.fukuoka.jp\ntoyotsu.fukuoka.jp\ntsuiki.fukuoka.jp\nukiha.fukuoka.jp\numi.fukuoka.jp\nusui.fukuoka.jp\nyamada.fukuoka.jp\nyame.fukuoka.jp\nyanagawa.fukuoka.jp\nyukuhashi.fukuoka.jp\naizubange.fukushima.jp\naizumisato.fukushima.jp\naizuwakamatsu.fukushima.jp\nasakawa.fukushima.jp\nbandai.fukushima.jp\ndate.fukushima.jp\nfukushima.fukushima.jp\nfurudono.fukushima.jp\nfutaba.fukushima.jp\nhanawa.fukushima.jp\nhigashi.fukushima.jp\nhirata.fukushima.jp\nhirono.fukushima.jp\niitate.fukushima.jp\ninawashiro.fukushima.jp\nishikawa.fukushima.jp\niwaki.fukushima.jp\nizumizaki.fukushima.jp\nkagamiishi.fukushima.jp\nkaneyama.fukushima.jp\nkawamata.fukushima.jp\nkitakata.fukushima.jp\nkitashiobara.fukushima.jp\nkoori.fukushima.jp\nkoriyama.fukushima.jp\nkunimi.fukushima.jp\nmiharu.fukushima.jp\nmishima.fukushima.jp\nnamie.fukushima.jp\nnango.fukushima.jp\nnishiaizu.fukushima.jp\nnishigo.fukushima.jp\nokuma.fukushima.jp\nomotego.fukushima.jp\nono.fukushima.jp\notama.fukushima.jp\nsamegawa.fukushima.jp\nshimogo.fukushima.jp\nshirakawa.fukushima.jp\nshowa.fukushima.jp\nsoma.fukushima.jp\nsukagawa.fukushima.jp\ntaishin.fukushima.jp\ntamakawa.fukushima.jp\ntanagura.fukushima.jp\ntenei.fukushima.jp\nyabuki.fukushima.jp\nyamato.fukushima.jp\nyamatsuri.fukushima.jp\nyanaizu.fukushima.jp\nyugawa.fukushima.jp\nanpachi.gifu.jp\nena.gifu.jp\ngifu.gifu.jp\nginan.gifu.jp\ngodo.gifu.jp\ngujo.gifu.jp\nhashima.gifu.jp\nhichiso.gifu.jp\nhida.gifu.jp\nhigashishirakawa.gifu.jp\nibigawa.gifu.jp\nikeda.gifu.jp\nkakamigahara.gifu.jp\nkani.gifu.jp\nkasahara.gifu.jp\nkasamatsu.gifu.jp\nkawaue.gifu.jp\nkitagata.gifu.jp\nmino.gifu.jp\nminokamo.gifu.jp\nmitake.gifu.jp\nmizunami.gifu.jp\nmotosu.gifu.jp\nnakatsugawa.gifu.jp\nogaki.gifu.jp\nsakahogi.gifu.jp\nseki.gifu.jp\nsekigahara.gifu.jp\nshirakawa.gifu.jp\ntajimi.gifu.jp\ntakayama.gifu.jp\ntarui.gifu.jp\ntoki.gifu.jp\ntomika.gifu.jp\nwanouchi.gifu.jp\nyamagata.gifu.jp\nyaotsu.gifu.jp\nyoro.gifu.jp\nannaka.gunma.jp\nchiyoda.gunma.jp\nfujioka.gunma.jp\nhigashiagatsuma.gunma.jp\nisesaki.gunma.jp\nitakura.gunma.jp\nkanna.gunma.jp\nkanra.gunma.jp\nkatashina.gunma.jp\nkawaba.gunma.jp\nkiryu.gunma.jp\nkusatsu.gunma.jp\nmaebashi.gunma.jp\nmeiwa.gunma.jp\nmidori.gunma.jp\nminakami.gunma.jp\nnaganohara.gunma.jp\nnakanojo.gunma.jp\nnanmoku.gunma.jp\nnumata.gunma.jp\noizumi.gunma.jp\nora.gunma.jp\nota.gunma.jp\nshibukawa.gunma.jp\nshimonita.gunma.jp\nshinto.gunma.jp\nshowa.gunma.jp\ntakasaki.gunma.jp\ntakayama.gunma.jp\ntamamura.gunma.jp\ntatebayashi.gunma.jp\ntomioka.gunma.jp\ntsukiyono.gunma.jp\ntsumagoi.gunma.jp\nueno.gunma.jp\nyoshioka.gunma.jp\nasaminami.hiroshima.jp\ndaiwa.hiroshima.jp\netajima.hiroshima.jp\nfuchu.hiroshima.jp\nfukuyama.hiroshima.jp\nhatsukaichi.hiroshima.jp\nhigashihiroshima.hiroshima.jp\nhongo.hiroshima.jp\njinsekikogen.hiroshima.jp\nkaita.hiroshima.jp\nkui.hiroshima.jp\nkumano.hiroshima.jp\nkure.hiroshima.jp\nmihara.hiroshima.jp\nmiyoshi.hiroshima.jp\nnaka.hiroshima.jp\nonomichi.hiroshima.jp\nosakikamijima.hiroshima.jp\notake.hiroshima.jp\nsaka.hiroshima.jp\nsera.hiroshima.jp\nseranishi.hiroshima.jp\nshinichi.hiroshima.jp\nshobara.hiroshima.jp\ntakehara.hiroshima.jp\nabashiri.hokkaido.jp\nabira.hokkaido.jp\naibetsu.hokkaido.jp\nakabira.hokkaido.jp\nakkeshi.hokkaido.jp\nasahikawa.hokkaido.jp\nashibetsu.hokkaido.jp\nashoro.hokkaido.jp\nassabu.hokkaido.jp\natsuma.hokkaido.jp\nbibai.hokkaido.jp\nbiei.hokkaido.jp\nbifuka.hokkaido.jp\nbihoro.hokkaido.jp\nbiratori.hokkaido.jp\nchippubetsu.hokkaido.jp\nchitose.hokkaido.jp\ndate.hokkaido.jp\nebetsu.hokkaido.jp\nembetsu.hokkaido.jp\neniwa.hokkaido.jp\nerimo.hokkaido.jp\nesan.hokkaido.jp\nesashi.hokkaido.jp\nfukagawa.hokkaido.jp\nfukushima.hokkaido.jp\nfurano.hokkaido.jp\nfurubira.hokkaido.jp\nhaboro.hokkaido.jp\nhakodate.hokkaido.jp\nhamatonbetsu.hokkaido.jp\nhidaka.hokkaido.jp\nhigashikagura.hokkaido.jp\nhigashikawa.hokkaido.jp\nhiroo.hokkaido.jp\nhokuryu.hokkaido.jp\nhokuto.hokkaido.jp\nhonbetsu.hokkaido.jp\nhorokanai.hokkaido.jp\nhoronobe.hokkaido.jp\nikeda.hokkaido.jp\nimakane.hokkaido.jp\nishikari.hokkaido.jp\niwamizawa.hokkaido.jp\niwanai.hokkaido.jp\nkamifurano.hokkaido.jp\nkamikawa.hokkaido.jp\nkamishihoro.hokkaido.jp\nkamisunagawa.hokkaido.jp\nkamoenai.hokkaido.jp\nkayabe.hokkaido.jp\nkembuchi.hokkaido.jp\nkikonai.hokkaido.jp\nkimobetsu.hokkaido.jp\nkitahiroshima.hokkaido.jp\nkitami.hokkaido.jp\nkiyosato.hokkaido.jp\nkoshimizu.hokkaido.jp\nkunneppu.hokkaido.jp\nkuriyama.hokkaido.jp\nkuromatsunai.hokkaido.jp\nkushiro.hokkaido.jp\nkutchan.hokkaido.jp\nkyowa.hokkaido.jp\nmashike.hokkaido.jp\nmatsumae.hokkaido.jp\nmikasa.hokkaido.jp\nminamifurano.hokkaido.jp\nmombetsu.hokkaido.jp\nmoseushi.hokkaido.jp\nmukawa.hokkaido.jp\nmuroran.hokkaido.jp\nnaie.hokkaido.jp\nnakagawa.hokkaido.jp\nnakasatsunai.hokkaido.jp\nnakatombetsu.hokkaido.jp\nnanae.hokkaido.jp\nnanporo.hokkaido.jp\nnayoro.hokkaido.jp\nnemuro.hokkaido.jp\nniikappu.hokkaido.jp\nniki.hokkaido.jp\nnishiokoppe.hokkaido.jp\nnoboribetsu.hokkaido.jp\nnumata.hokkaido.jp\nobihiro.hokkaido.jp\nobira.hokkaido.jp\noketo.hokkaido.jp\nokoppe.hokkaido.jp\notaru.hokkaido.jp\notobe.hokkaido.jp\notofuke.hokkaido.jp\notoineppu.hokkaido.jp\noumu.hokkaido.jp\nozora.hokkaido.jp\npippu.hokkaido.jp\nrankoshi.hokkaido.jp\nrebun.hokkaido.jp\nrikubetsu.hokkaido.jp\nrishiri.hokkaido.jp\nrishirifuji.hokkaido.jp\nsaroma.hokkaido.jp\nsarufutsu.hokkaido.jp\nshakotan.hokkaido.jp\nshari.hokkaido.jp\nshibecha.hokkaido.jp\nshibetsu.hokkaido.jp\nshikabe.hokkaido.jp\nshikaoi.hokkaido.jp\nshimamaki.hokkaido.jp\nshimizu.hokkaido.jp\nshimokawa.hokkaido.jp\nshinshinotsu.hokkaido.jp\nshintoku.hokkaido.jp\nshiranuka.hokkaido.jp\nshiraoi.hokkaido.jp\nshiriuchi.hokkaido.jp\nsobetsu.hokkaido.jp\nsunagawa.hokkaido.jp\ntaiki.hokkaido.jp\ntakasu.hokkaido.jp\ntakikawa.hokkaido.jp\ntakinoue.hokkaido.jp\nteshikaga.hokkaido.jp\ntobetsu.hokkaido.jp\ntohma.hokkaido.jp\ntomakomai.hokkaido.jp\ntomari.hokkaido.jp\ntoya.hokkaido.jp\ntoyako.hokkaido.jp\ntoyotomi.hokkaido.jp\ntoyoura.hokkaido.jp\ntsubetsu.hokkaido.jp\ntsukigata.hokkaido.jp\nurakawa.hokkaido.jp\nurausu.hokkaido.jp\nuryu.hokkaido.jp\nutashinai.hokkaido.jp\nwakkanai.hokkaido.jp\nwassamu.hokkaido.jp\nyakumo.hokkaido.jp\nyoichi.hokkaido.jp\naioi.hyogo.jp\nakashi.hyogo.jp\nako.hyogo.jp\namagasaki.hyogo.jp\naogaki.hyogo.jp\nasago.hyogo.jp\nashiya.hyogo.jp\nawaji.hyogo.jp\nfukusaki.hyogo.jp\ngoshiki.hyogo.jp\nharima.hyogo.jp\nhimeji.hyogo.jp\nichikawa.hyogo.jp\ninagawa.hyogo.jp\nitami.hyogo.jp\nkakogawa.hyogo.jp\nkamigori.hyogo.jp\nkamikawa.hyogo.jp\nkasai.hyogo.jp\nkasuga.hyogo.jp\nkawanishi.hyogo.jp\nmiki.hyogo.jp\nminamiawaji.hyogo.jp\nnishinomiya.hyogo.jp\nnishiwaki.hyogo.jp\nono.hyogo.jp\nsanda.hyogo.jp\nsannan.hyogo.jp\nsasayama.hyogo.jp\nsayo.hyogo.jp\nshingu.hyogo.jp\nshinonsen.hyogo.jp\nshiso.hyogo.jp\nsumoto.hyogo.jp\ntaishi.hyogo.jp\ntaka.hyogo.jp\ntakarazuka.hyogo.jp\ntakasago.hyogo.jp\ntakino.hyogo.jp\ntamba.hyogo.jp\ntatsuno.hyogo.jp\ntoyooka.hyogo.jp\nyabu.hyogo.jp\nyashiro.hyogo.jp\nyoka.hyogo.jp\nyokawa.hyogo.jp\nami.ibaraki.jp\nasahi.ibaraki.jp\nbando.ibaraki.jp\nchikusei.ibaraki.jp\ndaigo.ibaraki.jp\nfujishiro.ibaraki.jp\nhitachi.ibaraki.jp\nhitachinaka.ibaraki.jp\nhitachiomiya.ibaraki.jp\nhitachiota.ibaraki.jp\nibaraki.ibaraki.jp\nina.ibaraki.jp\ninashiki.ibaraki.jp\nitako.ibaraki.jp\niwama.ibaraki.jp\njoso.ibaraki.jp\nkamisu.ibaraki.jp\nkasama.ibaraki.jp\nkashima.ibaraki.jp\nkasumigaura.ibaraki.jp\nkoga.ibaraki.jp\nmiho.ibaraki.jp\nmito.ibaraki.jp\nmoriya.ibaraki.jp\nnaka.ibaraki.jp\nnamegata.ibaraki.jp\noarai.ibaraki.jp\nogawa.ibaraki.jp\nomitama.ibaraki.jp\nryugasaki.ibaraki.jp\nsakai.ibaraki.jp\nsakuragawa.ibaraki.jp\nshimodate.ibaraki.jp\nshimotsuma.ibaraki.jp\nshirosato.ibaraki.jp\nsowa.ibaraki.jp\nsuifu.ibaraki.jp\ntakahagi.ibaraki.jp\ntamatsukuri.ibaraki.jp\ntokai.ibaraki.jp\ntomobe.ibaraki.jp\ntone.ibaraki.jp\ntoride.ibaraki.jp\ntsuchiura.ibaraki.jp\ntsukuba.ibaraki.jp\nuchihara.ibaraki.jp\nushiku.ibaraki.jp\nyachiyo.ibaraki.jp\nyamagata.ibaraki.jp\nyawara.ibaraki.jp\nyuki.ibaraki.jp\nanamizu.ishikawa.jp\nhakui.ishikawa.jp\nhakusan.ishikawa.jp\nkaga.ishikawa.jp\nkahoku.ishikawa.jp\nkanazawa.ishikawa.jp\nkawakita.ishikawa.jp\nkomatsu.ishikawa.jp\nnakanoto.ishikawa.jp\nnanao.ishikawa.jp\nnomi.ishikawa.jp\nnonoichi.ishikawa.jp\nnoto.ishikawa.jp\nshika.ishikawa.jp\nsuzu.ishikawa.jp\ntsubata.ishikawa.jp\ntsurugi.ishikawa.jp\nuchinada.ishikawa.jp\nwajima.ishikawa.jp\nfudai.iwate.jp\nfujisawa.iwate.jp\nhanamaki.iwate.jp\nhiraizumi.iwate.jp\nhirono.iwate.jp\nichinohe.iwate.jp\nichinoseki.iwate.jp\niwaizumi.iwate.jp\niwate.iwate.jp\njoboji.iwate.jp\nkamaishi.iwate.jp\nkanegasaki.iwate.jp\nkarumai.iwate.jp\nkawai.iwate.jp\nkitakami.iwate.jp\nkuji.iwate.jp\nkunohe.iwate.jp\nkuzumaki.iwate.jp\nmiyako.iwate.jp\nmizusawa.iwate.jp\nmorioka.iwate.jp\nninohe.iwate.jp\nnoda.iwate.jp\nofunato.iwate.jp\noshu.iwate.jp\notsuchi.iwate.jp\nrikuzentakata.iwate.jp\nshiwa.iwate.jp\nshizukuishi.iwate.jp\nsumita.iwate.jp\ntanohata.iwate.jp\ntono.iwate.jp\nyahaba.iwate.jp\nyamada.iwate.jp\nayagawa.kagawa.jp\nhigashikagawa.kagawa.jp\nkanonji.kagawa.jp\nkotohira.kagawa.jp\nmanno.kagawa.jp\nmarugame.kagawa.jp\nmitoyo.kagawa.jp\nnaoshima.kagawa.jp\nsanuki.kagawa.jp\ntadotsu.kagawa.jp\ntakamatsu.kagawa.jp\ntonosho.kagawa.jp\nuchinomi.kagawa.jp\nutazu.kagawa.jp\nzentsuji.kagawa.jp\nakune.kagoshima.jp\namami.kagoshima.jp\nhioki.kagoshima.jp\nisa.kagoshima.jp\nisen.kagoshima.jp\nizumi.kagoshima.jp\nkagoshima.kagoshima.jp\nkanoya.kagoshima.jp\nkawanabe.kagoshima.jp\nkinko.kagoshima.jp\nkouyama.kagoshima.jp\nmakurazaki.kagoshima.jp\nmatsumoto.kagoshima.jp\nminamitane.kagoshima.jp\nnakatane.kagoshima.jp\nnishinoomote.kagoshima.jp\nsatsumasendai.kagoshima.jp\nsoo.kagoshima.jp\ntarumizu.kagoshima.jp\nyusui.kagoshima.jp\naikawa.kanagawa.jp\natsugi.kanagawa.jp\nayase.kanagawa.jp\nchigasaki.kanagawa.jp\nebina.kanagawa.jp\nfujisawa.kanagawa.jp\nhadano.kanagawa.jp\nhakone.kanagawa.jp\nhiratsuka.kanagawa.jp\nisehara.kanagawa.jp\nkaisei.kanagawa.jp\nkamakura.kanagawa.jp\nkiyokawa.kanagawa.jp\nmatsuda.kanagawa.jp\nminamiashigara.kanagawa.jp\nmiura.kanagawa.jp\nnakai.kanagawa.jp\nninomiya.kanagawa.jp\nodawara.kanagawa.jp\noi.kanagawa.jp\noiso.kanagawa.jp\nsagamihara.kanagawa.jp\nsamukawa.kanagawa.jp\ntsukui.kanagawa.jp\nyamakita.kanagawa.jp\nyamato.kanagawa.jp\nyokosuka.kanagawa.jp\nyugawara.kanagawa.jp\nzama.kanagawa.jp\nzushi.kanagawa.jp\naki.kochi.jp\ngeisei.kochi.jp\nhidaka.kochi.jp\nhigashitsuno.kochi.jp\nino.kochi.jp\nkagami.kochi.jp\nkami.kochi.jp\nkitagawa.kochi.jp\nkochi.kochi.jp\nmihara.kochi.jp\nmotoyama.kochi.jp\nmuroto.kochi.jp\nnahari.kochi.jp\nnakamura.kochi.jp\nnankoku.kochi.jp\nnishitosa.kochi.jp\nniyodogawa.kochi.jp\nochi.kochi.jp\nokawa.kochi.jp\notoyo.kochi.jp\notsuki.kochi.jp\nsakawa.kochi.jp\nsukumo.kochi.jp\nsusaki.kochi.jp\ntosa.kochi.jp\ntosashimizu.kochi.jp\ntoyo.kochi.jp\ntsuno.kochi.jp\numaji.kochi.jp\nyasuda.kochi.jp\nyusuhara.kochi.jp\namakusa.kumamoto.jp\narao.kumamoto.jp\naso.kumamoto.jp\nchoyo.kumamoto.jp\ngyokuto.kumamoto.jp\nkamiamakusa.kumamoto.jp\nkikuchi.kumamoto.jp\nkumamoto.kumamoto.jp\nmashiki.kumamoto.jp\nmifune.kumamoto.jp\nminamata.kumamoto.jp\nminamioguni.kumamoto.jp\nnagasu.kumamoto.jp\nnishihara.kumamoto.jp\noguni.kumamoto.jp\nozu.kumamoto.jp\nsumoto.kumamoto.jp\ntakamori.kumamoto.jp\nuki.kumamoto.jp\nuto.kumamoto.jp\nyamaga.kumamoto.jp\nyamato.kumamoto.jp\nyatsushiro.kumamoto.jp\nayabe.kyoto.jp\nfukuchiyama.kyoto.jp\nhigashiyama.kyoto.jp\nide.kyoto.jp\nine.kyoto.jp\njoyo.kyoto.jp\nkameoka.kyoto.jp\nkamo.kyoto.jp\nkita.kyoto.jp\nkizu.kyoto.jp\nkumiyama.kyoto.jp\nkyotamba.kyoto.jp\nkyotanabe.kyoto.jp\nkyotango.kyoto.jp\nmaizuru.kyoto.jp\nminami.kyoto.jp\nminamiyamashiro.kyoto.jp\nmiyazu.kyoto.jp\nmuko.kyoto.jp\nnagaokakyo.kyoto.jp\nnakagyo.kyoto.jp\nnantan.kyoto.jp\noyamazaki.kyoto.jp\nsakyo.kyoto.jp\nseika.kyoto.jp\ntanabe.kyoto.jp\nuji.kyoto.jp\nujitawara.kyoto.jp\nwazuka.kyoto.jp\nyamashina.kyoto.jp\nyawata.kyoto.jp\nasahi.mie.jp\ninabe.mie.jp\nise.mie.jp\nkameyama.mie.jp\nkawagoe.mie.jp\nkiho.mie.jp\nkisosaki.mie.jp\nkiwa.mie.jp\nkomono.mie.jp\nkumano.mie.jp\nkuwana.mie.jp\nmatsusaka.mie.jp\nmeiwa.mie.jp\nmihama.mie.jp\nminamiise.mie.jp\nmisugi.mie.jp\nmiyama.mie.jp\nnabari.mie.jp\nshima.mie.jp\nsuzuka.mie.jp\ntado.mie.jp\ntaiki.mie.jp\ntaki.mie.jp\ntamaki.mie.jp\ntoba.mie.jp\ntsu.mie.jp\nudono.mie.jp\nureshino.mie.jp\nwatarai.mie.jp\nyokkaichi.mie.jp\nfurukawa.miyagi.jp\nhigashimatsushima.miyagi.jp\nishinomaki.miyagi.jp\niwanuma.miyagi.jp\nkakuda.miyagi.jp\nkami.miyagi.jp\nkawasaki.miyagi.jp\nmarumori.miyagi.jp\nmatsushima.miyagi.jp\nminamisanriku.miyagi.jp\nmisato.miyagi.jp\nmurata.miyagi.jp\nnatori.miyagi.jp\nogawara.miyagi.jp\nohira.miyagi.jp\nonagawa.miyagi.jp\nosaki.miyagi.jp\nrifu.miyagi.jp\nsemine.miyagi.jp\nshibata.miyagi.jp\nshichikashuku.miyagi.jp\nshikama.miyagi.jp\nshiogama.miyagi.jp\nshiroishi.miyagi.jp\ntagajo.miyagi.jp\ntaiwa.miyagi.jp\ntome.miyagi.jp\ntomiya.miyagi.jp\nwakuya.miyagi.jp\nwatari.miyagi.jp\nyamamoto.miyagi.jp\nzao.miyagi.jp\naya.miyazaki.jp\nebino.miyazaki.jp\ngokase.miyazaki.jp\nhyuga.miyazaki.jp\nkadogawa.miyazaki.jp\nkawaminami.miyazaki.jp\nkijo.miyazaki.jp\nkitagawa.miyazaki.jp\nkitakata.miyazaki.jp\nkitaura.miyazaki.jp\nkobayashi.miyazaki.jp\nkunitomi.miyazaki.jp\nkushima.miyazaki.jp\nmimata.miyazaki.jp\nmiyakonojo.miyazaki.jp\nmiyazaki.miyazaki.jp\nmorotsuka.miyazaki.jp\nnichinan.miyazaki.jp\nnishimera.miyazaki.jp\nnobeoka.miyazaki.jp\nsaito.miyazaki.jp\nshiiba.miyazaki.jp\nshintomi.miyazaki.jp\ntakaharu.miyazaki.jp\ntakanabe.miyazaki.jp\ntakazaki.miyazaki.jp\ntsuno.miyazaki.jp\nachi.nagano.jp\nagematsu.nagano.jp\nanan.nagano.jp\naoki.nagano.jp\nasahi.nagano.jp\nazumino.nagano.jp\nchikuhoku.nagano.jp\nchikuma.nagano.jp\nchino.nagano.jp\nfujimi.nagano.jp\nhakuba.nagano.jp\nhara.nagano.jp\nhiraya.nagano.jp\niida.nagano.jp\niijima.nagano.jp\niiyama.nagano.jp\niizuna.nagano.jp\nikeda.nagano.jp\nikusaka.nagano.jp\nina.nagano.jp\nkaruizawa.nagano.jp\nkawakami.nagano.jp\nkiso.nagano.jp\nkisofukushima.nagano.jp\nkitaaiki.nagano.jp\nkomagane.nagano.jp\nkomoro.nagano.jp\nmatsukawa.nagano.jp\nmatsumoto.nagano.jp\nmiasa.nagano.jp\nminamiaiki.nagano.jp\nminamimaki.nagano.jp\nminamiminowa.nagano.jp\nminowa.nagano.jp\nmiyada.nagano.jp\nmiyota.nagano.jp\nmochizuki.nagano.jp\nnagano.nagano.jp\nnagawa.nagano.jp\nnagiso.nagano.jp\nnakagawa.nagano.jp\nnakano.nagano.jp\nnozawaonsen.nagano.jp\nobuse.nagano.jp\nogawa.nagano.jp\nokaya.nagano.jp\nomachi.nagano.jp\nomi.nagano.jp\nookuwa.nagano.jp\nooshika.nagano.jp\notaki.nagano.jp\notari.nagano.jp\nsakae.nagano.jp\nsakaki.nagano.jp\nsaku.nagano.jp\nsakuho.nagano.jp\nshimosuwa.nagano.jp\nshinanomachi.nagano.jp\nshiojiri.nagano.jp\nsuwa.nagano.jp\nsuzaka.nagano.jp\ntakagi.nagano.jp\ntakamori.nagano.jp\ntakayama.nagano.jp\ntateshina.nagano.jp\ntatsuno.nagano.jp\ntogakushi.nagano.jp\ntogura.nagano.jp\ntomi.nagano.jp\nueda.nagano.jp\nwada.nagano.jp\nyamagata.nagano.jp\nyamanouchi.nagano.jp\nyasaka.nagano.jp\nyasuoka.nagano.jp\nchijiwa.nagasaki.jp\nfutsu.nagasaki.jp\ngoto.nagasaki.jp\nhasami.nagasaki.jp\nhirado.nagasaki.jp\niki.nagasaki.jp\nisahaya.nagasaki.jp\nkawatana.nagasaki.jp\nkuchinotsu.nagasaki.jp\nmatsuura.nagasaki.jp\nnagasaki.nagasaki.jp\nobama.nagasaki.jp\nomura.nagasaki.jp\noseto.nagasaki.jp\nsaikai.nagasaki.jp\nsasebo.nagasaki.jp\nseihi.nagasaki.jp\nshimabara.nagasaki.jp\nshinkamigoto.nagasaki.jp\ntogitsu.nagasaki.jp\ntsushima.nagasaki.jp\nunzen.nagasaki.jp\nando.nara.jp\ngose.nara.jp\nheguri.nara.jp\nhigashiyoshino.nara.jp\nikaruga.nara.jp\nikoma.nara.jp\nkamikitayama.nara.jp\nkanmaki.nara.jp\nkashiba.nara.jp\nkashihara.nara.jp\nkatsuragi.nara.jp\nkawai.nara.jp\nkawakami.nara.jp\nkawanishi.nara.jp\nkoryo.nara.jp\nkurotaki.nara.jp\nmitsue.nara.jp\nmiyake.nara.jp\nnara.nara.jp\nnosegawa.nara.jp\noji.nara.jp\nouda.nara.jp\noyodo.nara.jp\nsakurai.nara.jp\nsango.nara.jp\nshimoichi.nara.jp\nshimokitayama.nara.jp\nshinjo.nara.jp\nsoni.nara.jp\ntakatori.nara.jp\ntawaramoto.nara.jp\ntenkawa.nara.jp\ntenri.nara.jp\nuda.nara.jp\nyamatokoriyama.nara.jp\nyamatotakada.nara.jp\nyamazoe.nara.jp\nyoshino.nara.jp\naga.niigata.jp\nagano.niigata.jp\ngosen.niigata.jp\nitoigawa.niigata.jp\nizumozaki.niigata.jp\njoetsu.niigata.jp\nkamo.niigata.jp\nkariwa.niigata.jp\nkashiwazaki.niigata.jp\nminamiuonuma.niigata.jp\nmitsuke.niigata.jp\nmuika.niigata.jp\nmurakami.niigata.jp\nmyoko.niigata.jp\nnagaoka.niigata.jp\nniigata.niigata.jp\nojiya.niigata.jp\nomi.niigata.jp\nsado.niigata.jp\nsanjo.niigata.jp\nseiro.niigata.jp\nseirou.niigata.jp\nsekikawa.niigata.jp\nshibata.niigata.jp\ntagami.niigata.jp\ntainai.niigata.jp\ntochio.niigata.jp\ntokamachi.niigata.jp\ntsubame.niigata.jp\ntsunan.niigata.jp\nuonuma.niigata.jp\nyahiko.niigata.jp\nyoita.niigata.jp\nyuzawa.niigata.jp\nbeppu.oita.jp\nbungoono.oita.jp\nbungotakada.oita.jp\nhasama.oita.jp\nhiji.oita.jp\nhimeshima.oita.jp\nhita.oita.jp\nkamitsue.oita.jp\nkokonoe.oita.jp\nkuju.oita.jp\nkunisaki.oita.jp\nkusu.oita.jp\noita.oita.jp\nsaiki.oita.jp\ntaketa.oita.jp\ntsukumi.oita.jp\nusa.oita.jp\nusuki.oita.jp\nyufu.oita.jp\nakaiwa.okayama.jp\nasakuchi.okayama.jp\nbizen.okayama.jp\nhayashima.okayama.jp\nibara.okayama.jp\nkagamino.okayama.jp\nkasaoka.okayama.jp\nkibichuo.okayama.jp\nkumenan.okayama.jp\nkurashiki.okayama.jp\nmaniwa.okayama.jp\nmisaki.okayama.jp\nnagi.okayama.jp\nniimi.okayama.jp\nnishiawakura.okayama.jp\nokayama.okayama.jp\nsatosho.okayama.jp\nsetouchi.okayama.jp\nshinjo.okayama.jp\nshoo.okayama.jp\nsoja.okayama.jp\ntakahashi.okayama.jp\ntamano.okayama.jp\ntsuyama.okayama.jp\nwake.okayama.jp\nyakage.okayama.jp\naguni.okinawa.jp\nginowan.okinawa.jp\nginoza.okinawa.jp\ngushikami.okinawa.jp\nhaebaru.okinawa.jp\nhigashi.okinawa.jp\nhirara.okinawa.jp\niheya.okinawa.jp\nishigaki.okinawa.jp\nishikawa.okinawa.jp\nitoman.okinawa.jp\nizena.okinawa.jp\nkadena.okinawa.jp\nkin.okinawa.jp\nkitadaito.okinawa.jp\nkitanakagusuku.okinawa.jp\nkumejima.okinawa.jp\nkunigami.okinawa.jp\nminamidaito.okinawa.jp\nmotobu.okinawa.jp\nnago.okinawa.jp\nnaha.okinawa.jp\nnakagusuku.okinawa.jp\nnakijin.okinawa.jp\nnanjo.okinawa.jp\nnishihara.okinawa.jp\nogimi.okinawa.jp\nokinawa.okinawa.jp\nonna.okinawa.jp\nshimoji.okinawa.jp\ntaketomi.okinawa.jp\ntarama.okinawa.jp\ntokashiki.okinawa.jp\ntomigusuku.okinawa.jp\ntonaki.okinawa.jp\nurasoe.okinawa.jp\nuruma.okinawa.jp\nyaese.okinawa.jp\nyomitan.okinawa.jp\nyonabaru.okinawa.jp\nyonaguni.okinawa.jp\nzamami.okinawa.jp\nabeno.osaka.jp\nchihayaakasaka.osaka.jp\nchuo.osaka.jp\ndaito.osaka.jp\nfujiidera.osaka.jp\nhabikino.osaka.jp\nhannan.osaka.jp\nhigashiosaka.osaka.jp\nhigashisumiyoshi.osaka.jp\nhigashiyodogawa.osaka.jp\nhirakata.osaka.jp\nibaraki.osaka.jp\nikeda.osaka.jp\nizumi.osaka.jp\nizumiotsu.osaka.jp\nizumisano.osaka.jp\nkadoma.osaka.jp\nkaizuka.osaka.jp\nkanan.osaka.jp\nkashiwara.osaka.jp\nkatano.osaka.jp\nkawachinagano.osaka.jp\nkishiwada.osaka.jp\nkita.osaka.jp\nkumatori.osaka.jp\nmatsubara.osaka.jp\nminato.osaka.jp\nminoh.osaka.jp\nmisaki.osaka.jp\nmoriguchi.osaka.jp\nneyagawa.osaka.jp\nnishi.osaka.jp\nnose.osaka.jp\nosakasayama.osaka.jp\nsakai.osaka.jp\nsayama.osaka.jp\nsennan.osaka.jp\nsettsu.osaka.jp\nshijonawate.osaka.jp\nshimamoto.osaka.jp\nsuita.osaka.jp\ntadaoka.osaka.jp\ntaishi.osaka.jp\ntajiri.osaka.jp\ntakaishi.osaka.jp\ntakatsuki.osaka.jp\ntondabayashi.osaka.jp\ntoyonaka.osaka.jp\ntoyono.osaka.jp\nyao.osaka.jp\nariake.saga.jp\narita.saga.jp\nfukudomi.saga.jp\ngenkai.saga.jp\nhamatama.saga.jp\nhizen.saga.jp\nimari.saga.jp\nkamimine.saga.jp\nkanzaki.saga.jp\nkaratsu.saga.jp\nkashima.saga.jp\nkitagata.saga.jp\nkitahata.saga.jp\nkiyama.saga.jp\nkouhoku.saga.jp\nkyuragi.saga.jp\nnishiarita.saga.jp\nogi.saga.jp\nomachi.saga.jp\nouchi.saga.jp\nsaga.saga.jp\nshiroishi.saga.jp\ntaku.saga.jp\ntara.saga.jp\ntosu.saga.jp\nyoshinogari.saga.jp\narakawa.saitama.jp\nasaka.saitama.jp\nchichibu.saitama.jp\nfujimi.saitama.jp\nfujimino.saitama.jp\nfukaya.saitama.jp\nhanno.saitama.jp\nhanyu.saitama.jp\nhasuda.saitama.jp\nhatogaya.saitama.jp\nhatoyama.saitama.jp\nhidaka.saitama.jp\nhigashichichibu.saitama.jp\nhigashimatsuyama.saitama.jp\nhonjo.saitama.jp\nina.saitama.jp\niruma.saitama.jp\niwatsuki.saitama.jp\nkamiizumi.saitama.jp\nkamikawa.saitama.jp\nkamisato.saitama.jp\nkasukabe.saitama.jp\nkawagoe.saitama.jp\nkawaguchi.saitama.jp\nkawajima.saitama.jp\nkazo.saitama.jp\nkitamoto.saitama.jp\nkoshigaya.saitama.jp\nkounosu.saitama.jp\nkuki.saitama.jp\nkumagaya.saitama.jp\nmatsubushi.saitama.jp\nminano.saitama.jp\nmisato.saitama.jp\nmiyashiro.saitama.jp\nmiyoshi.saitama.jp\nmoroyama.saitama.jp\nnagatoro.saitama.jp\nnamegawa.saitama.jp\nniiza.saitama.jp\nogano.saitama.jp\nogawa.saitama.jp\nogose.saitama.jp\nokegawa.saitama.jp\nomiya.saitama.jp\notaki.saitama.jp\nranzan.saitama.jp\nryokami.saitama.jp\nsaitama.saitama.jp\nsakado.saitama.jp\nsatte.saitama.jp\nsayama.saitama.jp\nshiki.saitama.jp\nshiraoka.saitama.jp\nsoka.saitama.jp\nsugito.saitama.jp\ntoda.saitama.jp\ntokigawa.saitama.jp\ntokorozawa.saitama.jp\ntsurugashima.saitama.jp\nurawa.saitama.jp\nwarabi.saitama.jp\nyashio.saitama.jp\nyokoze.saitama.jp\nyono.saitama.jp\nyorii.saitama.jp\nyoshida.saitama.jp\nyoshikawa.saitama.jp\nyoshimi.saitama.jp\naisho.shiga.jp\ngamo.shiga.jp\nhigashiomi.shiga.jp\nhikone.shiga.jp\nkoka.shiga.jp\nkonan.shiga.jp\nkosei.shiga.jp\nkoto.shiga.jp\nkusatsu.shiga.jp\nmaibara.shiga.jp\nmoriyama.shiga.jp\nnagahama.shiga.jp\nnishiazai.shiga.jp\nnotogawa.shiga.jp\nomihachiman.shiga.jp\notsu.shiga.jp\nritto.shiga.jp\nryuoh.shiga.jp\ntakashima.shiga.jp\ntakatsuki.shiga.jp\ntorahime.shiga.jp\ntoyosato.shiga.jp\nyasu.shiga.jp\nakagi.shimane.jp\nama.shimane.jp\ngotsu.shimane.jp\nhamada.shimane.jp\nhigashiizumo.shimane.jp\nhikawa.shimane.jp\nhikimi.shimane.jp\nizumo.shimane.jp\nkakinoki.shimane.jp\nmasuda.shimane.jp\nmatsue.shimane.jp\nmisato.shimane.jp\nnishinoshima.shimane.jp\nohda.shimane.jp\nokinoshima.shimane.jp\nokuizumo.shimane.jp\nshimane.shimane.jp\ntamayu.shimane.jp\ntsuwano.shimane.jp\nunnan.shimane.jp\nyakumo.shimane.jp\nyasugi.shimane.jp\nyatsuka.shimane.jp\narai.shizuoka.jp\natami.shizuoka.jp\nfuji.shizuoka.jp\nfujieda.shizuoka.jp\nfujikawa.shizuoka.jp\nfujinomiya.shizuoka.jp\nfukuroi.shizuoka.jp\ngotemba.shizuoka.jp\nhaibara.shizuoka.jp\nhamamatsu.shizuoka.jp\nhigashiizu.shizuoka.jp\nito.shizuoka.jp\niwata.shizuoka.jp\nizu.shizuoka.jp\nizunokuni.shizuoka.jp\nkakegawa.shizuoka.jp\nkannami.shizuoka.jp\nkawanehon.shizuoka.jp\nkawazu.shizuoka.jp\nkikugawa.shizuoka.jp\nkosai.shizuoka.jp\nmakinohara.shizuoka.jp\nmatsuzaki.shizuoka.jp\nminamiizu.shizuoka.jp\nmishima.shizuoka.jp\nmorimachi.shizuoka.jp\nnishiizu.shizuoka.jp\nnumazu.shizuoka.jp\nomaezaki.shizuoka.jp\nshimada.shizuoka.jp\nshimizu.shizuoka.jp\nshimoda.shizuoka.jp\nshizuoka.shizuoka.jp\nsusono.shizuoka.jp\nyaizu.shizuoka.jp\nyoshida.shizuoka.jp\nashikaga.tochigi.jp\nbato.tochigi.jp\nhaga.tochigi.jp\nichikai.tochigi.jp\niwafune.tochigi.jp\nkaminokawa.tochigi.jp\nkanuma.tochigi.jp\nkarasuyama.tochigi.jp\nkuroiso.tochigi.jp\nmashiko.tochigi.jp\nmibu.tochigi.jp\nmoka.tochigi.jp\nmotegi.tochigi.jp\nnasu.tochigi.jp\nnasushiobara.tochigi.jp\nnikko.tochigi.jp\nnishikata.tochigi.jp\nnogi.tochigi.jp\nohira.tochigi.jp\nohtawara.tochigi.jp\noyama.tochigi.jp\nsakura.tochigi.jp\nsano.tochigi.jp\nshimotsuke.tochigi.jp\nshioya.tochigi.jp\ntakanezawa.tochigi.jp\ntochigi.tochigi.jp\ntsuga.tochigi.jp\nujiie.tochigi.jp\nutsunomiya.tochigi.jp\nyaita.tochigi.jp\naizumi.tokushima.jp\nanan.tokushima.jp\nichiba.tokushima.jp\nitano.tokushima.jp\nkainan.tokushima.jp\nkomatsushima.tokushima.jp\nmatsushige.tokushima.jp\nmima.tokushima.jp\nminami.tokushima.jp\nmiyoshi.tokushima.jp\nmugi.tokushima.jp\nnakagawa.tokushima.jp\nnaruto.tokushima.jp\nsanagochi.tokushima.jp\nshishikui.tokushima.jp\ntokushima.tokushima.jp\nwajiki.tokushima.jp\nadachi.tokyo.jp\nakiruno.tokyo.jp\nakishima.tokyo.jp\naogashima.tokyo.jp\narakawa.tokyo.jp\nbunkyo.tokyo.jp\nchiyoda.tokyo.jp\nchofu.tokyo.jp\nchuo.tokyo.jp\nedogawa.tokyo.jp\nfuchu.tokyo.jp\nfussa.tokyo.jp\nhachijo.tokyo.jp\nhachioji.tokyo.jp\nhamura.tokyo.jp\nhigashikurume.tokyo.jp\nhigashimurayama.tokyo.jp\nhigashiyamato.tokyo.jp\nhino.tokyo.jp\nhinode.tokyo.jp\nhinohara.tokyo.jp\ninagi.tokyo.jp\nitabashi.tokyo.jp\nkatsushika.tokyo.jp\nkita.tokyo.jp\nkiyose.tokyo.jp\nkodaira.tokyo.jp\nkoganei.tokyo.jp\nkokubunji.tokyo.jp\nkomae.tokyo.jp\nkoto.tokyo.jp\nkouzushima.tokyo.jp\nkunitachi.tokyo.jp\nmachida.tokyo.jp\nmeguro.tokyo.jp\nminato.tokyo.jp\nmitaka.tokyo.jp\nmizuho.tokyo.jp\nmusashimurayama.tokyo.jp\nmusashino.tokyo.jp\nnakano.tokyo.jp\nnerima.tokyo.jp\nogasawara.tokyo.jp\nokutama.tokyo.jp\nome.tokyo.jp\noshima.tokyo.jp\nota.tokyo.jp\nsetagaya.tokyo.jp\nshibuya.tokyo.jp\nshinagawa.tokyo.jp\nshinjuku.tokyo.jp\nsuginami.tokyo.jp\nsumida.tokyo.jp\ntachikawa.tokyo.jp\ntaito.tokyo.jp\ntama.tokyo.jp\ntoshima.tokyo.jp\nchizu.tottori.jp\nhino.tottori.jp\nkawahara.tottori.jp\nkoge.tottori.jp\nkotoura.tottori.jp\nmisasa.tottori.jp\nnanbu.tottori.jp\nnichinan.tottori.jp\nsakaiminato.tottori.jp\ntottori.tottori.jp\nwakasa.tottori.jp\nyazu.tottori.jp\nyonago.tottori.jp\nasahi.toyama.jp\nfuchu.toyama.jp\nfukumitsu.toyama.jp\nfunahashi.toyama.jp\nhimi.toyama.jp\nimizu.toyama.jp\ninami.toyama.jp\njohana.toyama.jp\nkamiichi.toyama.jp\nkurobe.toyama.jp\nnakaniikawa.toyama.jp\nnamerikawa.toyama.jp\nnanto.toyama.jp\nnyuzen.toyama.jp\noyabe.toyama.jp\ntaira.toyama.jp\ntakaoka.toyama.jp\ntateyama.toyama.jp\ntoga.toyama.jp\ntonami.toyama.jp\ntoyama.toyama.jp\nunazuki.toyama.jp\nuozu.toyama.jp\nyamada.toyama.jp\narida.wakayama.jp\naridagawa.wakayama.jp\ngobo.wakayama.jp\nhashimoto.wakayama.jp\nhidaka.wakayama.jp\nhirogawa.wakayama.jp\ninami.wakayama.jp\niwade.wakayama.jp\nkainan.wakayama.jp\nkamitonda.wakayama.jp\nkatsuragi.wakayama.jp\nkimino.wakayama.jp\nkinokawa.wakayama.jp\nkitayama.wakayama.jp\nkoya.wakayama.jp\nkoza.wakayama.jp\nkozagawa.wakayama.jp\nkudoyama.wakayama.jp\nkushimoto.wakayama.jp\nmihama.wakayama.jp\nmisato.wakayama.jp\nnachikatsuura.wakayama.jp\nshingu.wakayama.jp\nshirahama.wakayama.jp\ntaiji.wakayama.jp\ntanabe.wakayama.jp\nwakayama.wakayama.jp\nyuasa.wakayama.jp\nyura.wakayama.jp\nasahi.yamagata.jp\nfunagata.yamagata.jp\nhigashine.yamagata.jp\niide.yamagata.jp\nkahoku.yamagata.jp\nkaminoyama.yamagata.jp\nkaneyama.yamagata.jp\nkawanishi.yamagata.jp\nmamurogawa.yamagata.jp\nmikawa.yamagata.jp\nmurayama.yamagata.jp\nnagai.yamagata.jp\nnakayama.yamagata.jp\nnanyo.yamagata.jp\nnishikawa.yamagata.jp\nobanazawa.yamagata.jp\noe.yamagata.jp\noguni.yamagata.jp\nohkura.yamagata.jp\noishida.yamagata.jp\nsagae.yamagata.jp\nsakata.yamagata.jp\nsakegawa.yamagata.jp\nshinjo.yamagata.jp\nshirataka.yamagata.jp\nshonai.yamagata.jp\ntakahata.yamagata.jp\ntendo.yamagata.jp\ntozawa.yamagata.jp\ntsuruoka.yamagata.jp\nyamagata.yamagata.jp\nyamanobe.yamagata.jp\nyonezawa.yamagata.jp\nyuza.yamagata.jp\nabu.yamaguchi.jp\nhagi.yamaguchi.jp\nhikari.yamaguchi.jp\nhofu.yamaguchi.jp\niwakuni.yamaguchi.jp\nkudamatsu.yamaguchi.jp\nmitou.yamaguchi.jp\nnagato.yamaguchi.jp\noshima.yamaguchi.jp\nshimonoseki.yamaguchi.jp\nshunan.yamaguchi.jp\ntabuse.yamaguchi.jp\ntokuyama.yamaguchi.jp\ntoyota.yamaguchi.jp\nube.yamaguchi.jp\nyuu.yamaguchi.jp\nchuo.yamanashi.jp\ndoshi.yamanashi.jp\nfuefuki.yamanashi.jp\nfujikawa.yamanashi.jp\nfujikawaguchiko.yamanashi.jp\nfujiyoshida.yamanashi.jp\nhayakawa.yamanashi.jp\nhokuto.yamanashi.jp\nichikawamisato.yamanashi.jp\nkai.yamanashi.jp\nkofu.yamanashi.jp\nkoshu.yamanashi.jp\nkosuge.yamanashi.jp\nminami-alps.yamanashi.jp\nminobu.yamanashi.jp\nnakamichi.yamanashi.jp\nnanbu.yamanashi.jp\nnarusawa.yamanashi.jp\nnirasaki.yamanashi.jp\nnishikatsura.yamanashi.jp\noshino.yamanashi.jp\notsuki.yamanashi.jp\nshowa.yamanashi.jp\ntabayama.yamanashi.jp\ntsuru.yamanashi.jp\nuenohara.yamanashi.jp\nyamanakako.yamanashi.jp\nyamanashi.yamanashi.jp\nke\nac.ke\nco.ke\ngo.ke\ninfo.ke\nme.ke\nmobi.ke\nne.ke\nor.ke\nsc.ke\nkg\ncom.kg\nedu.kg\ngov.kg\nmil.kg\nnet.kg\norg.kg\nkh\ncom.kh\nedu.kh\ngov.kh\nnet.kh\norg.kh\nki\nbiz.ki\ncom.ki\nedu.ki\ngov.ki\ninfo.ki\nnet.ki\norg.ki\nkm\nass.km\ncom.km\nedu.km\ngov.km\nmil.km\nnom.km\norg.km\nprd.km\ntm.km\nasso.km\ncoop.km\ngouv.km\nmedecin.km\nnotaires.km\npharmaciens.km\npresse.km\nveterinaire.km\nkn\nedu.kn\ngov.kn\nnet.kn\norg.kn\nkp\ncom.kp\nedu.kp\ngov.kp\norg.kp\nrep.kp\ntra.kp\nkr\nac.kr\nai.kr\nco.kr\nes.kr\ngo.kr\nhs.kr\nio.kr\nit.kr\nkg.kr\nme.kr\nmil.kr\nms.kr\nne.kr\nor.kr\npe.kr\nre.kr\nsc.kr\nbusan.kr\nchungbuk.kr\nchungnam.kr\ndaegu.kr\ndaejeon.kr\ngangwon.kr\ngwangju.kr\ngyeongbuk.kr\ngyeonggi.kr\ngyeongnam.kr\nincheon.kr\njeju.kr\njeonbuk.kr\njeonnam.kr\nseoul.kr\nulsan.kr\nkw\ncom.kw\nedu.kw\nemb.kw\ngov.kw\nind.kw\nnet.kw\norg.kw\nky\ncom.ky\nedu.ky\nnet.ky\norg.ky\nkz\ncom.kz\nedu.kz\ngov.kz\nmil.kz\nnet.kz\norg.kz\nla\ncom.la\nedu.la\ngov.la\ninfo.la\nint.la\nnet.la\norg.la\nper.la\nlb\ncom.lb\nedu.lb\ngov.lb\nnet.lb\norg.lb\nlc\nco.lc\ncom.lc\nedu.lc\ngov.lc\nnet.lc\norg.lc\nli\nlk\nac.lk\nassn.lk\ncom.lk\nedu.lk\ngov.lk\ngrp.lk\nhotel.lk\nint.lk\nltd.lk\nnet.lk\nngo.lk\norg.lk\nsch.lk\nsoc.lk\nweb.lk\nlr\ncom.lr\nedu.lr\ngov.lr\nnet.lr\norg.lr\nls\nac.ls\nbiz.ls\nco.ls\nedu.ls\ngov.ls\ninfo.ls\nnet.ls\norg.ls\nsc.ls\nlt\ngov.lt\nlu\nlv\nasn.lv\ncom.lv\nconf.lv\nedu.lv\ngov.lv\nid.lv\nmil.lv\nnet.lv\norg.lv\nly\ncom.ly\nedu.ly\ngov.ly\nid.ly\nmed.ly\nnet.ly\norg.ly\nplc.ly\nsch.ly\nma\nac.ma\nco.ma\ngov.ma\nnet.ma\norg.ma\npress.ma\nmc\nasso.mc\ntm.mc\nmd\nme\nac.me\nco.me\nedu.me\ngov.me\nits.me\nnet.me\norg.me\npriv.me\nmg\nco.mg\ncom.mg\nedu.mg\ngov.mg\nmil.mg\nnom.mg\norg.mg\nprd.mg\nmh\nmil\nmk\ncom.mk\nedu.mk\ngov.mk\ninf.mk\nname.mk\nnet.mk\norg.mk\nml\nac.ml\nart.ml\nasso.ml\ncom.ml\nedu.ml\ngouv.ml\ngov.ml\ninfo.ml\ninst.ml\nnet.ml\norg.ml\npr.ml\npresse.ml\n*.mm\nmn\nedu.mn\ngov.mn\norg.mn\nmo\ncom.mo\nedu.mo\ngov.mo\nnet.mo\norg.mo\nmobi\nmp\nmq\nmr\ngov.mr\nms\ncom.ms\nedu.ms\ngov.ms\nnet.ms\norg.ms\nmt\ncom.mt\nedu.mt\nnet.mt\norg.mt\nmu\nac.mu\nco.mu\ncom.mu\ngov.mu\nnet.mu\nor.mu\norg.mu\nmuseum\nmv\naero.mv\nbiz.mv\ncom.mv\ncoop.mv\nedu.mv\ngov.mv\ninfo.mv\nint.mv\nmil.mv\nmuseum.mv\nname.mv\nnet.mv\norg.mv\npro.mv\nmw\nac.mw\nbiz.mw\nco.mw\ncom.mw\ncoop.mw\nedu.mw\ngov.mw\nint.mw\nnet.mw\norg.mw\nmx\ncom.mx\nedu.mx\ngob.mx\nnet.mx\norg.mx\nmy\nbiz.my\ncom.my\nedu.my\ngov.my\nmil.my\nname.my\nnet.my\norg.my\nmz\nac.mz\nadv.mz\nco.mz\nedu.mz\ngov.mz\nmil.mz\nnet.mz\norg.mz\nna\nalt.na\nco.na\ncom.na\ngov.na\nnet.na\norg.na\nname\nnc\nasso.nc\nnom.nc\nne\nnet\nnf\narts.nf\ncom.nf\nfirm.nf\ninfo.nf\nnet.nf\nother.nf\nper.nf\nrec.nf\nstore.nf\nweb.nf\nng\ncom.ng\nedu.ng\ngov.ng\ni.ng\nmil.ng\nmobi.ng\nname.ng\nnet.ng\norg.ng\nsch.ng\nni\nac.ni\nbiz.ni\nco.ni\ncom.ni\nedu.ni\ngob.ni\nin.ni\ninfo.ni\nint.ni\nmil.ni\nnet.ni\nnom.ni\norg.ni\nweb.ni\nnl\nno\nfhs.no\nfolkebibl.no\nfylkesbibl.no\ngielda.no\nherad.no\nidrett.no\nkommune.no\nmuseum.no\npriv.no\nsuohkan.no\ntjielte.no\nuenorge.no\nvgs.no\ndep.no\nmil.no\nstat.no\naa.no\nah.no\nbu.no\nfm.no\nhl.no\nhm.no\njan-mayen.no\nmr.no\nnl.no\nnt.no\nof.no\nol.no\noslo.no\nrl.no\nsf.no\nst.no\nsvalbard.no\ntm.no\ntr.no\nva.no\nvf.no\ngs.aa.no\ngs.ah.no\ngs.bu.no\ngs.fm.no\ngs.hl.no\ngs.hm.no\ngs.jan-mayen.no\ngs.mr.no\ngs.nl.no\ngs.nt.no\ngs.of.no\ngs.ol.no\ngs.oslo.no\ngs.rl.no\ngs.sf.no\ngs.st.no\ngs.svalbard.no\ngs.tm.no\ngs.tr.no\ngs.va.no\ngs.vf.no\nakrehamn.no\nxn--krehamn-dxa.no\nalgard.no\nxn--lgrd-poac.no\narna.no\nbronnoysund.no\nxn--brnnysund-m8ac.no\nbrumunddal.no\nbryne.no\ndrobak.no\nxn--drbak-wua.no\negersund.no\nfetsund.no\nfloro.no\nxn--flor-jra.no\nfredrikstad.no\nhokksund.no\nhonefoss.no\nxn--hnefoss-q1a.no\njessheim.no\njorpeland.no\nxn--jrpeland-54a.no\nkirkenes.no\nkopervik.no\nkrokstadelva.no\nlangevag.no\nxn--langevg-jxa.no\nleirvik.no\nmjondalen.no\nxn--mjndalen-64a.no\nmo-i-rana.no\nmosjoen.no\nxn--mosjen-eya.no\nnesoddtangen.no\norkanger.no\nosoyro.no\nxn--osyro-wua.no\nraholt.no\nxn--rholt-mra.no\nsandnessjoen.no\nxn--sandnessjen-ogb.no\nskedsmokorset.no\nslattum.no\nspjelkavik.no\nstathelle.no\nstavern.no\nstjordalshalsen.no\nxn--stjrdalshalsen-sqb.no\ntananger.no\ntranby.no\nvossevangen.no\naarborte.no\naejrie.no\nafjord.no\nxn--fjord-lra.no\nagdenes.no\nnes.akershus.no\naknoluokta.no\nxn--koluokta-7ya57h.no\nal.no\nxn--l-1fa.no\nalaheadju.no\nxn--laheadju-7ya.no\nalesund.no\nxn--lesund-hua.no\nalstahaug.no\nalta.no\nxn--lt-liac.no\nalvdal.no\namli.no\nxn--mli-tla.no\namot.no\nxn--mot-tla.no\nandasuolo.no\nandebu.no\nandoy.no\nxn--andy-ira.no\nardal.no\nxn--rdal-poa.no\naremark.no\narendal.no\nxn--s-1fa.no\naseral.no\nxn--seral-lra.no\nasker.no\naskim.no\naskoy.no\nxn--asky-ira.no\naskvoll.no\nasnes.no\nxn--snes-poa.no\naudnedal.no\naukra.no\naure.no\naurland.no\naurskog-holand.no\nxn--aurskog-hland-jnb.no\naustevoll.no\naustrheim.no\naveroy.no\nxn--avery-yua.no\nbadaddja.no\nxn--bdddj-mrabd.no\nxn--brum-voa.no\nbahcavuotna.no\nxn--bhcavuotna-s4a.no\nbahccavuotna.no\nxn--bhccavuotna-k7a.no\nbaidar.no\nxn--bidr-5nac.no\nbajddar.no\nxn--bjddar-pta.no\nbalat.no\nxn--blt-elab.no\nbalestrand.no\nballangen.no\nbalsfjord.no\nbamble.no\nbardu.no\nbarum.no\nbatsfjord.no\nxn--btsfjord-9za.no\nbearalvahki.no\nxn--bearalvhki-y4a.no\nbeardu.no\nbeiarn.no\nberg.no\nbergen.no\nberlevag.no\nxn--berlevg-jxa.no\nbievat.no\nxn--bievt-0qa.no\nbindal.no\nbirkenes.no\nbjerkreim.no\nbjugn.no\nbodo.no\nxn--bod-2na.no\nbokn.no\nbomlo.no\nxn--bmlo-gra.no\nbremanger.no\nbronnoy.no\nxn--brnny-wuac.no\nbudejju.no\nnes.buskerud.no\nbygland.no\nbykle.no\ncahcesuolo.no\nxn--hcesuolo-7ya35b.no\ndavvenjarga.no\nxn--davvenjrga-y4a.no\ndavvesiida.no\ndeatnu.no\ndielddanuorri.no\ndivtasvuodna.no\ndivttasvuotna.no\ndonna.no\nxn--dnna-gra.no\ndovre.no\ndrammen.no\ndrangedal.no\ndyroy.no\nxn--dyry-ira.no\neid.no\neidfjord.no\neidsberg.no\neidskog.no\neidsvoll.no\neigersund.no\nelverum.no\nenebakk.no\nengerdal.no\netne.no\netnedal.no\nevenassi.no\nxn--eveni-0qa01ga.no\nevenes.no\nevje-og-hornnes.no\nfarsund.no\nfauske.no\nfedje.no\nfet.no\nfinnoy.no\nxn--finny-yua.no\nfitjar.no\nfjaler.no\nfjell.no\nfla.no\nxn--fl-zia.no\nflakstad.no\nflatanger.no\nflekkefjord.no\nflesberg.no\nflora.no\nfolldal.no\nforde.no\nxn--frde-gra.no\nforsand.no\nfosnes.no\nxn--frna-woa.no\nfrana.no\nfrogn.no\nfroland.no\nfrosta.no\nfroya.no\nxn--frya-hra.no\nfuoisku.no\nfuossko.no\nfusa.no\nfyresdal.no\ngaivuotna.no\nxn--givuotna-8ya.no\ngalsa.no\nxn--gls-elac.no\ngamvik.no\ngangaviika.no\nxn--ggaviika-8ya47h.no\ngaular.no\ngausdal.no\ngiehtavuoatna.no\ngildeskal.no\nxn--gildeskl-g0a.no\ngiske.no\ngjemnes.no\ngjerdrum.no\ngjerstad.no\ngjesdal.no\ngjovik.no\nxn--gjvik-wua.no\ngloppen.no\ngol.no\ngran.no\ngrane.no\ngranvin.no\ngratangen.no\ngrimstad.no\ngrong.no\ngrue.no\ngulen.no\nguovdageaidnu.no\nha.no\nxn--h-2fa.no\nhabmer.no\nxn--hbmer-xqa.no\nhadsel.no\nxn--hgebostad-g3a.no\nhagebostad.no\nhalden.no\nhalsa.no\nhamar.no\nhamaroy.no\nxn--hamary-fya.no\nhammarfeasta.no\nxn--hmmrfeasta-s4ac.no\nhammerfest.no\nhapmir.no\nxn--hpmir-xqa.no\nharam.no\nhareid.no\nharstad.no\nhasvik.no\nhattfjelldal.no\nhaugesund.no\nos.hedmark.no\nvaler.hedmark.no\nxn--vler-qoa.hedmark.no\nhemne.no\nhemnes.no\nhemsedal.no\nhitra.no\nhjartdal.no\nhjelmeland.no\nhobol.no\nxn--hobl-ira.no\nhof.no\nhol.no\nhole.no\nholmestrand.no\nholtalen.no\nxn--holtlen-hxa.no\nos.hordaland.no\nhornindal.no\nhorten.no\nhoyanger.no\nxn--hyanger-q1a.no\nhoylandet.no\nxn--hylandet-54a.no\nhurdal.no\nhurum.no\nhvaler.no\nhyllestad.no\nibestad.no\ninderoy.no\nxn--indery-fya.no\niveland.no\nivgu.no\njevnaker.no\njolster.no\nxn--jlster-bya.no\njondal.no\nkafjord.no\nxn--kfjord-iua.no\nkarasjohka.no\nxn--krjohka-hwab49j.no\nkarasjok.no\nkarlsoy.no\nxn--karlsy-fya.no\nkarmoy.no\nxn--karmy-yua.no\nkautokeino.no\nklabu.no\nxn--klbu-woa.no\nklepp.no\nkongsberg.no\nkongsvinger.no\nkraanghke.no\nxn--kranghke-b0a.no\nkragero.no\nxn--krager-gya.no\nkristiansand.no\nkristiansund.no\nkrodsherad.no\nxn--krdsherad-m8a.no\nxn--kvfjord-nxa.no\nxn--kvnangen-k0a.no\nkvafjord.no\nkvalsund.no\nkvam.no\nkvanangen.no\nkvinesdal.no\nkvinnherad.no\nkviteseid.no\nkvitsoy.no\nxn--kvitsy-fya.no\nlaakesvuemie.no\nxn--lrdal-sra.no\nlahppi.no\nxn--lhppi-xqa.no\nlardal.no\nlarvik.no\nlavagis.no\nlavangen.no\nleangaviika.no\nxn--leagaviika-52b.no\nlebesby.no\nleikanger.no\nleirfjord.no\nleka.no\nleksvik.no\nlenvik.no\nlerdal.no\nlesja.no\nlevanger.no\nlier.no\nlierne.no\nlillehammer.no\nlillesand.no\nlindas.no\nxn--linds-pra.no\nlindesnes.no\nloabat.no\nxn--loabt-0qa.no\nlodingen.no\nxn--ldingen-q1a.no\nlom.no\nloppa.no\nlorenskog.no\nxn--lrenskog-54a.no\nloten.no\nxn--lten-gra.no\nlund.no\nlunner.no\nluroy.no\nxn--lury-ira.no\nluster.no\nlyngdal.no\nlyngen.no\nmalatvuopmi.no\nxn--mlatvuopmi-s4a.no\nmalselv.no\nxn--mlselv-iua.no\nmalvik.no\nmandal.no\nmarker.no\nmarnardal.no\nmasfjorden.no\nmasoy.no\nxn--msy-ula0h.no\nmatta-varjjat.no\nxn--mtta-vrjjat-k7af.no\nmeland.no\nmeldal.no\nmelhus.no\nmeloy.no\nxn--mely-ira.no\nmeraker.no\nxn--merker-kua.no\nmidsund.no\nmidtre-gauldal.no\nmoareke.no\nxn--moreke-jua.no\nmodalen.no\nmodum.no\nmolde.no\nheroy.more-og-romsdal.no\nsande.more-og-romsdal.no\nxn--hery-ira.xn--mre-og-romsdal-qqb.no\nsande.xn--mre-og-romsdal-qqb.no\nmoskenes.no\nmoss.no\nmuosat.no\nxn--muost-0qa.no\nnaamesjevuemie.no\nxn--nmesjevuemie-tcba.no\nxn--nry-yla5g.no\nnamdalseid.no\nnamsos.no\nnamsskogan.no\nnannestad.no\nnaroy.no\nnarviika.no\nnarvik.no\nnaustdal.no\nnavuotna.no\nxn--nvuotna-hwa.no\nnedre-eiker.no\nnesna.no\nnesodden.no\nnesseby.no\nnesset.no\nnissedal.no\nnittedal.no\nnord-aurdal.no\nnord-fron.no\nnord-odal.no\nnorddal.no\nnordkapp.no\nbo.nordland.no\nxn--b-5ga.nordland.no\nheroy.nordland.no\nxn--hery-ira.nordland.no\nnordre-land.no\nnordreisa.no\nnore-og-uvdal.no\nnotodden.no\nnotteroy.no\nxn--nttery-byae.no\nodda.no\noksnes.no\nxn--ksnes-uua.no\nomasvuotna.no\noppdal.no\noppegard.no\nxn--oppegrd-ixa.no\norkdal.no\norland.no\nxn--rland-uua.no\norskog.no\nxn--rskog-uua.no\norsta.no\nxn--rsta-fra.no\nosen.no\nosteroy.no\nxn--ostery-fya.no\nvaler.ostfold.no\nxn--vler-qoa.xn--stfold-9xa.no\nostre-toten.no\nxn--stre-toten-zcb.no\noverhalla.no\novre-eiker.no\nxn--vre-eiker-k8a.no\noyer.no\nxn--yer-zna.no\noygarden.no\nxn--ygarden-p1a.no\noystre-slidre.no\nxn--ystre-slidre-ujb.no\nporsanger.no\nporsangu.no\nxn--porsgu-sta26f.no\nporsgrunn.no\nrade.no\nxn--rde-ula.no\nradoy.no\nxn--rady-ira.no\nxn--rlingen-mxa.no\nrahkkeravju.no\nxn--rhkkervju-01af.no\nraisa.no\nxn--risa-5na.no\nrakkestad.no\nralingen.no\nrana.no\nrandaberg.no\nrauma.no\nre.no\nrendalen.no\nrennebu.no\nrennesoy.no\nxn--rennesy-v1a.no\nrindal.no\nringebu.no\nringerike.no\nringsaker.no\nrisor.no\nxn--risr-ira.no\nrissa.no\nroan.no\nrodoy.no\nxn--rdy-0nab.no\nrollag.no\nromsa.no\nromskog.no\nxn--rmskog-bya.no\nroros.no\nxn--rros-gra.no\nrost.no\nxn--rst-0na.no\nroyken.no\nxn--ryken-vua.no\nroyrvik.no\nxn--ryrvik-bya.no\nruovat.no\nrygge.no\nsalangen.no\nsalat.no\nxn--slat-5na.no\nxn--slt-elab.no\nsaltdal.no\nsamnanger.no\nsandefjord.no\nsandnes.no\nsandoy.no\nxn--sandy-yua.no\nsarpsborg.no\nsauda.no\nsauherad.no\nsel.no\nselbu.no\nselje.no\nseljord.no\nsiellak.no\nsigdal.no\nsiljan.no\nsirdal.no\nskanit.no\nxn--sknit-yqa.no\nskanland.no\nxn--sknland-fxa.no\nskaun.no\nskedsmo.no\nski.no\nskien.no\nskierva.no\nxn--skierv-uta.no\nskiptvet.no\nskjak.no\nxn--skjk-soa.no\nskjervoy.no\nxn--skjervy-v1a.no\nskodje.no\nsmola.no\nxn--smla-hra.no\nsnaase.no\nxn--snase-nra.no\nsnasa.no\nxn--snsa-roa.no\nsnillfjord.no\nsnoasa.no\nsogndal.no\nsogne.no\nxn--sgne-gra.no\nsokndal.no\nsola.no\nsolund.no\nsomna.no\nxn--smna-gra.no\nsondre-land.no\nxn--sndre-land-0cb.no\nsongdalen.no\nsor-aurdal.no\nxn--sr-aurdal-l8a.no\nsor-fron.no\nxn--sr-fron-q1a.no\nsor-odal.no\nxn--sr-odal-q1a.no\nsor-varanger.no\nxn--sr-varanger-ggb.no\nsorfold.no\nxn--srfold-bya.no\nsorreisa.no\nxn--srreisa-q1a.no\nsortland.no\nsorum.no\nxn--srum-gra.no\nspydeberg.no\nstange.no\nstavanger.no\nsteigen.no\nsteinkjer.no\nstjordal.no\nxn--stjrdal-s1a.no\nstokke.no\nstor-elvdal.no\nstord.no\nstordal.no\nstorfjord.no\nstrand.no\nstranda.no\nstryn.no\nsula.no\nsuldal.no\nsund.no\nsunndal.no\nsurnadal.no\nsveio.no\nsvelvik.no\nsykkylven.no\ntana.no\nbo.telemark.no\nxn--b-5ga.telemark.no\ntime.no\ntingvoll.no\ntinn.no\ntjeldsund.no\ntjome.no\nxn--tjme-hra.no\ntokke.no\ntolga.no\ntonsberg.no\nxn--tnsberg-q1a.no\ntorsken.no\nxn--trna-woa.no\ntrana.no\ntranoy.no\nxn--trany-yua.no\ntroandin.no\ntrogstad.no\nxn--trgstad-r1a.no\ntromsa.no\ntromso.no\nxn--troms-zua.no\ntrondheim.no\ntrysil.no\ntvedestrand.no\ntydal.no\ntynset.no\ntysfjord.no\ntysnes.no\nxn--tysvr-vra.no\ntysvar.no\nullensaker.no\nullensvang.no\nulstein.no\nulvik.no\nunjarga.no\nxn--unjrga-rta.no\nutsira.no\nvaapste.no\nvadso.no\nxn--vads-jra.no\nxn--vry-yla5g.no\nvaga.no\nxn--vg-yiab.no\nvagan.no\nxn--vgan-qoa.no\nvagsoy.no\nxn--vgsy-qoa0j.no\nvaksdal.no\nvalle.no\nvang.no\nvanylven.no\nvardo.no\nxn--vard-jra.no\nvarggat.no\nxn--vrggt-xqad.no\nvaroy.no\nvefsn.no\nvega.no\nvegarshei.no\nxn--vegrshei-c0a.no\nvennesla.no\nverdal.no\nverran.no\nvestby.no\nsande.vestfold.no\nvestnes.no\nvestre-slidre.no\nvestre-toten.no\nvestvagoy.no\nxn--vestvgy-ixa6o.no\nvevelstad.no\nvik.no\nvikna.no\nvindafjord.no\nvoagat.no\nvolda.no\nvoss.no\n*.np\nnr\nbiz.nr\ncom.nr\nedu.nr\ngov.nr\ninfo.nr\nnet.nr\norg.nr\nnu\nnz\nac.nz\nco.nz\ncri.nz\ngeek.nz\ngen.nz\ngovt.nz\nhealth.nz\niwi.nz\nkiwi.nz\nmaori.nz\nxn--mori-qsa.nz\nmil.nz\nnet.nz\norg.nz\nparliament.nz\nschool.nz\nom\nco.om\ncom.om\nedu.om\ngov.om\nmed.om\nmuseum.om\nnet.om\norg.om\npro.om\nonion\norg\npa\nabo.pa\nac.pa\ncom.pa\nedu.pa\ngob.pa\ning.pa\nmed.pa\nnet.pa\nnom.pa\norg.pa\nsld.pa\npe\ncom.pe\nedu.pe\ngob.pe\nmil.pe\nnet.pe\nnom.pe\norg.pe\npf\ncom.pf\nedu.pf\norg.pf\n*.pg\nph\ncom.ph\nedu.ph\ngov.ph\ni.ph\nmil.ph\nnet.ph\nngo.ph\norg.ph\npk\nac.pk\nbiz.pk\ncom.pk\nedu.pk\nfam.pk\ngkp.pk\ngob.pk\ngog.pk\ngok.pk\ngop.pk\ngos.pk\ngov.pk\nnet.pk\norg.pk\nweb.pk\npl\ncom.pl\nnet.pl\norg.pl\nagro.pl\naid.pl\natm.pl\nauto.pl\nbiz.pl\nedu.pl\ngmina.pl\ngsm.pl\ninfo.pl\nmail.pl\nmedia.pl\nmiasta.pl\nmil.pl\nnieruchomosci.pl\nnom.pl\npc.pl\npowiat.pl\npriv.pl\nrealestate.pl\nrel.pl\nsex.pl\nshop.pl\nsklep.pl\nsos.pl\nszkola.pl\ntargi.pl\ntm.pl\ntourism.pl\ntravel.pl\nturystyka.pl\ngov.pl\nap.gov.pl\ngriw.gov.pl\nic.gov.pl\nis.gov.pl\nkmpsp.gov.pl\nkonsulat.gov.pl\nkppsp.gov.pl\nkwp.gov.pl\nkwpsp.gov.pl\nmup.gov.pl\nmw.gov.pl\noia.gov.pl\noirm.gov.pl\noke.gov.pl\noow.gov.pl\noschr.gov.pl\noum.gov.pl\npa.gov.pl\npinb.gov.pl\npiw.gov.pl\npo.gov.pl\npr.gov.pl\npsp.gov.pl\npsse.gov.pl\npup.gov.pl\nrzgw.gov.pl\nsa.gov.pl\nsdn.gov.pl\nsko.gov.pl\nso.gov.pl\nsr.gov.pl\nstarostwo.gov.pl\nug.gov.pl\nugim.gov.pl\num.gov.pl\numig.gov.pl\nupow.gov.pl\nuppo.gov.pl\nus.gov.pl\nuw.gov.pl\nuzs.gov.pl\nwif.gov.pl\nwiih.gov.pl\nwinb.gov.pl\nwios.gov.pl\nwitd.gov.pl\nwiw.gov.pl\nwkz.gov.pl\nwsa.gov.pl\nwskr.gov.pl\nwsse.gov.pl\nwuoz.gov.pl\nwzmiuw.gov.pl\nzp.gov.pl\nzpisdn.gov.pl\naugustow.pl\nbabia-gora.pl\nbedzin.pl\nbeskidy.pl\nbialowieza.pl\nbialystok.pl\nbielawa.pl\nbieszczady.pl\nboleslawiec.pl\nbydgoszcz.pl\nbytom.pl\ncieszyn.pl\nczeladz.pl\nczest.pl\ndlugoleka.pl\nelblag.pl\nelk.pl\nglogow.pl\ngniezno.pl\ngorlice.pl\ngrajewo.pl\nilawa.pl\njaworzno.pl\njelenia-gora.pl\njgora.pl\nkalisz.pl\nkarpacz.pl\nkartuzy.pl\nkaszuby.pl\nkatowice.pl\nkazimierz-dolny.pl\nkepno.pl\nketrzyn.pl\nklodzko.pl\nkobierzyce.pl\nkolobrzeg.pl\nkonin.pl\nkonskowola.pl\nkutno.pl\nlapy.pl\nlebork.pl\nlegnica.pl\nlezajsk.pl\nlimanowa.pl\nlomza.pl\nlowicz.pl\nlubin.pl\nlukow.pl\nmalbork.pl\nmalopolska.pl\nmazowsze.pl\nmazury.pl\nmielec.pl\nmielno.pl\nmragowo.pl\nnaklo.pl\nnowaruda.pl\nnysa.pl\nolawa.pl\nolecko.pl\nolkusz.pl\nolsztyn.pl\nopoczno.pl\nopole.pl\nostroda.pl\nostroleka.pl\nostrowiec.pl\nostrowwlkp.pl\npila.pl\npisz.pl\npodhale.pl\npodlasie.pl\npolkowice.pl\npomorskie.pl\npomorze.pl\nprochowice.pl\npruszkow.pl\nprzeworsk.pl\npulawy.pl\nradom.pl\nrawa-maz.pl\nrybnik.pl\nrzeszow.pl\nsanok.pl\nsejny.pl\nskoczow.pl\nslask.pl\nslupsk.pl\nsosnowiec.pl\nstalowa-wola.pl\nstarachowice.pl\nstargard.pl\nsuwalki.pl\nswidnica.pl\nswiebodzin.pl\nswinoujscie.pl\nszczecin.pl\nszczytno.pl\ntarnobrzeg.pl\ntgory.pl\nturek.pl\ntychy.pl\nustka.pl\nwalbrzych.pl\nwarmia.pl\nwarszawa.pl\nwaw.pl\nwegrow.pl\nwielun.pl\nwlocl.pl\nwloclawek.pl\nwodzislaw.pl\nwolomin.pl\nwroclaw.pl\nzachpomor.pl\nzagan.pl\nzarow.pl\nzgora.pl\nzgorzelec.pl\npm\npn\nco.pn\nedu.pn\ngov.pn\nnet.pn\norg.pn\npost\npr\nbiz.pr\ncom.pr\nedu.pr\ngov.pr\ninfo.pr\nisla.pr\nname.pr\nnet.pr\norg.pr\npro.pr\nac.pr\nest.pr\nprof.pr\npro\naaa.pro\naca.pro\nacct.pro\navocat.pro\nbar.pro\ncpa.pro\neng.pro\njur.pro\nlaw.pro\nmed.pro\nrecht.pro\nps\ncom.ps\nedu.ps\ngov.ps\nnet.ps\norg.ps\nplo.ps\nsec.ps\npt\ncom.pt\nedu.pt\ngov.pt\nint.pt\nnet.pt\nnome.pt\norg.pt\npubl.pt\npw\ngov.pw\npy\ncom.py\ncoop.py\nedu.py\ngov.py\nmil.py\nnet.py\norg.py\nqa\ncom.qa\nedu.qa\ngov.qa\nmil.qa\nname.qa\nnet.qa\norg.qa\nsch.qa\nre\nasso.re\ncom.re\nro\narts.ro\ncom.ro\nfirm.ro\ninfo.ro\nnom.ro\nnt.ro\norg.ro\nrec.ro\nstore.ro\ntm.ro\nwww.ro\nrs\nac.rs\nco.rs\nedu.rs\ngov.rs\nin.rs\norg.rs\nru\nrw\nac.rw\nco.rw\ncoop.rw\ngov.rw\nmil.rw\nnet.rw\norg.rw\nsa\ncom.sa\nedu.sa\ngov.sa\nmed.sa\nnet.sa\norg.sa\npub.sa\nsch.sa\nsb\ncom.sb\nedu.sb\ngov.sb\nnet.sb\norg.sb\nsc\ncom.sc\nedu.sc\ngov.sc\nnet.sc\norg.sc\nsd\ncom.sd\nedu.sd\ngov.sd\ninfo.sd\nmed.sd\nnet.sd\norg.sd\ntv.sd\nse\na.se\nac.se\nb.se\nbd.se\nbrand.se\nc.se\nd.se\ne.se\nf.se\nfh.se\nfhsk.se\nfhv.se\ng.se\nh.se\ni.se\nk.se\nkomforb.se\nkommunalforbund.se\nkomvux.se\nl.se\nlanbib.se\nm.se\nn.se\nnaturbruksgymn.se\no.se\norg.se\np.se\nparti.se\npp.se\npress.se\nr.se\ns.se\nt.se\ntm.se\nu.se\nw.se\nx.se\ny.se\nz.se\nsg\ncom.sg\nedu.sg\ngov.sg\nnet.sg\norg.sg\nsh\ncom.sh\ngov.sh\nmil.sh\nnet.sh\norg.sh\nsi\nsj\nsk\norg.sk\nsl\ncom.sl\nedu.sl\ngov.sl\nnet.sl\norg.sl\nsm\nsn\nart.sn\ncom.sn\nedu.sn\ngouv.sn\norg.sn\nuniv.sn\nso\ncom.so\nedu.so\ngov.so\nme.so\nnet.so\norg.so\nsr\nss\nbiz.ss\nco.ss\ncom.ss\nedu.ss\ngov.ss\nme.ss\nnet.ss\norg.ss\nsch.ss\nst\nco.st\ncom.st\nconsulado.st\nedu.st\nembaixada.st\nmil.st\nnet.st\norg.st\nprincipe.st\nsaotome.st\nstore.st\nsu\nsv\ncom.sv\nedu.sv\ngob.sv\norg.sv\nred.sv\nsx\ngov.sx\nsy\ncom.sy\nedu.sy\ngov.sy\nmil.sy\nnet.sy\norg.sy\nsz\nac.sz\nco.sz\norg.sz\ntc\ntd\ntel\ntf\ntg\nth\nac.th\nco.th\ngo.th\nin.th\nmi.th\nnet.th\nor.th\ntj\nbiz.tj\nco.tj\ncom.tj\nedu.tj\ngo.tj\ngov.tj\nint.tj\nmil.tj\nname.tj\nnet.tj\nnic.tj\norg.tj\ntest.tj\nweb.tj\ntk\ntl\ngov.tl\ntm\nco.tm\ncom.tm\nedu.tm\ngov.tm\nmil.tm\nnet.tm\nnom.tm\norg.tm\ntn\ncom.tn\nens.tn\nfin.tn\ngov.tn\nind.tn\ninfo.tn\nintl.tn\nmincom.tn\nnat.tn\nnet.tn\norg.tn\nperso.tn\ntourism.tn\nto\ncom.to\nedu.to\ngov.to\nmil.to\nnet.to\norg.to\ntr\nav.tr\nbbs.tr\nbel.tr\nbiz.tr\ncom.tr\ndr.tr\nedu.tr\ngen.tr\ngov.tr\ninfo.tr\nk12.tr\nkep.tr\nmil.tr\nname.tr\nnet.tr\norg.tr\npol.tr\ntel.tr\ntsk.tr\ntv.tr\nweb.tr\nnc.tr\ngov.nc.tr\ntt\nbiz.tt\nco.tt\ncom.tt\nedu.tt\ngov.tt\ninfo.tt\nmil.tt\nname.tt\nnet.tt\norg.tt\npro.tt\ntv\ntw\nclub.tw\ncom.tw\nebiz.tw\nedu.tw\ngame.tw\ngov.tw\nidv.tw\nmil.tw\nnet.tw\norg.tw\ntz\nac.tz\nco.tz\ngo.tz\nhotel.tz\ninfo.tz\nme.tz\nmil.tz\nmobi.tz\nne.tz\nor.tz\nsc.tz\ntv.tz\nua\ncom.ua\nedu.ua\ngov.ua\nin.ua\nnet.ua\norg.ua\ncherkassy.ua\ncherkasy.ua\nchernigov.ua\nchernihiv.ua\nchernivtsi.ua\nchernovtsy.ua\nck.ua\ncn.ua\ncr.ua\ncrimea.ua\ncv.ua\ndn.ua\ndnepropetrovsk.ua\ndnipropetrovsk.ua\ndonetsk.ua\ndp.ua\nif.ua\nivano-frankivsk.ua\nkh.ua\nkharkiv.ua\nkharkov.ua\nkherson.ua\nkhmelnitskiy.ua\nkhmelnytskyi.ua\nkiev.ua\nkirovograd.ua\nkm.ua\nkr.ua\nkropyvnytskyi.ua\nkrym.ua\nks.ua\nkv.ua\nkyiv.ua\nlg.ua\nlt.ua\nlugansk.ua\nluhansk.ua\nlutsk.ua\nlv.ua\nlviv.ua\nmk.ua\nmykolaiv.ua\nnikolaev.ua\nod.ua\nodesa.ua\nodessa.ua\npl.ua\npoltava.ua\nrivne.ua\nrovno.ua\nrv.ua\nsb.ua\nsebastopol.ua\nsevastopol.ua\nsm.ua\nsumy.ua\nte.ua\nternopil.ua\nuz.ua\nuzhgorod.ua\nuzhhorod.ua\nvinnica.ua\nvinnytsia.ua\nvn.ua\nvolyn.ua\nyalta.ua\nzakarpattia.ua\nzaporizhzhe.ua\nzaporizhzhia.ua\nzhitomir.ua\nzhytomyr.ua\nzp.ua\nzt.ua\nug\nac.ug\nco.ug\ncom.ug\nedu.ug\ngo.ug\ngov.ug\nmil.ug\nne.ug\nor.ug\norg.ug\nsc.ug\nus.ug\nuk\nac.uk\nco.uk\ngov.uk\nltd.uk\nme.uk\nnet.uk\nnhs.uk\norg.uk\nplc.uk\npolice.uk\n*.sch.uk\nus\ndni.us\nisa.us\nnsn.us\nak.us\nal.us\nar.us\nas.us\naz.us\nca.us\nco.us\nct.us\ndc.us\nde.us\nfl.us\nga.us\ngu.us\nhi.us\nia.us\nid.us\nil.us\nin.us\nks.us\nky.us\nla.us\nma.us\nmd.us\nme.us\nmi.us\nmn.us\nmo.us\nms.us\nmt.us\nnc.us\nnd.us\nne.us\nnh.us\nnj.us\nnm.us\nnv.us\nny.us\noh.us\nok.us\nor.us\npa.us\npr.us\nri.us\nsc.us\nsd.us\ntn.us\ntx.us\nut.us\nva.us\nvi.us\nvt.us\nwa.us\nwi.us\nwv.us\nwy.us\nk12.ak.us\nk12.al.us\nk12.ar.us\nk12.as.us\nk12.az.us\nk12.ca.us\nk12.co.us\nk12.ct.us\nk12.dc.us\nk12.fl.us\nk12.ga.us\nk12.gu.us\nk12.ia.us\nk12.id.us\nk12.il.us\nk12.in.us\nk12.ks.us\nk12.ky.us\nk12.la.us\nk12.ma.us\nk12.md.us\nk12.me.us\nk12.mi.us\nk12.mn.us\nk12.mo.us\nk12.ms.us\nk12.mt.us\nk12.nc.us\nk12.ne.us\nk12.nh.us\nk12.nj.us\nk12.nm.us\nk12.nv.us\nk12.ny.us\nk12.oh.us\nk12.ok.us\nk12.or.us\nk12.pa.us\nk12.pr.us\nk12.sc.us\nk12.tn.us\nk12.tx.us\nk12.ut.us\nk12.va.us\nk12.vi.us\nk12.vt.us\nk12.wa.us\nk12.wi.us\ncc.ak.us\nlib.ak.us\ncc.al.us\nlib.al.us\ncc.ar.us\nlib.ar.us\ncc.as.us\nlib.as.us\ncc.az.us\nlib.az.us\ncc.ca.us\nlib.ca.us\ncc.co.us\nlib.co.us\ncc.ct.us\nlib.ct.us\ncc.dc.us\nlib.dc.us\ncc.de.us\ncc.fl.us\nlib.fl.us\ncc.ga.us\nlib.ga.us\ncc.gu.us\nlib.gu.us\ncc.hi.us\nlib.hi.us\ncc.ia.us\nlib.ia.us\ncc.id.us\nlib.id.us\ncc.il.us\nlib.il.us\ncc.in.us\nlib.in.us\ncc.ks.us\nlib.ks.us\ncc.ky.us\nlib.ky.us\ncc.la.us\nlib.la.us\ncc.ma.us\nlib.ma.us\ncc.md.us\nlib.md.us\ncc.me.us\nlib.me.us\ncc.mi.us\nlib.mi.us\ncc.mn.us\nlib.mn.us\ncc.mo.us\nlib.mo.us\ncc.ms.us\ncc.mt.us\nlib.mt.us\ncc.nc.us\nlib.nc.us\ncc.ne.us\nlib.ne.us\ncc.nh.us\nlib.nh.us\ncc.nj.us\nlib.nj.us\ncc.nm.us\nlib.nm.us\ncc.nv.us\nlib.nv.us\ncc.ny.us\nlib.ny.us\ncc.oh.us\nlib.oh.us\ncc.ok.us\nlib.ok.us\ncc.or.us\nlib.or.us\ncc.pa.us\nlib.pa.us\ncc.pr.us\nlib.pr.us\ncc.ri.us\nlib.ri.us\ncc.sc.us\nlib.sc.us\ncc.sd.us\nlib.sd.us\ncc.tn.us\nlib.tn.us\ncc.tx.us\nlib.tx.us\ncc.ut.us\nlib.ut.us\ncc.va.us\nlib.va.us\ncc.vi.us\nlib.vi.us\ncc.vt.us\nlib.vt.us\ncc.wa.us\nlib.wa.us\ncc.wi.us\nlib.wi.us\ncc.wv.us\ncc.wy.us\nk12.wy.us\nlib.wy.us\nchtr.k12.ma.us\nparoch.k12.ma.us\npvt.k12.ma.us\nann-arbor.mi.us\ncog.mi.us\ndst.mi.us\neaton.mi.us\ngen.mi.us\nmus.mi.us\ntec.mi.us\nwashtenaw.mi.us\nuy\ncom.uy\nedu.uy\ngub.uy\nmil.uy\nnet.uy\norg.uy\nuz\nco.uz\ncom.uz\nnet.uz\norg.uz\nva\nvc\ncom.vc\nedu.vc\ngov.vc\nmil.vc\nnet.vc\norg.vc\nve\narts.ve\nbib.ve\nco.ve\ncom.ve\ne12.ve\nedu.ve\nemprende.ve\nfirm.ve\ngob.ve\ngov.ve\nia.ve\ninfo.ve\nint.ve\nmil.ve\nnet.ve\nnom.ve\norg.ve\nrar.ve\nrec.ve\nstore.ve\ntec.ve\nweb.ve\nvg\nedu.vg\nvi\nco.vi\ncom.vi\nk12.vi\nnet.vi\norg.vi\nvn\nac.vn\nai.vn\nbiz.vn\ncom.vn\nedu.vn\ngov.vn\nhealth.vn\nid.vn\ninfo.vn\nint.vn\nio.vn\nname.vn\nnet.vn\norg.vn\npro.vn\nangiang.vn\nbacgiang.vn\nbackan.vn\nbaclieu.vn\nbacninh.vn\nbaria-vungtau.vn\nbentre.vn\nbinhdinh.vn\nbinhduong.vn\nbinhphuoc.vn\nbinhthuan.vn\ncamau.vn\ncantho.vn\ncaobang.vn\ndaklak.vn\ndaknong.vn\ndanang.vn\ndienbien.vn\ndongnai.vn\ndongthap.vn\ngialai.vn\nhagiang.vn\nhaiduong.vn\nhaiphong.vn\nhanam.vn\nhanoi.vn\nhatinh.vn\nhaugiang.vn\nhoabinh.vn\nhue.vn\nhungyen.vn\nkhanhhoa.vn\nkiengiang.vn\nkontum.vn\nlaichau.vn\nlamdong.vn\nlangson.vn\nlaocai.vn\nlongan.vn\nnamdinh.vn\nnghean.vn\nninhbinh.vn\nninhthuan.vn\nphutho.vn\nphuyen.vn\nquangbinh.vn\nquangnam.vn\nquangngai.vn\nquangninh.vn\nquangtri.vn\nsoctrang.vn\nsonla.vn\ntayninh.vn\nthaibinh.vn\nthainguyen.vn\nthanhhoa.vn\nthanhphohochiminh.vn\nthuathienhue.vn\ntiengiang.vn\ntravinh.vn\ntuyenquang.vn\nvinhlong.vn\nvinhphuc.vn\nyenbai.vn\nvu\ncom.vu\nedu.vu\nnet.vu\norg.vu\nwf\nws\ncom.ws\nedu.ws\ngov.ws\nnet.ws\norg.ws\nyt\nxn--mgbaam7a8h\nxn--y9a3aq\nxn--54b7fta0cc\nxn--90ae\nxn--mgbcpq6gpa1a\nxn--90ais\nxn--fiqs8s\nxn--fiqz9s\nxn--lgbbat1ad8j\nxn--wgbh1c\nxn--e1a4c\nxn--qxa6a\nxn--mgbah1a3hjkrd\nxn--node\nxn--qxam\nxn--j6w193g\nxn--gmqw5a.xn--j6w193g\nxn--55qx5d.xn--j6w193g\nxn--mxtq1m.xn--j6w193g\nxn--wcvs22d.xn--j6w193g\nxn--uc0atv.xn--j6w193g\nxn--od0alg.xn--j6w193g\nxn--2scrj9c\nxn--3hcrj9c\nxn--45br5cyl\nxn--h2breg3eve\nxn--h2brj9c8c\nxn--mgbgu82a\nxn--rvc1e0am3e\nxn--h2brj9c\nxn--mgbbh1a\nxn--mgbbh1a71e\nxn--fpcrj9c3d\nxn--gecrj9c\nxn--s9brj9c\nxn--45brj9c\nxn--xkc2dl3a5ee0h\nxn--mgba3a4f16a\nxn--mgba3a4fra\nxn--mgbtx2b\nxn--mgbayh7gpa\nxn--3e0b707e\nxn--80ao21a\nxn--q7ce6a\nxn--fzc2c9e2c\nxn--xkc2al3hye2a\nxn--mgbc0a9azcg\nxn--d1alf\nxn--l1acc\nxn--mix891f\nxn--mix082f\nxn--mgbx4cd0ab\nxn--mgb9awbf\nxn--mgbai9azgqp6j\nxn--mgbai9a5eva00b\nxn--ygbi2ammx\nxn--90a3ac\nxn--80au.xn--90a3ac\nxn--90azh.xn--90a3ac\nxn--d1at.xn--90a3ac\nxn--c1avg.xn--90a3ac\nxn--o1ac.xn--90a3ac\nxn--o1ach.xn--90a3ac\nxn--p1ai\nxn--wgbl6a\nxn--mgberp4a5d4ar\nxn--mgberp4a5d4a87g\nxn--mgbqly7c0a67fbc\nxn--mgbqly7cvafr\nxn--mgbpl2fh\nxn--yfro4i67o\nxn--clchc0ea0b2g2a9gcd\nxn--ogbpf8fl\nxn--mgbtf8fl\nxn--o3cw4h\nxn--o3cyx2a.xn--o3cw4h\nxn--12co0c3b4eva.xn--o3cw4h\nxn--m3ch0j3a.xn--o3cw4h\nxn--h3cuzk1di.xn--o3cw4h\nxn--12c1fe0br.xn--o3cw4h\nxn--12cfi8ixb8l.xn--o3cw4h\nxn--pgbs0dh\nxn--kpry57d\nxn--kprw13d\nxn--nnx388a\nxn--j1amh\nxn--mgb2ddes\nxxx\nye\ncom.ye\nedu.ye\ngov.ye\nmil.ye\nnet.ye\norg.ye\nac.za\nagric.za\nalt.za\nco.za\nedu.za\ngov.za\ngrondar.za\nlaw.za\nmil.za\nnet.za\nngo.za\nnic.za\nnis.za\nnom.za\norg.za\nschool.za\ntm.za\nweb.za\nzm\nac.zm\nbiz.zm\nco.zm\ncom.zm\nedu.zm\ngov.zm\ninfo.zm\nmil.zm\nnet.zm\norg.zm\nsch.zm\nzw\nac.zw\nco.zw\ngov.zw\nmil.zw\norg.zw\naaa\naarp\nabb\nabbott\nabbvie\nabc\nable\nabogado\nabudhabi\nacademy\naccenture\naccountant\naccountants\naco\nactor\nads\nadult\naeg\naetna\nafl\nafrica\nagakhan\nagency\naig\nairbus\nairforce\nairtel\nakdn\nalibaba\nalipay\nallfinanz\nallstate\nally\nalsace\nalstom\namazon\namericanexpress\namericanfamily\namex\namfam\namica\namsterdam\nanalytics\nandroid\nanquan\nanz\naol\napartments\napp\napple\naquarelle\narab\naramco\narchi\narmy\nart\narte\nasda\nassociates\nathleta\nattorney\nauction\naudi\naudible\naudio\nauspost\nauthor\nauto\nautos\naws\naxa\nazure\nbaby\nbaidu\nbanamex\nband\nbank\nbar\nbarcelona\nbarclaycard\nbarclays\nbarefoot\nbargains\nbaseball\nbasketball\nbauhaus\nbayern\nbbc\nbbt\nbbva\nbcg\nbcn\nbeats\nbeauty\nbeer\nberlin\nbest\nbestbuy\nbet\nbharti\nbible\nbid\nbike\nbing\nbingo\nbio\nblack\nblackfriday\nblockbuster\nblog\nbloomberg\nblue\nbms\nbmw\nbnpparibas\nboats\nboehringer\nbofa\nbom\nbond\nboo\nbook\nbooking\nbosch\nbostik\nboston\nbot\nboutique\nbox\nbradesco\nbridgestone\nbroadway\nbroker\nbrother\nbrussels\nbuild\nbuilders\nbusiness\nbuy\nbuzz\nbzh\ncab\ncafe\ncal\ncall\ncalvinklein\ncam\ncamera\ncamp\ncanon\ncapetown\ncapital\ncapitalone\ncar\ncaravan\ncards\ncare\ncareer\ncareers\ncars\ncasa\ncase\ncash\ncasino\ncatering\ncatholic\ncba\ncbn\ncbre\ncenter\nceo\ncern\ncfa\ncfd\nchanel\nchannel\ncharity\nchase\nchat\ncheap\nchintai\nchristmas\nchrome\nchurch\ncipriani\ncircle\ncisco\ncitadel\nciti\ncitic\ncity\nclaims\ncleaning\nclick\nclinic\nclinique\nclothing\ncloud\nclub\nclubmed\ncoach\ncodes\ncoffee\ncollege\ncologne\ncommbank\ncommunity\ncompany\ncompare\ncomputer\ncomsec\ncondos\nconstruction\nconsulting\ncontact\ncontractors\ncooking\ncool\ncorsica\ncountry\ncoupon\ncoupons\ncourses\ncpa\ncredit\ncreditcard\ncreditunion\ncricket\ncrown\ncrs\ncruise\ncruises\ncuisinella\ncymru\ncyou\ndad\ndance\ndata\ndate\ndating\ndatsun\nday\ndclk\ndds\ndeal\ndealer\ndeals\ndegree\ndelivery\ndell\ndeloitte\ndelta\ndemocrat\ndental\ndentist\ndesi\ndesign\ndev\ndhl\ndiamonds\ndiet\ndigital\ndirect\ndirectory\ndiscount\ndiscover\ndish\ndiy\ndnp\ndocs\ndoctor\ndog\ndomains\ndot\ndownload\ndrive\ndtv\ndubai\ndupont\ndurban\ndvag\ndvr\nearth\neat\neco\nedeka\neducation\nemail\nemerck\nenergy\nengineer\nengineering\nenterprises\nepson\nequipment\nericsson\nerni\nesq\nestate\neurovision\neus\nevents\nexchange\nexpert\nexposed\nexpress\nextraspace\nfage\nfail\nfairwinds\nfaith\nfamily\nfan\nfans\nfarm\nfarmers\nfashion\nfast\nfedex\nfeedback\nferrari\nferrero\nfidelity\nfido\nfilm\nfinal\nfinance\nfinancial\nfire\nfirestone\nfirmdale\nfish\nfishing\nfit\nfitness\nflickr\nflights\nflir\nflorist\nflowers\nfly\nfoo\nfood\nfootball\nford\nforex\nforsale\nforum\nfoundation\nfox\nfree\nfresenius\nfrl\nfrogans\nfrontier\nftr\nfujitsu\nfun\nfund\nfurniture\nfutbol\nfyi\ngal\ngallery\ngallo\ngallup\ngame\ngames\ngap\ngarden\ngay\ngbiz\ngdn\ngea\ngent\ngenting\ngeorge\nggee\ngift\ngifts\ngives\ngiving\nglass\ngle\nglobal\nglobo\ngmail\ngmbh\ngmo\ngmx\ngodaddy\ngold\ngoldpoint\ngolf\ngoodyear\ngoog\ngoogle\ngop\ngot\ngrainger\ngraphics\ngratis\ngreen\ngripe\ngrocery\ngroup\ngucci\nguge\nguide\nguitars\nguru\nhair\nhamburg\nhangout\nhaus\nhbo\nhdfc\nhdfcbank\nhealth\nhealthcare\nhelp\nhelsinki\nhere\nhermes\nhiphop\nhisamitsu\nhitachi\nhiv\nhkt\nhockey\nholdings\nholiday\nhomedepot\nhomegoods\nhomes\nhomesense\nhonda\nhorse\nhospital\nhost\nhosting\nhot\nhotel\nhotels\nhotmail\nhouse\nhow\nhsbc\nhughes\nhyatt\nhyundai\nibm\nicbc\nice\nicu\nieee\nifm\nikano\nimamat\nimdb\nimmo\nimmobilien\ninc\nindustries\ninfiniti\ning\nink\ninstitute\ninsurance\ninsure\ninternational\nintuit\ninvestments\nipiranga\nirish\nismaili\nist\nistanbul\nitau\nitv\njaguar\njava\njcb\njeep\njetzt\njewelry\njio\njll\njmp\njnj\njoburg\njot\njoy\njpmorgan\njprs\njuegos\njuniper\nkaufen\nkddi\nkerryhotels\nkerryproperties\nkfh\nkia\nkids\nkim\nkindle\nkitchen\nkiwi\nkoeln\nkomatsu\nkosher\nkpmg\nkpn\nkrd\nkred\nkuokgroup\nkyoto\nlacaixa\nlamborghini\nlamer\nland\nlandrover\nlanxess\nlasalle\nlat\nlatino\nlatrobe\nlaw\nlawyer\nlds\nlease\nleclerc\nlefrak\nlegal\nlego\nlexus\nlgbt\nlidl\nlife\nlifeinsurance\nlifestyle\nlighting\nlike\nlilly\nlimited\nlimo\nlincoln\nlink\nlive\nliving\nllc\nllp\nloan\nloans\nlocker\nlocus\nlol\nlondon\nlotte\nlotto\nlove\nlpl\nlplfinancial\nltd\nltda\nlundbeck\nluxe\nluxury\nmadrid\nmaif\nmaison\nmakeup\nman\nmanagement\nmango\nmap\nmarket\nmarketing\nmarkets\nmarriott\nmarshalls\nmattel\nmba\nmckinsey\nmed\nmedia\nmeet\nmelbourne\nmeme\nmemorial\nmen\nmenu\nmerck\nmerckmsd\nmiami\nmicrosoft\nmini\nmint\nmit\nmitsubishi\nmlb\nmls\nmma\nmobile\nmoda\nmoe\nmoi\nmom\nmonash\nmoney\nmonster\nmormon\nmortgage\nmoscow\nmoto\nmotorcycles\nmov\nmovie\nmsd\nmtn\nmtr\nmusic\nnab\nnagoya\nnavy\nnba\nnec\nnetbank\nnetflix\nnetwork\nneustar\nnew\nnews\nnext\nnextdirect\nnexus\nnfl\nngo\nnhk\nnico\nnike\nnikon\nninja\nnissan\nnissay\nnokia\nnorton\nnow\nnowruz\nnowtv\nnra\nnrw\nntt\nnyc\nobi\nobserver\noffice\nokinawa\nolayan\nolayangroup\nollo\nomega\none\nong\nonl\nonline\nooo\nopen\noracle\norange\norganic\norigins\nosaka\notsuka\nott\novh\npage\npanasonic\nparis\npars\npartners\nparts\nparty\npay\npccw\npet\npfizer\npharmacy\nphd\nphilips\nphone\nphoto\nphotography\nphotos\nphysio\npics\npictet\npictures\npid\npin\nping\npink\npioneer\npizza\nplace\nplay\nplaystation\nplumbing\nplus\npnc\npohl\npoker\npolitie\nporn\npraxi\npress\nprime\nprod\nproductions\nprof\nprogressive\npromo\nproperties\nproperty\nprotection\npru\nprudential\npub\npwc\nqpon\nquebec\nquest\nracing\nradio\nread\nrealestate\nrealtor\nrealty\nrecipes\nred\nredumbrella\nrehab\nreise\nreisen\nreit\nreliance\nren\nrent\nrentals\nrepair\nreport\nrepublican\nrest\nrestaurant\nreview\nreviews\nrexroth\nrich\nrichardli\nricoh\nril\nrio\nrip\nrocks\nrodeo\nrogers\nroom\nrsvp\nrugby\nruhr\nrun\nrwe\nryukyu\nsaarland\nsafe\nsafety\nsakura\nsale\nsalon\nsamsclub\nsamsung\nsandvik\nsandvikcoromant\nsanofi\nsap\nsarl\nsas\nsave\nsaxo\nsbi\nsbs\nscb\nschaeffler\nschmidt\nscholarships\nschool\nschule\nschwarz\nscience\nscot\nsearch\nseat\nsecure\nsecurity\nseek\nselect\nsener\nservices\nseven\nsew\nsex\nsexy\nsfr\nshangrila\nsharp\nshell\nshia\nshiksha\nshoes\nshop\nshopping\nshouji\nshow\nsilk\nsina\nsingles\nsite\nski\nskin\nsky\nskype\nsling\nsmart\nsmile\nsncf\nsoccer\nsocial\nsoftbank\nsoftware\nsohu\nsolar\nsolutions\nsong\nsony\nsoy\nspa\nspace\nsport\nspot\nsrl\nstada\nstaples\nstar\nstatebank\nstatefarm\nstc\nstcgroup\nstockholm\nstorage\nstore\nstream\nstudio\nstudy\nstyle\nsucks\nsupplies\nsupply\nsupport\nsurf\nsurgery\nsuzuki\nswatch\nswiss\nsydney\nsystems\ntab\ntaipei\ntalk\ntaobao\ntarget\ntatamotors\ntatar\ntattoo\ntax\ntaxi\ntci\ntdk\nteam\ntech\ntechnology\ntemasek\ntennis\nteva\nthd\ntheater\ntheatre\ntiaa\ntickets\ntienda\ntips\ntires\ntirol\ntjmaxx\ntjx\ntkmaxx\ntmall\ntoday\ntokyo\ntools\ntop\ntoray\ntoshiba\ntotal\ntours\ntown\ntoyota\ntoys\ntrade\ntrading\ntraining\ntravel\ntravelers\ntravelersinsurance\ntrust\ntrv\ntube\ntui\ntunes\ntushu\ntvs\nubank\nubs\nunicom\nuniversity\nuno\nuol\nups\nvacations\nvana\nvanguard\nvegas\nventures\nverisign\nversicherung\nvet\nviajes\nvideo\nvig\nviking\nvillas\nvin\nvip\nvirgin\nvisa\nvision\nviva\nvivo\nvlaanderen\nvodka\nvolvo\nvote\nvoting\nvoto\nvoyage\nwales\nwalmart\nwalter\nwang\nwanggou\nwatch\nwatches\nweather\nweatherchannel\nweb\nwebcam\nweber\nwebsite\nwed\nwedding\nweibo\nweir\nwhoswho\nwien\nwiki\nwilliamhill\nwin\nwindows\nwine\nwinners\nwme\nwoodside\nwork\nworks\nworld\nwow\nwtc\nwtf\nxbox\nxerox\nxihuan\nxin\nxn--11b4c3d\nxn--1ck2e1b\nxn--1qqw23a\nxn--30rr7y\nxn--3bst00m\nxn--3ds443g\nxn--3pxu8k\nxn--42c2d9a\nxn--45q11c\nxn--4gbrim\nxn--55qw42g\nxn--55qx5d\nxn--5su34j936bgsg\nxn--5tzm5g\nxn--6frz82g\nxn--6qq986b3xl\nxn--80adxhks\nxn--80aqecdr1a\nxn--80asehdb\nxn--80aswg\nxn--8y0a063a\nxn--9dbq2a\nxn--9et52u\nxn--9krt00a\nxn--b4w605ferd\nxn--bck1b9a5dre4c\nxn--c1avg\nxn--c2br7g\nxn--cck2b3b\nxn--cckwcxetd\nxn--cg4bki\nxn--czr694b\nxn--czrs0t\nxn--czru2d\nxn--d1acj3b\nxn--eckvdtc9d\nxn--efvy88h\nxn--fct429k\nxn--fhbei\nxn--fiq228c5hs\nxn--fiq64b\nxn--fjq720a\nxn--flw351e\nxn--fzys8d69uvgm\nxn--g2xx48c\nxn--gckr3f0f\nxn--gk3at1e\nxn--hxt814e\nxn--i1b6b1a6a2e\nxn--imr513n\nxn--io0a7i\nxn--j1aef\nxn--jlq480n2rg\nxn--jvr189m\nxn--kcrx77d1x4a\nxn--kput3i\nxn--mgba3a3ejt\nxn--mgba7c0bbn0a\nxn--mgbab2bd\nxn--mgbca7dzdo\nxn--mgbi4ecexp\nxn--mgbt3dhd\nxn--mk1bu44c\nxn--mxtq1m\nxn--ngbc5azd\nxn--ngbe9e0a\nxn--ngbrx\nxn--nqv7f\nxn--nqv7fs00ema\nxn--nyqy26a\nxn--otu796d\nxn--p1acf\nxn--pssy2u\nxn--q9jyb4c\nxn--qcka1pmc\nxn--rhqv96g\nxn--rovu88b\nxn--ses554g\nxn--t60b56a\nxn--tckwe\nxn--tiq49xqyj\nxn--unup4y\nxn--vermgensberater-ctb\nxn--vermgensberatung-pwb\nxn--vhquv\nxn--vuq861b\nxn--w4r85el8fhu5dnra\nxn--w4rs40l\nxn--xhq521b\nxn--zfr164b\nxyz\nyachts\nyahoo\nyamaxun\nyandex\nyodobashi\nyoga\nyokohama\nyou\nyoutube\nyun\nzappos\nzara\nzero\nzip\nzone\nzuerich\nco.krd\nedu.krd\nart.pl\ngliwice.pl\nkrakow.pl\npoznan.pl\nwroc.pl\nzakopane.pl\ncc.ua\ninf.ua\nltd.ua\n611.to\na2hosted.com\ncpserver.com\nactivetrail.biz\nmyaddr.dev\nmyaddr.io\ndyn.addr.tools\nmyaddr.tools\nadobeaemcloud.com\n*.dev.adobeaemcloud.com\naem.live\nhlx.live\nadobeaemcloud.net\naem.network\naem.page\nhlx.page\naem.reviews\nadobeio-static.net\nadobeioruntime.net\nafrica.com\n*.auiusercontent.com\nbeep.pl\naiven.app\n*.aivencloud.com\nakadns.net\nakamai.net\nakamai-staging.net\nakamaiedge.net\nakamaiedge-staging.net\nakamaihd.net\nakamaihd-staging.net\nakamaiorigin.net\nakamaiorigin-staging.net\nakamaized.net\nakamaized-staging.net\nedgekey.net\nedgekey-staging.net\nedgesuite.net\nedgesuite-staging.net\nbarsy.ca\n*.compute.estate\n*.alces.network\nalibabacloudcs.com\nms.fun\nms.show\nkasserver.com\naltervista.org\nalwaysdata.net\nmyamaze.net\nexecute-api.cn-north-1.amazonaws.com.cn\nexecute-api.cn-northwest-1.amazonaws.com.cn\nexecute-api.af-south-1.amazonaws.com\nexecute-api.ap-east-1.amazonaws.com\nexecute-api.ap-northeast-1.amazonaws.com\nexecute-api.ap-northeast-2.amazonaws.com\nexecute-api.ap-northeast-3.amazonaws.com\nexecute-api.ap-south-1.amazonaws.com\nexecute-api.ap-south-2.amazonaws.com\nexecute-api.ap-southeast-1.amazonaws.com\nexecute-api.ap-southeast-2.amazonaws.com\nexecute-api.ap-southeast-3.amazonaws.com\nexecute-api.ap-southeast-4.amazonaws.com\nexecute-api.ap-southeast-5.amazonaws.com\nexecute-api.ca-central-1.amazonaws.com\nexecute-api.ca-west-1.amazonaws.com\nexecute-api.eu-central-1.amazonaws.com\nexecute-api.eu-central-2.amazonaws.com\nexecute-api.eu-north-1.amazonaws.com\nexecute-api.eu-south-1.amazonaws.com\nexecute-api.eu-south-2.amazonaws.com\nexecute-api.eu-west-1.amazonaws.com\nexecute-api.eu-west-2.amazonaws.com\nexecute-api.eu-west-3.amazonaws.com\nexecute-api.il-central-1.amazonaws.com\nexecute-api.me-central-1.amazonaws.com\nexecute-api.me-south-1.amazonaws.com\nexecute-api.sa-east-1.amazonaws.com\nexecute-api.us-east-1.amazonaws.com\nexecute-api.us-east-2.amazonaws.com\nexecute-api.us-gov-east-1.amazonaws.com\nexecute-api.us-gov-west-1.amazonaws.com\nexecute-api.us-west-1.amazonaws.com\nexecute-api.us-west-2.amazonaws.com\ncloudfront.net\nauth.af-south-1.amazoncognito.com\nauth.ap-east-1.amazoncognito.com\nauth.ap-northeast-1.amazoncognito.com\nauth.ap-northeast-2.amazoncognito.com\nauth.ap-northeast-3.amazoncognito.com\nauth.ap-south-1.amazoncognito.com\nauth.ap-south-2.amazoncognito.com\nauth.ap-southeast-1.amazoncognito.com\nauth.ap-southeast-2.amazoncognito.com\nauth.ap-southeast-3.amazoncognito.com\nauth.ap-southeast-4.amazoncognito.com\nauth.ap-southeast-5.amazoncognito.com\nauth.ap-southeast-7.amazoncognito.com\nauth.ca-central-1.amazoncognito.com\nauth.ca-west-1.amazoncognito.com\nauth.eu-central-1.amazoncognito.com\nauth.eu-central-2.amazoncognito.com\nauth.eu-north-1.amazoncognito.com\nauth.eu-south-1.amazoncognito.com\nauth.eu-south-2.amazoncognito.com\nauth.eu-west-1.amazoncognito.com\nauth.eu-west-2.amazoncognito.com\nauth.eu-west-3.amazoncognito.com\nauth.il-central-1.amazoncognito.com\nauth.me-central-1.amazoncognito.com\nauth.me-south-1.amazoncognito.com\nauth.mx-central-1.amazoncognito.com\nauth.sa-east-1.amazoncognito.com\nauth.us-east-1.amazoncognito.com\nauth-fips.us-east-1.amazoncognito.com\nauth.us-east-2.amazoncognito.com\nauth-fips.us-east-2.amazoncognito.com\nauth-fips.us-gov-east-1.amazoncognito.com\nauth-fips.us-gov-west-1.amazoncognito.com\nauth.us-west-1.amazoncognito.com\nauth-fips.us-west-1.amazoncognito.com\nauth.us-west-2.amazoncognito.com\nauth-fips.us-west-2.amazoncognito.com\nauth.cognito-idp.eusc-de-east-1.on.amazonwebservices.eu\n*.compute.amazonaws.com.cn\n*.compute.amazonaws.com\n*.compute-1.amazonaws.com\nus-east-1.amazonaws.com\nemrappui-prod.cn-north-1.amazonaws.com.cn\nemrnotebooks-prod.cn-north-1.amazonaws.com.cn\nemrstudio-prod.cn-north-1.amazonaws.com.cn\nemrappui-prod.cn-northwest-1.amazonaws.com.cn\nemrnotebooks-prod.cn-northwest-1.amazonaws.com.cn\nemrstudio-prod.cn-northwest-1.amazonaws.com.cn\nemrappui-prod.af-south-1.amazonaws.com\nemrnotebooks-prod.af-south-1.amazonaws.com\nemrstudio-prod.af-south-1.amazonaws.com\nemrappui-prod.ap-east-1.amazonaws.com\nemrnotebooks-prod.ap-east-1.amazonaws.com\nemrstudio-prod.ap-east-1.amazonaws.com\nemrappui-prod.ap-northeast-1.amazonaws.com\nemrnotebooks-prod.ap-northeast-1.amazonaws.com\nemrstudio-prod.ap-northeast-1.amazonaws.com\nemrappui-prod.ap-northeast-2.amazonaws.com\nemrnotebooks-prod.ap-northeast-2.amazonaws.com\nemrstudio-prod.ap-northeast-2.amazonaws.com\nemrappui-prod.ap-northeast-3.amazonaws.com\nemrnotebooks-prod.ap-northeast-3.amazonaws.com\nemrstudio-prod.ap-northeast-3.amazonaws.com\nemrappui-prod.ap-south-1.amazonaws.com\nemrnotebooks-prod.ap-south-1.amazonaws.com\nemrstudio-prod.ap-south-1.amazonaws.com\nemrappui-prod.ap-south-2.amazonaws.com\nemrnotebooks-prod.ap-south-2.amazonaws.com\nemrstudio-prod.ap-south-2.amazonaws.com\nemrappui-prod.ap-southeast-1.amazonaws.com\nemrnotebooks-prod.ap-southeast-1.amazonaws.com\nemrstudio-prod.ap-southeast-1.amazonaws.com\nemrappui-prod.ap-southeast-2.amazonaws.com\nemrnotebooks-prod.ap-southeast-2.amazonaws.com\nemrstudio-prod.ap-southeast-2.amazonaws.com\nemrappui-prod.ap-southeast-3.amazonaws.com\nemrnotebooks-prod.ap-southeast-3.amazonaws.com\nemrstudio-prod.ap-southeast-3.amazonaws.com\nemrappui-prod.ap-southeast-4.amazonaws.com\nemrnotebooks-prod.ap-southeast-4.amazonaws.com\nemrstudio-prod.ap-southeast-4.amazonaws.com\nemrappui-prod.ca-central-1.amazonaws.com\nemrnotebooks-prod.ca-central-1.amazonaws.com\nemrstudio-prod.ca-central-1.amazonaws.com\nemrappui-prod.ca-west-1.amazonaws.com\nemrnotebooks-prod.ca-west-1.amazonaws.com\nemrstudio-prod.ca-west-1.amazonaws.com\nemrappui-prod.eu-central-1.amazonaws.com\nemrnotebooks-prod.eu-central-1.amazonaws.com\nemrstudio-prod.eu-central-1.amazonaws.com\nemrappui-prod.eu-central-2.amazonaws.com\nemrnotebooks-prod.eu-central-2.amazonaws.com\nemrstudio-prod.eu-central-2.amazonaws.com\nemrappui-prod.eu-north-1.amazonaws.com\nemrnotebooks-prod.eu-north-1.amazonaws.com\nemrstudio-prod.eu-north-1.amazonaws.com\nemrappui-prod.eu-south-1.amazonaws.com\nemrnotebooks-prod.eu-south-1.amazonaws.com\nemrstudio-prod.eu-south-1.amazonaws.com\nemrappui-prod.eu-south-2.amazonaws.com\nemrnotebooks-prod.eu-south-2.amazonaws.com\nemrstudio-prod.eu-south-2.amazonaws.com\nemrappui-prod.eu-west-1.amazonaws.com\nemrnotebooks-prod.eu-west-1.amazonaws.com\nemrstudio-prod.eu-west-1.amazonaws.com\nemrappui-prod.eu-west-2.amazonaws.com\nemrnotebooks-prod.eu-west-2.amazonaws.com\nemrstudio-prod.eu-west-2.amazonaws.com\nemrappui-prod.eu-west-3.amazonaws.com\nemrnotebooks-prod.eu-west-3.amazonaws.com\nemrstudio-prod.eu-west-3.amazonaws.com\nemrappui-prod.il-central-1.amazonaws.com\nemrnotebooks-prod.il-central-1.amazonaws.com\nemrstudio-prod.il-central-1.amazonaws.com\nemrappui-prod.me-central-1.amazonaws.com\nemrnotebooks-prod.me-central-1.amazonaws.com\nemrstudio-prod.me-central-1.amazonaws.com\nemrappui-prod.me-south-1.amazonaws.com\nemrnotebooks-prod.me-south-1.amazonaws.com\nemrstudio-prod.me-south-1.amazonaws.com\nemrappui-prod.sa-east-1.amazonaws.com\nemrnotebooks-prod.sa-east-1.amazonaws.com\nemrstudio-prod.sa-east-1.amazonaws.com\nemrappui-prod.us-east-1.amazonaws.com\nemrnotebooks-prod.us-east-1.amazonaws.com\nemrstudio-prod.us-east-1.amazonaws.com\nemrappui-prod.us-east-2.amazonaws.com\nemrnotebooks-prod.us-east-2.amazonaws.com\nemrstudio-prod.us-east-2.amazonaws.com\nemrappui-prod.us-gov-east-1.amazonaws.com\nemrnotebooks-prod.us-gov-east-1.amazonaws.com\nemrstudio-prod.us-gov-east-1.amazonaws.com\nemrappui-prod.us-gov-west-1.amazonaws.com\nemrnotebooks-prod.us-gov-west-1.amazonaws.com\nemrstudio-prod.us-gov-west-1.amazonaws.com\nemrappui-prod.us-west-1.amazonaws.com\nemrnotebooks-prod.us-west-1.amazonaws.com\nemrstudio-prod.us-west-1.amazonaws.com\nemrappui-prod.us-west-2.amazonaws.com\nemrnotebooks-prod.us-west-2.amazonaws.com\nemrstudio-prod.us-west-2.amazonaws.com\n*.airflow.af-south-1.on.aws\n*.airflow.ap-east-1.on.aws\n*.airflow.ap-northeast-1.on.aws\n*.airflow.ap-northeast-2.on.aws\n*.airflow.ap-northeast-3.on.aws\n*.airflow.ap-south-1.on.aws\n*.airflow.ap-south-2.on.aws\n*.airflow.ap-southeast-1.on.aws\n*.airflow.ap-southeast-2.on.aws\n*.airflow.ap-southeast-3.on.aws\n*.airflow.ap-southeast-4.on.aws\n*.airflow.ap-southeast-5.on.aws\n*.airflow.ca-central-1.on.aws\n*.airflow.ca-west-1.on.aws\n*.airflow.eu-central-1.on.aws\n*.airflow.eu-central-2.on.aws\n*.airflow.eu-north-1.on.aws\n*.airflow.eu-south-1.on.aws\n*.airflow.eu-south-2.on.aws\n*.airflow.eu-west-1.on.aws\n*.airflow.eu-west-2.on.aws\n*.airflow.eu-west-3.on.aws\n*.airflow.il-central-1.on.aws\n*.airflow.me-central-1.on.aws\n*.airflow.me-south-1.on.aws\n*.airflow.sa-east-1.on.aws\n*.airflow.us-east-1.on.aws\n*.airflow.us-east-2.on.aws\n*.airflow.us-west-1.on.aws\n*.airflow.us-west-2.on.aws\n*.cn-north-1.airflow.amazonaws.com.cn\n*.cn-northwest-1.airflow.amazonaws.com.cn\n*.airflow.cn-north-1.on.amazonwebservices.com.cn\n*.airflow.cn-northwest-1.on.amazonwebservices.com.cn\n*.af-south-1.airflow.amazonaws.com\n*.ap-east-1.airflow.amazonaws.com\n*.ap-northeast-1.airflow.amazonaws.com\n*.ap-northeast-2.airflow.amazonaws.com\n*.ap-northeast-3.airflow.amazonaws.com\n*.ap-south-1.airflow.amazonaws.com\n*.ap-south-2.airflow.amazonaws.com\n*.ap-southeast-1.airflow.amazonaws.com\n*.ap-southeast-2.airflow.amazonaws.com\n*.ap-southeast-3.airflow.amazonaws.com\n*.ap-southeast-4.airflow.amazonaws.com\n*.ap-southeast-5.airflow.amazonaws.com\n*.ap-southeast-7.airflow.amazonaws.com\n*.ca-central-1.airflow.amazonaws.com\n*.ca-west-1.airflow.amazonaws.com\n*.eu-central-1.airflow.amazonaws.com\n*.eu-central-2.airflow.amazonaws.com\n*.eu-north-1.airflow.amazonaws.com\n*.eu-south-1.airflow.amazonaws.com\n*.eu-south-2.airflow.amazonaws.com\n*.eu-west-1.airflow.amazonaws.com\n*.eu-west-2.airflow.amazonaws.com\n*.eu-west-3.airflow.amazonaws.com\n*.il-central-1.airflow.amazonaws.com\n*.me-central-1.airflow.amazonaws.com\n*.me-south-1.airflow.amazonaws.com\n*.sa-east-1.airflow.amazonaws.com\n*.us-east-1.airflow.amazonaws.com\n*.us-east-2.airflow.amazonaws.com\n*.us-west-1.airflow.amazonaws.com\n*.us-west-2.airflow.amazonaws.com\n*.rds.cn-north-1.amazonaws.com.cn\n*.rds.cn-northwest-1.amazonaws.com.cn\n*.af-south-1.rds.amazonaws.com\n*.ap-east-1.rds.amazonaws.com\n*.ap-east-2.rds.amazonaws.com\n*.ap-northeast-1.rds.amazonaws.com\n*.ap-northeast-2.rds.amazonaws.com\n*.ap-northeast-3.rds.amazonaws.com\n*.ap-south-1.rds.amazonaws.com\n*.ap-south-2.rds.amazonaws.com\n*.ap-southeast-1.rds.amazonaws.com\n*.ap-southeast-2.rds.amazonaws.com\n*.ap-southeast-3.rds.amazonaws.com\n*.ap-southeast-4.rds.amazonaws.com\n*.ap-southeast-5.rds.amazonaws.com\n*.ap-southeast-6.rds.amazonaws.com\n*.ap-southeast-7.rds.amazonaws.com\n*.ca-central-1.rds.amazonaws.com\n*.ca-west-1.rds.amazonaws.com\n*.eu-central-1.rds.amazonaws.com\n*.eu-central-2.rds.amazonaws.com\n*.eu-west-1.rds.amazonaws.com\n*.eu-west-2.rds.amazonaws.com\n*.eu-west-3.rds.amazonaws.com\n*.il-central-1.rds.amazonaws.com\n*.me-central-1.rds.amazonaws.com\n*.me-south-1.rds.amazonaws.com\n*.mx-central-1.rds.amazonaws.com\n*.sa-east-1.rds.amazonaws.com\n*.us-east-1.rds.amazonaws.com\n*.us-east-2.rds.amazonaws.com\n*.us-gov-east-1.rds.amazonaws.com\n*.us-gov-west-1.rds.amazonaws.com\n*.us-northeast-1.rds.amazonaws.com\n*.us-west-1.rds.amazonaws.com\n*.us-west-2.rds.amazonaws.com\ns3.dualstack.cn-north-1.amazonaws.com.cn\ns3-accesspoint.dualstack.cn-north-1.amazonaws.com.cn\ns3-website.dualstack.cn-north-1.amazonaws.com.cn\ns3.cn-north-1.amazonaws.com.cn\ns3-accesspoint.cn-north-1.amazonaws.com.cn\ns3-deprecated.cn-north-1.amazonaws.com.cn\ns3-object-lambda.cn-north-1.amazonaws.com.cn\ns3-website.cn-north-1.amazonaws.com.cn\ns3.dualstack.cn-northwest-1.amazonaws.com.cn\ns3-accesspoint.dualstack.cn-northwest-1.amazonaws.com.cn\ns3.cn-northwest-1.amazonaws.com.cn\ns3-accesspoint.cn-northwest-1.amazonaws.com.cn\ns3-object-lambda.cn-northwest-1.amazonaws.com.cn\ns3-website.cn-northwest-1.amazonaws.com.cn\ns3.dualstack.af-south-1.amazonaws.com\ns3-accesspoint.dualstack.af-south-1.amazonaws.com\ns3-website.dualstack.af-south-1.amazonaws.com\ns3.af-south-1.amazonaws.com\ns3-accesspoint.af-south-1.amazonaws.com\ns3-object-lambda.af-south-1.amazonaws.com\ns3-website.af-south-1.amazonaws.com\ns3.dualstack.ap-east-1.amazonaws.com\ns3-accesspoint.dualstack.ap-east-1.amazonaws.com\ns3.ap-east-1.amazonaws.com\ns3-accesspoint.ap-east-1.amazonaws.com\ns3-object-lambda.ap-east-1.amazonaws.com\ns3-website.ap-east-1.amazonaws.com\ns3.dualstack.ap-northeast-1.amazonaws.com\ns3-accesspoint.dualstack.ap-northeast-1.amazonaws.com\ns3-website.dualstack.ap-northeast-1.amazonaws.com\ns3.ap-northeast-1.amazonaws.com\ns3-accesspoint.ap-northeast-1.amazonaws.com\ns3-object-lambda.ap-northeast-1.amazonaws.com\ns3-website.ap-northeast-1.amazonaws.com\ns3.dualstack.ap-northeast-2.amazonaws.com\ns3-accesspoint.dualstack.ap-northeast-2.amazonaws.com\ns3-website.dualstack.ap-northeast-2.amazonaws.com\ns3.ap-northeast-2.amazonaws.com\ns3-accesspoint.ap-northeast-2.amazonaws.com\ns3-object-lambda.ap-northeast-2.amazonaws.com\ns3-website.ap-northeast-2.amazonaws.com\ns3.dualstack.ap-northeast-3.amazonaws.com\ns3-accesspoint.dualstack.ap-northeast-3.amazonaws.com\ns3-website.dualstack.ap-northeast-3.amazonaws.com\ns3.ap-northeast-3.amazonaws.com\ns3-accesspoint.ap-northeast-3.amazonaws.com\ns3-object-lambda.ap-northeast-3.amazonaws.com\ns3-website.ap-northeast-3.amazonaws.com\ns3.dualstack.ap-south-1.amazonaws.com\ns3-accesspoint.dualstack.ap-south-1.amazonaws.com\ns3-website.dualstack.ap-south-1.amazonaws.com\ns3.ap-south-1.amazonaws.com\ns3-accesspoint.ap-south-1.amazonaws.com\ns3-object-lambda.ap-south-1.amazonaws.com\ns3-website.ap-south-1.amazonaws.com\ns3.dualstack.ap-south-2.amazonaws.com\ns3-accesspoint.dualstack.ap-south-2.amazonaws.com\ns3-website.dualstack.ap-south-2.amazonaws.com\ns3.ap-south-2.amazonaws.com\ns3-accesspoint.ap-south-2.amazonaws.com\ns3-object-lambda.ap-south-2.amazonaws.com\ns3-website.ap-south-2.amazonaws.com\ns3.dualstack.ap-southeast-1.amazonaws.com\ns3-accesspoint.dualstack.ap-southeast-1.amazonaws.com\ns3-website.dualstack.ap-southeast-1.amazonaws.com\ns3.ap-southeast-1.amazonaws.com\ns3-accesspoint.ap-southeast-1.amazonaws.com\ns3-object-lambda.ap-southeast-1.amazonaws.com\ns3-website.ap-southeast-1.amazonaws.com\ns3.dualstack.ap-southeast-2.amazonaws.com\ns3-accesspoint.dualstack.ap-southeast-2.amazonaws.com\ns3-website.dualstack.ap-southeast-2.amazonaws.com\ns3.ap-southeast-2.amazonaws.com\ns3-accesspoint.ap-southeast-2.amazonaws.com\ns3-object-lambda.ap-southeast-2.amazonaws.com\ns3-website.ap-southeast-2.amazonaws.com\ns3.dualstack.ap-southeast-3.amazonaws.com\ns3-accesspoint.dualstack.ap-southeast-3.amazonaws.com\ns3-website.dualstack.ap-southeast-3.amazonaws.com\ns3.ap-southeast-3.amazonaws.com\ns3-accesspoint.ap-southeast-3.amazonaws.com\ns3-object-lambda.ap-southeast-3.amazonaws.com\ns3-website.ap-southeast-3.amazonaws.com\ns3.dualstack.ap-southeast-4.amazonaws.com\ns3-accesspoint.dualstack.ap-southeast-4.amazonaws.com\ns3-website.dualstack.ap-southeast-4.amazonaws.com\ns3.ap-southeast-4.amazonaws.com\ns3-accesspoint.ap-southeast-4.amazonaws.com\ns3-object-lambda.ap-southeast-4.amazonaws.com\ns3-website.ap-southeast-4.amazonaws.com\ns3.dualstack.ap-southeast-5.amazonaws.com\ns3-accesspoint.dualstack.ap-southeast-5.amazonaws.com\ns3-website.dualstack.ap-southeast-5.amazonaws.com\ns3.ap-southeast-5.amazonaws.com\ns3-accesspoint.ap-southeast-5.amazonaws.com\ns3-deprecated.ap-southeast-5.amazonaws.com\ns3-object-lambda.ap-southeast-5.amazonaws.com\ns3-website.ap-southeast-5.amazonaws.com\ns3.dualstack.ca-central-1.amazonaws.com\ns3-accesspoint.dualstack.ca-central-1.amazonaws.com\ns3-accesspoint-fips.dualstack.ca-central-1.amazonaws.com\ns3-fips.dualstack.ca-central-1.amazonaws.com\ns3-website.dualstack.ca-central-1.amazonaws.com\ns3.ca-central-1.amazonaws.com\ns3-accesspoint.ca-central-1.amazonaws.com\ns3-accesspoint-fips.ca-central-1.amazonaws.com\ns3-fips.ca-central-1.amazonaws.com\ns3-object-lambda.ca-central-1.amazonaws.com\ns3-website.ca-central-1.amazonaws.com\ns3.dualstack.ca-west-1.amazonaws.com\ns3-accesspoint.dualstack.ca-west-1.amazonaws.com\ns3-accesspoint-fips.dualstack.ca-west-1.amazonaws.com\ns3-fips.dualstack.ca-west-1.amazonaws.com\ns3-website.dualstack.ca-west-1.amazonaws.com\ns3.ca-west-1.amazonaws.com\ns3-accesspoint.ca-west-1.amazonaws.com\ns3-accesspoint-fips.ca-west-1.amazonaws.com\ns3-fips.ca-west-1.amazonaws.com\ns3-object-lambda.ca-west-1.amazonaws.com\ns3-website.ca-west-1.amazonaws.com\ns3.dualstack.eu-central-1.amazonaws.com\ns3-accesspoint.dualstack.eu-central-1.amazonaws.com\ns3-website.dualstack.eu-central-1.amazonaws.com\ns3.eu-central-1.amazonaws.com\ns3-accesspoint.eu-central-1.amazonaws.com\ns3-object-lambda.eu-central-1.amazonaws.com\ns3-website.eu-central-1.amazonaws.com\ns3.dualstack.eu-central-2.amazonaws.com\ns3-accesspoint.dualstack.eu-central-2.amazonaws.com\ns3-website.dualstack.eu-central-2.amazonaws.com\ns3.eu-central-2.amazonaws.com\ns3-accesspoint.eu-central-2.amazonaws.com\ns3-object-lambda.eu-central-2.amazonaws.com\ns3-website.eu-central-2.amazonaws.com\ns3.dualstack.eu-north-1.amazonaws.com\ns3-accesspoint.dualstack.eu-north-1.amazonaws.com\ns3.eu-north-1.amazonaws.com\ns3-accesspoint.eu-north-1.amazonaws.com\ns3-object-lambda.eu-north-1.amazonaws.com\ns3-website.eu-north-1.amazonaws.com\ns3.dualstack.eu-south-1.amazonaws.com\ns3-accesspoint.dualstack.eu-south-1.amazonaws.com\ns3-website.dualstack.eu-south-1.amazonaws.com\ns3.eu-south-1.amazonaws.com\ns3-accesspoint.eu-south-1.amazonaws.com\ns3-object-lambda.eu-south-1.amazonaws.com\ns3-website.eu-south-1.amazonaws.com\ns3.dualstack.eu-south-2.amazonaws.com\ns3-accesspoint.dualstack.eu-south-2.amazonaws.com\ns3-website.dualstack.eu-south-2.amazonaws.com\ns3.eu-south-2.amazonaws.com\ns3-accesspoint.eu-south-2.amazonaws.com\ns3-object-lambda.eu-south-2.amazonaws.com\ns3-website.eu-south-2.amazonaws.com\ns3.dualstack.eu-west-1.amazonaws.com\ns3-accesspoint.dualstack.eu-west-1.amazonaws.com\ns3-website.dualstack.eu-west-1.amazonaws.com\ns3.eu-west-1.amazonaws.com\ns3-accesspoint.eu-west-1.amazonaws.com\ns3-deprecated.eu-west-1.amazonaws.com\ns3-object-lambda.eu-west-1.amazonaws.com\ns3-website.eu-west-1.amazonaws.com\ns3.dualstack.eu-west-2.amazonaws.com\ns3-accesspoint.dualstack.eu-west-2.amazonaws.com\ns3.eu-west-2.amazonaws.com\ns3-accesspoint.eu-west-2.amazonaws.com\ns3-object-lambda.eu-west-2.amazonaws.com\ns3-website.eu-west-2.amazonaws.com\ns3.dualstack.eu-west-3.amazonaws.com\ns3-accesspoint.dualstack.eu-west-3.amazonaws.com\ns3-website.dualstack.eu-west-3.amazonaws.com\ns3.eu-west-3.amazonaws.com\ns3-accesspoint.eu-west-3.amazonaws.com\ns3-object-lambda.eu-west-3.amazonaws.com\ns3-website.eu-west-3.amazonaws.com\ns3.dualstack.il-central-1.amazonaws.com\ns3-accesspoint.dualstack.il-central-1.amazonaws.com\ns3-website.dualstack.il-central-1.amazonaws.com\ns3.il-central-1.amazonaws.com\ns3-accesspoint.il-central-1.amazonaws.com\ns3-object-lambda.il-central-1.amazonaws.com\ns3-website.il-central-1.amazonaws.com\ns3.dualstack.me-central-1.amazonaws.com\ns3-accesspoint.dualstack.me-central-1.amazonaws.com\ns3-website.dualstack.me-central-1.amazonaws.com\ns3.me-central-1.amazonaws.com\ns3-accesspoint.me-central-1.amazonaws.com\ns3-object-lambda.me-central-1.amazonaws.com\ns3-website.me-central-1.amazonaws.com\ns3.dualstack.me-south-1.amazonaws.com\ns3-accesspoint.dualstack.me-south-1.amazonaws.com\ns3.me-south-1.amazonaws.com\ns3-accesspoint.me-south-1.amazonaws.com\ns3-object-lambda.me-south-1.amazonaws.com\ns3-website.me-south-1.amazonaws.com\ns3.amazonaws.com\ns3-1.amazonaws.com\ns3-ap-east-1.amazonaws.com\ns3-ap-northeast-1.amazonaws.com\ns3-ap-northeast-2.amazonaws.com\ns3-ap-northeast-3.amazonaws.com\ns3-ap-south-1.amazonaws.com\ns3-ap-southeast-1.amazonaws.com\ns3-ap-southeast-2.amazonaws.com\ns3-ca-central-1.amazonaws.com\ns3-eu-central-1.amazonaws.com\ns3-eu-north-1.amazonaws.com\ns3-eu-west-1.amazonaws.com\ns3-eu-west-2.amazonaws.com\ns3-eu-west-3.amazonaws.com\ns3-external-1.amazonaws.com\ns3-fips-us-gov-east-1.amazonaws.com\ns3-fips-us-gov-west-1.amazonaws.com\nmrap.accesspoint.s3-global.amazonaws.com\ns3-me-south-1.amazonaws.com\ns3-sa-east-1.amazonaws.com\ns3-us-east-2.amazonaws.com\ns3-us-gov-east-1.amazonaws.com\ns3-us-gov-west-1.amazonaws.com\ns3-us-west-1.amazonaws.com\ns3-us-west-2.amazonaws.com\ns3-website-ap-northeast-1.amazonaws.com\ns3-website-ap-southeast-1.amazonaws.com\ns3-website-ap-southeast-2.amazonaws.com\ns3-website-eu-west-1.amazonaws.com\ns3-website-sa-east-1.amazonaws.com\ns3-website-us-east-1.amazonaws.com\ns3-website-us-gov-west-1.amazonaws.com\ns3-website-us-west-1.amazonaws.com\ns3-website-us-west-2.amazonaws.com\ns3.dualstack.sa-east-1.amazonaws.com\ns3-accesspoint.dualstack.sa-east-1.amazonaws.com\ns3-website.dualstack.sa-east-1.amazonaws.com\ns3.sa-east-1.amazonaws.com\ns3-accesspoint.sa-east-1.amazonaws.com\ns3-object-lambda.sa-east-1.amazonaws.com\ns3-website.sa-east-1.amazonaws.com\ns3.dualstack.us-east-1.amazonaws.com\ns3-accesspoint.dualstack.us-east-1.amazonaws.com\ns3-accesspoint-fips.dualstack.us-east-1.amazonaws.com\ns3-fips.dualstack.us-east-1.amazonaws.com\ns3-website.dualstack.us-east-1.amazonaws.com\ns3.us-east-1.amazonaws.com\ns3-accesspoint.us-east-1.amazonaws.com\ns3-accesspoint-fips.us-east-1.amazonaws.com\ns3-deprecated.us-east-1.amazonaws.com\ns3-fips.us-east-1.amazonaws.com\ns3-object-lambda.us-east-1.amazonaws.com\ns3-website.us-east-1.amazonaws.com\ns3.dualstack.us-east-2.amazonaws.com\ns3-accesspoint.dualstack.us-east-2.amazonaws.com\ns3-accesspoint-fips.dualstack.us-east-2.amazonaws.com\ns3-fips.dualstack.us-east-2.amazonaws.com\ns3-website.dualstack.us-east-2.amazonaws.com\ns3.us-east-2.amazonaws.com\ns3-accesspoint.us-east-2.amazonaws.com\ns3-accesspoint-fips.us-east-2.amazonaws.com\ns3-deprecated.us-east-2.amazonaws.com\ns3-fips.us-east-2.amazonaws.com\ns3-object-lambda.us-east-2.amazonaws.com\ns3-website.us-east-2.amazonaws.com\ns3.dualstack.us-gov-east-1.amazonaws.com\ns3-accesspoint.dualstack.us-gov-east-1.amazonaws.com\ns3-accesspoint-fips.dualstack.us-gov-east-1.amazonaws.com\ns3-fips.dualstack.us-gov-east-1.amazonaws.com\ns3-website.dualstack.us-gov-east-1.amazonaws.com\ns3.us-gov-east-1.amazonaws.com\ns3-accesspoint.us-gov-east-1.amazonaws.com\ns3-accesspoint-fips.us-gov-east-1.amazonaws.com\ns3-fips.us-gov-east-1.amazonaws.com\ns3-object-lambda.us-gov-east-1.amazonaws.com\ns3-website.us-gov-east-1.amazonaws.com\ns3.dualstack.us-gov-west-1.amazonaws.com\ns3-accesspoint.dualstack.us-gov-west-1.amazonaws.com\ns3-accesspoint-fips.dualstack.us-gov-west-1.amazonaws.com\ns3-fips.dualstack.us-gov-west-1.amazonaws.com\ns3-website.dualstack.us-gov-west-1.amazonaws.com\ns3.us-gov-west-1.amazonaws.com\ns3-accesspoint.us-gov-west-1.amazonaws.com\ns3-accesspoint-fips.us-gov-west-1.amazonaws.com\ns3-fips.us-gov-west-1.amazonaws.com\ns3-object-lambda.us-gov-west-1.amazonaws.com\ns3-website.us-gov-west-1.amazonaws.com\ns3.dualstack.us-west-1.amazonaws.com\ns3-accesspoint.dualstack.us-west-1.amazonaws.com\ns3-accesspoint-fips.dualstack.us-west-1.amazonaws.com\ns3-fips.dualstack.us-west-1.amazonaws.com\ns3-website.dualstack.us-west-1.amazonaws.com\ns3.us-west-1.amazonaws.com\ns3-accesspoint.us-west-1.amazonaws.com\ns3-accesspoint-fips.us-west-1.amazonaws.com\ns3-fips.us-west-1.amazonaws.com\ns3-object-lambda.us-west-1.amazonaws.com\ns3-website.us-west-1.amazonaws.com\ns3.dualstack.us-west-2.amazonaws.com\ns3-accesspoint.dualstack.us-west-2.amazonaws.com\ns3-accesspoint-fips.dualstack.us-west-2.amazonaws.com\ns3-fips.dualstack.us-west-2.amazonaws.com\ns3-website.dualstack.us-west-2.amazonaws.com\ns3.us-west-2.amazonaws.com\ns3-accesspoint.us-west-2.amazonaws.com\ns3-accesspoint-fips.us-west-2.amazonaws.com\ns3-deprecated.us-west-2.amazonaws.com\ns3-fips.us-west-2.amazonaws.com\ns3-object-lambda.us-west-2.amazonaws.com\ns3-website.us-west-2.amazonaws.com\nlabeling.ap-northeast-1.sagemaker.aws\nlabeling.ap-northeast-2.sagemaker.aws\nlabeling.ap-south-1.sagemaker.aws\nlabeling.ap-southeast-1.sagemaker.aws\nlabeling.ap-southeast-2.sagemaker.aws\nlabeling.ca-central-1.sagemaker.aws\nlabeling.eu-central-1.sagemaker.aws\nlabeling.eu-west-1.sagemaker.aws\nlabeling.eu-west-2.sagemaker.aws\nlabeling.us-east-1.sagemaker.aws\nlabeling.us-east-2.sagemaker.aws\nlabeling.us-west-2.sagemaker.aws\nnotebook.af-south-1.sagemaker.aws\nnotebook.ap-east-1.sagemaker.aws\nnotebook.ap-northeast-1.sagemaker.aws\nnotebook.ap-northeast-2.sagemaker.aws\nnotebook.ap-northeast-3.sagemaker.aws\nnotebook.ap-south-1.sagemaker.aws\nnotebook.ap-south-2.sagemaker.aws\nnotebook.ap-southeast-1.sagemaker.aws\nnotebook.ap-southeast-2.sagemaker.aws\nnotebook.ap-southeast-3.sagemaker.aws\nnotebook.ap-southeast-4.sagemaker.aws\nnotebook.ca-central-1.sagemaker.aws\nnotebook-fips.ca-central-1.sagemaker.aws\nnotebook.ca-west-1.sagemaker.aws\nnotebook-fips.ca-west-1.sagemaker.aws\nnotebook.eu-central-1.sagemaker.aws\nnotebook.eu-central-2.sagemaker.aws\nnotebook.eu-north-1.sagemaker.aws\nnotebook.eu-south-1.sagemaker.aws\nnotebook.eu-south-2.sagemaker.aws\nnotebook.eu-west-1.sagemaker.aws\nnotebook.eu-west-2.sagemaker.aws\nnotebook.eu-west-3.sagemaker.aws\nnotebook.il-central-1.sagemaker.aws\nnotebook.me-central-1.sagemaker.aws\nnotebook.me-south-1.sagemaker.aws\nnotebook.sa-east-1.sagemaker.aws\nnotebook.us-east-1.sagemaker.aws\nnotebook-fips.us-east-1.sagemaker.aws\nnotebook.us-east-2.sagemaker.aws\nnotebook-fips.us-east-2.sagemaker.aws\nnotebook.us-gov-east-1.sagemaker.aws\nnotebook-fips.us-gov-east-1.sagemaker.aws\nnotebook.us-gov-west-1.sagemaker.aws\nnotebook-fips.us-gov-west-1.sagemaker.aws\nnotebook.us-west-1.sagemaker.aws\nnotebook-fips.us-west-1.sagemaker.aws\nnotebook.us-west-2.sagemaker.aws\nnotebook-fips.us-west-2.sagemaker.aws\nnotebook.cn-north-1.sagemaker.com.cn\nnotebook.cn-northwest-1.sagemaker.com.cn\nstudio.af-south-1.sagemaker.aws\nstudio.ap-east-1.sagemaker.aws\nstudio.ap-northeast-1.sagemaker.aws\nstudio.ap-northeast-2.sagemaker.aws\nstudio.ap-northeast-3.sagemaker.aws\nstudio.ap-south-1.sagemaker.aws\nstudio.ap-southeast-1.sagemaker.aws\nstudio.ap-southeast-2.sagemaker.aws\nstudio.ap-southeast-3.sagemaker.aws\nstudio.ca-central-1.sagemaker.aws\nstudio.eu-central-1.sagemaker.aws\nstudio.eu-central-2.sagemaker.aws\nstudio.eu-north-1.sagemaker.aws\nstudio.eu-south-1.sagemaker.aws\nstudio.eu-south-2.sagemaker.aws\nstudio.eu-west-1.sagemaker.aws\nstudio.eu-west-2.sagemaker.aws\nstudio.eu-west-3.sagemaker.aws\nstudio.il-central-1.sagemaker.aws\nstudio.me-central-1.sagemaker.aws\nstudio.me-south-1.sagemaker.aws\nstudio.sa-east-1.sagemaker.aws\nstudio.us-east-1.sagemaker.aws\nstudio.us-east-2.sagemaker.aws\nstudio.us-gov-east-1.sagemaker.aws\nstudio-fips.us-gov-east-1.sagemaker.aws\nstudio.us-gov-west-1.sagemaker.aws\nstudio-fips.us-gov-west-1.sagemaker.aws\nstudio.us-west-1.sagemaker.aws\nstudio.us-west-2.sagemaker.aws\nstudio.cn-north-1.sagemaker.com.cn\nstudio.cn-northwest-1.sagemaker.com.cn\n*.experiments.sagemaker.aws\nanalytics-gateway.ap-northeast-1.amazonaws.com\nanalytics-gateway.ap-northeast-2.amazonaws.com\nanalytics-gateway.ap-south-1.amazonaws.com\nanalytics-gateway.ap-southeast-1.amazonaws.com\nanalytics-gateway.ap-southeast-2.amazonaws.com\nanalytics-gateway.eu-central-1.amazonaws.com\nanalytics-gateway.eu-west-1.amazonaws.com\nanalytics-gateway.us-east-1.amazonaws.com\nanalytics-gateway.us-east-2.amazonaws.com\nanalytics-gateway.us-west-2.amazonaws.com\namplifyapp.com\n*.awsapprunner.com\nwebview-assets.aws-cloud9.af-south-1.amazonaws.com\nvfs.cloud9.af-south-1.amazonaws.com\nwebview-assets.cloud9.af-south-1.amazonaws.com\nwebview-assets.aws-cloud9.ap-east-1.amazonaws.com\nvfs.cloud9.ap-east-1.amazonaws.com\nwebview-assets.cloud9.ap-east-1.amazonaws.com\nwebview-assets.aws-cloud9.ap-northeast-1.amazonaws.com\nvfs.cloud9.ap-northeast-1.amazonaws.com\nwebview-assets.cloud9.ap-northeast-1.amazonaws.com\nwebview-assets.aws-cloud9.ap-northeast-2.amazonaws.com\nvfs.cloud9.ap-northeast-2.amazonaws.com\nwebview-assets.cloud9.ap-northeast-2.amazonaws.com\nwebview-assets.aws-cloud9.ap-northeast-3.amazonaws.com\nvfs.cloud9.ap-northeast-3.amazonaws.com\nwebview-assets.cloud9.ap-northeast-3.amazonaws.com\nwebview-assets.aws-cloud9.ap-south-1.amazonaws.com\nvfs.cloud9.ap-south-1.amazonaws.com\nwebview-assets.cloud9.ap-south-1.amazonaws.com\nwebview-assets.aws-cloud9.ap-southeast-1.amazonaws.com\nvfs.cloud9.ap-southeast-1.amazonaws.com\nwebview-assets.cloud9.ap-southeast-1.amazonaws.com\nwebview-assets.aws-cloud9.ap-southeast-2.amazonaws.com\nvfs.cloud9.ap-southeast-2.amazonaws.com\nwebview-assets.cloud9.ap-southeast-2.amazonaws.com\nwebview-assets.aws-cloud9.ca-central-1.amazonaws.com\nvfs.cloud9.ca-central-1.amazonaws.com\nwebview-assets.cloud9.ca-central-1.amazonaws.com\nwebview-assets.aws-cloud9.eu-central-1.amazonaws.com\nvfs.cloud9.eu-central-1.amazonaws.com\nwebview-assets.cloud9.eu-central-1.amazonaws.com\nwebview-assets.aws-cloud9.eu-north-1.amazonaws.com\nvfs.cloud9.eu-north-1.amazonaws.com\nwebview-assets.cloud9.eu-north-1.amazonaws.com\nwebview-assets.aws-cloud9.eu-south-1.amazonaws.com\nvfs.cloud9.eu-south-1.amazonaws.com\nwebview-assets.cloud9.eu-south-1.amazonaws.com\nwebview-assets.aws-cloud9.eu-west-1.amazonaws.com\nvfs.cloud9.eu-west-1.amazonaws.com\nwebview-assets.cloud9.eu-west-1.amazonaws.com\nwebview-assets.aws-cloud9.eu-west-2.amazonaws.com\nvfs.cloud9.eu-west-2.amazonaws.com\nwebview-assets.cloud9.eu-west-2.amazonaws.com\nwebview-assets.aws-cloud9.eu-west-3.amazonaws.com\nvfs.cloud9.eu-west-3.amazonaws.com\nwebview-assets.cloud9.eu-west-3.amazonaws.com\nwebview-assets.aws-cloud9.il-central-1.amazonaws.com\nvfs.cloud9.il-central-1.amazonaws.com\nwebview-assets.aws-cloud9.me-south-1.amazonaws.com\nvfs.cloud9.me-south-1.amazonaws.com\nwebview-assets.cloud9.me-south-1.amazonaws.com\nwebview-assets.aws-cloud9.sa-east-1.amazonaws.com\nvfs.cloud9.sa-east-1.amazonaws.com\nwebview-assets.cloud9.sa-east-1.amazonaws.com\nwebview-assets.aws-cloud9.us-east-1.amazonaws.com\nvfs.cloud9.us-east-1.amazonaws.com\nwebview-assets.cloud9.us-east-1.amazonaws.com\nwebview-assets.aws-cloud9.us-east-2.amazonaws.com\nvfs.cloud9.us-east-2.amazonaws.com\nwebview-assets.cloud9.us-east-2.amazonaws.com\nwebview-assets.aws-cloud9.us-west-1.amazonaws.com\nvfs.cloud9.us-west-1.amazonaws.com\nwebview-assets.cloud9.us-west-1.amazonaws.com\nwebview-assets.aws-cloud9.us-west-2.amazonaws.com\nvfs.cloud9.us-west-2.amazonaws.com\nwebview-assets.cloud9.us-west-2.amazonaws.com\nawsapps.com\ncn-north-1.eb.amazonaws.com.cn\ncn-northwest-1.eb.amazonaws.com.cn\nelasticbeanstalk.com\naf-south-1.elasticbeanstalk.com\nap-east-1.elasticbeanstalk.com\nap-northeast-1.elasticbeanstalk.com\nap-northeast-2.elasticbeanstalk.com\nap-northeast-3.elasticbeanstalk.com\nap-south-1.elasticbeanstalk.com\nap-southeast-1.elasticbeanstalk.com\nap-southeast-2.elasticbeanstalk.com\nap-southeast-3.elasticbeanstalk.com\nap-southeast-5.elasticbeanstalk.com\nap-southeast-7.elasticbeanstalk.com\nca-central-1.elasticbeanstalk.com\neu-central-1.elasticbeanstalk.com\neu-north-1.elasticbeanstalk.com\neu-south-1.elasticbeanstalk.com\neu-south-2.elasticbeanstalk.com\neu-west-1.elasticbeanstalk.com\neu-west-2.elasticbeanstalk.com\neu-west-3.elasticbeanstalk.com\nil-central-1.elasticbeanstalk.com\nme-central-1.elasticbeanstalk.com\nme-south-1.elasticbeanstalk.com\nsa-east-1.elasticbeanstalk.com\nus-east-1.elasticbeanstalk.com\nus-east-2.elasticbeanstalk.com\nus-gov-east-1.elasticbeanstalk.com\nus-gov-west-1.elasticbeanstalk.com\nus-west-1.elasticbeanstalk.com\nus-west-2.elasticbeanstalk.com\n*.elb.amazonaws.com.cn\n*.elb.amazonaws.com\nawsglobalaccelerator.com\nlambda-url.af-south-1.on.aws\nlambda-url.ap-east-1.on.aws\nlambda-url.ap-northeast-1.on.aws\nlambda-url.ap-northeast-2.on.aws\nlambda-url.ap-northeast-3.on.aws\nlambda-url.ap-south-1.on.aws\nlambda-url.ap-southeast-1.on.aws\nlambda-url.ap-southeast-2.on.aws\nlambda-url.ap-southeast-3.on.aws\nlambda-url.ca-central-1.on.aws\nlambda-url.eu-central-1.on.aws\nlambda-url.eu-north-1.on.aws\nlambda-url.eu-south-1.on.aws\nlambda-url.eu-west-1.on.aws\nlambda-url.eu-west-2.on.aws\nlambda-url.eu-west-3.on.aws\nlambda-url.me-south-1.on.aws\nlambda-url.sa-east-1.on.aws\nlambda-url.us-east-1.on.aws\nlambda-url.us-east-2.on.aws\nlambda-url.us-west-1.on.aws\nlambda-url.us-west-2.on.aws\n*.private.repost.aws\ntransfer-webapp.af-south-1.on.aws\ntransfer-webapp.ap-east-1.on.aws\ntransfer-webapp.ap-northeast-1.on.aws\ntransfer-webapp.ap-northeast-2.on.aws\ntransfer-webapp.ap-northeast-3.on.aws\ntransfer-webapp.ap-south-1.on.aws\ntransfer-webapp.ap-south-2.on.aws\ntransfer-webapp.ap-southeast-1.on.aws\ntransfer-webapp.ap-southeast-2.on.aws\ntransfer-webapp.ap-southeast-3.on.aws\ntransfer-webapp.ap-southeast-4.on.aws\ntransfer-webapp.ap-southeast-5.on.aws\ntransfer-webapp.ap-southeast-7.on.aws\ntransfer-webapp.ca-central-1.on.aws\ntransfer-webapp.ca-west-1.on.aws\ntransfer-webapp.eu-central-1.on.aws\ntransfer-webapp.eu-central-2.on.aws\ntransfer-webapp.eu-north-1.on.aws\ntransfer-webapp.eu-south-1.on.aws\ntransfer-webapp.eu-south-2.on.aws\ntransfer-webapp.eu-west-1.on.aws\ntransfer-webapp.eu-west-2.on.aws\ntransfer-webapp.eu-west-3.on.aws\ntransfer-webapp.il-central-1.on.aws\ntransfer-webapp.me-central-1.on.aws\ntransfer-webapp.me-south-1.on.aws\ntransfer-webapp.mx-central-1.on.aws\ntransfer-webapp.sa-east-1.on.aws\ntransfer-webapp.us-east-1.on.aws\ntransfer-webapp.us-east-2.on.aws\ntransfer-webapp.us-gov-east-1.on.aws\ntransfer-webapp-fips.us-gov-east-1.on.aws\ntransfer-webapp.us-gov-west-1.on.aws\ntransfer-webapp-fips.us-gov-west-1.on.aws\ntransfer-webapp.us-west-1.on.aws\ntransfer-webapp.us-west-2.on.aws\ntransfer-webapp.cn-north-1.on.amazonwebservices.com.cn\ntransfer-webapp.cn-northwest-1.on.amazonwebservices.com.cn\neero.online\neero-stage.online\nopentunnel.xyz\nantagonist.cloud\nclaude.app\nclaudeusercontent.com\nframe.claudeusercontent.com\n*.cursorusercontent.com\napigee.io\npanel.dev\nsiiites.com\nint.apple\n*.cloud.int.apple\n*.r.cloud.int.apple\n*.ap-north-1.r.cloud.int.apple\n*.ap-south-1.r.cloud.int.apple\n*.ap-south-2.r.cloud.int.apple\n*.eu-central-1.r.cloud.int.apple\n*.eu-north-1.r.cloud.int.apple\n*.us-central-1.r.cloud.int.apple\n*.us-central-2.r.cloud.int.apple\n*.us-east-1.r.cloud.int.apple\n*.us-east-2.r.cloud.int.apple\n*.us-west-1.r.cloud.int.apple\n*.us-west-2.r.cloud.int.apple\n*.us-west-3.r.cloud.int.apple\nappspacehosted.com\nappspaceusercontent.com\nappudo.net\nappwrite.global\nappwrite.network\n*.appwrite.run\non-aptible.com\nf5.si\narvanedge.ir\nuser.aseinet.ne.jp\ngv.vc\nd.gv.vc\nuser.party.eus\npimienta.org\npoivron.org\npotager.org\nsweetpepper.org\nmyasustor.com\n*.atlassian-3p.com\n*.atlassian-3p-us-gov-mod.com\n*.atlassian-isolated-3p.com\ncdn.prod.atlassian-dev.net\nmyfritz.link\nmyfritz.net\n*.awdev.ca\n*.advisor.ws\necommerce-shop.pl\nb-data.io\nbalena-devices.com\nbase.ec\nofficial.ec\nbuyshop.jp\nfashionstore.jp\nhandcrafted.jp\nkawaiishop.jp\nsupersale.jp\ntheshop.jp\nshopselect.net\nbase.shop\nbeagleboard.io\nbearblog.dev\n*.beget.app\n*.begetcdn.cloud\npages.gay\nbnr.la\nbitbucket.io\nblackbaudcdn.net\nof.je\nsquare.site\nbluebite.io\nboomla.net\nboutir.com\nboxfuse.io\nsquare7.ch\nbplaced.com\nbplaced.de\nsquare7.de\nbplaced.net\nsquare7.net\nbrave.app\n*.s.brave.app\nbrave.dev\n*.s.brave.dev\nbrave.io\n*.s.brave.io\nshop.brendly.ba\nshop.brendly.hr\nshop.brendly.rs\nbrowsersafetymark.io\nradio.am\nradio.fm\ncdn.bubble.io\nbubbleapps.io\n*.bwcloud-os-instance.de\ncafjs.com\ncanva-apps.cn\ncanva-code.cn\nmy.canvasite.cn\nkhsj.cn\ncanva-apps.com\ncanva-hosted-embed.com\ncanvacode.com\nrice-labs.com\ncanva.link\ncanva.run\nmy.canva.site\ndrr.ac\nuwu.ai\ncarrd.co\ncrd.co\nju.mp\napi.gov.uk\ncdn77-storage.com\nrsc.contentproxy9.cz\nr.cdn77.net\ncdn77-ssl.net\nc.cdn77.org\nrsc.cdn77.org\nssl.origin.cdn77-secure.org\nza.bz\nbr.com\ncn.com\nde.com\neu.com\njpn.com\nmex.com\nru.com\nsa.com\nuk.com\nus.com\nza.com\ncom.de\ngb.net\nhu.net\njp.net\nse.net\nuk.net\nae.org\ncom.se\ncx.ua\ndiscourse.diy\ndiscourse.group\ndiscourse.team\nclerk.app\nclerkstage.app\n*.lcl.dev\n*.lclstage.dev\n*.stg.dev\n*.stgstage.dev\ncleverapps.cc\n*.services.clever-cloud.com\ncleverapps.io\ncleverapps.tech\nclickrising.net\ncloudns.asia\ncloudns.be\ncloud-ip.biz\ncloudns.biz\ncloud-ip.cc\ncloudns.cc\ncloudns.ch\ncloudns.cl\ncloudns.club\nabrdns.com\ndnsabr.com\nip-ddns.com\ncloudns.cx\ncloudns.eu\ncloudns.in\ncloudns.info\nddns-ip.net\ndns-cloud.net\ndns-dynamic.net\ncloudns.nz\ncloudns.org\nip-dynamic.org\ncloudns.ph\ncloudns.pro\ncloudns.pw\ncloudns.us\nc66.me\ncloud66.ws\njdevcloud.com\nwpdevcloud.com\ncloudaccess.host\nfreesite.host\ncloudaccess.net\ncloudbeesusercontent.io\n*.cloudera.site\ncloudflare.app\ncf-ipfs.com\ncloudflare-ipfs.com\ntrycloudflare.com\npages.dev\nr2.dev\nworkers.dev\ncloudflare.net\ncdn.cloudflare.net\ncdn.cloudflareanycast.net\ncdn.cloudflarecn.net\ncdn.cloudflareglobal.net\ncust.cloudscale.ch\nobjects.lpg.cloudscale.ch\nobjects.rma.cloudscale.ch\nlpg.objectstorage.ch\nrma.objectstorage.ch\nwnext.app\ncnpy.gdn\n*.otap.co\nco.ca\nco.com\nsch.ac\ndev.cv\nstore.cv\ncodeberg.page\ncodepen.app\ncodepen.dev\ncsb.app\npreview.csb.app\nco.nl\nco.no\n*.devinapps.com\nwebhosting.be\nprvw.eu\nhosting-cluster.nl\nctfcloud.net\nconvex.app\nconvex.cloud\neu-west-1.convex.cloud\nus-east-1.convex.cloud\nconvex.site\neu-west-1.convex.site\nus-east-1.convex.site\nac.ru\nedu.ru\ngov.ru\nint.ru\nmil.ru\ncorespeed.app\ndyn.cosidns.de\ndnsupdater.de\ndynamisches-dns.de\ninternet-dns.de\nl-o-g-i-n.de\ndynamic-dns.info\nfeste-ip.net\nknx-server.net\nstatic-access.net\ncraft.me\nrealm.cz\ncfolks.pl\ncyon.link\ncyon.site\nbiz.dk\nco.dk\nfirm.dk\nreg.dk\nstore.dk\ndyndns.dappnode.io\nbuiltwithdark.com\ndarklang.io\ndemo.datadetect.com\ninstance.datadetect.com\nedgestack.me\ndattolocal.com\ndattorelay.com\ndattoweb.com\nmydatto.com\ndattolocal.net\nmydatto.net\nddnss.de\ndyn.ddnss.de\ndyndns.ddnss.de\ndyn-ip24.de\ndyndns1.de\nhome-webserver.de\ndyn.home-webserver.de\nmyhome-server.de\nddnss.org\ndebian.net\ndefinima.io\ndefinima.net\ndeno.dev\ndeno-staging.dev\ndeno.net\nsandbox.deno.net\ndeployagent.com\npiebox.site\ndeployagent.space\ndedyn.io\ndeuxfleurs.eu\ndeuxfleurs.page\n*.at.ply.gg\nd6.ply.gg\njoinmc.link\nplayit.plus\n*.at.playit.plus\nwith.playit.plus\nicp0.io\n*.raw.icp0.io\nicp1.io\n*.raw.icp1.io\nopencloud.me\n*.icp.net\ncaffeine.site\ncaffeine.xyz\nmybox.company\nintouch.email\nmybox.me\nmybox.page\ndfirma.pl\ndkonto.pl\nyou2.pl\nondigitalocean.app\n*.digitaloceanspaces.com\nqzz.io\nus.kg\nxx.kg\ndpdns.org\ndiscordsays.com\ndiscordsez.com\njozi.biz\nccwu.cc\ncc.cd\nus.ci\nde5.net\ndnshome.at\nresolve.bar\nddns.berlin\ndnshome.cloud\nddnssec.de\ndnshome.de\ndyndnssec.de\nheimdns.de\nsrvdns.de\ndnshome.eu\ndnshome.it\ndyn.now\nheimdns.online\nddns.wtf\nonline.th\nshop.th\nco.scot\nme.scot\norg.scot\ndrayddns.com\nshoparena.pl\ndreamhosters.com\ndurumis.com\nduckdns.org\ndy.fi\ntunk.org\ndyndns.biz\nfor-better.biz\nfor-more.biz\nfor-some.biz\nfor-the.biz\nselfip.biz\nwebhop.biz\nftpaccess.cc\ngame-server.cc\nmyphotos.cc\nscrapping.cc\nblogdns.com\ncechire.com\ndnsalias.com\ndnsdojo.com\ndoesntexist.com\ndontexist.com\ndoomdns.com\ndyn-o-saur.com\ndynalias.com\ndyndns-at-home.com\ndyndns-at-work.com\ndyndns-blog.com\ndyndns-free.com\ndyndns-home.com\ndyndns-ip.com\ndyndns-mail.com\ndyndns-office.com\ndyndns-pics.com\ndyndns-remote.com\ndyndns-server.com\ndyndns-web.com\ndyndns-wiki.com\ndyndns-work.com\nest-a-la-maison.com\nest-a-la-masion.com\nest-le-patron.com\nest-mon-blogueur.com\nfrom-ak.com\nfrom-al.com\nfrom-ar.com\nfrom-ca.com\nfrom-ct.com\nfrom-dc.com\nfrom-de.com\nfrom-fl.com\nfrom-ga.com\nfrom-hi.com\nfrom-ia.com\nfrom-id.com\nfrom-il.com\nfrom-in.com\nfrom-ks.com\nfrom-ky.com\nfrom-ma.com\nfrom-md.com\nfrom-mi.com\nfrom-mn.com\nfrom-mo.com\nfrom-ms.com\nfrom-mt.com\nfrom-nc.com\nfrom-nd.com\nfrom-ne.com\nfrom-nh.com\nfrom-nj.com\nfrom-nm.com\nfrom-nv.com\nfrom-oh.com\nfrom-ok.com\nfrom-or.com\nfrom-pa.com\nfrom-pr.com\nfrom-ri.com\nfrom-sc.com\nfrom-sd.com\nfrom-tn.com\nfrom-tx.com\nfrom-ut.com\nfrom-va.com\nfrom-vt.com\nfrom-wa.com\nfrom-wi.com\nfrom-wv.com\nfrom-wy.com\ngetmyip.com\ngotdns.com\nhobby-site.com\nhomelinux.com\nhomeunix.com\niamallama.com\nis-a-anarchist.com\nis-a-blogger.com\nis-a-bookkeeper.com\nis-a-bulls-fan.com\nis-a-caterer.com\nis-a-chef.com\nis-a-conservative.com\nis-a-cpa.com\nis-a-cubicle-slave.com\nis-a-democrat.com\nis-a-designer.com\nis-a-doctor.com\nis-a-financialadvisor.com\nis-a-geek.com\nis-a-green.com\nis-a-guru.com\nis-a-hard-worker.com\nis-a-hunter.com\nis-a-landscaper.com\nis-a-lawyer.com\nis-a-liberal.com\nis-a-libertarian.com\nis-a-llama.com\nis-a-musician.com\nis-a-nascarfan.com\nis-a-nurse.com\nis-a-painter.com\nis-a-personaltrainer.com\nis-a-photographer.com\nis-a-player.com\nis-a-republican.com\nis-a-rockstar.com\nis-a-socialist.com\nis-a-student.com\nis-a-teacher.com\nis-a-techie.com\nis-a-therapist.com\nis-an-accountant.com\nis-an-actor.com\nis-an-actress.com\nis-an-anarchist.com\nis-an-artist.com\nis-an-engineer.com\nis-an-entertainer.com\nis-certified.com\nis-gone.com\nis-into-anime.com\nis-into-cars.com\nis-into-cartoons.com\nis-into-games.com\nis-leet.com\nis-not-certified.com\nis-slick.com\nis-uberleet.com\nis-with-theband.com\nisa-geek.com\nisa-hockeynut.com\nissmarterthanyou.com\nlikes-pie.com\nlikescandy.com\nneat-url.com\nsaves-the-whales.com\nselfip.com\nsells-for-less.com\nsells-for-u.com\nservebbs.com\nsimple-url.com\nspace-to-rent.com\nteaches-yoga.com\nwritesthisblog.com\nath.cx\nfuettertdasnetz.de\nisteingeek.de\nistmein.de\nlebtimnetz.de\nleitungsen.de\ntraeumtgerade.de\nbarrel-of-knowledge.info\nbarrell-of-knowledge.info\ndyndns.info\nfor-our.info\ngroks-the.info\ngroks-this.info\nhere-for-more.info\nknowsitall.info\nselfip.info\nwebhop.info\nforgot.her.name\nforgot.his.name\nat-band-camp.net\nblogdns.net\nbroke-it.net\nbuyshouses.net\ndnsalias.net\ndnsdojo.net\ndoes-it.net\ndontexist.net\ndynalias.net\ndynathome.net\nendofinternet.net\nfrom-az.net\nfrom-co.net\nfrom-la.net\nfrom-ny.net\ngets-it.net\nham-radio-op.net\nhomeftp.net\nhomeip.net\nhomelinux.net\nhomeunix.net\nin-the-band.net\nis-a-chef.net\nis-a-geek.net\nisa-geek.net\nkicks-ass.net\noffice-on-the.net\npodzone.net\nscrapper-site.net\nselfip.net\nsells-it.net\nservebbs.net\nserveftp.net\nthruhere.net\nwebhop.net\nmerseine.nu\nmine.nu\nshacknet.nu\nblogdns.org\nblogsite.org\nboldlygoingnowhere.org\ndnsalias.org\ndnsdojo.org\ndoesntexist.org\ndontexist.org\ndoomdns.org\ndvrdns.org\ndynalias.org\ndyndns.org\ngo.dyndns.org\nhome.dyndns.org\nendofinternet.org\nendoftheinternet.org\nfrom-me.org\ngame-host.org\ngotdns.org\nhobby-site.org\nhomedns.org\nhomeftp.org\nhomelinux.org\nhomeunix.org\nis-a-bruinsfan.org\nis-a-candidate.org\nis-a-celticsfan.org\nis-a-chef.org\nis-a-geek.org\nis-a-knight.org\nis-a-linux-user.org\nis-a-patsfan.org\nis-a-soxfan.org\nis-found.org\nis-lost.org\nis-saved.org\nis-very-bad.org\nis-very-evil.org\nis-very-good.org\nis-very-nice.org\nis-very-sweet.org\nisa-geek.org\nkicks-ass.org\nmisconfused.org\npodzone.org\nreadmyblog.org\nselfip.org\nsellsyourhome.org\nservebbs.org\nserveftp.org\nservegame.org\nstuff-4-sale.org\nwebhop.org\nbetter-than.tv\ndyndns.tv\non-the-web.tv\nworse-than.tv\nis-by.us\nland-4-sale.us\nstuff-4-sale.us\ndyndns.ws\nmypets.ws\n1cooldns.com\nbumbleshrimp.com\nddnsfree.com\nddnsgeek.com\nddnsguru.com\ndynuddns.com\ndynuhosting.com\ngiize.com\ngleeze.com\nkozow.com\nloseyourip.com\nooguy.com\npivohosting.com\ntheworkpc.com\nwiredbladehosting.com\ncasacam.net\ndynu.net\ndynuddns.net\nmysynology.net\nopik.net\nspryt.net\naccesscam.org\ncamdvr.org\nfreeddns.org\nmywire.org\nroxa.org\nwebredirect.org\nmyddns.rocks\ndynv6.net\ne4.cz\neasypanel.app\neasypanel.host\n*.ewp.live\ntwmail.cc\ntwmail.net\ntwmail.org\nmymailer.com.tw\nurl.tw\nat.emf.camp\nrt.ht\nelementor.cloud\nelementor.cool\nemergent.cloud\npreview.emergentagent.com\nemergent.host\nmytuleap.com\ntuleap-partners.com\nencr.app\nfrontend.encr.app\nencoreapi.com\nlp.dev\napi.lp.dev\nobjects.lp.dev\neu.encoway.cloud\neu.org\nal.eu.org\nasso.eu.org\nat.eu.org\nau.eu.org\nbe.eu.org\nbg.eu.org\nca.eu.org\ncd.eu.org\nch.eu.org\ncn.eu.org\ncy.eu.org\ncz.eu.org\nde.eu.org\ndk.eu.org\nedu.eu.org\nee.eu.org\nes.eu.org\nfi.eu.org\nfr.eu.org\ngr.eu.org\nhr.eu.org\nhu.eu.org\nie.eu.org\nil.eu.org\nin.eu.org\nint.eu.org\nis.eu.org\nit.eu.org\njp.eu.org\nkr.eu.org\nlt.eu.org\nlu.eu.org\nlv.eu.org\nme.eu.org\nmk.eu.org\nmt.eu.org\nmy.eu.org\nnet.eu.org\nng.eu.org\nnl.eu.org\nno.eu.org\nnz.eu.org\npl.eu.org\npt.eu.org\nro.eu.org\nru.eu.org\nse.eu.org\nsi.eu.org\nsk.eu.org\ntr.eu.org\nuk.eu.org\nus.eu.org\neurodir.ru\neu-1.evennode.com\neu-2.evennode.com\neu-3.evennode.com\neu-4.evennode.com\nus-1.evennode.com\nus-2.evennode.com\nus-3.evennode.com\nus-4.evennode.com\nrelay.evervault.app\nrelay.evervault.dev\nexe.xyz\nexpo.app\non.expo.app\nstaging.expo.app\non.staging.expo.app\nfspages.org\nru.net\nadygeya.ru\nbashkiria.ru\nbir.ru\ncbg.ru\ncom.ru\ndagestan.ru\ngrozny.ru\nkalmykia.ru\nkustanai.ru\nmarine.ru\nmordovia.ru\nmsk.ru\nmytis.ru\nnalchik.ru\nnov.ru\npyatigorsk.ru\nspb.ru\nvladikavkaz.ru\nvladimir.ru\nabkhazia.su\nadygeya.su\naktyubinsk.su\narkhangelsk.su\narmenia.su\nashgabad.su\nazerbaijan.su\nbalashov.su\nbashkiria.su\nbryansk.su\nbukhara.su\nchimkent.su\ndagestan.su\neast-kazakhstan.su\nexnet.su\ngeorgia.su\ngrozny.su\nivanovo.su\njambyl.su\nkalmykia.su\nkaluga.su\nkaracol.su\nkaraganda.su\nkarelia.su\nkhakassia.su\nkrasnodar.su\nkurgan.su\nkustanai.su\nlenug.su\nmangyshlak.su\nmordovia.su\nmsk.su\nmurmansk.su\nnalchik.su\nnavoi.su\nnorth-kazakhstan.su\nnov.su\nobninsk.su\npenza.su\npokrovsk.su\nsochi.su\nspb.su\ntashkent.su\ntermez.su\ntogliatti.su\ntroitsk.su\ntselinograd.su\ntula.su\ntuva.su\nvladikavkaz.su\nvladimir.su\nvologda.su\nchannelsdvr.net\nu.channelsdvr.net\nedgecompute.app\nfastly-edge.com\nfastly-terrarium.com\nfreetls.fastly.net\nmap.fastly.net\na.prod.fastly.net\nglobal.prod.fastly.net\na.ssl.fastly.net\nb.ssl.fastly.net\nglobal.ssl.fastly.net\nfastlylb.net\nmap.fastlylb.net\n*.user.fm\nfastvps-server.com\nfastvps.host\nmyfast.host\nfastvps.site\nmyfast.space\nconn.uk\ncopro.uk\nhosp.uk\nfedorainfracloud.org\nfedorapeople.org\ncloud.fedoraproject.org\napp.os.fedoraproject.org\napp.os.stg.fedoraproject.org\nmydobiss.com\nfh-muenster.io\npayload.dev\nfigma.site\nfigma-gov.site\npreview.site\nfilegear.me\nfirebaseapp.com\nfldrv.com\non-fleek.app\nflutterflow.app\nsprites.app\nfly.dev\ne2b.app\nframer.ai\nframer.app\nframercanvas.com\nframer.media\nframer.photos\nframer.website\nframer.wiki\n*.0e.vc\nfreebox-os.com\nfreeboxos.com\nfbx-os.fr\nfbxos.fr\nfreebox-os.fr\nfreeboxos.fr\nfreedesktop.org\nfreemyip.com\n*.frusky.de\nwien.funkfeuer.at\ndaemon.asia\ndix.asia\nmydns.bz\n0am.jp\n0g0.jp\n0j0.jp\n0t0.jp\nmydns.jp\npgw.jp\nwjg.jp\nkeyword-on.net\nlive-on.net\nserver-on.net\nmydns.tw\nmydns.vc\n*.futurecms.at\n*.ex.futurecms.at\n*.in.futurecms.at\nfuturehosting.at\nfuturemailing.at\n*.ex.ortsinfo.at\n*.kunden.ortsinfo.at\n*.statics.cloud\ngadget.app\ngadget.host\naliases121.com\ncampaign.gov.uk\nservice.gov.uk\nindependent-commission.uk\nindependent-inquest.uk\nindependent-inquiry.uk\nindependent-panel.uk\nindependent-review.uk\npublic-inquiry.uk\nroyal-commission.uk\ngehirn.ne.jp\nusercontent.jp\ngentapps.com\ngentlentapis.com\ncdn-edges.net\ngsj.bz\ngitbook.io\ngithub.app\ngithubusercontent.com\ngithubpreview.dev\ngithub.io\ngitlab.io\ngitapp.si\ngitpage.si\nnog.community\nco.ro\nshop.ro\nlolipop.io\nangry.jp\nbabyblue.jp\nbabymilk.jp\nbackdrop.jp\nbambina.jp\nbitter.jp\nblush.jp\nboo.jp\nboy.jp\nboyfriend.jp\nbut.jp\ncandypop.jp\ncapoo.jp\ncatfood.jp\ncheap.jp\nchicappa.jp\nchillout.jp\nchips.jp\nchowder.jp\nchu.jp\nciao.jp\ncocotte.jp\ncoolblog.jp\ncranky.jp\ncutegirl.jp\ndaa.jp\ndeca.jp\ndeci.jp\ndigick.jp\negoism.jp\nfakefur.jp\nfem.jp\nflier.jp\nfloppy.jp\nfool.jp\nfrenchkiss.jp\ngirlfriend.jp\ngirly.jp\ngloomy.jp\ngonna.jp\ngreater.jp\nhacca.jp\nheavy.jp\nher.jp\nhiho.jp\nhippy.jp\nholy.jp\nhungry.jp\nicurus.jp\nitigo.jp\njellybean.jp\nkikirara.jp\nkill.jp\nkilo.jp\nkuron.jp\nlittlestar.jp\nlolipopmc.jp\nlolitapunk.jp\nlomo.jp\nlovepop.jp\nlovesick.jp\nmain.jp\nmods.jp\nmond.jp\nmongolian.jp\nmoo.jp\nnamaste.jp\nnikita.jp\nnobushi.jp\nnoor.jp\noops.jp\nparallel.jp\nparasite.jp\npecori.jp\npeewee.jp\npenne.jp\npepper.jp\nperma.jp\npigboat.jp\npinoko.jp\npunyu.jp\npupu.jp\npussycat.jp\npya.jp\nraindrop.jp\nreadymade.jp\nsadist.jp\nschoolbus.jp\nsecret.jp\nstaba.jp\nstripper.jp\nsub.jp\nsunnyday.jp\nthick.jp\ntonkotsu.jp\nunder.jp\nupper.jp\nvelvet.jp\nverse.jp\nversus.jp\nvivian.jp\nwatson.jp\nweblike.jp\nwhitesnow.jp\nzombie.jp\nheteml.net\nvibehost.space\ngraphic.design\ngoip.de\n*.hosted.app\n*.run.app\n*.mtls.run.app\nweb.app\n*.0emm.com\nappspot.com\n*.r.appspot.com\nblogspot.com\ncodespot.com\ngoogleapis.com\ngooglecode.com\npagespeedmobilizer.com\nwithgoogle.com\nwithyoutube.com\n*.gateway.dev\ncloud.goog\ntranslate.goog\n*.usercontent.goog\ncloudfunctions.net\ngoupile.fr\npymnt.uk\ngov.nl\ngrafana-dev.net\ngrayjayleagues.com\ngrebedoc.dev\nxn--gnstigbestellen-zvb.de\nxn--gnstigliefern-wob.de\ngv.uy\nhackclub.app\nxn--hkkinen-5wa.fi\nhashbang.sh\nhasura.app\nhasura-app.io\nhatenablog.com\nhatenadiary.com\nhateblo.jp\nhatenablog.jp\nhatenadiary.jp\nhatenadiary.org\npages.it.hs-heilbronn.de\npages-research.it.hs-heilbronn.de\nheiyu.space\nhelioho.st\nheliohost.us\nhepforge.org\nonhercules.app\nhercules-app.com\nhercules-dev.com\nhere.now\nherokuapp.com\nheyflow.page\nheyflow.site\nravendb.cloud\nravendb.community\ndevelopment.run\nravendb.run\nhidns.co\nhidns.vip\nhomesklep.pl\n*.kin.one\n*.id.pub\n*.kin.pub\nseprox.hooc.me\nhoplix.shop\norx.biz\nbiz.ng\nco.biz.ng\ndl.biz.ng\ngo.biz.ng\nlg.biz.ng\non.biz.ng\ncol.ng\nfirm.ng\ngen.ng\nltd.ng\nngo.ng\nplc.ng\nhstgr.cloud\nhostyhosting.io\nhf.space\nstatic.hf.space\nhypernode.io\niobb.net\nco.cz\n*.moonscale.io\nmoonscale.net\ngr.com\niki.fi\nibxos.it\niliadboxos.it\nimagine.diy\nimagine-proxy.work\nsmushcdn.com\nwphostedmail.com\nwpmucdn.com\ntempurl.host\nwpmudev.host\ndyn-berlin.de\nin-berlin.de\nin-brb.de\nin-butter.de\nin-dsl.de\nin-vpn.de\nin-dsl.net\nin-vpn.net\nin-dsl.org\nin-vpn.org\noninferno.net\ninfo.cx\nac.leg.br\nal.leg.br\nam.leg.br\nap.leg.br\nba.leg.br\nce.leg.br\ndf.leg.br\nes.leg.br\ngo.leg.br\nma.leg.br\nmg.leg.br\nms.leg.br\nmt.leg.br\npa.leg.br\npb.leg.br\npe.leg.br\npi.leg.br\npr.leg.br\nrj.leg.br\nrn.leg.br\nro.leg.br\nrr.leg.br\nrs.leg.br\nsc.leg.br\nse.leg.br\nsp.leg.br\nto.leg.br\npixolino.com\nna4u.ru\nbotdash.app\nbotdash.dev\nbotdash.gg\nbotdash.net\nbotda.sh\nbotdash.xyz\nonline-server.cloud\napps-1and1.com\nlive-website.com\nwebspace-host.com\napps-1and1.net\nwebsitebuilder.online\napp-ionos.space\niopsys.se\n*.inbrowser.dev\n*.dweb.link\n*.inbrowser.link\nipifony.net\nhome64.de\nipv64.de\nipv64.net\nir.md\nis-a-good.dev\niservschule.de\nmein-iserv.de\nschuldock.de\nschulplattform.de\nschulserver.de\ntest-iserv.de\niserv.dev\niserv.host\nispmanager.name\nmel.cloudlets.com.au\ncloud.interhostsolutions.be\nalp1.ae.flow.ch\nappengine.flow.ch\nes-1.axarnet.cloud\ndiadem.cloud\nvip.jelastic.cloud\njele.cloud\nit1.eur.aruba.jenv-aruba.cloud\nit1.jenv-aruba.cloud\nkeliweb.cloud\ncs.keliweb.cloud\noxa.cloud\ntn.oxa.cloud\nuk.oxa.cloud\nprimetel.cloud\nuk.primetel.cloud\nca.reclaim.cloud\nuk.reclaim.cloud\nus.reclaim.cloud\nch.trendhosting.cloud\nde.trendhosting.cloud\njele.club\ndopaas.com\npaas.hosted-by-previder.com\nrag-cloud.hosteur.com\nrag-cloud-ch.hosteur.com\njcloud.ik-server.com\njcloud-ver-jpc.ik-server.com\ndemo.jelastic.com\npaas.massivegrid.com\njed.wafaicloud.com\nryd.wafaicloud.com\nj.scaleforce.com.cy\njelastic.dogado.eu\nfi.cloudplatform.fi\njele.host\nmircloud.host\npaas.beebyte.io\nsekd1.beebyteapp.io\njele.io\njc.neen.it\njcloud.kz\ncloudjiffy.net\nfra1-de.cloudjiffy.net\nwest1-us.cloudjiffy.net\njls-sto1.elastx.net\njls-sto2.elastx.net\njls-sto3.elastx.net\nfr-1.paas.massivegrid.net\nlon-1.paas.massivegrid.net\nlon-2.paas.massivegrid.net\nny-1.paas.massivegrid.net\nny-2.paas.massivegrid.net\nsg-1.paas.massivegrid.net\njelastic.saveincloud.net\nnordeste-idc.saveincloud.net\nj.scaleforce.net\nsdscloud.pl\nunicloud.pl\nmircloud.ru\nenscaled.sg\njele.site\njelastic.team\norangecloud.tn\nj.layershift.co.uk\nphx.enscaled.us\nmircloud.us\nmyjino.ru\n*.hosting.myjino.ru\n*.landing.myjino.ru\n*.spectrum.myjino.ru\n*.vps.myjino.ru\njote.cloud\njotelulu.cloud\neu1-plenit.com\nla1-plenit.com\nus1-plenit.com\nwebadorsite.com\njouwweb.site\njs.org\nelastic.k2.cloud\nlb.ru-msk.k2.cloud\ns3.ru-msk.k2.cloud\nwebsite.ru-msk.k2.cloud\nlb.ru-spb.k2.cloud\ns3.ru-spb.k2.cloud\nwebsite.ru-spb.k2.cloud\ns3.k2.cloud\nwebsite.k2.cloud\nkaas.gg\nkhplay.nl\nkapsi.fi\nkdns.fr\nezproxy.kuleuven.be\nkuleuven.cloud\nkeenetic.io\nkeenetic.link\nkeenetic.name\nkeenetic.pro\nae.kg\nkeymachine.de\nkiloapps.ai\nkiloapps.io\nkinghost.net\nuni5.net\nknightpoint.systems\nkoobin.events\nwebthings.io\nkrellian.net\noya.to\nco.de\nshiptoday.app\nshiptoday.build\nlaravel.cloud\non-forge.com\non-vapor.com\n*.eth.limo\n*.eth.link\ngit-repos.de\nlcube-server.de\nsvn-repos.de\nleadpages.co\nlpages.co\nlpusercontent.com\nleapcell.app\nleapcell.dev\nleapcell.online\nliara.run\niran.liara.run\nlibp2p.direct\nruncontainers.dev\nco.business\nco.education\nco.events\nco.financial\nco.network\nco.place\nco.technology\nlinkyard-cloud.ch\nlinkyard.cloud\nmembers.linode.com\n*.nodebalancer.linode.com\n*.linodeobjects.com\nip.linodeusercontent.com\nwe.bs\nfilegear-sg.me\nggff.net\n*.user.localcert.dev\nlocaltonet.com\n*.localto.net\nlodz.pl\npabianice.pl\nplock.pl\nsieradz.pl\nskierniewice.pl\nzgierz.pl\nloginline.app\nloginline.dev\nloginline.io\nloginline.services\nloginline.site\nlohmus.me\nlovable.app\nlovableproject.com\nlovable.run\nlovable.sh\nkrasnik.pl\nleczna.pl\nlubartow.pl\nlublin.pl\nponiatowa.pl\nswidnik.pl\nglug.org.uk\nlug.org.uk\nlugs.org.uk\nbarsy.bg\nbarsy.club\nbarsycenter.com\nbarsyonline.com\nbarsy.de\nbarsy.dev\nbarsy.eu\nbarsy.gr\nbarsy.in\nbarsy.info\nbarsy.io\nbarsy.me\nbarsy.menu\nbarsyonline.menu\nbarsy.mobi\nbarsy.net\nbarsy.online\nbarsy.org\nbarsy.pro\nbarsy.pub\nbarsy.ro\nbarsy.rs\nbarsy.shop\nbarsyonline.shop\nbarsy.site\nbarsy.store\nbarsy.support\nbarsy.uk\nbarsy.co.uk\nbarsyonline.co.uk\n*.lutrausercontent.com\nluyani.app\nluyani.net\n*.magentosite.cloud\nmagicpatterns.app\nmagicpatternsapp.com\nhb.cldmail.ru\nmatlab.cloud\nmodelscape.com\nmwcloudnonprod.com\npolyspace.com\nmayfirst.info\nmcdir.me\nmcdir.ru\nvps.mcdir.ru\nmcpre.ru\nmediatech.by\nmediatech.dev\nhra.health\nmedusajs.app\nminiserver.com\nmemset.net\nmesserli.app\natmeta.com\napps.fbsbx.com\n*.metaaiusercontent.com\n*.cloud.metacentrum.cz\ncustom.metacentrum.cz\nflt.cloud.muni.cz\nusr.cloud.muni.cz\nmeteorapp.com\neu.meteorapp.com\nco.pl\n*.azurecontainer.io\nazure-api.net\nazure-mobile.net\nazureedge.net\nazurefd.net\nazurestaticapps.net\n1.azurestaticapps.net\n2.azurestaticapps.net\n3.azurestaticapps.net\n4.azurestaticapps.net\n5.azurestaticapps.net\n6.azurestaticapps.net\n7.azurestaticapps.net\ncentralus.azurestaticapps.net\neastasia.azurestaticapps.net\neastus2.azurestaticapps.net\nwesteurope.azurestaticapps.net\nwestus2.azurestaticapps.net\nazurewebsites.net\naustraliacentral-01.azurewebsites.net\naustraliacentral2-01.azurewebsites.net\naustraliaeast-01.azurewebsites.net\naustraliasoutheast-01.azurewebsites.net\naustriaeast-01.azurewebsites.net\nbelgiumcentral-01.azurewebsites.net\nbrazilsouth-01.azurewebsites.net\nbrazilsoutheast-01.azurewebsites.net\ncanadacentral-01.azurewebsites.net\ncanadaeast-01.azurewebsites.net\ncentralindia-01.azurewebsites.net\ncentralus-01.azurewebsites.net\ncentraluseuap-01.azurewebsites.net\nchilecentral-01.azurewebsites.net\ndenmarkeast-01.azurewebsites.net\neastasia-01.azurewebsites.net\neastasiastage-01.azurewebsites.net\neastus-01.azurewebsites.net\neastus2-01.azurewebsites.net\neastus2euap-01.azurewebsites.net\neastus3-01.azurewebsites.net\nfrancecentral-01.azurewebsites.net\nfrancesouth-01.azurewebsites.net\ngermanynorth-01.azurewebsites.net\ngermanywestcentral-01.azurewebsites.net\nindiasouthcentral-01.azurewebsites.net\nindonesiacentral-01.azurewebsites.net\nisraelcentral-01.azurewebsites.net\nisraelnorthwest-01.azurewebsites.net\nitalynorth-01.azurewebsites.net\njapaneast-01.azurewebsites.net\njapanwest-01.azurewebsites.net\njioindiacentral-01.azurewebsites.net\njioindiawest-01.azurewebsites.net\nkoreacentral-01.azurewebsites.net\nkoreasouth-01.azurewebsites.net\nmalaysiawest-01.azurewebsites.net\nmexicocentral-01.azurewebsites.net\nnewzealandnorth-01.azurewebsites.net\nnorthcentralus-01.azurewebsites.net\nnorthcentralusstage-01.azurewebsites.net\nnortheastus5-01.azurewebsites.net\nnortheurope-01.azurewebsites.net\nnorwayeast-01.azurewebsites.net\nnorwaywest-01.azurewebsites.net\n*.p.azurewebsites.net\npolandcentral-01.azurewebsites.net\nqatarcentral-01.azurewebsites.net\nsouthafricanorth-01.azurewebsites.net\nsouthafricawest-01.azurewebsites.net\nsouthcentralus-01.azurewebsites.net\nsouthcentralus2-01.azurewebsites.net\nsoutheastasia-01.azurewebsites.net\nsoutheastus5-01.azurewebsites.net\nsouthindia-01.azurewebsites.net\nspaincentral-01.azurewebsites.net\nswedencentral-01.azurewebsites.net\nswedensouth-01.azurewebsites.net\nswitzerlandnorth-01.azurewebsites.net\nswitzerlandwest-01.azurewebsites.net\ntaiwannorth-01.azurewebsites.net\ntaiwannorthwest-01.azurewebsites.net\nuaecentral-01.azurewebsites.net\nuaenorth-01.azurewebsites.net\nuksouth-01.azurewebsites.net\nukwest-01.azurewebsites.net\nwestcentralus-01.azurewebsites.net\nwesteurope-01.azurewebsites.net\nwestindia-01.azurewebsites.net\nwestus-01.azurewebsites.net\nwestus2-01.azurewebsites.net\nwestus3-01.azurewebsites.net\ncloudapp.net\ntrafficmanager.net\nblob.core.usgovcloudapi.net\nfile.core.usgovcloudapi.net\nweb.core.usgovcloudapi.net\nservicebus.usgovcloudapi.net\nusgovcloudapp.net\nusgovtrafficmanager.net\nblob.core.windows.net\nfile.core.windows.net\nweb.core.windows.net\nservicebus.windows.net\nazure-api.us\nazurewebsites.us\nroutingthecloud.com\nsn.mynetname.net\nroutingthecloud.net\nroutingthecloud.org\nsame-app.com\nsame-preview.com\ncsx.cc\nmiren.app\nmiren.systems\nmydbserver.com\nwebspaceconfig.de\nmittwald.info\nmittwaldserver.info\ntypo3server.info\nproject.space\nmkm.fan\nmocha.app\nmochausercontent.com\nmocha-sandbox.dev\nmodx.dev\nbmoattachments.org\nnet.ru\norg.ru\npp.ru\nmy.be\nhostedpi.com\ncaracal.mythic-beasts.com\ncustomer.mythic-beasts.com\nfentiger.mythic-beasts.com\nlynx.mythic-beasts.com\nocelot.mythic-beasts.com\noncilla.mythic-beasts.com\nonza.mythic-beasts.com\nsphinx.mythic-beasts.com\nvs.mythic-beasts.com\nx.mythic-beasts.com\nyali.mythic-beasts.com\ncust.retrosnub.co.uk\nui.nabu.casa\nneedle.run\nco.site\ncloud.nospamproxy.com\no365.cloud.nospamproxy.com\nnetlib.re\nnetlify.app\n4u.com\nnfshost.com\nipfs.nftstorage.link\nngo.us\nngrok.app\nngrok-free.app\nngrok.dev\nngrok-free.dev\nngrok.io\nap.ngrok.io\nau.ngrok.io\neu.ngrok.io\nin.ngrok.io\njp.ngrok.io\nsa.ngrok.io\nus.ngrok.io\nngrok.pizza\nngrok.pro\ntorun.pl\nnh-serv.co.uk\nnimsite.uk\nmmafan.biz\nmyftp.biz\nno-ip.biz\nno-ip.ca\nfantasyleague.cc\ngotdns.ch\n3utilities.com\nblogsyte.com\nciscofreak.com\ndamnserver.com\nddnsking.com\nditchyourip.com\ndnsiskinky.com\ndynns.com\ngeekgalaxy.com\nhealth-carereform.com\nhomesecuritymac.com\nhomesecuritypc.com\nmyactivedirectory.com\nmysecuritycamera.com\nmyvnc.com\nnet-freaks.com\nonthewifi.com\npoint2this.com\nquicksytes.com\nsecuritytactics.com\nservebeer.com\nservecounterstrike.com\nserveexchange.com\nserveftp.com\nservegame.com\nservehalflife.com\nservehttp.com\nservehumour.com\nserveirc.com\nservemp3.com\nservep2p.com\nservepics.com\nservequake.com\nservesarcasm.com\nstufftoread.com\nunusualperson.com\nworkisboring.com\ndvrcam.info\nilovecollege.info\nno-ip.info\nbrasilia.me\nddns.me\ndnsfor.me\nhopto.me\nloginto.me\nnoip.me\nwebhop.me\nbounceme.net\nddns.net\neating-organic.net\nmydissent.net\nmyeffect.net\nmymediapc.net\nmypsx.net\nmysecuritycamera.net\nnhlfan.net\nno-ip.net\npgafan.net\nprivatizehealthinsurance.net\nredirectme.net\nserveblog.net\nserveminecraft.net\nsytes.net\ncable-modem.org\ncollegefan.org\ncouchpotatofries.org\nhopto.org\nmlbfan.org\nmyftp.org\nmysecuritycamera.org\nnflfan.org\nno-ip.org\nread-books.org\nufcfan.org\nzapto.org\nno-ip.co.uk\ngolffan.us\nnoip.us\npointto.us\nstage.nodeart.io\n*.developer.app\nnoop.app\n*.northflank.app\n*.build.run\n*.code.run\n*.database.run\n*.migration.run\naberdeen.wa.us\nbainbridge-isl.wa.us\nbellevue.wa.us\nbremerton.wa.us\ncentralia.wa.us\nchehalis.wa.us\nforks.wa.us\ngig-harbor.wa.us\nhoquiam.wa.us\nkeyport.wa.us\nkingston.wa.us\nolympia.wa.us\nport-angeles.wa.us\nport-ludlow.wa.us\nport-orchard.wa.us\nport-townsend.wa.us\npoulsbo.wa.us\nredmond.wa.us\nrenton.wa.us\nsea.wa.us\nseattle.wa.us\nsequim.wa.us\nshelton.wa.us\nsilverdale.wa.us\nyarrow-point.wa.us\nnoticeable.news\nnotion.site\ndnsking.ch\nmypi.co\nmyiphost.com\nforumz.info\nsoundcast.me\ntcp4.me\ndnsup.net\nhicam.net\nnow-dns.net\nownip.net\nvpndns.net\ndynserv.org\nnow-dns.org\nx443.pw\nntdll.top\nfreeddns.us\nnsupdate.info\nnerdpol.ovh\nprvcy.page\nobservablehq.cloud\nstatic.observableusercontent.com\nomg.lol\ncloudycluster.net\nomniwe.site\n123webseite.at\n123website.be\nsimplesite.com.br\n123website.ch\nsimplesite.com\n123webseite.de\n123hjemmeside.dk\n123miweb.es\n123kotisivu.fi\n123siteweb.fr\nsimplesite.gr\n123homepage.it\n123website.lu\n123website.nl\n123hjemmeside.no\nservice.one\nwebsite.one\nsimplesite.pl\n123paginaweb.pt\n123minsida.se\nonid.ca\nis-a-fullstack.dev\nis-cool.dev\nis-not-a.dev\nlocalplayer.dev\nis-local.org\nopensocial.site\n*.oaiusercontent.com\nchatgpt.site\nopencraft.hosting\n16-b.it\n32-b.it\n64-b.it\norsites.com\noperaunite.com\n*.customer-oci.com\n*.oci.customer-oci.com\n*.ocp.customer-oci.com\n*.ocs.customer-oci.com\n*.oraclecloudapps.com\n*.oraclegovcloudapps.com\n*.oraclegovcloudapps.uk\ntech.orange\ncan.re\nauthgear-staging.com\nauthgearapps.com\noutsystemscloud.com\n*.hosting.ovh.net\n*.webpaas.ovh.net\nownprovider.com\nown.pm\n*.owo.codes\nox.rs\noy.lc\npgfog.com\ngotpantheon.com\npantheonsite.io\n*.paywhirl.com\n*.xmit.co\nxmit.dev\nmadethis.site\nsrv.us\ngh.srv.us\ngl.srv.us\nmypep.link\npplx.app\nperspecta.cloud\nforgeblocks.com\nid.forgerock.io\nsupport.site\non-web.fr\n*.upsun.app\nupsunapp.com\nent.platform.sh\neu.platform.sh\nus.platform.sh\n*.platformsh.site\n*.tst.site\nplaycode.site\npley.games\nonporter.run\nco.bn\npostman-echo.com\npstmn.io\nmock.pstmn.io\nhttpbin.org\nprequalifyme.today\nxen.prgmr.com\npriv.at\nc01.kr\neliv-api.kr\neliv-cdn.kr\neliv-dns.kr\nmmv.kr\nvki.kr\ndev.project-study.com\nplatter-app.dev\ne.id\nchirurgiens-dentistes-en-france.fr\nbyen.site\nnyc.mn\n*.cn.st\npubtls.org\nputer.app\nputer.site\nputer.work\npythonanywhere.com\neu.pythonanywhere.com\nqa2.com\nqcx.io\n*.sys.qcx.io\nmyqnapcloud.cn\nalpha-myqnapcloud.com\ndev-myqnapcloud.com\nmycloudnas.com\nmynascloud.com\nmyqnapcloud.com\nqoto.io\nqualifioapp.com\nladesk.com\n*.qualyhqpartner.com\n*.qualyhqportal.com\nqbuser.com\n*.quipelements.com\nvapor.cloud\nvaporcloud.io\nrackmaze.com\nrackmaze.net\ncloudsite.builders\nmyradweb.net\nservername.us\nweb.in\nin.net\nmyrdbx.io\nsite.rb-hosting.io\nup.railway.app\n*.on-rancher.cloud\n*.on-k3s.io\n*.on-rio.io\nravpage.co.il\nreadthedocs-hosted.com\nreadthedocs.io\nrhcloud.com\ninstances.spawn.cc\n*.clusters.rdpa.co\n*.srvrless.rdpa.co\nonrender.com\napp.render.com\nreplit.app\nid.replit.app\nfirewalledreplit.co\nid.firewalledreplit.co\nrepl.co\nid.repl.co\nreplit.dev\narcher.replit.dev\nbones.replit.dev\ncanary.replit.dev\nglobal.replit.dev\nhacker.replit.dev\nid.replit.dev\njaneway.replit.dev\nkim.replit.dev\nkira.replit.dev\nkirk.replit.dev\nodo.replit.dev\nparis.replit.dev\npicard.replit.dev\npike.replit.dev\nprerelease.replit.dev\nreed.replit.dev\nriker.replit.dev\nsisko.replit.dev\nspock.replit.dev\nstaging.replit.dev\nsulu.replit.dev\ntarpit.replit.dev\nteams.replit.dev\ntucker.replit.dev\nwesley.replit.dev\nworf.replit.dev\nrepl.run\nresindevice.io\ndevices.resinstaging.io\nadimo.co.uk\nitcouldbewor.se\naus.basketball\nnz.basketball\nsubsc-pay.com\nsubsc-pay.net\ngit-pages.rit.edu\nrocketpreview.app\n*.builtwithrocket.new\nrocky.page\nrub.de\nruhr-uni-bochum.de\nio.noc.ruhr-uni-bochum.de\nxn--90amc.xn--p1acf\nxn--j1aef.xn--p1acf\nxn--j1ael8b.xn--p1acf\nxn--h1ahn.xn--p1acf\nxn--j1adp.xn--p1acf\nxn--c1avg.xn--p1acf\nxn--80aaa0cvac.xn--p1acf\nxn--h1aliz.xn--p1acf\nxn--90a1af.xn--p1acf\nxn--41a.xn--p1acf\nras.ru\nnyat.app\n180r.com\ndojin.com\nsakuratan.com\nsakuraweb.com\nx0.com\n2-d.jp\nbona.jp\ncrap.jp\ndaynight.jp\neek.jp\nflop.jp\nhalfmoon.jp\njeez.jp\nmatrix.jp\nmimoza.jp\nivory.ne.jp\nmail-box.ne.jp\nmints.ne.jp\nmokuren.ne.jp\nopal.ne.jp\nsakura.ne.jp\nsumomo.ne.jp\ntopaz.ne.jp\nnetgamers.jp\nnyanta.jp\no0o0.jp\nrdy.jp\nrgr.jp\nrulez.jp\ns3.isk01.sakurastorage.jp\ns3.isk02.sakurastorage.jp\nsaloon.jp\nsblo.jp\nskr.jp\ntank.jp\nuh-oh.jp\nundo.jp\nrs.webaccel.jp\nuser.webaccel.jp\nwebsozai.jp\nxii.jp\nsquares.net\njpn.org\nkirara.st\nx0.to\nfrom.tv\nsakura.tv\n*.builder.code.com\n*.dev-builder.code.com\n*.stg-builder.code.com\n*.001.test.code-builder-stg.platform.salesforce.com\n*.aa.crm.dev\n*.ab.crm.dev\n*.ac.crm.dev\n*.ad.crm.dev\n*.ae.crm.dev\n*.af.crm.dev\n*.ci.crm.dev\n*.d.crm.dev\n*.pa.crm.dev\n*.pb.crm.dev\n*.pc.crm.dev\n*.pd.crm.dev\n*.pe.crm.dev\n*.pf.crm.dev\n*.w.crm.dev\n*.wa.crm.dev\n*.wb.crm.dev\n*.wc.crm.dev\n*.wd.crm.dev\n*.we.crm.dev\n*.wf.crm.dev\nsandcats.io\nsav.case\nlogoip.com\nlogoip.de\nfr-par-1.baremetal.scw.cloud\nfr-par-2.baremetal.scw.cloud\nnl-ams-1.baremetal.scw.cloud\ncockpit.fr-par.scw.cloud\nddl.fr-par.scw.cloud\ndtwh.fr-par.scw.cloud\nfnc.fr-par.scw.cloud\nfunctions.fnc.fr-par.scw.cloud\nifr.fr-par.scw.cloud\nk8s.fr-par.scw.cloud\nnodes.k8s.fr-par.scw.cloud\nkafk.fr-par.scw.cloud\nmgdb.fr-par.scw.cloud\nrdb.fr-par.scw.cloud\ns3.fr-par.scw.cloud\ns3-website.fr-par.scw.cloud\nscbl.fr-par.scw.cloud\nwhm.fr-par.scw.cloud\npriv.instances.scw.cloud\npub.instances.scw.cloud\nk8s.scw.cloud\ncockpit.nl-ams.scw.cloud\nddl.nl-ams.scw.cloud\ndtwh.nl-ams.scw.cloud\nifr.nl-ams.scw.cloud\nk8s.nl-ams.scw.cloud\nnodes.k8s.nl-ams.scw.cloud\nkafk.nl-ams.scw.cloud\nmgdb.nl-ams.scw.cloud\nrdb.nl-ams.scw.cloud\ns3.nl-ams.scw.cloud\ns3-website.nl-ams.scw.cloud\nscbl.nl-ams.scw.cloud\nwhm.nl-ams.scw.cloud\ncockpit.pl-waw.scw.cloud\nddl.pl-waw.scw.cloud\ndtwh.pl-waw.scw.cloud\nifr.pl-waw.scw.cloud\nk8s.pl-waw.scw.cloud\nnodes.k8s.pl-waw.scw.cloud\nkafk.pl-waw.scw.cloud\nmgdb.pl-waw.scw.cloud\nrdb.pl-waw.scw.cloud\ns3.pl-waw.scw.cloud\ns3-website.pl-waw.scw.cloud\nscbl.pl-waw.scw.cloud\nscalebook.scw.cloud\nsmartlabeling.scw.cloud\ndedibox.fr\nscw.site\nams.scw.site\nwaw.scw.site\nschokokeks.net\ngov.scot\nservice.gov.scot\nmygov.scot\nscrysec.com\nclient.scrypted.io\nfirewall-gateway.com\nfirewall-gateway.de\nmy-gateway.de\nmy-router.de\nspdns.de\nspdns.eu\nfirewall-gateway.net\nmy-firewall.org\nmyfirewall.org\nspdns.org\nseidat.net\nsellfy.store\nminisite.ms\nsenseering.net\nservebolt.cloud\nbiz.ua\nco.ua\npp.ua\nas.sh.cn\nvicp.fun\nyicp.fun\nzicp.fun\nsheezy.games\nmyshopblocks.com\nmyshopify.com\nshopitsite.com\nshopware.shop\nshopware.store\nmo-siemens.io\n1kapp.com\nappchizi.com\napplinzi.com\nsinaapp.com\nvipsinaapp.com\nsiteleaf.net\nsmall-web.org\naeroport.fr\navocat.fr\nchambagri.fr\nchirurgiens-dentistes.fr\nexperts-comptables.fr\nmedecin.fr\nnotaires.fr\npharmacien.fr\nport.fr\nveterinaire.fr\nvp4.me\n*.snowflake.app\n*.privatelink.snowflake.app\nstreamlit.app\nstreamlitapp.com\ntry-snowplow.com\nmafelo.net\nsol.site\nplaystation-cloud.com\nsrht.site\napps.lair.io\n*.stolos.io\n4.at\nmy.at\nmy.de\n*.nxa.eu\nnx.gw\nspawnbase.app\ncustomer.speedpartner.de\nmyspreadshop.at\nmyspreadshop.com.au\nmyspreadshop.be\nmyspreadshop.ca\nmyspreadshop.ch\nmyspreadshop.com\nmyspreadshop.de\nmyspreadshop.dk\nmyspreadshop.es\nmyspreadshop.fi\nmyspreadshop.fr\nmyspreadshop.ie\nmyspreadshop.it\nmyspreadshop.net\nmyspreadshop.nl\nmyspreadshop.no\nmyspreadshop.pl\nmyspreadshop.se\nmyspreadshop.co.uk\nw-corp-staticblitz.com\nw-credentialless-staticblitz.com\nw-staticblitz.com\nbolt.host\nstackhero-network.com\nruns.onstackit.cloud\nstackit.gg\nstackit.rocks\nstackit.run\nstackit.zone\nsryze.cc\nindevs.in\nmusician.io\nnovecore.site\nstatichost.page\nfeedback.ac\nforms.ac\nassessments.cx\ncalculators.cx\nfunnels.cx\npaynow.cx\nquizzes.cx\nresearched.cx\ntests.cx\nsurveys.so\nipfs.storacha.link\nipfs.w3s.link\nstorebase.store\nstrapiapp.com\nmedia.strapiapp.com\nvps-host.net\natl.jelastic.vps-host.net\nnjs.jelastic.vps-host.net\nric.jelastic.vps-host.net\nstreak-link.com\nstreaklinks.com\nstreakusercontent.com\nsoc.srcf.net\nuser.srcf.net\nutwente.io\ntemp-dns.com\nsupabase.co\nrealtime.supabase.co\nstorage.supabase.co\nsupabase.in\nsupabase.net\nsyncloud.it\ndscloud.biz\ndirect.quickconnect.cn\ndsmynas.com\nfamilyds.com\ndiskstation.me\ndscloud.me\ni234.me\nmyds.me\nsynology.me\ndscloud.mobi\ndsmynas.net\nfamilyds.net\ndsmynas.org\nfamilyds.org\ndirect.quickconnect.to\nvpnplus.to\nmytabit.com\nmytabit.co.il\ntabitorder.co.il\ntaifun-dns.de\nerp.dev\nweb.erp.dev\nts.net\n*.c.ts.net\ngda.pl\ngdansk.pl\ngdynia.pl\nmed.pl\nsopot.pl\ntaveusercontent.com\np.tawk.email\np.tawkto.email\ntche.br\nsite.tb-hosting.com\ndirectwp.eu\nec.cc\neu.cc\ngu.cc\nuk.cc\nus.cc\nedugit.io\ns3.teckids.org\ntelebit.app\ntelebit.io\n*.telebit.xyz\nteleport.sh\n*.firenet.ch\n*.svc.firenet.ch\nreservd.com\nthingdustdata.com\ncust.dev.thingdust.io\nreservd.dev.thingdust.io\ncust.disrec.thingdust.io\nreservd.disrec.thingdust.io\ncust.prod.thingdust.io\ncust.testing.thingdust.io\nreservd.testing.thingdust.io\ntickets.io\nt3.storage.dev\nt3.storageapi.dev\narvo.network\nazimuth.network\ntlon.network\ntorproject.net\npages.torproject.net\ntownnews-staging.com\n12hp.at\n2ix.at\n4lima.at\nlima-city.at\n12hp.ch\n2ix.ch\n4lima.ch\nlima-city.ch\ntrafficplex.cloud\nde.cool\n12hp.de\n2ix.de\n4lima.de\nlima-city.de\n1337.pictures\nclan.rip\nlima-city.rocks\nwebspace.rocks\nlima.zone\n*.transurl.be\n*.transurl.eu\nsite.transip.me\n*.transurl.nl\n*.triton.zone\ntunnelmole.net\ntuxfamily.org\ntypedream.app\npro.typeform.com\nuber.space\nhk.com\ninc.hk\nltd.hk\nhk.org\nit.com\numso.co\nunison-services.cloud\nvirtual-user.de\nvirtualuser.de\nobj.ag\nname.pm\nsch.tf\nbiz.wf\nsch.wf\norg.yt\nrs.ba\nbielsko.pl\nurown.cloud\ndnsupdate.info\nus.org\nv.ua\nval.run\nweb.val.run\nvercel.app\nv0.build\nvercel.dev\nvusercontent.net\ntmp.now\nvercel.run\nnow.sh\n2038.io\nv-info.info\nvistablog.ir\ndeus-canvas.com\nvivenushop.com\nvivenushop.dev\nvoorloper.cloud\n*.vultrobjects.com\nwafflecell.com\nwal.app\nwasmer.app\nwebflow.io\nwebflowtest.io\n*.webhare.dev\nhotelwithflight.com\nreserve-online.net\nbook.online\ncprapid.com\npleskns.com\nwp2.host\npdns.page\nplesk.page\ncpanel.site\nwpsquared.site\n*.wadl.top\nremotewd.com\nbox.ca\npages.wiardweb.com\ntoolforge.org\nwmcloud.org\nbeta.wmcloud.org\nwmflabs.org\nhrsn.dev\nis-a.dev\nvps.hrsn.net\nlocalcert.net\nwindsurf.app\nwindsurf.build\ndrive-platform.com\ndrive-platform.io\npanel.gg\ndaemon.panel.gg\nbase44.app\nbase44-sandbox.com\nwixsite.com\nwixstudio.com\neditorx.io\nwixstudio.io\nwix.run\nmesswithdns.com\nwoltlab-demo.com\nmyforum.community\ncommunity-pro.de\ndiskussionsbereich.de\ncommunity-pro.net\nmeinforum.net\naffinitylottery.org.uk\nraffleentry.org.uk\nweeklylottery.org.uk\nwpenginepowered.com\njs.wpenginepowered.com\ngrok.me\n*.xenonconnect.de\nhalf.host\ncistron.nl\ndemon.nl\nxs4all.space\nxtooldevice.com\nyandexcloud.net\nstorage.yandexcloud.net\nwebsite.yandexcloud.net\nsourcecraft.site\nofficial.academy\nyolasite.com\nynh.fr\nnohost.me\nnoho.st\nza.net\nza.org\nzap.cloud\nzeabur.app\n*.zerops.app\nprg1-zerops.zone\n*.zerops.zone\nbss.design\nbasicserver.io\nvirtualserver.io\nenterprisecloud.nu\nzone.id\nnett.to\nzabc.net";
|
|
7222
7677
|
const HTTP_SCHEME = /^https?:/i;
|
|
7223
7678
|
let activeHost = null;
|
|
7224
7679
|
async function stopBrowserHost() {
|
|
@@ -7244,7 +7699,7 @@ async function startBrowserHost(options) {
|
|
|
7244
7699
|
},
|
|
7245
7700
|
log
|
|
7246
7701
|
});
|
|
7247
|
-
configurePslRules(
|
|
7702
|
+
configurePslRules(PSL_RULES);
|
|
7248
7703
|
const cdp = new CdpPool({ log });
|
|
7249
7704
|
const views = /* @__PURE__ */ new Map();
|
|
7250
7705
|
let stateWriter = null;
|
|
@@ -7270,9 +7725,14 @@ async function startBrowserHost(options) {
|
|
|
7270
7725
|
});
|
|
7271
7726
|
}
|
|
7272
7727
|
const ownership = new OwnershipLedger({
|
|
7728
|
+
mayAdopt: (token, requester) => {
|
|
7729
|
+
const record = registry.requireSurface(token);
|
|
7730
|
+
return record.handedTo === requester.slice("session:".length) && !record.allocationId;
|
|
7731
|
+
},
|
|
7273
7732
|
closeTab: async (token) => {
|
|
7274
7733
|
try {
|
|
7275
7734
|
const record = registry.requireSurface(token);
|
|
7735
|
+
approvals.forgetDocument(token);
|
|
7276
7736
|
registry.destroy(record.tabId);
|
|
7277
7737
|
} catch {
|
|
7278
7738
|
}
|
|
@@ -7415,14 +7875,22 @@ async function startBrowserHost(options) {
|
|
|
7415
7875
|
});
|
|
7416
7876
|
contents.on("did-navigate", (_event, url) => {
|
|
7417
7877
|
registry.bumpEpoch(tabId);
|
|
7878
|
+
stopLogCapture(contents.id);
|
|
7879
|
+
startLogCapture(contents.id);
|
|
7418
7880
|
log(`[browser] tab ${tabId} navigated to ${url}`);
|
|
7419
7881
|
});
|
|
7420
|
-
contents.on("did-navigate-in-page", (_event, url) => {
|
|
7421
|
-
|
|
7882
|
+
contents.on("did-navigate-in-page", (_event, url, isMainFrame) => {
|
|
7883
|
+
if (!isMainFrame) return;
|
|
7884
|
+
registry.bumpEpoch(tabId, false);
|
|
7422
7885
|
log(`[browser] tab ${tabId} navigated in page to ${url}`);
|
|
7423
7886
|
});
|
|
7424
7887
|
contents.on("destroyed", () => {
|
|
7425
|
-
|
|
7888
|
+
const record = registry.get(tabId);
|
|
7889
|
+
if (record) {
|
|
7890
|
+
const token = surfaceToken(record);
|
|
7891
|
+
if (token) approvals.forgetDocument(token);
|
|
7892
|
+
registry.forget(tabId);
|
|
7893
|
+
}
|
|
7426
7894
|
releaseTab(tabId, contents.id);
|
|
7427
7895
|
});
|
|
7428
7896
|
}
|
|
@@ -7438,18 +7906,6 @@ function releaseView(window, view) {
|
|
|
7438
7906
|
} catch {
|
|
7439
7907
|
}
|
|
7440
7908
|
}
|
|
7441
|
-
function readOptionalPslRules(userDataDir, log) {
|
|
7442
|
-
try {
|
|
7443
|
-
const path2 = path$1.join(userDataDir, "browser", "psl.txt");
|
|
7444
|
-
if (!fs.existsSync(path2)) return null;
|
|
7445
|
-
const rules2 = fs.readFileSync(path2, "utf8");
|
|
7446
|
-
log(`[browser] loaded public-suffix rules from ${path2}`);
|
|
7447
|
-
return rules2;
|
|
7448
|
-
} catch (error) {
|
|
7449
|
-
log(`[browser] could not load public-suffix rules: ${String(error)}`);
|
|
7450
|
-
return null;
|
|
7451
|
-
}
|
|
7452
|
-
}
|
|
7453
7909
|
const OPERATION_ID = /^[a-zA-Z0-9_-]{1,128}$/;
|
|
7454
7910
|
function guardForegroundReceipts(window, send2) {
|
|
7455
7911
|
return (input) => {
|
|
@@ -9098,8 +9554,8 @@ function readInstallIdentity(shimPath) {
|
|
|
9098
9554
|
}
|
|
9099
9555
|
let shebang = null;
|
|
9100
9556
|
try {
|
|
9101
|
-
const
|
|
9102
|
-
shebang =
|
|
9557
|
+
const firstLine2 = fs.readFileSync(shimPath, "utf8").split("\n", 1)[0] ?? "";
|
|
9558
|
+
shebang = firstLine2.startsWith("#!") ? firstLine2 : null;
|
|
9103
9559
|
} catch {
|
|
9104
9560
|
shebang = null;
|
|
9105
9561
|
}
|
|
@@ -10210,86 +10666,6 @@ ${heal.removed.join("\n")}`,
|
|
|
10210
10666
|
electron.ipcMain.removeHandler("quit-for-update-install");
|
|
10211
10667
|
this.mainWindow = null;
|
|
10212
10668
|
}
|
|
10213
|
-
/**
|
|
10214
|
-
* Register the backend service for proper shutdown when app quits
|
|
10215
|
-
* This ensures that restarted backend services are properly shut down
|
|
10216
|
-
*/
|
|
10217
|
-
registerBackendShutdown() {
|
|
10218
|
-
if (!this.backendService || this.backendService.isUsingExternalBackend()) {
|
|
10219
|
-
return;
|
|
10220
|
-
}
|
|
10221
|
-
const shutdownHandler = async () => {
|
|
10222
|
-
logger.info(
|
|
10223
|
-
"Shutting down backend service before app quit...",
|
|
10224
|
-
LogFileType.UPDATE_SERVICE
|
|
10225
|
-
);
|
|
10226
|
-
try {
|
|
10227
|
-
await this.backendService?.stop(false);
|
|
10228
|
-
logger.info(
|
|
10229
|
-
"Backend service successfully shut down before app quit",
|
|
10230
|
-
LogFileType.UPDATE_SERVICE
|
|
10231
|
-
);
|
|
10232
|
-
} catch (error) {
|
|
10233
|
-
logger.error(
|
|
10234
|
-
"Error shutting down backend service before app quit:",
|
|
10235
|
-
LogFileType.UPDATE_SERVICE,
|
|
10236
|
-
error
|
|
10237
|
-
);
|
|
10238
|
-
try {
|
|
10239
|
-
logger.info(
|
|
10240
|
-
"Attempting forced shutdown of backend service...",
|
|
10241
|
-
LogFileType.UPDATE_SERVICE
|
|
10242
|
-
);
|
|
10243
|
-
await this.forceTerminateBackendProcess();
|
|
10244
|
-
logger.info(
|
|
10245
|
-
"Forced shutdown of backend service completed",
|
|
10246
|
-
LogFileType.UPDATE_SERVICE
|
|
10247
|
-
);
|
|
10248
|
-
} catch (forceError) {
|
|
10249
|
-
logger.error(
|
|
10250
|
-
"Error during forced shutdown of backend service:",
|
|
10251
|
-
LogFileType.UPDATE_SERVICE,
|
|
10252
|
-
forceError
|
|
10253
|
-
);
|
|
10254
|
-
}
|
|
10255
|
-
}
|
|
10256
|
-
};
|
|
10257
|
-
electron.app.removeAllListeners("before-quit");
|
|
10258
|
-
electron.app.once("before-quit", shutdownHandler);
|
|
10259
|
-
electron.app.once("will-quit", shutdownHandler);
|
|
10260
|
-
logger.info(
|
|
10261
|
-
"Registered backend service for proper shutdown on app quit",
|
|
10262
|
-
LogFileType.UPDATE_SERVICE
|
|
10263
|
-
);
|
|
10264
|
-
}
|
|
10265
|
-
/**
|
|
10266
|
-
* Force terminate the backend process using platform-specific commands
|
|
10267
|
-
* This is a last resort method when normal termination fails
|
|
10268
|
-
*/
|
|
10269
|
-
async forceTerminateBackendProcess() {
|
|
10270
|
-
if (!this.backendService) {
|
|
10271
|
-
return;
|
|
10272
|
-
}
|
|
10273
|
-
const execAsync = node_util.promisify(node_child_process.exec);
|
|
10274
|
-
try {
|
|
10275
|
-
if (process.platform === "win32") {
|
|
10276
|
-
await execAsync('taskkill /f /im "local-operator serve" /t');
|
|
10277
|
-
await execAsync(
|
|
10278
|
-
`wmic process where "commandline like '%local-operator serve%'" call terminate`
|
|
10279
|
-
);
|
|
10280
|
-
} else {
|
|
10281
|
-
await execAsync('pkill -f "local-operator serve"');
|
|
10282
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
10283
|
-
await execAsync('pkill -9 -f "local-operator serve"');
|
|
10284
|
-
}
|
|
10285
|
-
} catch (error) {
|
|
10286
|
-
logger.warn(
|
|
10287
|
-
"Error during force termination (this may be normal if process was already terminated):",
|
|
10288
|
-
LogFileType.UPDATE_SERVICE,
|
|
10289
|
-
error
|
|
10290
|
-
);
|
|
10291
|
-
}
|
|
10292
|
-
}
|
|
10293
10669
|
/**
|
|
10294
10670
|
* Set up event handlers for the autoUpdater
|
|
10295
10671
|
*/
|
|
@@ -10537,6 +10913,15 @@ ${heal.removed.join("\n")}`,
|
|
|
10537
10913
|
let block = null;
|
|
10538
10914
|
try {
|
|
10539
10915
|
block = await this.runInstallPreflight(this.lastUpdateInfo);
|
|
10916
|
+
if (!block) await this.backendService?.stop(false);
|
|
10917
|
+
} catch (error) {
|
|
10918
|
+
this.updateStage = "idle";
|
|
10919
|
+
logger.error(
|
|
10920
|
+
"Update handoff refused: owned backend cleanup failed",
|
|
10921
|
+
LogFileType.UPDATE_SERVICE,
|
|
10922
|
+
error
|
|
10923
|
+
);
|
|
10924
|
+
return false;
|
|
10540
10925
|
} finally {
|
|
10541
10926
|
this.installPreflightInFlight = false;
|
|
10542
10927
|
}
|
|
@@ -11368,16 +11753,6 @@ ${pipRun.stderr.trim()}`,
|
|
|
11368
11753
|
"Restarting backend service after update...",
|
|
11369
11754
|
LogFileType.UPDATE_SERVICE
|
|
11370
11755
|
);
|
|
11371
|
-
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
11372
|
-
const isHealthy = await this.checkBackendHealth();
|
|
11373
|
-
if (isHealthy) {
|
|
11374
|
-
logger.warn(
|
|
11375
|
-
"Backend service is still running after stop command, attempting force termination",
|
|
11376
|
-
LogFileType.UPDATE_SERVICE
|
|
11377
|
-
);
|
|
11378
|
-
await this.forceTerminateBackendProcess();
|
|
11379
|
-
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
11380
|
-
}
|
|
11381
11756
|
const restartSuccess = await this.backendService.restart();
|
|
11382
11757
|
if (restartSuccess) {
|
|
11383
11758
|
logger.info(
|
|
@@ -11411,7 +11786,6 @@ ${pipRun.stderr.trim()}`,
|
|
|
11411
11786
|
return false;
|
|
11412
11787
|
}
|
|
11413
11788
|
}
|
|
11414
|
-
this.registerBackendShutdown();
|
|
11415
11789
|
} else {
|
|
11416
11790
|
logger.error(
|
|
11417
11791
|
"Failed to restart backend service after update",
|
|
@@ -11999,6 +12373,16 @@ function createWindow() {
|
|
|
11999
12373
|
}
|
|
12000
12374
|
const backendService = new BackendServiceManager();
|
|
12001
12375
|
const backendInstaller = new BackendInstaller();
|
|
12376
|
+
const reportBackendFailure = (message, fileType) => {
|
|
12377
|
+
if (backendService.isShuttingDown()) {
|
|
12378
|
+
logger.error(
|
|
12379
|
+
`Backend Error (not shown; the app is shutting down): ${message}`,
|
|
12380
|
+
fileType
|
|
12381
|
+
);
|
|
12382
|
+
return;
|
|
12383
|
+
}
|
|
12384
|
+
electron.dialog.showErrorBox("Backend Error", message);
|
|
12385
|
+
};
|
|
12002
12386
|
const windowLaunch = resolveWindowLaunchPlan({
|
|
12003
12387
|
env: process.env,
|
|
12004
12388
|
argv: process.argv
|
|
@@ -12363,9 +12747,9 @@ electron.app.whenReady().then(async () => {
|
|
|
12363
12747
|
"Failed to start backend after installation, quitting app",
|
|
12364
12748
|
LogFileType.INSTALLER
|
|
12365
12749
|
);
|
|
12366
|
-
|
|
12367
|
-
"
|
|
12368
|
-
|
|
12750
|
+
reportBackendFailure(
|
|
12751
|
+
"Failed to start the Local Operator backend service after installation. Please restart the application.",
|
|
12752
|
+
LogFileType.INSTALLER
|
|
12369
12753
|
);
|
|
12370
12754
|
electron.app.quit();
|
|
12371
12755
|
return;
|
|
@@ -12377,9 +12761,9 @@ electron.app.whenReady().then(async () => {
|
|
|
12377
12761
|
"Failed to start backend with existing installation, quitting app",
|
|
12378
12762
|
LogFileType.BACKEND
|
|
12379
12763
|
);
|
|
12380
|
-
|
|
12381
|
-
"
|
|
12382
|
-
|
|
12764
|
+
reportBackendFailure(
|
|
12765
|
+
"Failed to start the Local Operator backend service. Please restart the application.",
|
|
12766
|
+
LogFileType.BACKEND
|
|
12383
12767
|
);
|
|
12384
12768
|
electron.app.quit();
|
|
12385
12769
|
return;
|
|
@@ -12503,161 +12887,34 @@ electron.app.on("window-all-closed", () => {
|
|
|
12503
12887
|
);
|
|
12504
12888
|
electron.app.quit();
|
|
12505
12889
|
});
|
|
12506
|
-
|
|
12507
|
-
|
|
12508
|
-
|
|
12509
|
-
|
|
12510
|
-
|
|
12511
|
-
|
|
12512
|
-
|
|
12513
|
-
|
|
12514
|
-
|
|
12515
|
-
|
|
12516
|
-
|
|
12517
|
-
"Local Operator backend service successfully stopped",
|
|
12518
|
-
LogFileType.BACKEND
|
|
12519
|
-
);
|
|
12520
|
-
logger.info(
|
|
12521
|
-
"Performing additional cleanup to ensure complete termination",
|
|
12522
|
-
LogFileType.BACKEND
|
|
12523
|
-
);
|
|
12524
|
-
if (process.platform === "win32") {
|
|
12525
|
-
try {
|
|
12526
|
-
require("node:child_process").execSync(
|
|
12527
|
-
'taskkill /f /im python.exe /fi "WINDOWTITLE eq *local-operator*" /t',
|
|
12528
|
-
{ stdio: "ignore" }
|
|
12529
|
-
);
|
|
12530
|
-
require("node:child_process").execSync(
|
|
12531
|
-
"taskkill /f /im local-operator.exe /t",
|
|
12532
|
-
{ stdio: "ignore" }
|
|
12533
|
-
);
|
|
12534
|
-
} catch (err) {
|
|
12535
|
-
logger.error(
|
|
12536
|
-
"Error during Windows process cleanup (may be normal):",
|
|
12537
|
-
LogFileType.BACKEND,
|
|
12538
|
-
err
|
|
12539
|
-
);
|
|
12540
|
-
}
|
|
12541
|
-
} else {
|
|
12542
|
-
try {
|
|
12543
|
-
require("node:child_process").execSync(
|
|
12544
|
-
'pkill -f "local-operator serve"',
|
|
12545
|
-
{ stdio: "ignore" }
|
|
12546
|
-
);
|
|
12547
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
12548
|
-
require("node:child_process").execSync(
|
|
12549
|
-
'pkill -9 -f "local-operator serve"',
|
|
12550
|
-
{ stdio: "ignore" }
|
|
12551
|
-
);
|
|
12552
|
-
} catch (err) {
|
|
12553
|
-
logger.error(
|
|
12554
|
-
"Error during Unix process cleanup (may be normal):",
|
|
12555
|
-
LogFileType.BACKEND,
|
|
12556
|
-
err
|
|
12557
|
-
);
|
|
12558
|
-
}
|
|
12559
|
-
}
|
|
12560
|
-
let allProcessesTerminated = true;
|
|
12561
|
-
try {
|
|
12562
|
-
if (process.platform === "win32") {
|
|
12563
|
-
const { stdout: pythonOutput } = require("node:child_process").execSync(
|
|
12564
|
-
`tasklist /fi "imagename eq python.exe" /fo csv`,
|
|
12565
|
-
{ encoding: "utf8" }
|
|
12566
|
-
);
|
|
12567
|
-
const hasPythonProcesses = pythonOutput?.trim().includes("python.exe");
|
|
12568
|
-
const { stdout: localOperatorOutput } = require("node:child_process").execSync(
|
|
12569
|
-
`tasklist /fi "imagename eq local-operator.exe" /fo csv`,
|
|
12570
|
-
{ encoding: "utf8" }
|
|
12571
|
-
);
|
|
12572
|
-
const hasLocalOperatorProcesses = localOperatorOutput?.trim().includes("local-operator.exe");
|
|
12573
|
-
allProcessesTerminated = !hasPythonProcesses && !hasLocalOperatorProcesses;
|
|
12574
|
-
} else {
|
|
12575
|
-
const { stdout } = require("node:child_process").execSync(
|
|
12576
|
-
`pgrep -f "local-operator serve" || echo ""`,
|
|
12577
|
-
{ encoding: "utf8" }
|
|
12578
|
-
);
|
|
12579
|
-
allProcessesTerminated = !stdout?.trim();
|
|
12580
|
-
}
|
|
12581
|
-
} catch (err) {
|
|
12582
|
-
logger.error(
|
|
12583
|
-
"Error checking for remaining processes:",
|
|
12584
|
-
LogFileType.BACKEND,
|
|
12585
|
-
err
|
|
12586
|
-
);
|
|
12587
|
-
allProcessesTerminated = true;
|
|
12588
|
-
}
|
|
12589
|
-
if (!allProcessesTerminated) {
|
|
12590
|
-
logger.error(
|
|
12591
|
-
"Some backend processes may still be running, attempting final cleanup",
|
|
12592
|
-
LogFileType.BACKEND
|
|
12593
|
-
);
|
|
12594
|
-
try {
|
|
12595
|
-
if (process.platform === "win32") {
|
|
12596
|
-
require("node:child_process").execSync(
|
|
12597
|
-
"taskkill /f /im python.exe /t",
|
|
12598
|
-
{ stdio: "ignore" }
|
|
12599
|
-
);
|
|
12600
|
-
} else {
|
|
12601
|
-
require("node:child_process").execSync("pkill -9 -f python", {
|
|
12602
|
-
stdio: "ignore"
|
|
12603
|
-
});
|
|
12604
|
-
}
|
|
12605
|
-
} catch (finalErr) {
|
|
12606
|
-
logger.error(
|
|
12607
|
-
"Error during final cleanup (may be normal):",
|
|
12608
|
-
LogFileType.BACKEND,
|
|
12609
|
-
finalErr
|
|
12610
|
-
);
|
|
12611
|
-
}
|
|
12612
|
-
}
|
|
12613
|
-
} catch (error) {
|
|
12614
|
-
logger.error(
|
|
12615
|
-
"Error stopping the Local Operator backend service:",
|
|
12616
|
-
LogFileType.BACKEND,
|
|
12617
|
-
error
|
|
12618
|
-
);
|
|
12619
|
-
logger.info(
|
|
12620
|
-
"Trying alternative termination approach",
|
|
12621
|
-
LogFileType.BACKEND
|
|
12622
|
-
);
|
|
12623
|
-
if (process.platform === "win32") {
|
|
12624
|
-
try {
|
|
12625
|
-
require("node:child_process").execSync(
|
|
12626
|
-
'taskkill /f /im python.exe /fi "WINDOWTITLE eq *local-operator*" /t',
|
|
12627
|
-
{ stdio: "ignore" }
|
|
12628
|
-
);
|
|
12629
|
-
require("node:child_process").execSync(
|
|
12630
|
-
"taskkill /f /im local-operator.exe /t",
|
|
12631
|
-
{ stdio: "ignore" }
|
|
12632
|
-
);
|
|
12633
|
-
} catch (_err) {
|
|
12634
|
-
}
|
|
12635
|
-
} else {
|
|
12636
|
-
try {
|
|
12637
|
-
require("node:child_process").execSync(
|
|
12638
|
-
'pkill -f "local-operator serve"',
|
|
12639
|
-
{ stdio: "ignore" }
|
|
12640
|
-
);
|
|
12641
|
-
require("node:child_process").execSync(
|
|
12642
|
-
'sleep 1 && pkill -9 -f "local-operator serve"',
|
|
12643
|
-
{ stdio: "ignore" }
|
|
12644
|
-
);
|
|
12645
|
-
} catch (_err) {
|
|
12646
|
-
}
|
|
12647
|
-
}
|
|
12648
|
-
} finally {
|
|
12649
|
-
logger.info("Exiting application...", LogFileType.BACKEND);
|
|
12650
|
-
setTimeout(() => {
|
|
12651
|
-
logger.info("Forcing app exit", LogFileType.BACKEND);
|
|
12652
|
-
electron.app.exit(0);
|
|
12653
|
-
}, 2e3);
|
|
12654
|
-
}
|
|
12655
|
-
} else if (!isBackendManagerDisabled && backendService.isUsingExternalBackend()) {
|
|
12656
|
-
logger.info(
|
|
12657
|
-
"Using external backend, skipping termination on app quit",
|
|
12890
|
+
const QUIT_FAILSAFE_MARGIN_MS = 5e3;
|
|
12891
|
+
const QUIT_CLEANUP_FAILSAFE_MS = CONSOLE_RESOLUTION_WORST_MS + INTERPRETER_RESOLUTION_WORST_MS + OWNED_STOP_WORST_MS + READINESS_POLL_INTERVAL_MS + QUIT_FAILSAFE_MARGIN_MS;
|
|
12892
|
+
let backendQuitPending = false;
|
|
12893
|
+
electron.app.on("will-quit", (event) => {
|
|
12894
|
+
if (backendService.isOwnedCleanupComplete()) return;
|
|
12895
|
+
event.preventDefault();
|
|
12896
|
+
if (backendQuitPending) return;
|
|
12897
|
+
backendQuitPending = true;
|
|
12898
|
+
const failsafe = setTimeout(() => {
|
|
12899
|
+
logger.error(
|
|
12900
|
+
`Owned backend cleanup did not finish within ${QUIT_CLEANUP_FAILSAFE_MS} ms; exiting with failure`,
|
|
12658
12901
|
LogFileType.BACKEND
|
|
12659
12902
|
);
|
|
12660
|
-
|
|
12903
|
+
electron.app.exit(1);
|
|
12904
|
+
}, QUIT_CLEANUP_FAILSAFE_MS);
|
|
12905
|
+
failsafe.unref();
|
|
12906
|
+
void backendService.stop(false).then(() => {
|
|
12907
|
+
clearTimeout(failsafe);
|
|
12908
|
+
electron.app.quit();
|
|
12909
|
+
}).catch((error) => {
|
|
12910
|
+
clearTimeout(failsafe);
|
|
12911
|
+
logger.error(
|
|
12912
|
+
"Owned backend cleanup failed; exiting with failure",
|
|
12913
|
+
LogFileType.BACKEND,
|
|
12914
|
+
error
|
|
12915
|
+
);
|
|
12916
|
+
electron.app.exit(1);
|
|
12917
|
+
});
|
|
12661
12918
|
});
|
|
12662
12919
|
electron.app.on("before-quit", () => {
|
|
12663
12920
|
logger.info("App is about to quit", LogFileType.BACKEND);
|
|
@@ -12666,114 +12923,24 @@ electron.app.on("before-quit", () => {
|
|
|
12666
12923
|
void stopBrowserHost();
|
|
12667
12924
|
});
|
|
12668
12925
|
process.on("exit", () => {
|
|
12669
|
-
logger.info(
|
|
12670
|
-
"Process exit event detected, ensuring the Local Operator backend service is terminated",
|
|
12671
|
-
LogFileType.BACKEND
|
|
12672
|
-
);
|
|
12673
12926
|
try {
|
|
12674
|
-
|
|
12675
|
-
logger.info(
|
|
12676
|
-
"Forcing termination of the Local Operator backend service",
|
|
12677
|
-
LogFileType.BACKEND
|
|
12678
|
-
);
|
|
12679
|
-
logger.info(
|
|
12680
|
-
"Performing final cleanup of any remaining backend processes",
|
|
12681
|
-
LogFileType.BACKEND
|
|
12682
|
-
);
|
|
12683
|
-
if (process.platform === "win32") {
|
|
12684
|
-
try {
|
|
12685
|
-
require("node:child_process").spawnSync("cmd.exe", [
|
|
12686
|
-
"/c",
|
|
12687
|
-
'taskkill /f /im python.exe /fi "WINDOWTITLE eq *local-operator*" /t'
|
|
12688
|
-
]);
|
|
12689
|
-
require("node:child_process").spawnSync("cmd.exe", [
|
|
12690
|
-
"/c",
|
|
12691
|
-
"taskkill /f /im local-operator.exe /t"
|
|
12692
|
-
]);
|
|
12693
|
-
} catch (_err) {
|
|
12694
|
-
}
|
|
12695
|
-
} else {
|
|
12696
|
-
try {
|
|
12697
|
-
require("node:child_process").spawnSync("bash", [
|
|
12698
|
-
"-c",
|
|
12699
|
-
`ps aux | grep "local-operator serve" | grep -v grep | awk '{print $2}' | xargs -r kill -15`
|
|
12700
|
-
]);
|
|
12701
|
-
require("node:child_process").spawnSync("bash", [
|
|
12702
|
-
"-c",
|
|
12703
|
-
`sleep 1 && ps aux | grep "local-operator serve" | grep -v grep | awk '{print $2}' | xargs -r kill -9`
|
|
12704
|
-
]);
|
|
12705
|
-
} catch (_err) {
|
|
12706
|
-
}
|
|
12707
|
-
}
|
|
12708
|
-
} else if (!process.env.VITE_DISABLE_BACKEND_MANAGER && backendService.isUsingExternalBackend()) {
|
|
12709
|
-
logger.info(
|
|
12710
|
-
"Using external backend, skipping force termination",
|
|
12711
|
-
LogFileType.BACKEND
|
|
12712
|
-
);
|
|
12713
|
-
}
|
|
12927
|
+
backendService.emergencyStopOwned();
|
|
12714
12928
|
} catch (error) {
|
|
12715
|
-
logger.error(
|
|
12929
|
+
logger.error(
|
|
12930
|
+
"Owned backend emergency cleanup failed",
|
|
12931
|
+
LogFileType.BACKEND,
|
|
12932
|
+
error
|
|
12933
|
+
);
|
|
12716
12934
|
}
|
|
12717
12935
|
posthogClient.shutdown();
|
|
12718
12936
|
});
|
|
12719
12937
|
process.on("uncaughtException", (error) => {
|
|
12720
12938
|
logger.error("Uncaught exception", LogFileType.BACKEND, error);
|
|
12721
|
-
|
|
12722
|
-
logger.
|
|
12723
|
-
"
|
|
12724
|
-
LogFileType.BACKEND
|
|
12725
|
-
|
|
12726
|
-
backendService.stop().catch((stopError) => {
|
|
12727
|
-
logger.error(
|
|
12728
|
-
"Error stopping the Local Operator backend service:",
|
|
12729
|
-
LogFileType.BACKEND,
|
|
12730
|
-
stopError
|
|
12731
|
-
);
|
|
12732
|
-
logger.info(
|
|
12733
|
-
"Trying alternative termination approach",
|
|
12734
|
-
LogFileType.BACKEND
|
|
12735
|
-
);
|
|
12736
|
-
if (process.platform === "win32") {
|
|
12737
|
-
try {
|
|
12738
|
-
require("node:child_process").spawnSync("cmd.exe", [
|
|
12739
|
-
"/c",
|
|
12740
|
-
'taskkill /f /im python.exe /fi "WINDOWTITLE eq *local-operator*" /t'
|
|
12741
|
-
]);
|
|
12742
|
-
require("node:child_process").spawnSync("cmd.exe", [
|
|
12743
|
-
"/c",
|
|
12744
|
-
"taskkill /f /im local-operator.exe /t"
|
|
12745
|
-
]);
|
|
12746
|
-
} catch (_err) {
|
|
12747
|
-
}
|
|
12748
|
-
} else {
|
|
12749
|
-
try {
|
|
12750
|
-
require("node:child_process").spawnSync("bash", [
|
|
12751
|
-
"-c",
|
|
12752
|
-
`ps aux | grep "local-operator serve" | grep -v grep | awk '{print $2}' | xargs -r kill -15`
|
|
12753
|
-
]);
|
|
12754
|
-
require("node:child_process").spawnSync("bash", [
|
|
12755
|
-
"-c",
|
|
12756
|
-
`sleep 1 && ps aux | grep "local-operator serve" | grep -v grep | awk '{print $2}' | xargs -r kill -9`
|
|
12757
|
-
]);
|
|
12758
|
-
} catch (_err) {
|
|
12759
|
-
}
|
|
12760
|
-
}
|
|
12761
|
-
}).finally(() => {
|
|
12762
|
-
setTimeout(() => {
|
|
12763
|
-
logger.info(
|
|
12764
|
-
"Forcing app exit after uncaught exception",
|
|
12765
|
-
LogFileType.BACKEND
|
|
12766
|
-
);
|
|
12767
|
-
process.exit(1);
|
|
12768
|
-
}, 1e3);
|
|
12769
|
-
});
|
|
12770
|
-
} else if (backendService && !process.env.VITE_DISABLE_BACKEND_MANAGER && backendService.isUsingExternalBackend()) {
|
|
12771
|
-
logger.info(
|
|
12772
|
-
"Using external backend, skipping termination on uncaught exception",
|
|
12773
|
-
LogFileType.BACKEND
|
|
12939
|
+
void backendService.stop(false).catch((stopError) => {
|
|
12940
|
+
logger.error(
|
|
12941
|
+
"Owned backend cleanup failed",
|
|
12942
|
+
LogFileType.BACKEND,
|
|
12943
|
+
stopError
|
|
12774
12944
|
);
|
|
12775
|
-
|
|
12776
|
-
} else {
|
|
12777
|
-
process.exit(1);
|
|
12778
|
-
}
|
|
12945
|
+
}).finally(() => process.exit(1));
|
|
12779
12946
|
});
|