@electron-memory/monitor 0.2.2 → 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 +72 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +73 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1114,6 +1114,7 @@ var path3 = __toESM(require("path"));
|
|
|
1114
1114
|
var import_electron2 = require("electron");
|
|
1115
1115
|
var import_promises = require("fs/promises");
|
|
1116
1116
|
var path2 = __toESM(require("path"));
|
|
1117
|
+
var import_node_url = require("url");
|
|
1117
1118
|
var SCHEME = "emm-dashboard";
|
|
1118
1119
|
var privilegedRegistered = false;
|
|
1119
1120
|
var handlerRegistered = false;
|
|
@@ -1148,6 +1149,48 @@ function isPathInsideRoot(filePath, root) {
|
|
|
1148
1149
|
}
|
|
1149
1150
|
return true;
|
|
1150
1151
|
}
|
|
1152
|
+
function urlToUiRelativePath(requestUrl) {
|
|
1153
|
+
let u;
|
|
1154
|
+
try {
|
|
1155
|
+
u = new URL(requestUrl);
|
|
1156
|
+
} catch {
|
|
1157
|
+
return "";
|
|
1158
|
+
}
|
|
1159
|
+
let p = "";
|
|
1160
|
+
try {
|
|
1161
|
+
p = decodeURIComponent(u.pathname || "");
|
|
1162
|
+
} catch {
|
|
1163
|
+
p = u.pathname || "";
|
|
1164
|
+
}
|
|
1165
|
+
p = p.replace(/^\/+/, "");
|
|
1166
|
+
const host = (u.hostname || "").toLowerCase();
|
|
1167
|
+
if (p.includes("..")) {
|
|
1168
|
+
return "";
|
|
1169
|
+
}
|
|
1170
|
+
if (host === "electron" || host === "") {
|
|
1171
|
+
return p || "index.html";
|
|
1172
|
+
}
|
|
1173
|
+
if (p) {
|
|
1174
|
+
return `${host}/${p}`.replace(/\\/g, "/");
|
|
1175
|
+
}
|
|
1176
|
+
if (host.includes(".")) {
|
|
1177
|
+
return host;
|
|
1178
|
+
}
|
|
1179
|
+
return "index.html";
|
|
1180
|
+
}
|
|
1181
|
+
function bufferToResponseBody(buf) {
|
|
1182
|
+
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
1183
|
+
}
|
|
1184
|
+
function looksLikeHtml(buf) {
|
|
1185
|
+
let i = 0;
|
|
1186
|
+
if (buf.length >= 3 && buf[0] === 239 && buf[1] === 187 && buf[2] === 191) {
|
|
1187
|
+
i = 3;
|
|
1188
|
+
}
|
|
1189
|
+
while (i < buf.length && (buf[i] === 32 || buf[i] === 9 || buf[i] === 10 || buf[i] === 13)) {
|
|
1190
|
+
i += 1;
|
|
1191
|
+
}
|
|
1192
|
+
return i < buf.length && buf[i] === 60;
|
|
1193
|
+
}
|
|
1151
1194
|
function corsHeaders() {
|
|
1152
1195
|
return {
|
|
1153
1196
|
"Access-Control-Allow-Origin": "*",
|
|
@@ -1189,24 +1232,40 @@ function ensureDashboardProtocolHandler(uiRoot) {
|
|
|
1189
1232
|
return new Response(null, { status: 204, headers: corsHeaders() });
|
|
1190
1233
|
}
|
|
1191
1234
|
try {
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
} catch {
|
|
1196
|
-
return new Response("Bad URL", { status: 400, headers: corsHeaders() });
|
|
1235
|
+
const rel = urlToUiRelativePath(request.url);
|
|
1236
|
+
if (!rel || rel.includes("..")) {
|
|
1237
|
+
return new Response("Bad path", { status: 400, headers: corsHeaders() });
|
|
1197
1238
|
}
|
|
1198
|
-
|
|
1199
|
-
if (!rel) {
|
|
1200
|
-
rel = "index.html";
|
|
1201
|
-
}
|
|
1202
|
-
const filePath = path2.resolve(path2.join(base, rel));
|
|
1239
|
+
const filePath = path2.resolve(path2.join(base, ...rel.split("/")));
|
|
1203
1240
|
if (!isPathInsideRoot(filePath, base)) {
|
|
1204
1241
|
return new Response("Forbidden", { status: 403, headers: corsHeaders() });
|
|
1205
1242
|
}
|
|
1206
|
-
const
|
|
1243
|
+
const fileUrl = (0, import_node_url.pathToFileURL)(filePath).href;
|
|
1244
|
+
let upstream;
|
|
1245
|
+
try {
|
|
1246
|
+
upstream = await import_electron2.net.fetch(fileUrl);
|
|
1247
|
+
} catch {
|
|
1248
|
+
upstream = new Response(null, { status: 599 });
|
|
1249
|
+
}
|
|
1250
|
+
let buf;
|
|
1251
|
+
if (!upstream.ok) {
|
|
1252
|
+
buf = await (0, import_promises.readFile)(filePath);
|
|
1253
|
+
} else {
|
|
1254
|
+
const ab = await upstream.arrayBuffer();
|
|
1255
|
+
buf = Buffer.from(ab);
|
|
1256
|
+
}
|
|
1207
1257
|
const ext = path2.extname(filePath).toLowerCase();
|
|
1258
|
+
if (ext === ".html" && !looksLikeHtml(buf)) {
|
|
1259
|
+
console.error(
|
|
1260
|
+
"[@electron-memory/monitor] emm-dashboard: not HTML at",
|
|
1261
|
+
filePath,
|
|
1262
|
+
"url=",
|
|
1263
|
+
request.url
|
|
1264
|
+
);
|
|
1265
|
+
return new Response("Invalid dashboard HTML", { status: 500, headers: corsHeaders() });
|
|
1266
|
+
}
|
|
1208
1267
|
const mime = MIME_BY_EXT[ext] || "application/octet-stream";
|
|
1209
|
-
return new Response(
|
|
1268
|
+
return new Response(bufferToResponseBody(buf), {
|
|
1210
1269
|
status: 200,
|
|
1211
1270
|
headers: {
|
|
1212
1271
|
"Content-Type": mime,
|
|
@@ -1216,6 +1275,7 @@ function ensureDashboardProtocolHandler(uiRoot) {
|
|
|
1216
1275
|
});
|
|
1217
1276
|
} catch (err) {
|
|
1218
1277
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1278
|
+
console.error("[@electron-memory/monitor] emm-dashboard:", request.url, err);
|
|
1219
1279
|
return new Response(msg, { status: 404, headers: corsHeaders() });
|
|
1220
1280
|
}
|
|
1221
1281
|
});
|