Christian Boos committed 807578a

0.12.3dev: fix an unicode issue in the `[[Image]]` macro.

When given a project relative path (as in #10485), we shouldn't
produce an UTF-8 encoded `str` out of it, as this will trigger an
`UnicodeError` when mixed with `unicode` later on.

Modified all the Image macros to take some unicode input, to verify
the other code paths. Also removed the request parameters from the
image URL, in the `alt` and `title` attributes, to make them less

Closes #10485.

  • Participants
  • Parent commits bbb02ca

Comments (0)

Files changed (2)

File trac/wiki/

 from trac.util.datefmt import format_date, from_utimestamp
 from trac.util.html import escape, find_element
 from trac.util.presentation import separated
-from trac.util.text import unicode_quote, unquote, to_unicode
+from trac.util.text import unicode_quote, to_unicode
 from trac.util.translation import _
 from import IWikiMacroProvider, WikiSystem, parse_args
 from import format_to_html, format_to_oneliner, \
         url = raw_url = desc = None
         attachment = None
         if (parts and parts[0] in ('http', 'https', 'ftp')): # absolute
-            raw_url = url = desc = filespec
+            raw_url = url = filespec
+            desc = url.rsplit('?')[0]
         elif filespec.startswith('//'):       # server-relative
-            raw_url = url = desc = filespec[1:]
+            raw_url = url = filespec[1:]
+            desc = url.rsplit('?')[0]
         elif filespec.startswith('/'):        # project-relative
-            # use href, but unquote to allow args (use default html escaping)
-            raw_url = url = desc = unquote(formatter.href(filespec))
+            params = ''
+            if '?' in filespec:
+                filespec, params = filespec.rsplit('?', 1)
+            url = formatter.href(filespec)
+            if params:
+                url += '?' + params
+            raw_url, desc = url, filespec
         elif len(parts) == 3:                 # realm:id:attachment-filename
             #                                 # or intertrac:realm:id 
             realm, id, filename = parts

File trac/wiki/tests/

+# -*- coding: utf-8 -*-
 from datetime import datetime
 import unittest
 # == [[Image]]
+# Note: using `« test »` string in the following tests for checking
+#       unicode robustness and whitespace support (first space is
+#       normal ASCII SPACE, second is Unicode NO-BREAK SPACE).
 ============================== source: Image, no other arguments
+[[Image(source:« test ».png)]]
-<a style="padding:0; border:none" href="/browser/test.png"><img src="/browser/test.png?format=raw" alt="source:test.png" title="source:test.png" /></a>
+<a style="padding:0; border:none" href="/browser/%C2%AB%20test%C2%A0%C2%BB.png"><img src="/browser/%C2%AB%20test%C2%A0%C2%BB.png?format=raw" alt="source:« test ».png" title="source:« test ».png" /></a>
 ============================== intertrac:source: Image, no other arguments
+[[Image(trac:source:/trunk/doc/images/bkgnd_pattern_« test ».png)]]
-<a style="padding:0; border:none" href=""><img src="" alt="source:/trunk/doc/images/bkgnd_pattern.png in Trac's Trac" title="source:/trunk/doc/images/bkgnd_pattern.png in Trac's Trac" /></a>
+<a style="padding:0; border:none" href=""><img src="" alt="source:/trunk/doc/images/bkgnd_pattern_« test ».png in Trac's Trac" title="source:/trunk/doc/images/bkgnd_pattern_« test ».png in Trac's Trac" /></a>
 ============================== source: Image, nolink
-[[Image(source:test.png, nolink)]]
+[[Image(source:« test », nolink)]]
-<img src="/browser/test.png?format=raw" alt="source:test.png" title="source:test.png" />
+<img src="/browser/%C2%AB%20test%C2%A0%C2%BB?format=raw" alt="source:« test »" title="source:« test »" />
 ============================== source: Image, normal args
-[[Image(source:test.png, align=left, title=Test)]]
+[[Image(source:« test », align=left, title=Test)]]
-<a style="padding:0; border:none" href="/browser/test.png"><img src="/browser/test.png?format=raw" alt="source:test.png" style="float:left" title="Test" /></a>
+<a style="padding:0; border:none" href="/browser/%C2%AB%20test%C2%A0%C2%BB"><img src="/browser/%C2%AB%20test%C2%A0%C2%BB?format=raw" alt="source:« test »" style="float:left" title="Test" /></a>
 ============================== source: Image, size arg
-[[Image(source:test.png, 30%)]]
+[[Image(source:« test », 30%)]]
-<a style="padding:0; border:none" href="/browser/test.png"><img width="30%" alt="source:test.png" title="source:test.png" src="/browser/test.png?format=raw" /></a>
+<a style="padding:0; border:none" href="/browser/%C2%AB%20test%C2%A0%C2%BB"><img width="30%" alt="source:« test »" title="source:« test »" src="/browser/%C2%AB%20test%C2%A0%C2%BB?format=raw" /></a>
 ============================== source: Image, keyword alignment
-[[Image(source:test.png, right)]]
+[[Image(source:« test », right)]]
-<a style="padding:0; border:none" href="/browser/test.png"><img src="/browser/test.png?format=raw" alt="source:test.png" style="float:right" title="source:test.png" /></a>
+<a style="padding:0; border:none" href="/browser/%C2%AB%20test%C2%A0%C2%BB"><img src="/browser/%C2%AB%20test%C2%A0%C2%BB?format=raw" alt="source:« test »" style="float:right" title="source:« test »" /></a>
 ============================== http: Image, nolink
-[[Image(, nolink)]]
+[[Image(« test ».png, nolink)]]
-<img src="" alt="" title="" />
+<img src="« test ».png" alt="« test ».png" title="« test ».png" />
 ============================== http: Image, absolute, many ':'
-[[Image(|World, title=Google & Charting, link=)]]
+[[Image(éllo|Wôrld, title=Google & Charting, link=)]]
-<img src=";chd=s:hW&amp;chs=250x100&amp;chl=Hello|World" alt=";chd=s:hW&amp;chs=250x100&amp;chl=Hello|World" title="Google &amp; Charting" />
+<img src=";chd=s:hW&amp;chs=250x100&amp;chl=Héllo|Wôrld" alt="" title="Google &amp; Charting" />
 ============================== // Image, server-relative
-[[Image(//browser/test.png?format=raw, link=)]]
+[[Image(//browser/« test »?format=raw, link=)]]
-<img src="/browser/test.png?format=raw" alt="/browser/test.png?format=raw" title="/browser/test.png?format=raw" />
+<img src="/browser/« test »?format=raw" alt="/browser/« test »" title="/browser/« test »" />
 ============================== / Image, project-relative, link to WikiStart
-[[Image(/browser/test.png?format=raw, link=wiki:WikiStart)]]
+[[Image(/browser/« test »?format=raw, link=wiki:WikiStart)]]
-<a style="padding:0; border:none" href="/wiki/WikiStart"><img src="/browser/test.png?format=raw" alt="/browser/test.png?format=raw" title="/browser/test.png?format=raw" /></a>
+<a style="padding:0; border:none" href="/wiki/WikiStart"><img src="/browser/%C2%AB%20test%C2%A0%C2%BB?format=raw" alt="/browser/« test »" title="/browser/« test »" /></a>
+# Note: in the <img> src attribute above, the Unicode characters
+#       within the URI sometimes come out as %-encoded, sometimes raw
+#       (server-relative case). Both forms are valid (at least
+#       according to the W3C XHTML validator).
 # == [[TitleIndex]]