hfs 0.35.0 → 0.37.0
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/README.md +4 -5
- package/admin/assets/{index-0859bb0d.js → index-3867a36f.js} +115 -115
- package/admin/assets/{index-6f45486d.css → index-a21d9024.css} +1 -1
- package/{frontend/assets/sha512-5cf58050.js → admin/assets/sha512-9a451918.js} +1 -1
- package/admin/index.html +2 -2
- package/frontend/assets/{index-c4c325e9.css → index-216f7ea9.css} +1 -1
- package/frontend/assets/index-420a7286.js +85 -0
- package/{admin/assets/sha512-1ab69ff8.js → frontend/assets/sha512-065c5d7c.js} +1 -1
- package/frontend/index.html +3 -3
- package/package.json +2 -2
- package/src/adminApis.js +2 -1
- package/src/api.monitor.js +34 -0
- package/src/api.vfs.js +9 -3
- package/src/const.js +5 -5
- package/src/frontEndApis.js +2 -3
- package/src/middlewares.js +1 -1
- package/src/serveGuiFiles.js +1 -0
- package/src/update.js +3 -3
- package/src/upload.js +21 -7
- package/src/vfs.js +7 -6
- package/frontend/assets/index-21e40dc5.js +0 -85
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as SF}from"./index-
|
|
1
|
+
import{c as SF}from"./index-420a7286.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
|
package/frontend/index.html
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
<link href="/fontello.css" rel="stylesheet" />
|
|
7
7
|
<link rel="icon"/>
|
|
8
8
|
<script>SESSION = _HFS_SESSION_</script>
|
|
9
|
-
<title>
|
|
10
|
-
<script type="module" crossorigin src="/assets/index-
|
|
11
|
-
<link rel="stylesheet" href="/assets/index-
|
|
9
|
+
<title>_HFS_TITLE_</title>
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-420a7286.js"></script>
|
|
11
|
+
<link rel="stylesheet" href="/assets/index-216f7ea9.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hfs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"description": "HTTP File Server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"file server",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"dist-bin": "npm run dist-modules && cd dist && pkg . -C gzip && mv -f hfs-win-x64.exe hfs.exe && zip hfs-windows.zip hfs.exe -r plugins && cp -f hfs-linux-x64 hfs && zip hfs-linux.zip hfs -r plugins && cp -f hfs-macos-x64 hfs && zip hfs-mac.zip hfs -r plugins && cp -f hfs-macos-arm64 hfs && zip hfs-mac-arm.zip hfs -r plugins && rm hfs",
|
|
28
28
|
"dist-modules": "cp package*.json dist && cd dist && npm ci --omit=dev && npm run dist-crclib && rm package-lock.json && cd .. && node prune_modules",
|
|
29
29
|
"dist-crclib": "npm i -f --no-save --omit=dev @node-rs/crc32-win32-x64-msvc @node-rs/crc32-darwin-arm64 @node-rs/crc32-darwin-x64 ",
|
|
30
|
-
"dist-win": "
|
|
30
|
+
"dist-win": "cp package*.json dist && cd dist && npm ci --omit=dev && npm i -f --no-save --omit=dev @node-rs/crc32-win32 && pkg . -C gzip -t node16-win-x64",
|
|
31
31
|
"dist-node": "npm run dist-modules && cd dist && zip hfs-node.zip -r * -x *.zip *.exe hfs-* *.log logs"
|
|
32
32
|
},
|
|
33
33
|
"engines": {
|
package/src/adminApis.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.ctxAdminAccess = exports.favicon = exports.localhostAdmin = exports.adminApis = void 0;
|
|
30
|
+
exports.ctxAdminAccess = exports.title = exports.favicon = exports.localhostAdmin = exports.adminApis = void 0;
|
|
31
31
|
const apiMiddleware_1 = require("./apiMiddleware");
|
|
32
32
|
const config_1 = require("./config");
|
|
33
33
|
const listen_1 = require("./listen");
|
|
@@ -162,6 +162,7 @@ for (const [k, was] of Object.entries(exports.adminApis))
|
|
|
162
162
|
};
|
|
163
163
|
exports.localhostAdmin = (0, config_1.defineConfig)('localhost_admin', true);
|
|
164
164
|
exports.favicon = (0, config_1.defineConfig)('favicon');
|
|
165
|
+
exports.title = (0, config_1.defineConfig)('title', "File server");
|
|
165
166
|
function ctxAdminAccess(ctx) {
|
|
166
167
|
return !ctx.state.proxiedFor // we consider localhost_admin only if no proxy is detected
|
|
167
168
|
&& exports.localhostAdmin.get() && (0, misc_1.isLocalHost)(ctx)
|
package/src/api.monitor.js
CHANGED
|
@@ -77,6 +77,7 @@ const apis = {
|
|
|
77
77
|
function fromCtx(ctx) {
|
|
78
78
|
return ctx && {
|
|
79
79
|
user: (0, perm_1.getCurrentUsername)(ctx),
|
|
80
|
+
agent: getBrowser(ctx.get('user-agent')),
|
|
80
81
|
archive: ctx.state.archive,
|
|
81
82
|
path: (ctx.fileSource || ctx.state.archive) && ctx.path // only for downloading files
|
|
82
83
|
};
|
|
@@ -102,3 +103,36 @@ function getConnAddress(conn) {
|
|
|
102
103
|
port: conn.socket.remotePort,
|
|
103
104
|
};
|
|
104
105
|
}
|
|
106
|
+
function getBrowser(agent) {
|
|
107
|
+
for (const [name, re] of Object.entries(BROWSERS))
|
|
108
|
+
if (re.test(agent))
|
|
109
|
+
return name;
|
|
110
|
+
return '';
|
|
111
|
+
}
|
|
112
|
+
const BROWSERS = {
|
|
113
|
+
YaBrowser: /yabrowser/i,
|
|
114
|
+
AlamoFire: /alamofire/i,
|
|
115
|
+
Edge: /edge|edga|edgios|edg/i,
|
|
116
|
+
PhantomJS: /phantomjs/i,
|
|
117
|
+
Konqueror: /konqueror/i,
|
|
118
|
+
Amaya: /amaya/i,
|
|
119
|
+
Epiphany: /epiphany/i,
|
|
120
|
+
SeaMonkey: /seamonkey/i,
|
|
121
|
+
Flock: /flock/i,
|
|
122
|
+
OmniWeb: /omniweb/i,
|
|
123
|
+
Opera: /opera|OPR\//i,
|
|
124
|
+
Chromium: /chromium/i,
|
|
125
|
+
Facebook: /FBA[NV]/,
|
|
126
|
+
Chrome: /chrome|crios/i,
|
|
127
|
+
WinJs: /msapphost/i,
|
|
128
|
+
IE: /msie|trident/i,
|
|
129
|
+
Firefox: /firefox|fxios/i,
|
|
130
|
+
Safari: /safari/i,
|
|
131
|
+
PS5: /playstation 5/i,
|
|
132
|
+
PS4: /playstation 4/i,
|
|
133
|
+
PS3: /playstation 3/i,
|
|
134
|
+
PSP: /playstation portable/i,
|
|
135
|
+
PS: /playstation/i,
|
|
136
|
+
Xbox: /xbox/i,
|
|
137
|
+
UC: /UCBrowser/i,
|
|
138
|
+
};
|
package/src/api.vfs.js
CHANGED
|
@@ -63,10 +63,16 @@ const apis = {
|
|
|
63
63
|
return {};
|
|
64
64
|
},
|
|
65
65
|
async set_vfs({ uri, props }) {
|
|
66
|
+
var _a;
|
|
66
67
|
const n = await urlToNodeOriginal(uri);
|
|
67
68
|
if (!n)
|
|
68
69
|
return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND, 'path not found');
|
|
69
70
|
props = pickProps(props, ['name', 'source', 'masks', 'default', ...Object.keys(vfs_1.defaultPerms)]);
|
|
71
|
+
if (props.name && props.name !== (0, vfs_1.getNodeName)(n)) {
|
|
72
|
+
const parent = await urlToNodeOriginal((0, path_1.dirname)(uri));
|
|
73
|
+
if ((_a = parent === null || parent === void 0 ? void 0 : parent.children) === null || _a === void 0 ? void 0 : _a.find(x => (0, vfs_1.getNodeName)(x) === props.name))
|
|
74
|
+
return new apiMiddleware_1.ApiError(const_1.HTTP_CONFLICT, 'name already present');
|
|
75
|
+
}
|
|
70
76
|
props = (0, misc_1.objSameKeys)(props, v => v === null ? undefined : v); // null is a way to serialize undefined, that will restore default values
|
|
71
77
|
if (props.masks && typeof props.masks !== 'object')
|
|
72
78
|
delete props.masks;
|
|
@@ -84,10 +90,10 @@ const apis = {
|
|
|
84
90
|
return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_ACCEPTABLE, 'invalid parent');
|
|
85
91
|
if ((0, misc_1.isWindowsDrive)(source))
|
|
86
92
|
source += '\\'; // slash must be included, otherwise it will refer to the cwd of that drive
|
|
87
|
-
|
|
88
|
-
if (
|
|
93
|
+
n.children || (n.children = []);
|
|
94
|
+
if (n.children.find(x => x.source === source || (0, vfs_1.getNodeName)(x) === name))
|
|
89
95
|
return new apiMiddleware_1.ApiError(const_1.HTTP_CONFLICT, 'already present');
|
|
90
|
-
|
|
96
|
+
n.children.unshift({ source, name });
|
|
91
97
|
await (0, vfs_1.saveVfs)();
|
|
92
98
|
return {};
|
|
93
99
|
},
|
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_WINDOWS = exports.HTTP_SERVER_ERROR = 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.COMPATIBLE_API_VERSION = exports.API_VERSION = exports.SESSION_DURATION = 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_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.COMPATIBLE_API_VERSION = exports.API_VERSION = exports.SESSION_DURATION = exports.DAY = 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,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-
|
|
41
|
+
exports.BUILD_TIMESTAMP = "2023-02-24T21:59:58.935Z";
|
|
42
42
|
const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'));
|
|
43
43
|
exports.VERSION = pkg.version;
|
|
44
44
|
exports.DAY = 86400000;
|
|
@@ -67,8 +67,8 @@ exports.HTTP_RANGE_NOT_SATISFIABLE = 416;
|
|
|
67
67
|
exports.HTTP_FOOL = 418;
|
|
68
68
|
exports.HTTP_SERVER_ERROR = 500;
|
|
69
69
|
exports.IS_WINDOWS = process.platform === 'win32';
|
|
70
|
-
|
|
71
|
-
exports.APP_PATH = (0, path_1.dirname)(IS_BINARY ? process.
|
|
70
|
+
exports.IS_BINARY = !(0, path_1.basename)(process.execPath).includes('node'); // this won't be node if pkg was used
|
|
71
|
+
exports.APP_PATH = (0, path_1.dirname)(exports.IS_BINARY ? process.execPath : __dirname);
|
|
72
72
|
// we want this to be the first stuff to be printed, then we print it in this module, that is executed at the beginning
|
|
73
73
|
if (exports.DEV)
|
|
74
74
|
console.clear();
|
|
@@ -81,7 +81,7 @@ console.log('version', exports.VERSION || '-');
|
|
|
81
81
|
console.log('build', exports.BUILD_TIMESTAMP || '-');
|
|
82
82
|
if (exports.argv.cwd)
|
|
83
83
|
process.chdir(exports.argv.cwd);
|
|
84
|
-
else if (!process.
|
|
84
|
+
else if (!process.execPath.endsWith('.exe')) { // still considering whether to use this behavior with Windows users, who may be less accustomed to it
|
|
85
85
|
const dir = (0, path_1.join)((0, os_1.homedir)(), '.hfs');
|
|
86
86
|
try {
|
|
87
87
|
(0, fs_1.mkdirSync)(dir);
|
package/src/frontEndApis.js
CHANGED
|
@@ -63,11 +63,10 @@ exports.frontEndApis = {
|
|
|
63
63
|
const parentNode = await (0, vfs_1.urlToNode)(path, ctx);
|
|
64
64
|
if (!parentNode)
|
|
65
65
|
return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND, 'parent not found');
|
|
66
|
-
|
|
67
|
-
if (!source || !(0, vfs_1.hasPermission)(parentNode, 'can_upload', ctx))
|
|
66
|
+
if (!(0, vfs_1.hasPermission)(parentNode, 'can_upload', ctx))
|
|
68
67
|
return new apiMiddleware_1.ApiError(const_1.HTTP_FORBIDDEN);
|
|
69
68
|
try {
|
|
70
|
-
await (0, promises_1.mkdir)((0, path_1.join)(source, name));
|
|
69
|
+
await (0, promises_1.mkdir)((0, path_1.join)(parentNode.source, name));
|
|
71
70
|
return {};
|
|
72
71
|
}
|
|
73
72
|
catch (e) {
|
package/src/middlewares.js
CHANGED
|
@@ -115,7 +115,7 @@ const serveGuiAndSharedFiles = async (ctx, next) => {
|
|
|
115
115
|
const canRead = (0, vfs_1.hasPermission)(node, 'can_read', ctx);
|
|
116
116
|
const isFolder = await (0, vfs_1.nodeIsDirectory)(node);
|
|
117
117
|
if (isFolder && !path.endsWith('/'))
|
|
118
|
-
return ctx.redirect(
|
|
118
|
+
return ctx.redirect(ctx.originalUrl + '/');
|
|
119
119
|
if (canRead && !isFolder)
|
|
120
120
|
return node.source ? (0, serveFile_1.serveFileNode)(node)(ctx, next)
|
|
121
121
|
: next();
|
package/src/serveGuiFiles.js
CHANGED
|
@@ -82,6 +82,7 @@ async function treatIndex(ctx, body, filesUri) {
|
|
|
82
82
|
return body
|
|
83
83
|
.replace(/((?:src|href) *= *['"])\/?(?![a-z]+:\/\/)/g, '$1' + filesUri)
|
|
84
84
|
.replace('<link rel="icon"/>', `<link rel="icon" href="${adminApis_1.favicon.get() ? '/favicon.ico' : 'data:;'}" />`)
|
|
85
|
+
.replace('_HFS_TITLE_', adminApis_1.title.get())
|
|
85
86
|
.replace('_HFS_SESSION_', session instanceof apiMiddleware_1.ApiError ? 'null' : JSON.stringify(session))
|
|
86
87
|
// replacing this text allow us to avoid injecting in frontends that don't support plugins. Don't use a <--comment--> or it will be removed by webpack
|
|
87
88
|
.replace('_HFS_PLUGINS_', pluginsInjection);
|
package/src/update.js
CHANGED
|
@@ -19,7 +19,7 @@ async function getUpdate() {
|
|
|
19
19
|
}
|
|
20
20
|
exports.getUpdate = getUpdate;
|
|
21
21
|
async function update() {
|
|
22
|
-
if (
|
|
22
|
+
if (!const_1.IS_BINARY)
|
|
23
23
|
throw "only binary versions are supported for now";
|
|
24
24
|
const update = await getUpdate();
|
|
25
25
|
const assetSearch = { win32: 'windows', darwin: 'mac', linux: 'linux' }[process.platform];
|
|
@@ -30,7 +30,7 @@ async function update() {
|
|
|
30
30
|
throw "asset not found";
|
|
31
31
|
const url = asset.browser_download_url;
|
|
32
32
|
console.log("downloading", url);
|
|
33
|
-
const bin = process.
|
|
33
|
+
const bin = process.execPath;
|
|
34
34
|
const binPath = (0, path_1.dirname)(bin);
|
|
35
35
|
const binFile = (0, path_1.basename)(bin);
|
|
36
36
|
const newBinFile = 'new-' + binFile;
|
|
@@ -64,7 +64,7 @@ async function update() {
|
|
|
64
64
|
}
|
|
65
65
|
exports.update = update;
|
|
66
66
|
if (const_1.argv.updating) { // we were launched with a temporary name, restore original name to avoid breaking references
|
|
67
|
-
const bin = process.
|
|
67
|
+
const bin = process.execPath;
|
|
68
68
|
(0, fs_1.renameSync)(bin, (0, path_1.join)((0, path_1.dirname)(bin), const_1.argv.updating));
|
|
69
69
|
console.log("renamed binary file to", const_1.argv.updating);
|
|
70
70
|
}
|
package/src/upload.js
CHANGED
|
@@ -14,21 +14,25 @@ const config_1 = require("./config");
|
|
|
14
14
|
const util_os_1 = require("./util-os");
|
|
15
15
|
exports.deleteUnfinishedUploadsAfter = (0, config_1.defineConfig)('delete_unfinished_uploads_after');
|
|
16
16
|
exports.minAvailableMb = (0, config_1.defineConfig)('min_available_mb', 100);
|
|
17
|
+
const dontOverwriteUploading = (0, config_1.defineConfig)('dont_overwrite_uploading', false);
|
|
17
18
|
const waitingToBeDeleted = {};
|
|
18
19
|
function uploadWriter(base, path, ctx) {
|
|
19
|
-
if (!
|
|
20
|
+
if (!(0, vfs_1.hasPermission)(base, 'can_upload', ctx))
|
|
20
21
|
return fail(base.can_upload === false ? const_1.HTTP_FORBIDDEN : const_1.HTTP_UNAUTHORIZED);
|
|
21
22
|
const fullPath = (0, path_1.join)(base.source, path);
|
|
22
23
|
const dir = (0, path_1.dirname)(fullPath);
|
|
23
24
|
const min = exports.minAvailableMb.get() * (1 << 20);
|
|
24
25
|
const reqSize = Number(ctx.headers["content-length"]);
|
|
25
|
-
if (
|
|
26
|
+
if (reqSize)
|
|
26
27
|
try {
|
|
27
|
-
|
|
28
|
+
const free = (0, util_os_1.getFreeDiskSync)(dir);
|
|
29
|
+
if (typeof free !== 'number' || isNaN(free))
|
|
30
|
+
throw '';
|
|
31
|
+
if (reqSize > (0, util_os_1.getFreeDiskSync)(dir) - (min || 0))
|
|
28
32
|
return fail(const_1.HTTP_PAYLOAD_TOO_LARGE);
|
|
29
33
|
}
|
|
30
34
|
catch (e) {
|
|
31
|
-
console.warn("can't check disk size", String(e));
|
|
35
|
+
console.warn("can't check disk size", e.message || String(e));
|
|
32
36
|
}
|
|
33
37
|
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
34
38
|
const keepName = (0, path_1.basename)(fullPath).slice(-200);
|
|
@@ -59,12 +63,22 @@ function uploadWriter(base, path, ctx) {
|
|
|
59
63
|
}
|
|
60
64
|
cancelDeletion(tempName);
|
|
61
65
|
ret.on('close', () => {
|
|
62
|
-
if (!ctx.req.aborted)
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
if (!ctx.req.aborted) {
|
|
67
|
+
let dest = fullPath;
|
|
68
|
+
if (dontOverwriteUploading.get() && fs_1.default.existsSync(dest)) {
|
|
69
|
+
const ext = (0, path_1.extname)(dest);
|
|
70
|
+
const base = dest.slice(0, -ext.length);
|
|
71
|
+
let i = 1;
|
|
72
|
+
do
|
|
73
|
+
dest = `${base} (${i++})${ext}`;
|
|
74
|
+
while (fs_1.default.existsSync(dest));
|
|
75
|
+
}
|
|
76
|
+
return fs_1.default.rename(tempName, dest, err => {
|
|
77
|
+
err && console.error("couldn't rename temp to", dest, String(err));
|
|
65
78
|
if (resumable)
|
|
66
79
|
delayedDelete(resumable, 0);
|
|
67
80
|
});
|
|
81
|
+
}
|
|
68
82
|
if (resumable) // we don't want to be left with 2 temp files
|
|
69
83
|
return delayedDelete(tempName, 0);
|
|
70
84
|
const sec = exports.deleteUnfinishedUploadsAfter.get();
|
package/src/vfs.js
CHANGED
|
@@ -62,9 +62,9 @@ async function urlToNode(url, ctx, parent = exports.vfs, getRest) {
|
|
|
62
62
|
original: child,
|
|
63
63
|
isTemp: true,
|
|
64
64
|
};
|
|
65
|
-
inheritFromParent(parent, ret);
|
|
66
65
|
inheritMasks(ret, parent, name);
|
|
67
66
|
applyMasks(ret, parent, name);
|
|
67
|
+
inheritFromParent(parent, ret);
|
|
68
68
|
if (child) // yes
|
|
69
69
|
return urlToNode(rest, ctx, ret, getRest);
|
|
70
70
|
// not in the tree, we can see consider continuing on the disk
|
|
@@ -123,7 +123,8 @@ async function nodeIsDirectory(node) {
|
|
|
123
123
|
exports.nodeIsDirectory = nodeIsDirectory;
|
|
124
124
|
function hasPermission(node, perm, ctx) {
|
|
125
125
|
var _a;
|
|
126
|
-
return
|
|
126
|
+
return (node.source || perm !== 'can_upload') // Upload possible only if we know where to store. First check node.source because is supposedly faster.
|
|
127
|
+
&& matchWho((_a = node[perm]) !== null && _a !== void 0 ? _a : exports.defaultPerms[perm], ctx)
|
|
127
128
|
&& (perm !== 'can_see' || hasPermission(node, 'can_read', ctx)); // can_see is used to hide something you nonetheless can_read, so you MUST also can_read
|
|
128
129
|
}
|
|
129
130
|
exports.hasPermission = hasPermission;
|
|
@@ -165,8 +166,8 @@ async function* walkNode(parent, ctx, depth = 0, prefixPath = '') {
|
|
|
165
166
|
// we basename for depth>0 where we already have the rest of the path in the parent's url, and would be duplicated
|
|
166
167
|
const virtualBasename = (0, path_1.basename)(name);
|
|
167
168
|
item.isTemp = true;
|
|
168
|
-
inheritFromParent(parent, item);
|
|
169
169
|
applyMasks(item, parent, virtualBasename);
|
|
170
|
+
inheritFromParent(parent, item);
|
|
170
171
|
if (ctx && !hasPermission(item, 'can_see', ctx))
|
|
171
172
|
return;
|
|
172
173
|
yield item;
|
|
@@ -181,10 +182,10 @@ function applyMasks(item, parent, virtualBasename) {
|
|
|
181
182
|
const { masks } = parent;
|
|
182
183
|
if (!masks)
|
|
183
184
|
return;
|
|
184
|
-
for (const k
|
|
185
|
+
for (const [k, v] of Object.entries(masks))
|
|
185
186
|
if (k.startsWith('**/') && (0, micromatch_1.isMatch)(virtualBasename, k.slice(3))
|
|
186
187
|
|| !k.includes('/') && (0, micromatch_1.isMatch)(virtualBasename, k))
|
|
187
|
-
|
|
188
|
+
lodash_1.default.defaults(item, v);
|
|
188
189
|
}
|
|
189
190
|
function inheritMasks(item, parent, virtualBasename) {
|
|
190
191
|
const { masks } = parent;
|
|
@@ -197,7 +198,7 @@ function inheritMasks(item, parent, virtualBasename) {
|
|
|
197
198
|
else if (k.startsWith(virtualBasename + '/'))
|
|
198
199
|
o[k.slice(virtualBasename.length + 1)] = v;
|
|
199
200
|
if (Object.keys(o).length)
|
|
200
|
-
item.masks = o;
|
|
201
|
+
item.masks = lodash_1.default.defaults(item.masks, o);
|
|
201
202
|
}
|
|
202
203
|
function renameUnderPath(rename, path) {
|
|
203
204
|
if (!rename)
|