diff options
Diffstat (limited to 'addons/document_webdav')
| -rw-r--r-- | addons/document_webdav/__openerp__.py | 5 | ||||
| -rw-r--r-- | addons/document_webdav/doc/well-known.rst | 29 | ||||
| -rw-r--r-- | addons/document_webdav/redirect.py | 108 | ||||
| -rw-r--r-- | addons/document_webdav/webdav_server.py | 25 |
4 files changed, 164 insertions, 3 deletions
diff --git a/addons/document_webdav/__openerp__.py b/addons/document_webdav/__openerp__.py index 6c1e24d1e96..0fd21a41a17 100644 --- a/addons/document_webdav/__openerp__.py +++ b/addons/document_webdav/__openerp__.py @@ -30,7 +30,7 @@ { "name" : "WebDAV server for Document Management", - "version" : "2.2", + "version" : "2.3", "author" : "OpenERP SA", "category" : "Generic Modules/Others", "website": "http://www.openerp.com", @@ -49,6 +49,9 @@ ; since the messages are routed to the python logging, with ; levels "debug" and "debug_rpc" respectively, you can leave ; these options on + + Also implements IETF RFC 5785 for services discovery on a http server, + which needs explicit configuration in openerp-server.conf, too. """, "depends" : ["base", "document"], "init_xml" : [], diff --git a/addons/document_webdav/doc/well-known.rst b/addons/document_webdav/doc/well-known.rst new file mode 100644 index 00000000000..ce7dbd7c9cf --- /dev/null +++ b/addons/document_webdav/doc/well-known.rst @@ -0,0 +1,29 @@ +================= +Well-known URIs +================= + +In accordance to IETF RFC 5785 [1], we shall publish a few locations +on the root of our http server, so that clients can discover our +services (CalDAV, eg.). + +This module merely installs a special http request handler, that will +redirect the URIs from "http://our-server:port/.well-known/xxx' to +the correct path for each xxx service. + +Note that well-known URIs cannot have a database-specific behaviour, +they are server-wide. So, we have to explicitly chose one of our databases +to serve at them. By default, the database of the configuration file +is chosen + +Example config: + +[http-well-known] +num_services = 2 +db_name = openerp-main ; must define that for path_1 below +service_1 = caldav +path_1 = /webdav/%(db_name)s/Calendars/ +service_2 = foo +path_2 = /other_db/static/Foo.html + + +[1] http://www.rfc-editor.org/rfc/rfc5785.txt
\ No newline at end of file diff --git a/addons/document_webdav/redirect.py b/addons/document_webdav/redirect.py new file mode 100644 index 00000000000..71af3271ab7 --- /dev/null +++ b/addons/document_webdav/redirect.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2010 OpenERP s.a. (<http://openerp.com>). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################## + + +import logging +import urlparse +from service.websrv_lib import FixSendError, HTTPHandler, HttpOptions +from service.http_server import HttpLogHandler + +class RedirectHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler): + _logger = logging.getLogger('httpd.well-known') + _HTTP_OPTIONS = { 'Allow': ['OPTIONS', 'GET', 'HEAD', 'PROPFIND'] } + redirect_paths = {} + + def __init__(self,request, client_address, server): + HTTPHandler.__init__(self,request,client_address,server) + + def send_head(self): + """Common code for GET and HEAD commands. + + It will either send the correct redirect (Location) response + or a 404. + """ + + if self.path.endswith('/'): + self.path = self.path[:-1] + + if not self.path: + # Return an empty page + self.send_response(200) + self.send_header("Content-Length", 0) + self.end_headers() + return None + + redir_path = self._find_redirect() + if redir_path is False: + self.send_error(404, "File not found") + return None + elif redir_path is None: + return None + + server_proto = getattr(self.server, 'proto', 'http').lower() + addr, port = self.server.server_name, self.server.server_port + try: + addr, port = self.request.getsockname() + except Exception, e: + self.log_error("Cannot calculate own address:" , e) + + if self.headers.has_key('Host'): + uparts = list(urlparse.urlparse("%s://%s:%d"% (server_proto, addr,port))) + uparts[1] = self.headers['Host'] + baseuri = urlparse.urlunparse(uparts) + else: + baseuri = "%s://%s:%d"% (server_proto, addr, port ) + + + location = baseuri + redir_path + # relative uri: location = self.redirect_paths[self.path] + + self.send_response(301) + self.send_header("Location", location) + self.send_header("Content-Length", 0) + self.end_headers() + # Do we need a Cache-content: header here? + self._logger.debug("redirecting %s to %s", self.path, redir_path) + return None + + def do_PROPFIND(self): + self._get_ignore_body() + return self.do_HEAD() + + def _find_redirect(self): + """ Locate self.path among the redirects we can handle + @return The new path, False for 404 or None for already sent error + """ + return self.redirect_paths.get(self.path, False) + + def _get_ignore_body(self): + if not self.headers.has_key("content-length"): + return + max_chunk_size = 10*1024*1024 + size_remaining = int(self.headers["content-length"]) + got = '' + while size_remaining: + chunk_size = min(size_remaining, max_chunk_size) + got = self.rfile.read(chunk_size) + size_remaining -= len(got) + +#eof + diff --git a/addons/document_webdav/webdav_server.py b/addons/document_webdav/webdav_server.py index 5810978a6d5..f2a230858bf 100644 --- a/addons/document_webdav/webdav_server.py +++ b/addons/document_webdav/webdav_server.py @@ -1,5 +1,5 @@ # -*- encoding: utf-8 -*- - +############################################################################9 # # Copyright P. Christeas <p_christ@hol.gr> 2008,2009 # Copyright OpenERP SA, 2010 (http://www.openerp.com ) @@ -14,7 +14,7 @@ # # This program is Free Software; you can redistribute it and/or # modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 +# as published by the Free Software Foundation; either version 3 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, @@ -43,6 +43,7 @@ import addons from DAV.errors import DAV_Error, DAV_Forbidden, DAV_NotFound from DAV.propfind import PROPFIND # from DAV.constants import DAV_VERSION_1, DAV_VERSION_2 +from redirect import RedirectHTTPHandler khtml_re = re.compile(r' KHTML/([0-9\.]+) ') @@ -453,6 +454,26 @@ except Exception, e: logger = netsvc.Logger() logger.notifyChannel('webdav', netsvc.LOG_ERROR, 'Cannot launch webdav: %s' % e) + +def init_well_known(): + reps = RedirectHTTPHandler.redirect_paths + + num_svcs = config.get_misc('http-well-known', 'num_services', '0') + + for nsv in range(1, int(num_svcs)+1): + uri = config.get_misc('http-well-known', 'service_%d' % nsv, False) + path = config.get_misc('http-well-known', 'path_%d' % nsv, False) + if not (uri and path): + continue + reps['/'+uri] = path + + if int(num_svcs): + if http_server.reg_http_service(HTTPDir('/.well-known', RedirectHTTPHandler)): + logging.getLogger("web-services").info("Registered HTTP redirect handler at /.well-known" ) + + +init_well_known() + #eof |
