from zope.publisher.http import HTTPRequest from zope.publisher.browser import BrowserRequest from zope.publisher.xmlrpc import XMLRPCRequest from zope.app.publication.httpfactory import HTTPPublicationRequestFactory from zope.app.publication.http import HTTPPublication from zope.app.publication.browser import BrowserPublication from zope.app.publication.xmlrpc import XMLRPCPublication _browser_methods = 'GET', 'POST', 'HEAD' # TODO make this configurable through a ZConfig file _dav_user_agents = ['cadaver/0.22.2 neon/0.24.7', 'cadaver/0.20.5 neon/0.23.9', 'neon/0.23.9 cadaver/0.20.5'] class DAVUserAgentFactory(HTTPPublicationRequestFactory): def __init__(self, db): super(DAVUserAgentFactory, self).__init__(db) self._request_cls = HTTPRequest self._publication_cls = HTTPPublication def makeRequest(self, request_cls, publication_cls, *args): # remember the kind of request and publication class for tests self._request_cls = request_cls self._publication_cls = publication_cls return request_cls(*args) def __call__(self, input_stream, output_steam, env): """See `zope.app.publication.interfaces.IPublicationRequestFactory`""" method = env.get('REQUEST_METHOD', 'GET').upper() # only make a distinction if we're dealing with browser # methods at all if method not in _browser_methods: request = self.makeRequest(HTTPRequest, HTTPPublication, input_stream, output_steam, env) request.setPublication(self._http) return request content_type = env.get('CONTENT_TYPE', '') is_xml = content_type.startswith('text/xml') if (method == 'POST' and is_xml): request= self.makeRequest(XMLRPCRequest, XMLRPCPublication, input_stream, output_steam, env) request.setPublication(self._xmlrpc) return request # check if we have a distinguished DAV client user_agent = env.get('HTTP_USER_AGENT', '') # TODO saner detection logic if user_agent in _dav_user_agents: request = self.makeRequest(HTTPRequest, HTTPPublication, input_stream, output_steam, env) request.setPublication(self._http) return request # fallback to a regular browser request request = self.makeRequest(BrowserRequest, BrowserPublication, input_stream, output_steam, env) request.setPublication(self._brower) # typo in superclass return request