Menu

UserAgents

Adam Tauno Williams

[Clients] WebDAV Implementation Notes

User Agents

Most of the time different clients can be automatically recognized by some type of User-Agent string in their requests.

When a request is received the user's agent (application) is matched to a user agent description (defined in coils.core.useragents) using the lookup_user_agent method.

from coils.core.useragents import lookup_user_agent
spec = lookup_user_agent('CardDAV-Sync (Android) (like iOS/5.0.1 (9A405) dataaccessd/1.0) gzip')

Each specification is a dictionary that describes the capacities, and most importantly the known bugs, of a specific client. Specifications all start with the default client description and then that description is then patched with the description of the specific client - this eliminates a lot of duplicate and boiler-plate content from the user agent descriptions.

Descriptions

The default description

'148c9d0d669648ed8b8ed0292df478fd':
   { 'name':      'default',
     'patterns':   [],
     'webdav':     { 'filenameAsDisplayName': False,  # Use the filename as the display name, for clients that confuse the two
                     'showProjectContactsFolder': True, # Enable/Disable showing the Contacts folder in a Project folder
                     'showProjectEnterprisesFolder': True, # Enable/Disable showing the Enterprise folder in a Project folder
                     'showProjectTasksFolder': True, # Enable/Disable showing the Tasks folder in a Project folder
                     'showProjectProjectsFolder': True, # Enable/Disable showing the Projects (sub-projects) folder in a Project folder
                     'showProjectDocumentsFolder': True, # Enable/Disable showing the Documents folder in a Project folder
                     'showProjectNotesFolder': True, # Enable/Disable showing the Notes folder in a Project folder
                     'showProjectVersionsFolder': False, # Enable/Disable showing the Versions folder in a Project folder
                     'folderContentType': 'unix/httpd-directory', # Mime-type for a collection/folder
                     'escapeGETs':         False,
                     'supports301':        True, # Does the client respond correctly to 301 responses
                     'supportsLocation':   True, # Does the client respond correct to Location: headers
                     'supportsMEMOs':      False, # Does the client properly handle Memo (VJOURNAL) objects
                     'absoluteHrefs':      False, # Does the client require HREF values to be absolute
                     'portInAbsoluteHref': False, # Does the client recognize port numbers in absolute HREFs
                     'hideLockRoot':       False,
                     'principalURL':       None,
                     'defaultPropeties':
                         [ ( u'name',             u'DAV:',                           u'webdav', 'D:name' ),
                           ( u'href',             u'DAV:',                           u'webdav', 'D:href' ),
                           ( u'getcontenttype',   u'DAV:',                           u'webdav', 'D:getcontenttype' ),
                           ( u'contentclass',     u'DAV:',                           u'webdav', 'D:contentclass' ),
                           ( u'getlastmodified',  u'DAV:',                           u'webdav', 'D:getlastmodified' ),
                           ( u'getcontentlength', u'DAV:',                           u'webdav', 'D:getcontentlength' ),
                           ( u'iscollection',     u'DAV:',                           u'webdav', 'D:iscollection' ),
                           ( u'displayname',      u'DAV:',                           u'webdav', 'D:displayname' ),
                           ( u'getctag',          u'urn:ietf:params:xml:ns:caldav', u'caldav', 'C:getctag' ),
                           ( u'resourcetype',     u'DAV:',                           u'webdav', 'D:resourcetype' ) ],
                    'defaultNamespaces': { 'C': 'urn:ietf:params:xml:ns:caldav',
                                           'D': 'DAV:',
                                           'G': 'http://groupdav.org/' } },
     'jsonrpc':    { },
     'xmlrpc':     { 'allowNone': False, },
     'vcard':       { 'setVoiceAttrInTel': True,
                      'setCoilsTypeInTel': True,
                      'telTypeMap': { '10_fax':         { 'types': ['fax','work'],    'voice': False  },
                                      '01_tel':         { 'types': ['work', 'pref' ], 'voice': True   },
                                      '03_tel_funk':    { 'types': ['cell'],          'voice': True   },
                                      '05_tel_private': { 'types': ['home'],          'voice': True,  },
                                      '30_pager':       { 'types': [ 'pager' ],       'voice': False  } },
                      'setCoilsTypeInAdr': True, # Encode the OGo address type in VCARD ADR properties
                      'adrTypeMap': { 'private':        { 'types': [ 'home' ] },
                                      'mailing':        { 'types': [ 'work', 'pref' ] },
                                      'bill':           { 'types': [ 'work', 'pref' ] },
                                      'shipto':         { 'types': [ 'work' ] } },
                      'includeObjectPropertes': False, # Encode the OGo object properties in VCARDs
                      'includeCoilsXAttributes': False, # Encode the OGo company values in VCARDs
                      'includeCompanyValues': False, # Encode the OGo company values in VCARDs
                    }, 
     'icalendar':  { 'includeAttachments': False,  # includeAttachments: False, inline, link
                   }, 
     'omphalos':   { 'associativeLists': False, # Use associate lists in Omphalos responses
                   }
   },

The current user agent description is always available via the [Context] object's user_agent_description property.

self.context.user_agent_description['webdav']['escapeGETs']

WebDAV Section

  • defaultPropeties : Specifies the properties to include in the response when the client sends an empty (aka default) PROPFIND request

JSON-RPC Section

XML-RPC Section

  • allowNone : Set to True if the client understands XML-RPC NULL values. By default this is disabled. NULL support is not part of the XML-RPC specification. But there is a common extension that adds NULL support to XML-RPC, this is referred to as the "nil extension"

VCard Section

  • telTypeMap :
  • setCoilsTypeInAdr :
  • adrTypeMap :

iCalendar Section

  • includeAttachments

Omphalos Section

  • associativeLists

Related

Wiki: Clients
Wiki: Context
Wiki: WebDAV

MongoDB Logo MongoDB