Edgewall Software

Ticket #2974: pdf_attachment_browser.diff

File pdf_attachment_browser.diff, 19.7 KB (added by cboos, 3 years ago)

combined and updated patch (i.e. the approach pushed to the extreme :) )

  • trac/attachment.py

     
    7979    path = property(_get_path) 
    8080 
    8181    def href(self, req, *args, **dict): 
    82         return req.href.attachment(self.parent_type, self.parent_id, 
    83                                    self.filename, *args, **dict) 
     82        base, filename = 'attachment', self.filename 
     83        if 'format' in dict: 
     84            format = dict.pop('format') 
     85            base += ';format=' + format # format passed in a segment parameter 
     86        else: # HTML preview 
     87            format = 'html' 
     88        if format != 'raw': 
     89            filename += '.' + format 
     90        return req.href(base, self.parent_type, self.parent_id, filename, 
     91                        *args, **dict) 
    8492 
    8593    def parent_href(self, req): 
    8694        return req.href(self.parent_type, self.parent_id) 
     
    250258    # IRequestHandler methods 
    251259 
    252260    def match_request(self, req): 
    253         match = re.match(r'^/attachment/(ticket|wiki)(?:[/:](.*))?$', 
     261        match = re.match(r'^/attachment(;format=[^/]+)?/' 
     262                         '(ticket|wiki)(?:[/:](.*))?$', 
    254263                         req.path_info) 
    255264        if match: 
    256             req.args['type'] = match.group(1) 
    257             req.args['path'] = match.group(2).replace(':', '/') 
     265            req.args['type'] = match.group(2) 
     266            req.args['path'] = match.group(3).replace(':', '/') 
     267            format = match.group(1) 
     268            if format: 
     269                req.args['format'] = format[8:] 
    258270            return True 
    259271 
    260272    def process_request(self, req): 
    261273        parent_type = req.args.get('type') 
    262274        path = req.args.get('path') 
     275        format = req.args.get('format') 
    263276        if not parent_type or not path: 
    264277            raise HTTPBadRequest('Bad request') 
    265278        if not parent_type in ['ticket', 'wiki']: 
     
    272285            segments = path.split('/') 
    273286            parent_id = '/'.join(segments[:-1]) 
    274287            filename = segments[-1] 
     288            if not format and filename.endswith('.html'): 
     289                filename = filename[:-5] 
    275290            if len(segments) == 1 or not filename: 
    276291                raise HTTPBadRequest('Bad request') 
    277292            attachment = Attachment(self.env, parent_type, parent_id, filename) 
     
    299314            self._render_form(req, attachment) 
    300315        else: 
    301316            add_link(req, 'up', parent_link, parent_text) 
    302             self._render_view(req, attachment) 
     317            self._render_view(req, attachment, format) 
    303318 
    304319        add_stylesheet(req, 'common/css/code.css') 
    305320        return 'attachment.cs', None 
     
    393408        req.hdf['attachment'] = {'mode': 'new', 
    394409                                 'author': util.get_reporter_id(req)} 
    395410 
    396     def _render_view(self, req, attachment): 
     411    def _render_view(self, req, attachment, format): 
    397412        perm_map = {'ticket': 'TICKET_VIEW', 'wiki': 'WIKI_VIEW'} 
    398413        req.perm.assert_permission(perm_map[attachment.parent_type]) 
    399414 
     
    420435            mime_type = mimeview.get_mimetype(attachment.filename, str_data) 
    421436 
    422437            # Eventually send the file directly 
    423             format = req.args.get('format') 
    424438            if format in ('raw', 'txt'): 
    425439                if not self.render_unsafe_content and not binary: 
    426440                    # Force browser to download HTML/SVG/etc pages that may 
  • trac/mimeview/rst.py

     
    5454def _browser(href, args): 
    5555    path = args[0] 
    5656    rev = len(args) == 2 and args[1] or '' 
    57     return href.browser(path, rev=rev) 
     57    from trac.versioncontrol.web_ui.browser import BrowserModule 
     58    return BrowserModule(self.env).href(req, path, rev=rev) 
    5859 
    5960# TracLink REs and callback functions 
    6061LINKS = [(TICKET_LINK, _ticket), 
  • trac/versioncontrol/web_ui/util.py

     
    6969        } 
    7070    return changes 
    7171 
    72 def get_path_links(href, path, rev): 
     72def get_path_links(browser, req, path, rev): 
    7373    links = [] 
    7474    parts = path.split('/') 
    7575    if not parts[-1]: 
     
    7979        path = path + part + '/' 
    8080        links.append({ 
    8181            'name': part or 'root', 
    82             'href': href.browser(path, rev=rev) 
     82            'href': browser.href(req, path, rev=rev) 
    8383        }) 
    8484    return links 
    8585 
  • trac/versioncontrol/web_ui/changeset.py

     
    3434from trac.versioncontrol import Changeset, Node 
    3535from trac.versioncontrol.diff import get_diff_options, hdf_diff, unified_diff 
    3636from trac.versioncontrol.svn_authz import SubversionAuthorizer 
     37from trac.versioncontrol.web_ui.browser import BrowserModule 
    3738from trac.versioncontrol.web_ui.util import render_node_property 
    3839from trac.web import IRequestHandler 
    3940from trac.web.chrome import INavigationContributor, add_link, add_stylesheet 
     
    264265 
    265266    def _render_html(self, req, repos, chgset, restricted, diff, diff_options): 
    266267        """HTML version""" 
     268        browser = BrowserModule(self.env) 
    267269        req.hdf['changeset'] = { 
    268270            'chgset': chgset and True, 
    269271            'restricted': restricted, 
    270272            'href': { 
    271273                'new_rev': req.href.changeset(diff.new_rev), 
    272274                'old_rev': req.href.changeset(diff.old_rev), 
    273                 'new_path': req.href.browser(diff.new_path, rev=diff.new_rev), 
    274                 'old_path': req.href.browser(diff.old_path, rev=diff.old_rev) 
     275                'new_path': browser.href(req, diff.new_path, rev=diff.new_rev), 
     276                'old_path': browser.href(req, diff.old_path, rev=diff.old_rev) 
    275277            } 
    276278        } 
    277279 
     
    375377                info['path.old'] = old_node.path 
    376378                info['rev.old'] = old_node.rev 
    377379                info['shortrev.old'] = repos.short_rev(old_node.rev) 
    378                 old_href = req.href.browser(old_node.created_path, 
    379                                             rev=old_node.created_rev) 
     380                old_href = browser.href(req, old_node.created_path, 
     381                                        rev=old_node.created_rev) 
    380382                # Reminder: old_node.path may not exist at old_node.rev 
    381383                #           as long as old_node.rev==old_node.created_rev 
    382384                #           ... and diff.old_rev may have nothing to do 
     
    386388                info['path.new'] = new_node.path 
    387389                info['rev.new'] = new_node.rev # created rev. 
    388390                info['shortrev.new'] = repos.short_rev(new_node.rev) 
    389                 new_href = req.href.browser(new_node.created_path, 
    390                                             rev=new_node.created_rev) 
     391                new_href = browser.href(req, new_node.created_path, 
     392                                        rev=new_node.created_rev) 
    391393                # (same remark as above) 
    392394                info['browser_href.new'] = new_href 
    393395            return info 
  • trac/versioncontrol/web_ui/log.py

     
    2424from trac.util import http_date 
    2525from trac.util.markup import html 
    2626from trac.versioncontrol import Changeset 
     27from trac.versioncontrol.web_ui.browser import BrowserModule 
    2728from trac.versioncontrol.web_ui.changeset import ChangesetModule 
    2829from trac.versioncontrol.web_ui.util import * 
    2930from trac.web import IRequestHandler 
     
    7879            if repos.rev_older_than(rev, stop_rev): 
    7980                rev, stop_rev = stop_rev, rev 
    8081             
     82        browser = BrowserModule(self.env) 
     83         
    8184        req.hdf['title'] = path + ' (log)' 
    8285        req.hdf['log'] = { 
    8386            'mode': mode, 
     
    8588            'rev': rev, 
    8689            'verbose': verbose, 
    8790            'stop_rev': stop_rev, 
    88             'browser_href': req.href.browser(path), 
     91            'browser_href': browser.href(req, path), 
    8992            'changeset_href': req.href.changeset(), 
    9093            'log_href': req.href.log(path, rev=rev) 
    9194        } 
    9295 
    93         path_links = get_path_links(req.href, path, rev) 
     96        path_links = get_path_links(browser, req, path, rev) 
    9497        req.hdf['log.path'] = path_links 
    9598        if path_links: 
    9699            add_link(req, 'up', path_links[-1]['href'], 'Parent directory') 
     
    116119                'rev': str(old_rev), 
    117120                'path': old_path, 
    118121                'log_href': req.href.log(old_path, rev=old_rev), 
    119                 'browser_href': req.href.browser(old_path, rev=old_rev), 
     122                'browser_href': browser.href(req, old_path, rev=old_rev), 
    120123                'changeset_href': req.href.changeset(old_rev), 
    121124                'restricted_href': req.href.changeset(old_rev, new_path=old_path), 
    122125                'change': old_chg 
  • trac/versioncontrol/web_ui/browser.py

     
    5757        glob patterns, i.e. "*" can be used as a wild card) 
    5858        (''since 0.10'')""") 
    5959 
     60    def href(self, req, path, *args, **dict): 
     61        base = 'browser' 
     62        if 'format' in dict: 
     63            format = dict.pop('format') 
     64            base += ';format=' + format # format passed in a segment parameter 
     65        else: # HTML preview 
     66            format = 'html' 
     67        if format != 'raw': 
     68            path += '.' + format 
     69        return req.href(base, path, *args, **dict) 
     70         
     71 
    6072    # INavigationContributor methods 
    6173 
    6274    def get_active_navigation_item(self, req): 
     
    7789 
    7890    def match_request(self, req): 
    7991        import re 
    80         match = re.match(r'/(browser|file)(?:(/.*))?', req.path_info) 
     92        match = re.match(r'/(raw|txt)?(browser|file)(?:(/.*))?', req.path_info) 
    8193        if match: 
    82             req.args['path'] = match.group(2) or '/' 
    83             if match.group(1) == 'file': 
    84                 req.redirect(req.href.browser(req.args.get('path'), 
    85                                               rev=req.args.get('rev'), 
    86                                               format=req.args.get('format')), 
     94            req.args['path'] = match.group(3) or '/' 
     95            if match.group(2) == 'file': 
     96                req.redirect(self.href(req, req.args.get('path'), 
     97                                       rev=req.args.get('rev'), 
     98                                       format=req.args.get('format')), 
    8799                             permanent=True) 
     100            format = match.group(1) 
     101            if format: 
     102                req.args['format'] = format 
    88103            return True 
    89104 
    90105    def process_request(self, req): 
    91106        path = req.args.get('path', '/') 
    92107        rev = req.args.get('rev') or None 
     108        format = req.args.get('format') 
    93109 
     110        if format: 
     111            if path.endswith('.txt'): 
     112                path = path[:-4] 
     113        elif path.endswith('.html'): 
     114                path = path[:-5] 
     115 
    94116        # Find node for the requested path/rev 
    95117        repos = self.env.get_repository(req.authname) 
    96118        if rev: 
     
    114136            'path': path, 
    115137            'revision': rev, 
    116138            'props': properties, 
    117             'href': req.href.browser(path, rev=rev), 
     139            'href': self.href(req, path, rev=rev), 
    118140            'log_href': req.href.log(path, rev=rev), 
    119141            'restr_changeset_href': req.href.changeset(node.rev, 
    120142                                                       node.created_path), 
    121143            'anydiff_href': req.href.anydiff(), 
    122144        } 
    123145 
    124         path_links = get_path_links(req.href, path, rev) 
     146        path_links = get_path_links(self, req, path, rev) 
    125147        if len(path_links) > 1: 
    126148            add_link(req, 'up', path_links[-2]['href'], 'Parent directory') 
    127149        req.hdf['browser.path'] = path_links 
     
    130152            req.hdf['browser.is_dir'] = True 
    131153            self._render_directory(req, repos, node, rev) 
    132154        else: 
    133             self._render_file(req, repos, node, rev) 
     155            self._render_file(req, repos, node, rev, format) 
    134156 
    135157        add_stylesheet(req, 'common/css/browser.css') 
    136158        return 'browser.cs', None 
     
    152174                'rev': entry.rev, 
    153175                'permission': 1, # FIXME 
    154176                'log_href': req.href.log(entry.path, rev=rev), 
    155                 'browser_href': req.href.browser(entry.path, rev=rev) 
     177                'browser_href': self.href(req, entry.path, rev=rev) 
    156178            }) 
    157179        changes = get_changes(self.env, repos, [i['rev'] for i in info]) 
    158180 
     
    179201 
    180202        switch_ordering_hrefs = {} 
    181203        for col in ('name', 'size', 'date'): 
    182             switch_ordering_hrefs[col] = req.href.browser( 
    183                 node.path, rev=rev, order=col, 
     204            switch_ordering_hrefs[col] = self.href( 
     205                req, node.path, rev=rev, order=col, 
    184206                desc=(col == order and not desc and 1 or None)) 
    185207 
    186208        # ''Zip Archive'' alternate link 
     
    196218                              'items': info, 'changes': changes, 
    197219                              'order_href': switch_ordering_hrefs} 
    198220 
    199     def _render_file(self, req, repos, node, rev=None): 
     221    def _render_file(self, req, repos, node, rev, format): 
    200222        req.perm.assert_permission('FILE_VIEW') 
    201223 
    202224        mimeview = Mimeview(self.env) 
     
    210232                        mime_type or 'text/plain' 
    211233 
    212234        # Eventually send the file directly 
    213         format = req.args.get('format') 
    214235        if format in ['raw', 'txt']: 
    215236            req.send_response(200) 
    216237            req.send_header('Content-Type', 
     
    247268 
    248269            # add ''Plain Text'' alternate link if needed 
    249270            if not is_binary(chunk) and mime_type != 'text/plain': 
    250                 plain_href = req.href.browser(node.path, rev=rev, format='txt') 
     271                plain_href = self.href(req, node.path, rev=rev, format='txt') 
    251272                add_link(req, 'alternate', plain_href, 'Plain Text', 
    252273                         'text/plain') 
    253274 
    254275            # add ''Original Format'' alternate link (always) 
    255             raw_href = req.href.browser(node.path, rev=rev, format='raw') 
     276            raw_href = self.href(req, node.path, rev=rev, format='raw') 
    256277            add_link(req, 'alternate', raw_href, 'Original Format', mime_type) 
    257278 
    258279            self.log.debug("Rendering preview of node %s@%s with mime-type %s" 
     
    287308        else: 
    288309            anchor = '' 
    289310        label = urllib.unquote(label) 
    290         return html.A(href=formatter.href.browser(path, rev=rev) + anchor, 
    291                       class_='source')[label] 
     311        href = formatter.href.browser(path, rev=rev) 
     312        if formatter.req: 
     313            href = self.href(formatter.req, path, rev=rev) 
     314        return html.A(label, href=href+anchor, class_='source') 
  • trac/Search.py

     
    237237            return req.href.milestone(kwd[len('milestone:'):]) 
    238238        # Source quickjump 
    239239        elif kwd[0] == '/': 
    240             return req.href.browser(kwd) 
     240            from trac.versioncontrol.web_ui.browser import BrowserModule 
     241            return BrowserModule(self.env).href(req, kwd) 
    241242        elif kwd[0:len('source:')] == 'source:': 
    242             return req.href.browser(kwd[len('source:'):]) 
     243            from trac.versioncontrol.web_ui.browser import BrowserModule 
     244            return BrowserModule(self.env).href(req, kwd[len('source:'):]) 
    243245        # Wiki quickjump 
    244246        elif kwd[0:len('wiki:')] == 'wiki:': 
    245247            r = "((^|(?<=[^A-Za-z]))[!]?[A-Z][a-z/]+(?:[A-Z][a-z/]+)+)" 
  • trac/wiki/api.py

     
    227227    # IWikiSyntaxProvider methods 
    228228     
    229229    def get_wiki_syntax(self): 
     230        from trac.wiki.formatter import Formatter 
    230231        yield (r"!?(?<!/)\b[A-Z][a-z]+(?:[A-Z][a-z]*[a-z/])+" 
    231232                "(?:#[A-Za-z0-9]+)?(?=:?\Z|:?\s|[.,;!?\)}\]])", 
    232233               lambda x, y, z: self._format_link(x, 'wiki', y, y, 
    233234                                                 self.ignore_missing_pages)) 
     235        yield (r"!?(\[%s\])" %  Formatter.QUOTED_STRING, 
     236               lambda x, y, z: self._format_link(x, 'wiki', y, y, False)) 
    234237 
    235238    def get_link_resolvers(self): 
    236239        yield ('wiki', self._format_fancy_link) 
  • trac/wiki/tests/formatter.py

     
    127127                % (msg, self.file, self.line, self.title, formatter.flavor)) 
    128128 
    129129    def formatter(self): 
    130         return Formatter(self.env) 
     130        return Formatter(self.env, self.env) 
     131    # Well, in the above, we fake `req` using `self.env`, as all we care about 
     132    # is the `href` attribute (at least for those unit tests!) 
    131133 
    132134    def shortDescription(self): 
    133135        return 'Test ' + self.title 
  • trac/wiki/tests/macros.py

     
    11import unittest 
    22 
    33import trac.wiki.macros 
     4from trac.versioncontrol.web_ui.browser import BrowserModule 
    45from trac.wiki.tests import formatter 
    56 
    67IMAGE_MACRO_TEST_CASES=u""" 
  • trac/wiki/formatter.py

     
    149149    ENDBLOCK_TOKEN = r"\}\}\}" 
    150150    ENDBLOCK = "}}}" 
    151151     
    152     LINK_SCHEME = r"[\w.+-]+" # as per RFC 2396 
     152    LINK_SCHEME = r"[a-zA-Z][a-zA-Z0-9.+-]*" # as per RFC 3986 
    153153    INTERTRAC_SCHEME = r"[a-zA-Z.+-]*?" # no digits (support for shorthand links) 
    154154 
    155155    QUOTED_STRING = r"'[^']+'|\"[^\"]+\"" 
  • trac/wiki/macros.py

     
    288288                raise Exception("%s module can't have attachments" % parts[0]) 
    289289        elif len(parts) == 2: 
    290290            from trac.versioncontrol.web_ui import BrowserModule 
     291            browser = BrowserModule(self.env) 
    291292            try: 
    292                 browser_links = [link for link,_ in  
    293                                  BrowserModule(self.env).get_link_resolvers()] 
     293                browser_links = [link for link,_ in 
     294                                 browser.get_link_resolvers()] 
    294295            except Exception: 
    295296                browser_links = [] 
    296297            if parts[0] in browser_links:   # source:path 
     
    298299                rev = None 
    299300                if '@' in file: 
    300301                    file, rev = file.split('@') 
    301                 url = self.env.href.browser(file, rev=rev) 
    302                 raw_url = self.env.href.browser(file, rev=rev, format='raw') 
     302                url = browser.href(req, file, rev=rev) 
     303                raw_url = browser.href(req, file, rev=rev, format='raw') 
    303304                desc = filespec 
    304305            else: # #ticket:attachment or WikiPage:attachment 
    305306                # FIXME: do something generic about shorthand forms...