@electron-memory/monitor 0.2.1 → 0.2.3
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/dist/index.js +91 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +92 -13
- package/dist/index.mjs.map +1 -1
- package/dist/ui/index.html +3 -3
- package/package.json +70 -70
package/dist/index.mjs
CHANGED
|
@@ -1073,9 +1073,10 @@ import { BrowserWindow as BrowserWindow2 } from "electron";
|
|
|
1073
1073
|
import * as path3 from "path";
|
|
1074
1074
|
|
|
1075
1075
|
// src/core/dashboard-protocol.ts
|
|
1076
|
-
import { app as app2, protocol } from "electron";
|
|
1076
|
+
import { app as app2, net, protocol } from "electron";
|
|
1077
1077
|
import { readFile } from "fs/promises";
|
|
1078
1078
|
import * as path2 from "path";
|
|
1079
|
+
import { pathToFileURL } from "url";
|
|
1079
1080
|
var SCHEME = "emm-dashboard";
|
|
1080
1081
|
var privilegedRegistered = false;
|
|
1081
1082
|
var handlerRegistered = false;
|
|
@@ -1104,8 +1105,60 @@ function isPathInsideRoot(filePath, root) {
|
|
|
1104
1105
|
if (f === r) {
|
|
1105
1106
|
return true;
|
|
1106
1107
|
}
|
|
1107
|
-
const
|
|
1108
|
-
|
|
1108
|
+
const rel = path2.relative(r, f);
|
|
1109
|
+
if (!rel || rel.startsWith("..") || path2.isAbsolute(rel)) {
|
|
1110
|
+
return false;
|
|
1111
|
+
}
|
|
1112
|
+
return true;
|
|
1113
|
+
}
|
|
1114
|
+
function urlToUiRelativePath(requestUrl) {
|
|
1115
|
+
let u;
|
|
1116
|
+
try {
|
|
1117
|
+
u = new URL(requestUrl);
|
|
1118
|
+
} catch {
|
|
1119
|
+
return "";
|
|
1120
|
+
}
|
|
1121
|
+
let p = "";
|
|
1122
|
+
try {
|
|
1123
|
+
p = decodeURIComponent(u.pathname || "");
|
|
1124
|
+
} catch {
|
|
1125
|
+
p = u.pathname || "";
|
|
1126
|
+
}
|
|
1127
|
+
p = p.replace(/^\/+/, "");
|
|
1128
|
+
const host = (u.hostname || "").toLowerCase();
|
|
1129
|
+
if (p.includes("..")) {
|
|
1130
|
+
return "";
|
|
1131
|
+
}
|
|
1132
|
+
if (host === "electron" || host === "") {
|
|
1133
|
+
return p || "index.html";
|
|
1134
|
+
}
|
|
1135
|
+
if (p) {
|
|
1136
|
+
return `${host}/${p}`.replace(/\\/g, "/");
|
|
1137
|
+
}
|
|
1138
|
+
if (host.includes(".")) {
|
|
1139
|
+
return host;
|
|
1140
|
+
}
|
|
1141
|
+
return "index.html";
|
|
1142
|
+
}
|
|
1143
|
+
function bufferToResponseBody(buf) {
|
|
1144
|
+
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
1145
|
+
}
|
|
1146
|
+
function looksLikeHtml(buf) {
|
|
1147
|
+
let i = 0;
|
|
1148
|
+
if (buf.length >= 3 && buf[0] === 239 && buf[1] === 187 && buf[2] === 191) {
|
|
1149
|
+
i = 3;
|
|
1150
|
+
}
|
|
1151
|
+
while (i < buf.length && (buf[i] === 32 || buf[i] === 9 || buf[i] === 10 || buf[i] === 13)) {
|
|
1152
|
+
i += 1;
|
|
1153
|
+
}
|
|
1154
|
+
return i < buf.length && buf[i] === 60;
|
|
1155
|
+
}
|
|
1156
|
+
function corsHeaders() {
|
|
1157
|
+
return {
|
|
1158
|
+
"Access-Control-Allow-Origin": "*",
|
|
1159
|
+
"Access-Control-Allow-Methods": "GET, OPTIONS",
|
|
1160
|
+
"Access-Control-Allow-Headers": "*"
|
|
1161
|
+
};
|
|
1109
1162
|
}
|
|
1110
1163
|
function registerDashboardSchemePrivileged() {
|
|
1111
1164
|
if (privilegedRegistered) {
|
|
@@ -1137,29 +1190,55 @@ function ensureDashboardProtocolHandler(uiRoot) {
|
|
|
1137
1190
|
handlerRegistered = true;
|
|
1138
1191
|
const base = path2.resolve(uiRoot);
|
|
1139
1192
|
protocol.handle(SCHEME, async (request) => {
|
|
1193
|
+
if (request.method === "OPTIONS") {
|
|
1194
|
+
return new Response(null, { status: 204, headers: corsHeaders() });
|
|
1195
|
+
}
|
|
1140
1196
|
try {
|
|
1141
|
-
const
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
rel = "index.html";
|
|
1197
|
+
const rel = urlToUiRelativePath(request.url);
|
|
1198
|
+
if (!rel || rel.includes("..")) {
|
|
1199
|
+
return new Response("Bad path", { status: 400, headers: corsHeaders() });
|
|
1145
1200
|
}
|
|
1146
|
-
const filePath = path2.resolve(path2.join(base, rel));
|
|
1201
|
+
const filePath = path2.resolve(path2.join(base, ...rel.split("/")));
|
|
1147
1202
|
if (!isPathInsideRoot(filePath, base)) {
|
|
1148
|
-
return new Response("Forbidden", { status: 403 });
|
|
1203
|
+
return new Response("Forbidden", { status: 403, headers: corsHeaders() });
|
|
1204
|
+
}
|
|
1205
|
+
const fileUrl = pathToFileURL(filePath).href;
|
|
1206
|
+
let upstream;
|
|
1207
|
+
try {
|
|
1208
|
+
upstream = await net.fetch(fileUrl);
|
|
1209
|
+
} catch {
|
|
1210
|
+
upstream = new Response(null, { status: 599 });
|
|
1211
|
+
}
|
|
1212
|
+
let buf;
|
|
1213
|
+
if (!upstream.ok) {
|
|
1214
|
+
buf = await readFile(filePath);
|
|
1215
|
+
} else {
|
|
1216
|
+
const ab = await upstream.arrayBuffer();
|
|
1217
|
+
buf = Buffer.from(ab);
|
|
1149
1218
|
}
|
|
1150
|
-
const body = await readFile(filePath);
|
|
1151
1219
|
const ext = path2.extname(filePath).toLowerCase();
|
|
1220
|
+
if (ext === ".html" && !looksLikeHtml(buf)) {
|
|
1221
|
+
console.error(
|
|
1222
|
+
"[@electron-memory/monitor] emm-dashboard: not HTML at",
|
|
1223
|
+
filePath,
|
|
1224
|
+
"url=",
|
|
1225
|
+
request.url
|
|
1226
|
+
);
|
|
1227
|
+
return new Response("Invalid dashboard HTML", { status: 500, headers: corsHeaders() });
|
|
1228
|
+
}
|
|
1152
1229
|
const mime = MIME_BY_EXT[ext] || "application/octet-stream";
|
|
1153
|
-
return new Response(
|
|
1230
|
+
return new Response(bufferToResponseBody(buf), {
|
|
1154
1231
|
status: 200,
|
|
1155
1232
|
headers: {
|
|
1156
1233
|
"Content-Type": mime,
|
|
1157
|
-
"Cache-Control": "no-store"
|
|
1234
|
+
"Cache-Control": "no-store",
|
|
1235
|
+
...corsHeaders()
|
|
1158
1236
|
}
|
|
1159
1237
|
});
|
|
1160
1238
|
} catch (err) {
|
|
1161
1239
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1162
|
-
|
|
1240
|
+
console.error("[@electron-memory/monitor] emm-dashboard:", request.url, err);
|
|
1241
|
+
return new Response(msg, { status: 404, headers: corsHeaders() });
|
|
1163
1242
|
}
|
|
1164
1243
|
});
|
|
1165
1244
|
}
|