diff --git a/packages/@uppy/companion/package.json b/packages/@uppy/companion/package.json index e80167eb03..2d3e8f2d2b 100644 --- a/packages/@uppy/companion/package.json +++ b/packages/@uppy/companion/package.json @@ -65,6 +65,7 @@ "supports-color": "8.x", "tus-js-client": "^4.1.0", "validator": "^13.0.0", + "webdav": "5.7.1", "ws": "8.17.1" }, "devDependencies": { diff --git a/packages/@uppy/companion/src/server/controllers/get.js b/packages/@uppy/companion/src/server/controllers/get.js index 1ba7f916ae..6364399967 100644 --- a/packages/@uppy/companion/src/server/controllers/get.js +++ b/packages/@uppy/companion/src/server/controllers/get.js @@ -8,7 +8,7 @@ async function get (req, res) { const { provider } = req.companion async function getSize () { - return provider.size({ id, token: accessToken, query: req.query }) + return provider.size({ id, token: accessToken, providerUserSession, query: req.query }) } const download = () => provider.download({ id, token: accessToken, providerUserSession, query: req.query }) diff --git a/packages/@uppy/companion/src/server/provider/index.js b/packages/@uppy/companion/src/server/provider/index.js index 55854e8b74..64449d1968 100644 --- a/packages/@uppy/companion/src/server/provider/index.js +++ b/packages/@uppy/companion/src/server/provider/index.js @@ -9,6 +9,7 @@ const instagram = require('./instagram/graph') const facebook = require('./facebook') const onedrive = require('./onedrive') const unsplash = require('./unsplash') +const webdav = require('./webdav') const zoom = require('./zoom') const { getURLBuilder } = require('../helpers/utils') const logger = require('../logger') @@ -68,7 +69,7 @@ module.exports.getProviderMiddleware = (providers, grantConfig) => { * @returns {Record} */ module.exports.getDefaultProviders = () => { - const providers = { dropbox, box, drive: Drive, googlephotos, facebook, onedrive, zoom, instagram, unsplash } + const providers = { dropbox, box, drive: Drive, googlephotos, facebook, onedrive, zoom, instagram, unsplash, webdav } return providers } diff --git a/packages/@uppy/companion/src/server/provider/webdav/index.js b/packages/@uppy/companion/src/server/provider/webdav/index.js new file mode 100644 index 0000000000..f379aff592 --- /dev/null +++ b/packages/@uppy/companion/src/server/provider/webdav/index.js @@ -0,0 +1,182 @@ + +const Provider = require('../Provider') +const { getProtectedHttpAgent, validateURL } = require('../../helpers/request') +const { ProviderApiError, ProviderAuthError } = require('../error') +const { ProviderUserError } = require('../error') +const logger = require('../../logger') + +const defaultDirectory = '/' + +/** + * Adapter for WebDAV servers that support simple auth (non-OAuth). + */ +class WebdavProvider extends Provider { + static get hasSimpleAuth () { + return true + } + + // eslint-disable-next-line class-methods-use-this + isAuthenticated ({ providerUserSession }) { + return providerUserSession.webdavUrl != null + } + + async getClient ({ providerUserSession }) { + const webdavUrl = providerUserSession?.webdavUrl + const { allowLocalUrls } = this + if (!validateURL(webdavUrl, allowLocalUrls)) { + throw new Error('invalid public link url') + } + + // dynamic import because Companion currently uses CommonJS and webdav is shipped as ESM + // todo implement as regular require as soon as Node 20.17 or 22 is required + // or as regular import when Companion is ported to ESM + const { AuthType } = await import('webdav') // eslint-disable-line import/no-unresolved + + // Is this an ownCloud or Nextcloud public link URL? e.g. https://example.com/s/kFy9Lek5sm928xP + // they have specific urls that we can identify + // todo not sure if this is the right way to support nextcloud and other webdavs + if (/\/s\/([^/]+)/.test(webdavUrl)) { + const [baseURL, publicLinkToken] = webdavUrl.split('/s/') + + return this.getClientHelper({ + url: `${baseURL.replace('/index.php', '')}/public.php/webdav/`, + authType: AuthType.Password, + username: publicLinkToken, + password: 'null', + }) + } + + // normal public WebDAV urls + return this.getClientHelper({ + url: webdavUrl, + authType: AuthType.None, + }) + } + + async logout () { // eslint-disable-line class-methods-use-this + return { revoked: true } + } + + async simpleAuth ({ requestBody }) { + try { + const providerUserSession = { webdavUrl: requestBody.form.webdavUrl } + + const client = await this.getClient({ providerUserSession }) + // call the list operation as a way to validate the url + await client.getDirectoryContents(defaultDirectory) + + return providerUserSession + } catch (err) { + logger.error(err, 'provider.webdav.error') + if (['ECONNREFUSED', 'ENOTFOUND'].includes(err.code)) { + throw new ProviderUserError({ message: 'Cannot connect to server' }) + } + // todo report back to the user what actually went wrong + throw err + } + } + + async getClientHelper ({ url, ...options }) { + const { allowLocalUrls } = this + if (!validateURL(url, allowLocalUrls)) { + throw new Error('invalid webdav url') + } + const { protocol } = new URL(url) + const HttpAgentClass = getProtectedHttpAgent({ protocol, allowLocalIPs: !allowLocalUrls }) + + // dynamic import because Companion currently uses CommonJS and webdav is shipped as ESM + // todo implement as regular require as soon as Node 20.17 or 22 is required + // or as regular import when Companion is ported to ESM + const { createClient } = await import('webdav') + return createClient(url, { + ...options, + [`${protocol}Agent`] : new HttpAgentClass(), + }) + } + + async list ({ directory, providerUserSession }) { + return this.withErrorHandling('provider.webdav.list.error', async () => { + // @ts-ignore + if (!this.isAuthenticated({ providerUserSession })) { + throw new ProviderAuthError() + } + + const data = { items: [] } + const client = await this.getClient({ providerUserSession }) + + /** @type {any} */ + const dir = await client.getDirectoryContents(directory || '/') + + dir.forEach(item => { + const isFolder = item.type === 'directory' + const requestPath = encodeURIComponent(`${directory || ''}/${item.basename}`) + + let modifiedDate + try { + modifiedDate = new Date(item.lastmod).toISOString() + } catch (e) { + // ignore invalid date from server + } + + data.items.push({ + isFolder, + id: requestPath, + name: item.basename, + modifiedDate, + requestPath, + ...(!isFolder && { + mimeType: item.mime, + size: item.size, + thumbnail: null, + + }), + }) + }) + + return data + }) + } + + async download ({ id, providerUserSession }) { + return this.withErrorHandling('provider.webdav.download.error', async () => { + const client = await this.getClient({ providerUserSession }) + const stream = client.createReadStream(`/${id}`) + return { stream } + }) + } + + // eslint-disable-next-line + async thumbnail ({ id, providerUserSession }) { + // not implementing this because a public thumbnail from webdav will be used instead + logger.error('call to thumbnail is not implemented', 'provider.webdav.thumbnail.error') + throw new Error('call to thumbnail is not implemented') + } + + // eslint-disable-next-line + async size ({ id, token, providerUserSession }) { + return this.withErrorHandling('provider.webdav.size.error', async () => { + const client = await this.getClient({ providerUserSession }) + + /** @type {any} */ + const stat = await client.stat(id) + return stat.size + }) + } + + // eslint-disable-next-line class-methods-use-this + async withErrorHandling (tag, fn) { + try { + return await fn() + } catch (err) { + let err2 = err + if (err.status === 401) err2 = new ProviderAuthError() + if (err.response) { + err2 = new ProviderApiError('WebDAV API error', err.status) // todo improve (read err?.response?.body readable stream and parse response) + } + logger.error(err2, tag) + throw err2 + } + } +} + +module.exports = WebdavProvider diff --git a/packages/@uppy/locales/src/en_US.ts b/packages/@uppy/locales/src/en_US.ts index 63db6e5714..ff2cdab57f 100644 --- a/packages/@uppy/locales/src/en_US.ts +++ b/packages/@uppy/locales/src/en_US.ts @@ -35,6 +35,7 @@ en_US.strings = { aspectRatioPortrait: 'Crop portrait (9:16)', aspectRatioSquare: 'Crop square', authAborted: 'Authentication aborted', + authenticate: 'Connect', authenticateWith: 'Connect to %{pluginName}', authenticateWithTitle: 'Please authenticate with %{pluginName} to select files', @@ -148,7 +149,10 @@ en_US.strings = { pluginNameScreenCapture: 'Screencast', pluginNameUnsplash: 'Unsplash', pluginNameUrl: 'Link', + pluginNameWebdav: 'WebDAV', pluginNameZoom: 'Zoom', + pluginWebdavInputLabel: + 'WebDAV URL for a file (e.g. from ownCloud or Nextcloud)', poweredBy: 'Powered by %{uppy}', processingXFiles: { '0': 'Processing %{smart_count} file', diff --git a/packages/@uppy/provider-views/src/GooglePicker/GooglePickerView.tsx b/packages/@uppy/provider-views/src/GooglePicker/GooglePickerView.tsx index bea83ebbe2..798ac34208 100644 --- a/packages/@uppy/provider-views/src/GooglePicker/GooglePickerView.tsx +++ b/packages/@uppy/provider-views/src/GooglePicker/GooglePickerView.tsx @@ -226,7 +226,7 @@ export default function GooglePickerView({ } pluginIcon={pickerType === 'drive' ? GoogleDriveIcon : GooglePhotosIcon} handleAuth={showPicker} - i18n={uppy.i18nArray} + i18n={uppy.i18n} loading={loading} /> ) diff --git a/packages/@uppy/provider-views/src/ProviderView/AuthView.tsx b/packages/@uppy/provider-views/src/ProviderView/AuthView.tsx index 3a8d5c9377..103e85b596 100644 --- a/packages/@uppy/provider-views/src/ProviderView/AuthView.tsx +++ b/packages/@uppy/provider-views/src/ProviderView/AuthView.tsx @@ -1,7 +1,7 @@ import { h } from 'preact' import { useCallback } from 'preact/hooks' import type { Body, Meta } from '@uppy/utils/lib/UppyFile' -import type Translator from '@uppy/utils/lib/Translator' +import type { I18n } from '@uppy/utils/lib/Translator' import type { Opts } from './ProviderView.ts' import type ProviderViews from './ProviderView.ts' @@ -9,7 +9,7 @@ type AuthViewProps = { loading: boolean | string pluginName: string pluginIcon: () => h.JSX.Element - i18n: Translator['translateArray'] + i18n: I18n handleAuth: ProviderViews['handleAuth'] renderForm?: Opts['renderAuthForm'] } @@ -56,7 +56,7 @@ function DefaultForm({ onAuth, }: { pluginName: string - i18n: Translator['translateArray'] + i18n: I18n onAuth: AuthViewProps['handleAuth'] }) { // In order to comply with Google's brand we need to create a different button @@ -100,7 +100,7 @@ const defaultRenderForm = ({ onAuth, }: { pluginName: string - i18n: Translator['translateArray'] + i18n: I18n onAuth: AuthViewProps['handleAuth'] }) => @@ -121,9 +121,7 @@ export default function AuthView({ })} -
- {renderForm({ pluginName, i18n, loading, onAuth: handleAuth })} -
+ {renderForm({ pluginName, i18n, loading, onAuth: handleAuth })} ) } diff --git a/packages/@uppy/provider-views/src/ProviderView/ProviderView.tsx b/packages/@uppy/provider-views/src/ProviderView/ProviderView.tsx index 8dc9ed28d2..dba9e2fb76 100644 --- a/packages/@uppy/provider-views/src/ProviderView/ProviderView.tsx +++ b/packages/@uppy/provider-views/src/ProviderView/ProviderView.tsx @@ -10,10 +10,10 @@ import type { } from '@uppy/core/lib/Uppy.js' import type { Body, Meta } from '@uppy/utils/lib/UppyFile' import type { CompanionFile } from '@uppy/utils/lib/CompanionFile' -import type Translator from '@uppy/utils/lib/Translator' import classNames from 'classnames' import type { ValidateableFile } from '@uppy/core/lib/Restricter.js' import remoteFileObjToLocal from '@uppy/utils/lib/remoteFileObjToLocal' +import type { I18n } from '@uppy/utils/lib/Translator' import AuthView from './AuthView.tsx' import Header from './Header.tsx' import Browser from '../Browser.tsx' @@ -75,7 +75,7 @@ export interface Opts { loadAllFiles: boolean renderAuthForm?: (args: { pluginName: string - i18n: Translator['translateArray'] + i18n: I18n loading: boolean | string onAuth: (authFormData: unknown) => Promise }) => h.JSX.Element @@ -434,7 +434,7 @@ export default class ProviderView { pluginName={this.plugin.title} pluginIcon={pluginIcon} handleAuth={this.handleAuth} - i18n={this.plugin.uppy.i18nArray} + i18n={this.plugin.uppy.i18n} renderForm={opts.renderAuthForm} loading={loading} /> diff --git a/packages/@uppy/provider-views/src/index.ts b/packages/@uppy/provider-views/src/index.ts index bdf3178237..98f6d95e9b 100644 --- a/packages/@uppy/provider-views/src/index.ts +++ b/packages/@uppy/provider-views/src/index.ts @@ -5,4 +5,6 @@ export { export { default as SearchProviderViews } from './SearchProviderView/index.ts' +export { default as SearchInput } from './SearchInput.tsx' + export { default as GooglePickerView } from './GooglePicker/GooglePickerView.tsx' diff --git a/packages/@uppy/webdav/package.json b/packages/@uppy/webdav/package.json new file mode 100644 index 0000000000..e3d6e8ee0e --- /dev/null +++ b/packages/@uppy/webdav/package.json @@ -0,0 +1,35 @@ +{ + "name": "@uppy/webdav", + "description": "Import files from WebDAV into Uppy.", + "version": "0.1.0", + "license": "MIT", + "main": "lib/index.js", + "types": "types/index.d.ts", + "type": "module", + "keywords": [ + "file uploader", + "uppy", + "uppy-plugin", + "webdav", + "provider", + "photos", + "videos" + ], + "homepage": "https://uppy.io", + "bugs": { + "url": "https://github.com/transloadit/uppy/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/transloadit/uppy.git" + }, + "dependencies": { + "@uppy/companion-client": "workspace:^", + "@uppy/provider-views": "workspace:^", + "@uppy/utils": "workspace:^", + "preact": "^10.5.13" + }, + "peerDependencies": { + "@uppy/core": "workspace:^" + } +} diff --git a/packages/@uppy/webdav/src/Webdav.tsx b/packages/@uppy/webdav/src/Webdav.tsx new file mode 100644 index 0000000000..26be66387c --- /dev/null +++ b/packages/@uppy/webdav/src/Webdav.tsx @@ -0,0 +1,159 @@ +import { h, type ComponentChild } from 'preact' +import { useState, useCallback } from 'preact/hooks' + +import { + UIPlugin, + type Body, + type Meta, + type UnknownProviderPlugin, + type UppyFile, +} from '@uppy/core' +import { + Provider, + tokenStorage, + type CompanionPluginOptions, +} from '@uppy/companion-client' +import { + SearchInput, + defaultPickerIcon, + ProviderViews, +} from '@uppy/provider-views' + +import type { + AsyncStore, + UnknownProviderPluginState, + Uppy, +} from '@uppy/core/lib/Uppy.js' +import type { I18n } from '@uppy/utils/lib/Translator' +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore We don't want TS to generate types for the package.json +import packageJson from '../package.json' +import locale from './locale.ts' + +class WebdavSimpleAuthProvider extends Provider< + M, + B +> { + async login({ + authFormData, + uppyVersions, + signal, + }: { + uppyVersions: string + authFormData: unknown + signal: AbortSignal + }) { + return this.loginSimpleAuth({ uppyVersions, authFormData, signal }) + } + + async logout(): Promise { + await this.removeAuthToken() + return { + ok: true, + revoked: true, + } as unknown as ResBody + } +} + +const AuthForm = ({ + i18n, + onAuth, +}: { + i18n: I18n + onAuth: (arg: { webdavUrl: string }) => void +}) => { + const [webdavUrl, setWebdavUrl] = useState('') + + const onSubmit = useCallback(() => { + onAuth({ webdavUrl: webdavUrl.trim() }) + }, [onAuth, webdavUrl]) + + return ( + + ) +} + +export type WebdavOptions = CompanionPluginOptions + +export default class Webdav + extends UIPlugin + implements UnknownProviderPlugin +{ + static VERSION = packageJson.version + + icon: () => h.JSX.Element = defaultPickerIcon + + provider: Provider + + view!: ProviderViews + + storage: AsyncStore + + files: UppyFile[] + + rootFolderId: string | null = null + + constructor(uppy: Uppy, opts: WebdavOptions) { + super(uppy, opts) + this.id = this.opts.id || 'WebDav' + this.type = 'acquirer' + this.files = [] + this.storage = this.opts.storage || tokenStorage + + this.defaultLocale = locale + + this.i18nInit() + + this.title = this.i18n('pluginNameWebdav') + + this.provider = new WebdavSimpleAuthProvider(uppy, { + companionUrl: this.opts.companionUrl, + companionHeaders: this.opts.companionHeaders, + companionKeysParams: this.opts.companionKeysParams, + companionCookiesRule: this.opts.companionCookiesRule, + provider: 'webdav', + pluginId: this.id, + supportsRefreshToken: false, + }) + + // this.onFirstRender = this.onFirstRender.bind(this) + this.render = this.render.bind(this) + } + + install() { + this.view = new ProviderViews(this, { + provider: this.provider, + viewType: 'list', + showTitles: true, + showFilter: true, + showBreadcrumbs: true, + renderAuthForm: ({ i18n, onAuth }) => ( + + ), + }) + + const { target } = this.opts + if (target) { + this.mount(target, this) + } + } + + uninstall() { + this.view.tearDown() + this.unmount() + } + + render(state: unknown): ComponentChild { + return this.view.render(state) + } +} diff --git a/packages/@uppy/webdav/src/index.ts b/packages/@uppy/webdav/src/index.ts new file mode 100644 index 0000000000..c5a3243f99 --- /dev/null +++ b/packages/@uppy/webdav/src/index.ts @@ -0,0 +1 @@ +export { default } from './Webdav.tsx' diff --git a/packages/@uppy/webdav/src/locale.ts b/packages/@uppy/webdav/src/locale.ts new file mode 100644 index 0000000000..3c79fb804f --- /dev/null +++ b/packages/@uppy/webdav/src/locale.ts @@ -0,0 +1,8 @@ +export default { + strings: { + pluginNameWebdav: 'WebDAV', + authenticate: 'Connect', + pluginWebdavInputLabel: + 'WebDAV URL for a file (e.g. from ownCloud or Nextcloud)', + }, +} diff --git a/packages/@uppy/webdav/tsconfig.build.json b/packages/@uppy/webdav/tsconfig.build.json new file mode 100644 index 0000000000..43364c8759 --- /dev/null +++ b/packages/@uppy/webdav/tsconfig.build.json @@ -0,0 +1,33 @@ +{ + "extends": "../../../tsconfig.shared", + "compilerOptions": { + "outDir": "./lib", + "paths": { + "@uppy/utils/lib/*": ["../utils/src/*"], + "@uppy/core": ["../core/src/index.js"], + "@uppy/core/lib/*": ["../core/src/*"], + "@uppy/companion-client": ["../companion-client/src/index.js"], + "@uppy/companion-client/lib/*": ["../companion-client/src/*"], + "@uppy/provider-views": ["../provider-views/src/index.js"], + "@uppy/provider-views/lib/*": ["../provider-views/src/*"] + }, + "resolveJsonModule": false, + "rootDir": "./src" + }, + "include": ["./src/**/*.*"], + "exclude": ["./src/**/*.test.ts"], + "references": [ + { + "path": "../utils/tsconfig.build.json" + }, + { + "path": "../core/tsconfig.build.json" + }, + { + "path": "../provider-views/tsconfig.build.json" + }, + { + "path": "../companion-client/tsconfig.build.json" + } + ] +} diff --git a/packages/@uppy/webdav/tsconfig.json b/packages/@uppy/webdav/tsconfig.json new file mode 100644 index 0000000000..0846a1d621 --- /dev/null +++ b/packages/@uppy/webdav/tsconfig.json @@ -0,0 +1,31 @@ +{ + "extends": "../../../tsconfig.shared", + "compilerOptions": { + "emitDeclarationOnly": false, + "noEmit": true, + "paths": { + "@uppy/utils/lib/*": ["../utils/src/*"], + "@uppy/core": ["../core/src/index.js"], + "@uppy/core/lib/*": ["../core/src/*"], + "@uppy/companion-client": ["../companion-client/src/index.js"], + "@uppy/companion-client/lib/*": ["../companion-client/src/*"], + "@uppy/provider-views": ["../provider-views/src/index.js"], + "@uppy/provider-views/lib/*": ["../provider-views/src/*"], + }, + }, + "include": ["./package.json", "./src/**/*.*"], + "references": [ + { + "path": "../utils/tsconfig.build.json", + }, + { + "path": "../core/tsconfig.build.json", + }, + { + "path": "../provider-views/tsconfig.build.json", + }, + { + "path": "../companion-client/tsconfig.build.json", + }, + ], +} diff --git a/packages/uppy/package.json b/packages/uppy/package.json index 3d284c33bd..02033abb5b 100644 --- a/packages/uppy/package.json +++ b/packages/uppy/package.json @@ -67,6 +67,7 @@ "@uppy/unsplash": "workspace:^", "@uppy/url": "workspace:^", "@uppy/webcam": "workspace:^", + "@uppy/webdav": "workspace:^", "@uppy/xhr-upload": "workspace:^", "@uppy/zoom": "workspace:^" } diff --git a/private/dev/Dashboard.js b/private/dev/Dashboard.js index 9c3d2d8a1c..726dc1ed07 100644 --- a/private/dev/Dashboard.js +++ b/private/dev/Dashboard.js @@ -15,6 +15,7 @@ import DropTarget from '@uppy/drop-target' import Audio from '@uppy/audio' import Compressor from '@uppy/compressor' import GoogleDrive from '@uppy/google-drive' +import Webdav from '@uppy/webdav' import english from '@uppy/locales/lib/en_US.js' import GoogleDrivePicker from '@uppy/google-drive-picker' import GooglePhotosPicker from '@uppy/google-photos-picker' @@ -164,6 +165,11 @@ export default () => { showVideoSourceDropdown: true, showRecordingLength: true, }) + .use(Webdav, { + target: Dashboard, + companionUrl: COMPANION_URL, + companionAllowedHosts + }) .use(Audio, { target: Dashboard, showRecordingLength: true, diff --git a/tsconfig.json b/tsconfig.json index c64bff1806..b3781ad6be 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -121,6 +121,9 @@ { "path": "./packages/@uppy/zoom/tsconfig.build.json", }, + { + "path": "./packages/@uppy/webdav/tsconfig.build.json", + }, { "path": "./packages/uppy/tsconfig.build.json", }, diff --git a/yarn.lock b/yarn.lock index b44966bd56..b2f3d7b2db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3100,6 +3100,18 @@ __metadata: languageName: node linkType: hard +"@buttercup/fetch@npm:^0.2.1": + version: 0.2.1 + resolution: "@buttercup/fetch@npm:0.2.1" + dependencies: + node-fetch: "npm:^3.3.0" + dependenciesMeta: + node-fetch: + optional: true + checksum: 10/ad2fc2ce964409a44238cca94a93ad3817666c477fd1c1ace914a3c589c638522747545bf53f3a684c10a2edf957134dc2d3fa7effe5a773d1bea2c2bee9dd2c + languageName: node + linkType: hard + "@cnakazawa/watch@npm:^1.0.3": version: 1.0.4 resolution: "@cnakazawa/watch@npm:1.0.4" @@ -8765,6 +8777,7 @@ __metadata: tus-js-client: "npm:^4.1.0" typescript: "npm:~5.4" validator: "npm:^13.0.0" + webdav: "npm:5.7.1" ws: "npm:8.17.1" bin: companion: ./bin/companion @@ -9312,6 +9325,19 @@ __metadata: languageName: unknown linkType: soft +"@uppy/webdav@workspace:^, @uppy/webdav@workspace:packages/@uppy/webdav": + version: 0.0.0-use.local + resolution: "@uppy/webdav@workspace:packages/@uppy/webdav" + dependencies: + "@uppy/companion-client": "workspace:^" + "@uppy/provider-views": "workspace:^" + "@uppy/utils": "workspace:^" + preact: "npm:^10.5.13" + peerDependencies: + "@uppy/core": "workspace:^" + languageName: unknown + linkType: soft + "@uppy/xhr-upload@workspace:*, @uppy/xhr-upload@workspace:^, @uppy/xhr-upload@workspace:packages/@uppy/xhr-upload": version: 0.0.0-use.local resolution: "@uppy/xhr-upload@workspace:packages/@uppy/xhr-upload" @@ -10854,6 +10880,13 @@ __metadata: languageName: node linkType: hard +"base-64@npm:^1.0.0": + version: 1.0.0 + resolution: "base-64@npm:1.0.0" + checksum: 10/d10b64a1fc9b2c5a5f39f1ce1e6c9d1c5b249222bbfa3a0604c592d90623caf74419983feadd8a170f27dc0c3389704f72faafa3e645aeb56bfc030c93ff074a + languageName: node + linkType: hard + "base-x@npm:^3.0.8": version: 3.0.9 resolution: "base-x@npm:3.0.9" @@ -11256,6 +11289,13 @@ __metadata: languageName: node linkType: hard +"byte-length@npm:^1.0.2": + version: 1.0.2 + resolution: "byte-length@npm:1.0.2" + checksum: 10/69e2b00a14a81f675ea9946135c42ee1a1d9f689d5ba1327eb6700fcde2ccacbd09b42f7e514de1d2b763960251d8c790b3d7304a5a1a27b1457e34c129be8c7 + languageName: node + linkType: hard + "bytes@npm:3.0.0": version: 3.0.0 resolution: "bytes@npm:3.0.0" @@ -11591,6 +11631,13 @@ __metadata: languageName: node linkType: hard +"charenc@npm:0.0.2": + version: 0.0.2 + resolution: "charenc@npm:0.0.2" + checksum: 10/81dcadbe57e861d527faf6dd3855dc857395a1c4d6781f4847288ab23cffb7b3ee80d57c15bba7252ffe3e5e8019db767757ee7975663ad2ca0939bb8fcaf2e5 + languageName: node + linkType: hard + "check-error@npm:^1.0.3": version: 1.0.3 resolution: "check-error@npm:1.0.3" @@ -12546,6 +12593,13 @@ __metadata: languageName: node linkType: hard +"crypt@npm:0.0.2": + version: 0.0.2 + resolution: "crypt@npm:0.0.2" + checksum: 10/2c72768de3d28278c7c9ffd81a298b26f87ecdfe94415084f339e6632f089b43fe039f2c93f612bcb5ffe447238373d93b2e8c90894cba6cfb0ac7a74616f8b9 + languageName: node + linkType: hard + "css-declaration-sorter@npm:^7.2.0": version: 7.2.0 resolution: "css-declaration-sorter@npm:7.2.0" @@ -12873,6 +12927,13 @@ __metadata: languageName: node linkType: hard +"data-uri-to-buffer@npm:^4.0.0": + version: 4.0.1 + resolution: "data-uri-to-buffer@npm:4.0.1" + checksum: 10/0d0790b67ffec5302f204c2ccca4494f70b4e2d940fea3d36b09f0bb2b8539c2e86690429eb1f1dc4bcc9e4df0644193073e63d9ee48ac9fce79ec1506e4aa4c + languageName: node + linkType: hard + "data-urls@npm:^5.0.0": version: 5.0.0 resolution: "data-urls@npm:5.0.0" @@ -13806,6 +13867,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^5.0.0": + version: 5.0.0 + resolution: "entities@npm:5.0.0" + checksum: 10/d7d1b855abee681e7570c1357c94986662c890890c30601ddaf59b7b2b63fcc225118e784ffa96f6bea39bfa675252831e32af49b1f7ebe5ceabf89d820f2beb + languageName: node + linkType: hard + "env-paths@npm:^2.2.0, env-paths@npm:^2.2.1": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -15521,6 +15589,17 @@ __metadata: languageName: node linkType: hard +"fast-xml-parser@npm:^4.4.1": + version: 4.5.0 + resolution: "fast-xml-parser@npm:4.5.0" + dependencies: + strnum: "npm:^1.0.5" + bin: + fxparser: src/cli/cli.js + checksum: 10/dc9571c10e7b57b5be54bcd2d92f50c446eb42ea5df347d253e94dd14eb99b5300a6d172e840f151e0721933ca2406165a8d9b316a6d777bf0596dc4fe1df756 + languageName: node + linkType: hard + "fastest-levenshtein@npm:^1.0.16": version: 1.0.16 resolution: "fastest-levenshtein@npm:1.0.16" @@ -15619,6 +15698,16 @@ __metadata: languageName: node linkType: hard +"fetch-blob@npm:^3.1.2, fetch-blob@npm:^3.1.4": + version: 3.2.0 + resolution: "fetch-blob@npm:3.2.0" + dependencies: + node-domexception: "npm:^1.0.0" + web-streams-polyfill: "npm:^3.0.3" + checksum: 10/5264ecceb5fdc19eb51d1d0359921f12730941e333019e673e71eb73921146dceabcb0b8f534582be4497312d656508a439ad0f5edeec2b29ab2e10c72a1f86b + languageName: node + linkType: hard + "figures@npm:^3.2.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -15955,6 +16044,15 @@ __metadata: languageName: node linkType: hard +"formdata-polyfill@npm:^4.0.10": + version: 4.0.10 + resolution: "formdata-polyfill@npm:4.0.10" + dependencies: + fetch-blob: "npm:^3.1.2" + checksum: 10/9b5001d2edef3c9449ac3f48bd4f8cc92e7d0f2e7c1a5c8ba555ad4e77535cc5cf621fabe49e97f304067037282dd9093b9160a3cb533e46420b446c4e6bc06f + languageName: node + linkType: hard + "formidable@npm:^2.1.2": version: 2.1.2 resolution: "formidable@npm:2.1.2" @@ -16835,6 +16933,13 @@ __metadata: languageName: node linkType: hard +"hot-patcher@npm:^2.0.1": + version: 2.0.1 + resolution: "hot-patcher@npm:2.0.1" + checksum: 10/c207007dd55609527bcb26450606c714c313ac52af466746d25916f722da2c48fd1257871c07bd07af5ee586f2c1bf8ab59919db66dcea4a2c82b7c51c9a1317 + languageName: node + linkType: hard + "hpack.js@npm:^2.1.6": version: 2.1.6 resolution: "hpack.js@npm:2.1.6" @@ -17601,7 +17706,7 @@ __metadata: languageName: node linkType: hard -"is-buffer@npm:^1.1.5": +"is-buffer@npm:^1.1.5, is-buffer@npm:~1.1.6": version: 1.1.6 resolution: "is-buffer@npm:1.1.6" checksum: 10/f63da109e74bbe8947036ed529d43e4ae0c5fcd0909921dce4917ad3ea212c6a87c29f525ba1d17c0858c18331cf1046d4fc69ef59ed26896b25c8288a627133 @@ -19531,6 +19636,13 @@ __metadata: languageName: node linkType: hard +"layerr@npm:^3.0.0": + version: 3.0.0 + resolution: "layerr@npm:3.0.0" + checksum: 10/5b9518795ef5d447f2b4c66ebab223b0a4fb37505ba27013920f71691726211298e630750d5fa8b03ddb5ce191d24e26d49fa40e0042193ecd680f15d89311f9 + languageName: node + linkType: hard + "lazy-ass@npm:1.6.0, lazy-ass@npm:^1.6.0": version: 1.6.0 resolution: "lazy-ass@npm:1.6.0" @@ -20564,6 +20676,17 @@ __metadata: languageName: node linkType: hard +"md5@npm:^2.3.0": + version: 2.3.0 + resolution: "md5@npm:2.3.0" + dependencies: + charenc: "npm:0.0.2" + crypt: "npm:0.0.2" + is-buffer: "npm:~1.1.6" + checksum: 10/88dce9fb8df1a084c2385726dcc18c7f54e0b64c261b5def7cdfe4928c4ee1cd68695c34108b4fab7ecceb05838c938aa411c6143df9fdc0026c4ddb4e4e72fa + languageName: node + linkType: hard + "mdast-comment-marker@npm:^2.0.0": version: 2.1.2 resolution: "mdast-comment-marker@npm:2.1.2" @@ -21985,6 +22108,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^9.0.5": + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10/dd6a8927b063aca6d910b119e1f2df6d2ce7d36eab91de83167dd136bb85e1ebff97b0d3de1cb08bd1f7e018ca170b4962479fefab5b2a69e2ae12cb2edc8348 + languageName: node + linkType: hard + "minimatch@npm:~3.0.2": version: 3.0.8 resolution: "minimatch@npm:3.0.8" @@ -22409,6 +22541,13 @@ __metadata: languageName: node linkType: hard +"nested-property@npm:^4.0.0": + version: 4.0.0 + resolution: "nested-property@npm:4.0.0" + checksum: 10/5653a67d68e19ed045d571b44f1a84ee07f8fd03f314e5876783d17e600d8799c51ff3f6e93892427ab011b81f885300126f231f2d6c7bb192234e6d97bbe245 + languageName: node + linkType: hard + "ng-packagr@npm:^18.0.0": version: 18.0.0 resolution: "ng-packagr@npm:18.0.0" @@ -22577,6 +22716,13 @@ __metadata: languageName: node linkType: hard +"node-domexception@npm:^1.0.0": + version: 1.0.0 + resolution: "node-domexception@npm:1.0.0" + checksum: 10/e332522f242348c511640c25a6fc7da4f30e09e580c70c6b13cb0be83c78c3e71c8d4665af2527e869fc96848924a4316ae7ec9014c091e2156f41739d4fa233 + languageName: node + linkType: hard + "node-fetch@npm:^1.0.1": version: 1.7.3 resolution: "node-fetch@npm:1.7.3" @@ -22601,6 +22747,17 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^3.3.0, node-fetch@npm:^3.3.2": + version: 3.3.2 + resolution: "node-fetch@npm:3.3.2" + dependencies: + data-uri-to-buffer: "npm:^4.0.0" + fetch-blob: "npm:^3.1.4" + formdata-polyfill: "npm:^4.0.10" + checksum: 10/24207ca8c81231c7c59151840e3fded461d67a31cf3e3b3968e12201a42f89ce4a0b5fb7079b1fa0a4655957b1ca9257553200f03a9f668b45ebad265ca5593d + languageName: node + linkType: hard + "node-forge@npm:^1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -23910,6 +24067,13 @@ __metadata: languageName: node linkType: hard +"path-posix@npm:^1.0.0": + version: 1.0.0 + resolution: "path-posix@npm:1.0.0" + checksum: 10/b4eae5cd4b7c943719c2f8679c53d02988bf1701583065cc5b301bb671e6ec13d6e4257257fe92a5c7b34c35e215b322a8976ce89d29dcf8801c0ee2cc75ca18 + languageName: node + linkType: hard + "path-scurry@npm:^1.11.1": version: 1.11.1 resolution: "path-scurry@npm:1.11.1" @@ -29831,6 +29995,7 @@ __metadata: "@uppy/unsplash": "workspace:^" "@uppy/url": "workspace:^" "@uppy/webcam": "workspace:^" + "@uppy/webdav": "workspace:^" "@uppy/xhr-upload": "workspace:^" "@uppy/zoom": "workspace:^" languageName: unknown @@ -29852,7 +30017,14 @@ __metadata: languageName: node linkType: hard -"url-parse@npm:^1.4.4, url-parse@npm:^1.5.3, url-parse@npm:^1.5.7": +"url-join@npm:^5.0.0": + version: 5.0.0 + resolution: "url-join@npm:5.0.0" + checksum: 10/5921384a8ad4395b49ce4b50aa26efbc429cebe0bc8b3660ad693dd12fd859747b5369be0443e60e53a7850b2bc9d7d0687bcb94386662b40e743596bbf38101 + languageName: node + linkType: hard + +"url-parse@npm:^1.4.4, url-parse@npm:^1.5.10, url-parse@npm:^1.5.3, url-parse@npm:^1.5.7": version: 1.5.10 resolution: "url-parse@npm:1.5.10" dependencies: @@ -30419,6 +30591,35 @@ __metadata: languageName: node linkType: hard +"web-streams-polyfill@npm:^3.0.3": + version: 3.3.3 + resolution: "web-streams-polyfill@npm:3.3.3" + checksum: 10/8e7e13501b3834094a50abe7c0b6456155a55d7571312b89570012ef47ec2a46d766934768c50aabad10a9c30dd764a407623e8bfcc74fcb58495c29130edea9 + languageName: node + linkType: hard + +"webdav@npm:5.7.1": + version: 5.7.1 + resolution: "webdav@npm:5.7.1" + dependencies: + "@buttercup/fetch": "npm:^0.2.1" + base-64: "npm:^1.0.0" + byte-length: "npm:^1.0.2" + entities: "npm:^5.0.0" + fast-xml-parser: "npm:^4.4.1" + hot-patcher: "npm:^2.0.1" + layerr: "npm:^3.0.0" + md5: "npm:^2.3.0" + minimatch: "npm:^9.0.5" + nested-property: "npm:^4.0.0" + node-fetch: "npm:^3.3.2" + path-posix: "npm:^1.0.0" + url-join: "npm:^5.0.0" + url-parse: "npm:^1.5.10" + checksum: 10/3b22e32b430d4815a52c5b51d8c2b7ce9b9ff6b03fd32c66ee73d208bd5142a9a15fab18cde674531a37cf8cf4bef2ca0f0d7ca613b4f2d7141f9a6be7c0c135 + languageName: node + linkType: hard + "webidl-conversions@npm:^3.0.0": version: 3.0.1 resolution: "webidl-conversions@npm:3.0.1"