55 lines
2.8 KiB
JavaScript
55 lines
2.8 KiB
JavaScript
import pathPosix from "path-posix";
|
|
import { joinURL, normaliseHREF } from "../tools/url.js";
|
|
import { encodePath, makePathAbsolute, normalisePath } from "../tools/path.js";
|
|
import { parseXML, prepareFileFromProps } from "../tools/dav.js";
|
|
import { request, prepareRequestOptions } from "../request.js";
|
|
import { handleResponseCode, processGlobFilter, processResponsePayload } from "../response.js";
|
|
export async function getDirectoryContents(context, remotePath, options = {}) {
|
|
const requestOptions = prepareRequestOptions({
|
|
url: joinURL(context.remoteURL, encodePath(remotePath), "/"),
|
|
method: "PROPFIND",
|
|
headers: {
|
|
Accept: "text/plain,application/xml",
|
|
Depth: options.deep ? "infinity" : "1"
|
|
}
|
|
}, context, options);
|
|
const response = await request(requestOptions, context);
|
|
handleResponseCode(context, response);
|
|
const responseData = await response.text();
|
|
if (!responseData) {
|
|
throw new Error("Failed parsing directory contents: Empty response");
|
|
}
|
|
const davResp = await parseXML(responseData);
|
|
const _remotePath = makePathAbsolute(remotePath);
|
|
const remoteBasePath = makePathAbsolute(context.remoteBasePath || context.remotePath);
|
|
let files = getDirectoryFiles(davResp, remoteBasePath, _remotePath, options.details, options.includeSelf);
|
|
if (options.glob) {
|
|
files = processGlobFilter(files, options.glob);
|
|
}
|
|
return processResponsePayload(response, files, options.details);
|
|
}
|
|
function getDirectoryFiles(result, serverremoteBasePath, requestPath, isDetailed = false, includeSelf = false) {
|
|
const serverBase = pathPosix.join(serverremoteBasePath, "/");
|
|
// Extract the response items (directory contents)
|
|
const { multistatus: { response: responseItems } } = result;
|
|
// Map all items to a consistent output structure (results)
|
|
const nodes = responseItems.map(item => {
|
|
// HREF is the file path (in full) - The href is already XML entities decoded (e.g. foo&bar is reverted to foo&bar)
|
|
const href = normaliseHREF(item.href);
|
|
// Each item should contain a stat object
|
|
const { propstat: { prop: props } } = item;
|
|
// Process the true full filename (minus the base server path)
|
|
const filename = serverBase === "/"
|
|
? decodeURIComponent(normalisePath(href))
|
|
: normalisePath(pathPosix.relative(decodeURIComponent(serverBase), decodeURIComponent(href)));
|
|
return prepareFileFromProps(props, filename, isDetailed);
|
|
});
|
|
// If specified, also return the current directory
|
|
if (includeSelf) {
|
|
return nodes;
|
|
}
|
|
// Else, filter out the item pointing to the current directory (not needed)
|
|
return nodes.filter(item => item.basename &&
|
|
(item.type === "file" || item.filename !== requestPath.replace(/\/$/, "")));
|
|
}
|