meatloaf-config/src/app/vendor/webdav-component/esm/protocol/parse.js
Jaime Idolpx 4a2f6032d2 feat: add WebDAV integration and utility functions
- Introduced a new `webdav-component` package for WebDAV protocol handling.
- Implemented `webdav.ts` with functions for managing WebDAV operations such as listing directories, checking file existence, creating folders, deleting paths, moving files, and handling file uploads/downloads.
- Added path normalization and utility functions for handling WebDAV paths.
- Enhanced the `Tag` class in `webdav3.py` to correctly register XML namespaces, improving compatibility with WebDAV responses.
2026-06-07 17:48:37 -04:00

76 lines
2.9 KiB
JavaScript

import { stripHostPrefix } from '../utils/url.js';
/**
* Parse a PROPFIND `multistatus` XML document into a listing keyed by name.
* The entry whose URI matches the requested URL is keyed as `.` (the current
* collection).
*/
export function parsePropfindListing(xml, ctx) {
const files = {};
const compareUrl = ctx.url.replace(/\/+$/, '');
xml.querySelectorAll('response').forEach((node) => {
const href = node.querySelector('href');
if (!href || !href.textContent) {
return;
}
const itemUri = href.textContent;
const compareItemUri = itemUri.replace(/\/+$/, '');
// Find the first 200 propstat; ignore 404s etc.
let propsNode = null;
node.querySelectorAll('propstat').forEach((propstat) => {
if (propsNode) {
return;
}
const status = propstat.querySelector('status');
if (status && /200/.test(status.textContent || '')) {
propsNode = propstat;
}
});
if (!propsNode) {
console.error('Cannot find properties for: ' + itemUri);
return;
}
// Alias for narrow-friendly access below.
const props = propsNode;
// Displayname falls back to the last path segment.
let name = itemUri.replace(/\/$/, '').split('/').pop() || '';
try {
name = decodeURIComponent(name);
}
catch {
// leave name as-is on malformed encoding
}
const displayname = props.querySelector('displayname');
if (displayname && displayname.textContent) {
name = displayname.textContent;
}
// Some servers (e.g. lighttpd) prefix each name with the hostname.
let host = null;
try {
host = new URL(ctx.baseUrl).hostname;
}
catch {
host = null;
}
name = stripHostPrefix(name, host);
const isDir = !!node.querySelector('resourcetype collection');
const lengthEl = props.querySelector('getcontentlength');
const mimeEl = props.querySelector('getcontenttype');
const modifiedEl = props.querySelector('getlastmodified');
const permsEl = props.querySelector('permissions');
const entry = {
uri: itemUri,
url: itemUri,
path: itemUri.substring(ctx.baseUrl.length),
name,
size: !isDir && lengthEl?.textContent ? parseInt(lengthEl.textContent, 10) : null,
mime: !isDir && mimeEl?.textContent ? mimeEl.textContent : null,
modified: modifiedEl?.textContent ? new Date(modifiedEl.textContent) : null,
isDir,
permissions: permsEl?.textContent ? permsEl.textContent : null,
};
const key = compareItemUri === compareUrl ? '.' : name;
files[key] = entry;
});
return files;
}
//# sourceMappingURL=parse.js.map