clone from: https://github.com/miquels/webdav-handler-rs
This commit is contained in:
46
doc/APPLE-Finder-hints.md
Normal file
46
doc/APPLE-Finder-hints.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# APPLE-FINDER-HINTS
|
||||
|
||||
The Apple Finder (and other subsystems) seem to probe for a few
|
||||
files at the root of the filesystems to get a hint about the
|
||||
behaviour they should show processing this filesystem.
|
||||
|
||||
It also looks for files with extra localization information in
|
||||
every directory, and for resource fork data (the `._` files).
|
||||
|
||||
## FILES
|
||||
|
||||
- `.metadata_never_index`
|
||||
prevents the system from indexing all of the data
|
||||
- `.ql_disablethumbnails`
|
||||
prevent the system from downloading all files that look like an
|
||||
image or a video to create a thumbnail
|
||||
- `.ql_disablecache`
|
||||
not really sure but it sounds useful
|
||||
|
||||
The `.ql_` files are configuration for the "QuickLook" functionality
|
||||
of the Finder.
|
||||
|
||||
The `.metadata_never_index` file appears to be a hint for the
|
||||
Spotlight indexing system.
|
||||
|
||||
Additionally, the Finder probes for a `.localized` file in every
|
||||
directory it encounters, and it does a PROPSTAT for every file
|
||||
in the directory prefixed with `._`.
|
||||
|
||||
## OPTIMIZATIONS
|
||||
|
||||
For a macOS client we return the metadata for a zero-sized file if it
|
||||
does a PROPSTAT of `/.metadata_never_index` or `/.ql_disablethumbnails`.
|
||||
|
||||
We always return a 404 Not Found for a PROPSTAT of any `.localized` file.
|
||||
|
||||
Furthermore, we disallow moving, removing etc of those files. The files
|
||||
do not show up in a PROPSTAT of the rootdirectory.
|
||||
|
||||
If a PROPFIND with `Depth: 1` is done on a directory, we add the
|
||||
directory pathname to an LRU cache, and the pathname of each file of
|
||||
which the name starts with `._`. Since we then know which `._` files
|
||||
exist, it is easy to return a fast 404 for PROPSTAT request for `._`
|
||||
files that do not exist. The cache is kept consistent by checking
|
||||
the timestamp on the parent directory, and a timeout.
|
||||
|
||||
57
doc/APPLE-doubleinfo.md
Normal file
57
doc/APPLE-doubleinfo.md
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
# APPLEDOUBLEINFO
|
||||
|
||||
Normally, after asking for a directory listing (using PROPFIND with Depth: 1)
|
||||
the macOS Finder will send a PROPFIND request for every file in the
|
||||
directory, prefixed with ".\_". Even though it just got a complete directory
|
||||
listing which doesn't list those files.
|
||||
|
||||
An optimization the Apple iDisk service makes, is that it sometimes
|
||||
synthesizes those info files ahead of time. It then lists those synthesized
|
||||
files in the PROPFIND response together with the <appledoubleheader> propery,
|
||||
which is the contents of the ".\_file" (if it would be present) in base64.
|
||||
It appears to only do this when the appledoubleinfo data is completely
|
||||
basic and is 82 bytes of size.
|
||||
|
||||
This prevents the webdav clients from launching an additional PROPFIND
|
||||
request for every file prefixed with ".\_".
|
||||
|
||||
Note that you cannot add an <appledoubleheader> propery to a PROPSTAT
|
||||
element of a "file" itself, that's ignored, alas. macOS only accepts
|
||||
it on ".\_" files.
|
||||
|
||||
There is not much information about this, but an Apple engineer mentioned it in
|
||||
https://lists.apple.com/archives/filesystem-dev/2009/Feb/msg00013.html
|
||||
|
||||
There is a default "empty"-like response for a file that I found at
|
||||
https://github.com/DanRohde/webdavcgi/blob/master/lib/perl/WebDAV/Properties.pm
|
||||
|
||||
So, what we _could_ do (but don't, yet) to optimize the macOS webdav client,
|
||||
when we reply to PROPFIND:
|
||||
|
||||
- for each file that does NOT have a ".\_file" present
|
||||
- we synthesize a virtual response
|
||||
- for a virtual file with name ".\_file
|
||||
- with size: 82 bytes
|
||||
- that contains:
|
||||
<DAV:prop xmlns:S="http://www.apple.com/webdav\_fs/props/">
|
||||
<S:appledoubleheader>
|
||||
AAUWBwACAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAACAAAAJgAAACwAAAAJAAAAMgAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
|
||||
</S:appledoubleheader>
|
||||
|
||||
The contents of this base64 string are explained at
|
||||
https://github.com/DanRohde/webdavcgi/blob/master/lib/perl/WebDAV/Properties.pm
|
||||
|
||||
... and they are:
|
||||
|
||||
```
|
||||
appledoubleheader: Magic(4) Version(4) Filler(16) EntryCout(2)
|
||||
EntryDescriptor(id:4(2:resource fork),offset:4,length:4)
|
||||
EntryDescriptor(id:9 finder)... Finder Info(16+16)
|
||||
|
||||
namespace: http://www.apple.com/webdav\_fs/props/
|
||||
content: MIME::Base64(pack('H\*', '00051607'. '00020000' . ( '00' x 16 ) .
|
||||
'0002'. '00000002'. '00000026' . '0000002C'.'00000009'. '00000032' . '00000020' .
|
||||
('00' x 32) ))
|
||||
```
|
||||
|
||||
85
doc/Apache-PUT-with-Content-Range.md
Normal file
85
doc/Apache-PUT-with-Content-Range.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# HTTP PUT-with-Content-Range support.
|
||||
|
||||
The [mod_dav](https://httpd.apache.org/docs/2.4/mod/mod_dav.html) module of
|
||||
the [Apache web server](https://httpd.apache.org/) was one of the first
|
||||
implementations of [Webdav](https://tools.ietf.org/html/rfc4918). Ever since
|
||||
the first released version, it has had support for partial uploads using
|
||||
the Content-Range header with PUT requests.
|
||||
|
||||
## A sample request
|
||||
|
||||
```text
|
||||
PUT /file.txt
|
||||
Content-Length: 4
|
||||
Content-Range: bytes 3-6/*
|
||||
|
||||
ABCD
|
||||
```
|
||||
|
||||
This request updates 'file.txt', specifically the bytes 3-6 (inclusive) to
|
||||
`ABCD`.
|
||||
|
||||
There is no explicit support for appending to a file, that is simply done
|
||||
by writing just past the end of a file. For example, if a file has size
|
||||
1000, and you want to append 4 bytes:
|
||||
|
||||
```text
|
||||
PUT /file.txt
|
||||
Content-Length: 4
|
||||
Content-Range: bytes 1000-1003/*
|
||||
|
||||
1234
|
||||
```
|
||||
|
||||
## Apache `mod_dav` behaviour:
|
||||
|
||||
- The `Content-Range` header is required, and the syntax is `bytes START-END/LENGTH`.
|
||||
- END must be bigger than or equal to START.
|
||||
- LENGTH is parsed by Apache mod_dav, and it must either be a valid number
|
||||
or a `*` (star), but mod_dav otherwise ignores it. Since it is not clearly
|
||||
defined what LENGTH should be, always use `*`.
|
||||
- Neither the start, nor the end-byte have to be within the file's current size.
|
||||
- If the start-byte is beyond the file's current length, the space in between
|
||||
will be filled with NULL bytes (`0x00`).
|
||||
|
||||
## Notes
|
||||
|
||||
- `bytes<space>`, _not_ `bytes=`.
|
||||
- The `Content-Length` header is not required by the original Apache mod_dav
|
||||
implementation. The body must either have a valid Content-Length, or it must
|
||||
use the `Chunked` transfer encoding. It is *strongly encouraged* though to
|
||||
include Content-Length, so that it can be validated against the range before
|
||||
accepting the PUT request.
|
||||
- If the `Content-Length` header is present, its value must be equal
|
||||
to `END - START + 1`.
|
||||
|
||||
## Status codes
|
||||
|
||||
### The following status codes are used:
|
||||
|
||||
Status code | Reason
|
||||
----------- | ------
|
||||
200 or 204 | When the operation was successful
|
||||
400 | Invalid `Content-Range` header
|
||||
416 | If there was something wrong with the bytes, such as a `Content-Length` not matching with what was sent as the start and end bytes, or an end byte being lower than the start byte.
|
||||
501 | Content-Range header present, but not supported.
|
||||
|
||||
## RECKOGNIZING PUT-with-Content-Range support (client).
|
||||
|
||||
There is no official way to know if PUT-with-content-range is supported by
|
||||
a webserver. For a client it's probably best to do an OPTIONS request,
|
||||
and then check two things:
|
||||
|
||||
- the `Server` header must contain the word `Apache`
|
||||
- the `DAV` header must contain `<http://apache.org/dav/propset/fs/1>`.
|
||||
|
||||
In that case, your are sure to talk to an Apache webserver with mod_dav enabled.
|
||||
|
||||
## IMPLEMENTING PUT-with-Content-Range support (server).
|
||||
|
||||
Don't. Implement [sabredav-partialupdate](SABREDAV-partialupdate.md).
|
||||
|
||||
## MORE INFORMATION.
|
||||
|
||||
https://blog.sphere.chronosempire.org.uk/2012/11/21/webdav-and-the-http-patch-nightmare
|
||||
|
||||
108
doc/SABREDAV-partialupdate.md
Normal file
108
doc/SABREDAV-partialupdate.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# HTTP PATCH support
|
||||
|
||||
This is a markdown translation of the document at
|
||||
[http://sabre.io/dav/http-patch/](http://sabre.io/dav/http-patch/)
|
||||
[© 2018 fruux GmbH](https://fruux.com/)
|
||||
|
||||
The `Sabre\\DAV\\PartialUpdate\\Plugin` from the Sabre DAV library provides
|
||||
support for the HTTP PATCH method [RFC5789](http://tools.ietf.org/html/rfc5789).
|
||||
This allows you to update just a portion of a file, or append to a file.
|
||||
|
||||
This document can be used as a spec for other implementors. There is some
|
||||
DAV-specific stuff in this document, but only in relation to the OPTIONS
|
||||
request.
|
||||
|
||||
## A sample request
|
||||
|
||||
```
|
||||
PATCH /file.txt
|
||||
Content-Length: 4
|
||||
Content-Type: application/x-sabredav-partialupdate
|
||||
X-Update-Range: bytes=3-6
|
||||
|
||||
ABCD
|
||||
```
|
||||
|
||||
This request updates 'file.txt', specifically the bytes 3-6 (inclusive) to
|
||||
`ABCD`.
|
||||
|
||||
If you just want to append to an existing file, use the following syntax:
|
||||
|
||||
```
|
||||
PATCH /file.txt
|
||||
Content-Length: 4
|
||||
Content-Type: application/x-sabredav-partialupdate
|
||||
X-Update-Range: append
|
||||
|
||||
1234
|
||||
```
|
||||
|
||||
The last request adds 4 bytes to the bottom of the file.
|
||||
|
||||
## The rules
|
||||
|
||||
- The `Content-Length` header is required.
|
||||
- `X-Update-Range` is also required.
|
||||
- The `bytes` value is the exact same as the HTTP Range header. The two numbers
|
||||
are inclusive (so `3-6` means that bytes 3,4,5 and 6 will be updated).
|
||||
- Just like the HTTP Range header, the specified bytes is a 0-based index.
|
||||
- The `application/x-sabredav-partialupdate` must also be specified.
|
||||
- The end-byte is optional.
|
||||
- The start-byte cannot be omitted.
|
||||
- If the start byte is negative, it's calculated from the end of the file. So
|
||||
`-1` will update the last byte in the file.
|
||||
- Use `X-Update-Range: append` to add to the end of the file.
|
||||
- Neither the start, nor the end-byte have to be within the file's current size.
|
||||
- If the start-byte is beyond the file's current length, the space in between
|
||||
will be filled with NULL bytes (`0x00`).
|
||||
- The specification currently does not support multiple ranges.
|
||||
- If both start and end offsets are given, than both must be non-negative, and
|
||||
the end offset must be greater or equal to the start offset.
|
||||
|
||||
## More examples
|
||||
|
||||
The following table illustrates most types of requests and what the end-result
|
||||
of them will be.
|
||||
|
||||
It is assumed that the input file contains `1234567890`, and the request body
|
||||
always contains 4 dashes (`----`).
|
||||
|
||||
X-Update-Range header | Result
|
||||
--------------------- | -------
|
||||
`bytes=0-3` | `----567890`
|
||||
`bytes=1-4` | `1----67890`
|
||||
`bytes=0-` | `----567890`
|
||||
`bytes=-4` | `123456----`
|
||||
`bytes=-2` | `12345678----`
|
||||
`bytes=2-` | `12----7890`
|
||||
`bytes=12-` | `1234567890..----`
|
||||
`append` | `1234567890----`
|
||||
|
||||
Please note that in the `bytes=12-` example, we used dots (`.`) to represent
|
||||
what are actually `NULL` bytes (so `0x00`). The null byte is not printable.
|
||||
|
||||
## Status codes
|
||||
|
||||
### The following status codes should be used:
|
||||
|
||||
Status code | Reason
|
||||
----------- | ------
|
||||
200 or 204 | When the operation was successful
|
||||
400 | Invalid `X-Update-Range` header
|
||||
411 | `Content-Length` header was not provided
|
||||
415 | Unrecognized content-type, should be `application/x-sabredav-partialupdate`
|
||||
416 | If there was something wrong with the bytes, such as a `Content-Length` not matching with what was sent as the start and end bytes, or an end byte being lower than the start byte.
|
||||
|
||||
## OPTIONS
|
||||
|
||||
If you want to be compliant with SabreDAV's implementation of PATCH, you must
|
||||
also return 'sabredav-partialupdate' in the 'DAV:' header:
|
||||
|
||||
```
|
||||
HTTP/1.1 204 No Content
|
||||
DAV: 1, 2, 3, sabredav-partialupdate, extended-mkcol
|
||||
```
|
||||
|
||||
This is only required if you are adding this feature to a DAV server. For
|
||||
non-webdav implementations such as REST services this is optional.
|
||||
|
||||
Reference in New Issue
Block a user