@nextcloud/files 4.0.0-beta.0 → 4.0.0-beta.2

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/dist/dav.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dav.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"dav.cjs","sources":["../lib/dav/davPermissions.ts","../lib/dav/davProperties.ts","../lib/dav/dav.ts"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\nimport { Permission } from '../permissions'\n\n/**\n * Parse the WebDAV permission string to a permission enum\n *\n * @param permString The DAV permission string\n */\nexport const parsePermissions = function(permString = ''): number {\n\tlet permissions = Permission.NONE\n\n\tif (!permString) { return permissions }\n\n\tif (permString.includes('C') || permString.includes('K')) { permissions |= Permission.CREATE }\n\n\tif (permString.includes('G')) { permissions |= Permission.READ }\n\n\tif (permString.includes('W') || permString.includes('N') || permString.includes('V')) { permissions |= Permission.UPDATE }\n\n\tif (permString.includes('D')) { permissions |= Permission.DELETE }\n\n\tif (permString.includes('R')) { permissions |= Permission.SHARE }\n\n\treturn permissions\n}\n","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\nimport { getCurrentUser } from '@nextcloud/auth'\nimport logger from '../utils/logger'\n\nexport type DavProperty = { [key: string]: string }\n\nexport const defaultDavProperties = [\n\t'd:getcontentlength',\n\t'd:getcontenttype',\n\t'd:getetag',\n\t'd:getlastmodified',\n\t'd:creationdate',\n\t'd:displayname',\n\t'd:quota-available-bytes',\n\t'd:resourcetype',\n\t'nc:has-preview',\n\t'nc:is-encrypted',\n\t'nc:mount-type',\n\t'oc:comments-unread',\n\t'oc:favorite',\n\t'oc:fileid',\n\t'oc:owner-display-name',\n\t'oc:owner-id',\n\t'oc:permissions',\n\t'oc:size',\n]\n\nexport const defaultDavNamespaces = {\n\td: 'DAV:',\n\tnc: 'http://nextcloud.org/ns',\n\toc: 'http://owncloud.org/ns',\n\tocs: 'http://open-collaboration-services.org/ns',\n}\n\n/**\n * Register custom DAV properties\n *\n * Can be used if your app introduces custom DAV properties, so e.g. the files app can make use of it.\n *\n * @param prop The property\n * @param namespace The namespace of the property\n */\nexport const registerDavProperty = function(prop: string, namespace: DavProperty = { nc: 'http://nextcloud.org/ns' }): boolean {\n\tif (typeof window._nc_dav_properties === 'undefined') {\n\t\twindow._nc_dav_properties = [...defaultDavProperties]\n\t\twindow._nc_dav_namespaces = { ...defaultDavNamespaces }\n\t}\n\n\tconst namespaces = { ...window._nc_dav_namespaces, ...namespace }\n\n\t// Check duplicates\n\tif (window._nc_dav_properties.find((search) => search === prop)) {\n\t\tlogger.warn(`${prop} already registered`, { prop })\n\t\treturn false\n\t}\n\n\tif (prop.startsWith('<') || prop.split(':').length !== 2) {\n\t\tlogger.error(`${prop} is not valid. See example: 'oc:fileid'`, { prop })\n\t\treturn false\n\t}\n\n\tconst ns = prop.split(':')[0]\n\tif (!namespaces[ns]) {\n\t\tlogger.error(`${prop} namespace unknown`, { prop, namespaces })\n\t\treturn false\n\t}\n\n\twindow._nc_dav_properties.push(prop)\n\twindow._nc_dav_namespaces = namespaces\n\treturn true\n}\n\n/**\n * Get the registered dav properties\n */\nexport const getDavProperties = function(): string {\n\tif (typeof window._nc_dav_properties === 'undefined') {\n\t\twindow._nc_dav_properties = [...defaultDavProperties]\n\t}\n\n\treturn window._nc_dav_properties.map((prop) => `<${prop} />`).join(' ')\n}\n\n/**\n * Get the registered dav namespaces\n */\nexport const getDavNameSpaces = function(): string {\n\tif (typeof window._nc_dav_namespaces === 'undefined') {\n\t\twindow._nc_dav_namespaces = { ...defaultDavNamespaces }\n\t}\n\n\treturn Object.keys(window._nc_dav_namespaces)\n\t\t.map((ns) => `xmlns:${ns}=\"${window._nc_dav_namespaces?.[ns]}\"`)\n\t\t.join(' ')\n}\n\n/**\n * Get the default PROPFIND request body\n */\nexport const getDefaultPropfind = function(): string {\n\treturn `<?xml version=\"1.0\"?>\n\t\t<d:propfind ${getDavNameSpaces()}>\n\t\t\t<d:prop>\n\t\t\t\t${getDavProperties()}\n\t\t\t</d:prop>\n\t\t</d:propfind>`\n}\n\n/**\n * Get the REPORT body to filter for favorite nodes\n */\nexport const getFavoritesReport = function(): string {\n\treturn `<?xml version=\"1.0\"?>\n\t\t<oc:filter-files ${getDavNameSpaces()}>\n\t\t\t<d:prop>\n\t\t\t\t${getDavProperties()}\n\t\t\t</d:prop>\n\t\t\t<oc:filter-rules>\n\t\t\t\t<oc:favorite>1</oc:favorite>\n\t\t\t</oc:filter-rules>\n\t\t</oc:filter-files>`\n}\n\n/**\n * Get the SEARCH body to search for recently modified files\n *\n * @param lastModified Oldest timestamp to include (Unix timestamp)\n * @example\n * ```ts\n * // SEARCH for recent files need a different DAV endpoint\n * const client = davGetClient(generateRemoteUrl('dav'))\n * // Timestamp of last week\n * const lastWeek = Math.round(Date.now() / 1000) - (60 * 60 * 24 * 7)\n * const contentsResponse = await client.getDirectoryContents(path, {\n * details: true,\n * data: davGetRecentSearch(lastWeek),\n * headers: {\n * method: 'SEARCH',\n * 'Content-Type': 'application/xml; charset=utf-8',\n * },\n * deep: true,\n * }) as ResponseDataDetailed<FileStat[]>\n * ```\n */\nexport const getRecentSearch = function(lastModified: number): string {\n\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<d:searchrequest ${getDavNameSpaces()}\n\txmlns:ns=\"https://github.com/icewind1991/SearchDAV/ns\">\n\t<d:basicsearch>\n\t\t<d:select>\n\t\t\t<d:prop>\n\t\t\t\t${getDavProperties()}\n\t\t\t</d:prop>\n\t\t</d:select>\n\t\t<d:from>\n\t\t\t<d:scope>\n\t\t\t\t<d:href>/files/${getCurrentUser()?.uid}/</d:href>\n\t\t\t\t<d:depth>infinity</d:depth>\n\t\t\t</d:scope>\n\t\t</d:from>\n\t\t<d:where>\n\t\t\t<d:and>\n\t\t\t\t<d:or>\n\t\t\t\t\t<d:not>\n\t\t\t\t\t\t<d:eq>\n\t\t\t\t\t\t\t<d:prop>\n\t\t\t\t\t\t\t\t<d:getcontenttype/>\n\t\t\t\t\t\t\t</d:prop>\n\t\t\t\t\t\t\t<d:literal>httpd/unix-directory</d:literal>\n\t\t\t\t\t\t</d:eq>\n\t\t\t\t\t</d:not>\n\t\t\t\t\t<d:eq>\n\t\t\t\t\t\t<d:prop>\n\t\t\t\t\t\t\t<oc:size/>\n\t\t\t\t\t\t</d:prop>\n\t\t\t\t\t\t<d:literal>0</d:literal>\n\t\t\t\t\t</d:eq>\n\t\t\t\t</d:or>\n\t\t\t\t<d:gt>\n\t\t\t\t\t<d:prop>\n\t\t\t\t\t\t<d:getlastmodified/>\n\t\t\t\t\t</d:prop>\n\t\t\t\t\t<d:literal>${lastModified}</d:literal>\n\t\t\t\t</d:gt>\n\t\t\t</d:and>\n\t\t</d:where>\n\t\t<d:orderby>\n\t\t\t<d:order>\n\t\t\t\t<d:prop>\n\t\t\t\t\t<d:getlastmodified/>\n\t\t\t\t</d:prop>\n\t\t\t\t<d:descending/>\n\t\t\t</d:order>\n\t\t</d:orderby>\n\t\t<d:limit>\n\t\t\t<d:nresults>100</d:nresults>\n\t\t\t<ns:firstresult>0</ns:firstresult>\n\t\t</d:limit>\n\t</d:basicsearch>\n</d:searchrequest>`\n}\n","/*\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { DAVResultResponseProps, FileStat, ResponseDataDetailed, WebDAVClient } from 'webdav'\nimport type { Node, NodeData } from '../node/index.ts'\n\nimport { getCurrentUser, getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth'\nimport { getSharingToken, isPublicShare } from '@nextcloud/sharing/public'\nimport { generateRemoteUrl } from '@nextcloud/router'\nimport { CancelablePromise } from 'cancelable-promise'\nimport { createClient, getPatcher } from 'webdav'\nimport { parsePermissions } from './davPermissions.ts'\nimport { getFavoritesReport } from './davProperties.ts'\nimport { File, Folder, NodeStatus } from '../node/index.ts'\n\n/**\n * Nextcloud DAV result response\n */\ninterface ResponseProps extends DAVResultResponseProps {\n\tcreationdate: string\n\tpermissions: string\n\tmime: string\n\tfileid: number\n\tsize: number\n\t'owner-id': string | number\n}\n\n/**\n * Get the DAV root path for the current user or public share\n */\nexport function getRootPath(): string {\n\tif (isPublicShare()) {\n\t\treturn `/files/${getSharingToken()}`\n\t}\n\treturn `/files/${getCurrentUser()?.uid}`\n}\n\n/**\n * The DAV root path for the current user\n * This is a cached version of `getRemoteURL`\n */\nexport const defaultRootPath = getRootPath()\n\n/**\n * Get the DAV remote URL used as base URL for the WebDAV client\n * It also handles public shares\n */\nexport function getRemoteURL(): string {\n\tconst url = generateRemoteUrl('dav')\n\tif (isPublicShare()) {\n\t\treturn url.replace('remote.php', 'public.php')\n\t}\n\treturn url\n}\n\n/**\n * The DAV remote URL used as base URL for the WebDAV client\n * This is a cached version of `getRemoteURL`\n */\nexport const defaultRemoteURL = getRemoteURL()\n\n/**\n * Get a WebDAV client configured to include the Nextcloud request token\n *\n * @param remoteURL The DAV server remote URL\n * @param headers Optional additional headers to set for every request\n */\nexport const getClient = function(remoteURL = defaultRemoteURL, headers: Record<string, string> = {}) {\n\tconst client = createClient(remoteURL, { headers })\n\n\t/**\n\t * Set headers for DAV requests\n\t * @param token CSRF token\n\t */\n\tfunction setHeaders(token: string | null) {\n\t\tclient.setHeaders({\n\t\t\t...headers,\n\t\t\t// Add this so the server knows it is an request from the browser\n\t\t\t'X-Requested-With': 'XMLHttpRequest',\n\t\t\t// Inject user auth\n\t\t\trequesttoken: token ?? '',\n\t\t})\n\t}\n\n\t// refresh headers when request token changes\n\tonRequestTokenUpdate(setHeaders)\n\tsetHeaders(getRequestToken())\n\n\t/**\n\t * Allow to override the METHOD to support dav REPORT\n\t *\n\t * @see https://github.com/perry-mitchell/webdav-client/blob/8d9694613c978ce7404e26a401c39a41f125f87f/source/request.ts\n\t */\n\tconst patcher = getPatcher()\n\t// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n\t// @ts-ignore\n\t// https://github.com/perry-mitchell/hot-patcher/issues/6\n\tpatcher.patch('fetch', (url: string, options: RequestInit): Promise<Response> => {\n\t\tconst headers = options.headers as Record<string, string>\n\t\tif (headers?.method) {\n\t\t\toptions.method = headers.method\n\t\t\tdelete headers.method\n\t\t}\n\t\treturn fetch(url, options)\n\t})\n\n\treturn client\n}\n\n/**\n * Use WebDAV to query for favorite Nodes\n *\n * @param davClient The WebDAV client to use for performing the request\n * @param path Base path for the favorites, if unset all favorites are queried\n * @param davRoot The root path for the DAV user (defaults to `defaultRootPath`)\n * @example\n * ```js\n * import { getClient, defaultRootPath, getFavoriteNodes } from '@nextcloud/files'\n *\n * const client = getClient()\n * // query favorites for the root\n * const favorites = await getFavoriteNodes(client)\n * // which is the same as writing:\n * const favorites = await getFavoriteNodes(client, '/', defaultRootPath)\n * ```\n */\nexport const getFavoriteNodes = (davClient: WebDAVClient, path = '/', davRoot = defaultRootPath): CancelablePromise<Node[]> => {\n\tconst controller = new AbortController()\n\treturn new CancelablePromise(async (resolve, reject, onCancel) => {\n\t\tonCancel(() => controller.abort())\n\t\ttry {\n\t\t\tconst contentsResponse = await davClient.getDirectoryContents(`${davRoot}${path}`, {\n\t\t\t\tsignal: controller.signal,\n\t\t\t\tdetails: true,\n\t\t\t\tdata: getFavoritesReport(),\n\t\t\t\theaders: {\n\t\t\t\t\t// see getClient for patched webdav client\n\t\t\t\t\tmethod: 'REPORT',\n\t\t\t\t},\n\t\t\t\tincludeSelf: true,\n\t\t\t}) as ResponseDataDetailed<FileStat[]>\n\n\t\t\tconst nodes = contentsResponse.data\n\t\t\t\t.filter(node => node.filename !== path) // exclude current dir\n\t\t\t\t.map((result) => resultToNode(result, davRoot))\n\t\t\tresolve(nodes)\n\t\t} catch (error) {\n\t\t\treject(error)\n\t\t}\n\t})\n}\n\n/**\n * Convert DAV result `FileStat` to `Node`\n *\n * @param node The DAV result\n * @param filesRoot The DAV files root path\n * @param remoteURL The DAV server remote URL (same as on `getClient`)\n */\nexport const resultToNode = function(node: FileStat, filesRoot = defaultRootPath, remoteURL = defaultRemoteURL): Node {\n\tlet userId = getCurrentUser()?.uid\n\tif (isPublicShare()) {\n\t\tuserId = userId ?? 'anonymous'\n\t} else if (!userId) {\n\t\tthrow new Error('No user id found')\n\t}\n\n\tconst props = node.props as ResponseProps\n\tconst permissions = parsePermissions(props?.permissions)\n\tconst owner = String(props?.['owner-id'] || userId)\n\tconst id = props.fileid || 0\n\n\tconst mtime = new Date(Date.parse(node.lastmod))\n\tconst crtime = new Date(Date.parse(props.creationdate))\n\n\tconst nodeData: NodeData = {\n\t\tid,\n\t\tsource: `${remoteURL}${node.filename}`,\n\t\tmtime: !isNaN(mtime.getTime()) && mtime.getTime() !== 0 ? mtime : undefined,\n\t\tcrtime: !isNaN(crtime.getTime()) && crtime.getTime() !== 0 ? crtime : undefined,\n\t\tmime: node.mime || 'application/octet-stream',\n\t\t// Manually cast to work around for https://github.com/perry-mitchell/webdav-client/pull/380\n\t\tdisplayname: props.displayname !== undefined ? String(props.displayname) : undefined,\n\t\tsize: props?.size || Number.parseInt(props.getcontentlength || '0'),\n\t\t// The fileid is set to -1 for failed requests\n\t\tstatus: id < 0 ? NodeStatus.FAILED : undefined,\n\t\tpermissions,\n\t\towner,\n\t\troot: filesRoot,\n\t\tattributes: {\n\t\t\t...node,\n\t\t\t...props,\n\t\t\thasPreview: props?.['has-preview'],\n\t\t},\n\t}\n\n\tdelete nodeData.attributes?.props\n\n\treturn node.type === 'file' ? new File(nodeData) : new Folder(nodeData)\n}\n"],"names":["Permission","logger","getCurrentUser","isPublicShare","getSharingToken","generateRemoteUrl","createClient","onRequestTokenUpdate","getRequestToken","getPatcher","headers","CancelablePromise","NodeStatus","File","Folder"],"mappings":"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"}
package/dist/dav.mjs CHANGED
@@ -1,20 +1,281 @@
1
- import { h, f, b, d, c, k, j, l, e, m, n, a, g, p, i, r } from "./chunks/dav-Dnz9REZG.mjs";
1
+ import { getCurrentUser, onRequestTokenUpdate, getRequestToken } from "@nextcloud/auth";
2
+ import { isPublicShare, getSharingToken } from "@nextcloud/sharing/public";
3
+ import { generateRemoteUrl } from "@nextcloud/router";
4
+ import { CancelablePromise } from "cancelable-promise";
5
+ import { createClient, getPatcher } from "webdav";
6
+ import { P as Permission, l as logger, c as NodeStatus, a as File, b as Folder } from "./chunks/folder-Cfi6CwMG.mjs";
7
+ const parsePermissions = function(permString = "") {
8
+ let permissions = Permission.NONE;
9
+ if (!permString) {
10
+ return permissions;
11
+ }
12
+ if (permString.includes("C") || permString.includes("K")) {
13
+ permissions |= Permission.CREATE;
14
+ }
15
+ if (permString.includes("G")) {
16
+ permissions |= Permission.READ;
17
+ }
18
+ if (permString.includes("W") || permString.includes("N") || permString.includes("V")) {
19
+ permissions |= Permission.UPDATE;
20
+ }
21
+ if (permString.includes("D")) {
22
+ permissions |= Permission.DELETE;
23
+ }
24
+ if (permString.includes("R")) {
25
+ permissions |= Permission.SHARE;
26
+ }
27
+ return permissions;
28
+ };
29
+ const defaultDavProperties = [
30
+ "d:getcontentlength",
31
+ "d:getcontenttype",
32
+ "d:getetag",
33
+ "d:getlastmodified",
34
+ "d:creationdate",
35
+ "d:displayname",
36
+ "d:quota-available-bytes",
37
+ "d:resourcetype",
38
+ "nc:has-preview",
39
+ "nc:is-encrypted",
40
+ "nc:mount-type",
41
+ "oc:comments-unread",
42
+ "oc:favorite",
43
+ "oc:fileid",
44
+ "oc:owner-display-name",
45
+ "oc:owner-id",
46
+ "oc:permissions",
47
+ "oc:size"
48
+ ];
49
+ const defaultDavNamespaces = {
50
+ d: "DAV:",
51
+ nc: "http://nextcloud.org/ns",
52
+ oc: "http://owncloud.org/ns",
53
+ ocs: "http://open-collaboration-services.org/ns"
54
+ };
55
+ const registerDavProperty = function(prop, namespace = { nc: "http://nextcloud.org/ns" }) {
56
+ if (typeof window._nc_dav_properties === "undefined") {
57
+ window._nc_dav_properties = [...defaultDavProperties];
58
+ window._nc_dav_namespaces = { ...defaultDavNamespaces };
59
+ }
60
+ const namespaces = { ...window._nc_dav_namespaces, ...namespace };
61
+ if (window._nc_dav_properties.find((search) => search === prop)) {
62
+ logger.warn(`${prop} already registered`, { prop });
63
+ return false;
64
+ }
65
+ if (prop.startsWith("<") || prop.split(":").length !== 2) {
66
+ logger.error(`${prop} is not valid. See example: 'oc:fileid'`, { prop });
67
+ return false;
68
+ }
69
+ const ns = prop.split(":")[0];
70
+ if (!namespaces[ns]) {
71
+ logger.error(`${prop} namespace unknown`, { prop, namespaces });
72
+ return false;
73
+ }
74
+ window._nc_dav_properties.push(prop);
75
+ window._nc_dav_namespaces = namespaces;
76
+ return true;
77
+ };
78
+ const getDavProperties = function() {
79
+ if (typeof window._nc_dav_properties === "undefined") {
80
+ window._nc_dav_properties = [...defaultDavProperties];
81
+ }
82
+ return window._nc_dav_properties.map((prop) => `<${prop} />`).join(" ");
83
+ };
84
+ const getDavNameSpaces = function() {
85
+ if (typeof window._nc_dav_namespaces === "undefined") {
86
+ window._nc_dav_namespaces = { ...defaultDavNamespaces };
87
+ }
88
+ return Object.keys(window._nc_dav_namespaces).map((ns) => `xmlns:${ns}="${window._nc_dav_namespaces?.[ns]}"`).join(" ");
89
+ };
90
+ const getDefaultPropfind = function() {
91
+ return `<?xml version="1.0"?>
92
+ <d:propfind ${getDavNameSpaces()}>
93
+ <d:prop>
94
+ ${getDavProperties()}
95
+ </d:prop>
96
+ </d:propfind>`;
97
+ };
98
+ const getFavoritesReport = function() {
99
+ return `<?xml version="1.0"?>
100
+ <oc:filter-files ${getDavNameSpaces()}>
101
+ <d:prop>
102
+ ${getDavProperties()}
103
+ </d:prop>
104
+ <oc:filter-rules>
105
+ <oc:favorite>1</oc:favorite>
106
+ </oc:filter-rules>
107
+ </oc:filter-files>`;
108
+ };
109
+ const getRecentSearch = function(lastModified) {
110
+ return `<?xml version="1.0" encoding="UTF-8"?>
111
+ <d:searchrequest ${getDavNameSpaces()}
112
+ xmlns:ns="https://github.com/icewind1991/SearchDAV/ns">
113
+ <d:basicsearch>
114
+ <d:select>
115
+ <d:prop>
116
+ ${getDavProperties()}
117
+ </d:prop>
118
+ </d:select>
119
+ <d:from>
120
+ <d:scope>
121
+ <d:href>/files/${getCurrentUser()?.uid}/</d:href>
122
+ <d:depth>infinity</d:depth>
123
+ </d:scope>
124
+ </d:from>
125
+ <d:where>
126
+ <d:and>
127
+ <d:or>
128
+ <d:not>
129
+ <d:eq>
130
+ <d:prop>
131
+ <d:getcontenttype/>
132
+ </d:prop>
133
+ <d:literal>httpd/unix-directory</d:literal>
134
+ </d:eq>
135
+ </d:not>
136
+ <d:eq>
137
+ <d:prop>
138
+ <oc:size/>
139
+ </d:prop>
140
+ <d:literal>0</d:literal>
141
+ </d:eq>
142
+ </d:or>
143
+ <d:gt>
144
+ <d:prop>
145
+ <d:getlastmodified/>
146
+ </d:prop>
147
+ <d:literal>${lastModified}</d:literal>
148
+ </d:gt>
149
+ </d:and>
150
+ </d:where>
151
+ <d:orderby>
152
+ <d:order>
153
+ <d:prop>
154
+ <d:getlastmodified/>
155
+ </d:prop>
156
+ <d:descending/>
157
+ </d:order>
158
+ </d:orderby>
159
+ <d:limit>
160
+ <d:nresults>100</d:nresults>
161
+ <ns:firstresult>0</ns:firstresult>
162
+ </d:limit>
163
+ </d:basicsearch>
164
+ </d:searchrequest>`;
165
+ };
166
+ function getRootPath() {
167
+ if (isPublicShare()) {
168
+ return `/files/${getSharingToken()}`;
169
+ }
170
+ return `/files/${getCurrentUser()?.uid}`;
171
+ }
172
+ const defaultRootPath = getRootPath();
173
+ function getRemoteURL() {
174
+ const url = generateRemoteUrl("dav");
175
+ if (isPublicShare()) {
176
+ return url.replace("remote.php", "public.php");
177
+ }
178
+ return url;
179
+ }
180
+ const defaultRemoteURL = getRemoteURL();
181
+ const getClient = function(remoteURL = defaultRemoteURL, headers = {}) {
182
+ const client = createClient(remoteURL, { headers });
183
+ function setHeaders(token) {
184
+ client.setHeaders({
185
+ ...headers,
186
+ // Add this so the server knows it is an request from the browser
187
+ "X-Requested-With": "XMLHttpRequest",
188
+ // Inject user auth
189
+ requesttoken: token ?? ""
190
+ });
191
+ }
192
+ onRequestTokenUpdate(setHeaders);
193
+ setHeaders(getRequestToken());
194
+ const patcher = getPatcher();
195
+ patcher.patch("fetch", (url, options) => {
196
+ const headers2 = options.headers;
197
+ if (headers2?.method) {
198
+ options.method = headers2.method;
199
+ delete headers2.method;
200
+ }
201
+ return fetch(url, options);
202
+ });
203
+ return client;
204
+ };
205
+ const getFavoriteNodes = (davClient, path = "/", davRoot = defaultRootPath) => {
206
+ const controller = new AbortController();
207
+ return new CancelablePromise(async (resolve, reject, onCancel) => {
208
+ onCancel(() => controller.abort());
209
+ try {
210
+ const contentsResponse = await davClient.getDirectoryContents(`${davRoot}${path}`, {
211
+ signal: controller.signal,
212
+ details: true,
213
+ data: getFavoritesReport(),
214
+ headers: {
215
+ // see getClient for patched webdav client
216
+ method: "REPORT"
217
+ },
218
+ includeSelf: true
219
+ });
220
+ const nodes = contentsResponse.data.filter((node) => node.filename !== path).map((result) => resultToNode(result, davRoot));
221
+ resolve(nodes);
222
+ } catch (error) {
223
+ reject(error);
224
+ }
225
+ });
226
+ };
227
+ const resultToNode = function(node, filesRoot = defaultRootPath, remoteURL = defaultRemoteURL) {
228
+ let userId = getCurrentUser()?.uid;
229
+ if (isPublicShare()) {
230
+ userId = userId ?? "anonymous";
231
+ } else if (!userId) {
232
+ throw new Error("No user id found");
233
+ }
234
+ const props = node.props;
235
+ const permissions = parsePermissions(props?.permissions);
236
+ const owner = String(props?.["owner-id"] || userId);
237
+ const id = props.fileid || 0;
238
+ const mtime = new Date(Date.parse(node.lastmod));
239
+ const crtime = new Date(Date.parse(props.creationdate));
240
+ const nodeData = {
241
+ id,
242
+ source: `${remoteURL}${node.filename}`,
243
+ mtime: !isNaN(mtime.getTime()) && mtime.getTime() !== 0 ? mtime : void 0,
244
+ crtime: !isNaN(crtime.getTime()) && crtime.getTime() !== 0 ? crtime : void 0,
245
+ mime: node.mime || "application/octet-stream",
246
+ // Manually cast to work around for https://github.com/perry-mitchell/webdav-client/pull/380
247
+ displayname: props.displayname !== void 0 ? String(props.displayname) : void 0,
248
+ size: props?.size || Number.parseInt(props.getcontentlength || "0"),
249
+ // The fileid is set to -1 for failed requests
250
+ status: id < 0 ? NodeStatus.FAILED : void 0,
251
+ permissions,
252
+ owner,
253
+ root: filesRoot,
254
+ attributes: {
255
+ ...node,
256
+ ...props,
257
+ hasPreview: props?.["has-preview"]
258
+ }
259
+ };
260
+ delete nodeData.attributes?.props;
261
+ return node.type === "file" ? new File(nodeData) : new Folder(nodeData);
262
+ };
2
263
  export {
3
- h as defaultDavNamespaces,
4
- f as defaultDavProperties,
5
- b as defaultRemoteURL,
6
- d as defaultRootPath,
7
- c as getClient,
8
- k as getDavNameSpaces,
9
- j as getDavProperties,
10
- l as getDefaultPropfind,
11
- e as getFavoriteNodes,
12
- m as getFavoritesReport,
13
- n as getRecentSearch,
14
- a as getRemoteURL,
15
- g as getRootPath,
16
- p as parsePermissions,
17
- i as registerDavProperty,
18
- r as resultToNode
264
+ defaultDavNamespaces,
265
+ defaultDavProperties,
266
+ defaultRemoteURL,
267
+ defaultRootPath,
268
+ getClient,
269
+ getDavNameSpaces,
270
+ getDavProperties,
271
+ getDefaultPropfind,
272
+ getFavoriteNodes,
273
+ getFavoritesReport,
274
+ getRecentSearch,
275
+ getRemoteURL,
276
+ getRootPath,
277
+ parsePermissions,
278
+ registerDavProperty,
279
+ resultToNode
19
280
  };
20
281
  //# sourceMappingURL=dav.mjs.map
package/dist/dav.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dav.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"dav.mjs","sources":["../lib/dav/davPermissions.ts","../lib/dav/davProperties.ts","../lib/dav/dav.ts"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\nimport { Permission } from '../permissions'\n\n/**\n * Parse the WebDAV permission string to a permission enum\n *\n * @param permString The DAV permission string\n */\nexport const parsePermissions = function(permString = ''): number {\n\tlet permissions = Permission.NONE\n\n\tif (!permString) { return permissions }\n\n\tif (permString.includes('C') || permString.includes('K')) { permissions |= Permission.CREATE }\n\n\tif (permString.includes('G')) { permissions |= Permission.READ }\n\n\tif (permString.includes('W') || permString.includes('N') || permString.includes('V')) { permissions |= Permission.UPDATE }\n\n\tif (permString.includes('D')) { permissions |= Permission.DELETE }\n\n\tif (permString.includes('R')) { permissions |= Permission.SHARE }\n\n\treturn permissions\n}\n","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\nimport { getCurrentUser } from '@nextcloud/auth'\nimport logger from '../utils/logger'\n\nexport type DavProperty = { [key: string]: string }\n\nexport const defaultDavProperties = [\n\t'd:getcontentlength',\n\t'd:getcontenttype',\n\t'd:getetag',\n\t'd:getlastmodified',\n\t'd:creationdate',\n\t'd:displayname',\n\t'd:quota-available-bytes',\n\t'd:resourcetype',\n\t'nc:has-preview',\n\t'nc:is-encrypted',\n\t'nc:mount-type',\n\t'oc:comments-unread',\n\t'oc:favorite',\n\t'oc:fileid',\n\t'oc:owner-display-name',\n\t'oc:owner-id',\n\t'oc:permissions',\n\t'oc:size',\n]\n\nexport const defaultDavNamespaces = {\n\td: 'DAV:',\n\tnc: 'http://nextcloud.org/ns',\n\toc: 'http://owncloud.org/ns',\n\tocs: 'http://open-collaboration-services.org/ns',\n}\n\n/**\n * Register custom DAV properties\n *\n * Can be used if your app introduces custom DAV properties, so e.g. the files app can make use of it.\n *\n * @param prop The property\n * @param namespace The namespace of the property\n */\nexport const registerDavProperty = function(prop: string, namespace: DavProperty = { nc: 'http://nextcloud.org/ns' }): boolean {\n\tif (typeof window._nc_dav_properties === 'undefined') {\n\t\twindow._nc_dav_properties = [...defaultDavProperties]\n\t\twindow._nc_dav_namespaces = { ...defaultDavNamespaces }\n\t}\n\n\tconst namespaces = { ...window._nc_dav_namespaces, ...namespace }\n\n\t// Check duplicates\n\tif (window._nc_dav_properties.find((search) => search === prop)) {\n\t\tlogger.warn(`${prop} already registered`, { prop })\n\t\treturn false\n\t}\n\n\tif (prop.startsWith('<') || prop.split(':').length !== 2) {\n\t\tlogger.error(`${prop} is not valid. See example: 'oc:fileid'`, { prop })\n\t\treturn false\n\t}\n\n\tconst ns = prop.split(':')[0]\n\tif (!namespaces[ns]) {\n\t\tlogger.error(`${prop} namespace unknown`, { prop, namespaces })\n\t\treturn false\n\t}\n\n\twindow._nc_dav_properties.push(prop)\n\twindow._nc_dav_namespaces = namespaces\n\treturn true\n}\n\n/**\n * Get the registered dav properties\n */\nexport const getDavProperties = function(): string {\n\tif (typeof window._nc_dav_properties === 'undefined') {\n\t\twindow._nc_dav_properties = [...defaultDavProperties]\n\t}\n\n\treturn window._nc_dav_properties.map((prop) => `<${prop} />`).join(' ')\n}\n\n/**\n * Get the registered dav namespaces\n */\nexport const getDavNameSpaces = function(): string {\n\tif (typeof window._nc_dav_namespaces === 'undefined') {\n\t\twindow._nc_dav_namespaces = { ...defaultDavNamespaces }\n\t}\n\n\treturn Object.keys(window._nc_dav_namespaces)\n\t\t.map((ns) => `xmlns:${ns}=\"${window._nc_dav_namespaces?.[ns]}\"`)\n\t\t.join(' ')\n}\n\n/**\n * Get the default PROPFIND request body\n */\nexport const getDefaultPropfind = function(): string {\n\treturn `<?xml version=\"1.0\"?>\n\t\t<d:propfind ${getDavNameSpaces()}>\n\t\t\t<d:prop>\n\t\t\t\t${getDavProperties()}\n\t\t\t</d:prop>\n\t\t</d:propfind>`\n}\n\n/**\n * Get the REPORT body to filter for favorite nodes\n */\nexport const getFavoritesReport = function(): string {\n\treturn `<?xml version=\"1.0\"?>\n\t\t<oc:filter-files ${getDavNameSpaces()}>\n\t\t\t<d:prop>\n\t\t\t\t${getDavProperties()}\n\t\t\t</d:prop>\n\t\t\t<oc:filter-rules>\n\t\t\t\t<oc:favorite>1</oc:favorite>\n\t\t\t</oc:filter-rules>\n\t\t</oc:filter-files>`\n}\n\n/**\n * Get the SEARCH body to search for recently modified files\n *\n * @param lastModified Oldest timestamp to include (Unix timestamp)\n * @example\n * ```ts\n * // SEARCH for recent files need a different DAV endpoint\n * const client = davGetClient(generateRemoteUrl('dav'))\n * // Timestamp of last week\n * const lastWeek = Math.round(Date.now() / 1000) - (60 * 60 * 24 * 7)\n * const contentsResponse = await client.getDirectoryContents(path, {\n * details: true,\n * data: davGetRecentSearch(lastWeek),\n * headers: {\n * method: 'SEARCH',\n * 'Content-Type': 'application/xml; charset=utf-8',\n * },\n * deep: true,\n * }) as ResponseDataDetailed<FileStat[]>\n * ```\n */\nexport const getRecentSearch = function(lastModified: number): string {\n\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<d:searchrequest ${getDavNameSpaces()}\n\txmlns:ns=\"https://github.com/icewind1991/SearchDAV/ns\">\n\t<d:basicsearch>\n\t\t<d:select>\n\t\t\t<d:prop>\n\t\t\t\t${getDavProperties()}\n\t\t\t</d:prop>\n\t\t</d:select>\n\t\t<d:from>\n\t\t\t<d:scope>\n\t\t\t\t<d:href>/files/${getCurrentUser()?.uid}/</d:href>\n\t\t\t\t<d:depth>infinity</d:depth>\n\t\t\t</d:scope>\n\t\t</d:from>\n\t\t<d:where>\n\t\t\t<d:and>\n\t\t\t\t<d:or>\n\t\t\t\t\t<d:not>\n\t\t\t\t\t\t<d:eq>\n\t\t\t\t\t\t\t<d:prop>\n\t\t\t\t\t\t\t\t<d:getcontenttype/>\n\t\t\t\t\t\t\t</d:prop>\n\t\t\t\t\t\t\t<d:literal>httpd/unix-directory</d:literal>\n\t\t\t\t\t\t</d:eq>\n\t\t\t\t\t</d:not>\n\t\t\t\t\t<d:eq>\n\t\t\t\t\t\t<d:prop>\n\t\t\t\t\t\t\t<oc:size/>\n\t\t\t\t\t\t</d:prop>\n\t\t\t\t\t\t<d:literal>0</d:literal>\n\t\t\t\t\t</d:eq>\n\t\t\t\t</d:or>\n\t\t\t\t<d:gt>\n\t\t\t\t\t<d:prop>\n\t\t\t\t\t\t<d:getlastmodified/>\n\t\t\t\t\t</d:prop>\n\t\t\t\t\t<d:literal>${lastModified}</d:literal>\n\t\t\t\t</d:gt>\n\t\t\t</d:and>\n\t\t</d:where>\n\t\t<d:orderby>\n\t\t\t<d:order>\n\t\t\t\t<d:prop>\n\t\t\t\t\t<d:getlastmodified/>\n\t\t\t\t</d:prop>\n\t\t\t\t<d:descending/>\n\t\t\t</d:order>\n\t\t</d:orderby>\n\t\t<d:limit>\n\t\t\t<d:nresults>100</d:nresults>\n\t\t\t<ns:firstresult>0</ns:firstresult>\n\t\t</d:limit>\n\t</d:basicsearch>\n</d:searchrequest>`\n}\n","/*\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { DAVResultResponseProps, FileStat, ResponseDataDetailed, WebDAVClient } from 'webdav'\nimport type { Node, NodeData } from '../node/index.ts'\n\nimport { getCurrentUser, getRequestToken, onRequestTokenUpdate } from '@nextcloud/auth'\nimport { getSharingToken, isPublicShare } from '@nextcloud/sharing/public'\nimport { generateRemoteUrl } from '@nextcloud/router'\nimport { CancelablePromise } from 'cancelable-promise'\nimport { createClient, getPatcher } from 'webdav'\nimport { parsePermissions } from './davPermissions.ts'\nimport { getFavoritesReport } from './davProperties.ts'\nimport { File, Folder, NodeStatus } from '../node/index.ts'\n\n/**\n * Nextcloud DAV result response\n */\ninterface ResponseProps extends DAVResultResponseProps {\n\tcreationdate: string\n\tpermissions: string\n\tmime: string\n\tfileid: number\n\tsize: number\n\t'owner-id': string | number\n}\n\n/**\n * Get the DAV root path for the current user or public share\n */\nexport function getRootPath(): string {\n\tif (isPublicShare()) {\n\t\treturn `/files/${getSharingToken()}`\n\t}\n\treturn `/files/${getCurrentUser()?.uid}`\n}\n\n/**\n * The DAV root path for the current user\n * This is a cached version of `getRemoteURL`\n */\nexport const defaultRootPath = getRootPath()\n\n/**\n * Get the DAV remote URL used as base URL for the WebDAV client\n * It also handles public shares\n */\nexport function getRemoteURL(): string {\n\tconst url = generateRemoteUrl('dav')\n\tif (isPublicShare()) {\n\t\treturn url.replace('remote.php', 'public.php')\n\t}\n\treturn url\n}\n\n/**\n * The DAV remote URL used as base URL for the WebDAV client\n * This is a cached version of `getRemoteURL`\n */\nexport const defaultRemoteURL = getRemoteURL()\n\n/**\n * Get a WebDAV client configured to include the Nextcloud request token\n *\n * @param remoteURL The DAV server remote URL\n * @param headers Optional additional headers to set for every request\n */\nexport const getClient = function(remoteURL = defaultRemoteURL, headers: Record<string, string> = {}) {\n\tconst client = createClient(remoteURL, { headers })\n\n\t/**\n\t * Set headers for DAV requests\n\t * @param token CSRF token\n\t */\n\tfunction setHeaders(token: string | null) {\n\t\tclient.setHeaders({\n\t\t\t...headers,\n\t\t\t// Add this so the server knows it is an request from the browser\n\t\t\t'X-Requested-With': 'XMLHttpRequest',\n\t\t\t// Inject user auth\n\t\t\trequesttoken: token ?? '',\n\t\t})\n\t}\n\n\t// refresh headers when request token changes\n\tonRequestTokenUpdate(setHeaders)\n\tsetHeaders(getRequestToken())\n\n\t/**\n\t * Allow to override the METHOD to support dav REPORT\n\t *\n\t * @see https://github.com/perry-mitchell/webdav-client/blob/8d9694613c978ce7404e26a401c39a41f125f87f/source/request.ts\n\t */\n\tconst patcher = getPatcher()\n\t// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n\t// @ts-ignore\n\t// https://github.com/perry-mitchell/hot-patcher/issues/6\n\tpatcher.patch('fetch', (url: string, options: RequestInit): Promise<Response> => {\n\t\tconst headers = options.headers as Record<string, string>\n\t\tif (headers?.method) {\n\t\t\toptions.method = headers.method\n\t\t\tdelete headers.method\n\t\t}\n\t\treturn fetch(url, options)\n\t})\n\n\treturn client\n}\n\n/**\n * Use WebDAV to query for favorite Nodes\n *\n * @param davClient The WebDAV client to use for performing the request\n * @param path Base path for the favorites, if unset all favorites are queried\n * @param davRoot The root path for the DAV user (defaults to `defaultRootPath`)\n * @example\n * ```js\n * import { getClient, defaultRootPath, getFavoriteNodes } from '@nextcloud/files'\n *\n * const client = getClient()\n * // query favorites for the root\n * const favorites = await getFavoriteNodes(client)\n * // which is the same as writing:\n * const favorites = await getFavoriteNodes(client, '/', defaultRootPath)\n * ```\n */\nexport const getFavoriteNodes = (davClient: WebDAVClient, path = '/', davRoot = defaultRootPath): CancelablePromise<Node[]> => {\n\tconst controller = new AbortController()\n\treturn new CancelablePromise(async (resolve, reject, onCancel) => {\n\t\tonCancel(() => controller.abort())\n\t\ttry {\n\t\t\tconst contentsResponse = await davClient.getDirectoryContents(`${davRoot}${path}`, {\n\t\t\t\tsignal: controller.signal,\n\t\t\t\tdetails: true,\n\t\t\t\tdata: getFavoritesReport(),\n\t\t\t\theaders: {\n\t\t\t\t\t// see getClient for patched webdav client\n\t\t\t\t\tmethod: 'REPORT',\n\t\t\t\t},\n\t\t\t\tincludeSelf: true,\n\t\t\t}) as ResponseDataDetailed<FileStat[]>\n\n\t\t\tconst nodes = contentsResponse.data\n\t\t\t\t.filter(node => node.filename !== path) // exclude current dir\n\t\t\t\t.map((result) => resultToNode(result, davRoot))\n\t\t\tresolve(nodes)\n\t\t} catch (error) {\n\t\t\treject(error)\n\t\t}\n\t})\n}\n\n/**\n * Convert DAV result `FileStat` to `Node`\n *\n * @param node The DAV result\n * @param filesRoot The DAV files root path\n * @param remoteURL The DAV server remote URL (same as on `getClient`)\n */\nexport const resultToNode = function(node: FileStat, filesRoot = defaultRootPath, remoteURL = defaultRemoteURL): Node {\n\tlet userId = getCurrentUser()?.uid\n\tif (isPublicShare()) {\n\t\tuserId = userId ?? 'anonymous'\n\t} else if (!userId) {\n\t\tthrow new Error('No user id found')\n\t}\n\n\tconst props = node.props as ResponseProps\n\tconst permissions = parsePermissions(props?.permissions)\n\tconst owner = String(props?.['owner-id'] || userId)\n\tconst id = props.fileid || 0\n\n\tconst mtime = new Date(Date.parse(node.lastmod))\n\tconst crtime = new Date(Date.parse(props.creationdate))\n\n\tconst nodeData: NodeData = {\n\t\tid,\n\t\tsource: `${remoteURL}${node.filename}`,\n\t\tmtime: !isNaN(mtime.getTime()) && mtime.getTime() !== 0 ? mtime : undefined,\n\t\tcrtime: !isNaN(crtime.getTime()) && crtime.getTime() !== 0 ? crtime : undefined,\n\t\tmime: node.mime || 'application/octet-stream',\n\t\t// Manually cast to work around for https://github.com/perry-mitchell/webdav-client/pull/380\n\t\tdisplayname: props.displayname !== undefined ? String(props.displayname) : undefined,\n\t\tsize: props?.size || Number.parseInt(props.getcontentlength || '0'),\n\t\t// The fileid is set to -1 for failed requests\n\t\tstatus: id < 0 ? NodeStatus.FAILED : undefined,\n\t\tpermissions,\n\t\towner,\n\t\troot: filesRoot,\n\t\tattributes: {\n\t\t\t...node,\n\t\t\t...props,\n\t\t\thasPreview: props?.['has-preview'],\n\t\t},\n\t}\n\n\tdelete nodeData.attributes?.props\n\n\treturn node.type === 'file' ? new File(nodeData) : new Folder(nodeData)\n}\n"],"names":["headers"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const dav = require("./chunks/dav-D7e9ysFW.cjs");
3
+ const folder = require("./chunks/folder-C3yiKTSb.cjs");
4
4
  const typescriptEventTarget = require("typescript-event-target");
5
5
  const require$$1 = require("string_decoder");
6
6
  const capabilities = require("@nextcloud/capabilities");
@@ -117,10 +117,10 @@ class FileAction {
117
117
  const registerFileAction = function(action) {
118
118
  if (typeof window._nc_fileactions === "undefined") {
119
119
  window._nc_fileactions = [];
120
- dav.logger.debug("FileActions initialized");
120
+ folder.logger.debug("FileActions initialized");
121
121
  }
122
122
  if (window._nc_fileactions.find((search) => search.id === action.id)) {
123
- dav.logger.error(`FileAction ${action.id} already registered`, { action });
123
+ folder.logger.error(`FileAction ${action.id} already registered`, { action });
124
124
  return;
125
125
  }
126
126
  window._nc_fileactions.push(action);
@@ -128,7 +128,7 @@ const registerFileAction = function(action) {
128
128
  const getFileActions = function() {
129
129
  if (typeof window._nc_fileactions === "undefined") {
130
130
  window._nc_fileactions = [];
131
- dav.logger.debug("FileActions initialized");
131
+ folder.logger.debug("FileActions initialized");
132
132
  }
133
133
  return window._nc_fileactions;
134
134
  };
@@ -182,7 +182,7 @@ const registerFileListAction = (action) => {
182
182
  window._nc_filelistactions = [];
183
183
  }
184
184
  if (window._nc_filelistactions.find((listAction) => listAction.id === action.id)) {
185
- dav.logger.error(`FileListAction with id "${action.id}" is already registered`, { action });
185
+ folder.logger.error(`FileListAction with id "${action.id}" is already registered`, { action });
186
186
  return;
187
187
  }
188
188
  window._nc_filelistactions.push(action);
@@ -884,10 +884,10 @@ class Header {
884
884
  const registerFileListHeaders = function(header) {
885
885
  if (typeof window._nc_filelistheader === "undefined") {
886
886
  window._nc_filelistheader = [];
887
- dav.logger.debug("FileListHeaders initialized");
887
+ folder.logger.debug("FileListHeaders initialized");
888
888
  }
889
889
  if (window._nc_filelistheader.find((search) => search.id === header.id)) {
890
- dav.logger.error(`Header ${header.id} already registered`, { header });
890
+ folder.logger.error(`Header ${header.id} already registered`, { header });
891
891
  return;
892
892
  }
893
893
  window._nc_filelistheader.push(header);
@@ -895,7 +895,7 @@ const registerFileListHeaders = function(header) {
895
895
  const getFileListHeaders = function() {
896
896
  if (typeof window._nc_filelistheader === "undefined") {
897
897
  window._nc_filelistheader = [];
898
- dav.logger.debug("FileListHeaders initialized");
898
+ folder.logger.debug("FileListHeaders initialized");
899
899
  }
900
900
  return window._nc_filelistheader;
901
901
  };
@@ -951,7 +951,7 @@ class Navigation extends typescriptEventTarget.TypedEventTarget {
951
951
  const getNavigation = function() {
952
952
  if (typeof window._nc_navigation === "undefined") {
953
953
  window._nc_navigation = new Navigation();
954
- dav.logger.debug("Navigation service initialized");
954
+ folder.logger.debug("Navigation service initialized");
955
955
  }
956
956
  return window._nc_navigation;
957
957
  };
@@ -2697,7 +2697,7 @@ class NewMenu {
2697
2697
  unregisterEntry(entry) {
2698
2698
  const entryIndex = typeof entry === "string" ? this.getEntryIndex(entry) : this.getEntryIndex(entry.id);
2699
2699
  if (entryIndex === -1) {
2700
- dav.logger.warn("Entry not found, nothing removed", { entry, entries: this.getEntries() });
2700
+ folder.logger.warn("Entry not found, nothing removed", { entry, entries: this.getEntries() });
2701
2701
  return;
2702
2702
  }
2703
2703
  this._entries.splice(entryIndex, 1);
@@ -2717,13 +2717,13 @@ class NewMenu {
2717
2717
  return this._entries.findIndex((entry) => entry.id === id);
2718
2718
  }
2719
2719
  validateEntry(entry) {
2720
- if (!entry.id || !entry.displayName || !(entry.iconSvgInline || entry.iconClass) || !entry.handler) {
2720
+ if (!entry.id || !entry.displayName || !entry.iconSvgInline || !entry.handler) {
2721
2721
  throw new Error("Invalid entry");
2722
2722
  }
2723
2723
  if (typeof entry.id !== "string" || typeof entry.displayName !== "string") {
2724
2724
  throw new Error("Invalid id or displayName property");
2725
2725
  }
2726
- if (entry.iconClass && typeof entry.iconClass !== "string" || entry.iconSvgInline && typeof entry.iconSvgInline !== "string") {
2726
+ if (entry.iconSvgInline && typeof entry.iconSvgInline !== "string") {
2727
2727
  throw new Error("Invalid icon provided");
2728
2728
  }
2729
2729
  if (entry.enabled !== void 0 && typeof entry.enabled !== "function") {
@@ -2743,7 +2743,7 @@ class NewMenu {
2743
2743
  function getNewFileMenu() {
2744
2744
  if (typeof window._nc_newfilemenu === "undefined") {
2745
2745
  window._nc_newfilemenu = new NewMenu();
2746
- dav.logger.debug("NewFileMenu initialized");
2746
+ folder.logger.debug("NewFileMenu initialized");
2747
2747
  }
2748
2748
  return window._nc_newfilemenu;
2749
2749
  }
@@ -2795,7 +2795,7 @@ class InvalidFilenameError extends Error {
2795
2795
  }
2796
2796
  function validateFilename(filename) {
2797
2797
  const capabilities$1 = capabilities.getCapabilities().files;
2798
- const forbiddenCharacters = capabilities$1.forbidden_filename_characters ?? window._oc_config?.forbidden_filenames_characters ?? ["/", "\\"];
2798
+ const forbiddenCharacters = capabilities$1.forbidden_filename_characters ?? ["/", "\\"];
2799
2799
  for (const character of forbiddenCharacters) {
2800
2800
  if (filename.includes(character)) {
2801
2801
  throw new InvalidFilenameError({ segment: character, reason: "character", filename });
@@ -2822,7 +2822,7 @@ function validateFilename(filename) {
2822
2822
  /* ReservedName */
2823
2823
  });
2824
2824
  }
2825
- const forbiddenFilenameExtensions = capabilities$1.forbidden_filename_extensions ?? [".part", ".filepart"];
2825
+ const forbiddenFilenameExtensions = capabilities$1.forbidden_filename_extensions ?? [];
2826
2826
  for (const extension of forbiddenFilenameExtensions) {
2827
2827
  if (filename.length > extension.length && filename.endsWith(extension)) {
2828
2828
  throw new InvalidFilenameError({ segment: extension, reason: "extension", filename });
@@ -2943,7 +2943,7 @@ function sortNodes(nodes, options = {}) {
2943
2943
  };
2944
2944
  function basename(node) {
2945
2945
  const name = node.displayname || node.attributes?.displayname || node.basename || "";
2946
- if (node.type === dav.FileType.Folder) {
2946
+ if (node.type === folder.FileType.Folder) {
2947
2947
  return name;
2948
2948
  }
2949
2949
  return name.lastIndexOf(".") > 0 ? name.slice(0, name.lastIndexOf(".")) : name;
@@ -2976,28 +2976,12 @@ function sortNodes(nodes, options = {}) {
2976
2976
  ];
2977
2977
  return orderBy(nodes, identifiers2, orders);
2978
2978
  }
2979
- exports.File = dav.File;
2980
- exports.FileType = dav.FileType;
2981
- exports.Folder = dav.Folder;
2982
- exports.Node = dav.Node;
2983
- exports.NodeStatus = dav.NodeStatus;
2984
- exports.Permission = dav.Permission;
2985
- exports.davGetClient = dav.getClient;
2986
- exports.davGetDefaultPropfind = dav.getDefaultPropfind;
2987
- exports.davGetFavoritesReport = dav.getFavoritesReport;
2988
- exports.davGetRecentSearch = dav.getRecentSearch;
2989
- exports.davGetRemoteURL = dav.getRemoteURL;
2990
- exports.davGetRootPath = dav.getRootPath;
2991
- exports.davParsePermissions = dav.parsePermissions;
2992
- exports.davRemoteURL = dav.defaultRemoteURL;
2993
- exports.davResultToNode = dav.resultToNode;
2994
- exports.davRootPath = dav.defaultRootPath;
2995
- exports.defaultDavNamespaces = dav.defaultDavNamespaces;
2996
- exports.defaultDavProperties = dav.defaultDavProperties;
2997
- exports.getDavNameSpaces = dav.getDavNameSpaces;
2998
- exports.getDavProperties = dav.getDavProperties;
2999
- exports.getFavoriteNodes = dav.getFavoriteNodes;
3000
- exports.registerDavProperty = dav.registerDavProperty;
2979
+ exports.File = folder.File;
2980
+ exports.FileType = folder.FileType;
2981
+ exports.Folder = folder.Folder;
2982
+ exports.Node = folder.Node;
2983
+ exports.NodeStatus = folder.NodeStatus;
2984
+ exports.Permission = folder.Permission;
3001
2985
  exports.Column = Column;
3002
2986
  exports.DefaultType = DefaultType;
3003
2987
  exports.FileAction = FileAction;