Пример #1
0
def test_iri_safe_conversion():
    strict_eq(urls.iri_to_uri(u"magnet:?foo=bar"), "magnet:?foo=bar")
    strict_eq(urls.iri_to_uri(u"itms-service://?foo=bar"), "itms-service:?foo=bar")
    strict_eq(
        urls.iri_to_uri(u"itms-service://?foo=bar", safe_conversion=True),
        "itms-service://?foo=bar",
    )
Пример #2
0
def test_iri_support():
    strict_eq(urls.uri_to_iri("http://xn--n3h.net/"), u"http://\u2603.net/")
    strict_eq(
        urls.uri_to_iri(b"http://%C3%BCser:p%C3%[email protected]/p%C3%A5th"),
        u"http://\xfcser:p\xe4ssword@\u2603.net/p\xe5th",
    )
    strict_eq(urls.iri_to_uri(u"http://☃.net/"), "http://xn--n3h.net/")
    strict_eq(
        urls.iri_to_uri(u"http://üser:pässword@☃.net/påth"),
        "http://%C3%BCser:p%C3%[email protected]/p%C3%A5th",
    )

    strict_eq(
        urls.uri_to_iri("http://test.com/%3Fmeh?foo=%26%2F"),
        u"http://test.com/%3Fmeh?foo=%26%2F",
    )

    # this should work as well, might break on 2.4 because of a broken
    # idna codec
    strict_eq(urls.uri_to_iri(b"/foo"), u"/foo")
    strict_eq(urls.iri_to_uri(u"/foo"), "/foo")

    strict_eq(
        urls.iri_to_uri(u"http://föö.com:8080/bam/baz"),
        "http://xn--f-1gaa.com:8080/bam/baz",
    )
Пример #3
0
    def __init__(self, path='/', base_url=None, query_string=None,
                 method='GET', input_stream=None, content_type=None,
                 content_length=None, errors_stream=None, multithread=False,
                 multiprocess=False, run_once=False, headers=None, data=None,
                 environ_base=None, environ_overrides=None, charset='utf-8'):
        path_s = make_literal_wrapper(path)
        if query_string is None and path_s('?') in path:
            path, query_string = path.split(path_s('?'), 1)
        self.charset = charset
        self.path = iri_to_uri(path)
        if base_url is not None:
            base_url = url_fix(iri_to_uri(base_url, charset), charset)
        self.base_url = base_url
        if isinstance(query_string, (bytes, text_type)):
            self.query_string = query_string
        else:
            if query_string is None:
                query_string = MultiDict()
            elif not isinstance(query_string, MultiDict):
                query_string = MultiDict(query_string)
            self.args = query_string
        self.method = method
        if headers is None:
            headers = Headers()
        elif not isinstance(headers, Headers):
            headers = Headers(headers)
        self.headers = headers
        if content_type is not None:
            self.content_type = content_type
        if errors_stream is None:
            errors_stream = sys.stderr
        self.errors_stream = errors_stream
        self.multithread = multithread
        self.multiprocess = multiprocess
        self.run_once = run_once
        self.environ_base = environ_base
        self.environ_overrides = environ_overrides
        self.input_stream = input_stream
        self.content_length = content_length
        self.closed = False

        if data:
            if input_stream is not None:
                raise TypeError('can\'t provide input stream and data')
            if hasattr(data, 'read'):
                data = data.read()
            if isinstance(data, text_type):
                data = data.encode(self.charset)
            if isinstance(data, bytes):
                self.input_stream = BytesIO(data)
                if self.content_length is None:
                    self.content_length = len(data)
            else:
                for key, value in _iter_data(data):
                    if isinstance(value, (tuple, dict)) or \
                       hasattr(value, 'read'):
                        self._add_file_from_data(key, value)
                    else:
                        self.form.setlistdefault(key).append(value)
Пример #4
0
 def test_iri_safe_conversion(self):
     self.assert_strict_equal(urls.iri_to_uri(u'magnet:?foo=bar'),
                              'magnet:?foo=bar')
     self.assert_strict_equal(urls.iri_to_uri(u'itms-service://?foo=bar'),
                              'itms-service:?foo=bar')
     self.assert_strict_equal(urls.iri_to_uri(u'itms-service://?foo=bar',
                                              safe_conversion=True),
                              'itms-service://?foo=bar')
Пример #5
0
def test_iri_safe_conversion():
    strict_eq(urls.iri_to_uri(u'magnet:?foo=bar'),
                             'magnet:?foo=bar')
    strict_eq(urls.iri_to_uri(u'itms-service://?foo=bar'),
                             'itms-service:?foo=bar')
    strict_eq(urls.iri_to_uri(u'itms-service://?foo=bar',
                                             safe_conversion=True),
                             'itms-service://?foo=bar')
Пример #6
0
def redirect(location, code=302):
    """Return a response object (a WSGI application) that, if called,
    redirects the client to the target location.  Supported codes are 301,
    302, 303, 305, and 307.  300 is not supported because it's not a real
    redirect and 304 because it's the answer for a request with a request
    with defined If-Modified-Since headers.

    .. versionadded:: 0.6
       The location can now be unicode strings that are encoded using
       the :func:`iri_to_uri` function.

    :param location: the location the response should redirect to.
    :param code: the redirect status code.
    """
    assert code in (301, 302, 303, 305, 307), 'invalid code'
    from werkzeug.wrappers import BaseResponse
    display_location = location
    if isinstance(location, unicode):
        from werkzeug.urls import iri_to_uri
        location = iri_to_uri(location)
    response = BaseResponse(
        '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n'
        '<title>Redirecting...</title>\n'
        '<h1>Redirecting...</h1>\n'
        '<p>You should be redirected automatically to target URL: '
        '<a href="%s">%s</a>.  If not click the link.' %
        (location, display_location), code, mimetype='text/html')
    response.headers['Location'] = location
    return response
Пример #7
0
def redirect(location, code=302):
    """Return a response object (a WSGI application) that, if called,
    redirects the client to the target location.  Supported codes are 301,
    302, 303, 305, and 307.  300 is not supported because it's not a real
    redirect and 304 because it's the answer for a request with a request
    with defined If-Modified-Since headers.

    .. versionadded:: 0.6
       The location can now be a unicode string that is encoded using
       the :func:`iri_to_uri` function.

    :param location: the location the response should redirect to.
    :param code: the redirect status code. defaults to 302.
    """
    from werkzeug.wrappers import Response
    display_location = escape(location)
    if isinstance(location, text_type):
        # Safe conversion is necessary here as we might redirect
        # to a broken URI scheme (for instance itms-services).
        from werkzeug.urls import iri_to_uri
        location = iri_to_uri(location, safe_conversion=True)
    response = Response(
        '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n'
        '<title>Redirecting...</title>\n'
        '<h1>Redirecting...</h1>\n'
        '<p>You should be redirected automatically to target URL: '
        '<a href="%s">%s</a>.  If not click the link.' %
        (escape(location), display_location), code, mimetype='text/html')
    response.headers['Location'] = location
    return response
Пример #8
0
def redirect(location, code=302):
    """Return a response object (a WSGI application) that, if called,
    redirects the client to the target location.  Supported codes are 301,
    302, 303, 305, and 307.  300 is not supported because it's not a real
    redirect and 304 because it's the answer for a request with a request
    with defined If-Modified-Since headers.

    .. versionadded:: 0.6
       The location can now be a unicode string that is encoded using
       the :func:`iri_to_uri` function.

    :param location: the location the response should redirect to.
    :param code: the redirect status code. defaults to 302.
    """
    display_location = escape(location)
    if isinstance(location, str):
        location = iri_to_uri(location)
    response = Response(
        '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n'
        '<title>Redirecting...</title>\n'
        '<h1>Redirecting...</h1>\n'
        '<p>You should be redirected automatically to target URL: '
        '<a href="%s">%s</a>.  If not click the link.' %
        (escape(location), display_location), code, mimetype="text/html")
    response.headers["Location"] = location
    return response
Пример #9
0
 def process_bind_param(self, value, dialect):
     if not value:
         return value
     if isinstance(value, str):
         value = value.decode('utf-8')
     # TODO: Ensure NFC order.
     value = iri_to_uri(value)
     return value
Пример #10
0
    def test_iri_support(self):
        self.assert_raises(UnicodeError, urls.uri_to_iri, u'http://föö.com/')
        self.assert_raises(UnicodeError, urls.iri_to_uri, 'http://föö.com/')
        assert urls.uri_to_iri('http://xn--n3h.net/') == u'http://\u2603.net/'
        assert urls.uri_to_iri('http://%C3%BCser:p%C3%[email protected]/p%C3%A5th') == \
            u'http://\xfcser:p\xe4ssword@\u2603.net/p\xe5th'
        assert urls.iri_to_uri(u'http://☃.net/') == 'http://xn--n3h.net/'
        assert urls.iri_to_uri(u'http://üser:pässword@☃.net/påth') == \
            'http://%C3%BCser:p%C3%[email protected]/p%C3%A5th'

        assert urls.uri_to_iri('http://test.com/%3Fmeh?foo=%26%2F') == \
            u'http://test.com/%3Fmeh?foo=%26%2F'

        # this should work as well, might break on 2.4 because of a broken
        # idna codec
        assert urls.uri_to_iri('/foo') == u'/foo'
        assert urls.iri_to_uri(u'/foo') == '/foo'
Пример #11
0
def redirect(location, code = 302):
    from werkzeug.wrappers import BaseResponse
    display_location = location
    if isinstance(location, unicode):
        from werkzeug.urls import iri_to_uri
        location = iri_to_uri(location)
    response = BaseResponse('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You should be redirected automatically to target URL: <a href="%s">%s</a>.  If not click the link.' % (location, display_location), code, mimetype='text/html')
    response.headers['Location'] = location
    return response
Пример #12
0
    def __init__(self, location, code=302):
        self.display_location = location
        if isinstance(location, unicode):
            from werkzeug.urls import iri_to_uri

            location = iri_to_uri(location)
        self.location = location
        self.code = code
        self.response = self._get_response()
Пример #13
0
def _redirect_to_nginx(location):
    """This creates an internal redirection to a specified location.

    This feature is only supported by nginx. See http://wiki.nginx.org/X-accel
    for more information about it.
    """
    response = Response(status=200)
    location = iri_to_uri(location, safe_conversion=True)
    response.headers['X-Accel-Redirect'] = location
    return response
Пример #14
0
    def test_iri_support(self):
        self.assert_raises(UnicodeError, urls.uri_to_iri, u"http://föö.com/")
        self.assert_raises(UnicodeError, urls.iri_to_uri, "http://föö.com/")
        assert urls.uri_to_iri("http://xn--n3h.net/") == u"http://\u2603.net/"
        assert (
            urls.uri_to_iri("http://%C3%BCser:p%C3%[email protected]/p%C3%A5th")
            == u"http://\xfcser:p\xe4ssword@\u2603.net/p\xe5th"
        )
        assert urls.iri_to_uri(u"http://☃.net/") == "http://xn--n3h.net/"
        assert (
            urls.iri_to_uri(u"http://üser:pässword@☃.net/påth")
            == "http://%C3%BCser:p%C3%[email protected]/p%C3%A5th"
        )

        assert urls.uri_to_iri("http://test.com/%3Fmeh?foo=%26%2F") == u"http://test.com/%3Fmeh?foo=%26%2F"

        # this should work as well, might break on 2.4 because of a broken
        # idna codec
        assert urls.uri_to_iri("/foo") == u"/foo"
        assert urls.iri_to_uri(u"/foo") == "/foo"
Пример #15
0
def test_uri_iri_normalization():
    uri = "http://xn--f-rgao.com/%E2%98%90/fred?utf8=%E2%9C%93"
    iri = u"http://föñ.com/\N{BALLOT BOX}/fred?utf8=\u2713"

    tests = [
        u"http://föñ.com/\N{BALLOT BOX}/fred?utf8=\u2713",
        u"http://xn--f-rgao.com/\u2610/fred?utf8=\N{CHECK MARK}",
        b"http://xn--f-rgao.com/%E2%98%90/fred?utf8=%E2%9C%93",
        u"http://xn--f-rgao.com/%E2%98%90/fred?utf8=%E2%9C%93",
        u"http://föñ.com/\u2610/fred?utf8=%E2%9C%93",
        b"http://xn--f-rgao.com/\xe2\x98\x90/fred?utf8=\xe2\x9c\x93",
    ]

    for test in tests:
        assert urls.uri_to_iri(test) == iri
        assert urls.iri_to_uri(test) == uri
        assert urls.uri_to_iri(urls.iri_to_uri(test)) == iri
        assert urls.iri_to_uri(urls.uri_to_iri(test)) == uri
        assert urls.uri_to_iri(urls.uri_to_iri(test)) == iri
        assert urls.iri_to_uri(urls.iri_to_uri(test)) == uri
Пример #16
0
    def test_uri_iri_normalization(self):
        uri = 'http://xn--f-rgao.com/%E2%98%90/fred?utf8=%E2%9C%93'
        iri = u'http://föñ.com/\N{BALLOT BOX}/fred?utf8=\u2713'

        tests = [
            u'http://föñ.com/\N{BALLOT BOX}/fred?utf8=\u2713',
            u'http://xn--f-rgao.com/\u2610/fred?utf8=\N{CHECK MARK}',
            b'http://xn--f-rgao.com/%E2%98%90/fred?utf8=%E2%9C%93',
            u'http://xn--f-rgao.com/%E2%98%90/fred?utf8=%E2%9C%93',
            u'http://föñ.com/\u2610/fred?utf8=%E2%9C%93',
            b'http://xn--f-rgao.com/\xe2\x98\x90/fred?utf8=\xe2\x9c\x93',
        ]

        for test in tests:
            self.assert_equal(urls.uri_to_iri(test), iri)
            self.assert_equal(urls.iri_to_uri(test), uri)
            self.assert_equal(urls.uri_to_iri(urls.iri_to_uri(test)), iri)
            self.assert_equal(urls.iri_to_uri(urls.uri_to_iri(test)), uri)
            self.assert_equal(urls.uri_to_iri(urls.uri_to_iri(test)), iri)
            self.assert_equal(urls.iri_to_uri(urls.iri_to_uri(test)), uri)
Пример #17
0
    def test_iri_support(self):
        self.assert_strict_equal(urls.uri_to_iri('http://xn--n3h.net/'),
                          u'http://\u2603.net/')
        self.assert_strict_equal(
            urls.uri_to_iri(b'http://%C3%BCser:p%C3%[email protected]/p%C3%A5th'),
                            u'http://\xfcser:p\xe4ssword@\u2603.net/p\xe5th')
        self.assert_strict_equal(urls.iri_to_uri(u'http://☃.net/'), 'http://xn--n3h.net/')
        self.assert_strict_equal(
            urls.iri_to_uri(u'http://üser:pässword@☃.net/påth'),
                            'http://%C3%BCser:p%C3%[email protected]/p%C3%A5th')

        self.assert_strict_equal(urls.uri_to_iri('http://test.com/%3Fmeh?foo=%26%2F'),
                                          u'http://test.com/%3Fmeh?foo=%26%2F')

        # this should work as well, might break on 2.4 because of a broken
        # idna codec
        self.assert_strict_equal(urls.uri_to_iri(b'/foo'), u'/foo')
        self.assert_strict_equal(urls.iri_to_uri(u'/foo'), '/foo')

        self.assert_strict_equal(urls.iri_to_uri(u'http://föö.com:8080/bam/baz'),
                          'http://xn--f-1gaa.com:8080/bam/baz')
Пример #18
0
    def _error_common(template, template_modal, code, e):
        # g.is_ajax здесь не всегда присутствует, так что так
        is_ajax = request.headers.get('X-AJAX') == '1' or request.args.get('isajax') == '1'
        if is_ajax:
            html = render_template(template_modal, error=e, error_code=code)
            response = jsonify({'page_content': {'modal': html}})
            response.status_code = code
            # for github-fetch polyfill:
            response.headers['X-Request-URL'] = iri_to_uri(request.url)
            return response

        html = render_template(template, error=e, error_code=code)
        return html, code
Пример #19
0
    def get_wsgi_headers(self, environ):
        headers = Headers(self.headers)
        location = headers.get('location')
        if location is not None:
            if isinstance(location, unicode):
                location = iri_to_uri(location)
            headers['Location'] = urlparse.urljoin(get_current_url(environ, root_only=True), location)
        content_location = headers.get('content-location')
        if content_location is not None and isinstance(content_location, unicode):
            headers['Content-Location'] = iri_to_uri(content_location)
        if 100 <= self.status_code < 200 or self.status_code == 204:
            headers['Content-Length'] = '0'
        elif self.status_code == 304:
            remove_entity_headers(headers)
        if self.is_sequence and 'content-length' not in self.headers:
            try:
                content_length = sum((len(str(x)) for x in self.response))
            except UnicodeError:
                pass
            else:
                headers['Content-Length'] = str(content_length)

        return headers
Пример #20
0
def redirect(location, status=302):
    """
    which is seldom used in api server
    """
    from werkzeug.wrappers import Response
    from werkzeug.urls import iri_to_uri
    location = iri_to_uri(location, safe_conversion=True)
    return Response(
            "<!DOCTYPE html>\
                <html>\
                    <h1>Redirecting...</h1>\
                    <a href='{0}'>touch this to make manually redirection</a>\
                </html>"
            .format(location), status=status, headers={'Location': location})
Пример #21
0
def handle_get(path):
    """
    Handle the GET
    """
    path = '/api' + iri_to_uri(request.url).partition('/api')[-1]
    if path == '/api':
        abort(400)
    logging.debug('Received %s', path)
    dump = session.get(path)
    logging.debug('From Fake APIC: %s', dump.json())
    response = json.dumps(dump.json(), indent=4, separators=(',', ':'))
    failure_hdlr.enforce_delay()
    if failure_hdlr.enforce_connection_failure():
        abort(400)
    return response
Пример #22
0
def get_page(path=''):
    path = Page.strip_path(path)
    page = page_service.get_page_by_path(path)

    if not page:
        # Try if this might be a redirect.
        redirection = Redirect.query.filter(Redirect.fro == path).first()
        if redirection:

            # get GET parameters so they can be applied to the redirected
            # URL
            if request.args:
                redir_url = redirection.to + '?'
                for key in request.args:
                    redir_url += key + '=' + \
                        request.args[key] + '&'

                # this is necssary to prevent incorrect escaping
                return redirect(iri_to_uri(redir_url))

            return redirect(redirection.to)

        return abort(404)

    if not page_service.can_user_read_page(page, current_user):
        return abort(403)

    revision = page.get_latest_revision()

    if not revision:
        return abort(500)

    # Check if the current user has already entered data in this custom
    # form
    if getattr(revision, 'custom_form', False):
        if current_user.is_authenticated and current_user.has_paid:
            all_form_results = CustomFormResult.query \
                .filter(CustomFormResult.form_id == revision.custom_form.id)
            form_result = all_form_results \
                .filter(CustomFormResult.owner_id == current_user.id).first()

            if form_result:
                revision.custom_form_data = form_result.data.replace('"', "'")
    can_write = role_service.user_has_role(current_user, Roles.PAGE_WRITE)
    return render_template('%s/view_single.htm' % (page.type), page=page,
                           revision=revision, title=revision.title,
                           context=revision.__class__.context,
                           can_write=can_write)
Пример #23
0
 def ajax_template_response(response):
     if response.headers.get('Vary'):
         response.headers['Vary'] = 'X-AJAX, ' + response.headers['Vary']
     else:
         response.headers['Vary'] = 'X-AJAX'
     if not getattr(g, 'is_ajax', False):
         return response
     if not response.direct_passthrough and response.data and response.data.startswith(b'{') and response.content_type == 'text/html; charset=utf-8':
         response.content_type = 'application/json'
         # for github-fetch polyfill:
         response.headers['X-Request-URL'] = iri_to_uri(request.url)
     elif response.status_code == 302:
         # Люблю разрабов js во всех смыслах
         response.data = flask_json.dumps({'page_content': {'redirect': response.headers.get('Location')}})
         response.content_type = 'application/json'
         response.status_code = 200
     return response
Пример #24
0
def short_url(id):
    context['short_url'] = id
    get_long_url()

    if context['long_url']:
        if context['json'] == True:
            return jsonify(long_url=context['long_url'], short_url= \
                           request.url_root + context['short_url'])

        if context['direct_redirect']:
            return redirect(iri_to_uri(context['long_url']))
        else:
            return render_template('show.html', long_url=context['long_url'], \
                                   short_url=request.url_root+context['short_url'])
    else:
        if context['json'] == True:
            return jsonify(error='404')
        abort(404)
Пример #25
0
def test_my_api():
    protcol = 'http://'
    domain = u'ほげ.com'
    query = u'?q=ふが'

    url = protcol + domain
    # idna_url = protcol + domain.encode('idna')
    idna_url = iri_to_uri(url)

    responses.add(responses.GET, idna_url,
                  json={"error": "not found"}, status=404)

    resp = requests.get(url)

    print resp.json()
    assert resp.json() == {"error": "not found"}

    assert len(responses.calls) == 1
    #assert responses.calls[0].request.url == url_quote(u'http://hoge?q=ぐーぐる')
    assert responses.calls[0].response.text == '{"error": "not found"}'
Пример #26
0
def get_page(path=''):
    path = Page.strip_path(path)
    page = Page.get_by_path(path)

    if not page:
        # Try if this might be a redirect.
        print("not page")
        redirection = Redirect.query.filter(Redirect.fro == path).first()
        if redirection:

            # get GET parameters so they can be applied to the redirected
            # URL
            if request.args:
                redir_url = redirection.to + '?'
                for key in request.args:
                    redir_url += key + '=' + \
                        request.args[key] + '&'
                print(redir_url)

                # this is necssary to prevent incorrect escaping
                return redirect(iri_to_uri(redir_url))

            return redirect(redirection.to)

        return abort(404)

    if not PageAPI.can_read(page):
        return abort(403)

    revision = page.get_latest_revision()

    if not revision:
        return abort(500)

    return render_template('%s/view_single.htm' % (page.type), page=page,
                           revision=revision, title=revision.title,
                           context=revision.__class__.context)
Пример #27
0
def dump_cookie(key, value='', max_age=None, expires=None, path='/',
                domain=None, secure=False, httponly=False,
                charset='utf-8', sync_expires=True):
    """Creates a new Set-Cookie header without the ``Set-Cookie`` prefix
    The parameters are the same as in the cookie Morsel object in the
    Python standard library but it accepts unicode data, too.

    On Python 3 the return value of this function will be a unicode
    string, on Python 2 it will be a native string.  In both cases the
    return value is usually restricted to ascii as the vast majority of
    values are properly escaped, but that is no guarantee.  If a unicode
    string is returned it's tunneled through latin1 as required by
    PEP 3333.

    The return value is not ASCII safe if the key contains unicode
    characters.  This is technically against the specification but
    happens in the wild.  It's strongly recommended to not use
    non-ASCII values for the keys.

    :param max_age: should be a number of seconds, or `None` (default) if
                    the cookie should last only as long as the client's
                    browser session.  Additionally `timedelta` objects
                    are accepted, too.
    :param expires: should be a `datetime` object or unix timestamp.
    :param path: limits the cookie to a given path, per default it will
                 span the whole domain.
    :param domain: Use this if you want to set a cross-domain cookie. For
                   example, ``domain=".example.com"`` will set a cookie
                   that is readable by the domain ``www.example.com``,
                   ``foo.example.com`` etc. Otherwise, a cookie will only
                   be readable by the domain that set it.
    :param secure: The cookie will only be available via HTTPS
    :param httponly: disallow JavaScript to access the cookie.  This is an
                     extension to the cookie standard and probably not
                     supported by all browsers.
    :param charset: the encoding for unicode values.
    :param sync_expires: automatically set expires if max_age is defined
                         but expires not.
    """
    key = to_bytes(key, charset)
    value = to_bytes(value, charset)

    if path is not None:
        path = iri_to_uri(path, charset)
    domain = _make_cookie_domain(domain)
    if isinstance(max_age, timedelta):
        max_age = (max_age.days * 60 * 60 * 24) + max_age.seconds
    if expires is not None:
        if not isinstance(expires, string_types):
            expires = cookie_date(expires)
    elif max_age is not None and sync_expires:
        expires = to_bytes(cookie_date(time() + max_age))

    buf = [key + b'=' + _cookie_quote(value)]

    # XXX: In theory all of these parameters that are not marked with `None`
    # should be quoted.  Because stdlib did not quote it before I did not
    # want to introduce quoting there now.
    for k, v, q in ((b'Domain', domain, True),
                    (b'Expires', expires, False,),
                    (b'Max-Age', max_age, False),
                    (b'Secure', secure, None),
                    (b'HttpOnly', httponly, None),
                    (b'Path', path, False)):
        if q is None:
            if v:
                buf.append(k)
            continue

        if v is None:
            continue

        tmp = bytearray(k)
        if not isinstance(v, (bytes, bytearray)):
            v = to_bytes(text_type(v), charset)
        if q:
            v = _cookie_quote(v)
        tmp += b'=' + v
        buf.append(bytes(tmp))

    # The return value will be an incorrectly encoded latin1 header on
    # Python 3 for consistency with the headers object and a bytestring
    # on Python 2 because that's how the API makes more sense.
    rv = b'; '.join(buf)
    if not PY2:
        rv = rv.decode('latin1')
    return rv
Пример #28
0
def dump_cookie(key, value='', max_age=None, expires=None, path='/',
                domain=None, secure=False, httponly=False,
                charset='utf-8', sync_expires=True):
    """Creates a new Set-Cookie header without the ``Set-Cookie`` prefix
    The parameters are the same as in the cookie Morsel object in the
    Python standard library but it accepts unicode data, too.

    On Python 3 the return value of this function will be a unicode
    string, on Python 2 it will be a native string.  In both cases the
    return value is usually restricted to ascii as the vast majority of
    values are properly escaped, but that is no guarantee.  If a unicode
    string is returned it's tunneled through latin1 as required by
    PEP 3333.

    The return value is not ASCII safe if the key contains unicode
    characters.  This is technically against the specification but
    happens in the wild.  It's strongly recommended to not use
    non-ASCII values for the keys.

    :param max_age: should be a number of seconds, or `None` (default) if
                    the cookie should last only as long as the client's
                    browser session.  Additionally `timedelta` objects
                    are accepted, too.
    :param expires: should be a `datetime` object or unix timestamp.
    :param path: limits the cookie to a given path, per default it will
                 span the whole domain.
    :param domain: Use this if you want to set a cross-domain cookie. For
                   example, ``domain=".example.com"`` will set a cookie
                   that is readable by the domain ``www.example.com``,
                   ``foo.example.com`` etc. Otherwise, a cookie will only
                   be readable by the domain that set it.
    :param secure: The cookie will only be available via HTTPS
    :param httponly: disallow JavaScript to access the cookie.  This is an
                     extension to the cookie standard and probably not
                     supported by all browsers.
    :param charset: the encoding for unicode values.
    :param sync_expires: automatically set expires if max_age is defined
                         but expires not.
    """
    key = to_bytes(key, charset)
    value = to_bytes(value, charset)

    if path is not None:
        path = iri_to_uri(path, charset)
    domain = _make_cookie_domain(domain)
    if isinstance(max_age, timedelta):
        max_age = (max_age.days * 60 * 60 * 24) + max_age.seconds
    if expires is not None:
        if not isinstance(expires, string_types):
            expires = cookie_date(expires)
    elif max_age is not None and sync_expires:
        expires = to_bytes(cookie_date(time() + max_age))

    buf = [key + b'=' + _cookie_quote(value)]

    # XXX: In theory all of these parameters that are not marked with `None`
    # should be quoted.  Because stdlib did not quote it before I did not
    # want to introduce quoting there now.
    for k, v, q in ((b'Domain', domain, True),
                    (b'Expires', expires, False,),
                    (b'Max-Age', max_age, False),
                    (b'Secure', secure, None),
                    (b'HttpOnly', httponly, None),
                    (b'Path', path, False)):
        if q is None:
            if v:
                buf.append(k)
            continue

        if v is None:
            continue

        tmp = bytearray(k)
        if not isinstance(v, (bytes, bytearray)):
            v = to_bytes(text_type(v), charset)
        if q:
            v = _cookie_quote(v)
        tmp += b'=' + v
        buf.append(bytes(tmp))

    # The return value will be an incorrectly encoded latin1 header on
    # Python 3 for consistency with the headers object and a bytestring
    # on Python 2 because that's how the API makes more sense.
    rv = b'; '.join(buf)
    if not PY2:
        rv = rv.decode('latin1')
    return rv
Пример #29
0
def test_quoting_of_local_urls():
    """Make sure that urls without domain quote correctly."""
    rv = iri_to_uri(u'/foo\x8f')
    assert rv == '/foo%C2%8F'
    assert type(rv) is str
Пример #30
0
def dump_cookie(key, value='', max_age=None, expires=None, path='/',
                domain=None, secure=False, httponly=False,
                charset='utf-8', sync_expires=True, max_size=4093,
                samesite=None):
    """Creates a new Set-Cookie header without the ``Set-Cookie`` prefix
    The parameters are the same as in the cookie Morsel object in the
    Python standard library but it accepts unicode data, too.

    On Python 3 the return value of this function will be a unicode
    string, on Python 2 it will be a native string.  In both cases the
    return value is usually restricted to ascii as the vast majority of
    values are properly escaped, but that is no guarantee.  If a unicode
    string is returned it's tunneled through latin1 as required by
    PEP 3333.

    The return value is not ASCII safe if the key contains unicode
    characters.  This is technically against the specification but
    happens in the wild.  It's strongly recommended to not use
    non-ASCII values for the keys.

    :param max_age: should be a number of seconds, or `None` (default) if
                    the cookie should last only as long as the client's
                    browser session.  Additionally `timedelta` objects
                    are accepted, too.
    :param expires: should be a `datetime` object or unix timestamp.
    :param path: limits the cookie to a given path, per default it will
                 span the whole domain.
    :param domain: Use this if you want to set a cross-domain cookie. For
                   example, ``domain=".example.com"`` will set a cookie
                   that is readable by the domain ``www.example.com``,
                   ``foo.example.com`` etc. Otherwise, a cookie will only
                   be readable by the domain that set it.
    :param secure: The cookie will only be available via HTTPS
    :param httponly: disallow JavaScript to access the cookie.  This is an
                     extension to the cookie standard and probably not
                     supported by all browsers.
    :param charset: the encoding for unicode values.
    :param sync_expires: automatically set expires if max_age is defined
                         but expires not.
    :param max_size: Warn if the final header value exceeds this size. The
        default, 4093, should be safely `supported by most browsers
        <cookie_>`_. Set to 0 to disable this check.
    :param samesite: Limits the scope of the cookie such that it will only
                     be attached to requests if those requests are "same-site".

    .. _`cookie`: http://browsercookielimits.squawky.net/
    """
    key = to_bytes(key, charset)
    value = to_bytes(value, charset)

    if path is not None:
        path = iri_to_uri(path, charset)
    domain = _make_cookie_domain(domain)
    if isinstance(max_age, timedelta):
        max_age = (max_age.days * 60 * 60 * 24) + max_age.seconds
    if expires is not None:
        if not isinstance(expires, string_types):
            expires = cookie_date(expires)
    elif max_age is not None and sync_expires:
        expires = to_bytes(cookie_date(time() + max_age))

    samesite = samesite.title() if samesite else None
    if samesite not in ('Strict', 'Lax', None):
        raise ValueError("invalid SameSite value; must be 'Strict', 'Lax' or None")

    buf = [key + b'=' + _cookie_quote(value)]

    # XXX: In theory all of these parameters that are not marked with `None`
    # should be quoted.  Because stdlib did not quote it before I did not
    # want to introduce quoting there now.
    for k, v, q in ((b'Domain', domain, True),
                    (b'Expires', expires, False,),
                    (b'Max-Age', max_age, False),
                    (b'Secure', secure, None),
                    (b'HttpOnly', httponly, None),
                    (b'Path', path, False),
                    (b'SameSite', samesite, False)):
        if q is None:
            if v:
                buf.append(k)
            continue

        if v is None:
            continue

        tmp = bytearray(k)
        if not isinstance(v, (bytes, bytearray)):
            v = to_bytes(text_type(v), charset)
        if q:
            v = _cookie_quote(v)
        tmp += b'=' + v
        buf.append(bytes(tmp))

    # The return value will be an incorrectly encoded latin1 header on
    # Python 3 for consistency with the headers object and a bytestring
    # on Python 2 because that's how the API makes more sense.
    rv = b'; '.join(buf)
    if not PY2:
        rv = rv.decode('latin1')

    # Warn if the final value of the cookie is less than the limit. If the
    # cookie is too large, then it may be silently ignored, which can be quite
    # hard to debug.
    cookie_size = len(rv)

    if max_size and cookie_size > max_size:
        value_size = len(value)
        warnings.warn(
            'The "{key}" cookie is too large: the value was {value_size} bytes'
            ' but the header required {extra_size} extra bytes. The final size'
            ' was {cookie_size} bytes but the limit is {max_size} bytes.'
            ' Browsers may silently ignore cookies larger than this.'.format(
                key=key,
                value_size=value_size,
                extra_size=cookie_size - value_size,
                cookie_size=cookie_size,
                max_size=max_size
            ),
            stacklevel=2
        )

    return rv
Пример #31
0
 def safe_url(self):
     """ Encoded URL as string rather than unicode. """
     return iri_to_uri(self.submitted_url)
Пример #32
0
def dump_cookie(key,
                value='',
                max_age=None,
                expires=None,
                path='/',
                domain=None,
                secure=False,
                httponly=False,
                charset='utf-8',
                sync_expires=True,
                max_size=4093,
                samesite=None):
    """Creates a new Set-Cookie header without the ``Set-Cookie`` prefix
    The parameters are the same as in the cookie Morsel object in the
    Python standard library but it accepts unicode data, too.

    On Python 3 the return value of this function will be a unicode
    string, on Python 2 it will be a native string.  In both cases the
    return value is usually restricted to ascii as the vast majority of
    values are properly escaped, but that is no guarantee.  If a unicode
    string is returned it's tunneled through latin1 as required by
    PEP 3333.

    The return value is not ASCII safe if the key contains unicode
    characters.  This is technically against the specification but
    happens in the wild.  It's strongly recommended to not use
    non-ASCII values for the keys.

    :param max_age: should be a number of seconds, or `None` (default) if
                    the cookie should last only as long as the client's
                    browser session.  Additionally `timedelta` objects
                    are accepted, too.
    :param expires: should be a `datetime` object or unix timestamp.
    :param path: limits the cookie to a given path, per default it will
                 span the whole domain.
    :param domain: Use this if you want to set a cross-domain cookie. For
                   example, ``domain=".example.com"`` will set a cookie
                   that is readable by the domain ``www.example.com``,
                   ``foo.example.com`` etc. Otherwise, a cookie will only
                   be readable by the domain that set it.
    :param secure: The cookie will only be available via HTTPS
    :param httponly: disallow JavaScript to access the cookie.  This is an
                     extension to the cookie standard and probably not
                     supported by all browsers.
    :param charset: the encoding for unicode values.
    :param sync_expires: automatically set expires if max_age is defined
                         but expires not.
    :param max_size: Warn if the final header value exceeds this size. The
        default, 4093, should be safely `supported by most browsers
        <cookie_>`_. Set to 0 to disable this check.
    :param samesite: Limits the scope of the cookie such that it will only
                     be attached to requests if those requests are "same-site".

    .. _`cookie`: http://browsercookielimits.squawky.net/
    """
    key = to_bytes(key, charset)
    value = to_bytes(value, charset)

    if path is not None:
        path = iri_to_uri(path, charset)
    domain = _make_cookie_domain(domain)
    if isinstance(max_age, timedelta):
        max_age = (max_age.days * 60 * 60 * 24) + max_age.seconds
    if expires is not None:
        if not isinstance(expires, string_types):
            expires = cookie_date(expires)
    elif max_age is not None and sync_expires:
        expires = to_bytes(cookie_date(time() + max_age))

    samesite = samesite.title() if samesite else None
    if samesite not in ('Strict', 'Lax', None):
        raise ValueError(
            "invalid SameSite value; must be 'Strict', 'Lax' or None")

    buf = [key + b'=' + _cookie_quote(value)]

    # XXX: In theory all of these parameters that are not marked with `None`
    # should be quoted.  Because stdlib did not quote it before I did not
    # want to introduce quoting there now.
    for k, v, q in ((b'Domain', domain, True), (
            b'Expires',
            expires,
            False,
    ), (b'Max-Age', max_age, False), (b'Secure', secure,
                                      None), (b'HttpOnly', httponly, None),
                    (b'Path', path, False), (b'SameSite', samesite, False)):
        if q is None:
            if v:
                buf.append(k)
            continue

        if v is None:
            continue

        tmp = bytearray(k)
        if not isinstance(v, (bytes, bytearray)):
            v = to_bytes(text_type(v), charset)
        if q:
            v = _cookie_quote(v)
        tmp += b'=' + v
        buf.append(bytes(tmp))

    # The return value will be an incorrectly encoded latin1 header on
    # Python 3 for consistency with the headers object and a bytestring
    # on Python 2 because that's how the API makes more sense.
    rv = b'; '.join(buf)
    if not PY2:
        rv = rv.decode('latin1')

    # Warn if the final value of the cookie is less than the limit. If the
    # cookie is too large, then it may be silently ignored, which can be quite
    # hard to debug.
    cookie_size = len(rv)

    if max_size and cookie_size > max_size:
        value_size = len(value)
        warnings.warn(
            'The "{key}" cookie is too large: the value was {value_size} bytes'
            ' but the header required {extra_size} extra bytes. The final size'
            ' was {cookie_size} bytes but the limit is {max_size} bytes.'
            ' Browsers may silently ignore cookies larger than this.'.format(
                key=key,
                value_size=value_size,
                extra_size=cookie_size - value_size,
                cookie_size=cookie_size,
                max_size=max_size),
            stacklevel=2)

    return rv
Пример #33
0
    def __init__(self,
                 path='/',
                 base_url=None,
                 query_string=None,
                 method='GET',
                 input_stream=None,
                 content_type=None,
                 content_length=None,
                 errors_stream=None,
                 multithread=False,
                 multiprocess=False,
                 run_once=False,
                 headers=None,
                 data=None,
                 environ_base=None,
                 environ_overrides=None,
                 charset='utf-8',
                 mimetype=None):
        path_s = make_literal_wrapper(path)
        if query_string is None and path_s('?') in path:
            path, query_string = path.split(path_s('?'), 1)
        self.charset = charset
        self.path = iri_to_uri(path)
        if base_url is not None:
            base_url = url_fix(iri_to_uri(base_url, charset), charset)
        self.base_url = base_url
        if isinstance(query_string, (bytes, text_type)):
            self.query_string = query_string
        else:
            if query_string is None:
                query_string = MultiDict()
            elif not isinstance(query_string, MultiDict):
                query_string = MultiDict(query_string)
            self.args = query_string
        self.method = method
        if headers is None:
            headers = Headers()
        elif not isinstance(headers, Headers):
            headers = Headers(headers)
        self.headers = headers
        if content_type is not None:
            self.content_type = content_type
        if errors_stream is None:
            errors_stream = sys.stderr
        self.errors_stream = errors_stream
        self.multithread = multithread
        self.multiprocess = multiprocess
        self.run_once = run_once
        self.environ_base = environ_base
        self.environ_overrides = environ_overrides
        self.input_stream = input_stream
        self.content_length = content_length
        self.closed = False

        if data:
            if input_stream is not None:
                raise TypeError('can\'t provide input stream and data')
            if hasattr(data, 'read'):
                data = data.read()
            if isinstance(data, text_type):
                data = data.encode(self.charset)
            if isinstance(data, bytes):
                self.input_stream = BytesIO(data)
                if self.content_length is None:
                    self.content_length = len(data)
            else:
                for key, value in _iter_data(data):
                    if isinstance(value, (tuple, dict)) or \
                            hasattr(value, 'read'):
                        self._add_file_from_data(key, value)
                    else:
                        self.form.setlistdefault(key).append(value)

        if mimetype is not None:
            self.mimetype = mimetype
Пример #34
0
def redirectCustom(location,
                   *render_args,
                   code=302,
                   response_cb=None,
                   force_redirect=False):
    """
    =======
    Summary
    =======

    Combines functionality of :func:`werkzeug.utils.redirect` with :func:`flask.templating.render_template`
    to allow for virtual redirection to an endpoint with any HTTP status code.\n

    =========
    Use Cases
    =========

    1. render template at a custom url (doesn't have to be an endpoint)

        def index():
            return redirectCustom('http://localhost:5000/notfound', render_template('not_found.html'), code=404)

        def index():
            html = '<h1>Are you lost {{ username }}?</h1>'
            return redirectCustom(url_for('notfound'), render_template_string(html), username='******', code=404)

    2. customizing the response before sending to the client

        def index():
            def addAuthHeaders(response):
                response.headers['Access-Control-Allow-Origin' = '*'
                response.headers['Access-Control-Allow-Headers'] = 'origin, x-requested-with, content-type'
                response.headers['Access-Control-Allow-Methods'] = 'PUT, GET, POST, DELETE, OPTIONS'
            return redirectCustom(url_for('login'), render_template('login_custom.html'), code=403, response_cb=addAuthHeaders)

    3. redirecting with a custom HTTP status code (normally restricted to 300's)

        def index():
            return redirectCustom(url_for('http://localhost:5000/error'), showError())

    4. forcing redirection when client normally would ignore location header

        def index():
            return redirectCustom(url_for(showError), showError(), code=500, force_redirect=True)


    :note: the endpoint logic is only executed when a the view function is passed in render_args
    :param location: the location the response should virtually redirect to
    :param render_args: the return value from a view / template rendering function
    :param code: the return HTTP status code, defaults to 302 like a normal redirect
    :param response_cb: callback function taking :class:`werkzeug.wrappers.Response` object as arg and returning edited response
    :param force_redirect: whether to force redirection on client, only needed when client ignores location header
    :return: client viewable :class:`werkzeug.wrappers.Response` object
    """

    display_location = escape(location)
    if isinstance(location, str):
        # Safe conversion as stated in :func:`werkzeug.utils.redirect`
        location = iri_to_uri(location, safe_conversion=True)

    # create a response object, from rendered data (accepts None)
    response = make_response(*render_args)

    # if no render_args given fill response with default redirect html
    if len(render_args) <= 0:
        response.response = '<!DOCTYPE HTML">\n' \
                            '<html><head><meta charset="utf-8"><meta http-equiv="refresh" content="0; URL={location}">' \
                            '<title>Redirecting</title></head>\n' \
                            '<body><script type="text/javascript">window.location.href={location};</script></body></html>' if force_redirect else \
            '<body><h1>Redirecting...</h1>\n' \
            '<p>You should be redirected automatically to target URL: ' \
            '<a href="{location}">{display_location}</a>.  If not click the link.</p></body></html>' \
                .format(location=escape(location), display_location=display_location)

        response.mimetype = 'text/html'

    # customize response if needed
    if response_cb is not None:
        response = response_cb(response)

    # override return code if set from render args
    # if len(render_args) == 3:
    response.status = code

    # change response location
    response.headers['Location'] = location

    return response
Пример #35
0
 def __init__(self,
              path='/',
              base_url=None,
              query_string=None,
              method='GET',
              input_stream=None,
              content_type=None,
              content_length=None,
              errors_stream=None,
              multithread=False,
              multiprocess=False,
              run_once=False,
              headers=None,
              data=None,
              environ_base=None,
              environ_overrides=None,
              charset='utf-8'):
     if query_string is None and '?' in path:
         path, query_string = path.split('?', 1)
     self.charset = charset
     if isinstance(path, unicode):
         path = iri_to_uri(path, charset)
     self.path = path
     if base_url is not None:
         if isinstance(base_url, unicode):
             base_url = iri_to_uri(base_url, charset)
         else:
             base_url = url_fix(base_url, charset)
     self.base_url = base_url
     if isinstance(query_string, basestring):
         self.query_string = query_string
     else:
         if query_string is None:
             query_string = MultiDict()
         elif not isinstance(query_string, MultiDict):
             query_string = MultiDict(query_string)
         self.args = query_string
     self.method = method
     if headers is None:
         headers = Headers()
     elif not isinstance(headers, Headers):
         headers = Headers(headers)
     self.headers = headers
     self.content_type = content_type
     if errors_stream is None:
         errors_stream = sys.stderr
     self.errors_stream = errors_stream
     self.multithread = multithread
     self.multiprocess = multiprocess
     self.run_once = run_once
     self.environ_base = environ_base
     self.environ_overrides = environ_overrides
     self.input_stream = input_stream
     self.content_length = content_length
     self.closed = False
     if data:
         if input_stream is not None:
             raise TypeError("can't provide input stream and data")
         if isinstance(data, basestring):
             self.input_stream = StringIO(data)
             if self.content_length is None:
                 self.content_length = len(data)
         else:
             for key, value in _iter_data(data):
                 if isinstance(value,
                               (tuple, dict)) or hasattr(value, 'read'):
                     self._add_file_from_data(key, value)
                 else:
                     self.form.setlistdefault(key).append(value)