hfs 0.30.0 → 0.30.2

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.
@@ -1,4 +1,4 @@
1
- import{c as SF}from"./index-57af5a8c.js";function OF(iF,hF){for(var eF=0;eF<hF.length;eF++){const tF=hF[eF];if(typeof tF!="string"&&!Array.isArray(tF)){for(const w in tF)if(w!=="default"&&!(w in iF)){const lF=Object.getOwnPropertyDescriptor(tF,w);lF&&Object.defineProperty(iF,w,lF.get?lF:{enumerable:!0,get:()=>tF[w]})}}}return Object.freeze(Object.defineProperty(iF,Symbol.toStringTag,{value:"Module"}))}var EF={},UF={get exports(){return EF},set exports(iF){EF=iF}};/*
1
+ import{c as SF}from"./index-ea9ae7b4.js";function OF(iF,hF){for(var eF=0;eF<hF.length;eF++){const tF=hF[eF];if(typeof tF!="string"&&!Array.isArray(tF)){for(const w in tF)if(w!=="default"&&!(w in iF)){const lF=Object.getOwnPropertyDescriptor(tF,w);lF&&Object.defineProperty(iF,w,lF.get?lF:{enumerable:!0,get:()=>tF[w]})}}}return Object.freeze(Object.defineProperty(iF,Symbol.toStringTag,{value:"Module"}))}var EF={},UF={get exports(){return EF},set exports(iF){EF=iF}};/*
2
2
  * [js-sha512]{@link https://github.com/emn178/js-sha512}
3
3
  *
4
4
  * @version 0.8.0
@@ -6,13 +6,13 @@
6
6
  <link href="/fontello.css" rel="stylesheet" />
7
7
  <script>SESSION = _HFS_SESSION_</script>
8
8
  <title>File Server</title>
9
- <script type="module" crossorigin src="/assets/index-b557b421.js"></script>
10
- <link rel="stylesheet" href="/assets/index-35d3e75f.css">
9
+ <script type="module" crossorigin src="/assets/index-ea9ae7b4.js"></script>
10
+ <link rel="stylesheet" href="/assets/index-6f1b310f.css">
11
11
  </head>
12
12
  <body>
13
- <div hidden>_HFS_PLUGINS_</div>
14
13
  <noscript>You need to enable JavaScript to run this app.</noscript>
15
14
 
16
15
  <div id="root"></div>
16
+ <div hidden>_HFS_PLUGINS_</div>
17
17
  </body>
18
18
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hfs",
3
- "version": "0.30.0",
3
+ "version": "0.30.2",
4
4
  "description": "HTTP File Server",
5
5
  "keywords": [
6
6
  "file server",
@@ -1,5 +1,5 @@
1
1
  exports.description = "If you want to have different home folders, based on domain"
2
- exports.version = 3 // support masks for host
2
+ exports.version = 3.1 // support masks for host
3
3
  exports.apiRequired = 2 // 2 is for the config 'array'
4
4
 
5
5
  exports.config = {
@@ -23,9 +23,12 @@ exports.init = api => {
23
23
  middleware(ctx) {
24
24
  let toModify = ctx
25
25
  if (ctx.path.startsWith(api.const.SPECIAL_URI)) { // special uris should be excluded...
26
+ // ...unless it's a frontend api with a path param
27
+ if (!ctx.path.startsWith(api.const.API_URI) || ctx.params.path === undefined) return
28
+ let { referer } = ctx.headers
29
+ referer &&= new URL(referer).pathname
30
+ if (referer?.startsWith(api.const.ADMIN_URI)) return
26
31
  toModify = ctx.params
27
- if (toModify?.path === undefined) // ...unless they carry a path in the query. In that case we'll work that.
28
- return
29
32
  }
30
33
  const hosts = api.getConfig('hosts')
31
34
  if (!hosts?.length) return
@@ -27,9 +27,6 @@ function apiMiddleware(apis) {
27
27
  ctx.body = 'invalid api';
28
28
  return ctx.status = const_1.HTTP_NOT_FOUND;
29
29
  }
30
- ctx.params = ctx.method === 'POST' ? (0, misc_1.tryJson)(await (0, misc_1.stream2string)(ctx.req))
31
- : (0, misc_1.objSameKeys)(ctx.query, x => Array.isArray(x) ? x : (0, misc_1.tryJson)(x));
32
- console.debug('API', ctx.method, ctx.path, { ...ctx.params });
33
30
  const csrf = ctx.cookies.get('csrf');
34
31
  // we don't rely on SameSite cookie option because it's https-only
35
32
  let res = csrf && csrf !== ctx.params.csrf ? new ApiError(const_1.HTTP_UNAUTHORIZED, 'csrf')
package/src/const.js CHANGED
@@ -38,7 +38,7 @@ 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-02-04T16:32:19.926Z";
41
+ exports.BUILD_TIMESTAMP = "2023-02-10T14:09:18.632Z";
42
42
  const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'));
43
43
  exports.VERSION = pkg.version;
44
44
  exports.DAY = 86400000;
package/src/index.js CHANGED
@@ -33,6 +33,7 @@ exports.app.use(middlewares_1.someSecurity)
33
33
  .use((0, log_1.log)())
34
34
  .use(throttler_1.throttler)
35
35
  .use(middlewares_1.gzipper)
36
+ .use(middlewares_1.paramsDecoder) // must be done before plugins, so they can manipulate params
36
37
  .use((0, plugins_1.pluginsMiddleware)())
37
38
  .use((0, koa_mount_1.default)(const_1.API_URI, (0, apiMiddleware_1.apiMiddleware)({ ...frontEndApis_1.frontEndApis, ...adminApis_1.adminApis })))
38
39
  .use(middlewares_1.serveGuiAndSharedFiles)
@@ -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.prepareState = exports.getProxyDetected = exports.someSecurity = exports.serveGuiAndSharedFiles = exports.sessions = exports.headRequests = exports.gzipper = void 0;
7
+ exports.paramsDecoder = exports.prepareState = exports.getProxyDetected = exports.someSecurity = exports.serveGuiAndSharedFiles = exports.sessions = exports.headRequests = exports.gzipper = void 0;
8
8
  const koa_compress_1 = __importDefault(require("koa-compress"));
9
9
  const koa_session_1 = __importDefault(require("koa-session"));
10
10
  const const_1 = require("./const");
@@ -191,3 +191,10 @@ async function srpCheck(username, password) {
191
191
  const clientRes2 = await clientRes1.step2(BigInt(salt), BigInt(pubKey));
192
192
  return await step1.step2(clientRes2.A, clientRes2.M1).then(() => true, () => false);
193
193
  }
194
+ // unify get/post parameters, with JSON decoding to not be limited to strings
195
+ const paramsDecoder = async (ctx, next) => {
196
+ ctx.params = ctx.method === 'POST' ? (0, misc_1.tryJson)(await (0, misc_1.stream2string)(ctx.req))
197
+ : (0, misc_1.objSameKeys)(ctx.query, x => Array.isArray(x) ? x : (0, misc_1.tryJson)(x));
198
+ await next();
199
+ };
200
+ exports.paramsDecoder = paramsDecoder;
package/src/plugins.js CHANGED
@@ -31,7 +31,6 @@ exports.parsePluginSource = exports.rescan = exports.pluginsConfig = exports.ena
31
31
  const fast_glob_1 = __importDefault(require("fast-glob"));
32
32
  const watchLoad_1 = require("./watchLoad");
33
33
  const lodash_1 = __importDefault(require("lodash"));
34
- const path_1 = __importDefault(require("path"));
35
34
  const const_1 = require("./const");
36
35
  const Const = __importStar(require("./const"));
37
36
  const misc_1 = require("./misc");
@@ -41,6 +40,7 @@ const events_1 = __importDefault(require("./events"));
41
40
  const promises_1 = require("fs/promises");
42
41
  const fs_1 = require("fs");
43
42
  const connections_1 = require("./connections");
43
+ const path_1 = require("path");
44
44
  exports.PATH = 'plugins';
45
45
  exports.DISABLING_POSTFIX = '-disabled';
46
46
  const plugins = {};
@@ -109,10 +109,9 @@ function pluginsMiddleware() {
109
109
  if (!ctx.pluginStopped) {
110
110
  if (path.startsWith(const_1.PLUGINS_PUB_URI)) {
111
111
  const a = path.substring(const_1.PLUGINS_PUB_URI.length).split('/');
112
- if (plugins.hasOwnProperty(a[0])) { // do it only if the plugin is loaded
113
- a.splice(1, 0, 'public');
114
- await (0, serveFile_1.serveFile)(exports.PATH + '/' + a.join('/'), 'auto')(ctx, next);
115
- }
112
+ const name = a.shift();
113
+ if (plugins.hasOwnProperty(name)) // do it only if the plugin is loaded
114
+ await (0, serveFile_1.serveFile)(plugins[name].folder + '/public/' + a.join('/'), 'auto')(ctx, next);
116
115
  }
117
116
  await next();
118
117
  }
@@ -122,8 +121,9 @@ function pluginsMiddleware() {
122
121
  }
123
122
  exports.pluginsMiddleware = pluginsMiddleware;
124
123
  class Plugin {
125
- constructor(id, data, unwatch) {
124
+ constructor(id, folder, data, unwatch) {
126
125
  this.id = id;
126
+ this.folder = folder;
127
127
  this.data = data;
128
128
  this.unwatch = unwatch;
129
129
  this.started = new Date();
@@ -219,7 +219,7 @@ async function rescan() {
219
219
  found.push(id);
220
220
  if (plugins[id]) // already loaded
221
221
  continue;
222
- const module = path_1.default.resolve(f);
222
+ const module = (0, path_1.resolve)(f);
223
223
  const { unwatch } = (0, watchLoad_1.watchLoad)(f, async () => {
224
224
  try {
225
225
  const alreadyRunning = plugins[id];
@@ -261,7 +261,7 @@ async function rescan() {
261
261
  getHfsConfig: config_1.getConfig,
262
262
  }));
263
263
  Object.assign(data, res);
264
- const plugin = new Plugin(id, data, unwatch);
264
+ const plugin = new Plugin(id, (0, path_1.dirname)(module), data, unwatch);
265
265
  if (alreadyRunning)
266
266
  events_1.default.emit('pluginUpdated', Object.assign(lodash_1.default.pick(plugin, 'started'), getPluginInfo(id)));
267
267
  else {
@@ -1 +0,0 @@
1
- @charset "UTF-8";:root{--bg: #fff;--text: #555;--faint-contrast: #0002;--mild-contrast: #0005;--good-contrast: #000a;--button-bg: #68a;--button-text: #fff;--focus-color: #468}:root .theme-dark{--bg: #000;--text: #999;--faint-contrast: #fff2;--mild-contrast: #fff5;--good-contrast: #fffa;--button-bg: #345;--button-text: #999;color-scheme:dark}:root .theme-dark a{color:#8ac}:root .theme-dark .dialog-closer{background:#633}:root .theme-dark .dialog-icon{color:#ccc}:root .theme-dark .dialog-icon .icon{color:#aaa;margin-left:-1px;font-size:95%}:root .theme-dark .dialog-backdrop{background:rgba(51,51,51,.7333333333)}:root .theme-dark .error-msg{color:#b88;background-color:#623}body{background:var(--bg);margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body,button,select,input{font-size:12pt}#root{max-width:50em;margin:auto;min-height:100vh;display:flex;flex-direction:column}body,input{color:var(--text)}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}input,select{padding:.3em .4em;border-radius:.5em;background:var(--bg);border-color:var(--mild-contrast);color:var(--good-contrast);max-width:100%;box-sizing:border-box}input[type=checkbox]{margin:0 1.3em 0 .8em;transform:scale(1.7);accent-color:var(--button-bg)}.hidden{display:none!important}.icon{font-size:1.2em}.icon.mirror:before{transform:scaleX(-1)}a{text-decoration:none;color:#57a}button{background-color:var(--button-bg);color:var(--button-text);padding:.5em 1em;border:transparent;text-decoration:none;border-radius:.3em;vertical-align:middle;cursor:pointer}button.toggled{opacity:.6}button:focus-visible,.breadcrumb:focus-visible{outline:3px solid var(--focus-color)}input:focus-visible,select:focus-visible,ul a:focus-visible{border-radius:.3em;border-color:transparent;outline:2px solid var(--focus-color)}.error-msg{background-color:#faa;color:#833;padding:.5em 1em}header{position:sticky;top:0;background:var(--bg);padding:.2em;z-index:1}.ani-working{animation:1s blink infinite}@keyframes blink{0%{opacity:1}50%{opacity:.2}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.spinner,.icon.spinner:before{animation:1.5s spin infinite linear}.icon.emoji.spinner{display:inline-block}.breadcrumb{padding:.1em .6em .2em;line-height:1.8em;border-radius:.7em;background-color:var(--button-bg);color:var(--button-text);border-top:1px solid #666;margin-right:-.1em}.breadcrumb:nth-child(-n+3) .icon{padding:0 .2em}#folder-stats{font-size:90%;margin:.4em 0 0 .5em;float:right}#folder-stats .icon{margin-right:.3em}header input{width:100%;margin:.2em auto;box-sizing:border-box}#filter-bar{display:flex;gap:.3em;margin:.5em 0}#filter-bar input{flex:1}#filter-bar button{padding:0 .5em}ul.dir{flex:1;padding:0;margin:0;clear:both}ul.dir li{display:block;list-style-type:none;margin-bottom:.3em;padding:.3em;border-top:1px solid var(--button-bg)}ul.dir li a{word-break:break-word;padding-right:.3em}ul.dir li a .icon{margin-right:.3em}ul.dir li a.container-folder:hover{text-decoration:underline}ul.dir li .entry-props{float:right;font-size:90%;margin-left:12px;margin-top:.2em}ul.dir li .entry-props .icon{margin:0 .3em}ul.dir li .entry-props .entry-size{display:inline-block}#menu-panel{margin-bottom:.2em}#menu-bar{display:flex;justify-content:space-evenly;flex-wrap:wrap}#menu-bar>*{flex:auto;margin:.1em}#menu-bar button{padding-left:0;padding-right:0}#menu-bar>a>button{width:100%}#searched{margin:.2em}#user-panel{display:flex;flex-direction:column;gap:1em}#user-panel a>button{width:100%}button label{cursor:inherit;margin-left:.5em}.dialog-backdrop.working{font-size:5em;animation:1s fade-in}.dialog-content{padding:.2em}.dialog{--color: var(--button-bg)}#paging{display:flex;position:sticky;bottom:0;background:var(--bg);gap:.5em;overflow-x:auto}#paging>button{flex:1;background:var(--button-bg);text-align:center}.upload-progress:before{content:" \2013 "}.upload-progress{min-width:4em;display:inline-block;margin-left:.5em}.upload-list td:nth-child(1){width:0}.upload-list td:nth-child(2){text-align:right;width:0;white-space:nowrap;padding-left:.5em}.upload-list td:nth-child(3){padding:.2em .5em;word-break:break-word}.dialog-login form{display:flex;flex-direction:column;gap:1.2em}.dialog-login label{display:block;margin-bottom:.5em;margin-left:.1em}*{scrollbar-width:thin;scrollbar-color:var(--button-bg) var(--faint-contrast)}*::-webkit-scrollbar{width:12px}*::-webkit-scrollbar-track{background:var(--faint-contrast)}*::-webkit-scrollbar-thumb{background-color:var(--button-bg);border-radius:20px;border:1px solid var(--faint-contrast)}@media (max-width: 42em){body,button,select{font-size:14pt}#menu-bar button label{display:none}#filter-bar{margin:.2em 0}#filter-bar label{display:none}#filter-bar button{width:17.6vw;height:2.3em}.breadcrumb{word-break:break-all}.breadcrumb .icon{font-size:24px}}.dialog-backdrop{position:fixed;inset:0;background:#888a;display:flex;justify-content:center;align-items:center;z-index:1000}.dialog{background:#fff;background:var(--bg);padding:max(.5em,1vw);border-radius:1em;position:relative;margin:0 3vw;overflow:hidden;max-height:calc(100vh - 2em)}.dialog-icon{color:#fff;background-color:var(--color);position:absolute;top:0;width:1.8em;height:1.7em;text-align:center;border-radius:.8em 0}.dialog-title{margin-top:-.4em;font-size:110%}.dialog-icon~.dialog-title{text-align:center}.dialog-closer{border-radius:0 .8em;right:0;padding:0;background-color:#c88}.dialog-icon~.dialog-content{margin-top:2em}.dialog-type{left:0;top:0;overflow:hidden;line-height:1.7em;opacity:.8}.dialog-content{overflow:auto;max-height:calc(100vh - 4.5em)}.dialog-content p{white-space:pre-wrap;margin:.5em 0}.dialog-confirm .dialog-content button{margin-top:1em}.dialog-alert-info{--color: #282 }.dialog-alert-warning{--color: #c91 }.dialog-alert-error{--color: #822}@media (max-width: 50em){.dialog-closer{font-size:120%}.dialog-icon~.dialog-content{margin-top:2em}}.dialog-prompt label{display:block;margin-bottom:.5em;margin-left:.1em}