templates: introduce revescape filter for escaping symbolic revisions
authorAnton Shestakov <av6@dwimlabs.net>
Sun, 12 Jul 2015 16:47:56 +0800
changeset 25778 3a33412792f1
parent 25777 1c2a8db33b8f
child 25779 cd842821db2c
templates: introduce revescape filter for escaping symbolic revisions There needs to be a way to escape symbolic revisions containing forward slashes, but urlescape filter doesn't escape slashes at all (in fact, it is used in places where forward slashes must be preserved). The filter considers @ to be safe just for bookmarks like @ and @default to look good in urls.
mercurial/hgweb/webutil.py
mercurial/templatefilters.py
--- a/mercurial/hgweb/webutil.py	Sun Jul 12 16:06:57 2015 +0800
+++ b/mercurial/hgweb/webutil.py	Sun Jul 12 16:47:56 2015 +0800
@@ -6,10 +6,11 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import os, copy, urllib
+import os, copy
 from mercurial import match, patch, error, ui, util, pathutil, context
 from mercurial.i18n import _
 from mercurial.node import hex, nullid, short
+from mercurial.templatefilters import revescape
 from common import ErrorResponse, paritygen
 from common import HTTP_NOT_FOUND
 import difflib
@@ -281,7 +282,7 @@
 
 def symrevorshortnode(req, ctx):
     if 'node' in req.form:
-        return urllib.quote(req.form['node'][0])
+        return revescape(req.form['node'][0])
     else:
         return short(ctx.node())
 
--- a/mercurial/templatefilters.py	Sun Jul 12 16:06:57 2015 +0800
+++ b/mercurial/templatefilters.py	Sun Jul 12 16:47:56 2015 +0800
@@ -283,6 +283,13 @@
     f = author.find('@')
     return author[:f].replace('.', ' ')
 
+def revescape(text):
+    """:revescape: Any text. Escapes all "special" characters, except @.
+    Forward slashes are escaped twice to prevent web servers from prematurely
+    unescaping them. For example, "@foo bar/baz" becomes "@foo%20bar%252Fbaz".
+    """
+    return urllib.quote(text, safe='/@').replace('/', '%252F')
+
 def rfc3339date(text):
     """:rfc3339date: Date. Returns a date using the Internet date format
     specified in RFC 3339: "2009-08-18T13:00:13+02:00".
@@ -402,6 +409,7 @@
     "obfuscate": obfuscate,
     "permissions": permissions,
     "person": person,
+    "revescape": revescape,
     "rfc3339date": rfc3339date,
     "rfc822date": rfc822date,
     "short": short,