And who is easy?
In the
previous post, the idea of an interface based on the
WebDAV protocol is presented. The natural requirement for its implementation is to ensure work with regular WebDAV-clients of various operating systems. Since
RFC is not a dogma, one should begin by clarifying the details of their “behavior”. Those. set and sequence of methods initiated by clients during connection, exchanging operations (transfer, receive) and remote operations (create, copy, move / rename, delete) over objects: file, folder, branch. It is useful to clarify customer support for
cookies ;
http authentication ; proxy settings for local addresses; interaction with a server port other than 80.
The review does not claim to be complete, since it is limited by the scope of the task and available software.
On hand were:
- openSUSE 13.2 KDE (
wdfs, cadaver, Konqueror, Dolphin );
- ubuntu 14.04 LTS Gnome (
davfs, Nautilus );
-
MS Windows 7 SP1 Starter ,
Windows 10 Home, Windows XP SP3 Professional (net use, Explorer).
The basics were obtained using a class 1 WebDAV server emulator (Server: noname / 0.0.7; DAV: 1; Allow: OPTIONS, GET, HEAD, PUT, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE). Server root: / test / dav /. The responses used only the properties of the namespace D = "DAV:", and in the tags <D: href> - absolute addressing. I note that according to RFCs, the emulator is "MUST", but not the fact that it corresponds. Questions arising during testing may be a consequence of this.
On the client side, operations were initiated by the context menu (copy | cut - paste), and for file systems - by console commands.
')
Generalized result:
- some clients transfer the file in two steps: first, zero-length, then the file itself;
- when copying a file remotely, most clients simulate the COPY method with a GET / PUT pair (for folders: MKCOL, GET / PUT of the file);
- not all use the MOVE method for moving objects (simulated by the MKCOL, GET / PUT, DELETE set);
- all use MOVE for renaming;
- none of the clients apply the PROPFIND method (Depth: infinity);
- not all use DELETE (Depth: infinity);
- not all the conductors check the contents of the folder (PROPFIND Depth: 1) after operations on nested objects, on the contrary, they cache data / actions;
- There are no problems with Cyrillic in localized OS.
MS Windows 7 SP1 Starter (Explorer, net use)User-Agent: Microsoft-WebDAV-MiniRedir / 6.1.7601
Supports cookies;
negotiate and digest (default), basic (after
shamanism with the registry ) authentication; IE proxy settings; non-standard http ports. Features of the exchange:
1. Connection: \\ host: port \ path or \\ host @ port \ path. When you first call the server, the client polls OPTIONS starting from the root "/" to the first segment of the path. Having received no positive response, it requests PROPFIND for the first segment. Resolved a misunderstanding by sending a client (301-Moved Permanently) to the server root address for OPTIONS, PROPFIND requests for intermediate segments.
Client requests contain
translate header
: f2. Client PROPFIND requests do not contain a body.
Windows Explorer on every click publishes a series of PROPFIND. Periodically asks for file properties: desktop.ini, folder.gif, folder.jpg, Thumbs.db. Answer 404 customers are quite satisfied. Because of his verbosity, he went to the console: COPY, XCOPY, MOVE, DEL, RMDIR, REN ...
3. File transfer is performed by a sequence of methods:
- PROPFIND (Depth: 0) destination folders;
- PROPFIND file (check for availability);
- PUT file of zero length in the absence;
- LOCK (Timeout: Second-3600) file:
<?xml version="1.0" encoding="utf-8" standalone="no"?> <D:lockinfo xmlns:D="DAV:"> <D:lockscope><D:exclusive/></D:lockscope> <D:locktype><D:write/></D:locktype> <D:owner><D:href>HOST_NAME\USER_NAME</D:href></D:owner> </D:lockinfo>
The server response is in accordance with the RFC, but the client accepts 501-Not Implemented.
- PROPPATCH file properties:
<?xml version="1.0" encoding="utf-8" standalone="no"?> <D:propertyupdate xmlns:D="DAV:" xmlns:Z="urn:schemas-microsoft-com:"> <D:set><D:prop> <Z:Win32CreationTime>Mon, 24 Jun 2013 11:16:17 GMT</Z:Win32CreationTime> <Z:Win32LastAccessTime>Tue, 23 Jun 2015 11:16:23 GMT</Z:Win32LastAccessTime> <Z:Win32LastModifiedTime>Mon, 24 Jun 2013 11:16:17 GMT</Z:Win32LastModifiedTime> <Z:Win32FileAttributes>00000000</Z:Win32FileAttributes> </D:prop></D:set> </D:propertyupdate>
The PROPPATCH method class 1 server must support. RFC allows 403-Forbidden (cannot-modify-protected-property) in the multi-status response. The client ignores the refusal and continues to bend his own.
- HEAD file;
- PUT file content;
- PROPPATCH file properties:
<?xml version="1.0" encoding="utf-8" standalone="no"?> <D:propertyupdate xmlns:D="DAV:" xmlns:Z="urn:schemas-microsoft-com:"> <D:set><D:prop> <Z:Win32LastModifiedTime>Mon, 24 Jun 2013 11:16:17 GMT</Z:Win32LastModifiedTime> <Z:Win32FileAttributes>00000020</Z:Win32FileAttributes> </D:prop></D:set> </D:propertyupdate>
- UNLOCK;
- PROPFIND file;
- PROPPATCH file attribute Win32FileAttributes = 00000020.
4. Get the file:
- PROPFIND (Depth: 0) folder-container;
- PROPFIND file;
- GET file.
5. Create a folder:
- PROPFIND (Depth: 0) destination folders;
- PROPFIND created folder;
- MKCOL;
- PROPPATCH folder properties similar to transferring a file (Win32FileAttributes value = 00000010).
6. File copying is performed in two steps:
- get the file (p.4);
- transfer the file (p.3).
7. Moving / renaming objects (including branches) is performed by the MOVE method (Overwrite: F; Destination: ....; Depth is absent, which implies Infinity).
8. Copying a branch is done by sequential creation of folders and copying (p.6) of files. Deleting a branch is done by sequential deletion of attached files and folders.
Dialogs in
Windows 10 (User-Agent: Microsoft-WebDAV-MiniRedir / 10.0.10240) are in no way different from the above.
Windows XP Redirector (
User-Agent: Microsoft-WebDAV-MiniRedir / 5.1.2600 ) DOES NOT SUPPORT cookies; ports other than 80; does not use LOCK / UNLOCK. Windows XP Explorer inserts an extra slash after the first segment of the server root in the PROPFIND requests of the file transfer / move dialog (PROPFIND
/test//dav/file.txt HTTP / 1.1).
ubuntu 14.04 LTS Gnome (Nautilus 3.10.1)User-Agent: gvfs / 1.20.3
Supports cookie, authentication, proxy settings, non-standard ports. Exchange details:
1. Connection (dav: // host: port / path):
- OPTIONS on the server root;
- PROPFIND (Depth: 0) of the server root (the set of properties is used to check the presence of the object):
<?xml version="1.0" encoding="utf-8" standalone="no"?> <D:propfind xmlns:D="DAV:"><D:prop> <D:resourcetype/> </D:prop></D:propfind>
- OPTIONS to the previous root segment, from where it was sent (301) to its destination;
- PROPFIND (
Apply-To-Redirect-Ref : T) of the server root with Depth: 0/1 headers and request properties (mostly they use):
<?xml version="1.0" encoding="utf-8" standalone="no"?> <D:propfind xmlns:D="DAV:"><D:prop> <D:creationdate/> <D:displayname/> <D:getcontentlength/> <D:getcontenttype/> <D:getetag/> <D:getlastmodified/> <D:resourcetype/> </D:prop></D:propfind>
2. Transfer the file:
- PROPFIND (Depth: 0) destination folders;
- PROPFIND disk quota of destination folder according to
rfc4331 :
<?xml version="1.0" encoding="utf-8" standalone="no"?> <D:propfind xmlns:D="DAV:"><D:prop> <D:quota-available-bytes/> <D:quota-used-bytes/> </D:prop></D:propfind>
- HEAD file for availability;
- PUT file;
- PROPFIND (Depth: 0) file
5 times (?) ;
3. Receive file:
- PROPFIND (Depth: 0) of file x5 times (?);
- GET file.
4. Create a folder:
- PROPFIND (Depth: 0) destination folders;
- PROPFIND disk quota of the destination folder;
- PROPFIND created folder;
- MKCOL created folder;
- PROPFIND created folder x5 times (?);
5. Copy file:
- PROPFIND disk quota in the destination folder;
- PROPFIND source file x5 times;
- GET file;
- HEAD file for the presence in the destination folder;
- PUT file to destination folder;
- PROPFIND copied file x5 times.
6. Rename file / folder / branch:
- MOVE (Overwrite: F; Destination: ...; Depth is missing) of the file / folder.
- PROPFIND (depth: 0) object
7. Delete the file:
- PROPFIND (Depth: 0) file;
- PROPFIND (Depth: 1) file;
- DELETE file.
8. Copying a branch is done by creating a branch structure in the destination folder and then copying (p.5) the files. Deleting a branch is done by sequential deletion of attached files and folders. Moving a file / folder / branch is made by copying (p.5 / p.8) and then deleting the source.
openSUSE 13.2 (wdfs, cadaver ), ubuntu 14.04 LTS ( davfs )Clients use the
neon /0.30.0 library, compatible with WebDAV RFC2518 from which support for cookies has been cut out in release 0.25.0. A quotation from the Feature list for the questions posed: “Modern HTTP authentication support”, RFC2617, supporting the Digest, Basic, and Negotiate protocols. ... The system's proxy configuration can be optionally used on some platforms. '
wdfsUser-Agent: wdfs / 1.4.2 neon / 0.30.0
Testing was conducted by console commands. Current folder: ~ /
1. Mounting fs (http: // host: port / path):
- OPTIONS on the server root.
2. ls on mount point:
- PROPFIND (Depth: 0/1):
<?xml version="1.0" encoding="utf-8"?> <propfind xmlns="DAV:"><prop> <resourcetype xmlns="DAV:"/> <getcontentlength xmlns="DAV:"/> <getlastmodified xmlns="DAV:"/> <creationdate xmlns="DAV:"/> </prop></propfind>
3. Transfer the file:
- PROPFIND (Depth: 0) of each folder in the destination path;
- PROPFIND file in the destination folder;
- PUT file of zero length;
- PROPFIND file;
- GET file of zero length;
- PUT file.
4. Receive file:
- PROPFIND (Depth: 0) of each file path folder;
- PROPFIND file;
- GET file.
5. Create a folder:
- PROPFIND (Depth: 0) of each folder in the destination path;
- PROPFIND created folder;
- MKCOL folders;
- PROPFIND created folder;
6. Copy file:
- PROPFIND (Depth: 0) of each folder in the destination path and the destination file for availability;
- PROPFIND (Depth: 0) of each folder in the source path and source file;
- GET source file;
- PUT file of zero length;
- PROPFIND file of zero length;
- GET file of zero length;
- PUT file.
7. Move / rename file / folder / branch:
- PROPFIND destination folders;
- PROPFIND of the source object;
- PROPFIND source object in destination folder
x2? ;
- MOVE (Overwrite: T; Destination: ...; Depth is missing) of the source object in the destination folder.
8. Deleting a folder / branch is done by one method DELETE (Depth is absent). Copying a branch is done by sequential creation of folders and copying files (GET / PUT).
davfsUser-Agent: davfs2 / 1.4.7 neon / 0.30.0
Testing was conducted by console commands. Current folder: ~ /
1. Mounting fs (http: // host: port / path):
- OPTIONS on the server root;
- PROPFIND (Depth: 1; Connection: TE; TE: trailers) root:
<?xml version="1.0" encoding="utf-8"?> <propfind xmlns="DAV:"><prop> <getetag xmlns="DAV:"/> <getcontentlength xmlns="DAV:"/> <creationdate xmlns="DAV:"/> <getlastmodified xmlns="DAV:"/> <resourcetype xmlns="DAV:"/> <executable xmlns="http://apache.org/dav/props/"/> </prop></propfind>
- PROPFIND (Depth: 0) root:
<?xml version="1.0" encoding="utf-8"?> <propfind xmlns="DAV:"><prop> <quota-available-bytes xmlns="DAV:"/> <quota-used-bytes xmlns="DAV:"/> </prop></propfind>
2. Transfer the file:
- PROPFIND (Depth: 1) of each folder in the destination path;
- PUT (If-None-Match: *) file;
- HEAD file.
3. Receive file:
- PROPFIND (Depth: 1) of each folder in the source path;
- GET (If-Modified-Since: ...) file.
4. Create a folder:
- PROPFIND (Depth: 1) of each folder in the destination path;
- MKDIR.
5. Copy file:
- PROPFIND (Depth: 1) destination folders;
- GET (If-Modified-Since: ...) of the source file;
- PUT (If-None-Match: *) file;
- HEAD file.
6. Renaming / moving objects is performed by one method MOVE.
7. Copying a folder / branch is done by sequential creation of folders and copying (receiving / transmitting) files in the general case.
8. Deleting a folder / branch is done by successive deletion of files and folders.
cadaverUser-Agent: cadaver / 0.23.3 neon / 0.30.0
Connection: http: // host: port / path
The body of the PROPFIND cadaver request contains:
<?xml version="1.0" encoding="utf-8" standalone="no"?> <propfind xmlns="DAV:"><prop> <getcontentlength/> <getlastmodified/> <executable xmlns="http://apache.org/dav/props/"/> <resourcetype/> <checked-in/> <checked-out/> </prop></propfind>
WebDAV methods are represented by the corresponding commands. The principal feature of cadaver is the ability to control user properties of objects.
openSUSE 13.2 KDE (Konqueror 4.14.8, Dolphin 15.04.0)User-Agent: Mozilla / 5.0 (X11; Linux x86_64) KHTML / 4.14.9 (like Gecko) Konqueror / 4.14 SUSE
Like any browser, Konqueror supports cookies; authentication; proxy settings for local addresses; non-standard http ports. As not everyone - WebDAV.
1. Connection: webdav: // host: port / path (localhost is available via ip). The client does not bother with OPTIONS, immediately requests PROPFIND to the server root:
<?xml version="1.0" encoding="utf-8" standalone="no"?> <D:propfind xmlns:D="DAV:"><D:prop> <D:creationdate/> <D:getcontentlength/> <D:displayname/> <D:source/> <D:getcontentlanguage/> <D:getcontenttype/> <D:getlastmodified/> <D:getetag/> <D:supportedlock/> <D:lockdiscovery/> <D:resourcetype/> </D:prop></D:propfind>
However, it is content that the server returns. And the server from the principle did not return the supportedlock and lockdiscovery properties.
2. Transfer the file:
- PROPFIND (Depth: 0) destination folders;
- PROPFIND file properties in the destination folder:
<?xml version="1.0" encoding="utf-8" standalone="no"?> <D:propfind xmlns:D="DAV:"><D:prop> <D:creationdate/> <D:getcontentlength/> <D:displayname/> <D:resourcetype/> </D:prop></D:propfind>
- PROPFIND properties (p.1) of the file in the destination folder, if it exists;
- PUT file;
- PROPFIND (Depth: 1) properties of the destination folder from P1.
3. Get the file:
- PROPFIND file in the source folder;
- GET file.
4. Create a folder:
- MKCOL;
- PROPFIND (Depth: 1) parent folder;
- PROPFIND (Depth: 0) created folder.
5. Copy file:
- PROPFIND file in the destination folder;
- COPY file to the destination folder;
- PROPFIND (Depth: 1) destination folders.
6. Move / rename file / folder / branch:
- PROPFIND (Depth: 0) destination folders;
- MOVE (Overwrite: F; Depth: infinity) file;
- PROPFIND (Depth: 1) destination folders.
7. When copying a branch / folder, a folder / branch is created in the destination folder, then files are copied using the COPY method.
8. Delete file / folder / branch:
- DELETE (Depth is missing, which implies Infinity).
Apple clients and Android file managers remained behind the scenes, I will try to fill this gap later.
December 11, 2015