Пример #1
0
 def f(_action=action, _self=self, *a, **b):
     self.is_restful = True
     method = _self.env.request_method
     if len(_self.args) and '.' in _self.args[-1]:
         _self.args[-1], _self.extension = _self.args[-1].rsplit(
             '.', 1)
         current.response.headers['Content-Type'] = \
             contenttype(_self.extension.lower())
     if not method in ['GET', 'POST', 'DELETE', 'PUT']:
         raise HTTP(400, "invalid method")
     rest_action = _action().get(method, None)
     if not rest_action:
         raise HTTP(400, "method not supported")
     try:
         return rest_action(*_self.args, **_self.vars)
     except TypeError, e:
         exc_type, exc_value, exc_traceback = sys.exc_info()
         if len(traceback.extract_tb(exc_traceback)) == 1:
             raise HTTP(400, "invalid arguments")
         else:
             raise e
    def callback(self):
        if self.keyword in self.request.vars:
            field = self.fields[0]
            rows = self.db(field.like(self.request.vars[self.keyword]+'%'))\
                .select(orderby=self.orderby,limitby=self.limitby,*self.fields)
            if rows:
                if self.is_reference:
                    id_field = self.fields[1]
                    raise HTTP(200,SELECT(_id=self.keyword,_class='autocomplete',
                                          _size=len(rows),_multiple=(len(rows)==1),
                                          *[OPTION(s[field.name],_value=s[id_field.name],
                                                   _selected=(k==0)) \
                                                for k,s in enumerate(rows)]).xml())
                else:
                    raise HTTP(200,SELECT(_id=self.keyword,_class='autocomplete',
                                          _size=len(rows),_multiple=(len(rows)==1),
                                          *[OPTION(s[field.name],
                                                   _selected=(k==0)) \
                                                for k,s in enumerate(rows)]).xml())
            else:

                raise HTTP(200, '')
Пример #3
0
def check_credentials(request, other_application='admin'):
    """ checks that user is authorized to access other_application"""

    if request.env.web2py_runtime_gae:
        from google.appengine.api import users
        if users.is_current_user_admin():
            return True
        else:
            login_html = '<a href="%s">Sign in with your google account</a>.' \
                % users.create_login_url(request.env.path_info)
            raise HTTP(200, '<html><body>%s</body></html>' % login_html)
    else:
        return get_session(request, other_application).authorized
Пример #4
0
 def map_controller(self):
     "identify controller"
     #  handle controller
     #
     arg0 = self.harg0    # map hyphens
     if not arg0 or (self.controllers and arg0 not in self.controllers):
         self.controller = self.default_controller or ''
     else:
         self.controller = arg0
     self.pop_arg_if(arg0 == self.controller)
     log_rewrite("route: controller=%s" % self.controller)
     if not self.router._acfe_match.match(self.controller):
         raise HTTP(400, thread.routes.error_message % 'invalid request',
                    web2py_error='invalid controller')
Пример #5
0
    def download(self, request, db, chunk_size=DEFAULT_CHUNK_SIZE, attachment=True, download_filename=None):
        """
        example of usage in controller::

            def download():
                return response.download(request, db)

        downloads from http://..../download/filename
        """

        current.session.forget(current.response)

        if not request.args:
            raise HTTP(404)
        name = request.args[-1]
        items = re.compile('(?P<table>.*?)\.(?P<field>.*?)\..*')\
            .match(name)
        if not items:
            raise HTTP(404)
        (t, f) = (items.group('table'), items.group('field'))
        try:
            field = db[t][f]
        except AttributeError:
            raise HTTP(404)
        try:
            (filename, stream) = field.retrieve(name,nameonly=True)
        except IOError:
            raise HTTP(404)
        headers = self.headers
        headers['Content-Type'] = contenttype(name)
        if download_filename == None:
            download_filename = filename
        if attachment:
            headers['Content-Disposition'] = \
                'attachment; filename="%s"' % download_filename.replace('"','\"')
        return self.stream(stream, chunk_size=chunk_size, request=request)
Пример #6
0
 def __call__(self, i, default=None, cast=None, url_onerror=None):        
     if 0<=i<len(self):
         value = self[i]
     else:
         value = default
     if cast:
         try:
             value = cast(value)
         except (ValueError, TypeError):
             from http import HTTP, redirect
             if url_onerror:
                 redirect(url_onerror)
             else:
                 raise HTTP(404)
     return value
Пример #7
0
def copystream_progress(request, chunk_size=10**5):
    """
    copies request.env.wsgi_input into request.body
    and stores progress upload status in cache_ram
    X-Progress-ID:length and X-Progress-ID:uploaded
    """
    env = request.env
    if not env.get('CONTENT_LENGTH', None):
        return cStringIO.StringIO()
    source = env['wsgi.input']
    try:
        size = int(env['CONTENT_LENGTH'])
    except ValueError:
        raise HTTP(400, "Invalid Content-Length header")
    try:  # Android requires this
        dest = tempfile.NamedTemporaryFile()
    except NotImplementedError:  # and GAE this
        dest = tempfile.TemporaryFile()
    if not 'X-Progress-ID' in request.get_vars:
        copystream(source, dest, size, chunk_size)
        return dest
    cache_key = 'X-Progress-ID:' + request.get_vars['X-Progress-ID']
    cache_ram = CacheInRam(request)  # same as cache.ram because meta_storage
    cache_ram(cache_key + ':length', lambda: size, 0)
    cache_ram(cache_key + ':uploaded', lambda: 0, 0)
    while size > 0:
        if size < chunk_size:
            data = source.read(size)
            cache_ram.increment(cache_key + ':uploaded', size)
        else:
            data = source.read(chunk_size)
            cache_ram.increment(cache_key + ':uploaded', chunk_size)
        length = len(data)
        if length > size:
            (data, length) = (data[:size], size)
        size -= length
        if length == 0:
            break
        dest.write(data)
        if length < chunk_size:
            break
    dest.seek(0)
    cache_ram(cache_key + ':length', None)
    cache_ram(cache_key + ':uploaded', None)
    return dest
Пример #8
0
def serve_controller(request, response, session):
    """
    this function is used to generate a dynamic page.
    It first runs all models, then runs the function in the controller,
    and then tries to render the output using a view/template.
    this function must run from the [application] folder.
    A typical example would be the call to the url
    /[application]/[controller]/[function] that would result in a call
    to [function]() in applications/[application]/[controller].py
    rendered by applications/[application]/views/[controller]/[function].html
    """

    # ##################################################
    # build environment for controller and view
    # ##################################################

    environment = build_environment(request, response, session)

    # set default view, controller can override it

    response.view = '%s/%s.%s' % (request.controller,
                                  request.function,
                                  request.extension)

    # also, make sure the flash is passed through
    # ##################################################
    # process models, controller and view (if required)
    # ##################################################

    run_models_in(environment)
    response._view_environment = copy.copy(environment)
    page = run_controller_in(request.controller, request.function, environment)
    if isinstance(page, dict):
        response._vars = page
        for key in page:
            response._view_environment[key] = page[key]
        run_view_in(response._view_environment)
        page = response.body.getvalue()
    # logic to garbage collect after exec, not always, once every 100 requests
    global requests
    requests = ('requests' in globals()) and (requests+1) % 100 or 0
    if not requests: gc.collect()
    # end garbage collection logic
    raise HTTP(response.status, page, **response.headers)
Пример #9
0
 def __call__(self, i, default=DEFAULT, cast=None, otherwise=None):
     """Allows to use a special syntax for fast-check of
     `request.args()` validity.
     :params:
         i: index
         default: use this value if arg not found
         cast: type cast
         otherwise:
             will be executed when:
                 - casts fail
                 - value not found, dont have default and otherwise is
                 especified
             can be:
                 - None: results in a 404
                 - str: redirect to this address
                 - callable: calls the function (nothing is passed)
     Example:
         You can use::
             request.args(0,default=0,cast=int,otherwise='http://error_url')
             request.args(0,default=0,cast=int,otherwise=lambda:...)
     """
     n = len(self)
     if 0 <= i < n or -n <= i < 0:
         value = self[i]
     elif default is DEFAULT:
         value = None
     else:
         value, cast, otherwise = default, False, False
     try:
         if cast:
             value = cast(value)
         if not value and otherwise:
             raise ValueError('Otherwise will raised.')
     except (ValueError, TypeError):
         from http import HTTP, redirect
         if otherwise is None:
             raise HTTP(404)
         elif isinstance(otherwise, str):
             redirect(otherwise)
         elif callable(otherwise):
             return otherwise()
         else:
             raise RuntimeError("invalid otherwise")
     return value
Пример #10
0
def check_credentials(request,
                      other_application='admin',
                      expiration=60 * 60,
                      gae_login=True):
    """ checks that user is authorized to access other_application"""
    if request.env.web2py_runtime_gae:
        from google.appengine.api import users
        if users.is_current_user_admin():
            return True
        elif gae_login:
            login_html = '<a href="%s">Sign in with your google account</a>.' \
                % users.create_login_url(request.env.path_info)
            raise HTTP(200, '<html><body>%s</body></html>' % login_html)
        else:
            return False
    else:
        dt = time.time() - expiration
        s = get_session(request, other_application)
        return (s.authorized and s.last_time and s.last_time > dt)
Пример #11
0
def get_client(env):
    """
    guess the client address from the environment variables

    first tries 'http_x_forwarded_for', secondly 'remote_addr'
    if all fails assume '127.0.0.1' (running locally)
    """
    g = regex_client.search(env.get('http_x_forwarded_for', ''))
    if g:
        client = g.group()
    else:
        g = regex_client.search(env.get('remote_addr', ''))
        if g:
            client = g.group()
        else:
            client = '127.0.0.1'
    if not is_valid_ip_address(client):
        raise HTTP(400, "Bad Request (request.client=%s)" % client)
    return client
Пример #12
0
def try_rewrite_on_error(http_response, request, environ, ticket=None):
    """
    called from main.wsgibase to rewrite the http response.
    """
    status = int(str(http_response.status).split()[0])
    if status >= 399 and thread.routes.routes_onerror:
        keys = set(('%s/%s' % (request.application, status),
                    '%s/*' % (request.application), '*/%s' % (status), '*/*'))
        for (key, uri) in thread.routes.routes_onerror:
            if key in keys:
                if uri == '!':
                    # do nothing!
                    return http_response, environ
                elif '?' in uri:
                    path_info, query_string = uri.split('?', 1)
                    query_string += '&'
                else:
                    path_info, query_string = uri, ''
                query_string += \
                    'code=%s&ticket=%s&requested_uri=%s&request_url=%s' % \
                    (status,ticket,request.env.request_uri,request.url)
                if uri.startswith('http://') or uri.startswith('https://'):
                    # make up a response
                    url = path_info + '?' + query_string
                    message = 'You are being redirected <a href="%s">here</a>'
                    return HTTP(303, message % url, Location=url), environ
                else:
                    error_raising_path = environ['PATH_INFO']
                    # Rewrite routes_onerror path.
                    path_info = '/' + path_info.lstrip(
                        '/')  # add leading '/' if missing
                    environ['PATH_INFO'] = path_info
                    error_handling_path = url_in(request,
                                                 environ)[1]['PATH_INFO']
                    # Avoid infinite loop.
                    if error_handling_path != error_raising_path:
                        # wsgibase will be called recursively with the routes_onerror path.
                        environ['PATH_INFO'] = path_info
                        environ['QUERY_STRING'] = query_string
                        return None, environ
    # do nothing!
    return http_response, environ
Пример #13
0
def copystream_progress(request, chunk_size=10**5):
    """
    copies request.env.wsgi_input into request.body
    and stores progress upload status in cache.ram
    X-Progress-ID:length and X-Progress-ID:uploaded
    """
    env = request.env
    if not env.content_length:
        return cStringIO.StringIO()
    source = env.wsgi_input
    try:
        size = int(env.content_length)
    except ValueError:
        raise HTTP(400, "Invalid Content-Length header")
    dest = tempfile.TemporaryFile()
    if not 'X-Progress-ID' in request.vars:
        copystream(source, dest, size, chunk_size)
        return dest
    cache_key = 'X-Progress-ID:' + request.vars['X-Progress-ID']
    cache = Cache(request)
    cache.ram(cache_key + ':length', lambda: size, 0)
    cache.ram(cache_key + ':uploaded', lambda: 0, 0)
    while size > 0:
        if size < chunk_size:
            data = source.read(size)
            cache.ram.increment(cache_key + ':uploaded', size)
        else:
            data = source.read(chunk_size)
            cache.ram.increment(cache_key + ':uploaded', chunk_size)
        length = len(data)
        if length > size:
            (data, length) = (data[:size], size)
        size -= length
        if length == 0:
            break
        dest.write(data)
        if length < chunk_size:
            break
    dest.seek(0)
    cache.ram(cache_key + ':length', None)
    cache.ram(cache_key + ':uploaded', None)
    return dest
Пример #14
0
def get_client(env):
    """
    guess the client address from the environment variables

    first tries 'http_x_forwarded_for', secondly 'remote_addr'
    if all fails, assume '127.0.0.1' or '::1' (running locally)
    """
    g = regex_client.search(env.get('http_x_forwarded_for', ''))
    client = (g.group() or '').split(',')[0] if g else None
    if client in (None, '', 'unknown'):
        g = regex_client.search(env.get('remote_addr', ''))
        if g:
            client = g.group()
        elif env.http_host.startswith('['):  # IPv6
            client = '::1'
        else:
            client = '127.0.0.1'  # IPv4
    if not is_valid_ip_address(client):
        raise HTTP(400, "Bad Request (request.client=%s)" % client)
    return client
Пример #15
0
def try_redirect_on_error(http_object, request, ticket=None):
    status = int(str(http_object.status).split()[0])
    if status > 399 and params.routes_onerror:
        keys = set(('%s/%s' % (request.application, status),
                    '%s/*' % (request.application), '*/%s' % (status), '*/*'))
        for (key, redir) in params.routes_onerror:
            if key in keys:
                if redir == '!':
                    break
                elif '?' in redir:
                    url = redir + '&' + 'code=%s&ticket=%s&requested_uri=%s' % (
                        status, ticket, request.env.request_uri)
                else:
                    url = redir + '?' + 'code=%s&ticket=%s&requested_uri=%s' % (
                        status, ticket, request.env.request_uri)
                return HTTP(303,
                            'You are being redirected <a href="%s">here</a>' %
                            url,
                            Location=url)
    return http_object
Пример #16
0
def try_redirect_on_error(http_object, request, ticket=None):
    "called from main.wsgibase to rewrite the http response"
    status = int(str(http_object.status).split()[0])
    if status > 399 and thread.routes.routes_onerror:
        keys = set(('%s/%s' % (request.application, status),
                    '%s/*' % (request.application), '*/%s' % (status), '*/*'))
        for (key, redir) in thread.routes.routes_onerror:
            if key in keys:
                if redir == '!':
                    break
                elif '?' in redir:
                    url = '%s&code=%s&ticket=%s&requested_uri=%s&request_url=%s' % \
                        (redir,status,ticket,request.env.request_uri,request.url)
                else:
                    url = '%s?code=%s&ticket=%s&requested_uri=%s&request_url=%s' % \
                        (redir,status,ticket,request.env.request_uri,request.url)
                return HTTP(303,
                            'You are being redirected <a href="%s">here</a>' %
                            url,
                            Location=url)
    return http_object
Пример #17
0
def stream_file_or_304_or_206(
    static_file,
    chunk_size=10**6,
    request=None,
    headers={},
    error_message=error_message,
):
    if not os.path.exists(static_file):
        raise HTTP(404, error_message, web2py_error='invalid file')
    stat_file = os.stat(static_file)
    fsize = stat_file[stat.ST_SIZE]
    mtime = time.strftime('%a, %d %b %Y %H:%M:%S GMT',
                          time.gmtime(stat_file[stat.ST_MTIME]))
    headers['Content-Type'] = contenttype(static_file)
    headers['Last-Modified'] = mtime
    headers['Pragma'] = 'cache'
    headers['Cache-Control'] = 'private'
    if request and request.env.http_if_modified_since == mtime:
        raise HTTP(304)
    elif request and request.env.http_range:
        start_items = regex_start_range.findall(request.env.http_range)
        if not start_items:
            start_items = [0]
        stop_items = regex_stop_range.findall(request.env.http_range)
        if not stop_items or int(stop_items[0]) > fsize - 1:
            stop_items = [fsize - 1]
        part = (int(start_items[0]), int(stop_items[0]), fsize)
        bytes = part[1] - part[0] + 1
        try:
            stream = open(static_file, 'rb')
        except IOError:
            raise HTTP(404)
        stream.seek(part[0])
        headers['Content-Range'] = 'bytes %i-%i/%i' % part
        headers['Content-Length'] = '%i' % bytes
        raise HTTP(206, streamer(stream, chunk_size=chunk_size, bytes=bytes),
                   **headers)
    else:
        try:
            stream = open(static_file, 'rb')
        except IOError:
            raise HTTP(404)
        headers['Content-Length'] = fsize
        raise HTTP(200, streamer(stream, chunk_size=chunk_size), **headers)
Пример #18
0
def serve_controller(request, response, session):
    """
    this function is used to generate a dynmaic page.
    It first runs all models, then runs the function in the controller,
    and then tries to render the output using a view/template.
    this function must run from the [applciation] folder.
    A typical examples would be the call to the url
    /[applicaiton]/[controller]/[function] that would result in a call
    to [function]() in applications/[application]/[controller].py
    renedred by applications/[application]/[controller]/[view].html
    """

    # ##################################################
    # build evnironment for controller and view
    # ##################################################

    environment = build_environment(request, response, session)

    # set default view, controller can override it

    response.view = '%s/%s.html' % (request.controller, request.function)

    # also, make sure the flash is passed through
    # ##################################################
    # process models, controller and view (if required)
    # ##################################################

    run_models_in(environment)
    response._view_environment = copy.copy(environment)
    run_controller_in(request.controller, request.function, environment)
    if not type(response.body) in [types.StringType, types.GeneratorType]:
        for (key, value) in response._vars.items():
            response._view_environment[key] = value
        run_view_in(response._view_environment)
        response.body = response.body.getvalue()
    raise HTTP(200, response.body, **response.headers)
 def __call__(self, i, default=None, cast=None, otherwise=None):
     """
     request.args(0,default=0,cast=int,otherwise='http://error_url')
     request.args(0,default=0,cast=int,otherwise=lambda:...)
     """
     n = len(self)
     if 0 <= i < n or -n <= i < 0:
         value = self[i]
     else:
         value = default
     if cast:
         try:
             value = cast(value)
         except (ValueError, TypeError):
             from http import HTTP, redirect
             if otherwise is None:
                 raise HTTP(404)
             elif isinstance(otherwise, str):
                 redirect(otherwise)
             elif callable(otherwise):
                 return otherwise()
             else:
                 raise RuntimeError, "invalid otherwise"
     return value
Пример #20
0
            raise HTTP(403, error_message, web2py_error='inaccessible file')
        else:
            raise HTTP(404, error_message, web2py_error='invalid file')
    else:
        fp.close()
    stat_file = os.stat(static_file)
    fsize = stat_file[stat.ST_SIZE]
    mtime = time.strftime('%a, %d %b %Y %H:%M:%S GMT',
                          time.gmtime(stat_file[stat.ST_MTIME]))
    headers['Content-Type'] = contenttype(static_file)
    headers['Last-Modified'] = mtime
    headers['Pragma'] = 'cache'
    headers['Cache-Control'] = 'private'

    if request and request.env.http_if_modified_since == mtime:
        raise HTTP(304)
    elif request and request.env.http_range:
        start_items = regex_start_range.findall(request.env.http_range)
        if not start_items:
            start_items = [0]
        stop_items = regex_stop_range.findall(request.env.http_range)
        if not stop_items or int(stop_items[0]) > fsize - 1:
            stop_items = [fsize - 1]
        part = (int(start_items[0]), int(stop_items[0]), fsize)
        bytes = part[1] - part[0] + 1
        try:
            stream = open(static_file, 'rb')
        except IOError, e:
            if e[0] in (errno.EISDIR, errno.EACCES):
                raise HTTP(403)
            else:
    def __init__(self,
                 table,
                 record=None,
                 deletable=False,
                 linkto=None,
                 upload=None,
                 fields=None,
                 labels=None,
                 col3={},
                 submit_button='Submit',
                 delete_label='Check to delete:',
                 showid=True,
                 readonly=False,
                 comments=True,
                 keepopts=[],
                 ignore_rw=False,
                 record_id=None,
                 formstyle='table3cols',
                 **attributes):
        """
        SQLFORM(db.table,
               record=None,
               fields=['name'],
               labels={'name': 'Your name'},
               linkto=URL(r=request, f='table/db/')
        """

        self.ignore_rw = ignore_rw
        self.formstyle = formstyle
        nbsp = XML('&nbsp;')  # Firefox2 does not display fields with blanks
        FORM.__init__(self, *[], **attributes)
        ofields = fields
        keyed = hasattr(table, '_primarykey')

        # if no fields are provided, build it from the provided table
        # will only use writable or readable fields, unless forced to ignore
        if fields == None:
            fields = [
                f.name for f in table
                if (ignore_rw or f.writable or f.readable) and not f.compute
            ]
        self.fields = fields

        # make sure we have an id
        if self.fields[0] != table.fields[0] and \
                isinstance(table,Table) and not keyed:
            self.fields.insert(0, table.fields[0])

        self.table = table

        # try to retrieve the indicated record using its id
        # otherwise ignore it
        if record and isinstance(record, (int, long, str, unicode)):
            if not str(record).isdigit():
                raise HTTP(404, "Object not found")
            record = table._db(table.id == record).select().first()
            if not record:
                raise HTTP(404, "Object not found")
        self.record = record

        self.record_id = record_id
        if keyed:
            if record:
                self.record_id = dict([(k, record[k])
                                       for k in table._primarykey])
            else:
                self.record_id = dict([(k, None) for k in table._primarykey])
        self.field_parent = {}
        xfields = []
        self.fields = fields
        self.custom = Storage()
        self.custom.dspval = Storage()
        self.custom.inpval = Storage()
        self.custom.label = Storage()
        self.custom.comment = Storage()
        self.custom.widget = Storage()
        self.custom.linkto = Storage()

        for fieldname in self.fields:
            if fieldname.find('.') >= 0:
                continue

            field = self.table[fieldname]
            comment = None

            if comments:
                comment = col3.get(fieldname, field.comment)
            if comment == None:
                comment = ''
            self.custom.comment[fieldname] = comment

            if labels != None and fieldname in labels:
                label = labels[fieldname]
                colon = ''
            else:
                label = field.label
                colon = ': '
            self.custom.label[fieldname] = label

            field_id = '%s_%s' % (table._tablename, fieldname)

            label = LABEL(label,
                          colon,
                          _for=field_id,
                          _id=field_id + SQLFORM.ID_LABEL_SUFFIX)

            row_id = field_id + SQLFORM.ID_ROW_SUFFIX
            if field.type == 'id':
                self.custom.dspval.id = nbsp
                self.custom.inpval.id = ''
                widget = ''
                if record:
                    if showid and 'id' in fields and field.readable:
                        v = record['id']
                        widget = SPAN(v, _id=field_id)
                        self.custom.dspval.id = str(v)
                        xfields.append((row_id, label, widget, comment))
                    self.record_id = str(record['id'])
                self.custom.widget.id = widget
                continue

            if readonly and not ignore_rw and not field.readable:
                continue

            if record:
                default = record[fieldname]
            else:
                default = field.default

            cond = readonly or \
                (not ignore_rw and not field.writable and field.readable)

            if default and not cond:
                default = field.formatter(default)
            dspval = default
            inpval = default

            if cond:

                # ## if field.represent is available else
                # ## ignore blob and preview uploaded images
                # ## format everything else

                if field.represent:
                    inp = field.represent(default)
                elif field.type in ['blob']:
                    continue
                elif field.type == 'upload':
                    inp = UploadWidget.represent(field, default, upload)
                else:
                    inp = field.formatter(default)
            elif hasattr(field, 'widget') and field.widget:
                inp = field.widget(field, default)
            elif field.type == 'upload':
                inp = self.widgets.upload.widget(field, default, upload)
            elif field.type == 'boolean':
                inp = self.widgets.boolean.widget(field, default)
                if default:
                    inpval = 'checked'
                else:
                    inpval = ''
            elif OptionsWidget.has_options(field):
                if not field.requires.multiple:
                    inp = self.widgets.options.widget(field, default)
                else:
                    inp = self.widgets.multiple.widget(field, default)
                if fieldname in keepopts:
                    inpval = TAG[''](*inp.components)
            elif str(field.type).startswith('list'):
                inp = self.widgets.list.widget(field, default)
            elif field.type == 'text':
                inp = self.widgets.text.widget(field, default)
            elif field.type == 'password':
                inp = self.widgets.password.widget(field, default)
                if self.record:
                    dspval = PasswordWidget.DEFAULT_PASSWORD_DISPLAY
                else:
                    dspval = ''
            elif field.type == 'blob':
                continue
            else:
                inp = self.widgets.string.widget(field, default)

            xfields.append((row_id, label, inp, comment))
            self.custom.dspval[fieldname] = dspval or nbsp
            self.custom.inpval[fieldname] = inpval or ''
            self.custom.widget[fieldname] = inp

        # if a record is provided and found, as is linkto
        # build a link
        if record and linkto:
            for (rtable, rfield) in table._referenced_by:
                if keyed:
                    rfld = table._db[rtable][rfield]
                    query = urllib.quote(
                        str(rfld == record[rfld.type[10:].split('.')[1]]))
                else:
                    #                 <block>
                    query = urllib.quote(
                        str(table._db[rtable][rfield] == record.id))
                lname = olname = '%s.%s' % (rtable, rfield)
                if ofields and not olname in ofields:
                    continue
                if labels and lname in labels:
                    lname = labels[lname]
                widget = A(lname,
                           _class='reference',
                           _href='%s/%s?query=%s' % (linkto, rtable, query))
                xfields.append(
                    (olname.replace('.', '__') + SQLFORM.ID_ROW_SUFFIX, '',
                     widget, col3.get(olname, '')))
                self.custom.linkto[olname.replace('.', '__')] = widget


#                 </block>

# when deletable, add delete? checkbox
        self.custom.deletable = ''
        if record and deletable:
            widget = INPUT(
                _type='checkbox',
                _class='delete',
                _id=self.FIELDKEY_DELETE_RECORD,
                _name=self.FIELDNAME_REQUEST_DELETE,
            )
            xfields.append(
                (self.FIELDKEY_DELETE_RECORD + SQLFORM.ID_ROW_SUFFIX,
                 LABEL(delete_label,
                       _for=self.FIELDKEY_DELETE_RECORD,
                       _id=self.FIELDKEY_DELETE_RECORD +
                       SQLFORM.ID_LABEL_SUFFIX), widget,
                 col3.get(self.FIELDKEY_DELETE_RECORD, '')))
            self.custom.deletable = widget
        # when writable, add submit button
        self.custom.submit = ''
        if not readonly:
            widget = INPUT(_type='submit', _value=submit_button)
            xfields.append(
                ('submit_record' + SQLFORM.ID_ROW_SUFFIX, '', widget,
                 col3.get('submit_button', '')))
            self.custom.submit = widget
        # if a record is provided and found
        # make sure it's id is stored in the form
        if record:
            if not self['hidden']:
                self['hidden'] = {}
            if not keyed:
                self['hidden']['id'] = record['id']

        (begin, end) = self._xml()
        self.custom.begin = XML("<%s %s>" % (self.tag, begin))
        self.custom.end = XML("%s</%s>" % (end, self.tag))
        if formstyle == 'table3cols':
            table = TABLE()
            for id, a, b, c in xfields:
                td_b = self.field_parent[id] = TD(b, _class='w2p_fw')
                table.append(
                    TR(TD(a, _class='w2p_fl'),
                       td_b,
                       TD(c, _class='w2p_fc'),
                       _id=id))
        elif formstyle == 'table2cols':
            table = TABLE()
            for id, a, b, c in xfields:
                td_b = self.field_parent[id] = TD(b,
                                                  _class='w2p_fw',
                                                  _colspan="2")
                table.append(
                    TR(TD(a, _class='w2p_fl'),
                       TD(c, _class='w2p_fc'),
                       _id=id + '1',
                       _class='even'))
                table.append(TR(td_b, _id=id + '2', _class='odd'))
        elif formstyle == 'divs':
            table = TAG['']()
            for id, a, b, c in xfields:
                div_b = self.field_parent[id] = DIV(b, _class='w2p_fw')
                table.append(
                    DIV(DIV(a, _class='w2p_fl'),
                        div_b,
                        DIV(c, _class='w2p_fc'),
                        _id=id))
        elif formstyle == 'ul':
            table = UL()
            for id, a, b, c in xfields:
                div_b = self.field_parent[id] = DIV(b, _class='w2p_fw')
                table.append(
                    LI(DIV(a, _class='w2p_fl'),
                       div_b,
                       DIV(c, _class='w2p_fc'),
                       _id=id))
        elif type(formstyle) == type(lambda: None):
            table = TABLE()
            for id, a, b, c in xfields:
                td_b = self.field_parent[id] = TD(b, _class='w2p_fw')
                newrows = formstyle(id, a, td_b, c)
                if type(newrows).__name__ != "tuple":
                    newrows = [newrows]
                for newrow in newrows:
                    table.append(newrow)
        else:
            raise RuntimeError, 'formsyle not supported'
        self.components = [table]
Пример #22
0
def parse_get_post_vars(request, environ):

    # always parse variables in URL for GET, POST, PUT, DELETE, etc. in get_vars
    env = request.env
    dget = cgi.parse_qsl(env.query_string or '', keep_blank_values=1)
    for (key, value) in dget:
        if key in request.get_vars:
            if isinstance(request.get_vars[key], list):
                request.get_vars[key] += [value]
            else:
                request.get_vars[key] = [request.get_vars[key]] + [value]
        else:
            request.get_vars[key] = value
        request.vars[key] = request.get_vars[key]

    # parse POST variables on POST, PUT, BOTH only in post_vars
    try:
        request.body = body = copystream_progress(request)
    except IOError:
        raise HTTP(400, "Bad Request - HTTP body is incomplete")
    if (body and env.request_method in ('POST', 'PUT', 'BOTH')):
        dpost = cgi.FieldStorage(fp=body, environ=environ, keep_blank_values=1)
        # The same detection used by FieldStorage to detect multipart POSTs
        is_multipart = dpost.type[:10] == 'multipart/'
        body.seek(0)
        isle25 = sys.version_info[1] <= 5

        def listify(a):
            return (not isinstance(a, list) and [a]) or a
        try:
            keys = sorted(dpost)
        except TypeError:
            keys = []
        for key in keys:
            if key is None:
                continue  # not sure why cgi.FieldStorage returns None key
            dpk = dpost[key]
            # if en element is not a file replace it with its value else leave it alone
            if isinstance(dpk, list):
                value = []
                for _dpk in dpk:
                    if not _dpk.filename:
                        value.append(_dpk.value)
                    else:
                        value.append(_dpk)
            elif not dpk.filename:
                value = dpk.value
            else:
                value = dpk
            pvalue = listify(value)
            if key in request.vars:
                gvalue = listify(request.vars[key])
                if isle25:
                    value = pvalue + gvalue
                elif is_multipart:
                    pvalue = pvalue[len(gvalue):]
                else:
                    pvalue = pvalue[:-len(gvalue)]
            request.vars[key] = value
            if len(pvalue):
                request.post_vars[key] = (len(pvalue) >
                                          1 and pvalue) or pvalue[0]
Пример #23
0
def run_view_in(environment):
    """
    Executes the view for the requested action.
    The view is the one specified in `response.view` or determined by the url
    or `view/generic.extension`
    It tries the pre-compiled views_controller_function.pyc before compiling it.
    """
    request = environment['request']
    response = environment['response']
    view = response.view
    folder = request.folder
    path = pjoin(folder, 'compiled')
    badv = 'invalid view (%s)' % view
    if response.generic_patterns:
        patterns = response.generic_patterns
        regex = re_compile('|'.join(map(fnmatch.translate, patterns)))
        short_action =  '%(controller)s/%(function)s.%(extension)s' % request
        allow_generic = regex.search(short_action)
    else:
        allow_generic = False
    if not isinstance(view, str):
        ccode = parse_template(view, pjoin(folder, 'views'),
                               context=environment)
        restricted(ccode, environment, 'file stream')
    elif os.path.exists(path):
        x = view.replace('/', '_')
        files = ['views_%s.pyc' % x]
        if allow_generic:
            files.append('views_generic.%s.pyc' % request.extension)
        # for backward compatibility
        if request.extension == 'html':
            files.append('views_%s.pyc' % x[:-5])
            if allow_generic:
                files.append('views_generic.pyc')
        # end backward compatibility code
        for f in files:
            filename = pjoin(path,f)
            if os.path.exists(filename):
                code = read_pyc(filename)
                restricted(code, environment, layer=filename)
                return
        raise HTTP(404,
                   rewrite.THREAD_LOCAL.routes.error_message % badv,
                   web2py_error=badv)
    else:
        filename = pjoin(folder, 'views', view)
        if not os.path.exists(filename) and allow_generic:
            view = 'generic.' + request.extension
            filename = pjoin(folder, 'views', view)
        if not os.path.exists(filename):
            raise HTTP(404,
                       rewrite.THREAD_LOCAL.routes.error_message % badv,
                       web2py_error=badv)
        layer = filename
        if is_gae:
            ccode = getcfs(layer, filename,
                           lambda: compile2(parse_template(view,
                                            pjoin(folder, 'views'),
                                            context=environment),layer))
        else:
            ccode = parse_template(view,
                                   pjoin(folder, 'views'),
                                   context=environment)
        restricted(ccode, environment, layer)
Пример #24
0
def run_controller_in(controller, function, environment):
    """
    Runs the controller.function() (for the app specified by
    the current folder).
    It tries pre-compiled controller_function.pyc first before compiling it.
    """

    # if compiled should run compiled!
    folder = environment['request'].folder
    path = pjoin(folder, 'compiled')
    badc = 'invalid controller (%s/%s)' % (controller, function)
    badf = 'invalid function (%s/%s)' % (controller, function)
    if os.path.exists(path):
        filename = pjoin(path, 'controllers_%s_%s.pyc'
                                 % (controller, function))
        if not os.path.exists(filename):
            raise HTTP(404,
                       rewrite.THREAD_LOCAL.routes.error_message % badf,
                       web2py_error=badf)
        restricted(read_pyc(filename), environment, layer=filename)
    elif function == '_TEST':
        # TESTING: adjust the path to include site packages
        from settings import global_settings
        from admin import abspath, add_path_first
        paths = (global_settings.gluon_parent, abspath('site-packages', gluon=True),  abspath('gluon', gluon=True), '')
        [add_path_first(path) for path in paths]
        # TESTING END

        filename = pjoin(folder, 'controllers/%s.py'
                                 % controller)
        if not os.path.exists(filename):
            raise HTTP(404,
                       rewrite.THREAD_LOCAL.routes.error_message % badc,
                       web2py_error=badc)
        environment['__symbols__'] = environment.keys()
        code = read_file(filename)
        code += TEST_CODE
        restricted(code, environment, layer=filename)
    else:
        filename = pjoin(folder, 'controllers/%s.py'
                                 % controller)
        if not os.path.exists(filename):
            raise HTTP(404,
                       rewrite.THREAD_LOCAL.routes.error_message % badc,
                       web2py_error=badc)
        code = read_file(filename)
        exposed = regex_expose.findall(code)
        if not function in exposed:
            raise HTTP(404,
                       rewrite.THREAD_LOCAL.routes.error_message % badf,
                       web2py_error=badf)
        code = "%s\nresponse._vars=response._caller(%s)\n" % (code, function)
        if is_gae:
            layer = filename + ':' + function
            code = getcfs(layer, filename,  lambda: compile2(code,layer))
        restricted(code, environment, filename)
    response = environment['response']
    vars=response._vars
    if response.postprocessing:
        vars = reduce(lambda vars, p: p(vars), response.postprocessing, vars)
    if isinstance(vars,unicode):
        vars = vars.encode('utf8')
    elif hasattr(vars,'xml') and callable(vars.xml):
        vars = vars.xml()
    return vars
Пример #25
0
def wsgibase(environ, responder):
    """
    this is the gluon wsgi application. the first function called when a page
    is requested (static or dynamic). it can be called by paste.httpserver
    or by apache mod_wsgi.

      - fills request with info
      - the environment variables, replacing '.' with '_'
      - adds web2py path and version info
      - compensates for fcgi missing path_info and query_string
      - validates the path in url

    The url path must be either:

    1. for static pages:

      - /<application>/static/<file>

    2. for dynamic pages:

      - /<application>[/<controller>[/<function>[/<sub>]]][.<extension>]
      - (sub may go several levels deep, currently 3 levels are supported:
         sub1/sub2/sub3)

    The naming conventions are:

      - application, controller, function and extension may only contain
        [a-zA-Z0-9_]
      - file and sub may also contain '-', '=', '.' and '/'
    """

    current.__dict__.clear()
    request = Request()
    response = Response()
    session = Session()
    env = request.env
    env.web2py_path = global_settings.applications_parent
    env.web2py_version = web2py_version
    env.update(global_settings)
    static_file = False
    try:
        try:
            try:
                # ##################################################
                # handle fcgi missing path_info and query_string
                # select rewrite parameters
                # rewrite incoming URL
                # parse rewritten header variables
                # parse rewritten URL
                # serve file if static
                # ##################################################

                fixup_missing_path_info(environ)
                (static_file, version, environ) = url_in(request, environ)
                response.status = env.web2py_status_code or response.status

                if static_file:
                    if environ.get('QUERY_STRING',
                                   '').startswith('attachment'):
                        response.headers['Content-Disposition'] \
                            = 'attachment'
                    if version:
                        response.headers['Cache-Control'] = 'max-age=315360000'
                        response.headers[
                            'Expires'] = 'Thu, 31 Dec 2037 23:59:59 GMT'
                    response.stream(static_file, request=request)

                # ##################################################
                # fill in request items
                # ##################################################
                app = request.application  # must go after url_in!

                if not global_settings.local_hosts:
                    local_hosts = set(['127.0.0.1', '::ffff:127.0.0.1', '::1'])
                    if not global_settings.web2py_runtime_gae:
                        try:
                            fqdn = socket.getfqdn()
                            local_hosts.add(socket.gethostname())
                            local_hosts.add(fqdn)
                            local_hosts.update([
                                addrinfo[4][0]
                                for addrinfo in getipaddrinfo(fqdn)
                            ])
                            if env.server_name:
                                local_hosts.add(env.server_name)
                                local_hosts.update([
                                    addrinfo[4][0] for addrinfo in
                                    getipaddrinfo(env.server_name)
                                ])
                        except (socket.gaierror, TypeError):
                            pass
                    global_settings.local_hosts = list(local_hosts)
                else:
                    local_hosts = global_settings.local_hosts
                client = get_client(env)
                x_req_with = str(env.http_x_requested_with).lower()

                request.update(
                    client = client,
                    folder = abspath('applications', app) + os.sep,
                    ajax = x_req_with == 'xmlhttprequest',
                    cid = env.http_web2py_component_element,
                    is_local = env.remote_addr in local_hosts,
                    is_https = env.wsgi_url_scheme in HTTPS_SCHEMES or \
                        request.env.http_x_forwarded_proto in HTTPS_SCHEMES \
                        or env.https == 'on')
                request.compute_uuid()  # requires client
                request.url = environ['PATH_INFO']

                # ##################################################
                # access the requested application
                # ##################################################

                if not exists(request.folder):
                    if app == rwthread.routes.default_application \
                            and app != 'welcome':
                        redirect(URL('welcome', 'default', 'index'))
                    elif rwthread.routes.error_handler:
                        _handler = rwthread.routes.error_handler
                        redirect(
                            URL(_handler['application'],
                                _handler['controller'],
                                _handler['function'],
                                args=app))
                    else:
                        raise HTTP(404,
                                   rwthread.routes.error_message %
                                   'invalid request',
                                   web2py_error='invalid application')
                elif not request.is_local and \
                        exists(pjoin(request.folder, 'DISABLED')):
                    raise HTTP(
                        503,
                        "<html><body><h1>Temporarily down for maintenance</h1></body></html>"
                    )

                # ##################################################
                # build missing folders
                # ##################################################

                create_missing_app_folders(request)

                # ##################################################
                # get the GET and POST data
                # ##################################################

                parse_get_post_vars(request, environ)

                # ##################################################
                # expose wsgi hooks for convenience
                # ##################################################

                request.wsgi.environ = environ_aux(environ, request)
                request.wsgi.start_response = \
                    lambda status='200', headers=[], \
                    exec_info=None, response=response: \
                    start_response_aux(status, headers, exec_info, response)
                request.wsgi.middleware = \
                    lambda *a: middleware_aux(request, response, *a)

                # ##################################################
                # load cookies
                # ##################################################

                if env.http_cookie:
                    try:
                        request.cookies.load(env.http_cookie)
                    except Cookie.CookieError, e:
                        pass  # invalid cookies

                # ##################################################
                # try load session or create new session file
                # ##################################################

                if not env.web2py_disable_session:
                    session.connect(request, response)

                # ##################################################
                # run controller
                # ##################################################

                if global_settings.debugging and app != "admin":
                    import gluon.debug
                    # activate the debugger
                    gluon.debug.dbg.do_debug(mainpyfile=request.folder)

                serve_controller(request, response, session)

            except HTTP, http_response:

                if static_file:
                    return http_response.to(responder, env=env)

                if request.body:
                    request.body.close()

                # ##################################################
                # on success, try store session in database
                # ##################################################
                session._try_store_in_db(request, response)

                # ##################################################
                # on success, commit database
                # ##################################################

                if response.do_not_commit is True:
                    BaseAdapter.close_all_instances(None)
                # elif response._custom_commit:
                #     response._custom_commit()
                elif response.custom_commit:
                    BaseAdapter.close_all_instances(response.custom_commit)
                else:
                    BaseAdapter.close_all_instances('commit')

                # ##################################################
                # if session not in db try store session on filesystem
                # this must be done after trying to commit database!
                # ##################################################

                session._try_store_in_cookie_or_file(request, response)

                if request.cid:
                    if response.flash:
                        http_response.headers['web2py-component-flash'] = \
                            urllib2.quote(xmlescape(response.flash)\
                                              .replace('\n',''))
                    if response.js:
                        http_response.headers['web2py-component-command'] = \
                            urllib2.quote(response.js.replace('\n',''))

                # ##################################################
                # store cookies in headers
                # ##################################################

                rcookies = response.cookies
                if session._forget and response.session_id_name in rcookies:
                    del rcookies[response.session_id_name]
                elif session._secure:
                    rcookies[response.session_id_name]['secure'] = True
                http_response.cookies2headers(rcookies)
                ticket = None

            except RestrictedError, e:

                if request.body:
                    request.body.close()

                # ##################################################
                # on application error, rollback database
                # ##################################################

                ticket = e.log(request) or 'unknown'
                if response._custom_rollback:
                    response._custom_rollback()
                else:
                    BaseAdapter.close_all_instances('rollback')

                http_response = \
                    HTTP(500, rwthread.routes.error_message_ticket %
                         dict(ticket=ticket),
                         web2py_error='ticket %s' % ticket)
Пример #26
0
def parse_get_post_vars(request, environ):

    # always parse variables in URL for GET, POST, PUT, DELETE, etc. in get_vars
    env = request.env
    dget = cgi.parse_qsl(env.query_string or '', keep_blank_values=1)
    for (key, value) in dget:
        if key in request.get_vars:
            if isinstance(request.get_vars[key], list):
                request.get_vars[key] += [value]
            else:
                request.get_vars[key] = [request.get_vars[key]] + [value]
        else:
            request.get_vars[key] = value
        request.vars[key] = request.get_vars[key]

    try:
        request.body = body = copystream_progress(request)
    except IOError:
        raise HTTP(400, "Bad Request - HTTP body is incomplete")

    #if content-type is application/json, we must read the body
    is_json = env.get('http_content_type', '')[:16] == 'application/json'

    if is_json:
        try:
            json_vars = sj.load(body)
            body.seek(0)
        except:
            # incoherent request bodies can still be parsed "ad-hoc"
            json_vars = {}
            pass
        # update vars and get_vars with what was posted as json
        request.get_vars.update(json_vars)
        request.vars.update(json_vars)

    # parse POST variables on POST, PUT, BOTH only in post_vars
    if (body and env.request_method in ('POST', 'PUT', 'DELETE', 'BOTH')):
        dpost = cgi.FieldStorage(fp=body, environ=environ, keep_blank_values=1)
        # The same detection used by FieldStorage to detect multipart POSTs
        is_multipart = dpost.type[:10] == 'multipart/'
        body.seek(0)

        def listify(a):
            return (not isinstance(a, list) and [a]) or a

        try:
            keys = sorted(dpost)
        except TypeError:
            keys = []
        for key in keys:
            if key is None:
                continue  # not sure why cgi.FieldStorage returns None key
            dpk = dpost[key]
            # if en element is not a file replace it with its value else leave it alone
            if isinstance(dpk, list):
                value = []
                for _dpk in dpk:
                    if not _dpk.filename:
                        value.append(_dpk.value)
                    else:
                        value.append(_dpk)
            elif not dpk.filename:
                value = dpk.value
            else:
                value = dpk
            pvalue = listify(value)
            if key in request.vars:
                gvalue = listify(request.vars[key])
                if ISLE25:
                    value = pvalue + gvalue
                elif is_multipart:
                    pvalue = pvalue[len(gvalue):]
                else:
                    pvalue = pvalue[:-len(gvalue)]
            request.vars[key] = value
            if len(pvalue):
                request.post_vars[key] = (len(pvalue) > 1
                                          and pvalue) or pvalue[0]
        if is_json:
            # update post_vars with what was posted as json
            request.post_vars.update(json_vars)
Пример #27
0
            # ##################################################
            # on application error, rollback database
            # ##################################################

            try:
                if response._custom_rollback:
                    response._custom_rollback()
                else:
                    BaseAdapter.close_all_instances('rollback')
            except:
                pass
            e = RestrictedError('Framework', '', '', locals())
            ticket = e.log(request) or 'unrecoverable'
            http_response = \
                HTTP(500, rwthread.routes.error_message_ticket
                     % dict(ticket=ticket),
                     web2py_error='ticket %s' % ticket)

    finally:
        if response and hasattr(response, 'session_file') \
                and response.session_file:
            response.session_file.close()

    session._unlock(response)
    http_response, new_environ = try_rewrite_on_error(http_response, request,
                                                      environ, ticket)
    if not http_response:
        return wsgibase(new_environ, responder)
    if global_settings.web2py_crontype == 'soft':
        newcron.softcron(global_settings.applications_parent).start()
    return http_response.to(responder, env=env)
Пример #28
0
                                 __/ |                
                                |___/  
          _)                              (_
         _) \ /\%/\  /\%/\  /\%/\  /\%/\ / (_
        _)  \\(0 0)  (0 0)  (0 0)  (0 0)//  (_
        )_ -- \(oo)   (oo)   (oo)  (oo)/-- _(
         )_ / /  \_,__/ \__,__/ \_,__/  \ \ _(
          )_ /   --;-- --;- --;-- --;--  \ _( 
       *.   (      ))   ()   ((     ()    )    .*
         '...(___)z z(__)z(__)z(__)z z(__)....'  

"""

exploits = {
    'ssh': SSH(),
    'http': HTTP(),
    'postgres': postgresql(),
    'ldap': LDAP()
}

def read_lines(filename):
    with open(filename, 'r') as f:
        lines = f.read_lines()
    return lines

def main():
    import argparse
    parser = argparse.ArgumentParser(description="Automate Hydra attacks against a specified network range.")
    parser.add_argument("-i", "--host_ips", metavar="<i>", type=str,
                        help="IP address range to search", dest='host_ips')
    parser.add_argument("-u", "--usernames", metavar="<u>", type=str,
Пример #29
0
            raise HTTP(403, error_message, web2py_error='inaccessible file')
        else:
            raise HTTP(404, error_message, web2py_error='invalid file')
    else:
        fp.close()
    stat_file = os.stat(static_file)
    fsize = stat_file[stat.ST_SIZE]
    mtime = time.strftime('%a, %d %b %Y %H:%M:%S GMT',
                          time.gmtime(stat_file[stat.ST_MTIME]))
    headers['Content-Type'] = contenttype(static_file)
    headers['Last-Modified'] = mtime
    headers['Pragma'] = 'cache'
    headers['Cache-Control'] = 'private'

    if request and request.env.http_if_modified_since == mtime:
        raise HTTP(304, **{'Content-Type': headers['Content-Type']})

    elif request and request.env.http_range:
        start_items = regex_start_range.findall(request.env.http_range)
        if not start_items:
            start_items = [0]
        stop_items = regex_stop_range.findall(request.env.http_range)
        if not stop_items or int(stop_items[0]) > fsize - 1:
            stop_items = [fsize - 1]
        part = (int(start_items[0]), int(stop_items[0]), fsize)
        bytes = part[1] - part[0] + 1
        try:
            stream = open(static_file, 'rb')
        except IOError, e:
            if e[0] in (errno.EISDIR, errno.EACCES):
                raise HTTP(403)
Пример #30
0
def regex_url_in(request, environ):
    "rewrite and parse incoming URL"

    # ##################################################
    # select application
    # rewrite URL if routes_in is defined
    # update request.env
    # ##################################################

    regex_select(env=environ, request=request)

    if thread.routes.routes_in:
        environ = regex_filter_in(environ)

    for (key, value) in environ.items():
        request.env[key.lower().replace('.', '_')] = value

    path = request.env.path_info.replace('\\', '/')

    # ##################################################
    # serve if a static file
    # ##################################################

    match = regex_static.match(regex_space.sub('_', path))
    if match and match.group('x'):
        static_file = os.path.join(request.env.applications_parent,
                                   'applications', match.group('b'), 'static',
                                   match.group('x'))
        return (static_file, environ)

    # ##################################################
    # parse application, controller and function
    # ##################################################

    path = re.sub('%20', ' ', path)
    match = regex_url.match(path)
    if not match or match.group('c') == 'static':
        raise HTTP(400,
                   thread.routes.error_message % 'invalid request',
                   web2py_error='invalid path')

    request.application = \
        regex_space.sub('_', match.group('a') or thread.routes.default_application)
    request.controller = \
        regex_space.sub('_', match.group('c') or thread.routes.default_controller)
    request.function = \
        regex_space.sub('_', match.group('f') or thread.routes.default_function)
    group_e = match.group('e')
    request.raw_extension = group_e and regex_space.sub('_', group_e) or None
    request.extension = request.raw_extension or 'html'
    request.raw_args = match.group('r')
    request.args = List([])
    if request.application in thread.routes.routes_apps_raw:
        # application is responsible for parsing args
        request.args = None
    elif request.raw_args:
        match = regex_args.match(request.raw_args.replace(' ', '_'))
        if match:
            group_s = match.group('s')
            request.args = \
                List((group_s and group_s.split('/')) or [])
            if request.args and request.args[-1] == '':
                request.args.pop()  # adjust for trailing empty arg
        else:
            raise HTTP(400,
                       thread.routes.error_message % 'invalid request',
                       web2py_error='invalid path (args)')
    return (None, environ)