[Clients] User Agent Management CardDAV CalDAV
--
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.
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"
PROPFIND requests have a maximum depth of 25. An infinite depth is changed to a depth of 25; inifinite depth searches are not supported.
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.
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 )
( [ ( '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/' } )
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 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
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>
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