From dc7cf2cfdce4ed1e26035a89518c67a6bb40af54 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 14 Jun 2015 20:03:11 +0530 Subject: [PATCH] Quote variable values in url_for() --- src/calibre/srv/routes.py | 8 ++++++++ src/calibre/srv/tests/routes.py | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/calibre/srv/routes.py b/src/calibre/srv/routes.py index 6fcd767e6f..de2b2d0882 100644 --- a/src/calibre/srv/routes.py +++ b/src/calibre/srv/routes.py @@ -7,6 +7,7 @@ __license__ = 'GPL v3' __copyright__ = '2015, Kovid Goyal ' import httplib, sys, inspect, re, time, numbers, json as jsonlib +from urllib import quote as urlquote from itertools import izip from operator import attrgetter @@ -144,6 +145,13 @@ class Route(object): raise RouteError('The required variable(s) %s were not specified for the route: %s' % (','.join(not_spec), self.endpoint.route)) args = self.defaults.copy() args.update(kwargs) + def quoted(x): + if not isinstance(x, unicode) and not isinstance(x, bytes): + x = unicode(x) + if isinstance(x, unicode): + x = x.encode('utf-8') + return urlquote(x, '') + args = {k:quoted(v) for k, v in args.iteritems()} route = self.var_pat.sub(lambda m:'{%s}' % m.group(1).partition('=')[0].lstrip('+'), self.endpoint.route) return route.format(**args) diff --git a/src/calibre/srv/tests/routes.py b/src/calibre/srv/tests/routes.py index fd62a61bf5..722cb929ff 100644 --- a/src/calibre/srv/tests/routes.py +++ b/src/calibre/srv/tests/routes.py @@ -64,6 +64,10 @@ class TestRouter(BaseTest): def soak_opt(ctx, dest, rest): pass + @endpoint('/needs quoting/{x}') + def quoting(ctx, dest, x): + pass + for x in locals().itervalues(): if getattr(x, 'is_endpoint', False): router.add(x) @@ -91,3 +95,5 @@ class TestRouter(BaseTest): self.ae(ep, soak_opt), self.ae(args, ['xxx']) ep, args = find('/soak_opt/a/b') self.ae(ep, soak_opt), self.ae(args, ['a/b']) + + self.ae(router.url_for('/needs quoting', x='a/b c'), '/needs quoting/a%2Fb%20c')