Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: perry-mitchell/webdav-client
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: baf858a4856d44ae19ac12cb10c469b3e6c41ae4
Choose a base ref
...
head repository: perry-mitchell/webdav-client
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1692dcf77f1acd8e27622a8f63f2e6004b7c3f51
Choose a head ref
Loading
Showing with 7,608 additions and 10,270 deletions.
  1. +2 −2 .babelrc
  2. +1 −0 .gitignore
  3. +6 −15 .travis.yml
  4. +42 −3 API.md
  5. +75 −0 CHANGELOG.md
  6. +46 −4 README.md
  7. +6,860 −10,044 package-lock.json
  8. +40 −33 package.json
  9. +14 −0 source/encode.js
  10. +40 −7 source/factory.js
  11. +1 −2 source/interface/copyFile.js
  12. +1 −2 source/interface/createDirectory.js
  13. +11 −4 source/interface/createStream.js
  14. +2 −3 source/interface/custom.js
  15. +59 −49 source/interface/dav.js
  16. +1 −2 source/interface/delete.js
  17. +15 −19 source/interface/directoryContents.js
  18. +16 −0 source/interface/exists.js
  19. +1 −2 source/interface/getFile.js
  20. +1 −2 source/interface/moveFile.js
  21. +15 −3 source/interface/putFile.js
  22. +10 −19 source/interface/quota.js
  23. +8 −10 source/interface/stat.js
  24. +53 −2 source/merge.js
  25. +21 −0 source/request.js
  26. +1 −1 source/url.js
  27. +5 −0 test/responses/empty-multistatus.xml
  28. +3 −3 test/server/index.js
  29. +1 −0 test/serverContents/file % name.txt
  30. +1 −0 test/serverContents/file&name.txt
  31. +1 −0 test/serverContents/with & in path/file.txt
  32. +1 −1 test/specs/auth.spec.js
  33. +33 −0 test/specs/exists.spec.js
  34. +45 −8 test/specs/getDirectoryContents.spec.js
  35. +1 −1 test/specs/getFileContents.spec.js
  36. +1 −1 test/specs/index.js
  37. +1 −1 test/specs/merge.spec.js
  38. +9 −0 test/specs/putFileContents.spec.js
  39. +1 −1 test/specs/request.spec.js
  40. +16 −0 test/specs/stat.spec.js
  41. +2 −2 test/web/karma.conf.js
  42. +26 −0 test/web/specs/exists.spec.js
  43. +24 −0 test/web/specs/factory.spec.js
  44. +1 −1 test/web/specs/getDirectoryContents.spec.js
  45. +43 −0 test/web/specs/getFileContents.spec.js
  46. +0 −23 test/web/webpack.config.js
  47. +51 −0 webpack.config.js
4 changes: 2 additions & 2 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"presets": [
["env", {
["@babel/preset-env", {
"targets": {
"node": 6
"node": 10
},
"debug": true
}]
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -7,3 +7,4 @@ test.js
node_modules
test/testContents
/dist
/web
21 changes: 6 additions & 15 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -7,30 +7,21 @@ matrix:
- NAME="Node stable"
- language: node_js
script: npm run test:node
node_js: "10"
node_js: "12"
env:
- NAME="Node 10"
- NAME="Node 12"
- language: node_js
script: npm run test:node
node_js: "8"
env:
- NAME="Node 8"
- language: node_js
script: npm run test:node
node_js: "6"
node_js: "10"
env:
- NAME="Node 6"
- NAME="Node 10"
- language: node_js
node_js: "8"
node_js: "12"
sudo: required
env:
- NAME="Web"
services:
- xvfb
addons:
apt:
sources:
- google-chrome
packages:
- google-chrome-stable
chrome: stable
script: npm run test:web
45 changes: 42 additions & 3 deletions API.md
Original file line number Diff line number Diff line change
@@ -14,6 +14,9 @@
<dt><a href="#encodePath">encodePath(path)</a> ⇒ <code>String</code></dt>
<dd><p>Encode a path for use with WebDAV servers</p>
</dd>
<dt><a href="#joinURL">joinURL(...parts)</a> ⇒ <code>String</code></dt>
<dd><p>Join URL segments</p>
</dd>
<dt><a href="#prepareRequestOptions">prepareRequestOptions(requestOptions, methodOptions)</a></dt>
<dd><p>Process request options before being passed to Axios</p>
</dd>
@@ -123,6 +126,18 @@ Encode a path for use with WebDAV servers
| --- | --- | --- |
| path | <code>String</code> | The path to encode |

<a name="joinURL"></a>

## joinURL(...parts) ⇒ <code>String</code>
Join URL segments

**Kind**: global function
**Returns**: <code>String</code> - A joined URL string

| Param | Type | Description |
| --- | --- | --- |
| ...parts | <code>String</code> | URL segments to join |

<a name="prepareRequestOptions"></a>

## prepareRequestOptions(requestOptions, methodOptions)
@@ -161,9 +176,10 @@ Client adapter
* [.copyFile(remotePath, targetRemotePath, [options])](#ClientInterface.copyFile) ⇒ <code>Promise</code>
* [.createDirectory(dirPath, [options])](#ClientInterface.createDirectory) ⇒ <code>Promise</code>
* [.createReadStream(remoteFilename, [options])](#ClientInterface.createReadStream) ⇒ <code>Readable</code>
* [.createWriteStream(remoteFilename, [options])](#ClientInterface.createWriteStream) ⇒ <code>Writeable</code>
* [.createWriteStream(remoteFilename, [options], [callback])](#ClientInterface.createWriteStream) ⇒ <code>Writeable</code>
* [.customRequest(remotePath, [requestOptions], [options])](#ClientInterface.customRequest) ⇒ <code>Promise.&lt;Any&gt;</code>
* [.deleteFile(remotePath, [options])](#ClientInterface.deleteFile) ⇒ <code>Promise</code>
* [.exists(remotePath, [options])](#ClientInterface.exists) ⇒ <code>Promise.&lt;Boolean&gt;</code>
* [.getDirectoryContents(remotePath, [options])](#ClientInterface.getDirectoryContents) ⇒ <code>Promise.&lt;Array.&lt;Stat&gt;&gt;</code>
* [.getFileContents(remoteFilename, [options])](#ClientInterface.getFileContents) ⇒ <code>Promise.&lt;(Buffer\|String)&gt;</code>
* [.getFileDownloadLink(remoteFilename, [options])](#ClientInterface.getFileDownloadLink) ⇒ <code>String</code>
@@ -228,7 +244,7 @@ const remote = client.createReadStream("/data.zip");
```
<a name="ClientInterface.createWriteStream"></a>

### ClientInterface.createWriteStream(remoteFilename, [options]) ⇒ <code>Writeable</code>
### ClientInterface.createWriteStream(remoteFilename, [options], [callback]) ⇒ <code>Writeable</code>
Create a writeable stream to a remote file

**Kind**: static method of [<code>ClientInterface</code>](#ClientInterface)
@@ -238,6 +254,7 @@ Create a writeable stream to a remote file
| --- | --- | --- |
| remoteFilename | <code>String</code> | The file to write to |
| [options] | [<code>PutOptions</code>](#PutOptions) | Options for the request |
| [callback] | <code>function</code> | Optional callback to fire once the request has finished |

**Example**
```js
@@ -286,6 +303,26 @@ Delete a remote file
```js
await client.deleteFile("/some/file.txt");
```
<a name="ClientInterface.exists"></a>

### ClientInterface.exists(remotePath, [options]) ⇒ <code>Promise.&lt;Boolean&gt;</code>
Check if a remote file or directory exists

**Kind**: static method of [<code>ClientInterface</code>](#ClientInterface)
**Returns**: <code>Promise.&lt;Boolean&gt;</code> - A promise that resolves with true if the path exists
or false if it does not

| Param | Type | Description |
| --- | --- | --- |
| remotePath | <code>String</code> | The remote path to check |
| [options] | [<code>UserOptions</code>](#UserOptions) | The options for the request |

**Example**
```js
if (await client.exists("/some-path/file.txt")) {
// Do something
}
```
<a name="ClientInterface.getDirectoryContents"></a>

### ClientInterface.getDirectoryContents(remotePath, [options]) ⇒ <code>Promise.&lt;Array.&lt;Stat&gt;&gt;</code>
@@ -425,6 +462,7 @@ Options for creating a resource
| Name | Type | Description |
| --- | --- | --- |
| [overwrite] | <code>Boolean</code> | Whether or not to overwrite existing files (default: true) |
| [maxBodyLength] | <code>Number</code> | The maximum amount of bytes to upload (default: 10 MiB) (only in nodejs-environments) |

<a name="OptionsWithFormat"></a>

@@ -438,6 +476,7 @@ Options with headers and format
| --- | --- | --- |
| format | <code>String</code> | The format to use (text/binary) |
| [details] | <code>Boolean</code> | Provided detailed response information, such as response headers (defaults to false). Only available on requests that return result data. |
| [maxContentLength] | <code>Number</code> | The maximum amount of bytes to download (default: 10 MiB) |

<a name="OptionsForAdvancedResponses"></a>

@@ -499,7 +538,7 @@ A stat result
| --- | --- | --- |
| filename | <code>String</code> | The full path and filename of the remote item |
| basename | <code>String</code> | The base filename of the remote item, without the path |
| lastmod | <code>String</code> | The last modification date (eg. "Sun, 13 Mar 2016 04:23:32 GMT") |
| lastmod | <code>String</code> \| <code>null</code> | The last modification date (eg. "Sun, 13 Mar 2016 04:23:32 GMT") |
| size | <code>Number</code> | The size of the remote item |
| type | <code>String</code> | The type of the item (file/directory) |
| [mime] | <code>String</code> | The file mimetype (not present on directories) |
75 changes: 75 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,80 @@
# WebDAV-Client changelog

## v3.6.2
_2021-01-06_

* **Security Patches**:
* [#232](https://github.com/perry-mitchell/webdav-client/issues/232) Axios server-side request forgery vulerability ([CVE-2020-28168](https://github.com/advisories/GHSA-4w2v-q235-vp99))

## v3.6.1
_2020-10-15_

* **Bugfixes**:
* [#221](https://github.com/perry-mitchell/webdav-client/issues/221) Stat function erroneously decodes paths with `%` in them

## v3.6.0
_2020-10-12_

* [#220](https://github.com/perry-mitchell/webdav-client/pull/220) `maxBodyLength` option for changing written files max size
* **Bugfixes**:
* [#218](https://github.com/perry-mitchell/webdav-client/issues/218) Invalid response error - No root multistatus

## v3.5.0
_2020-10-08_

* Upgrade dependencies (major versions)
* [axios upgrade -> 0.20](https://github.com/axios/axios/blob/master/CHANGELOG.md#0200-august-20-2020)

## v3.4.0
_2020-10-08_

* **Bugfixes**:
* [#215](https://github.com/perry-mitchell/webdav-client/pull/215) Excessive memory usage when uploading big files (axios max-redirects)
* [#213](https://github.com/perry-mitchell/webdav-client/pull/213) `getDirectoryContents` fails for directories with `&` in the name

## v3.3.0
_2020-04-19_

* Node 10 build configuration
* [#201](https://github.com/perry-mitchell/webdav-client/pull/201) Improved object merging for configurations (no merging instances)
* [#200](https://github.com/perry-mitchell/webdav-client/pull/200) `createWriteStream` callback support (when request finishes finishes)
* Improved filename decoding
* **Bugfix**:
* [#198](https://github.com/perry-mitchell/webdav-client/issues/198) Encoded characters in directory contents (HTML entities)

## v3.2.0
_2020-02-05_

* `exists` method

## v3.1.0
_2020-02-05_

* Improved parsing logic for more robust handling of various PROPFIND requests
* **Bugfix**:
* [#194](https://github.com/perry-mitchell/webdav-client/issues/194) Several properties not defined in directory-contents / stats payloads
* [#147](https://github.com/perry-mitchell/webdav-client/issues/147) `Content-length` header being attached to stream requests erroneously

## v3.0.0
_2020-01-26_

* Removed support for NodeJS < 10
* Web support
* Replaced XML parsing library (no dependencies, no streaming - better web support)
* `createReadStream` and `createWriteStream` stubbed but disabled in web version

## v2.10.2
_2020-01-25_

* **Bugfix**:
* [#189](https://github.com/perry-mitchell/webdav-client/issues/189) Maximum call stack size exceeded during digest auth usage (property merging)

## v2.10.1
_2019-12-17_

* **Bugfix**:
* [#185](https://github.com/perry-mitchell/webdav-client/issues/185) Extra trailing slash after join for URL components on root account requests

## v2.10.0
_2019-10-12_

50 changes: 46 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -10,13 +10,31 @@ WebDAV is a well-known, stable and highly flexible protocol for interacting with

This library provides a **WebDAV client** interface that makes interacting with WebDAV enabled services easy. The API returns promises and resolve with the results. It parses and prepares directory-contents requests for easy consumption, as well as providing methods for fetching things like file stats and quotas.

This library is compatibale with NodeJS version 6 and above (for version 4 support, use versions in the range of `1.*`). Version 1.x is now in maintenance mode and will receive no further feature additions. It will receive the odd bug fix when necessary.

Please read the [contribution guide](CONTRIBUTING.md) if you plan on making an issue or PR.

### Node support

This library is compatibale with **NodeJS version 10** and above (For version 6/8 support, use versions in the range of `2.*`. For version 4 support, use versions in the range of `1.*`). Version 2.x is now in maintenance mode and will receive no further feature additions. It will receive the odd bug fix when necessary. Version 1.x is no longer supported.

### Usage in the Browser

No transpiled package is provided, however it should be fine to transpile it with Webpack and Rollup (tested with Webpack in [external projects](https://github.com/buttercup/buttercup-browser-extension/blob/f980416d8c97e627ff9d8f3e1f48d09fcdfd53df/source/setup/library/remote.js#L1)). You must make sure to transpile/bundle all necessary WebDAV client dependencies, **including** NodeJS built-ins like `path`.
As of version 3, WebDAV client is now supported in the browser. The compilation settings specify a minimum supported browser version of Internet Explorer 11, however testing in this browser is not performed regularly.

_Although you may choose to transpile this library's default entry point (NodeJS) yourself, it is not advised - use the dedicated web version instead._

You can use the web version via a different entry point:

```javascript
import { createClient } from "webdav/web";
```

The browser version uses a UMD-style module definition, meaning you can simply load the library within your browser using a `<script>` tag. When using this method the library is made available on the window object as such: `window.WebDAV`. For example:

```javascript
const client = window.WebDAV.createClient(/* ... */);
```

**NB:** Streams are not available within the browser, so `createReadStream` and `createWriteStream` are just stubbed. Calling them will throw an exception.

## Installation

@@ -126,7 +144,17 @@ Create a read stream targeted at a remote file:
```javascript
client
.createReadStream("/video.mp4")
.pipe(fs.createWriteStream("~/video.np4"));
.pipe(fs.createWriteStream("~/video.mp4"));
```

If you want to stream only part of the file, you can specify the `range` in the options argument:

```javascript
client
.createReadStream(
"/video.mp4",
{ range: { start: start, end: end } }
).pipe(fs.createWriteStream("~/video.mp4"));
```

#### createWriteStream
@@ -146,6 +174,16 @@ Delete a remote file:
await client.deleteFile("/tmp.dat");
```

### exists

Check if a file or directory exists:

```javascript
if (await client.exists("/some/path") === false) {
await client.createDirectory("/some/path");
}
```

#### getDirectoryContents

Get the contents of a remote directory. Returns an array of [item stats](#item-stat).
@@ -179,6 +217,8 @@ Text files can also be fetched:
const str = await client.getFileContents("/config.json", { format: "text" });
```

Specify the `maxContentLength` option to alter the maximum number of bytes the client can receive in the request. **NodeJS only**.

#### getFileDownloadLink

Return a public link where a file can be downloaded. **This exposes authentication details in the URL**.
@@ -230,6 +270,8 @@ await client.putFileContents("/my/file.jpg", imageBuffer, { overwrite: false });
await client.putFileContents("/my/file.txt", str);
```

Specify the `maxBodyLength` option to alter the maximum number of bytes the client can send in the request. **NodeJS only**.

Handling Upload Progress (browsers only):
*This uses the axios onUploadProgress callback which uses the native XMLHttpRequest [progress event](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequestEventTarget/onprogress).*

Loading