1
# -*- coding: utf-8 -*-
3
# Copyright P. Christeas <p_christ@hol.gr> 2008-2010
4
# Copyright 2010 OpenERP SA. (http://www.openerp.com)
7
# WARNING: This program as such is intended to be used by professional
8
# programmers who take the whole responsibility of assessing all potential
9
# consequences resulting from its eventual inadequacies and bugs
10
# End users who are looking for a ready-to-use solution with commercial
11
# guarantees and support are strongly advised to contract a Free Software
14
# This program is Free Software; you can redistribute it and/or
15
# modify it under the terms of the GNU General Public License
16
# as published by the Free Software Foundation; either version 2
17
# of the License, or (at your option) any later version.
19
# This program is distributed in the hope that it will be useful,
20
# but WITHOUT ANY WARRANTY; without even the implied warranty of
21
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
# GNU General Public License for more details.
24
# You should have received a copy of the GNU General Public License
25
# along with this program; if not, write to the Free Software
26
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27
###############################################################################
30
""" This module offers the family of HTTP-based servers. These are not a single
31
class/functionality, but a set of network stack layers, implementing
32
extendable HTTP protocols.
34
The OpenERP server defines a single instance of a HTTP server, listening at
35
the standard 8069, 8071 ports (well, it is 2 servers, and ports are
36
configurable, of course). This "single" server then uses a `MultiHTTPHandler`
37
to dispatch requests to the appropriate channel protocol, like the XML-RPC,
38
static HTTP, DAV or other.
47
from websrv_lib import *
48
import openerp.tools as tools
56
from ssl import SSLError
58
class SSLError(Exception): pass
60
_logger = logging.getLogger(__name__)
62
# TODO delete this for 6.2, it is still needed for 6.1.
64
""" helper class for uniform log handling
65
Please define self._logger at each class that is derived from this
69
def log_message(self, format, *args):
70
self._logger.debug(format % args) # todo: perhaps other level
72
def log_error(self, format, *args):
73
self._logger.error(format % args)
75
def log_exception(self, format, *args):
76
self._logger.exception(format, *args)
78
def log_request(self, code='-', size='-'):
79
self._logger.debug('"%s" %s %s',
80
self.requestline, str(code), str(size))
82
class StaticHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler):
83
_logger = logging.getLogger(__name__)
85
_HTTP_OPTIONS = { 'Allow': ['OPTIONS', 'GET', 'HEAD'] }
87
def __init__(self,request, client_address, server):
88
HTTPHandler.__init__(self,request,client_address,server)
89
document_root = tools.config.get('static_http_document_root', False)
90
assert document_root, "Please specify static_http_document_root in configuration, or disable static-httpd!"
91
self.__basepath = document_root
93
def translate_path(self, path):
94
"""Translate a /-separated PATH to the local filename syntax.
96
Components that mean special things to the local file system
97
(e.g. drive or directory names) are ignored. (XXX They should
98
probably be diagnosed.)
101
# abandon query parameters
102
path = path.split('?',1)[0]
103
path = path.split('#',1)[0]
104
path = posixpath.normpath(urllib.unquote(path))
105
words = path.split('/')
106
words = filter(None, words)
107
path = self.__basepath
109
if word in (os.curdir, os.pardir): continue
110
path = os.path.join(path, word)
113
def init_static_http():
114
if not tools.config.get('static_http_enable', False):
117
document_root = tools.config.get('static_http_document_root', False)
118
assert document_root, "Document root must be specified explicitly to enable static HTTP service (option --static-http-document-root)"
120
base_path = tools.config.get('static_http_url_prefix', '/')
122
reg_http_service(base_path, StaticHTTPHandler)
124
_logger.info("Registered HTTP dir %s for %s", document_root, base_path)
128
class OpenERPAuthProvider(AuthProvider):
129
""" Require basic authentication."""
130
def __init__(self,realm='OpenERP User'):
134
self.last_auth = None
136
def authenticate(self, db, user, passwd, client_address):
138
uid = security.login(db,user,passwd)
141
return user, passwd, db, uid
143
_logger.debug("Fail auth: %s" % e )
146
def checkRequest(self,handler,path, db=False):
147
auth_str = handler.headers.get('Authorization',False)
150
db = handler.get_db_from_path(path)
152
if path.startswith('/'):
159
_logger.info("Wrong path: %s, failing auth" %path)
160
raise AuthRejectedExc("Authorization failed. Wrong sub-path.")
161
if self.auth_creds.get(db):
163
if auth_str and auth_str.startswith('Basic '):
164
auth_str=auth_str[len('Basic '):]
165
(user,passwd) = base64.decodestring(auth_str).split(':')
166
_logger.info("Found user=\"%s\", passwd=\"***\" for db=\"%s\"", user, db)
167
acd = self.authenticate(db,user,passwd,handler.client_address)
169
self.auth_creds[db] = acd
172
if self.auth_tries > 5:
173
_logger.info("Failing authorization after 5 requests w/o password")
174
raise AuthRejectedExc("Authorization failed.")
176
raise AuthRequiredExc(atype='Basic', realm=self.realm)
178
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: