Fix XML parsing for WebDav
This was a regression caused by the `@libs/xml` upgrade in v2.6.0
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
services:
|
services:
|
||||||
website:
|
website:
|
||||||
image: ghcr.io/bewcloud/bewcloud:v2.7.0
|
image: ghcr.io/bewcloud/bewcloud:v2.7.1
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- 127.0.0.1:8000:8000
|
- 127.0.0.1:8000:8000
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export function addDavPrefixToKeys(object: Record<string, any>, prefix = 'D:'):
|
|||||||
|
|
||||||
if (typeof object === 'object' && object !== null) {
|
if (typeof object === 'object' && object !== null) {
|
||||||
return Object.entries(object).reduce((reducedObject, [key, value]) => {
|
return Object.entries(object).reduce((reducedObject, [key, value]) => {
|
||||||
const prefixedKey = key === 'xml' || key.startsWith('#') || key.startsWith('@') ? key : `${prefix}${key}`;
|
const prefixedKey = key.startsWith('#') || key.startsWith('@') ? key : `${prefix}${key}`;
|
||||||
reducedObject[prefixedKey] = addDavPrefixToKeys(value);
|
reducedObject[prefixedKey] = addDavPrefixToKeys(value);
|
||||||
return reducedObject;
|
return reducedObject;
|
||||||
}, {} as Record<string, any>);
|
}, {} as Record<string, any>);
|
||||||
@@ -105,10 +105,8 @@ export async function buildPropFindResponse(
|
|||||||
const filePaths = await getFilePaths(join(rootPath, queryPath), depth);
|
const filePaths = await getFilePaths(join(rootPath, queryPath), depth);
|
||||||
|
|
||||||
const response: Record<string, any> = {
|
const response: Record<string, any> = {
|
||||||
xml: {
|
|
||||||
'@version': '1.0',
|
'@version': '1.0',
|
||||||
'@encoding': 'UTF-8',
|
'@encoding': 'UTF-8',
|
||||||
},
|
|
||||||
multistatus: {
|
multistatus: {
|
||||||
'@xmlns:D': 'DAV:',
|
'@xmlns:D': 'DAV:',
|
||||||
response: [],
|
response: [],
|
||||||
|
|||||||
217
lib/utils/webdav_test.ts
Normal file
217
lib/utils/webdav_test.ts
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
import { assertEquals } from '@std/assert';
|
||||||
|
import { parse, stringify } from '@libs/xml';
|
||||||
|
|
||||||
|
import { addDavPrefixToKeys, getProperDestinationPath, getPropertyNames } from './webdav.ts';
|
||||||
|
|
||||||
|
Deno.test('that getProperDestinationPath works', () => {
|
||||||
|
const tests: { input: string; expected?: string }[] = [
|
||||||
|
{
|
||||||
|
input: `http://127.0.0.1/dav/12345-abcde-67890`,
|
||||||
|
expected: 'dav/12345-abcde-67890',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: `http://127.0.0.1/dav/spaced-%20uid`,
|
||||||
|
expected: 'dav/spaced- uid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: `http://127.0.0.1/dav/something-deeper/spaced-%C3%A7uid`,
|
||||||
|
expected: 'dav/something-deeper/spaced-çuid',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const test of tests) {
|
||||||
|
const output = getProperDestinationPath(test.input);
|
||||||
|
if (test.expected) {
|
||||||
|
assertEquals(output, test.expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test('that addDavPrefixToKeys works', () => {
|
||||||
|
const tests: {
|
||||||
|
input: { object: Record<string, any> | Record<string, any>[]; prefix?: string };
|
||||||
|
expected: Record<string, any>;
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
object: {
|
||||||
|
displayname: 'test',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: {
|
||||||
|
'D:displayname': 'test',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
object: [
|
||||||
|
{ displayname: 'test' },
|
||||||
|
{ color: 'black' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
expected: [
|
||||||
|
{ 'D:displayname': 'test' },
|
||||||
|
{ 'D:color': 'black' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
object: { '@version': '1.0', '@encoding': 'UTF-8', displayname: 'test', color: 'black' },
|
||||||
|
},
|
||||||
|
expected: {
|
||||||
|
'@version': '1.0',
|
||||||
|
'@encoding': 'UTF-8',
|
||||||
|
'D:displayname': 'test',
|
||||||
|
'D:color': 'black',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
object: { displayname: 'test', color: 'black' },
|
||||||
|
prefix: 'S:',
|
||||||
|
},
|
||||||
|
expected: {
|
||||||
|
'S:displayname': 'test',
|
||||||
|
'S:color': 'black',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const test of tests) {
|
||||||
|
const output = addDavPrefixToKeys(test.input.object, test.input.prefix);
|
||||||
|
if (test.expected) {
|
||||||
|
assertEquals(output, test.expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test('that getPropertyNames works', () => {
|
||||||
|
const tests: {
|
||||||
|
input: Record<string, any>;
|
||||||
|
expected: string[];
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
'D:propfind': {
|
||||||
|
'D:prop': {
|
||||||
|
'D:displayname': 'test',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: ['displayname'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
'D:propfind': {
|
||||||
|
'D:prop': {
|
||||||
|
'D:displayname': 'test',
|
||||||
|
'D:color': 'black',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: ['displayname', 'color'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: {},
|
||||||
|
expected: ['allprop'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const test of tests) {
|
||||||
|
const output = getPropertyNames(test.input);
|
||||||
|
if (test.expected) {
|
||||||
|
assertEquals(output, test.expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test('that @libs/xml.parse works', () => {
|
||||||
|
const tests: { input: string; expected: Record<string, any> }[] = [
|
||||||
|
{
|
||||||
|
input: `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<propfind xmlns="DAV:">
|
||||||
|
<prop>
|
||||||
|
<displayname>test</displayname>
|
||||||
|
</prop>
|
||||||
|
</propfind>`,
|
||||||
|
expected: {
|
||||||
|
'@version': '1.0',
|
||||||
|
'@encoding': 'UTF-8',
|
||||||
|
propfind: {
|
||||||
|
'@xmlns': 'DAV:',
|
||||||
|
prop: {
|
||||||
|
displayname: 'test',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<D:propfind xmlns:D="DAV:">
|
||||||
|
<D:prop>
|
||||||
|
<D:displayname>test</D:displayname>
|
||||||
|
</D:prop>
|
||||||
|
</D:propfind>`,
|
||||||
|
expected: {
|
||||||
|
'@version': '1.0',
|
||||||
|
'@encoding': 'UTF-8',
|
||||||
|
'D:propfind': {
|
||||||
|
'@xmlns:D': 'DAV:',
|
||||||
|
'D:prop': {
|
||||||
|
'D:displayname': 'test',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const test of tests) {
|
||||||
|
const output = parse(test.input);
|
||||||
|
assertEquals(output, test.expected);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test('that @libs/xml.stringify works', () => {
|
||||||
|
const tests: { input: Record<string, any>; expected: string }[] = [
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
'@version': '1.0',
|
||||||
|
'@encoding': 'UTF-8',
|
||||||
|
'D:propfind': {
|
||||||
|
'D:prop': {
|
||||||
|
'D:displayname': 'test',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<D:propfind>
|
||||||
|
<D:prop>
|
||||||
|
<D:displayname>test</D:displayname>
|
||||||
|
</D:prop>
|
||||||
|
</D:propfind>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: {
|
||||||
|
'@version': '1.0',
|
||||||
|
'@encoding': 'UTF-8',
|
||||||
|
'D:propfind': {
|
||||||
|
'@xmlns:D': 'DAV:',
|
||||||
|
'D:prop': {
|
||||||
|
'D:displayname': 'test',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<D:propfind xmlns:D="DAV:">
|
||||||
|
<D:prop>
|
||||||
|
<D:displayname>test</D:displayname>
|
||||||
|
</D:prop>
|
||||||
|
</D:propfind>`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const test of tests) {
|
||||||
|
const output = stringify(test.input);
|
||||||
|
assertEquals(output, test.expected);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -168,10 +168,8 @@ export const handler: Handler<Data, FreshContextState> = async (request, context
|
|||||||
await lock.acquire();
|
await lock.acquire();
|
||||||
|
|
||||||
const responseXml: Record<string, any> = {
|
const responseXml: Record<string, any> = {
|
||||||
xml: {
|
|
||||||
'@version': '1.0',
|
'@version': '1.0',
|
||||||
'@encoding': 'UTF-8',
|
'@encoding': 'UTF-8',
|
||||||
},
|
|
||||||
prop: {
|
prop: {
|
||||||
'@xmlns:D': 'DAV:',
|
'@xmlns:D': 'DAV:',
|
||||||
lockdiscovery: {
|
lockdiscovery: {
|
||||||
@@ -218,10 +216,17 @@ export const handler: Handler<Data, FreshContextState> = async (request, context
|
|||||||
const depthString = request.headers.get('depth');
|
const depthString = request.headers.get('depth');
|
||||||
const depth = depthString ? parseInt(depthString, 10) : null;
|
const depth = depthString ? parseInt(depthString, 10) : null;
|
||||||
const xml = await request.clone().text();
|
const xml = await request.clone().text();
|
||||||
|
let properties: string[] = [];
|
||||||
|
|
||||||
const parsedXml = parse(xml);
|
try {
|
||||||
|
const parsedXml = parse(xml) as Record<string, any>;
|
||||||
|
|
||||||
const properties = getPropertyNames(parsedXml);
|
properties = getPropertyNames(parsedXml);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error parsing XML: ', error);
|
||||||
|
|
||||||
|
properties = ['allprop'];
|
||||||
|
}
|
||||||
|
|
||||||
await ensureUserPathIsValidAndSecurelyAccessible(userId, filePath);
|
await ensureUserPathIsValidAndSecurelyAccessible(userId, filePath);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user