From 824062778fac051658c097bdf0089e04ea661484 Mon Sep 17 00:00:00 2001 From: Mattias- Date: Tue, 24 Dec 2013 14:59:38 +0100 Subject: [PATCH] Moved unquoting of slashes in url to after routing --- werkzeug/routing.py | 1 + werkzeug/serving.py | 2 +- werkzeug/test.py | 2 +- werkzeug/testsuite/routing.py | 17 +++++++++++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/werkzeug/routing.py b/werkzeug/routing.py index 5e01468f2..7e72fe12a 100644 --- a/werkzeug/routing.py +++ b/werkzeug/routing.py @@ -834,6 +834,7 @@ def __init__(self, map): self.map = map def to_python(self, value): + value = value.replace('%2F', '/') return value def to_url(self, value): diff --git a/werkzeug/serving.py b/werkzeug/serving.py index 20664dad2..5ebc4b674 100644 --- a/werkzeug/serving.py +++ b/werkzeug/serving.py @@ -78,7 +78,7 @@ def shutdown_server(): self.server.shutdown_signal = True url_scheme = self.server.ssl_context is None and 'http' or 'https' - path_info = url_unquote(request_url.path) + path_info = url_unquote(request_url.path, unsafe='/') environ = { 'wsgi.version': (1, 0), diff --git a/werkzeug/test.py b/werkzeug/test.py index 0da052547..fd786013c 100644 --- a/werkzeug/test.py +++ b/werkzeug/test.py @@ -548,7 +548,7 @@ def get_environ(self): result.update(self.environ_base) def _path_encode(x): - return wsgi_encoding_dance(url_unquote(x, self.charset), self.charset) + return wsgi_encoding_dance(url_unquote(x, self.charset, unsafe='/'), self.charset) qs = wsgi_encoding_dance(self.query_string) diff --git a/werkzeug/testsuite/routing.py b/werkzeug/testsuite/routing.py index 4f0e238c9..1eb9b7b07 100644 --- a/werkzeug/testsuite/routing.py +++ b/werkzeug/testsuite/routing.py @@ -367,6 +367,23 @@ def test_non_string_parts(self): a = m.bind('example.com') self.assert_equal(a.build('foo', {'foo': 42}), '/42') + def test_not_unquote_slashes(self): + m = r.Map([ + r.Rule('/', endpoint='foo'), + r.Rule('/file:', endpoint='bar'), + r.Rule('//', endpoint='foobar'), + r.Rule('/mixed/', endpoint='mixed') + ]) + a = m.bind('example.com') + # %2F is a quoted / + self.assert_equal(a.match('/a%2Fb%2Fc'), ('foo', {'foo': 'a/b/c'})) + self.assert_equal(a.match('/%2Fb%2Fc'), ('foo', {'foo': '/b/c'})) + self.assert_equal(a.match('/%2Fb%2F'), ('foo', {'foo': '/b/'})) + self.assert_equal(a.match('/file:a%2Fb'), ('bar', {'bar': 'a/b'})) + self.assert_equal(a.match('/a/b/%2Fb%2F'), ('foobar', {'foo': 'a/b', 'bar': '/b/'})) + self.assert_equal(a.match('/mixed/a%2Fb/c'), ('mixed', {'mixed': 'a/b/c'})) + self.assert_equal(a.match('/mixed/%2F/%2Fa'), ('mixed', {'mixed': '///a'})) + def test_complex_routing_rules(self): m = r.Map([ r.Rule('/', endpoint='index'),