hfs 3.2.0-rc7 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/assets/{af-ChNqX4hQ.js → af-BcngPxum.js} +1 -1
- package/admin/assets/{am-BjFtueiH.js → am-DtFo7gXc.js} +1 -1
- package/admin/assets/{ar-D-43QXnv.js → ar-B_EQ0gOA.js} +1 -1
- package/admin/assets/{ar-dz-C8VVHyNZ.js → ar-dz-C7XYleW9.js} +1 -1
- package/admin/assets/{ar-iq-CKmgtu1N.js → ar-iq-BfQJc2dx.js} +1 -1
- package/admin/assets/{ar-kw-ClkacMxD.js → ar-kw-0U1JfQOh.js} +1 -1
- package/admin/assets/{ar-ly-aLe8xUWv.js → ar-ly-zXio0U_R.js} +1 -1
- package/admin/assets/{ar-ma-Cmy_9gim.js → ar-ma-RnCHj7rY.js} +1 -1
- package/admin/assets/{ar-sa-QkSOWVHV.js → ar-sa-CMO7zpcn.js} +1 -1
- package/admin/assets/{ar-tn-DRqs1RVC.js → ar-tn-BKftC1Mu.js} +1 -1
- package/admin/assets/{az-CheoE9qy.js → az-AiZRgUb5.js} +1 -1
- package/admin/assets/{be-DYX-A0EV.js → be-y6bzPWFN.js} +1 -1
- package/admin/assets/{bg-DulQmCnv.js → bg-BisLARft.js} +1 -1
- package/admin/assets/{bi-sXSY6Z-Y.js → bi-48sz9hUu.js} +1 -1
- package/admin/assets/{bm-DZH2Z1aA.js → bm-Bs6BVzFS.js} +1 -1
- package/admin/assets/{bn-Bt7DRG1U.js → bn-CyEiX_eK.js} +1 -1
- package/admin/assets/{bn-bd-DjnJjDbD.js → bn-bd-_Q2I_DOn.js} +1 -1
- package/admin/assets/{bo-DxZ6w_m-.js → bo-Ue1q-9BD.js} +1 -1
- package/admin/assets/{br-nx-cDa8u.js → br-Bb9l-ihS.js} +1 -1
- package/admin/assets/{bs-DPpnb77H.js → bs-BPmB5n9t.js} +1 -1
- package/admin/assets/{ca-DX4yoBal.js → ca-B_r4lj3j.js} +1 -1
- package/admin/assets/{cs-9WHoqMlY.js → cs-CyhhYDkg.js} +1 -1
- package/admin/assets/{cv-0eJI5pfF.js → cv-ulbhiGq8.js} +1 -1
- package/admin/assets/{cy-CA7_BoTT.js → cy-C3WqFe_5.js} +1 -1
- package/admin/assets/{da-D665uDBy.js → da-DZLHh8Xm.js} +1 -1
- package/admin/assets/{de-at--PMhXgqq.js → de-at-CCxj6Bp4.js} +1 -1
- package/admin/assets/{de-ch-D4RpimnV.js → de-ch-CM8icK9J.js} +1 -1
- package/admin/assets/{de-BdinBjB5.js → de-clnjk21u.js} +1 -1
- package/admin/assets/{dist-DuN_bSFE.js → dist-Cvm-5z2_.js} +1 -1
- package/admin/assets/{dv-CXsTNQun.js → dv-X1dg-Sap.js} +1 -1
- package/admin/assets/{el-Dl09YDqZ.js → el-Df4pHDZ3.js} +1 -1
- package/admin/assets/{en-au-_I-HW2KA.js → en-au-Ct_0mddK.js} +1 -1
- package/admin/assets/{en-ca-D_VojBrX.js → en-ca-CQqkpac1.js} +1 -1
- package/admin/assets/{en-in-IJiykx5a.js → en-gb-BL2mYabO.js} +1 -1
- package/admin/assets/{en-ie-CC236qsJ.js → en-ie-CFOYG_Tt.js} +1 -1
- package/admin/assets/{en-il-B-u-HwaM.js → en-il-DgoPI8Zb.js} +1 -1
- package/admin/assets/{en-tt-BHGzBxdn.js → en-in-DVbA81wM.js} +1 -1
- package/admin/assets/{en-nz-DwJKQp8B.js → en-nz-D4INWdbm.js} +1 -1
- package/admin/assets/{en-CBSdvf96.js → en-rCfYK-2n.js} +1 -1
- package/admin/assets/{en-sg-DoIn_GVI.js → en-sg-_a9wehQB.js} +1 -1
- package/admin/assets/{en-gb-CPvoJu-O.js → en-tt-BAyEMcr3.js} +1 -1
- package/admin/assets/{eo-1cIWQbm1.js → eo-CMQMiEUh.js} +1 -1
- package/admin/assets/{es-DqhiELfd.js → es-B7YOeh-c.js} +1 -1
- package/admin/assets/{es-do-DuMx3SkF.js → es-do-Mq8WNgVk.js} +1 -1
- package/admin/assets/{es-mx-HO31d1Y6.js → es-mx-B_RMTunI.js} +1 -1
- package/admin/assets/{es-pr-mJJdhxuA.js → es-pr-uqTuZpUr.js} +1 -1
- package/admin/assets/{es-us-BBkaLkVh.js → es-us-D598JSxH.js} +1 -1
- package/admin/assets/{esm-DDoh4r_E.js → esm-C8k0V7Wx.js} +1 -1
- package/admin/assets/{et-CwiZ3ooQ.js → et-B6n19kok.js} +1 -1
- package/admin/assets/{eu-DdN35uBq.js → eu-CNx2Jk1_.js} +1 -1
- package/admin/assets/{fa-Bv4nYsAf.js → fa-DGIot4qi.js} +1 -1
- package/admin/assets/{fi-c2OfDzeC.js → fi-DaJl-Yrn.js} +1 -1
- package/admin/assets/{fo-C62mMzt2.js → fo-DgxLc8Be.js} +1 -1
- package/admin/assets/{fr-D0bFR-U7.js → fr-DoSFLSk1.js} +1 -1
- package/admin/assets/{fr-ca-DfK_ohBt.js → fr-ca-XcVXSZm2.js} +1 -1
- package/admin/assets/{fr-ch-B55WjN5s.js → fr-ch-CY_qBJu6.js} +1 -1
- package/admin/assets/{fy-RTCxb-xz.js → fy-CwP6pdZi.js} +1 -1
- package/admin/assets/{ga-D3YPWmA9.js → ga-BtKmIiqR.js} +1 -1
- package/admin/assets/{gd-DGy1L0Ce.js → gd-BdHmijxR.js} +1 -1
- package/admin/assets/{gl-BnbDJ-cD.js → gl-C5lGSMcI.js} +1 -1
- package/admin/assets/{gom-latn-DaoXVqRf.js → gom-latn-DLun_Cyc.js} +1 -1
- package/admin/assets/{gu-D4exbB_g.js → gu-BBxROGEb.js} +1 -1
- package/admin/assets/{he-BJkMJuxS.js → he-DseTadyh.js} +1 -1
- package/admin/assets/{hi-NiKhlWJ4.js → hi-DM8DF6aA.js} +1 -1
- package/admin/assets/{hr-DCGm41fv.js → hr-Dcrr0w28.js} +1 -1
- package/admin/assets/{ht-9PxpBdcR.js → ht-B6ek9t1g.js} +1 -1
- package/admin/assets/{hu-DcAh8Q1o.js → hu-TGqjozNS.js} +1 -1
- package/admin/assets/{hy-am-CzkEComP.js → hy-am-D5nMz6Yy.js} +1 -1
- package/admin/assets/{id-BjmYaT4V.js → id-B9LrfD64.js} +1 -1
- package/admin/assets/index-BGZpazPR.css +1 -0
- package/admin/assets/{index-it4YES4N.js → index-CMfN0pC5.js} +8 -8
- package/admin/assets/{is-DJobXFZO.js → is-CHPxwKd7.js} +1 -1
- package/admin/assets/{it-D011VfLu.js → it-D1Dtu0nW.js} +1 -1
- package/admin/assets/{it-ch-CSqhnZAP.js → it-ch-C1zLR1pY.js} +1 -1
- package/admin/assets/{ja-XLoEifLy.js → ja-DNNRQqi9.js} +1 -1
- package/admin/assets/{jv-OeWvfXO2.js → jv-ByMRyHLP.js} +1 -1
- package/admin/assets/{ka-vxfsZHIu.js → ka-BaIaZhNb.js} +1 -1
- package/admin/assets/{kk-DgQLaj-M.js → kk-CdG5pC8o.js} +1 -1
- package/admin/assets/{km-BBTAUfZA.js → km-CQGImLMP.js} +1 -1
- package/admin/assets/{kn-C3MvNcEn.js → kn-i6v2JbuU.js} +1 -1
- package/admin/assets/{ko-DwIbgyA4.js → ko-B7ZMJY_D.js} +1 -1
- package/admin/assets/{ku-Do__Mt_N.js → ku-Du7Lj5Ai.js} +1 -1
- package/admin/assets/{ky-ChrqV98h.js → ky-BFcjDu3n.js} +1 -1
- package/admin/assets/{lb-BUYOdep8.js → lb-kUg2Mh9U.js} +1 -1
- package/admin/assets/{lo-BJglNG-5.js → lo-CP6L0V2h.js} +1 -1
- package/admin/assets/{lt-BO4SMpW1.js → lt-BIgC7Saa.js} +1 -1
- package/admin/assets/{lv-UBaju8El.js → lv-BOs7b0pg.js} +1 -1
- package/admin/assets/{me-Dhp2pN-l.js → me-DYHaVe93.js} +1 -1
- package/admin/assets/{mi-7RIOsaf-.js → mi-Drez7lLe.js} +1 -1
- package/admin/assets/{mk-B68Lk_2S.js → mk-BK-ldTLL.js} +1 -1
- package/admin/assets/{ml-BuVY-qhR.js → ml-DaF3pZLU.js} +1 -1
- package/admin/assets/{mn-yZhW1Fad.js → mn-nHbNPFAG.js} +1 -1
- package/admin/assets/{mr-BKsd0V-1.js → mr-Wwf63eZM.js} +1 -1
- package/admin/assets/{ms-Bo82cPWt.js → ms-BIXjE3b0.js} +1 -1
- package/admin/assets/{ms-my-GD3KkYVL.js → ms-my-CMG5GLpT.js} +1 -1
- package/admin/assets/{mt-C4AkYVMX.js → mt-SRQPZ5le.js} +1 -1
- package/admin/assets/{my-D4enXJiP.js → my-DQYSisI9.js} +1 -1
- package/admin/assets/{nb-CwWYDxQD.js → nb-BU06Sx9X.js} +1 -1
- package/admin/assets/{ne-oEPn-U_p.js → ne-BMChpdeq.js} +1 -1
- package/admin/assets/{nl-D4eVW0Ta.js → nl-CXWGdKg5.js} +1 -1
- package/admin/assets/{nl-be-BSE-tctP.js → nl-be-fI6vO9FU.js} +1 -1
- package/admin/assets/{nn-COYOhXYj.js → nn-CkojFw3N.js} +1 -1
- package/admin/assets/{oc-lnc-QfWotTsB.js → oc-lnc-BKfjK0lp.js} +1 -1
- package/admin/assets/{pa-in-Cv2-1w3m.js → pa-in-BT8DvsfB.js} +1 -1
- package/admin/assets/{pl-Cx5VGDkU.js → pl-D0Cpx-wE.js} +1 -1
- package/admin/assets/{pt-BFcMT_HF.js → pt-DD7k0D3o.js} +1 -1
- package/admin/assets/{pt-br-CVLlsO9j.js → pt-br-DPY09O20.js} +1 -1
- package/admin/assets/{rn-QdNijJlB.js → rn-DWaRj8UF.js} +1 -1
- package/admin/assets/{ro-BUbWPmG0.js → ro-X4IcZOVs.js} +1 -1
- package/admin/assets/{ru-BgF0tPG6.js → ru-DqdQ6YYP.js} +1 -1
- package/admin/assets/{rw-BopM7qvB.js → rw-q8Mu5eAK.js} +1 -1
- package/admin/assets/{sd-WUO1O-J_.js → sd-WzFJ-b9p.js} +1 -1
- package/admin/assets/{se-BfYWrejk.js → se-B0Nt39h7.js} +1 -1
- package/admin/assets/{sha512-rx5ALN8t.js → sha512-ChZ-ZgQF.js} +1 -1
- package/admin/assets/{si-DHmSYwAw.js → si-D7WSpsGm.js} +1 -1
- package/admin/assets/{sk-CsKf3OOS.js → sk-wIcTcNYq.js} +1 -1
- package/admin/assets/{sl-Oa9PyN_G.js → sl-k_cEMlZY.js} +1 -1
- package/admin/assets/{sq-BH1h9voV.js → sq-D145xgL0.js} +1 -1
- package/admin/assets/{sr-cyrl-CHV9rE5o.js → sr-cyrl-CEGYotNk.js} +1 -1
- package/admin/assets/{sr-F6A1nFQl.js → sr-hqDfAF1G.js} +1 -1
- package/admin/assets/{ss-BgnifXyo.js → ss-DnoCncEs.js} +1 -1
- package/admin/assets/{sv-DLJrR7ks.js → sv-DB81pVMk.js} +1 -1
- package/admin/assets/{sv-fi-DYAUC7Oh.js → sv-fi-DYpZcfvJ.js} +1 -1
- package/admin/assets/{sw-ugKcNvo_.js → sw-DjXd57gN.js} +1 -1
- package/admin/assets/{ta-MmY2jlJ5.js → ta-C3wYK0Z3.js} +1 -1
- package/admin/assets/{te-UXUUgSgi.js → te-BD4lPDF4.js} +1 -1
- package/admin/assets/{tet-_IC6psQY.js → tet-BDurv1U8.js} +1 -1
- package/admin/assets/{tg-Ch7_zd9k.js → tg-Bm80AbZW.js} +1 -1
- package/admin/assets/{th-BtS533XI.js → th-DflYkQDK.js} +1 -1
- package/admin/assets/{tk-DEI_Lsn_.js → tk-rvsm_JbC.js} +1 -1
- package/admin/assets/{tl-ph-DOYss52w.js → tl-ph-Bwc5zmby.js} +1 -1
- package/admin/assets/{tlh-B51tXaQv.js → tlh-HKfEoZ7k.js} +1 -1
- package/admin/assets/{tr-CeXmTdxI.js → tr-VizeBtG6.js} +1 -1
- package/admin/assets/{tzl-BZ9_HPjT.js → tzl-BwO5wCIa.js} +1 -1
- package/admin/assets/{tzm-iNKjQcg0.js → tzm-BG7lewWS.js} +1 -1
- package/admin/assets/{tzm-latn-f7Pea1t0.js → tzm-latn-CrnUHIcs.js} +1 -1
- package/admin/assets/{ug-cn-By4p8svK.js → ug-cn-BK--SUxc.js} +1 -1
- package/admin/assets/{uk-Byeqw2Wr.js → uk-AJsAkG20.js} +1 -1
- package/admin/assets/{ur-B7IjRPc0.js → ur-vO2PrLFV.js} +1 -1
- package/admin/assets/{uz-C-W3XxRf.js → uz-CU8j0C84.js} +1 -1
- package/admin/assets/{uz-latn-BIQ4pRgP.js → uz-latn-B1U_SldD.js} +1 -1
- package/admin/assets/{vi-DLqQk35n.js → vi-Br-FE8zw.js} +1 -1
- package/admin/assets/{x-pseudo-CDaSWh6b.js → x-pseudo-BEc6ucZj.js} +1 -1
- package/admin/assets/{yo-Cv-olgqy.js → yo-DL2G7So6.js} +1 -1
- package/admin/assets/{zh-SiBGR2oS.js → zh-DNL75MTZ.js} +1 -1
- package/admin/assets/{zh-cn-D9CP5PQQ.js → zh-cn-BBd_VD1y.js} +1 -1
- package/admin/assets/{zh-hk-DWLC0iAa.js → zh-hk-CNn_dGjQ.js} +1 -1
- package/admin/assets/{zh-tw-BrsFXhOk.js → zh-tw-B7cjw6lq.js} +1 -1
- package/admin/index.html +2 -2
- package/frontend/assets/{dist-legacy-BaWYNjA6.js → dist-legacy-CFPnugjA.js} +1 -1
- package/frontend/assets/index-legacy-CCOgiwQJ.js +1 -0
- package/frontend/assets/{lib-legacy-DKUc98Ib.js → lib-legacy-CCULxbTk.js} +1 -1
- package/frontend/assets/{sha512-legacy-Drx4F1hz.js → sha512-legacy-D8zcvvqa.js} +1 -1
- package/frontend/index.html +1 -1
- package/npm-shrinkwrap.json +35 -35
- package/package.json +1 -1
- package/src/comments.js +1 -1
- package/src/frontEndApis.js +26 -29
- package/src/index.js +1 -0
- package/src/plugins.js +1 -1
- package/src/serveFile.js +10 -10
- package/src/serveGuiAndSharedFiles.js +1 -1
- package/src/serveGuiFiles.js +31 -10
- package/src/upload.js +1 -1
- package/src/util-files.js +20 -12
- package/src/webdav.js +1 -4
- package/admin/assets/index-CdJ2GK-i.css +0 -1
- package/frontend/assets/index-legacy-DKhdXq5m.js +0 -1
package/src/serveGuiFiles.js
CHANGED
|
@@ -12,6 +12,7 @@ const plugins_1 = require("./plugins");
|
|
|
12
12
|
const api_auth_1 = require("./api.auth");
|
|
13
13
|
const apiMiddleware_1 = require("./apiMiddleware");
|
|
14
14
|
const path_1 = require("path");
|
|
15
|
+
const promises_1 = require("fs/promises");
|
|
15
16
|
const misc_1 = require("./misc");
|
|
16
17
|
const adminApis_1 = require("./adminApis");
|
|
17
18
|
const customHtml_1 = require("./customHtml");
|
|
@@ -27,6 +28,9 @@ exports.logGui = (0, config_1.defineConfig)(misc_1.CFG.log_gui, false);
|
|
|
27
28
|
lodash_1.default.each(misc_1.FRONTEND_OPTIONS, (v, k) => (0, config_1.defineConfig)(k, v)); // define default values
|
|
28
29
|
function serveStatic(uri) {
|
|
29
30
|
const folder = (const_1.DEV ? 'dist/' : '') + uri.slice(2, -1);
|
|
31
|
+
const root = (0, path_1.join)(__dirname, '..', folder);
|
|
32
|
+
prewarmGuiAssets(root) // keep pkg snapshot files in memory before the reported runtime access loss can happen
|
|
33
|
+
.catch(e => console.error(`GUI asset prewarm failed: ${e?.code || e}`));
|
|
30
34
|
return async (ctx) => {
|
|
31
35
|
if (!exports.logGui.get())
|
|
32
36
|
ctx.state.dontLog = true;
|
|
@@ -38,20 +42,37 @@ function serveStatic(uri) {
|
|
|
38
42
|
if (ctx.method !== 'GET')
|
|
39
43
|
return ctx.status = const_1.HTTP_METHOD_NOT_ALLOWED;
|
|
40
44
|
const serveApp = shouldServeApp(ctx);
|
|
41
|
-
const fullPath = (0, path_1.join)(
|
|
42
|
-
const
|
|
45
|
+
const fullPath = (0, path_1.join)(root, serveApp ? '/index.html' : ctx.path);
|
|
46
|
+
const cached = await parseGuiFile(fullPath)
|
|
43
47
|
.catch(e => {
|
|
44
|
-
if (e?.code
|
|
48
|
+
if (!/^(?:ENOENT|EISDIR)$/.test(e?.code)) // not supposed to happen, and yet a user reported a strange behavior
|
|
45
49
|
console.error(`serveStatic/parseFile: ${String(e)}`);
|
|
46
50
|
return null;
|
|
47
51
|
});
|
|
48
|
-
if (
|
|
52
|
+
if (cached === null)
|
|
49
53
|
return ctx.status = const_1.HTTP_NOT_FOUND;
|
|
50
|
-
if (!serveApp)
|
|
51
|
-
|
|
54
|
+
if (!serveApp) {
|
|
55
|
+
const c = cached.content;
|
|
56
|
+
return (0, serveFile_1.serveFile)(ctx, fullPath, const_1.MIME_AUTO, { ...cached, content: !c.length ? c : adjustBundlerLinks(ctx, uri, c) });
|
|
57
|
+
}
|
|
52
58
|
// we don't cache the index as it's small and may prevent plugins change to apply
|
|
53
|
-
ctx.body = await treatIndex(ctx, uri, String(content));
|
|
59
|
+
ctx.body = await treatIndex(ctx, uri, String(cached.content));
|
|
54
60
|
};
|
|
61
|
+
async function prewarmGuiAssets(dir) {
|
|
62
|
+
for (const entry of await (0, promises_1.readdir)(dir, { withFileTypes: true })) {
|
|
63
|
+
const fullPath = (0, path_1.join)(dir, entry.name);
|
|
64
|
+
if (entry.isDirectory()) {
|
|
65
|
+
await prewarmGuiAssets(fullPath);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (!entry.isFile())
|
|
69
|
+
continue;
|
|
70
|
+
await parseGuiFile(fullPath);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function parseGuiFile(fullPath) {
|
|
74
|
+
return (0, misc_1.parseFile)(fullPath, x => x, const_1.DEV ? 1000 : Infinity); // cache raw bytes so reverse-proxy URL rewriting can still use the current request context
|
|
75
|
+
}
|
|
55
76
|
}
|
|
56
77
|
function shouldServeApp(ctx) {
|
|
57
78
|
return ctx.state.serveApp ||= ctx.path.endsWith('/') && !ctx.headers.upgrade; // skip websockets
|
|
@@ -61,7 +82,7 @@ function adjustBundlerLinks(ctx, uri, data) {
|
|
|
61
82
|
const filesUri = ctx.state.revProxyPath + uri;
|
|
62
83
|
return ext && !ext.match(/\.(css|html|js|ts|scss)/) ? data
|
|
63
84
|
: String(data).replace(/((?:import[ (]| from )['"])\//g, `$1${filesUri}`)
|
|
64
|
-
.replace(/(
|
|
85
|
+
.replace(/(=function\(([\w$]+)\)\{return)[`'"]\/[`'"]\+\2\}/g, `$1${JSON.stringify(filesUri)}+$2}`); // vite's preload helper uses the configured absolute base for dynamic dependency hints
|
|
65
86
|
}
|
|
66
87
|
const getFaviconTimestamp = (0, misc_1.debounceAsync)(async () => {
|
|
67
88
|
const f = adminApis_1.favicon.get();
|
|
@@ -174,12 +195,12 @@ function serveProxied(port, uri) {
|
|
|
174
195
|
proxy = lib.default('127.0.0.1:' + port, {
|
|
175
196
|
parseReqBody: false, // the dev GUI proxy serves app/assets, so avoid koa-better-http-proxy trying to reread ctx.req
|
|
176
197
|
proxyReqPathResolver: (ctx) => shouldServeApp(ctx) ? '/' : ctx.path,
|
|
177
|
-
userResDecorator(
|
|
198
|
+
userResDecorator(_res, data, ctx) {
|
|
178
199
|
return shouldServeApp(ctx) ? treatIndex(ctx, uri, String(data))
|
|
179
200
|
: adjustBundlerLinks(ctx, uri, data);
|
|
180
201
|
}
|
|
181
202
|
}));
|
|
182
|
-
return function (ctx,
|
|
203
|
+
return function (ctx, _next) {
|
|
183
204
|
if (!exports.logGui.get())
|
|
184
205
|
ctx.state.dontLog = true;
|
|
185
206
|
return proxy(ctx, async () => { });
|
package/src/upload.js
CHANGED
|
@@ -197,7 +197,7 @@ function uploadWriter(base, baseUri, filename, ctx) {
|
|
|
197
197
|
if (mtime) // so we use it to touch the file
|
|
198
198
|
await (0, promises_1.utimes)(dest, Date.now() / 1000, mtime / 1000);
|
|
199
199
|
cancelDeletion(tempName); // not necessary, as deletion's failure is silent, but still
|
|
200
|
-
ctx.state.uploadDestinationPath = dest;
|
|
200
|
+
obj.fullPath = ctx.state.uploadDestinationPath = dest;
|
|
201
201
|
void setUploadMeta(dest, ctx);
|
|
202
202
|
if (ctx.query.comment)
|
|
203
203
|
void (0, comments_1.setCommentFor)(dest, String(ctx.query.comment));
|
package/src/util-files.js
CHANGED
|
@@ -17,6 +17,7 @@ exports.ensureParentFolder = ensureParentFolder;
|
|
|
17
17
|
exports.createFileWithPath = createFileWithPath;
|
|
18
18
|
exports.createSafeWriteStream = createSafeWriteStream;
|
|
19
19
|
exports.isValidFileName = isValidFileName;
|
|
20
|
+
exports.isValidWindowsFileName = isValidWindowsFileName;
|
|
20
21
|
exports.exists = exists;
|
|
21
22
|
exports.loadFileCached = loadFileCached;
|
|
22
23
|
exports.parseFile = parseFile;
|
|
@@ -110,6 +111,8 @@ async function unzip(stream, cb) {
|
|
|
110
111
|
.on('error', reject)
|
|
111
112
|
.on('entry', (entry) => chain = chain.then(async () => {
|
|
112
113
|
const { path, type } = entry;
|
|
114
|
+
if (hasDirTraversal(path))
|
|
115
|
+
return entry.autodrain().promise();
|
|
113
116
|
const dest = await (0, cross_1.try_)(() => cb(path), e => console.warn(String(e)));
|
|
114
117
|
if (!dest || type !== 'File')
|
|
115
118
|
return entry.autodrain().promise();
|
|
@@ -174,31 +177,36 @@ async function createSafeWriteStream(path, options) {
|
|
|
174
177
|
});
|
|
175
178
|
}
|
|
176
179
|
function isValidFileName(name, acceptUnreadable = false) {
|
|
177
|
-
return name && name !== '.' && !(const_1.IS_WINDOWS ?
|
|
180
|
+
return name && name !== '.' && !(const_1.IS_WINDOWS ? !isValidWindowsFileName(name) : /\//.test(name)) && !hasDirTraversal(name)
|
|
178
181
|
&& (acceptUnreadable || !/[\u0000-\u001F\u007F]/.test(name));
|
|
179
182
|
}
|
|
183
|
+
function isValidWindowsFileName(name) {
|
|
184
|
+
return !/[/:"*?<>|\\]/.test(name)
|
|
185
|
+
&& !/[. ]$/.test(name)
|
|
186
|
+
// windows treats these legacy DOS device names as device paths even when an extension is present
|
|
187
|
+
&& !/^(?:con|prn|aux|nul|conin\$|conout\$|com[1-9\u00b9\u00b2\u00b3]|lpt[1-9\u00b9\u00b2\u00b3])(?:\..*)?$/i.test(name);
|
|
188
|
+
}
|
|
180
189
|
function exists(path) {
|
|
181
190
|
return (0, promises_1.access)(path).then(() => true, () => false);
|
|
182
191
|
}
|
|
183
|
-
// parse a file, caching unless timestamp has changed
|
|
184
192
|
exports.parseFileCache = new Map();
|
|
185
193
|
async function loadFileCached(path, loader, minInterval = 0) {
|
|
186
194
|
const cached = exports.parseFileCache.get(path);
|
|
187
195
|
const now = Date.now();
|
|
188
196
|
if (cached && now - cached.lastCheck < minInterval)
|
|
189
|
-
return cached.
|
|
190
|
-
const
|
|
191
|
-
if (e?.message
|
|
192
|
-
|
|
193
|
-
|
|
197
|
+
return { stats: cached.stats, content: await cached.content };
|
|
198
|
+
const stats = await statWithTimeout(path).catch(e => {
|
|
199
|
+
if (e?.message === 'timeout' && cached)
|
|
200
|
+
return cached.stats; // on timeout (e.g. thread pool saturated), serve cache if any
|
|
201
|
+
throw e;
|
|
194
202
|
});
|
|
195
203
|
if (cached)
|
|
196
204
|
cached.lastCheck = now;
|
|
197
|
-
if (cached && Number(
|
|
198
|
-
return cached.
|
|
199
|
-
const
|
|
200
|
-
exports.parseFileCache.set(path, {
|
|
201
|
-
return
|
|
205
|
+
if (cached && Number(stats.mtime) === Number(cached.stats.mtime))
|
|
206
|
+
return { stats, content: await cached.content };
|
|
207
|
+
const content = Promise.resolve(loader(path));
|
|
208
|
+
exports.parseFileCache.set(path, { stats, content, lastCheck: now });
|
|
209
|
+
return { stats, content: await content };
|
|
202
210
|
}
|
|
203
211
|
async function parseFile(path, parse, skipStatIfFresherThan = 0) {
|
|
204
212
|
return loadFileCached(path, () => (0, promises_1.readFile)(path).then(parse), skipStatIfFresherThan);
|
package/src/webdav.js
CHANGED
|
@@ -206,10 +206,7 @@ const webdav = async (ctx, next) => {
|
|
|
206
206
|
if ((0, path_1.dirname)(path) === (0, path_1.dirname)(dest)) // rename case. `path` is is encoded, so we test before decoding `dest`
|
|
207
207
|
try {
|
|
208
208
|
// decode the single path segment so reserved chars like %2C become their real name on rename
|
|
209
|
-
|
|
210
|
-
if (!newName)
|
|
211
|
-
return ctx.status = cross_1.HTTP_BAD_REQUEST;
|
|
212
|
-
await (0, frontEndApis_1.requestedRename)(node, newName, ctx);
|
|
209
|
+
await (0, frontEndApis_1.requestedRename)(node, (0, cross_1.safeDecodeURIComponent)((0, path_1.basename)(dest), ''), ctx);
|
|
213
210
|
releaseWebdavLock(path); // RFC 4918 says MOVE must not carry locks to destination, so clear source lock on success
|
|
214
211
|
return ctx.status = cross_1.HTTP_CREATED;
|
|
215
212
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.ariaOnly{clip-path:rect(1px 1px 1px 1px);clip:rect(1px, 1px, 1px, 1px);position:absolute}.icon{text-align:center;width:1.4em;height:1.2em;font-size:1.2em;display:inline-block}@keyframes blink{0%{opacity:1}50%{opacity:.3}}:root{--success:#5c5;height:100dvh}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#000;height:100vh;margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}#root{min-height:100%;display:flex}main{word-break:break-word}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}img.flag{vertical-align:text-top;width:1.5em;height:1em;margin-top:1px}.icon-w-text{margin-right:.5em}form{max-width:100%}.MuiSvgIcon-root{vertical-align:bottom}div.MuiTreeItem-content{padding-top:1px;padding-bottom:0}.MuiDataGrid-columnHeaders{background-color:rgba(136,136,136,.133)}.MuiDataGrid-virtualScrollerRenderZone .MuiDataGrid-row .MuiDataGrid-cell{align-items:center;line-height:1.2em;display:flex}.MuiDataGrid-filterForm{flex-wrap:wrap;justify-content:space-evenly;row-gap:1em}.wrap[role=cell]{white-space:normal!important}ol,ul{margin-top:.2em;margin-bottom:.2em;padding-left:1.5em}h2.MuiDialogTitle-root{padding-top:2px;padding-bottom:2px}.dialog-alert .MuiDialogContent-root{white-space:pre-wrap;max-width:45em;padding:.5em 1em}.release code{background-color:rgba(136,136,136,.2);border-radius:.2em;padding:0 .2em;font-size:95%}.MuiAppBar-root .MuiAlert-standardInfo .MuiAlert-icon{color:rgba(255,255,255,.533)!important}.MuiAppBar-root .MuiAlert-standardInfo .MuiAlert-message{color:rgba(255,255,255,.667)!important}.MuiAppBar-root .MuiAlert-colorWarning .MuiAlert-icon{color:rgba(255,255,0,.533)!important}.MuiAppBar-root .MuiAlert-colorWarning .MuiAlert-message{color:rgba(255,255,0,.667)!important}.animated-dashed-line{background-image:linear-gradient(90deg,currentColor 50%,transparent 50%);background-size:10px 100%;width:100%;height:2px;animation:1s linear infinite alternate animate-dash}@keyframes animate-dash{to{background-position:20px 0}}@keyframes success{50%{color:var(--success);transform:scale(1.3)}to{transform:inherit;color:inherit}}::-webkit-scrollbar{width:4px}::-webkit-scrollbar-thumb{background:rgba(136,136,136,.533)}::-webkit-scrollbar-track{background:rgba(136,136,136,.133)}.token.operator{background:unset!important}.fflag{vertical-align:bottom;border:none;width:26px;height:17px}code[class*=language-],pre[class*=language-]{color:#657b83;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;line-height:1.5}pre[class*=language-]::-moz-selection{background:#073642}pre[class*=language-] ::-moz-selection{background:#073642}code[class*=language-]::-moz-selection{background:#073642}code[class*=language-] ::-moz-selection{background:#073642}pre[class*=language-]::-moz-selection{background:#073642}pre[class*=language-]::selection{background:#073642}pre[class*=language-] ::-moz-selection{background:#073642}pre[class*=language-] ::selection{background:#073642}code[class*=language-]::-moz-selection{background:#073642}code[class*=language-]::selection{background:#073642}code[class*=language-] ::-moz-selection{background:#073642}code[class*=language-] ::selection{background:#073642}pre[class*=language-]{border-radius:.3em;margin:.5em 0;padding:1em;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background-color:#fdf6e3}:not(pre)>code[class*=language-]{border-radius:.3em;padding:.1em}.token.comment,.token.prolog,.token.doctype,.token.cdata{color:#93a1a1}.token.punctuation{color:#586e75}.token.namespace{opacity:.7}.token.property,.token.tag,.token.boolean,.token.number,.token.constant,.token.symbol,.token.deleted{color:#268bd2}.token.selector,.token.attr-name,.token.string,.token.char,.token.builtin,.token.url,.token.inserted{color:#2aa198}.token.entity{color:#657b83;background:#eee8d5}.token.atrule,.token.attr-value,.token.keyword{color:#859900}.token.function,.token.class-name{color:#b58900}.token.regex,.token.important,.token.variable{color:#cb4b16}.token.important,.token.bold{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}
|