rblank  committed 2c4b7b8

0.12.3dev: Fixed the handling of `link=` attributes in `[[Image()]]` when linking to an attachment.

Research and initial patch by mitar, thanks!

  • Participants
  • Parent commits d9203dc
  • Branches 0.12-stable

Comments (0)

Files changed (5)

File trac/mimeview/

 from trac.core import *
 from trac.env import ISystemInfoProvider
 from trac.mimeview.api import IHTMLPreviewRenderer, content_to_unicode
-from trac.util.html import Element, Markup
+from trac.util.html import Element, Fragment, Markup, find_element
 from trac.util.translation import _
 from import WikiSystem
 from import WikiProcessor, Formatter, extract_link
         link = extract_link(env, context, fulltext)
         uri = None
         missing = False
-        if isinstance(link, Element):
+        if isinstance(link, (Element, Fragment)):
             linktext = Markup(link).striptags()
             # the following is a bit hackish, but it takes into account:
             #  - an eventual trailing '?' for missing wiki pages
             #  - space eventually introduced due to split_page_names option
             if linktext.rstrip('?').replace(' ', '') != target:
                 text = linktext
-            uri = link.attrib.get('href', '')
-            missing = 'missing' in link.attrib.get('class', '')
+            elt = find_element(link, 'href', 'missing')
+            if elt is not None:
+                uri = elt.attrib.get('href', '')
+                missing = 'missing' in elt.attrib.get('class', '').split()
             uri =
             missing = not WikiSystem(env).has_page(target)
             if missing:
             return reference
-        return None
     def trac_directive(name, arguments, options, content, lineno,
                        content_offset, block_text, state, state_machine):

File trac/search/

 import pkg_resources
 import re
-from genshi.builder import tag, Element
+from genshi.builder import tag
 from trac.config import IntOption, ListOption
 from trac.core import *
 from trac.perm import IPermissionRequestor
 from import ISearchSource
 from trac.util.datefmt import format_datetime
+from trac.util.html import find_element
 from trac.util.presentation import Paginator
 from trac.util.translation import _
 from trac.web import IRequestHandler
             name = kwd
             description = _('Browse repository path %(path)s', path=kwd)
-            link = extract_link(self.env, Context.from_request(req, 'search'),
-                                kwd)
-            if isinstance(link, Element):
+            context = Context.from_request(req, 'search')
+            link = find_element(extract_link(self.env, context, kwd), 'href')
+            if link is not None:
                 quickjump_href = link.attrib.get('href')
                 name = link.children
                 description = link.attrib.get('title', '')

File trac/util/

 from genshi.builder import Element, ElementFactory, Fragment
 from genshi.filters.html import HTMLSanitizer
-__all__ = ['escape', 'unescape', 'html', 'plaintext', 'TracHTMLSanitizer']
+__all__ = ['escape', 'unescape', 'html', 'plaintext', 'find_element',
+           'TracHTMLSanitizer']
 class TracHTMLSanitizer(HTMLSanitizer):
     return text
+def find_element(frag, attr=None, cls=None):
+    """Return the first element in the fragment having the given attribute or
+    class, using a preorder depth-first search.
+    """
+    if isinstance(frag, Element):
+        if attr is not None and attr in frag.attrib:
+            return frag
+        if cls is not None and cls in frag.attrib.get('class', '').split():
+            return fragment
+    if isinstance(frag, Fragment):
+        for child in frag.children:
+            elt = find_element(child, attr, cls)
+            if elt is not None:
+                return elt
 def expand_markup(stream, ctxt=None):
     """A Genshi stream filter for expanding Markup events.

File trac/wiki/

 from trac.core import *
 from trac.mimeview import Context
 from trac.perm import PermissionError
+from trac.util.html import find_element
 from trac.util.translation import _
 from trac.web import IRequestHandler
 from import IWikiMacroProvider
             if target and (target[0] not in '\'"' or target[0] != target[-1]):
                 link = '%s:"%s"' % (resolver, target)
         link_frag = extract_link(self.env, Context.from_request(req), link)
-        def get_first_href(item):
-            """Depth-first search for the first `href` attribute."""
-            if isinstance(item, Element):
-                href = item.attrib.get('href')
-                if href is not None:
-                    return href
-            if isinstance(item, Fragment):
-                for each in item.children:
-                    href = get_first_href(each)
-                    if href is not None:
-                        return href
         if isinstance(link_frag, (Element, Fragment)):
-            href = get_first_href(link_frag)
-            if href is None: # most probably no permissions to view
+            elt = find_element(link_frag, 'href')
+            if elt is None: # most probably no permissions to view
                 raise PermissionError(_("Can't view %(link)s:", link=link))
+            href = elt.attrib['href']
             href = req.href(link.rstrip(':'))

File trac/wiki/

 import re
 from StringIO import StringIO
-from genshi.builder import Element, tag
+from genshi.builder import tag
 from genshi.core import Markup
 from trac.core import *
                           get_resource_summary, get_resource_url
 from trac.util.compat import any, rpartition
 from trac.util.datefmt import format_date, from_utimestamp
-from trac.util.html import escape
+from trac.util.html import escape, find_element
 from trac.util.presentation import separated
 from trac.util.text import unquote, to_unicode
 from trac.util.translation import _
             elif arg.startswith('link='):
                 val = arg.split('=', 1)[1]
                 elt = extract_link(self.env, formatter.context, val.strip())
+                elt = find_element(elt, 'href')
                 link = None
-                if isinstance(elt, Element):
+                if elt is not None:
                     link = elt.attrib.get('href')
             elif arg in ('left', 'right'):
                 style['float'] = arg