hfs 0.56.0 → 0.57.0-beta2
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-DlA4sSmp.js → index-Cl7PJ7_4.js} +263 -263
- package/admin/assets/{sha512--f9T-TYW.js → sha512-DwXzavpM.js} +1 -1
- package/admin/index.html +14 -2
- package/frontend/assets/index-legacy-0ZDBWQI9.js +50 -0
- package/frontend/assets/{sha512-legacy-CX3vTVvC.js → sha512-legacy-slBG5k4n.js} +1 -1
- package/frontend/index.html +1 -1
- package/package.json +2 -2
- package/plugins/antibrute/plugin.js +25 -27
- package/src/SendList.js +2 -2
- package/src/acme.js +1 -2
- package/src/adminApis.js +1 -0
- package/src/api.accounts.js +3 -0
- package/src/api.auth.js +27 -4
- package/src/api.get_file_list.js +2 -6
- package/src/api.log.js +9 -4
- package/src/api.monitor.js +1 -1
- package/src/api.plugins.js +13 -0
- package/src/apiMiddleware.js +1 -1
- package/src/auth.js +17 -1
- package/src/comments.js +31 -8
- package/src/config.js +2 -0
- package/src/connections.js +16 -5
- package/src/const.js +4 -4
- package/src/cross-const.js +2 -1
- package/src/cross.js +13 -3
- package/src/customHtml.js +4 -2
- package/src/events.js +7 -5
- package/src/fileAttr.js +10 -5
- package/src/frontEndApis.js +0 -12
- package/src/geo.js +1 -0
- package/src/langs/hfs-lang-ar.json +4 -1
- package/src/langs/hfs-lang-de.json +4 -1
- package/src/langs/hfs-lang-el.json +4 -1
- package/src/langs/hfs-lang-es.json +4 -1
- package/src/langs/hfs-lang-fi.json +4 -1
- package/src/langs/hfs-lang-fr.json +4 -1
- package/src/langs/hfs-lang-hu.json +4 -1
- package/src/langs/hfs-lang-it.json +4 -1
- package/src/langs/hfs-lang-ja.json +4 -1
- package/src/langs/hfs-lang-ko.json +4 -1
- package/src/langs/hfs-lang-ms.json +4 -1
- package/src/langs/hfs-lang-nl.json +4 -1
- package/src/langs/hfs-lang-pt-br.json +4 -1
- package/src/langs/hfs-lang-ro.json +4 -1
- package/src/langs/hfs-lang-ru.json +16 -13
- package/src/langs/hfs-lang-sr.json +4 -1
- package/src/langs/hfs-lang-th.json +4 -1
- package/src/langs/hfs-lang-tr.json +7 -1
- package/src/langs/hfs-lang-uk.json +4 -1
- package/src/langs/hfs-lang-vi.json +8 -5
- package/src/langs/hfs-lang-zh-tw.json +4 -1
- package/src/langs/hfs-lang-zh.json +4 -1
- package/src/listen.js +3 -2
- package/src/log.js +10 -3
- package/src/middlewares.js +7 -23
- package/src/misc.js +6 -35
- package/src/perm.js +5 -3
- package/src/plugins.js +44 -4
- package/src/roots.js +1 -3
- package/src/serveGuiAndSharedFiles.js +18 -10
- package/src/serveGuiFiles.js +2 -4
- package/src/throttler.js +3 -2
- package/src/update.js +1 -1
- package/src/upload.js +1 -1
- package/src/vfs.js +1 -1
- package/README.md +0 -177
- package/frontend/assets/index-legacy-3T51dA5w.js +0 -50
package/src/const.js
CHANGED
|
@@ -39,7 +39,7 @@ const path_1 = require("path");
|
|
|
39
39
|
const cross_1 = require("./cross");
|
|
40
40
|
const argv_1 = require("./argv");
|
|
41
41
|
__exportStar(require("./cross-const"), exports);
|
|
42
|
-
exports.API_VERSION =
|
|
42
|
+
exports.API_VERSION = 12;
|
|
43
43
|
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
|
|
44
44
|
// you can add arguments with this file, currently used for the update process on mac/linux
|
|
45
45
|
exports.ARGS_FILE = (0, path_1.join)((0, os_1.homedir)(), 'hfs-args');
|
|
@@ -50,11 +50,11 @@ try {
|
|
|
50
50
|
fs.unlinkSync(exports.ARGS_FILE);
|
|
51
51
|
}
|
|
52
52
|
catch (_a) { }
|
|
53
|
-
exports.DEV = process.env.DEV
|
|
53
|
+
exports.DEV = process.env.DEV ? 'DEV' : '';
|
|
54
54
|
exports.ORIGINAL_CWD = process.cwd();
|
|
55
55
|
exports.HFS_STARTED = new Date();
|
|
56
56
|
const PKG_PATH = (0, path_1.join)(__dirname, '..', 'package.json');
|
|
57
|
-
exports.BUILD_TIMESTAMP = "2025-
|
|
57
|
+
exports.BUILD_TIMESTAMP = "2025-03-07T14:08:28.038Z";
|
|
58
58
|
const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'));
|
|
59
59
|
exports.VERSION = pkg.version;
|
|
60
60
|
exports.RUNNING_BETA = exports.VERSION.includes('-');
|
|
@@ -68,7 +68,7 @@ exports.CONFIG_FILE = 'config.yaml';
|
|
|
68
68
|
// we want this to be the first stuff to be printed, then we print it in this module, that is executed at the beginning
|
|
69
69
|
if (exports.DEV)
|
|
70
70
|
console.clear();
|
|
71
|
-
else
|
|
71
|
+
else if (!argv_1.argv.debug)
|
|
72
72
|
console.debug = () => { };
|
|
73
73
|
console.log(`HFS ~ HTTP File Server`);
|
|
74
74
|
console.log(`© Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt`);
|
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_SERVICE_UNAVAILABLE = exports.HTTP_SERVER_ERROR = exports.HTTP_TOO_MANY_REQUESTS = exports.HTTP_FAILED_DEPENDENCY = exports.HTTP_FOOL = exports.HTTP_RANGE_NOT_SATISFIABLE = exports.HTTP_PAYLOAD_TOO_LARGE = exports.HTTP_PRECONDITION_FAILED = 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_OK = exports.PREVIOUS_TAG = exports.UPLOAD_REQUEST_STATUS = exports.UPLOAD_RESUMABLE_HASH = exports.UPLOAD_RESUMABLE = 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_FOOL = exports.HTTP_RANGE_NOT_SATISFIABLE = exports.HTTP_PAYLOAD_TOO_LARGE = exports.HTTP_PRECONDITION_FAILED = 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_OK = exports.PREVIOUS_TAG = exports.UPLOAD_REQUEST_STATUS = exports.UPLOAD_RESUMABLE_HASH = exports.UPLOAD_RESUMABLE = 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/';
|
|
@@ -36,6 +36,7 @@ exports.HTTP_FAILED_DEPENDENCY = 424;
|
|
|
36
36
|
exports.HTTP_TOO_MANY_REQUESTS = 429;
|
|
37
37
|
exports.HTTP_SERVER_ERROR = 500;
|
|
38
38
|
exports.HTTP_SERVICE_UNAVAILABLE = 503;
|
|
39
|
+
exports.HTTP_INSUFFICIENT_STORAGE = 507;
|
|
39
40
|
exports.HTTP_MESSAGES = {
|
|
40
41
|
[exports.HTTP_UNAUTHORIZED]: "Unauthorized",
|
|
41
42
|
[exports.HTTP_FORBIDDEN]: "Forbidden",
|
package/src/cross.js
CHANGED
|
@@ -18,7 +18,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
20
|
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.stringAfter = exports.splitAt = exports.strinsert = exports.removeStarting = exports.enforceStarting = exports.enforceFinal = exports.objFromKeys = 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 = exports.WEBSITE = void 0;
|
|
21
|
-
exports.shortenAgent = exports.popKey = exports.safeDecodeURIComponent = exports.callable = 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.normalizeHost = exports.xlate = exports.isEqualLax = exports.isTimestampString = exports.isWindowsDrive = exports.isIP = exports.isPrimitive = exports.isNumeric = exports.formatDate = exports.formatTime = exports.formatTimestamp = exports.repeat = exports.asyncGeneratorToArray = exports.filterMapGenerator = exports.throw_ = exports.hasProp = exports.typedEntries = exports.typedKeys = exports.objRenameKey = exports.randomId = exports.getOrSet = void 0;
|
|
21
|
+
exports.shortenAgent = exports.patchKey = exports.popKey = exports.safeDecodeURIComponent = exports.callable = 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.normalizeHost = exports.xlate = exports.isEqualLax = exports.isTimestampString = exports.isWindowsDrive = exports.isIP = exports.isPrimitive = exports.isNumeric = exports.formatDate = exports.formatTime = exports.formatTimestamp = exports.repeat = exports.asyncGeneratorToArray = exports.filterMapGenerator = exports.throw_ = exports.hasProp = exports.typedEntries = exports.typedKeys = exports.objRenameKey = exports.randomId = exports.getOrSet = 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"));
|
|
@@ -46,10 +46,12 @@ exports.FRONTEND_OPTIONS = {
|
|
|
46
46
|
};
|
|
47
47
|
exports.SORT_BY_OPTIONS = ['name', 'extension', 'size', 'time', 'creation'];
|
|
48
48
|
exports.THEME_OPTIONS = { auto: '', light: 'light', dark: 'dark' };
|
|
49
|
+
// had found an interesting way to infer a type from all the calls to defineConfig (by the literals passed), but would not be usable also by admin-panel
|
|
49
50
|
exports.CFG = constMap(['geo_enable', 'geo_allow', 'geo_list', 'geo_allow_unknown', 'dynamic_dns_url',
|
|
50
51
|
'log', 'error_log', 'log_rotation', 'dont_log_net', 'log_gui', 'log_api', 'log_ua', 'log_spam', 'track_ips',
|
|
51
52
|
'max_downloads', 'max_downloads_per_ip', 'max_downloads_per_account', 'roots', 'force_address', 'split_uploads',
|
|
52
|
-
'allow_session_ip_change', 'force_lang', 'suspend_plugins', 'base_url', 'size_1024'
|
|
53
|
+
'allow_session_ip_change', 'force_lang', 'suspend_plugins', 'base_url', 'size_1024', 'disable_custom_html',
|
|
54
|
+
'comments_storage']);
|
|
53
55
|
exports.LIST = { add: '+', remove: '-', update: '=', props: 'props', ready: 'ready', error: 'e' };
|
|
54
56
|
exports.WHO_ANYONE = true;
|
|
55
57
|
exports.WHO_NO_ONE = false;
|
|
@@ -450,8 +452,11 @@ function makeMatcher(mask, emptyMaskReturns = false) {
|
|
|
450
452
|
: () => emptyMaskReturns;
|
|
451
453
|
}
|
|
452
454
|
exports.makeMatcher = makeMatcher;
|
|
455
|
+
// this is caching all matchers, so don't use it with frequently changing masks. Benchmarks revealed that _.memoize make it slower than not using it, while this simple cache can speed up to 30x
|
|
453
456
|
function matches(s, mask, emptyMaskReturns = false) {
|
|
454
|
-
|
|
457
|
+
var _a, _b;
|
|
458
|
+
const cache = (_a = matches).cache || (_a.cache = {});
|
|
459
|
+
return (cache[_b = mask + (emptyMaskReturns ? '1' : '0')] || (cache[_b] = makeMatcher(mask, emptyMaskReturns)))(s);
|
|
455
460
|
}
|
|
456
461
|
exports.matches = matches;
|
|
457
462
|
// if delimiter is specified, it is prefixed to symbols. If it contains a space, the part after the space is considered as suffix.
|
|
@@ -500,6 +505,11 @@ function popKey(o, k) {
|
|
|
500
505
|
return x;
|
|
501
506
|
}
|
|
502
507
|
exports.popKey = popKey;
|
|
508
|
+
function patchKey(o, k, replacer) {
|
|
509
|
+
o[k] = replacer(o[k]);
|
|
510
|
+
return o;
|
|
511
|
+
}
|
|
512
|
+
exports.patchKey = patchKey;
|
|
503
513
|
function shortenAgent(agent) {
|
|
504
514
|
var _a;
|
|
505
515
|
return lodash_1.default.findKey(BROWSERS, re => re.test(agent))
|
package/src/customHtml.js
CHANGED
|
@@ -3,9 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.saveCustomHtml = exports.getAllSections = exports.getSection = exports.watchLoadCustomHtml = exports.customHtml = exports.customHtmlSections = void 0;
|
|
6
|
+
exports.saveCustomHtml = exports.getAllSections = exports.getSection = exports.watchLoadCustomHtml = exports.disableCustomHtml = exports.customHtml = exports.customHtmlSections = void 0;
|
|
7
7
|
const misc_1 = require("./misc");
|
|
8
8
|
const watchLoad_1 = require("./watchLoad");
|
|
9
|
+
const config_1 = require("./config");
|
|
9
10
|
const promises_1 = require("fs/promises");
|
|
10
11
|
const plugins_1 = require("./plugins");
|
|
11
12
|
const lodash_1 = __importDefault(require("lodash"));
|
|
@@ -13,6 +14,7 @@ const FILE = 'custom.html';
|
|
|
13
14
|
exports.customHtmlSections = ['style', 'script', 'beforeHeader', 'afterHeader', 'afterMenuBar', 'afterList',
|
|
14
15
|
'footer', 'top', 'bottom', 'afterEntryName', 'beforeLogin', 'unauthorized', 'htmlHead', 'userPanelAfterInfo'];
|
|
15
16
|
exports.customHtml = watchLoadCustomHtml();
|
|
17
|
+
exports.disableCustomHtml = (0, config_1.defineConfig)(misc_1.CFG.disable_custom_html, false);
|
|
16
18
|
function watchLoadCustomHtml(folder = '') {
|
|
17
19
|
const sections = new Map();
|
|
18
20
|
const res = (0, watchLoad_1.watchLoad)((0, misc_1.prefix)('', folder, '/') + FILE, data => {
|
|
@@ -35,7 +37,7 @@ function watchLoadCustomHtml(folder = '') {
|
|
|
35
37
|
}
|
|
36
38
|
exports.watchLoadCustomHtml = watchLoadCustomHtml;
|
|
37
39
|
function getSection(name) {
|
|
38
|
-
return (exports.customHtml.sections.get(name) || '')
|
|
40
|
+
return (!exports.disableCustomHtml.get() && exports.customHtml.sections.get(name) || '')
|
|
39
41
|
+ (0, plugins_1.mapPlugins)(pl => pl.getData().getCustomHtml()[name]).join('\n');
|
|
40
42
|
}
|
|
41
43
|
exports.getSection = getSection;
|
package/src/events.js
CHANGED
|
@@ -19,7 +19,7 @@ class BetterEventEmitter {
|
|
|
19
19
|
cbs.add(listener);
|
|
20
20
|
if (cbs.size > warnAfter)
|
|
21
21
|
console.warn("Warning: many event listeners for ", e);
|
|
22
|
-
this.emit(e + LISTENERS_SUFFIX, cbs);
|
|
22
|
+
this.emit(e + LISTENERS_SUFFIX, cbs, listener);
|
|
23
23
|
}
|
|
24
24
|
if (callNow)
|
|
25
25
|
try {
|
|
@@ -41,13 +41,15 @@ class BetterEventEmitter {
|
|
|
41
41
|
return this.on(event + LISTENERS_SUFFIX, listener);
|
|
42
42
|
}
|
|
43
43
|
once(event, listener) {
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
let off;
|
|
45
|
+
const pro = new Promise(resolve => {
|
|
46
|
+
off = this.on(event, function (...args) {
|
|
46
47
|
off();
|
|
47
|
-
resolve(args);
|
|
48
|
-
return listener === null || listener === void 0 ? void 0 : listener(...
|
|
48
|
+
resolve(args.slice(0, -1)); // remove the extra argument at the end of our emit()
|
|
49
|
+
return listener === null || listener === void 0 ? void 0 : listener(...args);
|
|
49
50
|
});
|
|
50
51
|
});
|
|
52
|
+
return Object.assign(off, { then: pro.then.bind(pro) });
|
|
51
53
|
}
|
|
52
54
|
multi(map) {
|
|
53
55
|
const cbs = Object.entries(map).map(([name, cb]) => this.on(name.split(' '), cb));
|
package/src/fileAttr.js
CHANGED
|
@@ -19,17 +19,22 @@ const FN = 'file-attr.kv';
|
|
|
19
19
|
if ((0, fs_1.existsSync)(FN))
|
|
20
20
|
fileAttrDb.open(FN);
|
|
21
21
|
const FILE_ATTR_PREFIX = 'user.hfs.'; // user. prefix to be linux compatible
|
|
22
|
+
/* @param v must be JSON-able or undefined */
|
|
22
23
|
async function storeFileAttr(path, k, v) {
|
|
23
24
|
var _a, _b;
|
|
24
|
-
const s = await (0, promises_2.stat)(path);
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
const s = await (0, promises_2.stat)(path).catch(() => null);
|
|
26
|
+
// since we don't have fsx.remove, we simulate it with an empty string
|
|
27
|
+
if (await (fsx === null || fsx === void 0 ? void 0 : fsx.set(path, FILE_ATTR_PREFIX + k, v === undefined ? '' : JSON.stringify(v)).then(() => 1, () => 0))) {
|
|
28
|
+
if (s && const_1.IS_WINDOWS)
|
|
27
29
|
(0, promises_2.utimes)(path, s.atime, s.mtime); // restore timestamps, necessary only on Windows
|
|
28
30
|
return true;
|
|
29
31
|
}
|
|
30
32
|
// fallback to our kv-storage
|
|
31
33
|
if (!fileAttrDb.isOpen())
|
|
32
|
-
|
|
34
|
+
if (!s && !v)
|
|
35
|
+
return; // file was probably deleted, and we were asked to remove a possible attribute, but there's no fileAttrDb, so we are done, don't create the db file for nothing
|
|
36
|
+
else
|
|
37
|
+
await fileAttrDb.open(FN);
|
|
33
38
|
// pipe should be a safe separator
|
|
34
39
|
return (_b = await ((_a = fileAttrDb.put(`${path}|${k}`, v)) === null || _a === void 0 ? void 0 : _a.catch((e) => {
|
|
35
40
|
console.error("couldn't store metadata on", path, String(e.message || e));
|
|
@@ -39,7 +44,7 @@ async function storeFileAttr(path, k, v) {
|
|
|
39
44
|
exports.storeFileAttr = storeFileAttr;
|
|
40
45
|
async function loadFileAttr(path, k) {
|
|
41
46
|
var _a;
|
|
42
|
-
return (_a = await (fsx === null || fsx === void 0 ? void 0 : fsx.get(path, FILE_ATTR_PREFIX + k).then((x) => x
|
|
47
|
+
return (_a = await (fsx === null || fsx === void 0 ? void 0 : fsx.get(path, FILE_ATTR_PREFIX + k).then((x) => x === '' ? undefined : (0, cross_1.tryJson)(String(x)), () => fileAttrDb.isOpen() ? fileAttrDb.get(`${path}|${k}`) : null))) !== null && _a !== void 0 ? _a : undefined; // normalize, as we get null instead of undefined on windows
|
|
43
48
|
}
|
|
44
49
|
exports.loadFileAttr = loadFileAttr;
|
|
45
50
|
async function purgeFileAttr() {
|
package/src/frontEndApis.js
CHANGED
|
@@ -97,18 +97,6 @@ exports.frontEndApis = {
|
|
|
97
97
|
return new apiMiddleware_1.ApiError(e.code === 'EEXIST' ? const_1.HTTP_CONFLICT : const_1.HTTP_BAD_REQUEST, e);
|
|
98
98
|
}
|
|
99
99
|
},
|
|
100
|
-
async delete({ uri }, ctx) {
|
|
101
|
-
(0, misc_1.apiAssertTypes)({ string: { uri } });
|
|
102
|
-
const node = await (0, vfs_1.urlToNode)(uri, ctx);
|
|
103
|
-
if (!node)
|
|
104
|
-
throw new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND);
|
|
105
|
-
const res = await (0, misc_1.deleteNode)(ctx, node, uri);
|
|
106
|
-
if (typeof res === 'number')
|
|
107
|
-
throw new apiMiddleware_1.ApiError(res);
|
|
108
|
-
if (res instanceof Error)
|
|
109
|
-
throw new apiMiddleware_1.ApiError(const_1.HTTP_SERVER_ERROR, res);
|
|
110
|
-
return res && {};
|
|
111
|
-
},
|
|
112
100
|
async rename({ uri, dest }, ctx) {
|
|
113
101
|
(0, misc_1.apiAssertTypes)({ string: { uri, dest } });
|
|
114
102
|
ctx.logExtra(null, { target: decodeURI(uri), destination: decodeURI(dest) });
|
package/src/geo.js
CHANGED
|
@@ -17,6 +17,7 @@ const list = (0, config_1.defineConfig)(misc_1.CFG.geo_list, []);
|
|
|
17
17
|
const allowUnknown = (0, config_1.defineConfig)(misc_1.CFG.geo_allow_unknown, false);
|
|
18
18
|
enabled.sub(checkFiles);
|
|
19
19
|
setInterval(checkFiles, misc_1.DAY); // keep updated at run-time
|
|
20
|
+
// benchmark: memoize can make this 44x faster
|
|
20
21
|
exports.ip2country = lodash_1.default.memoize((ip) => ip2location.getCountryShortAsync(ip).then(v => v === '-' ? '' : v, () => ''));
|
|
21
22
|
const geoFilter = async (ctx, next) => {
|
|
22
23
|
var _a;
|
|
@@ -171,6 +171,9 @@
|
|
|
171
171
|
"creation": "إنشاء",
|
|
172
172
|
"required_change_password": "يجب عليك تغيير كلمة المرور الخاصة بك",
|
|
173
173
|
"Wildcards": "أحرف البدل",
|
|
174
|
-
"Considering resume": "جارٍ التحقق من استئناف الرفع"
|
|
174
|
+
"Considering resume": "جارٍ التحقق من استئناف الرفع",
|
|
175
|
+
"Yes": "نعم",
|
|
176
|
+
"No": "لا",
|
|
177
|
+
"esc_again": "انقر على ESC ثانية لاغلاق"
|
|
175
178
|
}
|
|
176
179
|
}
|
|
@@ -171,6 +171,9 @@
|
|
|
171
171
|
"creation": "Erstellung",
|
|
172
172
|
"required_change_password": "Sie müssen Ihr Passwort ändern.",
|
|
173
173
|
"Wildcards": "Platzhalter",
|
|
174
|
-
"Considering resume": "Prüfe Fortsetzen des Uploads"
|
|
174
|
+
"Considering resume": "Prüfe Fortsetzen des Uploads",
|
|
175
|
+
"Yes": "Ja",
|
|
176
|
+
"No": "Nein",
|
|
177
|
+
"esc_again": "Drucken Sie ESC zwei Mal, um das Fenster zu schließen."
|
|
175
178
|
}
|
|
176
179
|
}
|
|
@@ -171,6 +171,9 @@
|
|
|
171
171
|
"creation": "δημιουργία",
|
|
172
172
|
"required_change_password": "Πρέπει να αλλάξετε τον κωδικό πρόσβασής σας",
|
|
173
173
|
"Wildcards": "Χαρακτήρες μπαλαντέρ",
|
|
174
|
-
"Considering resume": "Εξέταση συνέχισης μεταφόρτωσης"
|
|
174
|
+
"Considering resume": "Εξέταση συνέχισης μεταφόρτωσης",
|
|
175
|
+
"Yes": "Ναι",
|
|
176
|
+
"No": "Οχι",
|
|
177
|
+
"esc_again": "Πατήστε ESC δυο φορές για να κλειστειτε"
|
|
175
178
|
}
|
|
176
179
|
}
|
|
@@ -175,6 +175,9 @@
|
|
|
175
175
|
"creation": "creación",
|
|
176
176
|
"required_change_password": "Debe cambiar su contraseña",
|
|
177
177
|
"Wildcards": "Comodines",
|
|
178
|
-
"Considering resume": "Considerando reanudar"
|
|
178
|
+
"Considering resume": "Considerando reanudar",
|
|
179
|
+
"Yes": "Si",
|
|
180
|
+
"No": "No",
|
|
181
|
+
"esc_again": "Presione ESC dos veces para cerrar"
|
|
179
182
|
}
|
|
180
183
|
}
|
|
@@ -175,6 +175,9 @@
|
|
|
175
175
|
"creation": "luonti",
|
|
176
176
|
"required_change_password": "Sinun täytyy vaihtaa salasanasi",
|
|
177
177
|
"Wildcards": "Villimerkit",
|
|
178
|
-
"Considering resume": "Yritetään jatkaa"
|
|
178
|
+
"Considering resume": "Yritetään jatkaa",
|
|
179
|
+
"Yes": "Kyllä",
|
|
180
|
+
"No": "Ei",
|
|
181
|
+
"esc_again": "Paina ESC kaksi kertaa sulkea"
|
|
179
182
|
}
|
|
180
183
|
}
|
|
@@ -175,6 +175,9 @@
|
|
|
175
175
|
"creation": "création",
|
|
176
176
|
"required_change_password": "Vous devez changer votre mot de passe",
|
|
177
177
|
"Wildcards": "Caractères génériques",
|
|
178
|
-
"Considering resume": "Reprise en cours d'analyse"
|
|
178
|
+
"Considering resume": "Reprise en cours d'analyse",
|
|
179
|
+
"Yes": "Oui",
|
|
180
|
+
"No": "Non",
|
|
181
|
+
"esc_again": "Appuyez ESC deux fois pour fermer"
|
|
179
182
|
}
|
|
180
183
|
}
|
|
@@ -175,6 +175,9 @@
|
|
|
175
175
|
"creation": "létrehozás",
|
|
176
176
|
"required_change_password": "Meg kell változtatnia a jelszavát",
|
|
177
177
|
"Wildcards": "Helyettesítő karakterek",
|
|
178
|
-
"Considering resume": "Feltöltés folytatásának ellenőrzése"
|
|
178
|
+
"Considering resume": "Feltöltés folytatásának ellenőrzése",
|
|
179
|
+
"Yes": "Igen",
|
|
180
|
+
"No": "Nem",
|
|
181
|
+
"esc_again": "ESC megadva 2 alkalommal"
|
|
179
182
|
}
|
|
180
183
|
}
|
|
@@ -162,6 +162,9 @@
|
|
|
162
162
|
"creation": "creazione",
|
|
163
163
|
"required_change_password": "È necessario cambiare la password",
|
|
164
164
|
"Wildcards": "Caratteri jolly",
|
|
165
|
-
"Considering resume": "Ripristino upload"
|
|
165
|
+
"Considering resume": "Ripristino upload",
|
|
166
|
+
"Yes": "Sì",
|
|
167
|
+
"No": "No",
|
|
168
|
+
"esc_again": "Premi ESC due volte per chiudere"
|
|
166
169
|
}
|
|
167
170
|
}
|
|
@@ -171,6 +171,9 @@
|
|
|
171
171
|
"creation": "作成日時",
|
|
172
172
|
"required_change_password": "パスワードを変更する必要があります",
|
|
173
173
|
"Wildcards": "ワイルドカード",
|
|
174
|
-
"Considering resume": "アップロード再開の確認中"
|
|
174
|
+
"Considering resume": "アップロード再開の確認中",
|
|
175
|
+
"Yes": "はい",
|
|
176
|
+
"No": "いいえ",
|
|
177
|
+
"esc_again": "ESCを2回押して閉じます"
|
|
175
178
|
}
|
|
176
179
|
}
|
|
@@ -171,6 +171,9 @@
|
|
|
171
171
|
"creation": "생성일",
|
|
172
172
|
"required_change_password": "비밀번호를 변경해야 합니다.",
|
|
173
173
|
"Wildcards": "와일드카드",
|
|
174
|
-
"Considering resume": "업로드 재개 여부 확인 중"
|
|
174
|
+
"Considering resume": "업로드 재개 여부 확인 중",
|
|
175
|
+
"Yes": "영",
|
|
176
|
+
"No": "안",
|
|
177
|
+
"esc_again": "ESC 두번 페스하기"
|
|
175
178
|
}
|
|
176
179
|
}
|
|
@@ -135,6 +135,9 @@
|
|
|
135
135
|
"creation": "penciptaan",
|
|
136
136
|
"required_change_password": "Anda perlu menukar kata laluan anda",
|
|
137
137
|
"Wildcards": "Kad bebas",
|
|
138
|
-
"Considering resume": "Mempertimbangkan sambungan semula"
|
|
138
|
+
"Considering resume": "Mempertimbangkan sambungan semula",
|
|
139
|
+
"Yes": "Ya",
|
|
140
|
+
"No": "Tidak",
|
|
141
|
+
"esc_again": "Tekan ESC dua kali untuk menutup"
|
|
139
142
|
}
|
|
140
143
|
}
|
|
@@ -170,6 +170,9 @@
|
|
|
170
170
|
"creation": "gecreëerd",
|
|
171
171
|
"required_change_password": "U bent verplicht Uw password te veranderen",
|
|
172
172
|
"Wildcards": "Wildcards",
|
|
173
|
-
"Considering resume": "Overweeg hervatten"
|
|
173
|
+
"Considering resume": "Overweeg hervatten",
|
|
174
|
+
"Yes": "Ja",
|
|
175
|
+
"No": "Nee",
|
|
176
|
+
"esc_again": "Druk ESC twee keer om te sluiten"
|
|
174
177
|
}
|
|
175
178
|
}
|
|
@@ -170,6 +170,9 @@
|
|
|
170
170
|
"creation": "criação",
|
|
171
171
|
"required_change_password": "Você precisa alterar sua senha",
|
|
172
172
|
"Wildcards": "Curingas",
|
|
173
|
-
"Considering resume": "Considerando retomar"
|
|
173
|
+
"Considering resume": "Considerando retomar",
|
|
174
|
+
"Yes": "Sim",
|
|
175
|
+
"No": "Nao",
|
|
176
|
+
"esc_again": "Pressione ESC duas vezes para fechar"
|
|
174
177
|
}
|
|
175
178
|
}
|
|
@@ -171,6 +171,9 @@
|
|
|
171
171
|
"creation": "creare",
|
|
172
172
|
"required_change_password": "Trebuie să-ți schimbi parola",
|
|
173
173
|
"Wildcards": "Metacaractere",
|
|
174
|
-
"Considering resume": "Se încearcă reluarea"
|
|
174
|
+
"Considering resume": "Se încearcă reluarea",
|
|
175
|
+
"Yes": "Da",
|
|
176
|
+
"No": "Nu",
|
|
177
|
+
"esc_again": "Apasa ESC de doua ori pentru a inchide"
|
|
175
178
|
}
|
|
176
179
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "Mefistofell, SanokKule, ItsNeverLight",
|
|
3
|
-
"version": 2.
|
|
3
|
+
"version": 2.71,
|
|
4
4
|
"hfs_version": "0.56.0",
|
|
5
5
|
"translate": {
|
|
6
6
|
"Select": "Выбор",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"filter_count": "{n,plural, one{# элемент} few{# элемента} many{# элементов}}",
|
|
10
10
|
"select_count": "{n,plural, one{Выбран #} other{Выбрано #}}",
|
|
11
11
|
"filter_placeholder": "Введите текст для фильтрации списка",
|
|
12
|
-
"Select some files": "
|
|
13
|
-
"zip_checkboxes": "
|
|
12
|
+
"Select some files": "Выбрать файлы",
|
|
13
|
+
"zip_checkboxes": "Выберите нужные файлы и снова нажмите zip",
|
|
14
14
|
"zip_tooltip_selected": "Скачать выбранные элементы в zip-архиве",
|
|
15
15
|
"zip_tooltip_whole": "Выбрать файлы для скачивания в zip-архиве. Если файлы не выбраны, то будет скачана вся папка",
|
|
16
16
|
"zip_confirm_search": "Скачать все результаты поиска в одном zip-архиве",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"delete_confirm": "Удалить {n,plural, one{# элемент} few{# элемента} many{# элементов}}?",
|
|
21
21
|
"delete_completed": "{n,plural, one{Удалён} other{Удалено}} {n,plural, one{# элемент} few{# элемента} many{# элементов}}",
|
|
22
22
|
"delete_failed": ", {n} неуспешно",
|
|
23
|
-
"delete_select": "
|
|
23
|
+
"delete_select": "Выберите элементы для удаления",
|
|
24
24
|
"Delete": "Удалить",
|
|
25
25
|
"Options": "Настройки",
|
|
26
26
|
"Search": "Поиск",
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
"Tiles mode:": "Плитки:",
|
|
113
113
|
"off": "выключено",
|
|
114
114
|
"Operation successful": "Операция успешна",
|
|
115
|
-
"Uploader": "
|
|
115
|
+
"Uploader": "Загружено",
|
|
116
116
|
"Download counter": "Счётчик загрузок",
|
|
117
117
|
"Switch zoom mode": "Переключить увеличение",
|
|
118
118
|
"Full screen": "Полный экран",
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"showHelp_↑/↓": "↑/↓",
|
|
123
123
|
"showHelp_space": "пробел",
|
|
124
124
|
"showHelp_←/→_body": "предыдущий/следующий файл",
|
|
125
|
-
"showHelp_↑/↓_body": "прокрутка
|
|
125
|
+
"showHelp_↑/↓_body": "прокрутка по высоте",
|
|
126
126
|
"showHelp_space_body": "выбрать файл",
|
|
127
127
|
"showHelp_D_body": "скачать",
|
|
128
128
|
"showHelp_Z_body": "переключение увеличения",
|
|
@@ -137,16 +137,16 @@
|
|
|
137
137
|
"n_items": "{n,plural, one{# элемент} few{# элемента} many{# элементов}}",
|
|
138
138
|
"good_bad": "{good} {good,plural, one{перемещён} other{перемещено}}, {bad} неуспешно",
|
|
139
139
|
"after_cut": "Выбранное скопировано в буфер обмена.\nПерейдите в папку назначения для вставки.",
|
|
140
|
-
"Cancel clipboard": "Отменить
|
|
141
|
-
"to_clipboard_source": "
|
|
140
|
+
"Cancel clipboard": "Отменить",
|
|
141
|
+
"to_clipboard_source": "Вернуться в исходную папку",
|
|
142
142
|
"Paste": "Вставить",
|
|
143
143
|
"clipboard_list": "Элементы в буфере обмена:",
|
|
144
144
|
"Close": "Закрыть",
|
|
145
145
|
"Folder": "Папка",
|
|
146
146
|
"Web page": "Веб адрес",
|
|
147
147
|
"Link": "Ссылка",
|
|
148
|
-
"Auto-play": "
|
|
149
|
-
"autoplay_seconds": "
|
|
148
|
+
"Auto-play": "Слайд-шоу",
|
|
149
|
+
"autoplay_seconds": "Время ожидания до следующего файла",
|
|
150
150
|
"Select all": "Выбрать всё",
|
|
151
151
|
"go_first": "К первому элементу",
|
|
152
152
|
"go_last": "К последнему элементу",
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
"Invalid value": "Недействительное значение",
|
|
157
157
|
"upload_skipped": "{n,plural, one{# пропущен} other{# пропущено}}",
|
|
158
158
|
"Overwrite policy": "Правило перезаписи",
|
|
159
|
-
"Rename to avoid overwriting": "Переименовать
|
|
159
|
+
"Rename to avoid overwriting": "Переименовать во избежание перезаписи",
|
|
160
160
|
"Overwrite existing files": "Перезаписать существующие файлы",
|
|
161
161
|
"Menu": "Меню",
|
|
162
162
|
"clipboard": "Буфер обмена ({content})",
|
|
@@ -169,12 +169,15 @@
|
|
|
169
169
|
"Cancel": "Отмена",
|
|
170
170
|
"allow_session_ip_change": "Разрешить смену IP в этой сессии",
|
|
171
171
|
"focus_hint": "Набирая текст на клавиатуре, вы можете выполнять поиск и выбирать элементы из списка.",
|
|
172
|
-
"copy_links": "
|
|
172
|
+
"copy_links": "Скопировать ссылки",
|
|
173
173
|
"Calculate": "Рассчитать",
|
|
174
174
|
"Creation": "Дата создания",
|
|
175
175
|
"creation": "созданию",
|
|
176
176
|
"required_change_password": "Вам необходимо изменить свой пароль",
|
|
177
177
|
"Wildcards": "Шаблоны",
|
|
178
|
-
"Considering resume": "Оценка возобновления"
|
|
178
|
+
"Considering resume": "Оценка возобновления",
|
|
179
|
+
"Yes": "Да",
|
|
180
|
+
"No": "Нет",
|
|
181
|
+
"esc_again": "Нажмите ESC дважды для закрытия"
|
|
179
182
|
}
|
|
180
183
|
}
|
|
@@ -174,6 +174,9 @@
|
|
|
174
174
|
"creation": "креирање",
|
|
175
175
|
"required_change_password": "Потребно је да промените лозинку",
|
|
176
176
|
"Wildcards": "Џокер знакови",
|
|
177
|
-
"Considering resume": "Разматрам наставак"
|
|
177
|
+
"Considering resume": "Разматрам наставак",
|
|
178
|
+
"Yes": "Да",
|
|
179
|
+
"No": "Не",
|
|
180
|
+
"esc_again": "Пritisnite ESC два пута за затварање"
|
|
178
181
|
}
|
|
179
182
|
}
|
|
@@ -171,6 +171,9 @@
|
|
|
171
171
|
"creation": "การสร้าง",
|
|
172
172
|
"required_change_password": "คุณจำเป็นต้องเปลี่ยนรหัสผ่านของคุณ",
|
|
173
173
|
"Wildcards": "อักขระตัวแทน",
|
|
174
|
-
"Considering resume": "กำลังพิจารณาดำเนินการต่อ"
|
|
174
|
+
"Considering resume": "กำลังพิจารณาดำเนินการต่อ",
|
|
175
|
+
"Yes": "ใช่",
|
|
176
|
+
"No": "ไม่",
|
|
177
|
+
"esc_again": "กด ESC สองครั้งเพื่อปิด"
|
|
175
178
|
}
|
|
176
179
|
}
|
|
@@ -168,6 +168,12 @@
|
|
|
168
168
|
"copy_links": "Bağlantıları kopyala",
|
|
169
169
|
"Calculate": "Hesapla",
|
|
170
170
|
"Creation": "Oluşturma",
|
|
171
|
-
"creation": "oluşturma"
|
|
171
|
+
"creation": "oluşturma",
|
|
172
|
+
"required_change_password": "Sifrenizi değiştirmeniz gerekiyor",
|
|
173
|
+
"Wildcards": "Metakarakterler",
|
|
174
|
+
"Considering resume": "Tekrarlama aranıyor",
|
|
175
|
+
"Yes": "Evet",
|
|
176
|
+
"No": "Hayır",
|
|
177
|
+
"esc_again": "ESC'i iki kere basarak kapat"
|
|
172
178
|
}
|
|
173
179
|
}
|
|
@@ -175,6 +175,9 @@
|
|
|
175
175
|
"creation": "створення",
|
|
176
176
|
"required_change_password": "Вам необхідно змінити пароль",
|
|
177
177
|
"Wildcards": "Шаблони",
|
|
178
|
-
"Considering resume": "Оцінка відновлення"
|
|
178
|
+
"Considering resume": "Оцінка відновлення",
|
|
179
|
+
"Yes": "Так",
|
|
180
|
+
"No": "Ні",
|
|
181
|
+
"esc_again": "Натисніть ESC два рази для закриття"
|
|
179
182
|
}
|
|
180
183
|
}
|
|
@@ -68,10 +68,10 @@
|
|
|
68
68
|
"enter_folder": "Tới folder",
|
|
69
69
|
"folder_exists": "Trùng tên folder!",
|
|
70
70
|
"Sort by": "Sắp xếp theo",
|
|
71
|
-
"name": "
|
|
72
|
-
"extension": "
|
|
73
|
-
"size": "
|
|
74
|
-
"time": "
|
|
71
|
+
"name": "tên",
|
|
72
|
+
"extension": "phần mở rộng",
|
|
73
|
+
"size": "kích cỡ",
|
|
74
|
+
"time": "thời gian",
|
|
75
75
|
"Invert order": "Đảo ngược thứ tự",
|
|
76
76
|
"Folders first": "Folder trước",
|
|
77
77
|
"Numeric names": "Tên số",
|
|
@@ -175,6 +175,9 @@
|
|
|
175
175
|
"creation": "ngày tạo",
|
|
176
176
|
"required_change_password": "Bạn được yêu cầu đổi ngay cái password",
|
|
177
177
|
"Wildcards": "Wildcards (nâng cao)",
|
|
178
|
-
"Considering resume": "Lỗi kết nối. Đang kết nối lại..."
|
|
178
|
+
"Considering resume": "Lỗi kết nối. Đang kết nối lại...",
|
|
179
|
+
"Yes": "Có",
|
|
180
|
+
"No": "Không",
|
|
181
|
+
"esc_again": "Nâng câp ESC bằng cách nâng câp"
|
|
179
182
|
}
|
|
180
183
|
}
|
package/src/listen.js
CHANGED
|
@@ -49,7 +49,7 @@ const persistence_1 = require("./persistence");
|
|
|
49
49
|
const argv_1 = require("./argv");
|
|
50
50
|
let httpSrv;
|
|
51
51
|
let httpsSrv;
|
|
52
|
-
const openBrowserAtStart = (0, config_1.defineConfig)('open_browser_at_start',
|
|
52
|
+
const openBrowserAtStart = (0, config_1.defineConfig)('open_browser_at_start', true);
|
|
53
53
|
exports.baseUrl = (0, config_1.defineConfig)(misc_1.CFG.base_url, '', x => { var _a; return (_a = /(?<=\/\/)[^\/]+/.exec(x)) === null || _a === void 0 ? void 0 : _a[0]; }); // compiled is host only
|
|
54
54
|
async function getBaseUrlOrDefault() {
|
|
55
55
|
return exports.baseUrl.get() || await nat_1.defaultBaseUrl.get();
|
|
@@ -121,7 +121,8 @@ const considerHttps = (0, misc_1.debounceAsync)(async () => {
|
|
|
121
121
|
nat_1.defaultBaseUrl.port = (_a = getCurrentPort(httpSrv)) !== null && _a !== void 0 ? _a : 0;
|
|
122
122
|
let port = exports.httpsPortCfg.get();
|
|
123
123
|
try {
|
|
124
|
-
|
|
124
|
+
const moreOptions = Object.assign({}, ...await events_1.default.emitAsync('httpsServerOptions') || []);
|
|
125
|
+
httpsSrv = Object.assign(https.createServer(port === const_1.PORT_DISABLED ? {} : { ...commonServerOptions, key: httpsOptions.private_key, cert: httpsOptions.cert, ...moreOptions }, index_1.app.callback()), { name: 'https' }, commonServerAssign);
|
|
125
126
|
if (port >= 0) {
|
|
126
127
|
const cert = getCertObject();
|
|
127
128
|
if (cert) {
|