Edgewall Software

Ticket #1153: dont_escape_wiki_text_beforehand.patch

File dont_escape_wiki_text_beforehand.patch, 7.8 kB (added by cboos, 3 years ago)

Keep "<", ">" and "&" in the Wiki text being parsed, and escape them during the parsing. This enables an easier manipulation of those characters in regexps (instead of having to handle the corresponding substituted strings). Patch made on r2403.

  • trac/ticket/query.py

     
    590590    def _format_link(self, formatter, ns, query, label): 
    591591        if query[0] == '?': 
    592592            return '<a class="query" href="%s">%s</a>' \ 
    593                    % (escape(formatter.href.query()) + query.replace(' ', '+'), 
     593                   % (escape(formatter.href.query() + query.replace(' ', '+')), 
    594594                      label) 
    595595        else: 
    596596            from trac.ticket.query import Query, QuerySyntaxError 
    597597            try: 
    598                 query = Query.from_string(formatter.env, unescape(query)) 
     598                query = Query.from_string(formatter.env, query) 
    599599                return '<a class="query" href="%s">%s</a>' \ 
    600600                       % (escape(query.get_href()), label) 
    601601            except QuerySyntaxError, e: 
  • trac/Search.py

     
    237237 
    238238    def _format_link(self, formatter, ns, query, label): 
    239239        if query and query[0] == '?': 
    240             href = formatter.href.search() + \ 
    241                    query.replace('&amp;', '&').replace(' ', '+') 
     240            href = formatter.href.search() + query.replace(' ', '+') 
    242241        else: 
    243242            href = formatter.href.search(q=query) 
    244243        return '<a class="search" href="%s">%s</a>' % (escape(href), label) 
  • trac/wiki/tests/wiki-tests.txt

     
    115115ticket:1 
    116116This ticket is the first one 
    117117changeset:123> 
     118changeset:123& 
    118119------------------------------ 
    119120<p> 
    120121Add-on to <a class="missing changeset" href="/changeset/123" rel="nofollow">changeset:123</a>: 
     
    122123<a class="missing ticket" href="/ticket/1" rel="nofollow">ticket:1</a> 
    123124This ticket is the first one 
    124125<a class="missing changeset" href="/changeset/123" rel="nofollow">changeset:123</a>&gt; 
     126<a class="missing changeset" href="/changeset/123" rel="nofollow">changeset:123</a>&amp; 
    125127</p> 
    126128------------------------------ 
    127129Add-on to <a class="missing changeset" href="/changeset/123" rel="nofollow">changeset:123</a>: 
     
    129131<a class="missing ticket" href="/ticket/1" rel="nofollow">ticket:1</a> 
    130132This ticket is the first one 
    131133<a class="missing changeset" href="/changeset/123" rel="nofollow">changeset:123</a>&gt; 
     134<a class="missing changeset" href="/changeset/123" rel="nofollow">changeset:123</a>&amp; 
    132135============================== 
    133136CamelCase AlabamA ABc AlaBamA FooBar 
    134137------------------------------ 
  • trac/wiki/formatter.py

     
    138138    QUOTED_STRING = r"'[^']+'|\"[^\"]+\"" 
    139139 
    140140    SHREF_TARGET_FIRST = r"[\w/?!#@]" 
    141     SHREF_TARGET_MIDDLE = r"(?:\|(?=[^|\s])|&(?!lt;|gt;)|[^|&\s])" 
     141    SHREF_TARGET_MIDDLE = r"(?:\|(?=[^|\s])|[^|<>\s])" 
    142142    SHREF_TARGET_LAST = r"[a-zA-Z0-9/=]" # we don't want "_" 
    143143 
    144144    LHREF_RELATIVE_TARGET = r"[/.][^\s[\]]*" 
     
    148148    # between _pre_rules and _post_rules 
    149149 
    150150    _pre_rules = [ 
     151        r"(?P<htmlescape>[&<>])", 
    151152        # Font styles 
    152153        r"(?P<bolditalic>%s)" % BOLDITALIC_TOKEN, 
    153154        r"(?P<bold>%s)" % BOLD_TOKEN, 
     
    297298 
    298299    def _make_link(self, ns, target, match, label): 
    299300        if ns in self.link_resolvers: 
    300             return self.link_resolvers[ns](self, ns, target, label) 
     301            return self.link_resolvers[ns](self, ns, target, 
     302                                           util.escape(label, False)) 
    301303        elif target.startswith('//') or ns == "mailto": 
    302304            return self._make_ext_link(ns+':'+target, label) 
    303305        else: 
    304             return match 
     306            return util.escape(match) 
    305307 
    306308    def _make_ext_link(self, url, text, title=''): 
    307         title_attr = title and ' title="%s"' % title or '' 
     309        url = util.escape(url) 
     310        title_attr = title and ' title="%s"' % util.escape(title) or '' 
    308311        if Formatter.img_re.search(url) and self.flavor != 'oneliner': 
    309             return '<img src="%s" alt="%s" />' % (url, title or text) 
     312            return '<img src="%s" alt="%s" />' % (url, 
     313                                                  util.escape(title or text)) 
    310314        if not url.startswith(self._local): 
    311315            return '<a class="ext-link" href="%s"%s><span class="icon">' \ 
    312316                   '</span>%s</a>' % (url, title_attr, text) 
     
    314318            return '<a href="%s"%s>%s</a>' % (url, title_attr, text) 
    315319 
    316320    def _make_relative_link(self, url, text): 
     321        url, text = util.escape(url), util.escape(text) 
    317322        if Formatter.img_re.search(url) and self.flavor != 'oneliner': 
    318323            return '<img src="%s" alt="%s" />' % (url, text) 
    319324        if url.startswith('//'): # only the protocol will be kept 
     
    365370        # the tickethref regexp 
    366371        return match 
    367372 
     373    def _htmlescape_formatter(self, match, fullmatch): 
     374        return match == "&" and "&amp;" or match == "<" and "&lt;" or "&gt;" 
     375 
    368376    def _macro_formatter(self, match, fullmatch): 
    369377        name = fullmatch.group('macroname') 
    370378        if name in ['br', 'BR']: 
    371379            return '<br />' 
    372380        args = fullmatch.group('macroargs') 
    373         args = util.unescape(args) 
    374381        try: 
    375382            macro = WikiProcessor(self.env, name) 
    376383            return macro.process(self.req, args, 1) 
     
    390397        depth = min(len(fullmatch.group('hdepth')), 5) 
    391398        heading = match[depth + 1:len(match) - depth - 1] 
    392399 
    393         text = wiki_to_oneliner(util.unescape(heading), self.env, self.db, 
    394                                 self._absurls) 
     400        text = wiki_to_oneliner(heading, self.env, self.db, self._absurls) 
    395401        sans_markup = re.sub(r'</?\w+(?: .*?)?>', '', text) 
    396402 
    397403        anchor = self._anchor_re.sub('', sans_markup.decode('utf-8')) 
     
    600606                self.close_def_list() 
    601607                continue 
    602608 
    603             line = util.escape(line, False) 
    604609            if escape_newlines: 
    605610                line += ' [[BR]]' 
    606611            self.in_list_item = False 
     
    643648    # Override a few formatters to disable some wiki syntax in "oneliner"-mode 
    644649    def _list_formatter(self, match, fullmatch): return match 
    645650    def _indent_formatter(self, match, fullmatch): return match 
    646     def _heading_formatter(self, match, fullmatch): return match 
    647     def _definition_formatter(self, match, fullmatch): return match 
     651    def _heading_formatter(self, match, fullmatch): 
     652        return util.escape(match, False) 
     653    def _definition_formatter(self, match, fullmatch): 
     654        return util.escape(match, False) 
    648655    def _table_cell_formatter(self, match, fullmatch): return match 
    649656    def _last_table_cell_formatter(self, match, fullmatch): return match 
    650657 
     
    664671        self.out = out 
    665672        self._open_tags = [] 
    666673 
    667         result = re.sub(self.rules, self.replace, util.escape(text.strip(), False)) 
     674        result = re.sub(self.rules, self.replace, text.strip()) 
    668675        # Close all open 'one line'-tags 
    669676        result += self.close_tag(None) 
    670677        out.write(result) 
     
    712719        depth = min(len(fullmatch.group('hdepth')), 5) 
    713720        heading = match[depth + 1:len(match) - depth - 1] 
    714721        anchor = self._anchors[-1] 
    715         text = wiki_to_oneliner(util.unescape(heading), self.env, self.db, 
    716                                 self._absurls) 
     722        text = wiki_to_oneliner(heading, self.env, self.db, self._absurls) 
    717723        text = re.sub(r'</?a(?: .*?)?>', '', text) # Strip out link tags 
    718724        self.outline.append((depth, '<a href="#%s">%s</a>' % (anchor, text))) 
    719725