changeset 7555:9376ca7157f3 stable

compare: correct display of special branch names in initial placeholder When a branch name contains special characters like '<' or '>', and a 'compare' operation is performed with such branch as one of the two compare sides, then the special branch name will be part of the URL, e.g. http://localhost:5000/myrepo/compare/branch@master...branch@%3Cscript%3Eblabla%3C/script%3E?other_repo=myrepo The encoded branch name is then used at page load as placeholders for the branch selection dropdowns. But, the special characters, were escaped too much, causing '<' to become &lt; in the display of the dropdown. The placeholder was escaped via the default mako escape filter, before being passed to make_revision_dropdown, thus too early. We want the raw value. h.js() (copied from the default branch) gives us that, while still formatting and escaping the string so it is safe inside the script tag.
author Mads Kiilerich <mads@kiilerich.com>
date Wed, 27 Feb 2019 02:30:58 +0100
parents 04e44ea05c5f
children b2410a5d6563
files kallithea/lib/helpers.py kallithea/templates/compare/compare_diff.html
diffstat 2 files changed, 33 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/lib/helpers.py	Tue Feb 26 21:27:42 2019 +0100
+++ b/kallithea/lib/helpers.py	Wed Feb 27 02:30:58 2019 +0100
@@ -18,6 +18,7 @@
 available to Controllers. This module is available to both as 'h'.
 """
 import hashlib
+import json
 import StringIO
 import math
 import logging
@@ -100,6 +101,36 @@
         .replace("'", "&apos;")
         )
 
+def js(value):
+    """Convert Python value to the corresponding JavaScript representation.
+
+    This is necessary to safely insert arbitrary values into HTML <script>
+    sections e.g. using Mako template expression substitution.
+
+    Note: Rather than using this function, it's preferable to avoid the
+    insertion of values into HTML <script> sections altogether. Instead,
+    data should (to the extent possible) be passed to JavaScript using
+    data attributes or AJAX calls, eliminating the need for JS specific
+    escaping.
+
+    Note: This is not safe for use in attributes (e.g. onclick), because
+    quotes are not escaped.
+
+    Because the rules for parsing <script> varies between XHTML (where
+    normal rules apply for any special characters) and HTML (where
+    entities are not interpreted, but the literal string "</script>"
+    is forbidden), the function ensures that the result never contains
+    '&', '<' and '>', thus making it safe in both those contexts (but
+    not in attributes).
+    """
+    return literal(
+        ('(' + json.dumps(value) + ')')
+        # In JSON, the following can only appear in string literals.
+        .replace('&', r'\x26')
+        .replace('<', r'\x3c')
+        .replace('>', r'\x3e')
+    )
+
 def shorter(s, size=20):
     postfix = '...'
     if len(s) > size:
--- a/kallithea/templates/compare/compare_diff.html	Tue Feb 26 21:27:42 2019 +0100
+++ b/kallithea/templates/compare/compare_diff.html	Wed Feb 27 02:30:58 2019 +0100
@@ -140,8 +140,8 @@
     });
     }
 
-    make_revision_dropdown("#compare_org",   "${'%s@%s' % (c.a_repo.repo_name, c.a_ref_name)}",   "${c.a_repo.repo_name}",  'cache');
-    make_revision_dropdown("#compare_other", "${'%s@%s' % (c.cs_repo.repo_name, c.cs_ref_name)}", "${c.cs_repo.repo_name}", 'cache2');
+    make_revision_dropdown("#compare_org",   ${h.js('%s@%s' % (c.a_repo.repo_name, c.a_ref_name))},   "${c.a_repo.repo_name}",  'cache');
+    make_revision_dropdown("#compare_other", ${h.js('%s@%s' % (c.cs_repo.repo_name, c.cs_ref_name))}, "${c.cs_repo.repo_name}", 'cache2');
 
     var values_changed = function() {
         var values = $('#compare_org').select2('data') && $('#compare_other').select2('data');