Beispiel #1
0
 def to_url(self, value):
     if isinstance(value, str) and value in Brother.__members__:
         return url_quote(value)
     elif isinstance(value, enum.Enum) and value in Brother:
         return url_quote(value.name)
     else:
         return url_quote('oso')
Beispiel #2
0
 def to_url(self, value):
     if isinstance(value, str) and value in NormalCouple.__members__:
         return url_quote(value)
     elif isinstance(value, enum.Enum) and value in NormalCouple:
         return url_quote(value.name)
     else:
         return url_quote('chyoukei')
Beispiel #3
0
 def to_url(self, value):
     if isinstance(value, str) and value in Nickname.subdomains():
         return url_quote(value)
     elif isinstance(value, enum.Enum) and value in Nickname:
         return url_quote(value.subdomain)
     else:
         return url_quote('lesser.oso')
Beispiel #4
0
 def test_quoting(self):
     assert urls.url_quote(u'\xf6\xe4\xfc') == '%C3%B6%C3%A4%C3%BC'
     assert urls.url_unquote(urls.url_quote(u'#%="\xf6')) == u'#%="\xf6'
     assert urls.url_quote_plus('foo bar') == 'foo+bar'
     assert urls.url_unquote_plus('foo+bar') == 'foo bar'
     assert urls.url_encode({'a': None, 'b': 'foo bar'}) == 'b=foo+bar'
     assert urls.url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffsklärung)') == \
            'http://de.wikipedia.org/wiki/Elf%20%28Begriffskl%C3%A4rung%29'
Beispiel #5
0
 def test_quoting(self):
     self.assert_strict_equal(urls.url_quote(u'\xf6\xe4\xfc'), '%C3%B6%C3%A4%C3%BC')
     self.assert_strict_equal(urls.url_unquote(urls.url_quote(u'#%="\xf6')), u'#%="\xf6')
     self.assert_strict_equal(urls.url_quote_plus('foo bar'), 'foo+bar')
     self.assert_strict_equal(urls.url_unquote_plus('foo+bar'), u'foo bar')
     self.assert_strict_equal(urls.url_encode({b'a': None, b'b': b'foo bar'}), 'b=foo+bar')
     self.assert_strict_equal(urls.url_encode({u'a': None, u'b': u'foo bar'}), 'b=foo+bar')
     self.assert_strict_equal(urls.url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffsklärung)'),
            'http://de.wikipedia.org/wiki/Elf%20(Begriffskl%C3%A4rung)')
Beispiel #6
0
    def match(self, path_info = None, method = None, return_rule = False):
        self.map.update()
        if path_info is None:
            path_info = self.path_info
        if not isinstance(path_info, unicode):
            path_info = path_info.decode(self.map.charset, 'ignore')
        method = (method or self.default_method).upper()
        path = u'%s|/%s' % (self.subdomain, path_info.lstrip('/'))
        have_match_for = set()
        for rule in self.map._rules:
            try:
                rv = rule.match(path)
            except RequestSlash:
                raise RequestRedirect(str('%s://%s%s%s/%s/' % (self.url_scheme,
                 self.subdomain and self.subdomain + '.' or '',
                 self.server_name,
                 self.script_name[:-1],
                 url_quote(path_info.lstrip('/'), self.map.charset))))

            if rv is None:
                continue
            if rule.methods is not None and method not in rule.methods:
                have_match_for.update(rule.methods)
                continue
            if self.map.redirect_defaults:
                for r in self.map._rules_by_endpoint[rule.endpoint]:
                    if r.provides_defaults_for(rule) and r.suitable_for(rv, method):
                        rv.update(r.defaults)
                        subdomain, path = r.build(rv)
                        raise RequestRedirect(str('%s://%s%s%s/%s' % (self.url_scheme,
                         subdomain and subdomain + '.' or '',
                         self.server_name,
                         self.script_name[:-1],
                         url_quote(path.lstrip('/'), self.map.charset))))

            if rule.redirect_to is not None:
                if isinstance(rule.redirect_to, basestring):

                    def _handle_match(match):
                        value = rv[match.group(1)]
                        return rule._converters[match.group(1)].to_url(value)

                    redirect_url = _simple_rule_re.sub(_handle_match, rule.redirect_to)
                else:
                    redirect_url = rule.redirect_to(self, **rv)
                raise RequestRedirect(str(urljoin('%s://%s%s%s' % (self.url_scheme,
                 self.subdomain and self.subdomain + '.' or '',
                 self.server_name,
                 self.script_name), redirect_url)))
            if return_rule:
                return (rule, rv)
            return (rule.endpoint, rv)

        if have_match_for:
            raise MethodNotAllowed(valid_methods=list(have_match_for))
        raise NotFound()
Beispiel #7
0
 def test_quoting(self):
     assert urls.url_quote(u"\xf6\xe4\xfc") == "%C3%B6%C3%A4%C3%BC"
     assert urls.url_unquote(urls.url_quote(u'#%="\xf6')) == u'#%="\xf6'
     assert urls.url_quote_plus("foo bar") == "foo+bar"
     assert urls.url_unquote_plus("foo+bar") == "foo bar"
     assert urls.url_encode({"a": None, "b": "foo bar"}) == "b=foo+bar"
     assert (
         urls.url_fix(u"http://de.wikipedia.org/wiki/Elf (Begriffsklärung)")
         == "http://de.wikipedia.org/wiki/Elf%20%28Begriffskl%C3%A4rung%29"
     )
Beispiel #8
0
def get_current_url(environ, root_only=False, strip_querystring=False,
                    host_only=False, trusted_hosts=None):
    """A handy helper function that recreates the full URL for the current
    request or parts of it.  Here an example:

    >>> from werkzeug.test import create_environ
    >>> env = create_environ("/?param=foo", "http://localhost/script")
    >>> get_current_url(env)
    'http://localhost/script/?param=foo'
    >>> get_current_url(env, root_only=True)
    'http://localhost/script/'
    >>> get_current_url(env, host_only=True)
    'http://localhost/'
    >>> get_current_url(env, strip_querystring=True)
    'http://localhost/script/'

    This optionally it verifies that the host is in a list of trusted hosts.
    If the host is not in there it will raise a
    :exc:`~werkzeug.exceptions.SecurityError`.

    :param environ: the WSGI environment to get the current URL from.
    :param root_only: set `True` if you only want the root URL.
    :param strip_querystring: set to `True` if you don't want the querystring.
    :param host_only: set to `True` if the host URL should be returned.
    :param trusted_hosts: a list of trusted hosts, see :func:`host_is_trusted`
                          for more information.
    """
    from werkzeug.urls import uri_to_iri
    tmp = [environ['wsgi.url_scheme'], '://', get_host(environ, trusted_hosts)]
    cat = tmp.append
    if host_only:
        return uri_to_iri(''.join(tmp) + '/')
    cat(urls.url_quote(environ.get('SCRIPT_NAME', '').rstrip('/')))
    if root_only:
        cat('/')
    else:
        cat(urls.url_quote('/' + environ.get('PATH_INFO', '').lstrip('/')))
        if not strip_querystring:
            qs = environ.get('QUERY_STRING')
            if qs:
                # QUERY_STRING really should be ascii safe but some browsers
                # will send us some unicode stuff (I am looking at you IE).
                # In that case we want to urllib quote it badly.
                try:
                    if hasattr(qs, 'decode'):
                        qs.decode('ascii')
                    else:
                        qs.encode('ascii')
                except UnicodeError:
                    qs = ''.join(x > 127 and '%%%02X' % x or c
                                 for x, c in ((ord(x), x) for x in qs))
                cat('?' + qs)
    return uri_to_iri(''.join(tmp))
Beispiel #9
0
def test_quoting():
    strict_eq(urls.url_quote(u'\xf6\xe4\xfc'), '%C3%B6%C3%A4%C3%BC')
    strict_eq(urls.url_unquote(urls.url_quote(u'#%="\xf6')), u'#%="\xf6')
    strict_eq(urls.url_quote_plus('foo bar'), 'foo+bar')
    strict_eq(urls.url_unquote_plus('foo+bar'), u'foo bar')
    strict_eq(urls.url_quote_plus('foo+bar'), 'foo%2Bbar')
    strict_eq(urls.url_unquote_plus('foo%2Bbar'), u'foo+bar')
    strict_eq(urls.url_encode({b'a': None, b'b': b'foo bar'}), 'b=foo+bar')
    strict_eq(urls.url_encode({u'a': None, u'b': u'foo bar'}), 'b=foo+bar')
    strict_eq(urls.url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffsklärung)'),
           'http://de.wikipedia.org/wiki/Elf%20(Begriffskl%C3%A4rung)')
    strict_eq(urls.url_quote_plus(42), '42')
    strict_eq(urls.url_quote(b'\xff'), '%FF')
Beispiel #10
0
def get_current_url(environ, root_only=False, strip_querystring=False,
                    host_only=False, trusted_hosts=None):
    """A handy helper function that recreates the full URL as IRI for the
    current request or parts of it.  Here an example:

    >>> from werkzeug.test import create_environ
    >>> env = create_environ("/?param=foo", "http://localhost/script")
    >>> get_current_url(env)
    'http://localhost/script/?param=foo'
    >>> get_current_url(env, root_only=True)
    'http://localhost/script/'
    >>> get_current_url(env, host_only=True)
    'http://localhost/'
    >>> get_current_url(env, strip_querystring=True)
    'http://localhost/script/'

    This optionally it verifies that the host is in a list of trusted hosts.
    If the host is not in there it will raise a
    :exc:`~werkzeug.exceptions.SecurityError`.

    Note that the string returned might contain unicode characters as the
    representation is an IRI not an URI.  If you need an ASCII only
    representation you can use the :func:`~werkzeug.urls.iri_to_uri`
    function:

    >>> from werkzeug.urls import iri_to_uri
    >>> iri_to_uri(get_current_url(env))
    'http://localhost/script/?param=foo'

    :param environ: the WSGI environment to get the current URL from.
    :param root_only: set `True` if you only want the root URL.
    :param strip_querystring: set to `True` if you don't want the querystring.
    :param host_only: set to `True` if the host URL should be returned.
    :param trusted_hosts: a list of trusted hosts, see :func:`host_is_trusted`
                          for more information.
    """
    tmp = [environ['wsgi.url_scheme'], '://', get_host(environ, trusted_hosts)]
    cat = tmp.append
    if host_only:
        return uri_to_iri(''.join(tmp) + '/')
    cat(url_quote(wsgi_get_bytes(environ.get('SCRIPT_NAME', ''))).rstrip('/'))
    cat('/')
    if not root_only:
        cat(url_quote(wsgi_get_bytes(environ.get('PATH_INFO', '')).lstrip(b'/')))
        if not strip_querystring:
            qs = get_query_string(environ)
            if qs:
                cat('?' + qs)
    return uri_to_iri(''.join(tmp))
Beispiel #11
0
def test_quoting():
    strict_eq(urls.url_quote(u"\xf6\xe4\xfc"), "%C3%B6%C3%A4%C3%BC")
    strict_eq(urls.url_unquote(urls.url_quote(u'#%="\xf6')), u'#%="\xf6')
    strict_eq(urls.url_quote_plus("foo bar"), "foo+bar")
    strict_eq(urls.url_unquote_plus("foo+bar"), u"foo bar")
    strict_eq(urls.url_quote_plus("foo+bar"), "foo%2Bbar")
    strict_eq(urls.url_unquote_plus("foo%2Bbar"), u"foo+bar")
    strict_eq(urls.url_encode({b"a": None, b"b": b"foo bar"}), "b=foo+bar")
    strict_eq(urls.url_encode({u"a": None, u"b": u"foo bar"}), "b=foo+bar")
    strict_eq(
        urls.url_fix(u"http://de.wikipedia.org/wiki/Elf (Begriffsklärung)"),
        "http://de.wikipedia.org/wiki/Elf%20(Begriffskl%C3%A4rung)",
    )
    strict_eq(urls.url_quote_plus(42), "42")
    strict_eq(urls.url_quote(b"\xff"), "%FF")
Beispiel #12
0
def url_for(endpoint, **args):
    """Get the URL to an endpoint.  The keyword arguments provided are used
    as URL values.  Unknown URL values are used as keyword argument.
    Additionally there are some special keyword arguments:

    `_anchor`
        This string is used as URL anchor.

    `_external`
        If set to `True` the URL will be generated with the full server name
        and `http://` prefix.
    """
    if hasattr(endpoint, 'get_url_values'):
        rv = endpoint.get_url_values()
        if rv is not None:
            if isinstance(rv, basestring):
                return make_external_url(rv)
            endpoint, updated_args = rv
            args.update(updated_args)
    anchor = args.pop('_anchor', None)
    external = args.pop('_external', False)
    rv = get_application().url_adapter.build(endpoint, args,
                                             force_external=external)
    if anchor is not None:
        rv += '#' + url_quote(anchor)
    return rv
Beispiel #13
0
    def url_for(self, endpoint, use_partyline=True, **values):
        """Build a URL, asking other applications if BuildError occurs locally.

        This implementation is a fork of :func:`~flask.helpers.url_for`, where
        the implementation you see here works around Flask's context-locals to
        provide URL routing specific to ``self``.  Then it implements the
        wsgi_party url_for requests across Flask applications loaded into the
        partyline.
        """
        # Some values are popped; keep an original copy for re-requesting URL.
        copy_values = copy.deepcopy(values)
        blueprint_name = request.blueprint
        if endpoint[:1] == '.':
            if blueprint_name is not None:
                endpoint = blueprint_name + endpoint
            else:
                endpoint = endpoint[1:]
        external = values.pop('_external', False)
        anchor = values.pop('_anchor', None)
        method = values.pop('_method', None)
        self.inject_url_defaults(endpoint, values)
        url_adapter = self.create_url_adapter(request)
        try:
            rv = url_adapter.build(endpoint, values, method=method,
                                   force_external=external)
        except BuildError:
            # We do not have this URL, ask the partyline.
            if not use_partyline:
                raise
            for url in self.partyline.ask_around('url', (endpoint, copy_values)):
                # First response wins.
                return url
        if anchor is not None:
            rv += '#' + url_quote(anchor)
        return rv
Beispiel #14
0
 def _get_pts_link(self):
     """
     returns an URL for the package in the Debian Package Tracking System
     """
     pts_link = PTS_PREFIX + self.package
     pts_link = url_quote(pts_link)  # for '+' symbol in package names
     return pts_link
Beispiel #15
0
    def fb_request(self, original_url):
        conf_ = conf['fb']

        original_url = oauth_base + conf_['callback_base'] + url_quote(original_url)
        uri = conf_['token_url'] + '?' + url_encode({'client_id': conf_['consumer_key'],
                                                     'redirect_uri': original_url})
        self.redirect(uri)
Beispiel #16
0
def url_for(endpoint, anchor=None, method=None, external=False, **values):
    """Generates a URL to the given endpoint with the method provided.

    endpoint
    :   The endpoint of the URL (name of the function).
    anchor
    :   If provided this is added as anchor to the URL.
    method
    :   If provided this explicitly specifies an HTTP method.
    external
    :   Set to `True`, to generate an absolute URL.
    values
    :   The variable arguments of the URL rule

    """
    try:
        urls = local.urls
    except AttributeError:
        raise RuntimeError("You must call this function only from"
            " inside a view or a template")
    try:
        url = urls.build(endpoint, values, method=method,
            force_external=external)
    except BuildError:
        url = ''

    if anchor is not None:
        url += '#' + url_quote(anchor)
    return url
Beispiel #17
0
    def test_settings_avatar(self):
        response = self.client.get('/user/settings/avatar')
        self.assertRedirects(response, location='/login?next=%s' %
                             url_quote('/user/settings/avatar', safe=''))

        self._login()
        self._test_get_request('/user/settings/avatar', 'settings/avatar.html')
Beispiel #18
0
    def test_profile(self):
        endpoint = '/settings/profile'

        response = self.client.get(endpoint)
        self.assertRedirects(response, location='/login?next=%s' % url_quote(endpoint, safe=''))

        user = self._login()
        response = self.client.get('/settings/profile')
        self.assert200(response)
        self.assertTemplateUsed("settings/profile.html")

        data = {
            'name': 'demo1',
            'email': '*****@*****.**',
            'role_id': ADMIN,
            'status_id': NEW,
            'real_name': user.user_detail.real_name,
            'age': user.user_detail.age,
            'url': user.user_detail.url,
            'location': user.user_detail.location,
            'bio': user.user_detail.bio,
        }
        response = self.client.post(endpoint, data=data)
        print response.data
        assert "help-block error" not in response.data
        self.assert200(response)
        self.assertTemplateUsed("settings/profile.html")
        
        new_user = User.query.filter_by(name=data.get('name')).first()
        assert new_user is not None
        assert new_user.email == data.get('email')
        assert new_user.getRole() == USER_ROLE.get(ADMIN)
        assert new_user.getStatus() == USER_STATUS.get(NEW)
Beispiel #19
0
    def twitter_request(self, original_url):
        conf_ = conf['twitter']
        original_url = oauth_base + conf_['callback_base'] + url_quote(original_url)

        consumer = oauth2.Consumer(conf_['consumer_key'], conf_['consumer_secret'])
        client = oauth2.Client(consumer)

        q, content = client.request(conf_['token_url'], "POST",
                                    body = url_encode({'oauth_callback':original_url}))

        if q['status'] != "200":
            stderr.write("Login error twitter auth:\n    %s\n" % q.content)
            return self.redirect('/?msg=2')
        del q

        oauth_data = url_decode(content)
        oauth_token = oauth_data['oauth_token']
        oauth_token_secret = oauth_data['oauth_token_secret']

        del content
        del oauth_data

        f = open(oauth_secrets_path_prefix + oauth_token, 'w')
        f.write(oauth_token_secret)
        f.close()

        self.redirect(conf_['authenticate'] + "?oauth_token=" + oauth_token)
Beispiel #20
0
    def test_home(self):
        response = self.client.get('/user/')
        self.assertRedirects(response, location='/login?next=%s' %
                             url_quote('/user/', safe=''))

        self.login('demo', '123456')
        self._test_get_request('/user/', 'user/index.html')
def member_is_pending(username):
    rv = github_api_request('GET', 'teams/%s/memberships/%s' % (
        app.config['MEMBER_TEAM_ID'],
        url_quote(username),
    ))
    if rv.status_code == 404:
        return False
    return rv.json().get('state') == 'pending'
Beispiel #22
0
    def run_dev_server(application):
        app_pkg = tmpdir.mkdir("testsuite_app")
        appfile = app_pkg.join("__init__.py")
        port = next(port_generator)
        appfile.write(
            "\n\n".join(
                (
                    "kwargs = {{'hostname': 'localhost', 'port': {port:d}}}".format(
                        port=port
                    ),
                    textwrap.dedent(application),
                )
            )
        )

        monkeypatch.delitem(sys.modules, "testsuite_app", raising=False)
        monkeypatch.syspath_prepend(str(tmpdir))
        import testsuite_app

        hostname = testsuite_app.kwargs["hostname"]
        port = testsuite_app.kwargs["port"]
        addr = "{}:{}".format(hostname, port)

        if hostname.startswith("unix://"):
            addr = hostname.split("unix://", 1)[1]
            requests_url = "http+unix://" + url_quote(addr, safe="")
        elif testsuite_app.kwargs.get("ssl_context", None):
            requests_url = "https://localhost:{0}".format(port)
        else:
            requests_url = "http://localhost:{0}".format(port)

        info = _ServerInfo(xprocess, addr, requests_url, port)

        from xprocess import ProcessStarter

        class Starter(ProcessStarter):
            args = [sys.executable, __file__, str(tmpdir)]

            @property
            def pattern(self):
                return "pid=%s" % info.request_pid()

        xprocess.ensure("dev_server", Starter, restart=True)

        @request.addfinalizer
        def teardown():
            # Killing the process group that runs the server, not just the
            # parent process attached. xprocess is confused about Werkzeug's
            # reloader and won't help here.
            pid = info.request_pid()
            if not pid:
                return
            if platform.system() == "Windows":
                subprocess.call(["taskkill", "/F", "/T", "/PID", str(pid)])
            else:
                os.killpg(os.getpgid(pid), signal.SIGTERM)

        return info
Beispiel #23
0
def fb_callback(request, original_url):
    if "code" not in request.args:
        return redirect("/?msg=2")

    code = request.args["code"]
    callback_uri = request.host_url + "login/callback/fb/" + url_quote(original_url)

    q = requests.get(
        "https://graph.facebook.com/oauth/access_token?"
        + url_encode(
            {
                "client_id": FB["consumer_key"],
                "redirect_uri": url_quote(callback_uri),
                "client_secret": FB["consumer_secret"],
                "code": code,
            }
        )
    )

    if q.status_code != 200:
        return redirect("/?msg=2")

    content = url_decode(q.content)
    access_token = content["access_token"]

    q = requests.get("https://graph.facebook.com/me?access_token=" + access_token)

    if q.status_code != 200:
        return redirect("/?msg=2")

    userdata = loads(q.content)

    profile_id = userdata["id"]
    email = userdata.get("email")
    fullname = userdata["name"]

    img_url = None
    try:
        q = requests.get("https://graph.facebook.com/%s/picture?redirect=0" % profile_id)
        if q.status_code == 200:
            userdata = loads(q.content)["data"]
            img_url = userdata["url"]

    except Exception, exc:
        stderr.write("fb profile pic fetch error: " + str(exc))
Beispiel #24
0
 def external_url_handler(error, endpoint, values):
     method = values.pop('_method', None)
     anchor = values.pop('_anchor', None)
     values.pop('_external', None)
     rv = ext_adapter.build(endpoint, values, method=method,
                            force_external=True)
     if anchor is not None:
         rv += '#' + url_quote(anchor)
     return rv
def index():
    idform = GetIdForm(prefix="get")
    if idform.validate_on_submit():
        return redirect(url_for('component_page', identifier=url_quote(idform.identifier.data, safe='')))

    sform = SearchForm(prefix="search")
    if sform.validate_on_submit():
        return redirect(url_for('component_search', search_str=url_quote(sform.text.data, safe='')))

    itemform = SearchItemsForm(prefix="search-item")
    if itemform.validate_on_submit():
        return redirect(url_for('find_feature', kind=itemform.kind.data, value=url_quote(itemform.text.data, safe='')))

    return render_template('index.html',
        title = 'Home',
        idform = idform,
        sform = sform,
        itemform = itemform)
Beispiel #26
0
    def test_profile(self):
        endpoint = '/settings/profile'

        response = self.client.get(endpoint)
        self.assertRedirects(response, location='/login?next=%s' % url_quote(endpoint, safe=''))

        self.login('demo', '123456')
        response = self.client.get('/settings/profile')
        self.assert200(response)
        self.assertTemplateUsed("settings/profile.html")
Beispiel #27
0
def send_file_inline(filename):
    """Send a file inline, including the original filename.

    Ref: http://test.greenbytes.de/tech/tc2231/.
    """
    response = send_file(filename)
    basename = os.path.basename(filename)
    cont_disp = "inline; filename*=UTF-8''{}".format(url_quote(basename))
    response.headers['Content-Disposition'] = cont_disp
    return response
Beispiel #28
0
def href(*args, **kw):
    """
    Simple function for URL generation.  Position arguments are used for the
    URL path and keyword arguments are used for the url parameters.
    """
    result = [(request and request.script_root or '') + '/']
    for idx, arg in enumerate(args):
        result.append((idx and '/' or '') + url_quote(arg))
    if kw:
        result.append('?' + url_encode(kw))
    return ''.join(result)
Beispiel #29
0
def href(*args, **kw):
    """
    Simple function for URL generation.  Position arguments are used for the
    URL path and keyword arguments are used for the url parameters.
    """
    result = [(request.script_root if request else "") + "/"]
    for idx, arg in enumerate(args):
        result.append(("/" if idx else "") + url_quote(arg))
    if kw:
        result.append("?" + url_encode(kw))
    return "".join(result)
Beispiel #30
0
def get_current_url(environ, root_only=False, strip_querystring=False, host_only=False, trusted_hosts=None):
    """A handy helper function that recreates the full URL for the current
    request or parts of it.  Here an example:

    >>> from werkzeug.test import create_environ
    >>> env = create_environ("/?param=foo", "http://localhost/script")
    >>> get_current_url(env)
    'http://localhost/script/?param=foo'
    >>> get_current_url(env, root_only=True)
    'http://localhost/script/'
    >>> get_current_url(env, host_only=True)
    'http://localhost/'
    >>> get_current_url(env, strip_querystring=True)
    'http://localhost/script/'

    This optionally it verifies that the host is in a list of trusted hosts.
    If the host is not in there it will raise a
    :exc:`~werkzeug.exceptions.SecurityError`.

    :param environ: the WSGI environment to get the current URL from.
    :param root_only: set `True` if you only want the root URL.
    :param strip_querystring: set to `True` if you don't want the querystring.
    :param host_only: set to `True` if the host URL should be returned.
    :param trusted_hosts: a list of trusted hosts, see :func:`host_is_trusted`
                          for more information.
    """
    tmp = [environ["wsgi.url_scheme"], "://", get_host(environ, trusted_hosts)]
    cat = tmp.append
    if host_only:
        return uri_to_iri("".join(tmp) + "/")
    cat(url_quote(wsgi_get_bytes(environ.get("SCRIPT_NAME", ""))).rstrip("/"))
    cat("/")
    if not root_only:
        cat(url_quote(wsgi_get_bytes(environ.get("PATH_INFO", "")).lstrip(b"/")))
        if not strip_querystring:
            qs = get_query_string(environ)
            if qs:
                cat("?" + qs)
    return uri_to_iri("".join(tmp))
Beispiel #31
0
 def to_url(self, value):
     return url_quote(value, self.map.charset)
Beispiel #32
0
 def pypi_url(self):
     pypi_name = self.pypi
     if pypi_name is not None:
         return 'https://pypi.python.org/pypi/%s/' % url_quote(pypi_name)
Beispiel #33
0
        def application(environ, start_response):
            headers = list(EnvironHeaders(environ).items())
            headers[:] = [(k, v) for k, v in headers
                          if not is_hop_by_hop_header(k) and k.lower() not in (
                              'content-length', 'host')]
            headers.append(('Connection', 'close'))
            if opts['host'] == '<auto>':
                headers.append(('Host', target.ascii_host))
            elif opts['host'] is None:
                headers.append(('Host', environ['HTTP_HOST']))
            else:
                headers.append(('Host', opts['host']))
            headers.extend(opts['headers'].items())

            remote_path = path
            if opts['remove_prefix']:
                remote_path = '%s/%s' % (target.path.rstrip('/'),
                                         remote_path[len(prefix):].lstrip('/'))

            content_length = environ.get('CONTENT_LENGTH')
            chunked = False
            if content_length not in ('', None):
                headers.append(('Content-Length', content_length))
            elif content_length is not None:
                headers.append(('Transfer-Encoding', 'chunked'))
                chunked = True

            try:
                if target.scheme == 'http':
                    con = httplib.HTTPConnection(target.ascii_host,
                                                 target.port or 80,
                                                 timeout=self.timeout)
                elif target.scheme == 'https':
                    con = httplib.HTTPSConnection(target.ascii_host,
                                                  target.port or 443,
                                                  timeout=self.timeout,
                                                  context=opts['ssl_context'])
                con.connect()

                remote_url = url_quote(remote_path)
                querystring = environ['QUERY_STRING']
                if querystring:
                    remote_url = remote_url + '?' + querystring

                con.putrequest(environ['REQUEST_METHOD'],
                               remote_url,
                               skip_host=True)

                for k, v in headers:
                    if k.lower() == 'connection':
                        v = 'close'
                    con.putheader(k, v)
                con.endheaders()

                stream = get_input_stream(environ)
                while 1:
                    data = stream.read(self.chunk_size)
                    if not data:
                        break
                    if chunked:
                        con.send(b'%x\r\n%s\r\n' % (len(data), data))
                    else:
                        con.send(data)

                resp = con.getresponse()
            except socket.error:
                from werkzeug.exceptions import BadGateway
                return BadGateway()(environ, start_response)

            start_response(
                '%d %s' % (resp.status, resp.reason),
                [(k.title(), v)
                 for k, v in resp.getheaders() if not is_hop_by_hop_header(k)])

            def read():
                while 1:
                    try:
                        data = resp.read(self.chunk_size)
                    except socket.error:
                        break
                    if not data:
                        break
                    yield data

            return read()
Beispiel #34
0
def results_csv(group_id):
    if current_user.is_admin:
        group = Group.query.get_or_404(group_id)

        def generate():
            group = Group.query.get_or_404(group_id)
            group_name_with_subject = group.name + ' (' + group.subject + ')'
            header = (gettext('Grupa:'), group_name_with_subject)
            yield ",".join(header) + '\n'
            header = (
                gettext("Sekcja"),
                gettext("Tytuł projektu"),
                # gettext("Suma wszystkich punktów"),
                gettext("Punkty z oceniania sposobem 1"),
                gettext("Punkty z oceniania sposobem 2"),
                gettext("Punkty z oceniania sposobem 3"),
                gettext("Punkty od nauczyciela"),
                gettext("Punkty od nauczyciela (poprawa)"),
                gettext("Wyróżnienia (studenci)"),
                gettext("Wyróżnienie (nauczyciel)"))
            yield ",".join(header) + '\n'
            group_points_per_project = gettext(
                f'(od 1 do {str(group.points_per_project)})')
            row = '', '', '', '', group_points_per_project, group_points_per_project, group_points_per_project
            yield ",".join(row) + '\n'

            # Count numbers of evaluators
            section_keys = [section.login for section in group.users]
            points_pool_evaluators = User.query.filter_by(
                did_rate=True, rating_type='points_pool').join(
                    Group, Group.id == User.group_id).filter(
                        Group.name.in_(section_keys)).count()
            points_pool_shuffled_evaluators = User.query.filter_by(
                did_rate=True, rating_type='points_pool_shuffled').join(
                    Group, Group.id == User.group_id).filter(
                        Group.name.in_(section_keys)).count()
            pool_per_project_evaluators = User.query.filter_by(
                did_rate=True, rating_type='pool_per_project').join(
                    Group, Group.id == User.group_id).filter(
                        Group.name.in_(section_keys)).count()

            # numbers needed to calculate score for 3 method
            group_projects = Project.query.join(User).filter(
                User.group == group).order_by(User.section_number.asc()).all()
            raters_pool_per_project_nums = dict()
            for project in group_projects:
                raters_num_temp = User.query.filter_by(
                    did_rate=True, rating_type='pool_per_project').join(
                        Group, Group.id == User.group_id).filter(
                            Group.name.in_(section_keys),
                            Group.name != project.author.login).count()
                if raters_num_temp == 0:
                    raters_num_temp = 1
                raters_pool_per_project_nums[project] = raters_num_temp

            for section in group.users:
                section_name = '\n' + gettext('Sekcja ') + str(
                    section.section_number)
                if section.project:
                    if section.project.upload_file_improvement and (
                            group.rating_status == 'disabled_improvement'
                            or group.rating_status == 'enabled_improvement'
                            or group.rating_status == 'ended_improvement'):
                        section_project_title = section.project.title_improvement
                    else:
                        section_project_title = section.project.title
                    # section_points_sum = (str(section.project.score_points_pool + section.project.score_points_pool_shuffled))
                    section_score_points_pool = (str(
                        section.project.score_points_pool))
                    section_score_points_pool_shuffled = (str(
                        section.project.score_points_pool_shuffled))
                    section_score_pool_per_project = (str(
                        round(
                            section.project.score_pool_per_project /
                            (raters_pool_per_project_nums.get(
                                section.project)), 2)))
                    section_score_admin = (str(section.project.score_admin))
                    section_score_admin_improvement = (str(
                        section.project.score_admin_improvement))
                    section_user_distinctions = (str(
                        section.project.user_distinctions))
                    section_admin_distinction = gettext(
                        "tak"
                    ) if section.project.admin_distinction else gettext("nie")
                else:
                    section_project_title = '---'
                    # section_points_sum = '---'
                    section_score_points_pool = '---'
                    section_score_points_pool_shuffled = '---'
                    section_score_pool_per_project = '---'
                    section_score_admin = '---'
                    section_score_admin_improvement = '---'
                    section_user_distinctions = '---'
                    section_admin_distinction = '---'

                row = (section_name, section_project_title,
                       section_score_points_pool,
                       section_score_points_pool_shuffled,
                       section_score_pool_per_project, section_score_admin,
                       section_score_admin_improvement,
                       section_user_distinctions, section_admin_distinction)
                yield ','.join(row)

            row = gettext('\n\n' + 'Oceniający sposobem 1:'), str(
                points_pool_evaluators)
            yield ','.join(row)
            row = gettext('\n' + 'Oceniający sposobem 2:'), str(
                points_pool_shuffled_evaluators)
            yield ','.join(row)
            row = gettext('\n' + 'Oceniający sposobem 3:'), str(
                pool_per_project_evaluators)
            yield ','.join(row)
    else:
        flash(
            gettext(
                'Musisz mieć uprawnienia administratora, aby uzyskać dostęp do tej strony'
            ), 'warning')
        return redirect(url_for('main.home'))
    filename = group.subject + '-' + group.name.replace(
        " ", "_") + gettext('-wyniki') + ".csv"
    filename = filename.encode('utf-8')
    filename = url_quote(filename)
    return Response(
        generate(),
        mimetype='text/csv',
        headers={"Content-Disposition": "attachment;filename=" + filename})
Beispiel #35
0
 def to_url(self, value):
     return url_quote(self.v2k.get(value, value), self.map.charset)
Beispiel #36
0
 def urlquote(value, charset='utf-8'):
     """ Url Quote. """
     return url_quote(value, charset)
Beispiel #37
0
def test_bytes_unquoting():
    strict_eq(
        urls.url_unquote(urls.url_quote(u'#%="\xf6', charset="latin1"), charset=None),
        b'#%="\xf6',
    )
Beispiel #38
0
        def download():
            """
            Download the zip file.
            """
            # Deny new downloads if "Stop After First Download" is checked and there is
            # currently a download
            deny_download = (self.web.settings.get("share", "autostop_sharing")
                             and self.download_in_progress)
            if deny_download:
                r = make_response(render_template("denied.html"))
                return self.web.add_security_headers(r)

            # Prepare some variables to use inside generate() function below
            # which is outside of the request context
            shutdown_func = request.environ.get("werkzeug.server.shutdown")
            path = request.path

            # If this is a zipped file, then serve as-is. If it's not zipped, then,
            # if the http client supports gzip compression, gzip the file first
            # and serve that
            use_gzip = self.should_use_gzip()
            if use_gzip:
                file_to_download = self.gzip_filename
                self.filesize = self.gzip_filesize
            else:
                file_to_download = self.download_filename
                self.filesize = self.download_filesize

            # Tell GUI the download started
            history_id = self.cur_history_id
            self.cur_history_id += 1
            self.web.add_request(self.web.REQUEST_STARTED, path, {
                "id": history_id,
                "use_gzip": use_gzip
            })

            basename = os.path.basename(self.download_filename)

            def generate():
                # Starting a new download
                if self.web.settings.get("share", "autostop_sharing"):
                    self.download_in_progress = True

                chunk_size = 102400  # 100kb

                fp = open(file_to_download, "rb")
                self.web.done = False
                canceled = False
                while not self.web.done:
                    # The user has canceled the download, so stop serving the file
                    if not self.web.stop_q.empty():
                        self.web.add_request(self.web.REQUEST_CANCELED, path,
                                             {"id": history_id})
                        break

                    chunk = fp.read(chunk_size)
                    if chunk == b"":
                        self.web.done = True
                    else:
                        try:
                            yield chunk

                            # tell GUI the progress
                            downloaded_bytes = fp.tell()
                            percent = (1.0 * downloaded_bytes /
                                       self.filesize) * 100

                            # only output to stdout if running onionshare in CLI mode, or if using Linux (#203, #304)
                            if (not self.web.is_gui
                                    or self.common.platform == "Linux"
                                    or self.common.platform == "BSD"):
                                sys.stdout.write(
                                    "\r{0:s}, {1:.2f}%          ".format(
                                        self.common.human_readable_filesize(
                                            downloaded_bytes),
                                        percent,
                                    ))
                                sys.stdout.flush()

                            self.web.add_request(
                                self.web.REQUEST_PROGRESS,
                                path,
                                {
                                    "id": history_id,
                                    "bytes": downloaded_bytes
                                },
                            )
                            self.web.done = False
                        except:
                            # looks like the download was canceled
                            self.web.done = True
                            canceled = True

                            # tell the GUI the download has canceled
                            self.web.add_request(self.web.REQUEST_CANCELED,
                                                 path, {"id": history_id})

                fp.close()

                if self.common.platform != "Darwin":
                    sys.stdout.write("\n")

                # Download is finished
                if self.web.settings.get("share", "autostop_sharing"):
                    self.download_in_progress = False

                # Close the server, if necessary
                if self.web.settings.get("share",
                                         "autostop_sharing") and not canceled:
                    print("Stopped because transfer is complete")
                    self.web.running = False
                    try:
                        if shutdown_func is None:
                            raise RuntimeError(
                                "Not running with the Werkzeug Server")
                        shutdown_func()
                    except:
                        pass

            r = Response(generate())
            if use_gzip:
                r.headers.set("Content-Encoding", "gzip")
            r.headers.set("Content-Length", self.filesize)
            filename_dict = {
                'filename': unidecode(basename),
                'filename*': "UTF-8''%s" % url_quote(basename)
            }
            r.headers.set("Content-Disposition", "inline", **filename_dict)
            r = self.web.add_security_headers(r)
            # guess content type
            (content_type, _) = mimetypes.guess_type(basename, strict=False)
            if content_type is not None:
                r.headers.set("Content-Type", content_type)
            return r
Beispiel #39
0
def get_tweets(username):
    """Returns the tweets of a given user"""
    resp = urllib2.urlopen('http://twitter.com/statuses/user_timeline/' +
                           url_quote(username) + '.json')
    return json.load(resp)
Beispiel #40
0
def url_for(endpoint, **values):
    """Generates a URL to the given endpoint with the method provided.

    Variable arguments that are unknown to the target endpoint are appended
    to the generated URL as query arguments.  If the value of a query argument
    is ``None``, the whole pair is skipped.  In case blueprints are active
    you can shortcut references to the same blueprint by prefixing the
    local endpoint with a dot (``.``).

    This will reference the index function local to the current blueprint::

        url_for('.index')

    For more information, head over to the :ref:`Quickstart <url-building>`.

    Configuration values ``APPLICATION_ROOT`` and ``SERVER_NAME`` are only used when
    generating URLs outside of a request context.

    To integrate applications, :class:`Flask` has a hook to intercept URL build
    errors through :attr:`Flask.url_build_error_handlers`.  The `url_for`
    function results in a :exc:`~werkzeug.routing.BuildError` when the current
    app does not have a URL for the given endpoint and values.  When it does, the
    :data:`~flask.current_app` calls its :attr:`~Flask.url_build_error_handlers` if
    it is not ``None``, which can return a string to use as the result of
    `url_for` (instead of `url_for`'s default to raise the
    :exc:`~werkzeug.routing.BuildError` exception) or re-raise the exception.
    An example::

        def external_url_handler(error, endpoint, values):
            "Looks up an external URL when `url_for` cannot build a URL."
            # This is an example of hooking the build_error_handler.
            # Here, lookup_url is some utility function you've built
            # which looks up the endpoint in some external URL registry.
            url = lookup_url(endpoint, **values)
            if url is None:
                # External lookup did not have a URL.
                # Re-raise the BuildError, in context of original traceback.
                exc_type, exc_value, tb = sys.exc_info()
                if exc_value is error:
                    raise exc_type, exc_value, tb
                else:
                    raise error
            # url_for will use this result, instead of raising BuildError.
            return url

        app.url_build_error_handlers.append(external_url_handler)

    Here, `error` is the instance of :exc:`~werkzeug.routing.BuildError`, and
    `endpoint` and `values` are the arguments passed into `url_for`.  Note
    that this is for building URLs outside the current application, and not for
    handling 404 NotFound errors.

    .. versionadded:: 0.10
       The `_scheme` parameter was added.

    .. versionadded:: 0.9
       The `_anchor` and `_method` parameters were added.

    .. versionadded:: 0.9
       Calls :meth:`Flask.handle_build_error` on
       :exc:`~werkzeug.routing.BuildError`.

    :param endpoint: the endpoint of the URL (name of the function)
    :param values: the variable arguments of the URL rule
    :param _external: if set to ``True``, an absolute URL is generated. Server
      address can be changed via ``SERVER_NAME`` configuration variable which
      falls back to the `Host` header, then to the IP and port of the request.
    :param _scheme: a string specifying the desired URL scheme. The `_external`
      parameter must be set to ``True`` or a :exc:`ValueError` is raised. The default
      behavior uses the same scheme as the current request, or
      ``PREFERRED_URL_SCHEME`` from the :ref:`app configuration <config>` if no
      request context is available. As of Werkzeug 0.10, this also can be set
      to an empty string to build protocol-relative URLs.
    :param _anchor: if provided this is added as anchor to the URL.
    :param _method: if provided this explicitly specifies an HTTP method.
    """
    appctx = _app_ctx_stack.top
    reqctx = _request_ctx_stack.top

    if appctx is None:
        raise RuntimeError(
            "Attempted to generate a URL without the application context being"
            " pushed. This has to be executed when application context is"
            " available."
        )

    # If request specific information is available we have some extra
    # features that support "relative" URLs.
    if reqctx is not None:
        url_adapter = reqctx.url_adapter
        blueprint_name = request.blueprint

        if endpoint[:1] == ".":
            if blueprint_name is not None:
                endpoint = blueprint_name + endpoint
            else:
                endpoint = endpoint[1:]

        external = values.pop("_external", False)

    # Otherwise go with the url adapter from the appctx and make
    # the URLs external by default.
    else:
        url_adapter = appctx.url_adapter

        if url_adapter is None:
            raise RuntimeError(
                "Application was not able to create a URL adapter for request"
                " independent URL generation. You might be able to fix this by"
                " setting the SERVER_NAME config variable."
            )

        external = values.pop("_external", True)

    anchor = values.pop("_anchor", None)
    method = values.pop("_method", None)
    scheme = values.pop("_scheme", None)
    appctx.app.inject_url_defaults(endpoint, values)

    # This is not the best way to deal with this but currently the
    # underlying Werkzeug router does not support overriding the scheme on
    # a per build call basis.
    old_scheme = None
    if scheme is not None:
        if not external:
            raise ValueError("When specifying _scheme, _external must be True")
        old_scheme = url_adapter.url_scheme
        url_adapter.url_scheme = scheme

    try:
        try:
            rv = url_adapter.build(
                endpoint, values, method=method, force_external=external
            )
        finally:
            if old_scheme is not None:
                url_adapter.url_scheme = old_scheme
    except BuildError as error:
        # We need to inject the values again so that the app callback can
        # deal with that sort of stuff.
        values["_external"] = external
        values["_anchor"] = anchor
        values["_method"] = method
        values["_scheme"] = scheme
        return appctx.app.handle_url_build_error(error, endpoint, values)

    if anchor is not None:
        rv += "#" + url_quote(anchor)
    return rv
Beispiel #41
0
    def create_an_event(self, event):
        """ Create a new event in google calendar from the given event in Harpiya.
            :param event : record of calendar.event to export to google calendar
        """
        data = self.generate_data(event, isCreating=True)

        url = "/calendar/v3/calendars/%s/events?fields=%s&access_token=%s" % ('primary', urls.url_quote('id,updated'), self.get_token())
        headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
        data_json = json.dumps(data)
        return self.env['google.service']._do_request(url, data_json, headers, type='POST')
Beispiel #42
0
def send_file(filename_or_fp, mimetype=None, as_attachment=False,
              attachment_filename=None, add_etags=True,
              cache_timeout=None, conditional=False, last_modified=None):
    """Sends the contents of a file to the client.  This will use the
    most efficient method available and configured.  By default it will
    try to use the WSGI server's file_wrapper support.  Alternatively
    you can set the application's :attr:`~Flask.use_x_sendfile` attribute
    to ``True`` to directly emit an ``X-Sendfile`` header.  This however
    requires support of the underlying webserver for ``X-Sendfile``.

    By default it will try to guess the mimetype for you, but you can
    also explicitly provide one.  For extra security you probably want
    to send certain files as attachment (HTML for instance).  The mimetype
    guessing requires a `filename` or an `attachment_filename` to be
    provided.

    ETags will also be attached automatically if a `filename` is provided. You
    can turn this off by setting `add_etags=False`.

    If `conditional=True` and `filename` is provided, this method will try to
    upgrade the response stream to support range requests.  This will allow
    the request to be answered with partial content response.

    Please never pass filenames to this function from user sources;
    you should use :func:`send_from_directory` instead.

    .. versionadded:: 0.2

    .. versionadded:: 0.5
       The `add_etags`, `cache_timeout` and `conditional` parameters were
       added.  The default behavior is now to attach etags.

    .. versionchanged:: 0.7
       mimetype guessing and etag support for file objects was
       deprecated because it was unreliable.  Pass a filename if you are
       able to, otherwise attach an etag yourself.  This functionality
       will be removed in Flask 1.0

    .. versionchanged:: 0.9
       cache_timeout pulls its default from application config, when None.

    .. versionchanged:: 0.12
       The filename is no longer automatically inferred from file objects. If
       you want to use automatic mimetype and etag support, pass a filepath via
       `filename_or_fp` or `attachment_filename`.

    .. versionchanged:: 0.12
       The `attachment_filename` is preferred over `filename` for MIME-type
       detection.

    .. versionchanged:: 0.13
        UTF-8 filenames, as specified in `RFC 2231`_, are supported.

    .. _RFC 2231: https://tools.ietf.org/html/rfc2231#section-4

    :param filename_or_fp: the filename of the file to send.
                           This is relative to the :attr:`~Flask.root_path`
                           if a relative path is specified.
                           Alternatively a file object might be provided in
                           which case ``X-Sendfile`` might not work and fall
                           back to the traditional method.  Make sure that the
                           file pointer is positioned at the start of data to
                           send before calling :func:`send_file`.
    :param mimetype: the mimetype of the file if provided. If a file path is
                     given, auto detection happens as fallback, otherwise an
                     error will be raised.
    :param as_attachment: set to ``True`` if you want to send this file with
                          a ``Content-Disposition: attachment`` header.
    :param attachment_filename: the filename for the attachment if it
                                differs from the file's filename.
    :param add_etags: set to ``False`` to disable attaching of etags.
    :param conditional: set to ``True`` to enable conditional responses.

    :param cache_timeout: the timeout in seconds for the headers. When ``None``
                          (default), this value is set by
                          :meth:`~Flask.get_send_file_max_age` of
                          :data:`~flask.current_app`.
    :param last_modified: set the ``Last-Modified`` header to this value,
        a :class:`~datetime.datetime` or timestamp.
        If a file was passed, this overrides its mtime.
    """
    mtime = None
    fsize = None
    if isinstance(filename_or_fp, string_types):
        filename = filename_or_fp
        if not os.path.isabs(filename):
            filename = os.path.join(current_app.root_path, filename)
        file = None
        if attachment_filename is None:
            attachment_filename = os.path.basename(filename)
    else:
        file = filename_or_fp
        filename = None

    if mimetype is None:
        if attachment_filename is not None:
            mimetype = mimetypes.guess_type(attachment_filename)[0] \
                or 'application/octet-stream'

        if mimetype is None:
            raise ValueError(
                'Unable to infer MIME-type because no filename is available. '
                'Please set either `attachment_filename`, pass a filepath to '
                '`filename_or_fp` or set your own MIME-type via `mimetype`.'
            )

    headers = Headers()
    if as_attachment:
        if attachment_filename is None:
            raise TypeError('filename unavailable, required for '
                            'sending as attachment')

        try:
            attachment_filename = attachment_filename.encode('latin-1')
        except UnicodeEncodeError:
            filenames = {
                'filename': unicodedata.normalize(
                    'NFKD', attachment_filename).encode('latin-1', 'ignore'),
                'filename*': "UTF-8''%s" % url_quote(attachment_filename),
            }
        else:
            filenames = {'filename': attachment_filename}

        headers.add('Content-Disposition', 'attachment', **filenames)

    if current_app.use_x_sendfile and filename:
        if file is not None:
            file.close()
        headers['X-Sendfile'] = filename
        fsize = os.path.getsize(filename)
        headers['Content-Length'] = fsize
        data = None
    else:
        if file is None:
            file = open(filename, 'rb')
            mtime = os.path.getmtime(filename)
            fsize = os.path.getsize(filename)
            headers['Content-Length'] = fsize
        data = wrap_file(request.environ, file)

    rv = current_app.response_class(data, mimetype=mimetype, headers=headers,
                                    direct_passthrough=True)

    if last_modified is not None:
        rv.last_modified = last_modified
    elif mtime is not None:
        rv.last_modified = mtime

    rv.cache_control.public = True
    if cache_timeout is None:
        cache_timeout = current_app.get_send_file_max_age(filename)
    if cache_timeout is not None:
        rv.cache_control.max_age = cache_timeout
        rv.expires = int(time() + cache_timeout)

    if add_etags and filename is not None:
        from warnings import warn

        try:
            rv.set_etag('%s-%s-%s' % (
                os.path.getmtime(filename),
                os.path.getsize(filename),
                adler32(
                    filename.encode('utf-8') if isinstance(filename, text_type)
                    else filename
                ) & 0xffffffff
            ))
        except OSError:
            warn('Access %s failed, maybe it does not exist, so ignore etags in '
                 'headers' % filename, stacklevel=2)

    if conditional:
        try:
            rv = rv.make_conditional(request, accept_ranges=True,
                                     complete_length=fsize)
        except RequestedRangeNotSatisfiable:
            if file is not None:
                file.close()
            raise
        # make sure we don't send x-sendfile for servers that
        # ignore the 304 status code for x-sendfile.
        if rv.status_code == 304:
            rv.headers.pop('x-sendfile', None)
    return rv
def url_for(endpoint, **values):
    """Generates a URL to the given endpoint with the method provided.

    Variable arguments that are unknown to the target endpoint are appended
    to the generated URL as query arguments.  If the value of a query argument
    is `None`, the whole pair is skipped.  In case blueprints are active
    you can shortcut references to the same blueprint by prefixing the
    local endpoint with a dot (``.``).

    This will reference the index function local to the current blueprint::

        url_for('.index')

    For more information, head over to the :ref:`Quickstart <url-building>`.

    To integrate applications, :class:`Flask` has a hook to intercept URL build
    errors through :attr:`Flask.build_error_handler`.  The `url_for` function
    results in a :exc:`~werkzeug.routing.BuildError` when the current app does
    not have a URL for the given endpoint and values.  When it does, the
    :data:`~flask.current_app` calls its :attr:`~Flask.build_error_handler` if
    it is not `None`, which can return a string to use as the result of
    `url_for` (instead of `url_for`'s default to raise the
    :exc:`~werkzeug.routing.BuildError` exception) or re-raise the exception.
    An example::

        def external_url_handler(error, endpoint, **values):
            "Looks up an external URL when `url_for` cannot build a URL."
            # This is an example of hooking the build_error_handler.
            # Here, lookup_url is some utility function you've built
            # which looks up the endpoint in some external URL registry.
            url = lookup_url(endpoint, **values)
            if url is None:
                # External lookup did not have a URL.
                # Re-raise the BuildError, in context of original traceback.
                exc_type, exc_value, tb = sys.exc_info()
                if exc_value is error:
                    raise exc_type, exc_value, tb
                else:
                    raise error
            # url_for will use this result, instead of raising BuildError.
            return url

        app.build_error_handler = external_url_handler

    Here, `error` is the instance of :exc:`~werkzeug.routing.BuildError`, and
    `endpoint` and `**values` are the arguments passed into `url_for`.  Note
    that this is for building URLs outside the current application, and not for
    handling 404 NotFound errors.

    .. versionadded:: 0.10
       The `_scheme` parameter was added.

    .. versionadded:: 0.9
       The `_anchor` and `_method` parameters were added.

    .. versionadded:: 0.9
       Calls :meth:`Flask.handle_build_error` on
       :exc:`~werkzeug.routing.BuildError`.

    :param endpoint: the endpoint of the URL (name of the function)
    :param values: the variable arguments of the URL rule
    :param _external: if set to `True`, an absolute URL is generated. Server
      address can be changed via `SERVER_NAME` configuration variable which
      defaults to `localhost`.
    :param _scheme: a string specifying the desired URL scheme. The `_external`
      parameter must be set to `True` or a `ValueError` is raised.
    :param _anchor: if provided this is added as anchor to the URL.
    :param _method: if provided this explicitly specifies an HTTP method.
    """
    appctx = _app_ctx_stack.top
    reqctx = _request_ctx_stack.top
    if appctx is None:
        raise RuntimeError('Attempted to generate a URL without the '
                           'application context being pushed. This has to be '
                           'executed when application context is available.')

    # If request specific information is available we have some extra
    # features that support "relative" urls.
    if reqctx is not None:
        url_adapter = reqctx.url_adapter
        blueprint_name = request.blueprint
        if not reqctx.request._is_old_module:
            if endpoint[:1] == '.':
                if blueprint_name is not None:
                    endpoint = blueprint_name + endpoint
                else:
                    endpoint = endpoint[1:]
        else:
            # TODO: get rid of this deprecated functionality in 1.0
            if '.' not in endpoint:
                if blueprint_name is not None:
                    endpoint = blueprint_name + '.' + endpoint
            elif endpoint.startswith('.'):
                endpoint = endpoint[1:]
        external = values.pop('_external', False)

    # Otherwise go with the url adapter from the appctx and make
    # the urls external by default.
    else:
        url_adapter = appctx.url_adapter
        if url_adapter is None:
            raise RuntimeError('Application was not able to create a URL '
                               'adapter for request independent URL generation. '
                               'You might be able to fix this by setting '
                               'the SERVER_NAME config variable.')
        external = values.pop('_external', True)

    anchor = values.pop('_anchor', None)
    method = values.pop('_method', None)
    scheme = values.pop('_scheme', None)
    appctx.app.inject_url_defaults(endpoint, values)

    if scheme is not None:
        if not external:
            raise ValueError('When specifying _scheme, _external must be True')
        url_adapter.url_scheme = scheme

    try:
        rv = url_adapter.build(endpoint, values, method=method,
                               force_external=external)
    except BuildError as error:
        # We need to inject the values again so that the app callback can
        # deal with that sort of stuff.
        values['_external'] = external
        values['_anchor'] = anchor
        values['_method'] = method
        return appctx.app.handle_url_build_error(error, endpoint, values)

    if anchor is not None:
        rv += '#' + url_quote(anchor)
    return rv
Beispiel #44
0
    def _notify_members(self, message):
        """Send the given message to all members of the mail group (except the author)."""
        self.ensure_one()

        if message.mail_group_id != self:
            raise UserError(_('The group of the message do not match.'))

        if not message.mail_message_id.reply_to:
            _logger.error('The alias or the catchall domain is missing, group might not work properly.')

        base_url = self.get_base_url()
        body = self.env['mail.render.mixin']._replace_local_links(message.body)
        access_token = self._generate_group_access_token()
        mail_values = []

        # Email added in a dict to be sure to send only once the email to each address
        member_emails = {
            email_normalize(member.email): member.email
            for member in self.member_ids
        }

        for batch_email_member in tools.split_every(GROUP_SEND_BATCH_SIZE, member_emails.items()):
            for email_member_normalized, email_member in batch_email_member:
                if email_member_normalized == message.email_from_normalized:
                    # Do not send the email to his author
                    continue

                # SMTP headers related to the subscription
                email_url_encoded = urls.url_quote(email_member)
                headers = {
                    ** self._notify_email_header_dict(),
                    'List-Archive': f'<{base_url}/groups/{slug(self)}>',
                    'List-Subscribe': f'<{base_url}/groups?email={email_url_encoded}>',
                    'List-Unsubscribe': f'<{base_url}/groups?unsubscribe&email={email_url_encoded}>',
                    'Precedence': 'list',
                    'X-Auto-Response-Suppress': 'OOF',  # avoid out-of-office replies from MS Exchange
                }
                if self.alias_name and self.alias_domain:
                    headers.update({
                        'List-Id': f'<{self.alias_name}.{self.alias_domain}>',
                        'List-Post': f'<mailto:{self.alias_name}@{self.alias_domain}>',
                        'X-Forge-To': f'"{self.name}" <{self.alias_name}@{self.alias_domain}>',
                    })

                if message.mail_message_id.parent_id:
                    headers['In-Reply-To'] = message.mail_message_id.parent_id.message_id

                # Add the footer (member specific) in the body
                template_values = {
                    'mailto': f'{self.alias_name}@{self.alias_domain}',
                    'group_url': f'{base_url}/groups/{slug(self)}',
                    'unsub_label': f'{base_url}/groups?unsubscribe',
                    'unsub_url':  f'{base_url}/groups?unsubscribe&group_id={self.id}&token={access_token}&email={email_url_encoded}',
                }
                template = self.env.ref('mail_group.mail_group_footer')
                footer = template._render(template_values, engine='ir.qweb', minimal_qcontext=True)
                member_body = tools.append_content_to_html(body, footer, plaintext=False)

                mail_values.append({
                    'auto_delete': True,
                    'attachment_ids': message.attachment_ids.ids,
                    'body_html': member_body,
                    'email_from': message.email_from,
                    'email_to': email_member,
                    'headers': json.dumps(headers),
                    'mail_message_id': message.mail_message_id.id,
                    'message_id': message.mail_message_id.message_id,
                    'model': 'mail.group',
                    'reply_to': message.mail_message_id.reply_to,
                    'res_id': self.id,
                    'subject': message.subject,
                })

            if mail_values:
                self.env['mail.mail'].sudo().create(mail_values)
        def download():
            """
            Download the zip file.
            """
            # Deny new downloads if "Stop After First Download" is checked and there is
            # currently a download
            deny_download = (self.web.settings.get("share", "autostop_sharing")
                             and self.download_in_progress)
            if deny_download:
                return render_template("denied.html")

            # Prepare some variables to use inside generate() function below
            # which is outside of the request context
            shutdown_func = request.environ.get("werkzeug.server.shutdown")
            request_path = request.path

            # If this is a zipped file, then serve as-is. If it's not zipped, then,
            # if the http client supports gzip compression, gzip the file first
            # and serve that
            use_gzip = self.should_use_gzip()
            if use_gzip:
                file_to_download = self.gzip_filename
                self.filesize = self.gzip_filesize
                etag = self.gzip_etag
            else:
                file_to_download = self.download_filename
                self.filesize = self.download_filesize
                etag = self.download_etag

            # for range requests
            range_, status_code = self.get_range_and_status_code(
                self.filesize, etag, self.last_modified)

            # Tell GUI the download started
            history_id = self.cur_history_id
            self.cur_history_id += 1
            self.web.add_request(
                self.web.REQUEST_STARTED,
                request_path,
                {
                    "id": history_id,
                    "use_gzip": use_gzip
                },
            )

            basename = os.path.basename(self.download_filename)

            if status_code == 304:
                r = Response()
            else:
                r = Response(
                    self.generate(
                        shutdown_func,
                        range_,
                        file_to_download,
                        request_path,
                        history_id,
                        self.filesize,
                    ))

            if use_gzip:
                r.headers.set("Content-Encoding", "gzip")

            r.headers.set("Content-Length", range_[1] - range_[0] + 1)
            filename_dict = {
                "filename": unidecode(basename),
                "filename*": "UTF-8''%s" % url_quote(basename),
            }
            r.headers.set("Content-Disposition", "attachment", **filename_dict)
            # guess content type
            (content_type, _) = mimetypes.guess_type(basename, strict=False)
            if content_type is not None:
                r.headers.set("Content-Type", content_type)
            r.headers.set("Accept-Ranges", "bytes")
            r.headers.set("ETag", etag)
            r.headers.set("Last-Modified", http_date(self.last_modified))
            # we need to set this for range requests
            r.headers.set("Vary", "Accept-Encoding")

            if status_code == 206:
                r.headers.set(
                    "Content-Range",
                    "bytes {}-{}/{}".format(range_[0], range_[1],
                                            self.filesize),
                )

            r.status_code = status_code

            return r
Beispiel #46
0
def send_stream(stream, filename, size, mtime, mimetype=None, restricted=True,
                as_attachment=False, etag=None, content_md5=None,
                chunk_size=None, conditional=True, trusted=False):
    """Send the contents of a file to the client.

    .. warning::

        It is very easy to be exposed to Cross-Site Scripting (XSS) attacks if
        you serve user uploaded files. Here are some recommendations:

            1. Serve user uploaded files from a separate domain
               (not a subdomain). This way a malicious file can only attack
               other user uploaded files.
            2. Prevent the browser from rendering and executing HTML files (by
               setting ``trusted=False``).
            3. Force the browser to download the file as an attachment
               (``as_attachment=True``).

    :param stream: The file stream to send.
    :param filename: The file name.
    :param size: The file size.
    :param mtime: A Unix timestamp that represents last modified time (UTC).
    :param mimetype: The file mimetype. If ``None``, the module will try to
        guess. (Default: ``None``)
    :param restricted: If the file is not restricted, the module will set the
        cache-control. (Default: ``True``)
    :param as_attachment: If the file is an attachment. (Default: ``False``)
    :param etag: If defined, it will be set as HTTP E-Tag.
    :param content_md5: If defined, a HTTP Content-MD5 header will be set.
    :param chunk_size: The chunk size.
    :param conditional: Make the response conditional to the request.
        (Default: ``True``)
    :param trusted: Do not enable this option unless you know what you are
        doing. By default this function will send HTTP headers and MIME types
        that prevents your browser from rendering e.g. a HTML file which could
        contain a malicious script tag.
        (Default: ``False``)
    :returns: A Flask response instance.
    """
    chunk_size = chunk_size_or_default(chunk_size)

    # Guess mimetype from filename if not provided.
    if mimetype is None and filename:
        mimetype = mimetypes.guess_type(filename)[0]
    if mimetype is None:
        mimetype = 'application/octet-stream'

    # Construct headers
    headers = Headers()
    headers['Content-Length'] = size
    if content_md5:
        headers['Content-MD5'] = content_md5

    if not trusted:
        # Sanitize MIME type
        mimetype = sanitize_mimetype(mimetype, filename=filename)
        # See https://www.owasp.org/index.php/OWASP_Secure_Headers_Project
        # Prevent JavaScript execution
        headers['Content-Security-Policy'] = "default-src 'none';"
        # Prevent MIME type sniffing for browser.
        headers['X-Content-Type-Options'] = 'nosniff'
        # Prevent opening of downloaded file by IE
        headers['X-Download-Options'] = 'noopen'
        # Prevent cross domain requests from Flash/Acrobat.
        headers['X-Permitted-Cross-Domain-Policies'] = 'none'
        # Prevent files from being embedded in frame, iframe and object tags.
        headers['X-Frame-Options'] = 'deny'
        # Enable XSS protection (IE, Chrome, Safari)
        headers['X-XSS-Protection'] = '1; mode=block'

    # Force Content-Disposition for application/octet-stream to prevent
    # Content-Type sniffing.
    if as_attachment or mimetype == 'application/octet-stream':
        # See https://github.com/pallets/flask/commit/0049922f2e690a6d
        try:
            filenames = {'filename': filename.encode('latin-1')}
        except UnicodeEncodeError:
            filenames = {'filename*': "UTF-8''%s" % url_quote(filename)}
            encoded_filename = (unicodedata.normalize('NFKD', filename)
                                .encode('latin-1', 'ignore'))
            if encoded_filename:
                filenames['filename'] = encoded_filename
        headers.add('Content-Disposition', 'attachment', **filenames)
    else:
        headers.add('Content-Disposition', 'inline')

    # Construct response object.
    rv = current_app.response_class(
        FileWrapper(stream, buffer_size=chunk_size),
        mimetype=mimetype,
        headers=headers,
        direct_passthrough=True,
    )

    # Set etag if defined
    if etag:
        rv.set_etag(etag)

    # Set last modified time
    if mtime is not None:
        rv.last_modified = int(mtime)

    # Set cache-control
    if not restricted:
        rv.cache_control.public = True
        cache_timeout = current_app.get_send_file_max_age(filename)
        if cache_timeout is not None:
            rv.cache_control.max_age = cache_timeout
            rv.expires = int(time() + cache_timeout)

    if conditional:
        rv = rv.make_conditional(request)

    return rv
def remove_member(username):
    github_api_request(
        'DELETE', 'teams/%s/members/%s' % (
            app.config['MEMBER_TEAM_ID'],
            url_quote(username),
        )).raise_for_status()
Beispiel #48
0
def redirect_stream(url,
                    filename,
                    size,
                    mtime,
                    mimetype=None,
                    restricted=True,
                    as_attachment=False,
                    etag=None,
                    content_md5=None,
                    chunk_size=None,
                    conditional=True,
                    trusted=False):
    """Redirect to URL to serve the file directly from there.

    :param url: redirection URL

    :return: Flaks response.
    """
    chunk_size = chunk_size_or_default(chunk_size)

    # Guess mimetype from filename if not provided.
    if mimetype is None and filename:
        mimetype = mimetypes.guess_type(filename)[0]
    if mimetype is None:
        mimetype = 'application/octet-stream'

    # Construct headers
    headers = Headers()
    headers['Content-Length'] = size
    if content_md5:
        headers['Content-MD5'] = content_md5
    # Add redirect url as localtion
    headers['Location'] = url

    if not trusted:
        # Sanitize MIME type
        mimetype = sanitize_mimetype(mimetype, filename=filename)
        # See https://www.owasp.org/index.php/OWASP_Secure_Headers_Project
        # Prevent JavaScript execution
        headers['Content-Security-Policy'] = "default-src 'none';"
        # Prevent MIME type sniffing for browser.
        headers['X-Content-Type-Options'] = 'nosniff'
        # Prevent opening of downloaded file by IE
        headers['X-Download-Options'] = 'noopen'
        # Prevent cross domain requests from Flash/Acrobat.
        headers['X-Permitted-Cross-Domain-Policies'] = 'none'
        # Prevent files from being embedded in frame, iframe and object tags.
        headers['X-Frame-Options'] = 'deny'
        # Enable XSS protection (IE, Chrome, Safari)
        headers['X-XSS-Protection'] = '1; mode=block'

    # Force Content-Disposition for application/octet-stream to prevent
    # Content-Type sniffing.
    if as_attachment or mimetype == 'application/octet-stream':
        # See https://github.com/pallets/flask/commit/0049922f2e690a6d
        try:
            filenames = {'filename': filename.encode('latin-1')}
        except UnicodeEncodeError:
            filenames = {'filename*': "UTF-8''%s" % url_quote(filename)}
            encoded_filename = (unicodedata.normalize('NFKD', filename).encode(
                'latin-1', 'ignore'))
            if encoded_filename:
                filenames['filename'] = encoded_filename
        headers.add('Content-Disposition', 'attachment', **filenames)
    else:
        headers.add('Content-Disposition', 'inline')

    # Construct response object.
    rv = current_app.response_class(
        url,
        status=302,
        mimetype=mimetype,
        headers=headers,
        direct_passthrough=True,
    )

    # Set etag if defined
    if etag:
        rv.set_etag(etag)

    # Set last modified time
    if mtime is not None:
        rv.last_modified = int(mtime)

    # Set cache-control
    if not restricted:
        rv.cache_control.public = True
        cache_timeout = current_app.get_send_file_max_age(filename)
        if cache_timeout is not None:
            rv.cache_control.max_age = cache_timeout
            rv.expires = int(time() + cache_timeout)

    if conditional:
        rv = rv.make_conditional(request)

    return rv
def add_member(username):
    github_api_request(
        'PUT', 'teams/%s/memberships/%s' % (
            app.config['MEMBER_TEAM_ID'],
            url_quote(username),
        )).raise_for_status()
Beispiel #50
0
        def application(environ, start_response):
            headers = list(EnvironHeaders(environ).items())
            headers[:] = [(k, v) for k, v in headers
                          if not is_hop_by_hop_header(k) and k.lower() not in (
                              "content-length", "host")]
            headers.append(("Connection", "close"))
            if opts["host"] == "<auto>":
                headers.append(("Host", target.ascii_host))
            elif opts["host"] is None:
                headers.append(("Host", environ["HTTP_HOST"]))
            else:
                headers.append(("Host", opts["host"]))
            headers.extend(opts["headers"].items())

            remote_path = path
            if opts["remove_prefix"]:
                remote_path = "%s/%s" % (
                    target.path.rstrip("/"),
                    remote_path[len(prefix):].lstrip("/"),
                )

            content_length = environ.get("CONTENT_LENGTH")
            chunked = False
            if content_length not in ("", None):
                headers.append(("Content-Length", content_length))
            elif content_length is not None:
                headers.append(("Transfer-Encoding", "chunked"))
                chunked = True

            try:
                if target.scheme == "http":
                    con = httplib.HTTPConnection(target.ascii_host,
                                                 target.port or 80,
                                                 timeout=self.timeout)
                elif target.scheme == "https":
                    con = httplib.HTTPSConnection(
                        target.ascii_host,
                        target.port or 443,
                        timeout=self.timeout,
                        context=opts["ssl_context"],
                    )
                con.connect()
                con.putrequest(environ["REQUEST_METHOD"],
                               url_quote(remote_path),
                               skip_host=True)

                for k, v in headers:
                    if k.lower() == "connection":
                        v = "close"
                    con.putheader(k, v)
                con.endheaders()

                stream = get_input_stream(environ)
                while 1:
                    data = stream.read(self.chunk_size)
                    if not data:
                        break
                    if chunked:
                        con.send(b"%x\r\n%s\r\n" % (len(data), data))
                    else:
                        con.send(data)

                resp = con.getresponse()
            except socket.error:
                from werkzeug.exceptions import BadGateway

                return BadGateway()(environ, start_response)

            start_response(
                "%d %s" % (resp.status, resp.reason),
                [(k.title(), v)
                 for k, v in resp.getheaders() if not is_hop_by_hop_header(k)],
            )

            def read():
                while 1:
                    try:
                        data = resp.read(self.chunk_size)
                    except socket.error:
                        break
                    if not data:
                        break
                    yield data

            return read()
Beispiel #51
0
 def to_url(self, value):
     parts = itertools.chain.from_iterable(value)
     quoted_parts = (urls.url_quote(p, charset=self.map.charset, safe='')
                     for p in parts)
     return ''.join(p + '/' for p in quoted_parts)
Beispiel #52
0
                              values,
                              method=method,
                              force_external=external)
    except BuildError, error:
        values['_external'] = external
        values['_anchor'] = anchor
        values['_method'] = method
        return appctx.app.handleBuildError(error, endpoint, **values)

    rv = urlAdapter.build(endpoint,
                          values,
                          method=method,
                          force_external=external)

    if anchor is not None:
        rv += '#' + url_quote(anchor)
    return rv


def findPackage(importName):
    rootModName = importName.split('.')[0]
    loader = pkgutil.get_loader(rootModName)
    if loader is None or importName == '__main__':
        pkgPath = os.getcwd()
    else:
        if hasattr(loader, 'get_filename'):
            filename = loader.get_filename(rootModName)
        elif hasattr(loader, 'active'):
            filename = loader.active
        else:
            __import__(importName)
Beispiel #53
0
def url_for_item(item_name,
                 wiki_name='',
                 field='',
                 namespace='',
                 rev=CURRENT,
                 endpoint='frontend.show_item',
                 _external=False,
                 regex=''):
    """
    Compute URL for some local or remote/interwiki item.

    For local items:
    give <rev> to get the url of some specific revision.
    give the <endpoint> to get the url of some specific view,
    give _external=True to compute fully specified URLs.

    For remote/interwiki items:
    If you just give <item_name> and <wiki_name>, a generic interwiki URL
    will be built.
    If you also give <rev> and/or <endpoint>, it is assumed that remote wiki
    URLs are built in the same way as local URLs.
    Computed URLs are always fully specified.
    """
    if field == NAME_EXACT:
        field = ''
    if is_local_wiki(wiki_name):
        item_name = get_fqname(item_name, field, namespace)
        if rev is None or rev == CURRENT:
            url = url_for(endpoint, item_name=item_name, _external=_external)
        else:
            url = url_for(endpoint,
                          item_name=item_name,
                          rev=rev,
                          _external=_external)
    else:
        try:
            wiki_base_url = app.cfg.interwiki_map[wiki_name]
        except KeyError as err:
            logging.warning(
                "no interwiki_map entry for {0!r}".format(wiki_name))
            item_name = get_fqname(item_name, field, namespace)
            if wiki_name:
                url = '{0}/{1}'.format(wiki_name, item_name)
            else:
                url = item_name
            url = '/{0}'.format(url)
        else:
            if (rev is None
                    or rev == CURRENT) and endpoint == 'frontend.show_item':
                # we just want to show latest revision (no special revision given) -
                # this is the generic interwiki url support, should work for any remote wiki
                url = join_wiki(wiki_base_url, item_name, field, namespace)
            else:
                # rev and/or endpoint was given, assume same URL building as for local wiki.
                # we need this for moin wiki farms, e.g. to link from search results to
                # some specific item/revision in another farm wiki.
                item_name = get_fqname(item_name, field, namespace)
                local_url = url_for(endpoint,
                                    item_name=item_name,
                                    rev=rev,
                                    _external=False)
                # we know that everything left of the + belongs to script url, but we
                # just want e.g. +show/42/FooBar to append it to the other wiki's
                # base URL.
                i = local_url.index('/+')
                path = local_url[i + 1:]
                url = wiki_base_url + path
    if regex:
        url += '?regex={0}'.format(url_quote(regex, charset=CHARSET))
    return url
Beispiel #54
0
def send_file(
    filename_or_fp,
    mimetype=None,
    as_attachment=False,
    attachment_filename=None,
    add_etags=True,
    cache_timeout=None,
    conditional=False,
    last_modified=None,
):
    """Sends the contents of a file to the client.  This will use the
    most efficient method available and configured.  By default it will
    try to use the WSGI server's file_wrapper support.  Alternatively
    you can set the application's :attr:`~Flask.use_x_sendfile` attribute
    to ``True`` to directly emit an ``X-Sendfile`` header.  This however
    requires support of the underlying webserver for ``X-Sendfile``.

    By default it will try to guess the mimetype for you, but you can
    also explicitly provide one.  For extra security you probably want
    to send certain files as attachment (HTML for instance).  The mimetype
    guessing requires a `filename` or an `attachment_filename` to be
    provided.

    When passing a file-like object instead of a filename, only binary
    mode is supported (``open(filename, "rb")``, :class:`~io.BytesIO`,
    etc.). Text mode files and :class:`~io.StringIO` will raise a
    :exc:`ValueError`.

    ETags will also be attached automatically if a `filename` is provided. You
    can turn this off by setting `add_etags=False`.

    If `conditional=True` and `filename` is provided, this method will try to
    upgrade the response stream to support range requests.  This will allow
    the request to be answered with partial content response.

    Please never pass filenames to this function from user sources;
    you should use :func:`send_from_directory` instead.

    .. versionchanged:: 2.0
        Passing a file-like object that inherits from
        :class:`~io.TextIOBase` will raise a :exc:`ValueError` rather
        than sending an empty file.

    .. versionchanged:: 1.1
        ``filename`` may be a :class:`~os.PathLike` object.

    .. versionchanged:: 1.1
        Passing a :class:`~io.BytesIO` object supports range requests.

    .. versionchanged:: 1.0.3
        Filenames are encoded with ASCII instead of Latin-1 for broader
        compatibility with WSGI servers.

    .. versionchanged:: 1.0
        UTF-8 filenames, as specified in `RFC 2231`_, are supported.

    .. _RFC 2231: https://tools.ietf.org/html/rfc2231#section-4

    .. versionchanged:: 0.12
       The filename is no longer automatically inferred from file
       objects. If you want to use automatic MIME and etag support, pass
       a filename via ``filename_or_fp`` or ``attachment_filename``.

    .. versionchanged:: 0.12
       ``attachment_filename`` is preferred over ``filename`` for MIME
       detection.

    .. versionchanged:: 0.9
       ``cache_timeout`` defaults to
       :meth:`Flask.get_send_file_max_age`.

    .. versionchanged:: 0.7
       MIME guessing and etag support for file-like objects was
       deprecated because it was unreliable. Pass a filename if you are
       able to, otherwise attach an etag yourself. This functionality
       will be removed in Flask 1.0.

    .. versionadded:: 0.5
       The ``add_etags``, ``cache_timeout`` and ``conditional``
       parameters were added. The default behavior is to add etags.

    .. versionadded:: 0.2

    :param filename_or_fp: The filename of the file to send, relative to
        :attr:`~Flask.root_path` if a relative path is specified.
        Alternatively, a file-like object opened in binary mode. Make
        sure the file pointer is seeked to the start of the data.
        ``X-Sendfile`` will only be used with filenames.
    :param mimetype: the mimetype of the file if provided. If a file path is
                     given, auto detection happens as fallback, otherwise an
                     error will be raised.
    :param as_attachment: set to ``True`` if you want to send this file with
                          a ``Content-Disposition: attachment`` header.
    :param attachment_filename: the filename for the attachment if it
                                differs from the file's filename.
    :param add_etags: set to ``False`` to disable attaching of etags.
    :param conditional: set to ``True`` to enable conditional responses.

    :param cache_timeout: the timeout in seconds for the headers. When ``None``
                          (default), this value is set by
                          :meth:`~Flask.get_send_file_max_age` of
                          :data:`~flask.current_app`.
    :param last_modified: set the ``Last-Modified`` header to this value,
        a :class:`~datetime.datetime` or timestamp.
        If a file was passed, this overrides its mtime.
    """
    mtime = None
    fsize = None

    if hasattr(filename_or_fp, "__fspath__"):
        filename_or_fp = os.fspath(filename_or_fp)

    if isinstance(filename_or_fp, str):
        filename = filename_or_fp
        if not os.path.isabs(filename):
            filename = os.path.join(current_app.root_path, filename)
        file = None
        if attachment_filename is None:
            attachment_filename = os.path.basename(filename)
    else:
        file = filename_or_fp
        filename = None

    if mimetype is None:
        if attachment_filename is not None:
            mimetype = (mimetypes.guess_type(attachment_filename)[0]
                        or "application/octet-stream")

        if mimetype is None:
            raise ValueError(
                "Unable to infer MIME-type because no filename is available. "
                "Please set either `attachment_filename`, pass a filepath to "
                "`filename_or_fp` or set your own MIME-type via `mimetype`.")

    headers = Headers()
    if as_attachment:
        if attachment_filename is None:
            raise TypeError(
                "filename unavailable, required for sending as attachment")

        if not isinstance(attachment_filename, str):
            attachment_filename = attachment_filename.decode("utf-8")

        try:
            attachment_filename = attachment_filename.encode("ascii")
        except UnicodeEncodeError:
            quoted = url_quote(attachment_filename, safe="")
            filenames = {
                "filename":
                unicodedata.normalize("NFKD", attachment_filename).encode(
                    "ascii", "ignore"),
                "filename*":
                f"UTF-8''{quoted}",
            }
        else:
            filenames = {"filename": attachment_filename}

        headers.add("Content-Disposition", "attachment", **filenames)

    if current_app.use_x_sendfile and filename:
        if file is not None:
            file.close()

        headers["X-Sendfile"] = filename
        fsize = os.path.getsize(filename)
        data = None
    else:
        if file is None:
            file = open(filename, "rb")
            mtime = os.path.getmtime(filename)
            fsize = os.path.getsize(filename)
        elif isinstance(file, io.BytesIO):
            fsize = file.getbuffer().nbytes
        elif isinstance(file, io.TextIOBase):
            raise ValueError(
                "Files must be opened in binary mode or use BytesIO.")

        data = wrap_file(request.environ, file)

    if fsize is not None:
        headers["Content-Length"] = fsize

    rv = current_app.response_class(data,
                                    mimetype=mimetype,
                                    headers=headers,
                                    direct_passthrough=True)

    if last_modified is not None:
        rv.last_modified = last_modified
    elif mtime is not None:
        rv.last_modified = mtime

    rv.cache_control.public = True
    if cache_timeout is None:
        cache_timeout = current_app.get_send_file_max_age(filename)
    if cache_timeout is not None:
        rv.cache_control.max_age = cache_timeout
        rv.expires = int(time() + cache_timeout)

    if add_etags and filename is not None:
        from warnings import warn

        try:
            check = (adler32(
                filename.encode("utf-8") if isinstance(filename, str
                                                       ) else filename)
                     & 0xFFFFFFFF)
            rv.set_etag(
                f"{os.path.getmtime(filename)}-{os.path.getsize(filename)}-{check}"
            )
        except OSError:
            warn(
                f"Access {filename} failed, maybe it does not exist, so"
                " ignore etags in headers",
                stacklevel=2,
            )

    if conditional:
        try:
            rv = rv.make_conditional(request,
                                     accept_ranges=True,
                                     complete_length=fsize)
        except RequestedRangeNotSatisfiable:
            if file is not None:
                file.close()
            raise
        # make sure we don't send x-sendfile for servers that
        # ignore the 304 status code for x-sendfile.
        if rv.status_code == 304:
            rv.headers.pop("x-sendfile", None)
    return rv
    def wsd_upload_file(self,
                        upload,
                        alt='File',
                        filename=None,
                        is_image=False,
                        **post_data):
        Attachments = request.env['ir.attachment'].sudo()
        attachment_data = {
            'name': alt,
            # TODO: How to use file type checking for case 'upload'?
            'datas_fname': filename or 'upload',
            'public': False,
        }

        if post_data.get('request_id'):
            try:
                attachment_data['res_id'] = int(post_data.get('request_id'))
            except (ValueError, TypeError):
                _logger.debug("Cannon convert request_id %r",
                              post_data.get('request_id'),
                              exc_info=True)
            else:
                attachment_data['res_model'] = 'request.request'

        # Check max filesize and return error if file is too big
        upload.seek(0, os.SEEK_END)
        file_size = upload.tell()
        max_size = self._get_max_upload_size()
        if max_size and file_size > max_size:
            _logger.warning("File size is too big: %s > %s", file_size,
                            max_size)
            return json.dumps({
                'status': 'FAIL',
                'success': False,
                'message': _("File size is too big!"),
            })
        upload.seek(0, os.SEEK_SET)

        try:
            data = upload.read()

            if is_image:
                data = self._optimize_image(data, disable_optimization=False)

            attachment = Attachments.create(
                dict(
                    attachment_data,
                    datas=base64.b64encode(data),
                ))
        except Exception as e:
            _logger.exception("Failed to upload file to attachment")
            message = ustr(e)
            return json.dumps({
                'status': 'FAIL',
                'success': False,
                'message': message,
            })

        attachment.generate_access_token()
        if is_image:
            attachment_url = "%s?access_token=%s" % (
                url_quote("/web/image/%d/%s" %
                          (attachment.id, attachment.datas_fname)),
                attachment.sudo().access_token,
            )
        else:
            attachment_url = "%s?access_token=%s&download" % (
                url_quote("/web/content/%d/%s" %
                          (attachment.id, attachment.datas_fname)),
                attachment.sudo().access_token,
            )

        return json.dumps({
            'status': 'OK',
            'success': True,
            'attachment_url': attachment_url,
        })
Beispiel #56
0
 def test_bytes_unquoting(self):
     self.assert_strict_equal(
         urls.url_unquote(urls.url_quote(u'#%="\xf6', charset='latin1'),
                          charset=None), b'#%="\xf6')
Beispiel #57
0
 def quote(self, value):
     if self.has_slug:
         return self.model.slug.slugify(value)
     else:
         return url_quote(value)
Beispiel #58
0
    def record_to_html(self, record, field_name, options):
        assert options['tagName'] != 'img',\
            "Oddly enough, the root tag of an image field can not be img. " \
            "That is because the image goes into the tag, or it gets the " \
            "hose again."

        if options.get('qweb_img_raw_data', False):
            return super(Image, self).record_to_html(record, field_name,
                                                     options)

        aclasses = ['img', 'img-fluid'] if options.get('qweb_img_responsive',
                                                       True) else ['img']
        aclasses += options.get('class', '').split()
        classes = ' '.join(map(escape, aclasses))

        max_size = None
        if options.get('resize'):
            max_size = options.get('resize')
        else:
            max_width, max_height = options.get('max_width', 0), options.get(
                'max_height', 0)
            if max_width or max_height:
                max_size = '%sx%s' % (max_width, max_height)

        sha = hashlib.sha1(
            str(getattr(record,
                        '__last_update')).encode('utf-8')).hexdigest()[0:7]
        max_size = '' if max_size is None else '/%s' % max_size

        if options.get('filename-field') and getattr(
                record, options['filename-field'], None):
            filename = record[options['filename-field']]
        elif options.get('filename'):
            filename = options['filename']
        else:
            filename = record.display_name
        filename = filename.replace('/', '-').replace('\\', '-')

        src = '/web/image/%s/%s/%s%s/%s?unique=%s' % (
            record._name, record.id, options.get('preview_image', field_name),
            max_size, url_quote(filename), sha)

        if options.get('alt-field') and getattr(record, options['alt-field'],
                                                None):
            alt = escape(record[options['alt-field']])
        elif options.get('alt'):
            alt = options['alt']
        else:
            alt = escape(record.display_name)

        src_zoom = None
        if options.get('zoom') and getattr(record, options['zoom'], None):
            src_zoom = '/web/image/%s/%s/%s%s/%s?unique=%s' % (
                record._name, record.id, options['zoom'], max_size,
                url_quote(filename), sha)
        elif options.get('zoom'):
            src_zoom = options['zoom']

        itemprop = None
        if options.get('itemprop'):
            itemprop = options['itemprop']

        atts = OrderedDict()
        atts["src"] = src
        atts["itemprop"] = itemprop
        atts["class"] = classes
        atts["style"] = options.get('style')
        atts["alt"] = alt
        atts["data-zoom"] = src_zoom and u'1' or None
        atts["data-zoom-image"] = src_zoom
        atts["data-no-post-process"] = options.get('data-no-post-process')

        atts = self.env['ir.qweb']._post_processing_att(
            'img', atts, options.get('template_options'))

        img = ['<img']
        for name, value in atts.items():
            if value:
                img.append(' ')
                img.append(escape(pycompat.to_text(name)))
                img.append('="')
                img.append(escape(pycompat.to_text(value)))
                img.append('"')
        img.append('/>')

        return u''.join(img)
Beispiel #59
0
 def _encode(self, key):
     """
     we need to get rid of slashes in revids because we put them into URLs
     and it would confuse the URL routing.
     """
     return url_quote(key, safe='')
    def stream_individual_file(self, filesystem_path):
        """
        Return a flask response that's streaming the download of an individual file, and gzip
        compressing it if the browser supports it.
        """
        use_gzip = self.should_use_gzip()

        # gzip compress the individual file, if it hasn't already been compressed
        if use_gzip:
            if filesystem_path not in self.gzip_individual_files:
                self.gzip_files.append(
                    tempfile.NamedTemporaryFile(
                        "wb+", dir=self.common.build_tmp_dir()))
                gzip_file = self.gzip_files[-1]
                self._gzip_compress(filesystem_path, gzip_file.name, 6, None)
                self.gzip_individual_files[filesystem_path] = gzip_file.name

                # Cleanup this temp file
                self.web.cleanup_tempfiles.append(gzip_file)

            file_to_download = self.gzip_individual_files[filesystem_path]
            filesize = os.path.getsize(
                self.gzip_individual_files[filesystem_path])
        else:
            file_to_download = filesystem_path
            filesize = os.path.getsize(filesystem_path)

        path = request.path

        # Tell GUI the individual file started
        history_id = self.cur_history_id
        self.cur_history_id += 1

        self.web.add_request(
            self.web.REQUEST_INDIVIDUAL_FILE_STARTED,
            path,
            {
                "id": history_id,
                "filesize": filesize
            },
        )

        def generate():
            chunk_size = 102400  # 100kb

            fp = open(file_to_download, "rb")
            done = False
            while not done:
                chunk = fp.read(chunk_size)
                if chunk == b"":
                    done = True
                else:
                    try:
                        yield chunk

                        # Tell GUI the progress
                        downloaded_bytes = fp.tell()
                        percent = (1.0 * downloaded_bytes / filesize) * 100
                        if (not self.web.is_gui
                                or self.common.platform == "Linux"
                                or self.common.platform == "BSD"):
                            sys.stdout.write(
                                "\r{0:s}, {1:.2f}%          ".format(
                                    self.common.human_readable_filesize(
                                        downloaded_bytes),
                                    percent,
                                ))
                            sys.stdout.flush()

                        self.web.add_request(
                            self.web.REQUEST_INDIVIDUAL_FILE_PROGRESS,
                            path,
                            {
                                "id": history_id,
                                "bytes": downloaded_bytes,
                                "filesize": filesize,
                            },
                        )
                        done = False
                    except Exception:
                        # Looks like the download was canceled
                        done = True

                        # Tell the GUI the individual file was canceled
                        self.web.add_request(
                            self.web.REQUEST_INDIVIDUAL_FILE_CANCELED,
                            path,
                            {"id": history_id},
                        )

            fp.close()

            if self.common.platform != "Darwin":
                sys.stdout.write("\n")

        basename = os.path.basename(filesystem_path)

        r = Response(generate())
        if use_gzip:
            r.headers.set("Content-Encoding", "gzip")
        r.headers.set("Content-Length", filesize)
        filename_dict = {
            "filename": unidecode(basename),
            "filename*": "UTF-8''%s" % url_quote(basename),
        }
        r.headers.set("Content-Disposition", "inline", **filename_dict)
        (content_type, _) = mimetypes.guess_type(basename, strict=False)
        if content_type is not None:
            r.headers.set("Content-Type", content_type)
        return r