hfs 0.46.1 → 0.47.0-alpha6

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.
Files changed (50) hide show
  1. package/README.md +4 -4
  2. package/admin/assets/{index-35f6e3dc.css → index-20dd43f3.css} +1 -1
  3. package/admin/assets/index-d55dfed9.js +518 -0
  4. package/{frontend/assets/sha512-d9635c9d.js → admin/assets/sha512-9867267f.js} +1 -1
  5. package/admin/index.html +2 -2
  6. package/frontend/assets/index-3a32a9b9.css +1 -0
  7. package/frontend/assets/index-ad78cbad.js +116 -0
  8. package/{admin/assets/sha512-3412b98f.js → frontend/assets/sha512-4c1cbf45.js} +1 -1
  9. package/frontend/fontello.css +5 -2
  10. package/frontend/fontello.woff2 +0 -0
  11. package/frontend/index.html +2 -3
  12. package/package.json +2 -2
  13. package/plugins/download-counter/plugin.js +15 -7
  14. package/plugins/download-counter/public/main.js +1 -1
  15. package/plugins/list-uploader/plugin.js +1 -1
  16. package/plugins/list-uploader/public/main.js +9 -10
  17. package/plugins/vhosting/plugin.js +5 -2
  18. package/src/QuickZipStream.js +3 -0
  19. package/src/adminApis.js +20 -5
  20. package/src/api.auth.js +0 -3
  21. package/src/api.file_list.js +3 -2
  22. package/src/api.monitor.js +36 -33
  23. package/src/api.vfs.js +37 -34
  24. package/src/apiMiddleware.js +44 -15
  25. package/src/commands.js +2 -2
  26. package/src/config.js +16 -13
  27. package/src/connections.js +3 -4
  28. package/src/consoleLog.js +17 -0
  29. package/src/const.js +4 -3
  30. package/src/frontEndApis.js +17 -10
  31. package/src/github.js +1 -1
  32. package/src/index.js +3 -1
  33. package/src/langs/embedded.js +3 -1
  34. package/src/langs/hfs-lang-es.json +118 -0
  35. package/src/langs/hfs-lang-it.json +7 -5
  36. package/src/langs/hfs-lang-nl.json +118 -0
  37. package/src/langs/hfs-lang-ru.json +3 -3
  38. package/src/langs/hfs-lang-zh.json +25 -5
  39. package/src/log.js +5 -3
  40. package/src/middlewares.js +2 -2
  41. package/src/misc.js +5 -1
  42. package/src/perm.js +1 -1
  43. package/src/serveFile.js +3 -1
  44. package/src/throttler.js +2 -1
  45. package/src/update.js +45 -7
  46. package/src/util-http.js +8 -3
  47. package/src/vfs.js +36 -12
  48. package/admin/assets/index-7f1741ba.js +0 -517
  49. package/frontend/assets/index-b49b8a16.js +0 -94
  50. package/frontend/assets/index-f2f8fd6b.css +0 -1
package/src/config.js CHANGED
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.saveConfigAsap = exports.setConfig = exports.getWholeConfig = exports.getConfig = exports.configKeyExists = exports.defineConfig = void 0;
7
+ exports.saveConfigAsap = exports.setConfig = exports.getWholeConfig = exports.getConfig = exports.configKeyExists = exports.defineConfig = exports.currentVersion = exports.versionToScalar = void 0;
8
8
  const events_1 = __importDefault(require("events"));
9
9
  const const_1 = require("./const");
10
10
  const watchLoad_1 = require("./watchLoad");
@@ -48,27 +48,30 @@ if (!(0, fs_1.existsSync)(filePath) && (0, fs_1.existsSync)(legacyPosition))
48
48
  catch (_b) { }
49
49
  }
50
50
  // takes a semver like 1.2.3-alpha1, but alpha and beta numbers must share the number progression
51
- const versionToScalar = lodash_1.default.memoize((ver) => {
52
- var _a;
53
- const [official, beta] = ver.split('-');
54
- const numbers = official.split('.').map(Number);
55
- if (numbers.length !== 3)
51
+ exports.versionToScalar = lodash_1.default.memoize((ver) => {
52
+ // this regexp is supposed to be resistant to optional leading "v" and an optional custom name after a space
53
+ const res = /^v?(\d+)\.(\d+)\.(\d+)(?:-\D+([0-9.]+))?/.exec(ver);
54
+ if (!res)
56
55
  return NaN;
57
- const officialScalar = numbers.reduce((acc, x, i) => acc + x * 1000 ** (2 - i), 0); // 1000 gives 3 digits for each number
58
- const betaScalar = 1 / (beta && Number((_a = /\d+/.exec(beta)) === null || _a === void 0 ? void 0 : _a[0]) || Infinity); // beta tends to 0, while non-beta is 0
56
+ const [, a, b, c, beta] = res.map(Number);
57
+ const officialScalar = c + b * 1E3 + a * 1E6; // gives 3 digits for each number
58
+ const betaScalar = 1 / (1 + beta || Infinity); // beta tends to 0, while non-beta is 0. +1 to make it work even in case of alpha0
59
59
  return officialScalar - betaScalar;
60
60
  });
61
61
  class Version extends String {
62
62
  olderThan(otherVersion) {
63
- return versionToScalar(this.valueOf()) < versionToScalar(otherVersion);
63
+ return (0, exports.versionToScalar)(this.valueOf()) < (0, exports.versionToScalar)(otherVersion);
64
+ }
65
+ getScalar() {
66
+ return (0, exports.versionToScalar)(this.valueOf());
64
67
  }
65
68
  }
66
69
  const CONFIG_CHANGE_EVENT_PREFIX = 'new.';
67
- const currentVersion = new Version(const_1.VERSION);
70
+ exports.currentVersion = new Version(const_1.VERSION);
68
71
  const configVersion = defineConfig('version', const_1.VERSION, v => new Version(v));
69
72
  function defineConfig(k, defaultValue, compiler) {
70
73
  configProps[k] = { defaultValue };
71
- let compiled = compiler === null || compiler === void 0 ? void 0 : compiler(defaultValue, { version: currentVersion, defaultValue });
74
+ let compiled = compiler === null || compiler === void 0 ? void 0 : compiler(defaultValue, { version: exports.currentVersion, defaultValue });
72
75
  const ret = {
73
76
  key() {
74
77
  return k;
@@ -112,7 +115,7 @@ function defineConfig(k, defaultValue, compiler) {
112
115
  }
113
116
  exports.defineConfig = defineConfig;
114
117
  function configKeyExists(k) {
115
- return k in configProps;
118
+ return configProps.hasOwnProperty(k);
116
119
  }
117
120
  exports.configKeyExists = configKeyExists;
118
121
  const stack = [];
@@ -162,7 +165,7 @@ function setConfig(newCfg, save) {
162
165
  if (version !== const_1.VERSION) // be sure to save version
163
166
  (0, exports.saveConfigAsap)();
164
167
  function apply(k, newV, isDefault = false) {
165
- return setConfig1(k, newV, save === undefined, argCfg && k in argCfg || isDefault ? currentVersion : version);
168
+ return setConfig1(k, newV, save === undefined, argCfg && k in argCfg || isDefault ? exports.currentVersion : version);
166
169
  }
167
170
  }
168
171
  exports.setConfig = setConfig;
@@ -6,7 +6,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.updateConnection = exports.socket2connection = exports.getConnections = exports.newConnection = exports.normalizeIp = exports.Connection = void 0;
8
8
  const events_1 = __importDefault(require("./events"));
9
- const lodash_1 = __importDefault(require("lodash"));
10
9
  class Connection {
11
10
  constructor(socket) {
12
11
  this.socket = socket;
@@ -49,9 +48,9 @@ function socket2connection(socket) {
49
48
  }
50
49
  exports.socket2connection = socket2connection;
51
50
  function updateConnection(conn, change) {
52
- // if no change is detected, skip update. ctx is a special case
53
- if (!change.ctx && Object.entries(change).every(([k, v]) => lodash_1.default.isEqual(v, conn[k])))
54
- return;
51
+ var _a;
52
+ if (change.op)
53
+ (_a = change.opProgress) !== null && _a !== void 0 ? _a : (change.opProgress = change.opOffset || 0);
55
54
  Object.assign(conn, change);
56
55
  events_1.default.emit('connectionUpdated', conn, change);
57
56
  }
@@ -0,0 +1,17 @@
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.consoleLog = void 0;
7
+ const events_1 = __importDefault(require("./events"));
8
+ exports.consoleLog = [];
9
+ for (const k of ['log', 'warn', 'error']) {
10
+ const original = console[k];
11
+ console[k] = (...args) => {
12
+ const rec = { ts: new Date(), k, msg: args.join(' ') };
13
+ exports.consoleLog.push(rec);
14
+ events_1.default.emit('console', rec);
15
+ return original(...args);
16
+ };
17
+ }
package/src/const.js CHANGED
@@ -27,7 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  return (mod && mod.__esModule) ? mod : { "default": mod };
28
28
  };
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
- exports.APP_PATH = exports.IS_BINARY = exports.IS_WINDOWS = exports.HTTP_SERVER_ERROR = exports.HTTP_FAILED_DEPENDENCY = exports.HTTP_FOOL = exports.HTTP_RANGE_NOT_SATISFIABLE = exports.HTTP_PAYLOAD_TOO_LARGE = 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_PARTIAL_CONTENT = exports.HTTP_NO_CONTENT = exports.HTTP_OK = exports.PLUGINS_PUB_URI = exports.API_URI = exports.ADMIN_URI = exports.FRONTEND_URI = exports.SPECIAL_URI = exports.HFS_REPO = exports.COMPATIBLE_API_VERSION = exports.API_VERSION = exports.DAY = exports.VERSION = exports.BUILD_TIMESTAMP = exports.HFS_STARTED = exports.ORIGINAL_CWD = exports.DEV = exports.argv = void 0;
30
+ exports.APP_PATH = exports.IS_BINARY = exports.IS_WINDOWS = exports.HTTP_SERVER_ERROR = exports.HTTP_FAILED_DEPENDENCY = exports.HTTP_FOOL = exports.HTTP_RANGE_NOT_SATISFIABLE = exports.HTTP_PAYLOAD_TOO_LARGE = 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_PARTIAL_CONTENT = exports.HTTP_NO_CONTENT = exports.HTTP_OK = exports.PLUGINS_PUB_URI = exports.API_URI = exports.ADMIN_URI = exports.FRONTEND_URI = exports.SPECIAL_URI = exports.HFS_REPO = exports.COMPATIBLE_API_VERSION = exports.API_VERSION = exports.DAY = exports.RUNNING_BETA = exports.VERSION = exports.BUILD_TIMESTAMP = exports.HFS_STARTED = exports.ORIGINAL_CWD = exports.DEV = exports.argv = void 0;
31
31
  const minimist_1 = __importDefault(require("minimist"));
32
32
  const fs = __importStar(require("fs"));
33
33
  const os_1 = require("os");
@@ -38,11 +38,12 @@ exports.DEV = process.env.DEV || exports.argv.dev ? 'DEV' : '';
38
38
  exports.ORIGINAL_CWD = process.cwd();
39
39
  exports.HFS_STARTED = new Date();
40
40
  const PKG_PATH = (0, path_1.join)(__dirname, '..', 'package.json');
41
- exports.BUILD_TIMESTAMP = "2023-07-08T18:00:25.802Z";
41
+ exports.BUILD_TIMESTAMP = "2023-08-03T13:37:16.289Z";
42
42
  const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'));
43
43
  exports.VERSION = pkg.version;
44
+ exports.RUNNING_BETA = exports.VERSION.includes('-');
44
45
  exports.DAY = 86400000;
45
- exports.API_VERSION = 8.23;
46
+ exports.API_VERSION = 8.3;
46
47
  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
47
48
  exports.HFS_REPO = 'rejetto/hfs';
48
49
  exports.SPECIAL_URI = '/~/';
@@ -53,13 +53,19 @@ exports.frontEndApis = {
53
53
  }
54
54
  });
55
55
  },
56
- async get_file_details({ uri }, ctx) {
57
- apiAssertTypes({ string: { uri } });
58
- const node = await (0, vfs_1.urlToNode)(uri, ctx);
59
- if (!node)
60
- return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND);
56
+ async get_file_details({ uris }, ctx) {
57
+ if (typeof (uris === null || uris === void 0 ? void 0 : uris[0]) !== 'string')
58
+ return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad uris');
61
59
  return {
62
- upload: node.source && await (0, upload_1.getUploadMeta)(node.source).catch(() => undefined)
60
+ details: Promise.all(uris.map(async (uri) => {
61
+ if (typeof uri !== 'string')
62
+ return false; // false means error
63
+ const node = await (0, vfs_1.urlToNode)(uri, ctx);
64
+ if (!node)
65
+ return false;
66
+ const upload = node.source && await (0, upload_1.getUploadMeta)(node.source).catch(() => undefined);
67
+ return upload && { upload };
68
+ }))
63
69
  };
64
70
  },
65
71
  async create_folder({ uri, name }, ctx) {
@@ -127,8 +133,9 @@ function notifyClient(ctx, name, data) {
127
133
  exports.notifyClient = notifyClient;
128
134
  const NOTIFICATION_PREFIX = 'notificationChannel:';
129
135
  function apiAssertTypes(paramsByType) {
130
- for (const [type, params] of Object.entries(paramsByType))
131
- for (const [name, val] of Object.entries(params))
132
- if (typeof val !== type)
133
- throw new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad ' + name);
136
+ for (const [types, params] of Object.entries(paramsByType))
137
+ for (const type of types.split('_'))
138
+ for (const [name, val] of Object.entries(params))
139
+ if (typeof val !== type)
140
+ throw new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad ' + name);
134
141
  }
package/src/github.js CHANGED
@@ -36,7 +36,7 @@ async function downloadPlugin(repo, branch = '', overwrite) {
36
36
  return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, "bad repo");
37
37
  const folder2repo = getFolder2repo();
38
38
  const folder = overwrite ? lodash_1.default.findKey(folder2repo, x => x === repo) // use existing folder
39
- : short in folder2repo ? repo.replace('/', '-') // longer form only if another plugin is using short form
39
+ : folder2repo.hasOwnProperty(short) ? repo.replace('/', '-') // longer form only if another plugin is using short form
40
40
  : short;
41
41
  const installPath = plugins_1.PATH + '/' + folder;
42
42
  const GITHUB_ZIP_ROOT = short + '-' + branch; // GitHub puts everything within this folder
package/src/index.js CHANGED
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.app = void 0;
10
10
  const koa_1 = __importDefault(require("koa"));
11
11
  const koa_mount_1 = __importDefault(require("koa-mount"));
12
+ require("./consoleLog");
12
13
  const apiMiddleware_1 = require("./apiMiddleware");
13
14
  const const_1 = require("./const");
14
15
  const frontEndApis_1 = require("./frontEndApis");
@@ -24,7 +25,8 @@ const assert_1 = require("assert");
24
25
  const lodash_1 = __importDefault(require("lodash"));
25
26
  const misc_1 = require("./misc");
26
27
  const koa_session_1 = __importDefault(require("koa-session"));
27
- (0, assert_1.ok)(lodash_1.default.intersection(Object.keys(frontEndApis_1.frontEndApis), Object.keys(adminApis_1.adminApis)).length === 0); // they share same endpoints
28
+ (0, assert_1.ok)(lodash_1.default.intersection(Object.keys(frontEndApis_1.frontEndApis), Object.keys(adminApis_1.adminApis)).length === 0); // they share same endpoints, don't clash
29
+ process.title = 'HFS ' + const_1.VERSION;
28
30
  const keys = ((_a = process.env.COOKIE_SIGN_KEYS) === null || _a === void 0 ? void 0 : _a.split(',')) || [(0, misc_1.randomId)(30)];
29
31
  exports.app = new koa_1.default({ keys });
30
32
  exports.app.use(middlewares_1.someSecurity)
@@ -13,4 +13,6 @@ const hfs_lang_zh_tw_json_1 = __importDefault(require("./hfs-lang-zh-tw.json"));
13
13
  const hfs_lang_fr_json_1 = __importDefault(require("./hfs-lang-fr.json"));
14
14
  const hfs_lang_pt_json_1 = __importDefault(require("./hfs-lang-pt.json"));
15
15
  const hfs_lang_vi_json_1 = __importDefault(require("./hfs-lang-vi.json"));
16
- exports.default = { it: hfs_lang_it_json_1.default, zh: hfs_lang_zh_json_1.default, ru: hfs_lang_ru_json_1.default, sr: hfs_lang_sr_json_1.default, ko: hfs_lang_ko_json_1.default, ms: hfs_lang_ms_json_1.default, 'zh-tw': hfs_lang_zh_tw_json_1.default, fr: hfs_lang_fr_json_1.default, pt: hfs_lang_pt_json_1.default, vi: hfs_lang_vi_json_1.default };
16
+ const hfs_lang_es_json_1 = __importDefault(require("./hfs-lang-es.json"));
17
+ const hfs_lang_nl_json_1 = __importDefault(require("./hfs-lang-nl.json"));
18
+ exports.default = { it: hfs_lang_it_json_1.default, zh: hfs_lang_zh_json_1.default, ru: hfs_lang_ru_json_1.default, sr: hfs_lang_sr_json_1.default, ko: hfs_lang_ko_json_1.default, ms: hfs_lang_ms_json_1.default, 'zh-tw': hfs_lang_zh_tw_json_1.default, fr: hfs_lang_fr_json_1.default, pt: hfs_lang_pt_json_1.default, vi: hfs_lang_vi_json_1.default, es: hfs_lang_es_json_1.default, nl: hfs_lang_nl_json_1.default };
@@ -0,0 +1,118 @@
1
+ {
2
+ "author": "Eidy Estupiñan Varona",
3
+ "version": 1.0,
4
+ "hfs_version": "0.46.0",
5
+ "translate": {
6
+ "Select": "Seleccionar",
7
+ "n_files": "{n,plural,one{# archivo} other {# archivos}}",
8
+ "n_folders": "{n,plural,one{# carpeta} other{# carpetas}}",
9
+ "filter_count": "{n,plural, one{# filtrado} other{# filtrados}}",
10
+ "select_count": "{n,plural, one{# seleccionado} other{# seleccionados}}",
11
+ "filter_placeholder": "Escriba aquí para filtrar la lista a continuación",
12
+ "Select some files": "Seleccione algunos archivos",
13
+ "zip_checkboxes": "Use casillas de verificación para seleccionar los archivos, luego puede usar la opción Zip nuevamente",
14
+ "zip_tooltip_selected": "Descargue los elementos seleccionados como un solo archivo zip",
15
+ "zip_tooltip_whole": "Descargue la lista completa (sin filtrar) como un solo archivo zip. Si selecciona algunos elementos, solo se descargarán esos.",
16
+ "zip_confirm_search": "¿Descargar TODOS los resultados de esta búsqueda como archivo ZIP?",
17
+ "zip_confirm_folder": "¿Descargar toda la carpeta como archivo Zip?",
18
+ "select_tooltip": "La selección se aplica a \"Zip\" y \"Eliminar\" (cuando esté disponible), pero también puede filtrar la lista",
19
+ "delete_hint": "Para eliminar, primero debe seleccionar",
20
+ "delete_confirm": "Eliminar {n,plural, one {# elemento} other {# elementos}}?",
21
+ "delete_completed": "Eliminado: {n} completado",
22
+ "delete_failed": ", {n,plural, one {# fallo} other{# fallaron}}",
23
+ "delete_select": "Seleccione algo para eliminar",
24
+ "Delete": "Eliminar",
25
+ "Options": "Opciones",
26
+ "Search": "Buscar",
27
+ "Zip": "Zip",
28
+ "search_msg": "Buscar esta carpeta y subcarpetas",
29
+ "Searching": "Buscando",
30
+ "Searched": "Buscado",
31
+ "Clear search": "Limpiar búsqueda",
32
+ "Interrupted": "Interrumpido",
33
+ "stopped_before": "stopped_before",
34
+ "empty_list": "Lista vacia",
35
+ "filter_none": "No filtrado",
36
+ "Admin-panel": "Administración",
37
+ "Login": "Acceder",
38
+ "Username": "Usuario",
39
+ "Password": "Contraseña",
40
+ "login_untrusted": "Acceso abortado: la identidad del servidor no es confiable",
41
+ "login_bad_credentials": "Credenciales no válidas",
42
+ "login_bad_cookies": "Las Cookies no funcionan - acceso fallido",
43
+ "User panel": "Panel de usuario",
44
+ "Change password": "Cambiar contraseña",
45
+ "enter_pass": "Nueva contraseña",
46
+ "enter_pass2": "Confirmación",
47
+ "pass2_mismatch": "Error: Las contraseñas no coinciden. cambio abortado.",
48
+ "password_changed": "Contraseña cambiada",
49
+ "Logout": "Salir",
50
+ "connection error": "Error de conexión",
51
+ "Full timestamp:": "Fecha - Hora completa",
52
+ "Search was interrupted": "La búsqueda fue interrumpida",
53
+ "Stop list": "Detener Lista",
54
+ "upload_starting": "Su descarga debería iniciar ahora",
55
+ "wrong_account": "La cuenta {u} no tiene acceso, prueba otra",
56
+ "no_upload_here": "No tiene permisos para subir a la carpeta actual",
57
+ "Create folder": "Crear carpeta",
58
+ "Pick files": "Seleccioanr archivo",
59
+ "Pick folder": "Seleccionar carpeta",
60
+ "send_files": "Enviar {n,plural,one {# archivo} other{# archivos}}, {size}",
61
+ "Clear": "Limpiar",
62
+ "failed_upload": "No se puede subir {name}",
63
+ "confirm_resume": "Continuar subida?",
64
+ "file too large": "archivo demasiado grande",
65
+ "Enter folder name": "Nombre de la carpeta",
66
+ "Successfully created": "Creado satisfactoriamente",
67
+ "enter_folder": "Entre la carpeta",
68
+ "folder_exists": "Ya existe una carpeta con ese nombre",
69
+ "Sort by": "Ordenar por",
70
+ "name": "nombre",
71
+ "extension": "extensión",
72
+ "size": "tamaño",
73
+ "time": "fecha",
74
+ "Invert order": "Invertir orden",
75
+ "Folders first": "Carpetas primero",
76
+ "Numeric names": "Nombres numéricos",
77
+ "theme:": "Tema",
78
+ "auto": "auto",
79
+ "light": "Claro",
80
+ "dark": "Oscuro",
81
+ "parent folder": "Carpeta superior",
82
+ "home": "inicio",
83
+ "Continue": "Continuar",
84
+ "Confirm": "Confirmar",
85
+ "Don't": "Cancelar",
86
+ "Warning": "Alerta",
87
+ "Error": "Error",
88
+ "Info": "Info",
89
+ "Unauthorized": "No autorizado",
90
+ "Forbidden": "Denegado",
91
+ "Not found": "No encontrado",
92
+ "Server error": "Server error",
93
+ "Upload": "Subir",
94
+ "upload_concluded": "Subida completada",
95
+ "upload_finished": "{n} completado ({size})",
96
+ "upload_errors": "{n} fallido",
97
+ "upload_file_rejected": "Algunos archivos no fueron aceptados",
98
+ "File menu": "Archivo",
99
+ "Folder menu": "Carpeta",
100
+ "Name": "Nombre",
101
+ "file_open": "Abrir",
102
+ "Download": "Descargar",
103
+ "Missing permission": "No dispone de permisos",
104
+ "Reload": "Recargar",
105
+ "Get list": "Obtener lista",
106
+ "Skip existing files": "Saltar archivos existentes",
107
+ "Size": "Tamaño",
108
+ "Timestamp": "Feha - Hora",
109
+ "Show": "Mostrar",
110
+ "Loading failed": "Carga fallida",
111
+ "Rename": "Renombrar",
112
+ "Tiles mode:": "Cantidad elementos",
113
+ "off": "Apagado",
114
+ "Operation successful": "Operación Completada",
115
+ "Uploader": "Subido por",
116
+ "Download counter": "Contador de descargas"
117
+ }
118
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "author": "Massimo Melina",
3
- "version": 1.6,
4
- "hfs_version": "0.46.0",
3
+ "version": 1.7,
4
+ "hfs_version": "0.47.0",
5
5
  "translate": {
6
6
  "Select": "Seleziona",
7
7
  "n_files": "{n} file",
@@ -64,10 +64,10 @@
64
64
  "Successfully created": "Creazione riuscita",
65
65
  "enter_folder": "Accedi alla nuova cartella",
66
66
  "folder_exists": "Questo nome esiste già",
67
- "Sort by": "Ordinamento",
67
+ "Sort by:": "Ordina per {by}",
68
68
  "name": "nome",
69
69
  "extension": "estensione",
70
- "size": "dimensioni",
70
+ "size": "dimensione",
71
71
  "time": "data/ora",
72
72
  "Invert order": "Inverti ordine",
73
73
  "Folders first": "Prima le cartelle",
@@ -107,6 +107,8 @@
107
107
  "off": "no",
108
108
  "Operation successful": "Operazione riuscita",
109
109
  "Uploader": "Upload da",
110
- "Download counter": "Download conteggiati"
110
+ "Download counter": "Download conteggiati",
111
+ "Switch _z_oom mode": "Cambia _z_oom",
112
+ "_F_ull screen": "Pieno schermo (_F_)"
111
113
  }
112
114
  }
@@ -0,0 +1,118 @@
1
+ {
2
+ "author": "H.F.P. Pit - PH5HP",
3
+ "version": 1.0,
4
+ "hfs_version": "0.46.0",
5
+ "translate": {
6
+ "Select": "Selecteer",
7
+ "n_files": "{n,plural,one{# bestand} other{# bestanden}}",
8
+ "n_folders": "{n,plural,one{# map} other{# mappen}}",
9
+ "filter_count": "{n,plural, one{# gefilterd} other{# gefilterd}}",
10
+ "select_count": "{n,plural, one{# geselecteerd} other{# geselecteerd}}",
11
+ "filter_placeholder": "Typ hier om de lijst hieronder te filteren",
12
+ "Select some files": "Selecteer enige bestanden",
13
+ "zip_checkboxes": "Gebruik checkboxes om de bestanden te selecteren, daarna kunt U Zip opnieuw gebruiken",
14
+ "zip_tooltip_selected": "Download geselecteerde elementen als 1 zip bestand",
15
+ "zip_tooltip_whole": "Download de hele lijst (niet gefilterd) als 1 zip bestand. Als U sommige elementen selecteerd, dan zullen alleen die gedownload worden.",
16
+ "zip_confirm_search": "Download ALLE resultaten van deze zoekopdracht als een ZIP archief?",
17
+ "zip_confirm_folder": "Download de HELE map als een ZIP archief?",
18
+ "select_tooltip": "Selection applies to \"Zip\" and \"Delete\" (when available), but you can also filter the list",
19
+ "delete_hint": "Om te verwijderen, klik eerst op Select",
20
+ "delete_confirm": "Verwijder {n,plural, one{# item} other{# items}}?",
21
+ "delete_completed": "Verwijderen: {n} voltooid",
22
+ "delete_failed": ", {n,plural, one{# mislukt} other{# mislukt}}",
23
+ "delete_select": "Selecteer iets om te verwijderen",
24
+ "Delete": "Verwijder",
25
+ "Options": "Opties",
26
+ "Search": "Zoek",
27
+ "Zip": "Zip",
28
+ "search_msg": "Doorzoek deze map en sub-mappen",
29
+ "Searching": "Aan het zoeken",
30
+ "Searched": "Gezocht",
31
+ "Clear search": "Verwijder zoekopdracht",
32
+ "Interrupted": "Onderbroken",
33
+ "stopped_before": "stopped_before",
34
+ "empty_list": "lege_lijst",
35
+ "filter_none": "filter_niets",
36
+ "Admin-panel": "Admin-panel",
37
+ "Login": "Inloggen",
38
+ "Username": "Gebruikersnaam",
39
+ "Password": "Password",
40
+ "login_untrusted": "Inloggen afgebroken: server identiteit kan niet worden vertrouwd",
41
+ "login_bad_credentials": "Ontoereikende bevoegdheden",
42
+ "login_bad_cookies": "Cookies werken niet - inloggen mislukt",
43
+ "User panel": "Gebruikers paneel",
44
+ "Change password": "Verander password",
45
+ "enter_pass": "Geef nieuw password",
46
+ "enter_pass2": "Geef opnieuw hetzelfde nieuwe password",
47
+ "pass2_mismatch": "Het 2e password dat U hebt ingegeven komt niet met de 1e overeen. Procedure afgebroken.",
48
+ "password_changed": "password_veranderd",
49
+ "Logout": "Log uit",
50
+ "connection error": "connectie fout",
51
+ "Full timestamp:": "Volledige timestamp:",
52
+ "Search was interrupted": "Zoeken is onderbroken",
53
+ "Stop list": "Stop lijst",
54
+ "upload_starting": "Uw download zou nu moeten starten",
55
+ "wrong_account": "Account {u} heeft geen toegang, probeer een andere",
56
+ "no_upload_here": "Geen upload toestemming voor de huidige map",
57
+ "Create folder": "Creeer map",
58
+ "Pick files": "Kies bestand",
59
+ "Pick folder": "Kies map",
60
+ "send_files": "Verzonden {n,plural,one{# bestand} other{# bestanden}}, {grootte}",
61
+ "Clear": "Clear",
62
+ "failed_upload": "Kon het niet uploaden {name}",
63
+ "confirm_resume": "Upload hervatten?",
64
+ "file too large": "bestand te groot",
65
+ "Enter folder name": "Geef map naam in",
66
+ "Successfully created": "Succesvol gecreeerd",
67
+ "enter_folder": "Ga naar de map",
68
+ "folder_exists": "Map met dezelfde naam bestaan al",
69
+ "Sort by": "Gesorteerd op",
70
+ "name": "naam",
71
+ "extension": "extensie",
72
+ "size": "grootte",
73
+ "time": "tijd",
74
+ "Invert order": "Inveer volgorde",
75
+ "Folders first": "Mappen eerst",
76
+ "Numeric names": "Numerieke namen",
77
+ "theme:": "thema:",
78
+ "auto": "auto",
79
+ "light": "licht",
80
+ "dark": "donker",
81
+ "parent folder": "map terug",
82
+ "home": "thuis",
83
+ "Continue": "Doorgaan",
84
+ "Confirm": "Bevestig",
85
+ "Don't": "Niet doen",
86
+ "Warning": "Waarschuwing",
87
+ "Error": "Fout",
88
+ "Info": "Info",
89
+ "Unauthorized": "Niet ge-authoriseerd",
90
+ "Forbidden": "Verboden",
91
+ "Not found": "Niet gevonden",
92
+ "Server error": "Server fout",
93
+ "Upload": "Upload",
94
+ "upload_concluded": "Upload afgesloten:",
95
+ "upload_finished": "{n} voltooid ({size})",
96
+ "upload_errors": "{n} niet voltooid",
97
+ "upload_file_rejected": "Sommige bestanden zijn niet geaccepteerd",
98
+ "File menu": "Bestand menu",
99
+ "Folder menu": "Map menu",
100
+ "Name": "Naam",
101
+ "file_open": "Open",
102
+ "Download": "Download",
103
+ "Missing permission": "Toestemming ontbreekt",
104
+ "Reload": "Herlaad",
105
+ "Get list": "Laad lijst",
106
+ "Skip existing files": "Sla bestaande bestanden over",
107
+ "Size": "Grootte",
108
+ "Timestamp": "Timestamp",
109
+ "Show": "Laat zien",
110
+ "Loading failed": "Laden mislukt",
111
+ "Rename": "Herbenoemen",
112
+ "Tiles mode:": "Tegels mode:",
113
+ "off": "uit",
114
+ "Operation successful": "Operatie succesvol",
115
+ "Uploader": "Uploader",
116
+ "Download counter": "Download teller"
117
+ }
118
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "author": "Mefistofell, SanokKule",
3
- "version": 1.97,
4
- "hfs_version": "0.46.0",
3
+ "version": 1.98,
4
+ "hfs_version": "0.47.0",
5
5
  "translate": {
6
6
  "Select": "Выбор",
7
7
  "n_files": "{n,plural, one{1 файл} few{# файла} other{# файлов}}",
@@ -66,7 +66,7 @@
66
66
  "Successfully created": "Успешно создано",
67
67
  "enter_folder": "Перейти в папку",
68
68
  "folder_exists": "Папка уже существует",
69
- "Sort by": "Сортировка по",
69
+ "Sort by:": "Сортировка по: {by}",
70
70
  "name": "имени",
71
71
  "extension": "расширению",
72
72
  "size": "размеру",
@@ -1,7 +1,7 @@
1
1
  {
2
- "author": "yx3016",
3
- "version": 1.1,
4
- "hfs_version": "0.40.1",
2
+ "author": "yx3016 & MircoH0",
3
+ "version": 1.2,
4
+ "hfs_version": "0.46.0",
5
5
  "translate": {
6
6
  "Select": "选择",
7
7
  "n_files": "{n} 个文件",
@@ -85,14 +85,34 @@
85
85
  "Don't": "取消",
86
86
  "Warning": "警告",
87
87
  "Error": "错误",
88
+ "Info": "信息",
88
89
  "Unauthorized": "未授权",
89
90
  "Forbidden": "禁止",
90
91
  "Not found": "未找到",
91
92
  "Server error": "服务器错误",
92
93
  "Upload": "上传",
93
- "Upload terminated": "上传已终止",
94
+ "upload_concluded": "上传已终止:",
94
95
  "upload_finished": "上传{n} 结束 ({size})",
95
96
  "upload_errors": "上传失败{n} 失败",
96
- "download counter": "download 计数"
97
+ "upload_file_rejected": "部分文件被服务器拒绝接收",
98
+ "File menu": "文件菜单",
99
+ "Folder menu": "文件夹菜单",
100
+ "Name": "名称",
101
+ "file_open": "打开",
102
+ "Download": "下载",
103
+ "Missing permission": "权限缺失",
104
+ "Reload": "刷新",
105
+ "Get list": "生成列表",
106
+ "Skip existing files": "跳过已存在的文件",
107
+ "Size": "大小",
108
+ "Timestamp": "时间戳",
109
+ "Show": "显示",
110
+ "Loading failed": "加载失败",
111
+ "Rename": "重命名",
112
+ "Tiles mode:": "图标平铺模式:",
113
+ "off": "关闭",
114
+ "Operation successful": "操作执行成功",
115
+ "Uploader": "上传者",
116
+ "Download counter": "下载计数"
97
117
  }
98
118
  }
package/src/log.js CHANGED
@@ -70,7 +70,7 @@ class Logger {
70
70
  const accessLogger = new Logger('log');
71
71
  const accessErrorLog = new Logger('error_log');
72
72
  exports.loggers = [accessLogger, accessErrorLog];
73
- (0, config_1.defineConfig)('log', 'logs/access.log').sub(path => {
73
+ (0, config_1.defineConfig)(accessLogger.name, 'logs/access.log').sub(path => {
74
74
  console.debug('access log file: ' + (path || 'disabled'));
75
75
  accessLogger.setPath(path);
76
76
  });
@@ -86,7 +86,9 @@ const logMw = async (ctx, next) => {
86
86
  const now = new Date();
87
87
  await next();
88
88
  console.debug(ctx.status, ctx.method, ctx.originalUrl);
89
- Promise.race([(0, stream_1.once)(ctx.res, 'finish'), (0, stream_1.once)(ctx.res, 'close')]).then(() => {
89
+ // don't await, as we don't want to hold the middlewares chain
90
+ ctx.state.completed = Promise.race([(0, stream_1.once)(ctx.res, 'finish'), (0, stream_1.once)(ctx.res, 'close')]);
91
+ ctx.state.completed.then(() => {
90
92
  var _a, _b, _c, _d, _e;
91
93
  if (ctx.state.dont_log)
92
94
  return;
@@ -111,7 +113,7 @@ const logMw = async (ctx, next) => {
111
113
  (0, fs_1.renameSync)(path, path + '-' + postfix);
112
114
  }
113
115
  catch (e) { // ok, rename failed, but this doesn't mean we ain't gonna log
114
- console.error(e);
116
+ console.error(String(e || e.message));
115
117
  }
116
118
  stream = logger.reopen(); // keep variable updated
117
119
  if (!stream)
@@ -222,9 +222,9 @@ const prepareState = async (ctx, next) => {
222
222
  ctx.state.account = (_a = await getHttpAccount(ctx)) !== null && _a !== void 0 ? _a : (0, perm_1.getAccount)((_b = ctx.session) === null || _b === void 0 ? void 0 : _b.username, false);
223
223
  const conn = ctx.state.connection = (0, connections_1.socket2connection)(ctx.socket);
224
224
  ctx.state.revProxyPath = ctx.get('x-forwarded-prefix');
225
- await next();
226
225
  if (conn)
227
- (0, connections_1.updateConnection)(conn, { ctx });
226
+ (0, connections_1.updateConnection)(conn, { ctx, op: undefined });
227
+ await next();
228
228
  };
229
229
  exports.prepareState = prepareState;
230
230
  async function getHttpAccount(ctx) {
package/src/misc.js CHANGED
@@ -18,7 +18,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
18
18
  return (mod && mod.__esModule) ? mod : { "default": mod };
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.try_ = exports.stream2string = exports.tryJson = exports.same = exports.matches = exports.makeMatcher = exports.makeNetMatcher = exports.isLocalHost = exports.with_ = exports.hasProp = exports.typedKeys = exports.objRenameKey = exports.onOff = exports.pendingPromise = exports.onlyTruthy = exports.truthy = exports.pattern2filter = exports.onFirstEvent = exports.onProcessExit = exports.randomId = exports.getOrSet = exports.wantArray = exports.waitFor = exports.wait = exports.newObj = exports.setHidden = exports.prefix = exports.removeStarting = exports.enforceFinal = exports.debounceAsync = void 0;
21
+ exports.try_ = exports.stream2string = exports.tryJson = exports.same = exports.matches = exports.makeMatcher = exports.makeNetMatcher = exports.isLocalHost = exports.with_ = exports.hasProp = exports.typedEntries = exports.typedKeys = exports.objRenameKey = exports.onOff = exports.pendingPromise = exports.onlyTruthy = exports.truthy = exports.pattern2filter = exports.onFirstEvent = exports.onProcessExit = exports.randomId = exports.getOrSet = exports.wantArray = exports.waitFor = exports.wait = exports.newObj = exports.setHidden = exports.prefix = exports.removeStarting = exports.enforceFinal = exports.debounceAsync = void 0;
22
22
  const path_1 = require("path");
23
23
  const lodash_1 = __importDefault(require("lodash"));
24
24
  const assert_1 = __importDefault(require("assert"));
@@ -166,6 +166,10 @@ function typedKeys(o) {
166
166
  return Object.keys(o);
167
167
  }
168
168
  exports.typedKeys = typedKeys;
169
+ function typedEntries(o) {
170
+ return Object.entries(o);
171
+ }
172
+ exports.typedEntries = typedEntries;
169
173
  function hasProp(obj, key) {
170
174
  return key in obj;
171
175
  }
package/src/perm.js CHANGED
@@ -62,7 +62,7 @@ async function updateAccount(account, changer) {
62
62
  if (account.belongs) {
63
63
  account.belongs = (0, misc_1.wantArray)(account.belongs);
64
64
  lodash_1.default.remove(account.belongs, b => {
65
- if (b in accounts)
65
+ if (accounts.hasOwnProperty(b))
66
66
  return;
67
67
  console.error(`account ${username} belongs to non-existing ${b}`);
68
68
  return true;