Menu

WebDAV

Adam Tauno Williams

[Clients] User Agent Management CardDAV CalDAV

--

WebDAV

The base class for WebDAV presentation is coils.net.foundation.DAV. From this class is derived DAVObject and DAVFolder.

See Standards & Specifications for a list of reference documents.

Name Spaces

WebDAV makes extensive use of XML; in LOCK, PROPFIND, and REPORT operations This makes name space management very important. Internally OpenGroupware Coils maps knows namespaces to namespace labels. These labels are used when the property in a request is mapped to an object method to get the value (as namespaces contain many characters that are illegal in method names, and some namespaces are functionally equivalent - such as the two namespaces that CalDAV properties can use).

Namespace Label
http://www.w3.org/1999/xhtml xhtml
dav webdav
http://apache.org/dav/props/ webdav
urn:schemas-microsoft-com:office:office msoffice
urn:schemas-microsoft-com:office:word msword
http://schemas.microsoft.com/hotmail/ hotmail
urn:schemas-microsoft-com mswebdav
urn:schemas:httpmail: mshttpmail
http://schemas.microsoft.com/exchange/ msexchange
urn:schemas:calendar: mscalendar
urn:schemas:contacts: mscontacts
http://webdav.org/cadaver/custom-properties/ cadaver
http://services.eazel.com/namespaces eazel # Nautilus?
http://www.w3.org/2005/Atom atom
http://groupdav.org/ groupdav
http://calendarserver.org/ns/ caldav
urn:ietf:params:xml:ns:caldav caldav
urn:ietf:params:xml:ns:carddav carddav
57c7fc84-3cea-417d-af54-b659eb87a046 coils
http://ucb.openoffice.org/dav/props/ openoffice

Name spaces are defined in "coils/net/foundation/reports/namespaces.py"

Properties

PROPFIND

PROPFIND requests have a maximum depth of 25. An infinite depth is changed to a depth of 25; inifinite depth searches are not supported.

  • Infinite depth PROPFINDs are stupid and should never have existed in the WebDAV specification. Designers... really? What were you thinking?
    • Fortunately the vast majority of clients are sane - they don't want infinite (or just massive) results either and they only issue Depth 0 and 1 requests.
    • In spite of the spec saying there are three depths: 0, 1, and infinite; Coils is happy with any depth between 0 and 25 (inclusive). But if you do that with your client it will probably break for any server other than Coils. So just use 0 or 1.

A PROPFIND's payload is parsed using the coils.net.foundation.reports.Parser (static) propfind method.

Parser.propfind(payload, user_agent_description=self.context.user_agent_description)

If the PROPFIND request has a zero-length payload (is empty) then a default set of properties is returned; this is handled by the Parser classes (static) method default_properties. The default properties depend on the client's user agent so the response can be customized - this is handled in the user agent definitions. If the PROPFIND has a payload is is parsed using minidom's parseString method and the actual XML is scanned for properties by the Parser's (static) properties method. This result is returned to the DAV object's PROPFIND method. The properties response is a tuple of properties and namespaces.

Parsing a PROPFIND Request

from pprint import pprint
from coils.core.useragents import lookup_user_agent
from coils.net.foundation.reports import Parser

request = '''<?xml version="1.0" encoding="utf-8" ?>
<A:propfind xmlns:A="DAV:" xmlns:B="urn:ietf:params:xml:ns:carddav">
    <A:prop>
        <A:displayname/>
        <A:resourcetype/>
        <B:addressbook-home-set/>
    </A:prop>
</A:propfind>'''

ua_string = 'CardDAV-Sync (Android) (like iOS/5.0.1 (9A405) dataaccessd/1.0) gzip'
ui, ua = lookup_user_agent( ua_string )
pf = Parser.propfind( request, user_agent_description=ua )
pprint( pf )

Parse Response

( [ ( 'get_property_webdav_displayname',
     u'DAV:',
     u'displayname',
     u'webdav',
     'D:displayname'),
   (  'get_property_webdav_resourcetype',
     u'DAV:',
     u'resourcetype',
     u'webdav',
      'D:resourcetype'),
   ( 'get_property_carddav_addressbook_home_set',
     u'urn:ietf:params:xml:ns:carddav',
     u'addressbook-home-set',
     u'carddav',
    'E:addressbook-home-set' ) ],
  { 'A': 'http://apache.org/dav/props/',
    'B': 'http://icewarp.com/ns/',
    'C': 'urn:ietf:params:xml:ns:caldav',
    'D': 'DAV:',
    'E': 'urn:ietf:params:xml:ns:cardav',
    'G': 'http://groupdav.org/' } )

PROPATCH

Property patching is how a WebDAV client modifies the meta-data of an object.

A Typical PROPATCH Request

PROPPATCH /dav/Projects/test123/Documents/ComericaPositivePayIn.yaml HTTP/1.0
Host: coils.wmmi.net
Connection: close
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/xml; charset="utf-8"
User-Agent: Microsoft-WebDAV-MiniRedir/6.1.7601
If: (<opaquelocktoken:08e7b8a645c7423eb4ddccd0fec80fc2>)
translate: f
Content-Length: 388
Authorization: Basic YXdpbGxpYW06

<?xml version="1.0" encoding="utf-8" ?>
<D:propertyupdate xmlns:D="DAV:" xmlns:Z="urn:schemas-microsoft-com:">
    <D:set>
        <D:prop>
            <Z:Win32CreationTime>Mon, 26 Nov 2012 22:48:16 GMT</Z:Win32CreationTime>
            <Z:Win32LastAccessTime>Tue, 27 Nov 2012 10:46:41 GMT</Z:Win32LastAccessTime>
            <Z:Win32LastModifiedTime>Tue, 27 Nov 2012 10:46:41 GMT</Z:Win32LastModifiedTime>
        </D:prop>
    </D:set>
</D:propertyupdate>

Response

HTTP/1.0 207 Multistatus
Server: BaseHTTP/0.3 Python/2.7.3
Date: Tue, 27 Nov 2012 10:46:38 GMT
Content-Length: 684
Content-Type: text/xml; charset=UTF-8

<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:J="urn:schemas-microsoft-com:" xmlns:G="http://groupdav.org/" xmlns:E="urn:ietf:params:xml:ns:carddav" xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:A="http://apache.org/dav/props/">
  <D:response>
    <D:propstat>
      <D:prop><J:Win32CreationTime/></D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
    <D:propstat>
      <D:prop><J:Win32LastAccessTime/></D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
    <D:propstat>
      <D:prop><J:Win32LastModifiedTime/></D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>

LOCKING

Locking and unlocking of objects is managed using the [LockManager]. The WebDAV layer maps WebDAV LOCK and UNLOCK requests to lock and unlock requests to the [LockManager].

The lock identifier is a "token" string which is operationally the same as using a GUID except that it always begins with the string "opaquelocktoken:" - this is per the WebDAV specification.

See Faking LOCK & UNLOCK Requests

  • [#24] - Implement LOCK / UNLOCK on documents

LOCK Operations

A Typical Lock Request

LOCK /dav/Projects/test123/Documents/ComericaPositivePayIn.yaml HTTP/1.0
Host: coils.wmmi.net
Connection: close
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/xml; charset="utf-8"
User-Agent: Microsoft-WebDAV-MiniRedir/6.1.7601
translate: f
Timeout: Second-3600
Content-Length: 199
Authorization: Basic YXdpbGxpYW06

<?xml version="1.0" encoding="utf-8" ?>
<D:lockinfo xmlns:D="DAV:">
    <D:lockscope><D:exclusive/></D:lockscope>
    <D:locktype><D:write/></D:locktype>
    <D:owner><D:href>awilliam</D:href></D:owner>
</D:lockinfo>

Response

HTTP/1.0 200 OK
Server: BaseHTTP/0.3 Python/2.7.3
Date: Tue, 27 Nov 2012 10:46:37 GMT
Content-Length: 516
Content-Type: text/xml; charset=UTF-8
Lock-Token: opaquelocktoken:opaquelocktoken:08e7b8a645c7423eb4ddccd0fec80fc2

<?xml version="1.0" encoding="utf-8"?>
<D:prop xmlns:D="DAV">
  <D:lockdiscovery>
    <D:activelock>
      <D:locktype>
        <D:write/>
      </D:locktype>
      <D:lockscope>
        <D:exclusive/>
      </D:lockscope>
      <D:depth>0</D:depth>
      <D:owner xmlns:D="DAV:"><D:href>awilliam</D:href></D:owner>
      <D:timeout>Second-3600</D:timeout>
      <D:locktoken>
        <D:href>opaquelocktoken:08e7b8a645c7423eb4ddccd0fec80fc2</D:href>
      </D:locktoken>
    </D:activelock>
  </D:lockdiscovery>
</D:prop>

UNLOCK Operations


Related

Tickets: #24
Wiki: AndroidCardDAVSync
Wiki: CalDAV
Wiki: CardDAV
Wiki: Clients
Wiki: CyberDuck
Wiki: DAVProperties
Wiki: Development
Wiki: EMClient
Wiki: FakeLockRequests
Wiki: FakePROPFINDRequests
Wiki: GNOMEEvolution
Wiki: MSRedirector
Wiki: RoadMap
Wiki: Standards
Wiki: Tornado
Wiki: UserAgents

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.