~openerp-dev/openobject-server/trunk-imp-onchange-behave-darshan

« back to all changes in this revision

Viewing changes to openerp/service/http_server.py

  • Committer: Darshan Kalola(OpenERP)
  • Date: 2014-04-09 08:44:52 UTC
  • mfrom: (4936.1.232 openobject-server)
  • Revision ID: dka@tinyerp.com-20140409084452-w1e499j21i3eli9d
[MERGE]sync with trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
#
3
 
# Copyright P. Christeas <p_christ@hol.gr> 2008-2010
4
 
# Copyright 2010 OpenERP SA. (http://www.openerp.com)
5
 
#
6
 
#
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
12
 
# Service Company
13
 
#
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.
18
 
#
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.
23
 
#
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
 
###############################################################################
28
 
 
29
 
 
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.
33
 
 
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.
39
 
"""
40
 
 
41
 
import base64
42
 
import posixpath
43
 
import urllib
44
 
import os
45
 
import logging
46
 
 
47
 
from websrv_lib import *
48
 
import openerp.tools as tools
49
 
 
50
 
try:
51
 
    import fcntl
52
 
except ImportError:
53
 
    fcntl = None
54
 
 
55
 
try:
56
 
    from ssl import SSLError
57
 
except ImportError:
58
 
    class SSLError(Exception): pass
59
 
 
60
 
_logger = logging.getLogger(__name__)
61
 
 
62
 
# TODO delete this for 6.2, it is still needed for 6.1.
63
 
class HttpLogHandler:
64
 
    """ helper class for uniform log handling
65
 
    Please define self._logger at each class that is derived from this
66
 
    """
67
 
    _logger = None
68
 
    
69
 
    def log_message(self, format, *args):
70
 
        self._logger.debug(format % args) # todo: perhaps other level
71
 
 
72
 
    def log_error(self, format, *args):
73
 
        self._logger.error(format % args)
74
 
        
75
 
    def log_exception(self, format, *args):
76
 
        self._logger.exception(format, *args)
77
 
 
78
 
    def log_request(self, code='-', size='-'):
79
 
        self._logger.debug('"%s" %s %s',
80
 
            self.requestline, str(code), str(size))
81
 
 
82
 
class StaticHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler):
83
 
    _logger = logging.getLogger(__name__)
84
 
 
85
 
    _HTTP_OPTIONS = { 'Allow': ['OPTIONS', 'GET', 'HEAD'] }
86
 
 
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
92
 
 
93
 
    def translate_path(self, path):
94
 
        """Translate a /-separated PATH to the local filename syntax.
95
 
 
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.)
99
 
 
100
 
        """
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
108
 
        for word in words:
109
 
            if word in (os.curdir, os.pardir): continue
110
 
            path = os.path.join(path, word)
111
 
        return path
112
 
 
113
 
def init_static_http():
114
 
    if not tools.config.get('static_http_enable', False):
115
 
        return
116
 
    
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)"
119
 
    
120
 
    base_path = tools.config.get('static_http_url_prefix', '/')
121
 
    
122
 
    reg_http_service(base_path, StaticHTTPHandler)
123
 
    
124
 
    _logger.info("Registered HTTP dir %s for %s", document_root, base_path)
125
 
 
126
 
import security
127
 
 
128
 
class OpenERPAuthProvider(AuthProvider):
129
 
    """ Require basic authentication."""
130
 
    def __init__(self,realm='OpenERP User'):
131
 
        self.realm = realm
132
 
        self.auth_creds = {}
133
 
        self.auth_tries = 0
134
 
        self.last_auth = None
135
 
 
136
 
    def authenticate(self, db, user, passwd, client_address):
137
 
        try:
138
 
            uid = security.login(db,user,passwd)
139
 
            if uid is False:
140
 
                return False
141
 
            return user, passwd, db, uid
142
 
        except Exception,e:
143
 
            _logger.debug("Fail auth: %s" % e )
144
 
            return False
145
 
 
146
 
    def checkRequest(self,handler,path, db=False):        
147
 
        auth_str = handler.headers.get('Authorization',False)
148
 
        try:
149
 
            if not db:
150
 
                db = handler.get_db_from_path(path)
151
 
        except Exception:
152
 
            if path.startswith('/'):
153
 
                path = path[1:]
154
 
            psp= path.split('/')
155
 
            if len(psp)>1:
156
 
                db = psp[0]
157
 
            else:
158
 
                #FIXME!
159
 
                _logger.info("Wrong path: %s, failing auth" %path)
160
 
                raise AuthRejectedExc("Authorization failed. Wrong sub-path.") 
161
 
        if self.auth_creds.get(db):
162
 
            return True 
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)
168
 
            if acd != False:
169
 
                self.auth_creds[db] = acd
170
 
                self.last_auth = db
171
 
                return True
172
 
        if self.auth_tries > 5:
173
 
            _logger.info("Failing authorization after 5 requests w/o password")
174
 
            raise AuthRejectedExc("Authorization failed.")
175
 
        self.auth_tries += 1
176
 
        raise AuthRequiredExc(atype='Basic', realm=self.realm)
177
 
 
178
 
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: