hfs 0.53.0-alpha2 → 0.53.0-alpha3
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/{index-CwIN7CM4.css → index-CA0TStF8.css} +1 -1
- package/admin/assets/index-D95ycf6f.js +805 -0
- package/admin/assets/{sha512-BjLhiBem.js → sha512-NegoJIqW.js} +1 -1
- package/admin/index.html +2 -2
- package/frontend/assets/{index-legacy-C21Ot_ue.js → index-legacy-BzpvPuwE.js} +7 -7
- package/frontend/assets/{sha512-legacy-DYmEZJfO.js → sha512-legacy-BaHlAWFl.js} +1 -1
- package/frontend/index.html +2 -2
- package/package.json +2 -1
- package/src/api.monitor.js +1 -1
- package/src/api.net.js +4 -3
- package/src/apiMiddleware.js +0 -10
- package/src/basicWeb.js +64 -0
- package/src/const.js +2 -2
- package/src/cross.js +17 -3
- package/src/github.js +16 -10
- package/src/listen.js +6 -6
- package/src/nat.js +4 -3
- package/src/plugins.js +8 -0
- package/src/roots.js +19 -9
- package/src/serveFile.js +1 -1
- package/src/serveGuiAndSharedFiles.js +3 -0
- package/src/serveGuiFiles.js +1 -1
- package/admin/assets/index-Dsv2tjnU.js +0 -805
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
System.register(["./index-legacy-
|
|
1
|
+
System.register(["./index-legacy-BzpvPuwE.js"],(function(h,t){"use strict";var i,s;return{setters:[function(h){i=h.g,s=h.c}],execute:function(){function t(h,t){for(var i=function(){var i=t[s];if("string"!=typeof i&&!Array.isArray(i)){var r=function(t){if("default"!==t&&!(t in h)){var s=Object.getOwnPropertyDescriptor(i,t);s&&Object.defineProperty(h,t,s.get?s:{enumerable:!0,get:function(){return i[t]}})}};for(var e in i)r(e)}},s=0;s<t.length;s++)i();return Object.freeze(Object.defineProperty(h,Symbol.toStringTag,{value:"Module"}))}var r={exports:{}};
|
|
2
2
|
/*
|
|
3
3
|
* [js-sha512]{@link https://github.com/emn178/js-sha512}
|
|
4
4
|
*
|
package/frontend/index.html
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
|
-
<noscript>
|
|
10
|
+
<noscript>Enable JavaScript or <a href="?get=basic">go simple</a></noscript>
|
|
11
11
|
<div id="root"></div>
|
|
12
12
|
<script nomodule>document.getElementById('root').innerText = "Please use a newer browser"</script>
|
|
13
13
|
<script crossorigin id="vite-legacy-polyfill" src="/assets/polyfills-legacy-DMrMt_pQ.js"></script>
|
|
14
|
-
<script crossorigin id="vite-legacy-entry" data-src="/assets/index-legacy-
|
|
14
|
+
<script crossorigin id="vite-legacy-entry" data-src="/assets/index-legacy-BzpvPuwE.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
|
|
15
15
|
</body>
|
|
16
16
|
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hfs",
|
|
3
|
-
"version": "0.53.0-
|
|
3
|
+
"version": "0.53.0-alpha3",
|
|
4
4
|
"description": "HTTP File Server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"file server",
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@koa/router": "^12.0.1",
|
|
73
73
|
"@node-rs/crc32": "^1.6.0",
|
|
74
|
+
"@rejetto/kvstorage": "^0.4.0",
|
|
74
75
|
"acme-client": "^5.2.0",
|
|
75
76
|
"basic-auth": "^2.0.1",
|
|
76
77
|
"buffer-crc32": "^0.2.13",
|
package/src/api.monitor.js
CHANGED
|
@@ -71,7 +71,7 @@ exports.default = {
|
|
|
71
71
|
: s.uploadPath ? { op: 'upload', path: decodeURIComponent(s.uploadPath) }
|
|
72
72
|
: {
|
|
73
73
|
op: !s.considerAsGui && s.op || undefined,
|
|
74
|
-
path: decodeURIComponent(ctx.originalUrl)
|
|
74
|
+
path: (0, misc_1.try_)(() => decodeURIComponent(ctx.originalUrl), () => ctx.originalUrl),
|
|
75
75
|
},
|
|
76
76
|
opProgress: lodash_1.default.isNumber(s.opProgress) ? lodash_1.default.round(s.opProgress, 3) : undefined,
|
|
77
77
|
opTotal: s.opTotal,
|
package/src/api.net.js
CHANGED
|
@@ -17,6 +17,7 @@ const acme_1 = require("./acme");
|
|
|
17
17
|
const selfCheck_1 = require("./selfCheck");
|
|
18
18
|
const apis = {
|
|
19
19
|
get_nat: nat_1.getNatInfo,
|
|
20
|
+
get_public_ips: nat_1.getPublicIps,
|
|
20
21
|
async check_domain({ domain }) {
|
|
21
22
|
(0, misc_1.apiAssertTypes)({ string: domain });
|
|
22
23
|
const resolver = new promises_1.Resolver();
|
|
@@ -63,15 +64,15 @@ const apis = {
|
|
|
63
64
|
if (url)
|
|
64
65
|
return await (0, selfCheck_1.selfCheck)(url)
|
|
65
66
|
|| new apiMiddleware_1.ApiError(const_1.HTTP_SERVICE_UNAVAILABLE);
|
|
66
|
-
const nat = await (0, nat_1.getNatInfo)();
|
|
67
|
-
if (!
|
|
67
|
+
const [publicIps, nat] = await Promise.all([(0, nat_1.getPublicIps)(), (0, nat_1.getNatInfo)()]);
|
|
68
|
+
if (!publicIps.length)
|
|
68
69
|
return new apiMiddleware_1.ApiError(const_1.HTTP_FAILED_DEPENDENCY, 'cannot detect public ip');
|
|
69
70
|
if (!nat.internalPort)
|
|
70
71
|
return new apiMiddleware_1.ApiError(const_1.HTTP_FAILED_DEPENDENCY, 'no internal port');
|
|
71
72
|
const finalPort = nat.externalPort || nat.internalPort;
|
|
72
73
|
const proto = nat.proto || ((0, listen_1.getCertObject)() ? 'https' : 'http');
|
|
73
74
|
const defPort = proto === 'https' ? 443 : 80;
|
|
74
|
-
const results = (0, misc_1.onlyTruthy)(await (0, misc_1.promiseBestEffort)(
|
|
75
|
+
const results = (0, misc_1.onlyTruthy)(await (0, misc_1.promiseBestEffort)(publicIps.map(ip => (0, selfCheck_1.selfCheck)(`${proto}://${ip}${finalPort === defPort ? '' : ':' + finalPort}`))));
|
|
75
76
|
return results.length ? results : new apiMiddleware_1.ApiError(const_1.HTTP_SERVICE_UNAVAILABLE);
|
|
76
77
|
},
|
|
77
78
|
async make_cert({ domain, email, altNames }) {
|
package/src/apiMiddleware.js
CHANGED
|
@@ -36,19 +36,9 @@ function apiMiddleware(apis) {
|
|
|
36
36
|
// we don't rely on SameSite cookie option because it's https-only
|
|
37
37
|
let res;
|
|
38
38
|
try {
|
|
39
|
-
if (ctx.state.revProxyPath)
|
|
40
|
-
for (const [k, v] of Object.entries(params))
|
|
41
|
-
if (k.startsWith('uri'))
|
|
42
|
-
if (typeof v === 'string')
|
|
43
|
-
fixUri(params, k);
|
|
44
|
-
else if (typeof (v === null || v === void 0 ? void 0 : v[0]) === 'string')
|
|
45
|
-
v.forEach((x, i) => fixUri(v, i));
|
|
46
39
|
res = await apiFun(params, ctx);
|
|
47
40
|
if (res === null)
|
|
48
41
|
return;
|
|
49
|
-
function fixUri(obj, k) {
|
|
50
|
-
obj[k] = (0, misc_1.removeStarting)(ctx.state.revProxyPath, obj[k]);
|
|
51
|
-
}
|
|
52
42
|
}
|
|
53
43
|
catch (e) {
|
|
54
44
|
if (typeof e === 'string') // message meant to be transmitted
|
package/src/basicWeb.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.basicWeb = void 0;
|
|
7
|
+
const auth_1 = require("./auth");
|
|
8
|
+
const cross_const_1 = require("./cross-const");
|
|
9
|
+
const config_1 = require("./config");
|
|
10
|
+
const vfs_1 = require("./vfs");
|
|
11
|
+
const misc_1 = require("./misc");
|
|
12
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
13
|
+
const adminApis_1 = require("./adminApis");
|
|
14
|
+
const customHtml_1 = require("./customHtml");
|
|
15
|
+
const autoBasic = (0, config_1.defineConfig)('auto_basic', true);
|
|
16
|
+
function basicWeb(ctx, node) {
|
|
17
|
+
const { get } = ctx.query;
|
|
18
|
+
if (get === 'login') {
|
|
19
|
+
if ((0, auth_1.getCurrentUsername)(ctx))
|
|
20
|
+
ctx.redirect('?');
|
|
21
|
+
else {
|
|
22
|
+
ctx.set('WWW-Authenticate', 'Basic');
|
|
23
|
+
ctx.status = cross_const_1.HTTP_UNAUTHORIZED;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (get === 'logout') {
|
|
28
|
+
ctx.body = `<script>location = '?'</script>`;
|
|
29
|
+
(0, auth_1.setLoggedIn)(ctx, false);
|
|
30
|
+
ctx.status = cross_const_1.HTTP_UNAUTHORIZED;
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
const forced = get === 'basic';
|
|
34
|
+
if (forced || detectBasicAgent()) {
|
|
35
|
+
ctx.type = 'html';
|
|
36
|
+
const force = forced ? '?get=basic' : '';
|
|
37
|
+
const walker = (0, vfs_1.walkNode)(node, { ctx, depth: 0 });
|
|
38
|
+
const stream = (0, misc_1.asyncGeneratorToReadable)((0, misc_1.filterMapGenerator)(walker, async (el) => {
|
|
39
|
+
const isFolder = await (0, vfs_1.nodeIsDirectory)(el);
|
|
40
|
+
const name = (0, vfs_1.getNodeName)(el) + (isFolder ? '/' : '');
|
|
41
|
+
return `<li>${a((0, misc_1.pathEncode)(name) + (isFolder ? force : ''), name)}\n`;
|
|
42
|
+
}));
|
|
43
|
+
ctx.body = stream;
|
|
44
|
+
stream.push(`<title>${adminApis_1.title.get()}</title><body>`);
|
|
45
|
+
stream.push((0, customHtml_1.getSection)('basicHeader'));
|
|
46
|
+
const links = (0, auth_1.getCurrentUsername)(ctx) ? { '?get=logout': "Logout" } : { '?get=login': "Login" };
|
|
47
|
+
stream.push(lodash_1.default.map(links, (v, k) => a(k, v)).join(' ') + '\n<ul>\n');
|
|
48
|
+
if (ctx.state.originalPath.length > 1)
|
|
49
|
+
stream.push('<li>' + a('..' + force, '..') + '\n');
|
|
50
|
+
stream.push('</ul>\n');
|
|
51
|
+
stream.push((0, customHtml_1.getSection)('basicFooter'));
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
function a(href, label) {
|
|
55
|
+
return `<a href='${href}'>${label}</a>`;
|
|
56
|
+
}
|
|
57
|
+
function detectBasicAgent() {
|
|
58
|
+
const ua = ctx.get('user-agent');
|
|
59
|
+
const v = autoBasic.get();
|
|
60
|
+
return v && (/Mozilla\/4|WebKit\/([234]\d\d|5[012]\d|53[0123456])[. ]|Trident|Lynx|Firefox\/(\d|[123]\d)\./.test(ua)
|
|
61
|
+
|| lodash_1.default.isString(v) && ua.includes(v));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.basicWeb = basicWeb;
|
package/src/const.js
CHANGED
|
@@ -37,7 +37,7 @@ const os_1 = require("os");
|
|
|
37
37
|
const fs_1 = require("fs");
|
|
38
38
|
const path_1 = require("path");
|
|
39
39
|
__exportStar(require("./cross-const"), exports);
|
|
40
|
-
exports.API_VERSION = 8.
|
|
40
|
+
exports.API_VERSION = 8.81;
|
|
41
41
|
exports.COMPATIBLE_API_VERSION = 1; // while changes in the api are not breaking, this number stays the same, otherwise it is made equal to API_VERSION
|
|
42
42
|
exports.HFS_REPO = 'rejetto/hfs';
|
|
43
43
|
exports.argv = (0, minimist_1.default)(process.argv.slice(2));
|
|
@@ -45,7 +45,7 @@ exports.DEV = process.env.DEV || exports.argv.dev ? 'DEV' : '';
|
|
|
45
45
|
exports.ORIGINAL_CWD = process.cwd();
|
|
46
46
|
exports.HFS_STARTED = new Date();
|
|
47
47
|
const PKG_PATH = (0, path_1.join)(__dirname, '..', 'package.json');
|
|
48
|
-
exports.BUILD_TIMESTAMP = "2024-05-
|
|
48
|
+
exports.BUILD_TIMESTAMP = "2024-05-15T10:18:26.357Z";
|
|
49
49
|
const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'));
|
|
50
50
|
exports.VERSION = pkg.version;
|
|
51
51
|
exports.RUNNING_BETA = exports.VERSION.includes('-');
|
package/src/cross.js
CHANGED
|
@@ -17,8 +17,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.
|
|
21
|
-
exports.shortenAgent = exports.mapFilter = exports.inCommon = exports.replace = exports.matches = exports.makeMatcher = exports.runAt = exports.pathEncode = exports.promiseBestEffort = exports.escapeHTML = exports.ipForUrl = exports.isIpLan = exports.isIpLocalHost = exports.xlate = exports.isEqualLax = exports.isTimestampString = exports.isWindowsDrive = exports.isIP = exports.isPrimitive = exports.formatTimestamp = exports.repeat = exports.asyncGeneratorToArray = exports.filterMapGenerator = exports.throw_ = exports.hasProp = void 0;
|
|
20
|
+
exports.objRenameKey = exports.randomId = exports.getOrSet = exports.waitFor = exports.newObj = exports.findDefined = exports.isOrderedEqual = exports.swap = exports.tryJson = exports.dirname = exports.basename = exports.pendingPromise = exports._dbg = exports._log = exports.wantArray = exports.formatPerc = exports.with_ = exports.try_ = exports.setHidden = exports.onlyTruthy = exports.truthy = exports.splitAt = exports.strinsert = exports.removeStarting = exports.enforceStarting = exports.enforceFinal = exports.objSameKeys = exports.haveTimeout = exports.wait = exports.join = exports.prefix = exports.formatSpeed = exports.formatBytes = exports.isWhoObject = exports.PERM_KEYS = exports.defaultPerms = exports.WHO_ANY_ACCOUNT = exports.WHO_NO_ONE = exports.WHO_ANYONE = exports.LIST = exports.CFG = exports.THEME_OPTIONS = exports.SORT_BY_OPTIONS = exports.FRONTEND_OPTIONS = exports.MAX_TILE_SIZE = exports.DAY = exports.HOUR = exports.MINUTE = exports.WIKI_URL = exports.REPO_URL = void 0;
|
|
21
|
+
exports.shortenAgent = exports.mapFilter = exports.inCommon = exports.replace = exports.matches = exports.makeMatcher = exports.runAt = exports.pathEncode = exports.promiseBestEffort = exports.escapeHTML = exports.ipForUrl = exports.isIpLan = exports.isIpLocalHost = exports.xlate = exports.isEqualLax = exports.isTimestampString = exports.isWindowsDrive = exports.isIP = exports.isPrimitive = exports.formatTimestamp = exports.repeat = exports.asyncGeneratorToArray = exports.filterMapGenerator = exports.throw_ = exports.hasProp = exports.typedEntries = exports.typedKeys = void 0;
|
|
22
22
|
// This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
|
|
23
23
|
// all content here is shared between client and server
|
|
24
24
|
const lodash_1 = __importDefault(require("lodash"));
|
|
@@ -85,6 +85,16 @@ function prefix(pre, v, post = '') {
|
|
|
85
85
|
return v ? (pre || '') + v + (post || '') : '';
|
|
86
86
|
}
|
|
87
87
|
exports.prefix = prefix;
|
|
88
|
+
function join(a, b, joiner = '/') {
|
|
89
|
+
if (!b)
|
|
90
|
+
return a;
|
|
91
|
+
if (!a)
|
|
92
|
+
return b;
|
|
93
|
+
const ends = a.at(-1) === joiner;
|
|
94
|
+
const starts = b[0] === joiner;
|
|
95
|
+
return a + (!ends && !starts ? joiner + b : ends && starts ? b.slice(1) : b);
|
|
96
|
+
}
|
|
97
|
+
exports.join = join;
|
|
88
98
|
function wait(ms, val) {
|
|
89
99
|
return new Promise(res => setTimeout(res, ms, val));
|
|
90
100
|
}
|
|
@@ -98,9 +108,13 @@ function objSameKeys(src, newValue) {
|
|
|
98
108
|
}
|
|
99
109
|
exports.objSameKeys = objSameKeys;
|
|
100
110
|
function enforceFinal(sub, s, evenEmpty = false) {
|
|
101
|
-
return
|
|
111
|
+
return evenEmpty && !s || !s.endsWith(sub) ? s + sub : s;
|
|
102
112
|
}
|
|
103
113
|
exports.enforceFinal = enforceFinal;
|
|
114
|
+
function enforceStarting(sub, s, evenEmpty = false) {
|
|
115
|
+
return evenEmpty && !s || !s.startsWith(sub) ? sub + s : s;
|
|
116
|
+
}
|
|
117
|
+
exports.enforceStarting = enforceStarting;
|
|
104
118
|
function removeStarting(sub, s) {
|
|
105
119
|
return s.startsWith(sub) ? s.slice(sub.length) : s;
|
|
106
120
|
}
|
package/src/github.js
CHANGED
|
@@ -165,20 +165,26 @@ async function* apiGithubPaginated(uri) {
|
|
|
165
165
|
const PAGE_SIZE = 100;
|
|
166
166
|
let page = 1;
|
|
167
167
|
let n = 0;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
168
|
+
try {
|
|
169
|
+
while (1) {
|
|
170
|
+
const res = await apiGithub(uri + `&page=${page++}&per_page=${PAGE_SIZE}`);
|
|
171
|
+
for (const x of res.items)
|
|
172
|
+
yield x;
|
|
173
|
+
const now = res.items.length;
|
|
174
|
+
n += now;
|
|
175
|
+
if (!now || n >= res.total_count)
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch (e) {
|
|
180
|
+
if (e.message !== '422') // for some strange reason github api is returning this error if we search repos for a missing user, instead of empty set
|
|
181
|
+
throw e;
|
|
176
182
|
}
|
|
177
183
|
}
|
|
178
184
|
async function searchPlugins(text = '', { skipRepos = [''] } = {}) {
|
|
179
185
|
const projectInfo = await (0, exports.getProjectInfo)();
|
|
180
|
-
const
|
|
181
|
-
|
|
186
|
+
const searches = [encodeURI(text), ...text.split(' ').filter(Boolean).slice(0, 2).map(x => 'user:' + encodeURI(x))]; // first 2 words can be the author
|
|
187
|
+
const list = await Promise.all(searches.map(x => (0, misc_1.asyncGeneratorToArray)(apiGithubPaginated(`search/repositories?q=topic:hfs-plugin+${x}`))))
|
|
182
188
|
.then(all => all.flat()); // make it a single array
|
|
183
189
|
return new misc_1.AsapStream(list.map(async (it) => {
|
|
184
190
|
var _a, _b;
|
package/src/listen.js
CHANGED
|
@@ -283,14 +283,14 @@ async function getIps(external = true) {
|
|
|
283
283
|
const ips = (0, misc_1.onlyTruthy)(Object.entries((0, os_1.networkInterfaces)()).flatMap(([name, nets]) => nets && !ignore.test(name) && nets.map(net => !net.internal && net.address)));
|
|
284
284
|
const e = external && nat_1.defaultBaseUrl.externalIp;
|
|
285
285
|
if (e && !ips.includes(e))
|
|
286
|
-
ips.
|
|
286
|
+
ips.push(e);
|
|
287
287
|
const noLinkLocal = ips.filter(x => !isLinkLocal(x));
|
|
288
|
-
const ret =
|
|
289
|
-
|
|
288
|
+
const ret = lodash_1.default.sortBy(noLinkLocal.length ? noLinkLocal : ips, [
|
|
289
|
+
x => x !== nat_1.defaultBaseUrl.localIp,
|
|
290
|
+
net_1.isIPv6 // false=IPV4 comes first
|
|
291
|
+
]);
|
|
292
|
+
nat_1.defaultBaseUrl.localIp || (nat_1.defaultBaseUrl.localIp = ret[0] || '');
|
|
290
293
|
return ret;
|
|
291
|
-
function v4first(a) {
|
|
292
|
-
return lodash_1.default.sortBy(a, net_1.isIPv6); // works because `false` comes first
|
|
293
|
-
}
|
|
294
294
|
}
|
|
295
295
|
exports.getIps = getIps;
|
|
296
296
|
async function getUrls() {
|
package/src/nat.js
CHANGED
|
@@ -63,11 +63,10 @@ exports.getPublicIps = (0, debounceAsync_1.debounceAsync)(async () => {
|
|
|
63
63
|
throw "no good";
|
|
64
64
|
return validIps;
|
|
65
65
|
}))));
|
|
66
|
-
return lodash_1.default.uniq(ips.flat());
|
|
66
|
+
return exports.defaultBaseUrl.publicIps = lodash_1.default.uniq(ips.flat());
|
|
67
67
|
}, 0, { retain: 10 * cross_1.MINUTE });
|
|
68
68
|
exports.getNatInfo = (0, debounceAsync_1.debounceAsync)(async () => {
|
|
69
69
|
var _a, _b, _c, _d;
|
|
70
|
-
const gettingIps = (0, exports.getPublicIps)(); // don't wait, do it in parallel
|
|
71
70
|
const res = await (0, cross_1.haveTimeout)(10000, exports.upnpClient.getGateway()).catch(() => null);
|
|
72
71
|
const status = await (0, listen_1.getServerStatus)();
|
|
73
72
|
const mappings = res && await (0, cross_1.haveTimeout)(5000, exports.upnpClient.getMappings()).catch(() => null);
|
|
@@ -78,12 +77,13 @@ exports.getNatInfo = (0, debounceAsync_1.debounceAsync)(async () => {
|
|
|
78
77
|
const internalPort = ((_a = status === null || status === void 0 ? void 0 : status.https) === null || _a === void 0 ? void 0 : _a.listening) && status.https.port || ((_b = status === null || status === void 0 ? void 0 : status.http) === null || _b === void 0 ? void 0 : _b.listening) && status.http.port || undefined;
|
|
79
78
|
const mapped = lodash_1.default.find(mappings, x => x.private.host === localIp && x.private.port === internalPort);
|
|
80
79
|
const externalPort = mapped === null || mapped === void 0 ? void 0 : mapped.public.port;
|
|
80
|
+
if (localIp)
|
|
81
|
+
exports.defaultBaseUrl.localIp = localIp;
|
|
81
82
|
exports.defaultBaseUrl.port = externalPort || internalPort || 0;
|
|
82
83
|
return {
|
|
83
84
|
upnp: Boolean(res),
|
|
84
85
|
localIp,
|
|
85
86
|
gatewayIp,
|
|
86
|
-
publicIps: exports.defaultBaseUrl.publicIps = await gettingIps,
|
|
87
87
|
externalIp: exports.defaultBaseUrl.externalIp,
|
|
88
88
|
mapped,
|
|
89
89
|
mapped80: lodash_1.default.find(mappings, x => x.private.host === localIp && x.private.port === 80 && x.public.port === 80),
|
|
@@ -92,6 +92,7 @@ exports.getNatInfo = (0, debounceAsync_1.debounceAsync)(async () => {
|
|
|
92
92
|
proto: ((_c = status === null || status === void 0 ? void 0 : status.https) === null || _c === void 0 ? void 0 : _c.listening) ? 'https' : ((_d = status === null || status === void 0 ? void 0 : status.http) === null || _d === void 0 ? void 0 : _d.listening) ? 'http' : '',
|
|
93
93
|
};
|
|
94
94
|
});
|
|
95
|
+
(0, exports.getNatInfo)();
|
|
95
96
|
function findGateway() {
|
|
96
97
|
return new Promise((resolve, reject) => (0, child_process_1.exec)(const_1.IS_WINDOWS || const_1.IS_MAC ? 'netstat -rn' : 'route -n', (err, out) => {
|
|
97
98
|
var _a;
|
package/src/plugins.js
CHANGED
|
@@ -42,6 +42,7 @@ const fs_1 = require("fs");
|
|
|
42
42
|
const connections_1 = require("./connections");
|
|
43
43
|
const path_1 = require("path");
|
|
44
44
|
const customHtml_1 = require("./customHtml");
|
|
45
|
+
const kvstorage_1 = require("@rejetto/kvstorage");
|
|
45
46
|
exports.PATH = 'plugins';
|
|
46
47
|
exports.DISABLING_SUFFIX = '-disabled';
|
|
47
48
|
exports.STORAGE_FOLDER = 'storage';
|
|
@@ -389,6 +390,13 @@ function watchPlugin(id, path) {
|
|
|
389
390
|
await initPlugin(pluginData, {
|
|
390
391
|
srcDir: __dirname,
|
|
391
392
|
storageDir,
|
|
393
|
+
async openDb(filename, options) {
|
|
394
|
+
if (!filename)
|
|
395
|
+
throw Error("missing filename");
|
|
396
|
+
const db = new kvstorage_1.KvStorage(options);
|
|
397
|
+
await db.open((0, path_1.join)(storageDir, filename));
|
|
398
|
+
return db;
|
|
399
|
+
},
|
|
392
400
|
log(...args) {
|
|
393
401
|
console.log('plugin', id + ':', ...args);
|
|
394
402
|
},
|
package/src/roots.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.rootsMiddleware = exports.roots = void 0;
|
|
4
7
|
const config_1 = require("./config");
|
|
5
8
|
const misc_1 = require("./misc");
|
|
6
9
|
const connections_1 = require("./connections");
|
|
7
10
|
const listen_1 = require("./listen");
|
|
11
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
8
12
|
exports.roots = (0, config_1.defineConfig)(misc_1.CFG.roots, {}, map => {
|
|
9
13
|
const list = Object.keys(map);
|
|
10
14
|
const matchers = list.map(hostMask => (0, misc_1.makeMatcher)(hostMask));
|
|
@@ -18,6 +22,7 @@ forceAddress.sub((v, { version }) => {
|
|
|
18
22
|
});
|
|
19
23
|
const rootsMiddleware = (ctx, next) => (() => {
|
|
20
24
|
var _a;
|
|
25
|
+
ctx.state.originalPath = ctx.path;
|
|
21
26
|
const root = (_a = exports.roots.compiled()) === null || _a === void 0 ? void 0 : _a(ctx.host);
|
|
22
27
|
if (!ctx.state.skipFilters && forceAddress.get())
|
|
23
28
|
if (root === undefined && !(0, misc_1.isLocalHost)(ctx) && ctx.host !== listen_1.baseUrl.compiled()) {
|
|
@@ -30,21 +35,26 @@ const rootsMiddleware = (ctx, next) => (() => {
|
|
|
30
35
|
if (ctx.path.startsWith(misc_1.SPECIAL_URI)) { // special uris should be excluded...
|
|
31
36
|
if (!ctx.path.startsWith(misc_1.API_URI))
|
|
32
37
|
return; // ...unless it's an api
|
|
38
|
+
params = ctx.state.params || ctx.query; // for api we'll translate params
|
|
39
|
+
changeUriParams(v => (0, misc_1.removeStarting)(ctx.state.revProxyPath, v)); // removal must be done before adding the root
|
|
33
40
|
let { referer } = ctx.headers;
|
|
34
41
|
referer && (referer = new URL(referer).pathname);
|
|
35
42
|
if (referer === null || referer === void 0 ? void 0 : referer.startsWith(ctx.state.revProxyPath + misc_1.ADMIN_URI))
|
|
36
43
|
return; // exclude apis for admin-panel
|
|
37
|
-
params = ctx.state.params || ctx.query; // for api we'll translate params
|
|
38
44
|
}
|
|
39
|
-
if (
|
|
40
|
-
|
|
45
|
+
if (lodash_1.default.isEmpty(exports.roots.get()))
|
|
46
|
+
return;
|
|
47
|
+
if (root === '' || root === '/')
|
|
41
48
|
return;
|
|
49
|
+
changeUriParams(v => (0, misc_1.join)(root, v));
|
|
50
|
+
if (!params)
|
|
51
|
+
ctx.path = (0, misc_1.join)(root, ctx.path);
|
|
52
|
+
function changeUriParams(cb) {
|
|
53
|
+
if (!params)
|
|
54
|
+
return;
|
|
55
|
+
for (const [k, v] of Object.entries(params))
|
|
56
|
+
if (k.startsWith('uri'))
|
|
57
|
+
params[k] = Array.isArray(v) ? v.map(cb) : cb(v);
|
|
42
58
|
}
|
|
43
|
-
for (const [k, v] of Object.entries(params))
|
|
44
|
-
if (k.startsWith('uri'))
|
|
45
|
-
params[k] = Array.isArray(v) ? v.map(x => join(root, x)) : join(root, v);
|
|
46
59
|
})() || next();
|
|
47
60
|
exports.rootsMiddleware = rootsMiddleware;
|
|
48
|
-
function join(a, b) {
|
|
49
|
-
return a + (b && b[0] !== '/' ? '/' : '') + b;
|
|
50
|
-
}
|
package/src/serveFile.js
CHANGED
|
@@ -57,7 +57,7 @@ async function serveFile(ctx, source, mime, content) {
|
|
|
57
57
|
return;
|
|
58
58
|
const fn = (0, path_1.basename)(source);
|
|
59
59
|
mime = mime !== null && mime !== void 0 ? mime : mimeCfg.compiled()(fn);
|
|
60
|
-
if (mime === const_1.MIME_AUTO)
|
|
60
|
+
if (!mime || mime === const_1.MIME_AUTO)
|
|
61
61
|
mime = mime_types_1.default.lookup(source) || '';
|
|
62
62
|
if (mime)
|
|
63
63
|
ctx.type = mime;
|
|
@@ -20,6 +20,7 @@ const serveGuiFiles_1 = require("./serveGuiFiles");
|
|
|
20
20
|
const koa_mount_1 = __importDefault(require("koa-mount"));
|
|
21
21
|
const listen_1 = require("./listen");
|
|
22
22
|
const misc_1 = require("./misc");
|
|
23
|
+
const basicWeb_1 = require("./basicWeb");
|
|
23
24
|
const serveFrontendFiles = (0, serveGuiFiles_1.serveGuiFiles)(process.env.FRONTEND_PROXY, cross_const_1.FRONTEND_URI);
|
|
24
25
|
const serveFrontendPrefixed = (0, koa_mount_1.default)(cross_const_1.FRONTEND_URI.slice(0, -1), serveFrontendFiles);
|
|
25
26
|
const serveAdminFiles = (0, serveGuiFiles_1.serveGuiFiles)(process.env.ADMIN_PROXY, cross_const_1.ADMIN_URI);
|
|
@@ -106,6 +107,8 @@ const serveGuiAndSharedFiles = async (ctx, next) => {
|
|
|
106
107
|
return serveFrontendFiles(ctx, next);
|
|
107
108
|
}
|
|
108
109
|
ctx.set({ server: `HFS ${const_1.VERSION} ${const_1.BUILD_TIMESTAMP}` });
|
|
110
|
+
if ((0, basicWeb_1.basicWeb)(ctx, node))
|
|
111
|
+
return;
|
|
109
112
|
return get === 'zip' ? (0, zip_1.zipStreamFromFolder)(node, ctx)
|
|
110
113
|
: get === 'list' ? sendFolderList(node, ctx)
|
|
111
114
|
: serveFrontendFiles(ctx, next);
|
package/src/serveGuiFiles.js
CHANGED
|
@@ -107,7 +107,7 @@ async function treatIndex(ctx, filesUri, body) {
|
|
|
107
107
|
const timestamp = await getFaviconTimestamp();
|
|
108
108
|
const lang = await (0, lang_1.getLangData)(ctx);
|
|
109
109
|
return body
|
|
110
|
-
.replace(/((?:src|href) *= *['"])\/?(?!([a-z]+:\/)?\/)/g, '$1' + ctx.state.revProxyPath + filesUri)
|
|
110
|
+
.replace(/((?:src|href) *= *['"])\/?(?!([a-z]+:\/)?\/)(?!\?)/g, '$1' + ctx.state.revProxyPath + filesUri)
|
|
111
111
|
.replace(/<(\/)?(head|body)>/g, (all, isClose, name) => {
|
|
112
112
|
const isHead = name === 'head';
|
|
113
113
|
const isBody = !isHead;
|