#2756 Show VCS and DistURL tags as links when appropriate
Merged 3 years ago by tkopecek. Opened 3 years ago by alexi.
alexi/koji issue_2748  into  master

file modified
+32 -1
@@ -1,6 +1,6 @@ 

  import unittest

  

- from kojiweb.util import formatMode

+ from kojiweb.util import formatMode, formatLink, escapeHTML

  

  class TestFormatMode(unittest.TestCase):

      def test_format_mode(self):
@@ -16,3 +16,34 @@ 

  

          for s, mode in formats:

              self.assertEqual(formatMode(mode), s)

+ 

+     def test_format_link(self):

+         formats = (

+             ('test me', 'test me'),

+             ('  test ', 'test'),

+             ('<script>hack</script>', '&lt;script&gt;hack&lt;/script&gt;'),

+             ('not://valid', 'not://valid'),

+             ('https://foo.com', '<a href="https://foo.com">https://foo.com</a>'),

+             ('http://bar.com/', '<a href="http://bar.com/">http://bar.com/</a>'),

+             ('HTtP://BaR.CoM/', '<a href="HTtP://BaR.CoM/">HTtP://BaR.CoM/</a>'),

+             ('https://baz.com/baz&t=1', '<a href="https://baz.com/baz&amp;t=1">https://baz.com/baz&amp;t=1</a>'),

+             ('ssh://git@pagure.io/foo', '<a href="ssh://git@pagure.io/foo">ssh://git@pagure.io/foo</a>'),

+             ('git://git@pagure.io/foo', '<a href="git://git@pagure.io/foo">git://git@pagure.io/foo</a>'),

+             ('obs://build.opensuse.org/foo', '<a href="obs://build.opensuse.org/foo">obs://build.opensuse.org/foo</a>'),

+         )

+ 

+         for input, output in formats:

+             self.assertEqual(formatLink(input), output)

+ 

+     def test_escape_html(self):

+         tests = (

+             ('test me', 'test me'),

+             ('test <danger>', 'test &lt;danger&gt;'),

+             ('test <danger="true">', 'test &lt;danger=&quot;true&quot;&gt;'),

+             ("test <danger='true'>", 'test &lt;danger=&#x27;true&#x27;&gt;'),

+             ('test&test', 'test&amp;test'),

+             ('test&amp;test', 'test&amp;test'),

+         )

+ 

+         for input, output in tests:

+             self.assertEqual(escapeHTML(input), output)

file modified
+2 -2
@@ -52,12 +52,12 @@ 

      #end if

      #if $vcs

      <tr>

-         <th><label title="Package source code VCS location">VCS</label></th><td>$util.escapeHTML($vcs)</td>

+         <th><label title="Package source code VCS location">VCS</label></th><td>$util.formatLink($vcs)</td>

      </tr>

      #end if

      #if $disturl

      <tr>

-         <th>DistURL</th><td>$util.escapeHTML($disturl)</td>

+         <th>DistURL</th><td>$util.formatLink($disturl)</td>

      </tr>

      #end if

      <tr>

file modified
+2 -2
@@ -70,12 +70,12 @@ 

      </tr>

      #if $vcs

      <tr>

-         <th><label title="Package source code VCS location">VCS</label></th><td>$util.escapeHTML($vcs)</td>

+         <th><label title="Package source code VCS location">VCS</label></th><td>$util.formatLink($vcs)</td>

      </tr>

      #end if

      #if $disturl

      <tr>

-         <th>DistURL</th><td>$util.escapeHTML($disturl)</td>

+         <th>DistURL</th><td>$util.formatLink($disturl)</td>

      </tr>

      #end if

      #end if

file modified
+18 -8
@@ -117,12 +117,7 @@ 

  class XHTMLFilter(DecodeUTF8):

      def filter(self, *args, **kw):

          result = super(XHTMLFilter, self).filter(*args, **kw)

-         result = result.replace('&', '&amp;')

-         result = result.replace('&amp;amp;', '&amp;')

-         result = result.replace('&amp;nbsp;', '&nbsp;')

-         result = result.replace('&amp;lt;', '&lt;')

-         result = result.replace('&amp;gt;', '&gt;')

-         return result

+         return re.sub(r'&(?![a-zA-Z0-9#]+;)', '&amp;', result)

  

  

  TEMPLATES = {}
@@ -534,6 +529,17 @@ 

      return '{:,}'.format(value)

  

  

+ def formatLink(url):

+     """Turn a string into an HTML link if it looks vaguely like a URL.

+     If it doesn't, just return it properly escaped."""

+     url = escapeHTML(url.strip())

+     m = re.match(r'(https?|ssh|git|obs)://.*', url, flags=re.IGNORECASE)

+     if m:

+         return '<a href="{}">{}</a>'.format(url, url)

+ 

+     return url

+ 

+ 

  def rowToggle(template):

      """If the value of template._rowNum is even, return 'row-even';

      if it is odd, return 'row-odd'.  Increment the value before checking it.
@@ -594,14 +600,18 @@ 

      < : &lt;

      > : &gt;

      & : &amp;

+     " : &quot;

+     ' : &#x27;

      """

      if not value:

          return value

  

      value = koji.fixEncoding(value)

-     return value.replace('&', '&amp;').\

+     return re.sub(r'&(?![a-zA-Z0-9#]+;)', '&amp;', value).\

          replace('<', '&lt;').\

-         replace('>', '&gt;')

+         replace('>', '&gt;').\

+         replace('"', '&quot;').\

+         replace("'", '&#x27;')

  

  

  def authToken(template, first=False, form=False):

pretty please pagure-ci rebuild

3 years ago

1 new commit added

  • Escape single and double quotes as well, plus add test
3 years ago

2 new commits added

  • Escape single and double quotes as well, plus add test
  • Show VCS and DistURL tags as links when appropriate
3 years ago

1 new commit added

  • Don't encode already encoded entities
3 years ago

Test is failing here (flake8) - E302 expected 2 blank lines, found 1

It is not doing the same thing as before. e.g. ``re.sub(r'&(?![a-zA-Z0-9#]+;)', '&', 'a&amp<x') -> a&amp<x

It is not doing the same thing as before. e.g. ``re.sub(r'&(?![a-zA-Z0-9#]+;)', '&', 'a&amp<x') -> a&amp<x

The previous code replaced & for &amp;, and then fixed the HTML character references it broke in the first pass.

This line replaces & only when it's not part of a character reference. It's true that this isn't exactly the same because now it preserves all character references, and not just those four, but is that a bad thing?

1 new commit added

  • Make flake8 happy
3 years ago

I've gone through some pages with mixed content and it seems to work correctly. @mikem any idea if this still can break some page?

For what it's worth, we've been running with this patch in production for the last couple of weeks and we haven't noticed any issues.

Metadata Update from @tkopecek:
- Pull-request tagged with: testing-ready

3 years ago

Metadata Update from @jobrauer:
- Pull-request tagged with: testing-done

3 years ago

Commit 8d13743 fixes this pull-request

Pull-Request has been merged by tkopecek

3 years ago