diff -Nur loggerhead-1.17/loggerhead/controllers/annotate_ui.py loggerhead-1.17.new/loggerhead/controllers/annotate_ui.py
--- loggerhead-1.17/loggerhead/controllers/annotate_ui.py 2009-08-20 23:53:02.000000000 +1000
+++ loggerhead-1.17.new/loggerhead/controllers/annotate_ui.py 2011-03-24 14:15:34.486850157 +1100
@@ -17,7 +17,6 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-import cgi
import os
import time
@@ -71,7 +70,7 @@
hl_lines = highlight(file_name, file_text, encoding)
hl_lines.extend([u''] * (len(file_lines) - len(hl_lines)))
else:
- hl_lines = map(cgi.escape, file_lines)
+ hl_lines = map(util.html_escape, file_lines)
change_cache = {}
diff -Nur loggerhead-1.17/loggerhead/templatefunctions.py loggerhead-1.17.new/loggerhead/templatefunctions.py
--- loggerhead-1.17/loggerhead/templatefunctions.py 2009-08-20 23:53:02.000000000 +1000
+++ loggerhead-1.17.new/loggerhead/templatefunctions.py 2011-03-24 14:15:34.486850157 +1100
@@ -14,8 +14,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-import cgi
import os
+import urllib
import pkg_resources
@@ -23,6 +23,7 @@
import loggerhead
from loggerhead.zptsupport import zpt
+from loggerhead.util import html_format
templatefunctions = {}
@@ -49,16 +50,21 @@
if style == 'fragment':
def file_link(filename):
if currently_showing and filename == currently_showing:
- return '%s' % (
- cgi.escape(filename), cgi.escape(filename))
+ return html_format(
+ '%s',
+ urllib.quote(filename.encode('utf-8')), filename)
else:
return revision_link(
- url, entry.revno, filename, '#' + filename)
+ url, entry.revno, filename,
+ '#' + urllib.quote(filename.encode('utf-8')))
else:
def file_link(filename):
- return '%s'%(
- url(['/revision', entry.revno]), '#' + filename, cgi.escape(filename),
- cgi.escape(entry.revno), cgi.escape(filename))
+ return html_format(
+ ''
+ '%s',
+ url(['/revision', entry.revno]),
+ '#' + urllib.quote(filename.encode('utf-8')),
+ filename, entry.revno, filename)
return _pt('revisionfilechanges').expand(
entry=entry, file_changes=file_changes, file_link=file_link, **templatefunctions)
@@ -122,14 +128,15 @@
@templatefunc
def annotate_link(url, revno, path):
- return '%s'%(
- url(['/annotate', revno, path]), cgi.escape(path), cgi.escape(path))
+ return html_format(
+ '%s',
+ url(['/annotate', revno, path]), path, path)
@templatefunc
def revision_link(url, revno, path, frag=''):
- return '%s'%(
- url(['/revision', revno, path]), frag, cgi.escape(path),
- cgi.escape(revno), cgi.escape(path))
+ return html_format(
+ '%s',
+ url(['/revision', revno, path]), frag, path, revno, path)
@templatefunc
diff -Nur loggerhead-1.17/loggerhead/tests/test_simple.py loggerhead-1.17.new/loggerhead/tests/test_simple.py
--- loggerhead-1.17/loggerhead/tests/test_simple.py 2009-08-20 23:53:02.000000000 +1000
+++ loggerhead-1.17.new/loggerhead/tests/test_simple.py 2011-03-24 14:15:34.486850157 +1100
@@ -59,9 +59,11 @@
self.filecontents = ('some\nmultiline\ndata\n'
'with", ">"),
+ ("<", "<"),
+ ]
+
+
+def html_escape(s):
+ """Transform dangerous (X)HTML characters into entities.
+
+ Like cgi.escape, except also escaping " and '. This makes it safe to use
+ in both attribute and element content.
+
+ If you want to safely fill a format string with escaped values, use
+ html_format instead
+ """
+ for char, repl in html_entity_subs:
+ s = s.replace(char, repl)
+ return s
+
+def html_format(template, *args):
+ """Safely format an HTML template string, escaping the arguments.
+
+ The template string must not be user-controlled; it will not be escaped.
+ """
+ return template % tuple(html_escape(arg) for arg in args)
+
+
+# FIXME: get rid of this method; use fixed_width() and avoid XML().
def html_clean(s):
"""
@@ -202,7 +232,7 @@
entities, and replace spaces with ' '. this is primarily for use
in displaying monospace text.
"""
- s = cgi.escape(s.expandtabs())
+ s = html_escape(s.expandtabs())
s = s.replace(' ', ' ')
return s
@@ -250,7 +280,7 @@
except UnicodeDecodeError:
s = s.decode('iso-8859-15')
- s = cgi.escape(s).expandtabs().replace(' ', NONBREAKING_SPACE)
+ s = html_escape(s).expandtabs().replace(' ', NONBREAKING_SPACE)
return HSC.clean(s).replace('\n', '
')