@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/README.md +9 -0
- package/dist/actions/fileAction.d.ts +1 -1
- package/dist/actions/fileListAction.d.ts +1 -1
- package/dist/chunks/{dav-D7e9ysFW.cjs → folder-C3yiKTSb.cjs} +1 -278
- package/dist/chunks/folder-C3yiKTSb.cjs.map +1 -0
- package/dist/chunks/{dav-Dnz9REZG.mjs → folder-Cfi6CwMG.mjs} +5 -282
- package/dist/chunks/folder-Cfi6CwMG.mjs.map +1 -0
- package/dist/dav.cjs +278 -17
- package/dist/dav.cjs.map +1 -1
- package/dist/dav.mjs +278 -17
- package/dist/dav.mjs.map +1 -1
- package/dist/index.cjs +22 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -81
- package/dist/index.mjs +126 -142
- package/dist/index.mjs.map +1 -1
- package/dist/newMenu/NewMenu.d.ts +0 -5
- package/dist/types.d.ts +18 -0
- package/dist/utils/filename-validation.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunks/dav-D7e9ysFW.cjs.map +0 -1
- package/dist/chunks/dav-Dnz9REZG.mjs.map +0 -1
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":";;;;;;;;AAWO,MAAM,mBAAmB,SAAS,aAAa,IAAY;AACjE,MAAI,cAAcA,OAAAA,WAAW;AAE7B,MAAI,CAAC,YAAY;AAAE,WAAO;AAAA,EAAY;AAEtC,MAAI,WAAW,SAAS,GAAG,KAAK,WAAW,SAAS,GAAG,GAAG;AAAE,mBAAeA,OAAAA,WAAW;AAAA,EAAO;AAE7F,MAAI,WAAW,SAAS,GAAG,GAAG;AAAE,mBAAeA,OAAAA,WAAW;AAAA,EAAK;AAE/D,MAAI,WAAW,SAAS,GAAG,KAAK,WAAW,SAAS,GAAG,KAAK,WAAW,SAAS,GAAG,GAAG;AAAE,mBAAeA,OAAAA,WAAW;AAAA,EAAO;AAEzH,MAAI,WAAW,SAAS,GAAG,GAAG;AAAE,mBAAeA,OAAAA,WAAW;AAAA,EAAO;AAEjE,MAAI,WAAW,SAAS,GAAG,GAAG;AAAE,mBAAeA,OAAAA,WAAW;AAAA,EAAM;AAEhE,SAAO;AACR;AClBO,MAAM,uBAAuB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEO,MAAM,uBAAuB;AAAA,EACnC,GAAG;AAAA,EACH,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,KAAK;AACN;AAUO,MAAM,sBAAsB,SAAS,MAAc,YAAyB,EAAE,IAAI,6BAAsC;AAC9H,MAAI,OAAO,OAAO,uBAAuB,aAAa;AACrD,WAAO,qBAAqB,CAAC,GAAG,oBAAoB;AACpD,WAAO,qBAAqB,EAAE,GAAG,qBAAA;AAAA,EAClC;AAEA,QAAM,aAAa,EAAE,GAAG,OAAO,oBAAoB,GAAG,UAAA;AAGtD,MAAI,OAAO,mBAAmB,KAAK,CAAC,WAAW,WAAW,IAAI,GAAG;AAChEC,WAAAA,OAAO,KAAK,GAAG,IAAI,uBAAuB,EAAE,MAAM;AAClD,WAAO;AAAA,EACR;AAEA,MAAI,KAAK,WAAW,GAAG,KAAK,KAAK,MAAM,GAAG,EAAE,WAAW,GAAG;AACzDA,WAAAA,OAAO,MAAM,GAAG,IAAI,2CAA2C,EAAE,MAAM;AACvE,WAAO;AAAA,EACR;AAEA,QAAM,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC;AAC5B,MAAI,CAAC,WAAW,EAAE,GAAG;AACpBA,kBAAO,MAAM,GAAG,IAAI,sBAAsB,EAAE,MAAM,YAAY;AAC9D,WAAO;AAAA,EACR;AAEA,SAAO,mBAAmB,KAAK,IAAI;AACnC,SAAO,qBAAqB;AAC5B,SAAO;AACR;AAKO,MAAM,mBAAmB,WAAmB;AAClD,MAAI,OAAO,OAAO,uBAAuB,aAAa;AACrD,WAAO,qBAAqB,CAAC,GAAG,oBAAoB;AAAA,EACrD;AAEA,SAAO,OAAO,mBAAmB,IAAI,CAAC,SAAS,IAAI,IAAI,KAAK,EAAE,KAAK,GAAG;AACvE;AAKO,MAAM,mBAAmB,WAAmB;AAClD,MAAI,OAAO,OAAO,uBAAuB,aAAa;AACrD,WAAO,qBAAqB,EAAE,GAAG,qBAAA;AAAA,EAClC;AAEA,SAAO,OAAO,KAAK,OAAO,kBAAkB,EAC1C,IAAI,CAAC,OAAO,SAAS,EAAE,KAAK,OAAO,qBAAqB,EAAE,CAAC,GAAG,EAC9D,KAAK,GAAG;AACX;AAKO,MAAM,qBAAqB,WAAmB;AACpD,SAAO;AAAA,gBACQ,kBAAkB;AAAA;AAAA,MAE5B,kBAAkB;AAAA;AAAA;AAGxB;AAKO,MAAM,qBAAqB,WAAmB;AACpD,SAAO;AAAA,qBACa,kBAAkB;AAAA;AAAA,MAEjC,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAMxB;AAuBO,MAAM,kBAAkB,SAAS,cAA8B;AACrE,SAAO;AAAA,mBACW,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,MAK/B,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,qBAKHC,KAAAA,eAAA,GAAkB,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBA0BxB,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkB9B;AC3KO,SAAS,cAAsB;AACrC,MAAIC,QAAAA,iBAAiB;AACpB,WAAO,UAAUC,QAAAA,iBAAiB;AAAA,EACnC;AACA,SAAO,UAAUF,oBAAA,GAAkB,GAAG;AACvC;AAMO,MAAM,kBAAkB,YAAA;AAMxB,SAAS,eAAuB;AACtC,QAAM,MAAMG,OAAAA,kBAAkB,KAAK;AACnC,MAAIF,QAAAA,iBAAiB;AACpB,WAAO,IAAI,QAAQ,cAAc,YAAY;AAAA,EAC9C;AACA,SAAO;AACR;AAMO,MAAM,mBAAmB,aAAA;AAQzB,MAAM,YAAY,SAAS,YAAY,kBAAkB,UAAkC,CAAA,GAAI;AACrG,QAAM,SAASG,OAAAA,aAAa,WAAW,EAAE,SAAS;AAMlD,WAAS,WAAW,OAAsB;AACzC,WAAO,WAAW;AAAA,MACjB,GAAG;AAAA;AAAA,MAEH,oBAAoB;AAAA;AAAA,MAEpB,cAAc,SAAS;AAAA,IAAA,CACvB;AAAA,EACF;AAGAC,OAAAA,qBAAqB,UAAU;AAC/B,aAAWC,KAAAA,iBAAiB;AAO5B,QAAM,UAAUC,OAAAA,WAAA;AAIhB,UAAQ,MAAM,SAAS,CAAC,KAAa,YAA4C;AAChF,UAAMC,WAAU,QAAQ;AACxB,QAAIA,UAAS,QAAQ;AACpB,cAAQ,SAASA,SAAQ;AACzB,aAAOA,SAAQ;AAAA,IAChB;AACA,WAAO,MAAM,KAAK,OAAO;AAAA,EAC1B,CAAC;AAED,SAAO;AACR;AAmBO,MAAM,mBAAmB,CAAC,WAAyB,OAAO,KAAK,UAAU,oBAA+C;AAC9H,QAAM,aAAa,IAAI,gBAAA;AACvB,SAAO,IAAIC,kBAAAA,kBAAkB,OAAO,SAAS,QAAQ,aAAa;AACjE,aAAS,MAAM,WAAW,OAAO;AACjC,QAAI;AACH,YAAM,mBAAmB,MAAM,UAAU,qBAAqB,GAAG,OAAO,GAAG,IAAI,IAAI;AAAA,QAClF,QAAQ,WAAW;AAAA,QACnB,SAAS;AAAA,QACT,MAAM,mBAAA;AAAA,QACN,SAAS;AAAA;AAAA,UAER,QAAQ;AAAA,QAAA;AAAA,QAET,aAAa;AAAA,MAAA,CACb;AAED,YAAM,QAAQ,iBAAiB,KAC7B,OAAO,UAAQ,KAAK,aAAa,IAAI,EACrC,IAAI,CAAC,WAAW,aAAa,QAAQ,OAAO,CAAC;AAC/C,cAAQ,KAAK;AAAA,IACd,SAAS,OAAO;AACf,aAAO,KAAK;AAAA,IACb;AAAA,EACD,CAAC;AACF;AASO,MAAM,eAAe,SAAS,MAAgB,YAAY,iBAAiB,YAAY,kBAAwB;AACrH,MAAI,SAAST,KAAAA,kBAAkB;AAC/B,MAAIC,QAAAA,iBAAiB;AACpB,aAAS,UAAU;AAAA,EACpB,WAAW,CAAC,QAAQ;AACnB,UAAM,IAAI,MAAM,kBAAkB;AAAA,EACnC;AAEA,QAAM,QAAQ,KAAK;AACnB,QAAM,cAAc,iBAAiB,OAAO,WAAW;AACvD,QAAM,QAAQ,OAAO,QAAQ,UAAU,KAAK,MAAM;AAClD,QAAM,KAAK,MAAM,UAAU;AAE3B,QAAM,QAAQ,IAAI,KAAK,KAAK,MAAM,KAAK,OAAO,CAAC;AAC/C,QAAM,SAAS,IAAI,KAAK,KAAK,MAAM,MAAM,YAAY,CAAC;AAEtD,QAAM,WAAqB;AAAA,IAC1B;AAAA,IACA,QAAQ,GAAG,SAAS,GAAG,KAAK,QAAQ;AAAA,IACpC,OAAO,CAAC,MAAM,MAAM,QAAA,CAAS,KAAK,MAAM,QAAA,MAAc,IAAI,QAAQ;AAAA,IAClE,QAAQ,CAAC,MAAM,OAAO,QAAA,CAAS,KAAK,OAAO,QAAA,MAAc,IAAI,SAAS;AAAA,IACtE,MAAM,KAAK,QAAQ;AAAA;AAAA,IAEnB,aAAa,MAAM,gBAAgB,SAAY,OAAO,MAAM,WAAW,IAAI;AAAA,IAC3E,MAAM,OAAO,QAAQ,OAAO,SAAS,MAAM,oBAAoB,GAAG;AAAA;AAAA,IAElE,QAAQ,KAAK,IAAIS,OAAAA,WAAW,SAAS;AAAA,IACrC;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,YAAY;AAAA,MACX,GAAG;AAAA,MACH,GAAG;AAAA,MACH,YAAY,QAAQ,aAAa;AAAA,IAAA;AAAA,EAClC;AAGD,SAAO,SAAS,YAAY;AAE5B,SAAO,KAAK,SAAS,SAAS,IAAIC,OAAAA,KAAK,QAAQ,IAAI,IAAIC,OAAAA,OAAO,QAAQ;AACvE;;;;;;;;;;;;;;;;;"}
|
package/dist/dav.mjs
CHANGED
|
@@ -1,20 +1,281 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
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
|
-
|
|
120
|
+
folder.logger.debug("FileActions initialized");
|
|
121
121
|
}
|
|
122
122
|
if (window._nc_fileactions.find((search) => search.id === action.id)) {
|
|
123
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
887
|
+
folder.logger.debug("FileListHeaders initialized");
|
|
888
888
|
}
|
|
889
889
|
if (window._nc_filelistheader.find((search) => search.id === header.id)) {
|
|
890
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 || !
|
|
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.
|
|
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
|
-
|
|
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 ??
|
|
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 ?? [
|
|
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 ===
|
|
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 =
|
|
2980
|
-
exports.FileType =
|
|
2981
|
-
exports.Folder =
|
|
2982
|
-
exports.Node =
|
|
2983
|
-
exports.NodeStatus =
|
|
2984
|
-
exports.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;
|