hfs 3.3.4 → 3.4.0-alpha2
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/AccountsPage-CoiPofEv.js +4 -0
- package/admin/assets/ConfigFilePage-jUH2feqi.js +4 -0
- package/admin/assets/CustomHtmlPage-Pl_AJZrl.js +2 -0
- package/admin/assets/InternetPage-DIcAwhFk.js +6 -0
- package/admin/assets/LangPage-BwVY8QRD.js +2 -0
- package/admin/assets/LogsPage-CcjS12cP.js +3 -0
- package/admin/assets/MonitorPage-DMVFXyMe.js +2 -0
- package/admin/assets/OptionsPage-BB40ax9G.js +3 -0
- package/admin/assets/PluginsPage-CC2dINcb.js +1 -0
- package/admin/assets/icons-C_ux1zLA.js +1 -0
- package/admin/assets/index-BSSQOMG_.js +755 -0
- package/admin/assets/index-mI9kZlpb.css +1 -0
- package/admin/assets/routing-Be72yFmd.js +1 -0
- package/admin/index.html +2 -2
- package/central.json +100 -1
- package/frontend/assets/{dist-legacy-CnYHQXZ6.js → dist-legacy-D7Dg5w3L.js} +1 -1
- package/frontend/assets/index-legacy-CnazC3Dj.js +1 -0
- package/frontend/assets/{lib-legacy-3xYueNHt.js → lib-legacy-BxFHpdER.js} +1 -1
- package/frontend/assets/{sha512-legacy-Cl3f_PhN.js → sha512-legacy-C8xoQBnP.js} +1 -1
- package/frontend/index.html +1 -1
- package/npm-shrinkwrap.json +9 -9
- package/package.json +2 -2
- package/plugins/antibrute/plugin.js +62 -15
- package/src/acme.js +143 -50
- package/src/acmeConfig.js +43 -0
- package/src/acmeDns.js +285 -0
- package/src/admin-langs/embedded.js +33 -0
- package/src/admin-langs/hfs-admin-lang-ar.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-bg.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-de.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-el.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-en.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-es.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-fi.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-fr.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-hu.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-it.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-ja.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-ko.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-lt.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-ms.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-nl.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-pl.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-pt-br.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-ro.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-ru.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-sr-latn.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-sr.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-th.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-tr.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-uk.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-vi.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-zh-hant.json +1149 -0
- package/src/admin-langs/hfs-admin-lang-zh.json +1149 -0
- package/src/adminApis.js +2 -2
- package/src/adminLang.js +51 -0
- package/src/api.auth.js +1 -1
- package/src/api.lang.js +22 -13
- package/src/api.log.js +5 -3
- package/src/api.net.js +20 -3
- package/src/api.plugins.js +53 -19
- package/src/api.vfs.js +3 -2
- package/src/argv.js +4 -0
- package/src/auth.js +13 -9
- package/src/basicWeb.js +6 -2
- package/src/block.js +1 -1
- package/src/config.js +1 -0
- package/src/connections.js +4 -7
- package/src/consoleLog.js +4 -0
- package/src/const.js +1 -1
- package/src/cross-const.js +8 -6
- package/src/cross.js +16 -2
- package/src/customHtml.js +3 -2
- package/src/frontEndApis.js +44 -7
- package/src/github.js +6 -37
- package/src/i18n.js +16 -4
- package/src/index.js +4 -3
- package/src/lang.js +21 -9
- package/src/langs/embedded.js +3 -2
- package/src/langs/hfs-lang-ar.json +7 -2
- package/src/langs/hfs-lang-bg.json +7 -2
- package/src/langs/hfs-lang-de.json +7 -2
- package/src/langs/hfs-lang-el.json +7 -2
- package/src/langs/hfs-lang-en.json +189 -0
- package/src/langs/hfs-lang-es.json +9 -4
- package/src/langs/hfs-lang-fi.json +8 -3
- package/src/langs/hfs-lang-fr.json +12 -7
- package/src/langs/hfs-lang-hu.json +7 -2
- package/src/langs/hfs-lang-it.json +11 -5
- package/src/langs/hfs-lang-ja.json +7 -2
- package/src/langs/hfs-lang-ko.json +7 -2
- package/src/langs/hfs-lang-lt.json +7 -2
- package/src/langs/hfs-lang-ms.json +9 -2
- package/src/langs/hfs-lang-nl.json +7 -2
- package/src/langs/hfs-lang-pl.json +7 -2
- package/src/langs/hfs-lang-pt-br.json +9 -4
- package/src/langs/hfs-lang-ro.json +7 -2
- package/src/langs/hfs-lang-ru.json +9 -4
- package/src/langs/hfs-lang-sr-latn.json +7 -2
- package/src/langs/hfs-lang-sr.json +7 -2
- package/src/langs/hfs-lang-th.json +8 -3
- package/src/langs/hfs-lang-tr.json +8 -3
- package/src/langs/hfs-lang-uk.json +16 -11
- package/src/langs/hfs-lang-vi.json +7 -2
- package/src/langs/hfs-lang-zh-hant.json +189 -0
- package/src/langs/hfs-lang-zh.json +97 -95
- package/src/listen.js +6 -3
- package/src/log.js +7 -1
- package/src/middlewares.js +87 -31
- package/src/multipartUpload.js +21 -0
- package/src/perm.js +38 -20
- package/src/pluginCatalog.js +66 -0
- package/src/pluginUsage.js +64 -0
- package/src/plugins.js +14 -2
- package/src/roots.js +22 -13
- package/src/serveFile.js +28 -11
- package/src/serveGuiAndSharedFiles.js +6 -6
- package/src/serveGuiFiles.js +7 -4
- package/src/update.js +51 -18
- package/src/upload.js +49 -8
- package/src/util-http.js +31 -5
- package/src/vfs.js +93 -4
- package/src/webdav.js +14 -8
- package/admin/assets/AccountsPage-CnZGcUox.js +0 -6
- package/admin/assets/ArrayField-F7fpCJIv.js +0 -2
- package/admin/assets/ConfigFilePage-CEgZ8Wq4.js +0 -4
- package/admin/assets/CustomHtmlPage-DDUNxF1H.js +0 -2
- package/admin/assets/DataTable-D_TeYxvk.js +0 -119
- package/admin/assets/DateTimeField-CsIdkTqz.js +0 -1
- package/admin/assets/EventManager--HiXIAY0.js +0 -1
- package/admin/assets/FileField-HsDCdr5S.js +0 -117
- package/admin/assets/InternetPage-DDwKrXJH.js +0 -8
- package/admin/assets/LangPage-Dd8hi_9K.js +0 -2
- package/admin/assets/LogsPage-BcPfugNY.js +0 -4
- package/admin/assets/MenuButton-cuehhVig.js +0 -1
- package/admin/assets/MonitorPage-Bre9d6MA.js +0 -2
- package/admin/assets/OptionsPage-Dd_cRDf4.js +0 -3
- package/admin/assets/PluginsPage-DJiseD4G.js +0 -1
- package/admin/assets/Tabs-C87E85Fh.js +0 -1
- package/admin/assets/TextEditor-BeS-mR2I.css +0 -1
- package/admin/assets/TextEditor-Cr0VI9Xi.js +0 -34
- package/admin/assets/VfsPathField-D1BkfhAM.js +0 -1
- package/admin/assets/agentIcons-CDoUTPUC.js +0 -1
- package/admin/assets/baseUrl-CnrV7Huu.js +0 -2
- package/admin/assets/icons-DJJYoK9E.js +0 -1
- package/admin/assets/index-11n5z0Ez.css +0 -1
- package/admin/assets/index-DwXlUHAs.js +0 -477
- package/admin/assets/routing-BQpoUdjq.js +0 -1
- package/frontend/assets/index-legacy-JYULclbY.js +0 -1
- package/src/langs/hfs-lang-zh-tw.json +0 -183
package/src/adminApis.js
CHANGED
|
@@ -150,11 +150,11 @@ exports.adminApis = {
|
|
|
150
150
|
configFile: config_1.configFile.getPath(),
|
|
151
151
|
urls: await (0, listen_1.getUrls)(),
|
|
152
152
|
ips: await (0, listen_1.getIps)(false),
|
|
153
|
-
connectionAddress: (0,
|
|
153
|
+
connectionAddress: (0, misc_1.normalizeIp)(ctx.socket.localAddress || ''),
|
|
154
154
|
baseUrl: await (0, listen_1.getBaseUrlOrDefault)(),
|
|
155
155
|
roots: roots_1.roots.get(),
|
|
156
156
|
anyAccountCanLoginAdmin: anyAccountCanLoginAdmin(),
|
|
157
|
-
updatePossible: !await (0, update_1.
|
|
157
|
+
updatePossible: !await (0, update_1.updateNotSupported)() && (await (0, update_1.localUpdateAvailable)() ? 'local' : true),
|
|
158
158
|
previousVersionAvailable: await (0, update_1.previousAvailable)(),
|
|
159
159
|
autoCheckUpdateResult: update_1.autoCheckUpdateResult.get(), // in this form, we get the same type of the serialized json
|
|
160
160
|
alerts: // in this form, we get the same type of the serialized json
|
package/src/adminLang.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// This file is part of HFS - Copyright 2026, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.adminLang = void 0;
|
|
8
|
+
exports.getAdminLangs = getAdminLangs;
|
|
9
|
+
exports.getAdminLangData = getAdminLangData;
|
|
10
|
+
exports.invalidateAdminLang = invalidateAdminLang;
|
|
11
|
+
const promises_1 = require("fs/promises");
|
|
12
|
+
const misc_1 = require("./misc");
|
|
13
|
+
const config_1 = require("./config");
|
|
14
|
+
const expiringCache_1 = require("./expiringCache");
|
|
15
|
+
const embedded_1 = __importDefault(require("./admin-langs/embedded"));
|
|
16
|
+
const const_1 = require("./const");
|
|
17
|
+
const lang_1 = require("./lang");
|
|
18
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
19
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
20
|
+
async function getAdminLangs() {
|
|
21
|
+
const files = await (0, fast_glob_1.default)((0, lang_1.code2file)('*', true));
|
|
22
|
+
return lodash_1.default.uniq([...Object.keys(embedded_1.default), ...files.map(name => (0, lang_1.file2code)(name, true))
|
|
23
|
+
.filter(code => (0, lang_1.normalizeLangCode)(code) === code)]);
|
|
24
|
+
}
|
|
25
|
+
exports.adminLang = (0, config_1.defineConfig)(misc_1.CFG.admin_lang, '', v => (0, lang_1.langCodeForLookup)((0, lang_1.normalizeLangCode)(v)));
|
|
26
|
+
const cache = (0, expiringCache_1.expiringCache)(3_000);
|
|
27
|
+
function getAdminLangData(ctx, langs) {
|
|
28
|
+
const configured = exports.adminLang.compiled();
|
|
29
|
+
const code = langs.includes(configured) ? configured : browserAdminLang(ctx, langs);
|
|
30
|
+
return cache.try(code, async () => ({
|
|
31
|
+
[code]: (0, misc_1.tryJson)(await (0, promises_1.readFile)((0, lang_1.code2file)(code, true), 'utf8').catch(() => ''))
|
|
32
|
+
|| embedded_1.default[code] || embedded_1.default.en,
|
|
33
|
+
...code === const_1.EMBEDDED_LANGUAGE ? {} : { [const_1.EMBEDDED_LANGUAGE]: embedded_1.default.en },
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
function invalidateAdminLang(code) {
|
|
37
|
+
cache.delete(code); // uploads and deletions must be visible immediately after the Admin reloads
|
|
38
|
+
}
|
|
39
|
+
function browserAdminLang(ctx, langs) {
|
|
40
|
+
const accepted = ctx?.get('Accept-Language') || '';
|
|
41
|
+
for (const raw of accepted.split(',')) {
|
|
42
|
+
let code = (0, lang_1.normalizeLangCode)(raw);
|
|
43
|
+
while (code) {
|
|
44
|
+
const candidate = (0, lang_1.langCodeForLookup)(code);
|
|
45
|
+
if (langs.includes(candidate))
|
|
46
|
+
return candidate;
|
|
47
|
+
code = code.substring(0, code.lastIndexOf('-'));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return const_1.EMBEDDED_LANGUAGE;
|
|
51
|
+
}
|
package/src/api.auth.js
CHANGED
|
@@ -67,7 +67,7 @@ exports.authApis = {
|
|
|
67
67
|
return new apiMiddleware_1.ApiError(const_1.HTTP_SERVER_ERROR);
|
|
68
68
|
if (account?.plugin?.auth) // tell client to do clear-text login, before firing attemptingLogin, before triggering anti-brute
|
|
69
69
|
return new apiMiddleware_1.ApiError(const_1.HTTP_METHOD_NOT_ALLOWED);
|
|
70
|
-
if ((await events_1.default.emitAsync('attemptingLogin', { ctx, username }))?.isDefaultPrevented())
|
|
70
|
+
if ((await events_1.default.emitAsync('attemptingLogin', { ctx, username, via: 'srp' }))?.isDefaultPrevented())
|
|
71
71
|
return;
|
|
72
72
|
if (account && !(0, perm_1.accountCanLogin)(account)) {
|
|
73
73
|
ctx.logExtra({ u: username });
|
package/src/api.lang.js
CHANGED
|
@@ -12,30 +12,36 @@ const const_1 = require("./const");
|
|
|
12
12
|
const misc_1 = require("./misc");
|
|
13
13
|
const lang_1 = require("./lang");
|
|
14
14
|
const embedded_1 = __importDefault(require("./langs/embedded"));
|
|
15
|
+
const embedded_2 = __importDefault(require("./admin-langs/embedded"));
|
|
16
|
+
const adminLang_1 = require("./adminLang");
|
|
15
17
|
const SendList_1 = require("./SendList");
|
|
16
18
|
const apis = {
|
|
17
19
|
get_langs() {
|
|
18
20
|
return new SendList_1.SendListReadable({
|
|
19
21
|
doAtStart: async (list) => {
|
|
20
|
-
for
|
|
21
|
-
name
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
for (const admin of [false, true]) {
|
|
23
|
+
for await (const name of fast_glob_1.default.stream((0, lang_1.code2file)('*', admin))) {
|
|
24
|
+
const code = (0, lang_1.file2code)(String(name), admin);
|
|
25
|
+
try {
|
|
26
|
+
const data = JSON.parse(await (0, promises_1.readFile)(String(name), 'utf8'));
|
|
27
|
+
list.add({ ...lodash_1.default.omit(data, 'translate'), code, admin, embedded: false });
|
|
28
|
+
}
|
|
29
|
+
catch { }
|
|
26
30
|
}
|
|
27
|
-
|
|
31
|
+
for (const [code, data] of Object.entries(admin ? embedded_2.default : embedded_1.default))
|
|
32
|
+
list.add({ ...lodash_1.default.omit(data, 'translate'), code, admin, embedded: true });
|
|
28
33
|
}
|
|
29
|
-
for (const [code, data] of Object.entries(embedded_1.default))
|
|
30
|
-
list.add({ code, embedded: true, ...lodash_1.default.omit(data, 'translate') });
|
|
31
34
|
list.close();
|
|
32
35
|
}
|
|
33
36
|
});
|
|
34
37
|
},
|
|
35
|
-
async del_lang({ code }) {
|
|
38
|
+
async del_lang({ code, admin = false }) {
|
|
39
|
+
(0, misc_1.apiAssertTypes)({ string: { code }, boolean: { admin } });
|
|
36
40
|
validateCode(code);
|
|
37
41
|
try {
|
|
38
|
-
await (0, promises_1.rm)((0, lang_1.code2file)(code));
|
|
42
|
+
await (0, promises_1.rm)((0, lang_1.code2file)(code, admin));
|
|
43
|
+
if (admin)
|
|
44
|
+
(0, adminLang_1.invalidateAdminLang)(code.toLowerCase());
|
|
39
45
|
return {};
|
|
40
46
|
}
|
|
41
47
|
catch (e) {
|
|
@@ -45,14 +51,17 @@ const apis = {
|
|
|
45
51
|
async add_langs({ langs }) {
|
|
46
52
|
(0, misc_1.apiAssertTypes)({ object: { langs } });
|
|
47
53
|
for (let [code, content] of Object.entries(langs)) {
|
|
48
|
-
|
|
54
|
+
const admin = code.startsWith('hfs-admin-lang-');
|
|
55
|
+
code = (0, lang_1.file2code)(code, admin);
|
|
49
56
|
validateCode(code);
|
|
50
|
-
const fn = (0, lang_1.code2file)(code);
|
|
57
|
+
const fn = (0, lang_1.code2file)(code, admin);
|
|
51
58
|
const s = String(content);
|
|
52
59
|
const o = (0, misc_1.tryJson)(s);
|
|
53
60
|
if (!o?.translate)
|
|
54
61
|
return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_ACCEPTABLE, "bad content for file " + fn);
|
|
55
62
|
await (0, promises_1.writeFile)(fn, s, 'utf8');
|
|
63
|
+
if (admin)
|
|
64
|
+
(0, adminLang_1.invalidateAdminLang)(code.toLowerCase());
|
|
56
65
|
}
|
|
57
66
|
return {};
|
|
58
67
|
}
|
package/src/api.log.js
CHANGED
|
@@ -33,25 +33,27 @@ exports.default = {
|
|
|
33
33
|
await (0, serveFile_1.serveFile)(ctx, log.path);
|
|
34
34
|
return null;
|
|
35
35
|
},
|
|
36
|
-
get_log({ file = 'log' }, ctx) {
|
|
36
|
+
get_log({ file = 'log', skipInitial }, ctx) {
|
|
37
37
|
(0, misc_1.apiAssertTypes)({ string: { file } });
|
|
38
38
|
const files = file.split('|'); // potentially more than one
|
|
39
39
|
return new SendList_1.SendListReadable({
|
|
40
40
|
bufferTime: 10,
|
|
41
41
|
async doAtStart(list) {
|
|
42
42
|
if (file === 'disconnections') {
|
|
43
|
-
for (const x of connections_1.disconnectionsLog)
|
|
43
|
+
for (const x of skipInitial ? [] : connections_1.disconnectionsLog)
|
|
44
44
|
list.add(x);
|
|
45
45
|
ctx.res.once('close', events_1.default.on('disconnection', x => list.add(x)));
|
|
46
46
|
return list.ready();
|
|
47
47
|
}
|
|
48
48
|
if (file === 'ips') {
|
|
49
|
+
if (skipInitial)
|
|
50
|
+
return list.ready();
|
|
49
51
|
for await (const [k, v] of ips_1.ips.iterator())
|
|
50
52
|
list.add({ ip: k, ...v });
|
|
51
53
|
return list.ready();
|
|
52
54
|
}
|
|
53
55
|
if (file === 'console') {
|
|
54
|
-
for (const chunk of lodash_1.default.chunk(consoleLog_1.consoleLog, 1000)) { // avoid occupying the thread too long
|
|
56
|
+
for (const chunk of lodash_1.default.chunk(skipInitial ? [] : consoleLog_1.consoleLog, 1000)) { // avoid occupying the thread too long
|
|
55
57
|
for (const x of chunk)
|
|
56
58
|
list.add(x);
|
|
57
59
|
await (0, cross_1.wait)(0);
|
package/src/api.net.js
CHANGED
|
@@ -14,6 +14,7 @@ const promises_1 = require("dns/promises");
|
|
|
14
14
|
const net_1 = require("net");
|
|
15
15
|
const nat_1 = require("./nat");
|
|
16
16
|
const acme_1 = require("./acme");
|
|
17
|
+
const acmeConfig_1 = require("./acmeConfig");
|
|
17
18
|
const selfCheck_1 = require("./selfCheck");
|
|
18
19
|
exports.default = {
|
|
19
20
|
get_nat: nat_1.getNatInfo,
|
|
@@ -83,13 +84,29 @@ exports.default = {
|
|
|
83
84
|
const results = (0, misc_1.onlyTruthy)(await (0, misc_1.promiseBestEffort)(publicIps.map(ip => (0, selfCheck_1.selfCheck)(`${proto}://${(0, misc_1.ipForUrl)(ip)}${finalPort === defPort ? '' : ':' + finalPort}`))));
|
|
84
85
|
return results.length ? results : new apiMiddleware_1.ApiError(const_1.HTTP_SERVICE_UNAVAILABLE);
|
|
85
86
|
},
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
get_acme: acmeConfig_1.getAcmeSettings,
|
|
88
|
+
get_acme_status: acme_1.getAcmeStatusEvents,
|
|
89
|
+
async set_acme({ settings }) {
|
|
90
|
+
if ((0, acme_1.getAcmeStatus)().state === 'running')
|
|
91
|
+
throw new apiMiddleware_1.ApiError(409, "Certificate request already running");
|
|
92
|
+
if (!settings || typeof settings !== 'object')
|
|
93
|
+
throw new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST);
|
|
94
|
+
return (0, acmeConfig_1.setAcmeSettings)(settings).catch(error => { throw new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, error.message); });
|
|
95
|
+
},
|
|
96
|
+
async make_cert({ domain, email, altNames, background }) {
|
|
97
|
+
(0, misc_1.apiAssertTypes)({ string: { domain }, string_undefined: { email }, array_undefined: { altNames }, boolean_undefined: { background } });
|
|
88
98
|
if (!domain)
|
|
89
99
|
return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad params');
|
|
90
100
|
if (altNames?.some((name) => typeof name !== 'string'))
|
|
91
101
|
return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad altNames');
|
|
92
|
-
|
|
102
|
+
if ((0, acme_1.getAcmeStatus)().state === 'running')
|
|
103
|
+
throw new apiMiddleware_1.ApiError(409, "Certificate request already running");
|
|
104
|
+
const pending = (0, acme_1.makeCert)(domain, email, altNames);
|
|
105
|
+
if (background) {
|
|
106
|
+
void pending.catch(() => { }); // the status stream carries the error even after the browser disconnects
|
|
107
|
+
return { id: (0, acme_1.getAcmeStatus)().id };
|
|
108
|
+
}
|
|
109
|
+
await pending.catch(e => {
|
|
93
110
|
throw new apiMiddleware_1.ApiError(const_1.HTTP_SERVER_ERROR, e.message || String(e));
|
|
94
111
|
});
|
|
95
112
|
return {};
|
package/src/api.plugins.js
CHANGED
|
@@ -13,9 +13,10 @@ const promises_1 = require("fs/promises");
|
|
|
13
13
|
const github_1 = require("./github");
|
|
14
14
|
const const_1 = require("./const");
|
|
15
15
|
const SendList_1 = require("./SendList");
|
|
16
|
+
const pluginCatalog_1 = require("./pluginCatalog");
|
|
16
17
|
const apis = {
|
|
17
|
-
get_plugins({}, ctx) {
|
|
18
|
-
const list = new SendList_1.SendListReadable({ addAtStart: [...(0, plugins_1.mapPlugins)(serialize, false), ...(0, plugins_1.getInactivePlugins)().map(serialize)] });
|
|
18
|
+
get_plugins({ skipInitial }, ctx) {
|
|
19
|
+
const list = new SendList_1.SendListReadable({ addAtStart: skipInitial ? [] : [...(0, plugins_1.mapPlugins)(serialize, false), ...(0, plugins_1.getInactivePlugins)().map(serialize)] });
|
|
19
20
|
return list.events(ctx, {
|
|
20
21
|
pluginInstalled: p => list.add(serialize(p)),
|
|
21
22
|
'pluginStarted pluginStopped pluginUpdated': p => {
|
|
@@ -26,7 +27,7 @@ const apis = {
|
|
|
26
27
|
pluginLog: id => list.update({ id }, { log: true }) // SendList is already capping frequency
|
|
27
28
|
});
|
|
28
29
|
},
|
|
29
|
-
async get_plugin_updates({}, ctx) {
|
|
30
|
+
async get_plugin_updates({ skipInitial }, ctx) {
|
|
30
31
|
return new SendList_1.SendListReadable({
|
|
31
32
|
async doAtStart(list) {
|
|
32
33
|
const errs = {};
|
|
@@ -38,6 +39,8 @@ const apis = {
|
|
|
38
39
|
list.update({ id }, { updated: true });
|
|
39
40
|
}
|
|
40
41
|
});
|
|
42
|
+
if (skipInitial)
|
|
43
|
+
return list.ready();
|
|
41
44
|
await plugins_1.pluginsScanned;
|
|
42
45
|
await Promise.allSettled(lodash_1.default.map((0, github_1.getFolder2repo)(), async (repo, folder) => {
|
|
43
46
|
try {
|
|
@@ -73,11 +76,17 @@ const apis = {
|
|
|
73
76
|
async start_plugin({ id }) {
|
|
74
77
|
assertPluginId(id);
|
|
75
78
|
if ((0, plugins_1.isPluginRunning)(id))
|
|
76
|
-
return
|
|
79
|
+
return serializeRunningPlugin(id);
|
|
77
80
|
if (plugins_1.suspendPlugins.get())
|
|
78
81
|
return new apiMiddleware_1.ApiError(misc_1.HTTP_PRECONDITION_FAILED, 'all plugins suspended');
|
|
79
82
|
await (0, plugins_1.stopPlugin)(id);
|
|
80
|
-
|
|
83
|
+
try {
|
|
84
|
+
await (0, plugins_1.startPlugin)(id);
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
return new apiMiddleware_1.ApiError(const_1.HTTP_SERVER_ERROR, e.message);
|
|
88
|
+
}
|
|
89
|
+
return serializeRunningPlugin(id);
|
|
81
90
|
},
|
|
82
91
|
async stop_plugin({ id }) {
|
|
83
92
|
assertPluginId(id);
|
|
@@ -104,42 +113,63 @@ const apis = {
|
|
|
104
113
|
}
|
|
105
114
|
};
|
|
106
115
|
},
|
|
107
|
-
get_online_plugins({ text }, ctx) {
|
|
116
|
+
get_online_plugins({ text, skipInitial }, ctx) {
|
|
108
117
|
if (text !== undefined && !lodash_1.default.isString(text))
|
|
109
118
|
return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad text');
|
|
110
119
|
return new SendList_1.SendListReadable({
|
|
111
120
|
async doAtStart(list) {
|
|
121
|
+
// resumed clients retain their own rows; updates for other repos are ignored by useApiList
|
|
112
122
|
const repos = [];
|
|
113
123
|
list.events(ctx, {
|
|
114
124
|
pluginInstalled: p => {
|
|
115
|
-
if (repos.includes(p.repo))
|
|
125
|
+
if (skipInitial || repos.includes(p.repo))
|
|
116
126
|
list.update({ id: p.repo }, { installed: true });
|
|
117
127
|
},
|
|
118
128
|
pluginUninstalled: (_folder, repo) => {
|
|
119
129
|
if (typeof repo !== 'string')
|
|
120
130
|
return; // custom repo
|
|
121
|
-
if (repos.includes(repo))
|
|
131
|
+
if (skipInitial || repos.includes(repo))
|
|
122
132
|
list.update({ id: repo }, { installed: false });
|
|
123
133
|
},
|
|
124
134
|
pluginDownload({ repo, status }) {
|
|
125
|
-
if (repos.includes(repo))
|
|
135
|
+
if (skipInitial || repos.includes(repo))
|
|
126
136
|
list.update({ id: repo }, { downloading: status ?? null });
|
|
127
137
|
}
|
|
128
138
|
});
|
|
139
|
+
if (skipInitial)
|
|
140
|
+
return list.ready();
|
|
141
|
+
let updatedAt;
|
|
142
|
+
let previous = new Map();
|
|
129
143
|
try {
|
|
130
|
-
const
|
|
131
|
-
|
|
144
|
+
for await (const snapshot of (0, pluginCatalog_1.getPluginCatalog)()) {
|
|
145
|
+
const already = Object.values((0, github_1.getFolder2repo)()).filter(Boolean).map(String);
|
|
146
|
+
const plugins = await (0, pluginCatalog_1.searchPluginCatalog)(snapshot, text, already);
|
|
132
147
|
if (ctx.isAborted())
|
|
133
148
|
return;
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
149
|
+
const rows = plugins.map(pl => {
|
|
150
|
+
const missing = (0, plugins_1.getMissingDependencies)(pl);
|
|
151
|
+
return { ...pl, missing: missing.length ? missing : null, downloading: github_1.downloading[pl.repo] ?? null };
|
|
152
|
+
});
|
|
153
|
+
// reconcile snapshots without dropping selection or retaining obsolete optional metadata
|
|
154
|
+
for (const id of previous.keys())
|
|
155
|
+
if (!rows.some(row => row.id === id))
|
|
156
|
+
list.remove({ id });
|
|
157
|
+
for (const row of rows) {
|
|
158
|
+
const old = previous.get(row.id);
|
|
159
|
+
if (old)
|
|
160
|
+
list.update({ id: row.id }, { ...lodash_1.default.mapValues(old, () => null), ...lodash_1.default.mapValues(row, value => value ?? null) });
|
|
161
|
+
else
|
|
162
|
+
list.add(row);
|
|
163
|
+
}
|
|
164
|
+
previous = new Map(rows.map(row => [row.id, row]));
|
|
165
|
+
repos.splice(0, repos.length, ...rows.map(row => row.repo));
|
|
166
|
+
updatedAt = snapshot.updatedAt;
|
|
167
|
+
list.props({ updatedAt, refreshing: snapshot.refreshing });
|
|
168
|
+
list.ready();
|
|
140
169
|
}
|
|
141
170
|
}
|
|
142
171
|
catch (err) {
|
|
172
|
+
list.props({ updatedAt, refreshing: false });
|
|
143
173
|
list.error(err.code || err.message);
|
|
144
174
|
}
|
|
145
175
|
list.ready();
|
|
@@ -177,12 +207,12 @@ const apis = {
|
|
|
177
207
|
(0, plugins_1.setPluginConfig)(id, null);
|
|
178
208
|
return {};
|
|
179
209
|
},
|
|
180
|
-
get_plugin_log({ id }, ctx) {
|
|
210
|
+
get_plugin_log({ id, skipInitial }, ctx) {
|
|
181
211
|
assertPluginId(id);
|
|
182
212
|
const p = (0, plugins_1.getPluginInfo)(id);
|
|
183
213
|
if (!p)
|
|
184
214
|
return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND);
|
|
185
|
-
const list = new SendList_1.SendListReadable({ addAtStart: p.log });
|
|
215
|
+
const list = new SendList_1.SendListReadable({ addAtStart: skipInitial ? [] : p.log });
|
|
186
216
|
return list.events(ctx, {
|
|
187
217
|
['pluginLog:' + id]: x => list.add(x)
|
|
188
218
|
});
|
|
@@ -202,6 +232,10 @@ function serialize(p) {
|
|
|
202
232
|
: JSON.stringify(o.config, (_k, v) => lodash_1.default.isFunction(v) ? String(v) : v); // allow simple functions
|
|
203
233
|
return lodash_1.default.defaults(o, { started: null, badApi: null }); // nulls should be used to be sure to overwrite previous values,
|
|
204
234
|
}
|
|
235
|
+
function serializeRunningPlugin(id) {
|
|
236
|
+
const plugin = (0, plugins_1.firstPlugin)((plugin, pluginId) => pluginId === id ? plugin : undefined);
|
|
237
|
+
return plugin ? serialize(plugin) : new apiMiddleware_1.ApiError(const_1.HTTP_SERVER_ERROR);
|
|
238
|
+
}
|
|
205
239
|
async function checkDependencies(plugin) {
|
|
206
240
|
const miss = await (0, plugins_1.getMissingDependencies)(plugin);
|
|
207
241
|
if (miss.length)
|
package/src/api.vfs.js
CHANGED
|
@@ -36,8 +36,9 @@ exports.default = {
|
|
|
36
36
|
delete copyStats.mtime;
|
|
37
37
|
const inherited = node.parent && (0, vfs_1.permsFromParent)(node.parent, {});
|
|
38
38
|
const byMasks = node.original && lodash_1.default.pickBy(node, (v, k) => v !== node.original[k] // something is changing me...
|
|
39
|
-
&&
|
|
40
|
-
|
|
39
|
+
&& (k === 'gui_asset'
|
|
40
|
+
? v !== node.parent?.gui_asset // gui_asset inherits outside the permission helpers
|
|
41
|
+
: !(inherited && k in inherited) && misc_1.PERM_KEYS.includes(k))); // ...must be masks
|
|
41
42
|
return {
|
|
42
43
|
...copyStats,
|
|
43
44
|
...node.original || node,
|
package/src/argv.js
CHANGED
|
@@ -6,3 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.argv = void 0;
|
|
7
7
|
const minimist_1 = __importDefault(require("minimist"));
|
|
8
8
|
exports.argv = (0, minimist_1.default)(process.argv.slice(2));
|
|
9
|
+
// Node's internal flag is read-only when enabled via its CLI, but remains configurable
|
|
10
|
+
Object.defineProperty(process, 'traceProcessWarnings', {
|
|
11
|
+
value: exports.argv['trace-warnings'] !== false, writable: true, configurable: true,
|
|
12
|
+
});
|
package/src/auth.js
CHANGED
|
@@ -85,13 +85,19 @@ function getCurrentUsername(ctx) {
|
|
|
85
85
|
async function clearTextLogin(ctx, u, p, via) {
|
|
86
86
|
if (!p)
|
|
87
87
|
return;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
88
|
+
let account;
|
|
89
|
+
try {
|
|
90
|
+
if ((await events_1.default.emitAsync('attemptingLogin', { ctx, username: u, via }))?.isDefaultPrevented())
|
|
91
|
+
return;
|
|
92
|
+
const plugins = await events_1.default.emitAsync('clearTextLogin', { ctx, username: u, password: p, via }); // provide clear password to plugins
|
|
93
|
+
account = plugins?.some(x => x === true) ? (0, perm_1.getAccount)(u) : await srpCheck(u, p);
|
|
94
|
+
if (!account && u)
|
|
95
|
+
events_1.default.emit('failedLogin', { ctx, username: u, via });
|
|
96
|
+
return account;
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
events_1.default.emit('loginAttemptFinished', { ctx, username: u, via, success: Boolean(account) });
|
|
100
|
+
}
|
|
95
101
|
}
|
|
96
102
|
// centralized log-in state
|
|
97
103
|
async function setLoggedIn(ctx, username, via) {
|
|
@@ -122,8 +128,6 @@ async function setLoggedIn(ctx, username, via) {
|
|
|
122
128
|
ctx.throw(cross_const_1.HTTP_UNAUTHORIZED, error);
|
|
123
129
|
}
|
|
124
130
|
const normalized = (0, perm_1.normalizeUsername)(username);
|
|
125
|
-
if (s.username !== normalized)
|
|
126
|
-
delete s.allowNet; // discard restrictions cached for another identity before replacing the session account
|
|
127
131
|
s.username = normalized;
|
|
128
132
|
s.ip = ctx.ip;
|
|
129
133
|
s.stamp = sessionStamp;
|
package/src/basicWeb.js
CHANGED
|
@@ -17,8 +17,12 @@ const autoBasic = (0, config_1.defineConfig)(misc_1.CFG.auto_basic, true, v => l
|
|
|
17
17
|
function basicWeb(ctx, node) {
|
|
18
18
|
const { get } = ctx.query;
|
|
19
19
|
if (get === 'login') {
|
|
20
|
-
if ((0, auth_1.getCurrentUsername)(ctx))
|
|
21
|
-
ctx.
|
|
20
|
+
if ((0, auth_1.getCurrentUsername)(ctx)) {
|
|
21
|
+
const referer = ctx.get('referer');
|
|
22
|
+
const url = referer && (0, misc_1.try_)(() => new URL(referer, ctx.URL));
|
|
23
|
+
// keep the origin in Location because a same-origin path starting with // would redirect externally
|
|
24
|
+
ctx.redirect(url && url.origin === ctx.URL.origin ? url.origin + url.pathname + url.search + url.hash : '/');
|
|
25
|
+
}
|
|
22
26
|
else {
|
|
23
27
|
ctx.set('WWW-Authenticate', cross_const_1.BASIC_AUTHENTICATE_HEADER);
|
|
24
28
|
ctx.status = cross_const_1.HTTP_UNAUTHORIZED;
|
package/src/block.js
CHANGED
|
@@ -26,7 +26,7 @@ exports.block = (0, config_1.defineConfig)(misc_1.CFG.block, [], rules => {
|
|
|
26
26
|
});
|
|
27
27
|
return ret;
|
|
28
28
|
});
|
|
29
|
-
function applyBlock(socket, ip = (0,
|
|
29
|
+
function applyBlock(socket, ip = (0, misc_1.normalizeIp)(socket.remoteAddress || '')) {
|
|
30
30
|
if (ip && isBlocked(ip))
|
|
31
31
|
return (0, connections_1.disconnect)(socket, 'block-ip');
|
|
32
32
|
}
|
package/src/config.js
CHANGED
|
@@ -244,6 +244,7 @@ Most common configurations:
|
|
|
244
244
|
For a description of each configuration, please refer to https://rejetto.com/hfs-config
|
|
245
245
|
Other options:
|
|
246
246
|
--debug will print extra information
|
|
247
|
+
--no-trace-warnings will disable stack traces for Node.js warnings (enabled by default)
|
|
247
248
|
`);
|
|
248
249
|
process.exit(0);
|
|
249
250
|
});
|
package/src/connections.js
CHANGED
|
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.disconnectionsLog = exports.Connection = void 0;
|
|
8
|
-
exports.normalizeIp = normalizeIp;
|
|
9
8
|
exports.newConnection = newConnection;
|
|
10
9
|
exports.getConnections = getConnections;
|
|
11
10
|
exports.socket2connection = socket2connection;
|
|
@@ -16,6 +15,7 @@ exports.disconnect = disconnect;
|
|
|
16
15
|
const events_1 = __importDefault(require("./events"));
|
|
17
16
|
const geo_1 = require("./geo");
|
|
18
17
|
const lodash_1 = __importDefault(require("lodash"));
|
|
18
|
+
const cross_1 = require("./cross");
|
|
19
19
|
class Connection {
|
|
20
20
|
socket;
|
|
21
21
|
started = new Date();
|
|
@@ -41,19 +41,16 @@ class Connection {
|
|
|
41
41
|
events_1.default.emit('connectionNewIp', this, this._cachedIp, this.ctx.ip);
|
|
42
42
|
this._cachedIp = undefined;
|
|
43
43
|
}
|
|
44
|
-
return this.ctx?.ip || (this._cachedIp ??= normalizeIp(this.socket.remoteAddress || ''));
|
|
44
|
+
return this.ctx?.ip || (this._cachedIp ??= (0, cross_1.normalizeIp)(this.socket.remoteAddress || ''));
|
|
45
45
|
}
|
|
46
46
|
get secure() {
|
|
47
47
|
return this.socket.server.cert > '';
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
exports.Connection = Connection;
|
|
51
|
-
function normalizeIp(ip) {
|
|
52
|
-
return ip.replace(/^::ffff:/, ''); // simplify ipv6-mapped addresses
|
|
53
|
-
}
|
|
54
51
|
const all = [];
|
|
55
52
|
function newConnection(socket) {
|
|
56
|
-
const ip = normalizeIp(socket.remoteAddress || '');
|
|
53
|
+
const ip = (0, cross_1.normalizeIp)(socket.remoteAddress || '');
|
|
57
54
|
const res = events_1.default.emit('newSocket', { socket, ip });
|
|
58
55
|
const msg = res?.isDefaultPrevented() ? 'plugin (newSocket)' : res?.find(lodash_1.default.isString);
|
|
59
56
|
if (!msg)
|
|
@@ -90,7 +87,7 @@ exports.disconnectionsLog = [];
|
|
|
90
87
|
function disconnect(what, logMessage = '') {
|
|
91
88
|
if ('socket' in what)
|
|
92
89
|
what = what.socket;
|
|
93
|
-
const ip = normalizeIp(what.remoteAddress || '');
|
|
90
|
+
const ip = (0, cross_1.normalizeIp)(what.remoteAddress || '');
|
|
94
91
|
if (logMessage)
|
|
95
92
|
console.debug("Disconnection:", logMessage, ip);
|
|
96
93
|
(0, geo_1.ip2country)(ip).then(res => {
|
package/src/consoleLog.js
CHANGED
|
@@ -17,6 +17,7 @@ f?.on('error', err => {
|
|
|
17
17
|
console.error("Cannot write console file", argv_1.argv.consoleFile, String(err));
|
|
18
18
|
});
|
|
19
19
|
let terminalOutputBroken = false;
|
|
20
|
+
let lastTerminalDate = '';
|
|
20
21
|
for (const stream of [process.stdout, process.stderr])
|
|
21
22
|
stream.on('error', err => {
|
|
22
23
|
if (!isBrokenTerminalOutput(err))
|
|
@@ -40,6 +41,9 @@ for (const k of ['log', 'warn', 'error', 'debug']) {
|
|
|
40
41
|
events_1.default.emit('console', rec);
|
|
41
42
|
f?.write(`${(0, cross_1.formatTimestamp)(ts)} [${k}] ${msg}\n`);
|
|
42
43
|
if (!terminalOutputBroken) {
|
|
44
|
+
const date = (0, cross_1.formatDate)(ts);
|
|
45
|
+
if (date !== lastTerminalDate)
|
|
46
|
+
console.log.original(lastTerminalDate = date);
|
|
43
47
|
try {
|
|
44
48
|
return original((0, cross_1.formatTime)(ts), ...args);
|
|
45
49
|
} // bundled nodejs doesn't have locales (and apparently uses en-US)
|
package/src/const.js
CHANGED
|
@@ -49,7 +49,7 @@ const path_1 = require("path");
|
|
|
49
49
|
const cross_1 = require("./cross");
|
|
50
50
|
const argv_1 = require("./argv");
|
|
51
51
|
__exportStar(require("./cross-const"), exports);
|
|
52
|
-
exports.API_VERSION = 13.
|
|
52
|
+
exports.API_VERSION = 13.71;
|
|
53
53
|
exports.COMPATIBLE_API_VERSION = 1; // the day we break with the past, we'll update this
|
|
54
54
|
// you can add arguments with this file, currently used for the update process on mac/linux.
|
|
55
55
|
// we are using homedir because it's the only stable path both the old and new process can agree on (open() doesn't preserve cwd)
|
package/src/cross-const.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.HTTP_MESSAGES = exports.HTTP_INSUFFICIENT_STORAGE = exports.HTTP_SERVICE_UNAVAILABLE = exports.HTTP_SERVER_ERROR = exports.HTTP_TOO_MANY_REQUESTS = exports.HTTP_FAILED_DEPENDENCY = exports.HTTP_LOCKED = exports.HTTP_FOOL = exports.HTTP_RANGE_NOT_SATISFIABLE = exports.HTTP_PAYLOAD_TOO_LARGE = exports.HTTP_PRECONDITION_FAILED = exports.HTTP_LENGTH_REQUIRED = exports.HTTP_CONFLICT = exports.HTTP_NOT_ACCEPTABLE = exports.HTTP_METHOD_NOT_ALLOWED = exports.HTTP_NOT_FOUND = exports.HTTP_FORBIDDEN = exports.HTTP_UNAUTHORIZED = exports.HTTP_BAD_REQUEST = exports.HTTP_NOT_MODIFIED = exports.HTTP_TEMPORARY_REDIRECT = exports.HTTP_MOVED_PERMANENTLY = exports.HTTP_PARTIAL_CONTENT = exports.HTTP_NO_CONTENT = exports.HTTP_CREATED = exports.HTTP_OK = exports.CFG = exports.MB = exports.KB = exports.BASIC_AUTHENTICATE_HEADER = exports.EMBEDDED_LANGUAGE = exports.MASK_IN_TESTS = exports.HIDE_IN_TESTS = exports.ALLOW_SESSION_IP_CHANGE = exports.PREVIOUS_TAG = exports.MTIME_CHECK = exports.UPLOAD_TEMP_HASH = exports.UPLOAD_TEMP_PREFIX = exports.HFS_REPO = exports.PLUGIN_CUSTOM_REST_PREFIX = exports.NBSP = exports.PORT_DISABLED = exports.ICONS_URI = exports.PLUGINS_PUB_URI = exports.API_URI = exports.ADMIN_URI = exports.FRONTEND_URI = exports.SPECIAL_URI = void 0;
|
|
3
|
+
exports.HTTP_MESSAGES = exports.HTTP_INSUFFICIENT_STORAGE = exports.HTTP_SERVICE_UNAVAILABLE = exports.HTTP_SERVER_ERROR = exports.HTTP_TOO_MANY_REQUESTS = exports.HTTP_FAILED_DEPENDENCY = exports.HTTP_LOCKED = exports.HTTP_FOOL = exports.HTTP_RANGE_NOT_SATISFIABLE = exports.HTTP_PAYLOAD_TOO_LARGE = exports.HTTP_PRECONDITION_FAILED = exports.HTTP_LENGTH_REQUIRED = exports.HTTP_CONFLICT = exports.HTTP_NOT_ACCEPTABLE = exports.HTTP_METHOD_NOT_ALLOWED = exports.HTTP_NOT_FOUND = exports.HTTP_FORBIDDEN = exports.HTTP_UNAUTHORIZED = exports.HTTP_BAD_REQUEST = exports.HTTP_TEMPORARY_REDIRECT_KEEP_METHOD = exports.HTTP_NOT_MODIFIED = exports.HTTP_TEMPORARY_REDIRECT = exports.HTTP_MOVED_PERMANENTLY = exports.HTTP_PARTIAL_CONTENT = exports.HTTP_NO_CONTENT = exports.HTTP_CREATED = exports.HTTP_OK = exports.CFG = exports.MB = exports.KB = exports.BASIC_AUTHENTICATE_HEADER = exports.EMBEDDED_LANGUAGE = exports.MASK_IN_TESTS = exports.HIDE_IN_TESTS = exports.ALLOW_SESSION_IP_CHANGE = exports.PREVIOUS_TAG = exports.MTIME_CHECK = exports.UPLOAD_TEMP_HASH = exports.UPLOAD_TEMP_PREFIX = exports.PLUGIN_USAGE_URL = exports.HFS_REPO = exports.PLUGIN_CUSTOM_REST_PREFIX = exports.NBSP = exports.PORT_DISABLED = exports.ICONS_URI = exports.PLUGINS_PUB_URI = exports.API_URI = exports.ADMIN_URI = exports.FRONTEND_URI = exports.SPECIAL_URI = void 0;
|
|
4
4
|
exports.SPECIAL_URI = '/~/';
|
|
5
5
|
exports.FRONTEND_URI = exports.SPECIAL_URI + 'frontend/';
|
|
6
6
|
exports.ADMIN_URI = exports.SPECIAL_URI + 'admin/';
|
|
@@ -11,6 +11,7 @@ exports.PORT_DISABLED = -1;
|
|
|
11
11
|
exports.NBSP = '\xA0';
|
|
12
12
|
exports.PLUGIN_CUSTOM_REST_PREFIX = '_';
|
|
13
13
|
exports.HFS_REPO = 'rejetto/hfs';
|
|
14
|
+
exports.PLUGIN_USAGE_URL = 'https://hfs-api.rejetto.com/plugin-usage';
|
|
14
15
|
exports.UPLOAD_TEMP_PREFIX = 'hfs$upload-';
|
|
15
16
|
exports.UPLOAD_TEMP_HASH = 'upload-temp-hash';
|
|
16
17
|
exports.MTIME_CHECK = 'x-mtime-check';
|
|
@@ -18,12 +19,12 @@ exports.PREVIOUS_TAG = 'previous';
|
|
|
18
19
|
exports.ALLOW_SESSION_IP_CHANGE = 'allow_session_ip_change';
|
|
19
20
|
exports.HIDE_IN_TESTS = 'hideInTests'; // elements that have variable size, where masking would produce changes, must be hidden
|
|
20
21
|
exports.MASK_IN_TESTS = 'maskInTests';
|
|
21
|
-
exports.EMBEDDED_LANGUAGE = 'en';
|
|
22
|
+
exports.EMBEDDED_LANGUAGE = 'en';
|
|
22
23
|
exports.BASIC_AUTHENTICATE_HEADER = 'Basic realm="HFS"';
|
|
23
24
|
exports.KB = 1024;
|
|
24
25
|
exports.MB = exports.KB * exports.KB;
|
|
25
26
|
exports.CFG = constMap([
|
|
26
|
-
'accounts', 'acme_domain', 'acme_renew', 'admin_net', 'allowed_referer',
|
|
27
|
+
'accounts', 'acme_domain', 'acme_renew', 'acme_challenge', 'acme_dns', 'admin_lang', 'admin_net', 'allowed_referer',
|
|
27
28
|
'authorization_header', 'auto_basic', 'auto_check_update', 'auto_play_seconds',
|
|
28
29
|
'base_url', 'block', 'cache_control_disk_files', 'cert', 'comments_storage',
|
|
29
30
|
'create-admin', 'debug', 'delete_unfinished_uploads_after',
|
|
@@ -33,16 +34,16 @@ exports.CFG = constMap([
|
|
|
33
34
|
'force_https', 'force_lang', 'force_webdav_login',
|
|
34
35
|
'geo_allow', 'geo_allow_unknown', 'geo_enable', 'geo_ignore_net', 'geo_list',
|
|
35
36
|
'ignore_proxies', 'invert_order', 'keep_session_alive', 'listen_interface',
|
|
36
|
-
'localhost_admin', 'log', 'log_api', 'log_gui', 'log_host', 'log_rotation', 'log_spam',
|
|
37
|
+
'localhost_admin', 'log', 'log_api', 'log_gui', 'log_host', 'log_rotation', 'log_spam', 'log_spam_regex',
|
|
37
38
|
'log_ua', 'mapped_port', 'max_downloads', 'max_downloads_per_account',
|
|
38
39
|
'max_downloads_per_ip', 'max_kbps', 'max_kbps_per_ip', 'menu_at_top', 'mime',
|
|
39
40
|
'min_available_mb', 'open_browser_at_start', 'outbound_interface', 'outbound_proxy', 'own_upload_delete_hours',
|
|
40
41
|
'page_size', 'plugins_config', 'port', 'private_key', 'proxies', 'roots', 'server_code',
|
|
41
|
-
'session_duration', 'show_hidden_files', 'show_uploader', 'size_1024',
|
|
42
|
+
'session_duration', 'share_usage_stats', 'show_hidden_files', 'show_uploader', 'size_1024',
|
|
42
43
|
'smart_unc_folder_detection', 'sort_by', 'sort_numerics', 'split_uploads',
|
|
43
44
|
'suspend_plugins', 'theme', 'tile_size', 'title', 'title_with_path', 'track_ips',
|
|
44
45
|
'update_to_beta', 'upnp_enabled', 'version', 'vfs', 'webdav_initial_auth',
|
|
45
|
-
'zip_calculate_size_for_seconds', 'https_port'
|
|
46
|
+
'zip_calculate_size_for_seconds', 'https_port', 'require_upload_approval_for_active_content',
|
|
46
47
|
]);
|
|
47
48
|
function constMap(a) {
|
|
48
49
|
return Object.fromEntries(a.map(x => [x, x]));
|
|
@@ -54,6 +55,7 @@ exports.HTTP_PARTIAL_CONTENT = 206;
|
|
|
54
55
|
exports.HTTP_MOVED_PERMANENTLY = 301;
|
|
55
56
|
exports.HTTP_TEMPORARY_REDIRECT = 302;
|
|
56
57
|
exports.HTTP_NOT_MODIFIED = 304;
|
|
58
|
+
exports.HTTP_TEMPORARY_REDIRECT_KEEP_METHOD = 307;
|
|
57
59
|
exports.HTTP_BAD_REQUEST = 400;
|
|
58
60
|
exports.HTTP_UNAUTHORIZED = 401;
|
|
59
61
|
exports.HTTP_FORBIDDEN = 403;
|