hfs 3.3.0-beta2 → 3.3.0-beta3
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/npm-shrinkwrap.json +5 -5
- package/package.json +1 -1
- package/src/vfs.js +2 -0
- package/src/watchLoad.js +4 -1
- package/src/webdav.js +15 -12
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hfs",
|
|
3
|
-
"version": "3.3.0-
|
|
3
|
+
"version": "3.3.0-beta3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "hfs",
|
|
9
|
-
"version": "3.3.0-
|
|
9
|
+
"version": "3.3.0-beta3",
|
|
10
10
|
"license": "GPL-3.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@gregoranders/csv": "^0.0.13",
|
|
@@ -1710,9 +1710,9 @@
|
|
|
1710
1710
|
}
|
|
1711
1711
|
},
|
|
1712
1712
|
"node_modules/pvutils": {
|
|
1713
|
-
"version": "1.
|
|
1714
|
-
"resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.
|
|
1715
|
-
"integrity": "sha512-
|
|
1713
|
+
"version": "1.2.0",
|
|
1714
|
+
"resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.2.0.tgz",
|
|
1715
|
+
"integrity": "sha512-BbubeCEyTuQjVMakvJQ/Sxbc93F2pwmbsxONT/ZRrwU7Ua38d8unYTwXpTVLAKJ4BDuH9IGztCjQcd/N/39Dvg==",
|
|
1716
1716
|
"license": "MIT",
|
|
1717
1717
|
"engines": {
|
|
1718
1718
|
"node": ">=16.0.0"
|
package/package.json
CHANGED
package/src/vfs.js
CHANGED
|
@@ -261,6 +261,8 @@ function nodeIsFolder(node) {
|
|
|
261
261
|
}
|
|
262
262
|
// we mark folder paths with a final slash – the UI already does so, but the config may be modified
|
|
263
263
|
function persistFolderMarker(node) {
|
|
264
|
+
if ('original' in node && !node.original)
|
|
265
|
+
return; // disk-derived nodes are temporary and must not persist VFS changes
|
|
264
266
|
const stored = node.original || node; // temporary VFS nodes must update their stored original for saveVfs to persist the marker
|
|
265
267
|
if (!stored.source || (0, misc_1.hasFinalSlash)(stored.source))
|
|
266
268
|
return;
|
package/src/watchLoad.js
CHANGED
|
@@ -19,6 +19,8 @@ function watchLoad(path, parser, { failedOnFirstAttempt, immediateFirst } = {})
|
|
|
19
19
|
let last;
|
|
20
20
|
const emitter = new events_1.BetterEventEmitter();
|
|
21
21
|
const save = (0, debounceAsync_1.debounceAsync)(async (data, { reparse = false } = {}) => {
|
|
22
|
+
if (doing)
|
|
23
|
+
await debounced.isWorking();
|
|
22
24
|
await promises_1.default.writeFile(path, data, 'utf8');
|
|
23
25
|
last = data;
|
|
24
26
|
if (reparse)
|
|
@@ -59,9 +61,10 @@ function watchLoad(path, parser, { failedOnFirstAttempt, immediateFirst } = {})
|
|
|
59
61
|
async function load() {
|
|
60
62
|
if (doing)
|
|
61
63
|
return;
|
|
64
|
+
const saving = save.flush(); // saves started after this handoff wait for the read, while we wait only for the save captured here
|
|
62
65
|
doing = true;
|
|
63
66
|
try {
|
|
64
|
-
await
|
|
67
|
+
await saving; // apply pending saves first
|
|
65
68
|
const text = await (0, util_files_1.readFileWithBusyRetry)(path).catch(e => {
|
|
66
69
|
if (e.code === 'EPERM')
|
|
67
70
|
console.error("Missing permissions on file", path); // warn user, who could be clueless about this problem
|
package/src/webdav.js
CHANGED
|
@@ -452,14 +452,18 @@ async function applyProppatchProp(prop, node, path, ctx) {
|
|
|
452
452
|
const k = prop.name.toLowerCase();
|
|
453
453
|
if (PROPPATCH_PROTECTED_LIVE_PROPS.has(k))
|
|
454
454
|
return cross_1.HTTP_FORBIDDEN;
|
|
455
|
-
if (
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
455
|
+
if (!PROPPATCH_UTIME_PROPS.has(k)
|
|
456
|
+
&& !(const_1.IS_WINDOWS && k === 'win32fileattributes'))
|
|
457
|
+
return cross_1.HTTP_OK; // PROPPATCH is only persisted when HFS gets real dead-property storage; no-op success keeps Windows and macOS clients from aborting writes
|
|
458
|
+
const { source } = node;
|
|
459
|
+
if (!source)
|
|
460
|
+
return cross_1.HTTP_FORBIDDEN;
|
|
461
|
+
// WebDAV clients patch metadata right after upload; outside that short same-username grace, metadata writes are file modifications
|
|
462
|
+
const missingWritePerm = canOverwrite.has(path + (0, cross_1.prefix)('|', (0, auth_1.getCurrentUsername)(ctx))) ? 0
|
|
463
|
+
: (0, vfs_1.statusCodeForMissingPerm)(node, 'can_delete', ctx, false);
|
|
464
|
+
if (missingWritePerm)
|
|
465
|
+
return missingWritePerm;
|
|
466
|
+
if (PROPPATCH_UTIME_PROPS.has(k)) {
|
|
463
467
|
const date = new Date(String(prop.value));
|
|
464
468
|
if (isNaN(Number(date)))
|
|
465
469
|
return cross_1.HTTP_BAD_REQUEST;
|
|
@@ -467,18 +471,17 @@ async function applyProppatchProp(prop, node, path, ctx) {
|
|
|
467
471
|
const atime = k === 'win32lastaccesstime' ? date : stats?.atime ?? new Date();
|
|
468
472
|
const mtime = k === 'win32lastmodifiedtime' ? date : stats?.mtime ?? new Date();
|
|
469
473
|
// WebDAV clients often use dead properties for file times; apply the portable subset instead of only pretending success
|
|
470
|
-
await (0, promises_1.utimes)(
|
|
474
|
+
await (0, promises_1.utimes)(source, atime, mtime);
|
|
471
475
|
}
|
|
472
|
-
|
|
476
|
+
else {
|
|
473
477
|
const attributes = parseWindowsFileAttributes(prop.value);
|
|
474
478
|
if (attributes === undefined)
|
|
475
479
|
return cross_1.HTTP_BAD_REQUEST;
|
|
476
480
|
// fswin is already our Windows attribute bridge; this keeps PROPPATCH metadata aligned with the actual filesystem
|
|
477
|
-
const ok = await new Promise(resolve => fswin_1.default.setAttributes(
|
|
481
|
+
const ok = await new Promise(resolve => fswin_1.default.setAttributes(source, lodash_1.default.mapValues(WINDOWS_FILE_ATTRIBUTE_FLAGS, flag => Boolean(attributes & flag)), ok => resolve(Boolean(ok))));
|
|
478
482
|
if (!ok)
|
|
479
483
|
return cross_1.HTTP_SERVER_ERROR;
|
|
480
484
|
}
|
|
481
|
-
// PROPPATCH is only persisted when HFS gets real dead-property storage; no-op success keeps Windows and macOS clients from aborting writes
|
|
482
485
|
return cross_1.HTTP_OK;
|
|
483
486
|
}
|
|
484
487
|
function parseWindowsFileAttributes(v) {
|