Esempio n. 1
0
    def expand_macro(self, formatter, name, content):
        env = formatter.env
        req = formatter.req
        if not 'VOTE_VIEW' in req.perm:
            return
        # Simplify function calls.
        format_author = partial(Chrome(self.env).format_author, req)
        if not content:
            args = []
            compact = None
            kw = {}
            top = 5
        else:
            args, kw = parse_args(content)
            compact = 'compact' in args and True
            top = as_int(kw.get('top'), 5, min=0)

        if name == 'LastVoted':
            lst = tag.ul()
            for i in self.get_votes(req, top=top):
                resource = Resource(i[0], i[1])
                # Anotate who and when.
                voted = ('by %s at %s'
                         % (format_author(i[3]),
                            format_datetime(to_datetime(i[4]))))
                lst(tag.li(tag.a(
                    get_resource_description(env, resource, compact and
                                             'compact' or 'default'),
                    href=get_resource_url(env, resource, formatter.href),
                    title=(compact and '%+i %s' % (i[2], voted) or None)),
                    (not compact and Markup(' %s %s' % (tag.b('%+i' % i[2]),
                                                        voted)) or '')))
            return lst

        elif name == 'TopVoted':
            realm = kw.get('realm')
            lst = tag.ul()
            for i in self.get_top_voted(req, realm=realm, top=top):
                if 'up-only' in args and i[2] < 1:
                    break
                resource = Resource(i[0], i[1])
                lst(tag.li(tag.a(
                    get_resource_description(env, resource, compact and
                                             'compact' or 'default'),
                    href=get_resource_url(env, resource, formatter.href),
                    title=(compact and '%+i' % i[2] or None)),
                    (not compact and ' (%+i)' % i[2] or '')))
            return lst

        elif name == 'VoteList':
            lst = tag.ul()
            resource = resource_from_path(env, req.path_info)
            for i in self.get_votes(req, resource, top=top):
                vote = ('at %s' % format_datetime(to_datetime(i[4])))
                lst(tag.li(
                    compact and format_author(i[3]) or
                    Markup(u'%s by %s %s' % (tag.b('%+i' % i[2]),
                                             tag(format_author(i[3])), vote)),
                    title=(compact and '%+i %s' % (i[2], vote) or None)))
            return lst
 def do_update(db):
     mailinglist = Mailinglist.select_by_address(self.env, mailinglist_emailpart,
                                                 localpart=True, db=db)
     if req.args.get('updatepostergroups'):
         current_statuses =  mailinglist.groups()
     else:
         current_statuses =  mailinglist.individuals()
     for subname, poster in current_statuses:
         if req.args.get('updatepostergroups'):                            
             updater = partial(mailinglist.update_poster, group=subname)
         else:
             updater = partial(mailinglist.update_poster, user=subname)                            
         if poster and subname not in sel:
             updater(poster=False)
         elif not poster and subname in sel:
             updater(poster=True)
Esempio n. 3
0
 def content(self, req, ticket):
     data = {"headline": "Dependency Graph for Ticket #%s" % ticket.id}
     data["tkt"] = ticket
     g = self._build_graph(req, ticket.id)
     data["graph"] = g
     data["graph_render"] = partial(g.render, self.dot_path)
     data["use_gs"] = self.use_gs
     data["path"] = req.href.depgraph(ticket.id)
     return Chrome(self.env).load_template("depgraph-sidebar.html").generate(**data)
Esempio n. 4
0
 def content(self, req, ticket):
     data = {'headline': 'Dependency Graph for Ticket #%s' %ticket.id }
     data['tkt'] = ticket
     g = self._build_graph(req, ticket.id)
     data['graph'] = g
     data['graph_render'] = partial(g.render, self.dot_path)
     data['use_gs'] = self.use_gs
     data['path'] = req.href.depgraph(ticket.id)
     return Chrome(self.env).load_template('depgraph-sidebar.html').generate(**data)
Esempio n. 5
0
 def content(self, req, ticket):
     data = {'headline': 'Dependency Graph for Ticket #%s' % ticket.id}
     data['tkt'] = ticket
     g = self._build_graph(req, ticket.id)
     data['graph'] = g
     data['graph_render'] = partial(g.render, self.dot_path)
     data['use_gs'] = self.use_gs
     data['path'] = req.href.depgraph(ticket.id)
     return Chrome(
         self.env).load_template('depgraph-sidebar.html').generate(**data)
Esempio n. 6
0
    def _transform(self, stream, req, filename, url):
        filename = filename.rstrip('.html')
        xpath = self._get_config('transform_xpath', filename)
        method = self._get_config('transform_method', filename)
        class_ = self._get_config('buttons_class', filename)
        style = self._get_config('buttons_style', filename)

        if method not in ('after', 'before', 'append', 'prepend'):
            return stream

        locale = req.locale and str(req.locale)
        transformer = Transformer(xpath)
        kwargs = {'class_': class_ or None, 'style': style or None}
        create = partial(self._create_buttons, url, locale, kwargs)
        return stream | getattr(transformer, method)(create)
Esempio n. 7
0
    def _transform(self, stream, req, filename, url):
        filename = filename.rstrip('.html')
        xpath = self._get_config('transform_xpath', filename)
        method = self._get_config('transform_method', filename)
        class_ = self._get_config('buttons_class', filename)
        style = self._get_config('buttons_style', filename)

        if method not in ('after', 'before', 'append', 'prepend'):
            return stream

        locale = req.locale and str(req.locale)
        transformer = Transformer(xpath)
        kwargs = {'class_': class_ or None, 'style': style or None}
        create = partial(self._create_buttons, url, locale, kwargs)
        return stream | getattr(transformer, method)(create)
Esempio n. 8
0
    def process_request(self, req):
        path_info = req.path_info[10:]

        if not path_info:
            raise TracError('No ticket specified')

        tkt_id = path_info.split('/', 1)[0]
        g = self._build_graph(req, tkt_id)
        if '/' in path_info or 'format' in req.args:

            format = req.args.get('format')
            if format == 'text':
                req.send(str(g), 'text/plain')
            elif format == 'debug':
                import pprint
                req.send(pprint.pformat(TicketLinks(self.env, tkt_id)),
                         'text/plain')
            elif format is not None:
                req.send(g.render(self.dot_path, format), 'text/plain')

            if self.use_gs:
                ps = g.render(self.dot_path, 'ps2')
                gs = subprocess.Popen([
                    self.gs_path, '-q', '-dTextAlphaBits=4',
                    '-dGraphicsAlphaBits=4', '-sDEVICE=png16m', '-o',
                    '%stdout%', '-'
                ],
                                      stdin=subprocess.PIPE,
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE)
                img, err = gs.communicate(ps)
                if err:
                    self.log.debug('MasterTickets: Error from gs: %s', err)
            else:
                img = g.render(self.dot_path)
            req.send(img, 'image/png')
        else:
            data = {}

            tkt = Ticket(self.env, tkt_id)
            data['tkt'] = tkt
            data['graph'] = g
            data['graph_render'] = partial(g.render, self.dot_path)
            data['use_gs'] = self.use_gs

            add_ctxtnav(req, 'Back to Ticket #%s' % tkt.id,
                        req.href.ticket(tkt_id))
            return 'depgraph.html', data, None
Esempio n. 9
0
 def _reindex_changeset(self, realm, feedback, finish_fb):
     """Iterate all changesets and call self.changeset_added on them"""
     # TODO Multiple repository support
     repo = self.env.get_repository()
     def all_revs():
         rev = repo.oldest_rev
         yield rev
         while 1:
             rev = repo.next_rev(rev)
             if rev is None:
                 return
             yield rev
     def check(changeset, status):
         return status is None or changeset.date > to_datetime(int(status))
     resources = (repo.get_changeset(rev) for rev in all_revs())
     index = partial(self.changeset_added, repo)
     return self._index(realm, resources, check, index, feedback, finish_fb)
Esempio n. 10
0
    def process_request(self, req):
        """ process the request and render the response template
        """
        if TESTER_PERMISSION in req.perm:
            # add default trac admin css
            add_stylesheet(req, 'common/css/admin.css')
            # custom css
            add_stylesheet(req, 'TestManager/css/testmanager.css')

            # get the panels and their providers
            panels, providers = self._get_panels(req)
            if not panels:
                # no providers found
                raise HTTPNotFound(_('No TestManager panels available'))

            # Navigation tree
            cat_id    = req.args.get('cat_id') or panels[0][0]
            panel_id  = req.args.get('panel_id')
            path_info = req.args.get('path_info')
            # TODO: what to do? REFACTOR!
            if not panel_id:
                panel_id = filter(lambda panel: panel[0] == cat_id, panels)[0][2]

            provider = providers.get((cat_id, panel_id), None)
            if not provider:
                raise HTTPNotFound(_('Unknown TestManager panel'))

            data = dict()
            if hasattr(provider, 'render_admin_panel'):
                template, data = provider.render_admin_panel(req, cat_id, panel_id, path_info)

            data.update({
                'active_cat': cat_id,
                'active_panel': panel_id,
                'panel_href': partial(req.href, 'TestManager', cat_id, panel_id),
                'panels': [{
                    'category': {'id': panel[0], 'label': panel[1]},
                    'panel': {'id': panel[2], 'label': panel[3]}
                } for panel in panels]
            })

            return template, data, None
Esempio n. 11
0
    def _reindex_changeset(self, realm, feedback, finish_fb):
        """Iterate all changesets and call self.changeset_added on them"""
        # TODO Multiple repository support
        repo = self.env.get_repository()

        def all_revs():
            rev = repo.oldest_rev
            yield rev
            while 1:
                rev = repo.next_rev(rev)
                if rev is None:
                    return
                yield rev

        def check(changeset, status):
            return status is None or changeset.date > to_datetime(int(status))

        resources = (repo.get_changeset(rev) for rev in all_revs())
        index = partial(self.changeset_added, repo)
        return self._index(realm, resources, check, index, feedback, finish_fb)
Esempio n. 12
0
 def process_request(self, req):
     path_info = req.path_info[10:]
     
     if not path_info:
         raise TracError('No ticket specified')
     
     tkt_id = path_info.split('/', 1)[0]
     g = self._build_graph(req, tkt_id)
     if '/' in path_info or 'format' in req.args:
         
         format = req.args.get('format')
         if format == 'text':
             req.send(str(g), 'text/plain')
         elif format == 'debug':
             import pprint
             req.send(pprint.pformat(TicketLinks(self.env, tkt_id)), 'text/plain')
         elif format is not None:
             req.send(g.render(self.dot_path, format), 'text/plain')
         
         if self.use_gs:
             ps = g.render(self.dot_path, 'ps2')
             gs = subprocess.Popen([self.gs_path, '-q', '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4', '-sDEVICE=png16m', '-sOutputFile=%stdout%', '-'], 
                                   stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
             img, err = gs.communicate(ps)
             if err:
                 self.log.debug('MasterTickets: Error from gs: %s', err)
         else:
             img = g.render(self.dot_path)
         req.send(img, 'image/png')
     else:
         data = {}
         
         tkt = Ticket(self.env, tkt_id)
         data['tkt'] = tkt
         data['graph'] = g
         data['graph_render'] = partial(g.render, self.dot_path)
         data['use_gs'] = self.use_gs
         
         add_ctxtnav(req, 'Back to Ticket #%s'%tkt.id, req.href.ticket(tkt_id))
         return 'depgraph.html', data, None
Esempio n. 13
0
    def process_request(self, req):
        panels, providers = self._get_panels(req)
        if not panels:
            raise HTTPNotFound(_('No monitoring panels available'))

        panels.sort()
        cat_id = req.args.get('cat_id') or panels[0][0]
        panel_id = req.args.get('panel_id')
        path_info = req.args.get('path_info')
        if not panel_id:
            panel_id = filter(lambda panel: panel[0] == cat_id, panels)[0][2]

        provider = providers.get((cat_id, panel_id), None)
        if not provider:
            raise HTTPNotFound(_('Unknown monitoring panel'))

        if hasattr(provider, 'render_panel'):
            res  = provider.render_panel(req, cat_id, panel_id,
                                                         path_info)
            if len(res) == 2:
              template, data = res
              contenttype = None
            elif len(res) == 3:
              template, data, contenttype = res
              
        data.update({
            'active_cat': cat_id, 'active_panel': panel_id,
            'panel_href': partial(req.href, 'monitoring', cat_id, panel_id),
            'panels': [{
                'category': {'id': panel[0], 'label': panel[1]},
                'panel': {'id': panel[2], 'label': panel[3]}
            } for panel in panels]
        })

        add_stylesheet(req, 'common/css/admin.css')
        return template, data, contenttype
Esempio n. 14
0
    def dispatch(self, req):
        """Find a registered handler that matches the request and let it process
        it.
        
        In addition, this method initializes the HDF data set and adds the web
        site chrome.
        """
        self.log.debug('Dispatching %r', req)
        chrome = Chrome(self.env)

        # Setup request callbacks for lazily-evaluated properties
        req.callbacks.update({
            'authname': self.authenticate,
            'chrome': chrome.prepare_request,
            'hdf': self._get_hdf,
            'perm': self._get_perm,
            'session': self._get_session,
            'locale': self._get_locale,
            'tz': self._get_timezone,
            'form_token': self._get_form_token
        })

        try:
            try:
                # Select the component that should handle the request
                chosen_handler = None
                try:
                    for handler in self.handlers:
                        if handler.match_request(req):
                            chosen_handler = handler
                            break
                    if not chosen_handler:
                        if not req.path_info or req.path_info == '/':
                            chosen_handler = self.default_handler
                    # pre-process any incoming request, whether a handler
                    # was found or not
                    chosen_handler = self._pre_process_request(
                        req, chosen_handler)
                except TracError, e:
                    raise HTTPInternalError(e)
                if not chosen_handler:
                    if req.path_info.endswith('/'):
                        # Strip trailing / and redirect
                        target = req.path_info.rstrip('/').encode('utf-8')
                        if req.query_string:
                            target += '?' + req.query_string
                        req.redirect(req.href + target, permanent=True)
                    raise HTTPNotFound('No handler matched request to %s',
                                       req.path_info)

                req.callbacks['chrome'] = partial(chrome.prepare_request,
                                                  handler=chosen_handler)

                # Protect against CSRF attacks: we validate the form token
                # for all POST requests with a content-type corresponding
                # to form submissions
                if req.method == 'POST':
                    ctype = req.get_header('Content-Type')
                    if ctype:
                        ctype, options = cgi.parse_header(ctype)
                    if ctype in ('application/x-www-form-urlencoded',
                                 'multipart/form-data') and \
                            req.args.get('__FORM_TOKEN') != req.form_token:
                        if self.env.secure_cookies and req.scheme == 'http':
                            msg = _('Secure cookies are enabled, you must '
                                    'use https to submit forms.')
                        else:
                            msg = _('Do you have cookies enabled?')
                        raise HTTPBadRequest(
                            _('Missing or invalid form token.'
                              ' %(msg)s',
                              msg=msg))

                # Process the request and render the template
                resp = chosen_handler.process_request(req)
                if resp:
                    if len(resp) == 2:  # Clearsilver
                        chrome.populate_hdf(req)
                        template, content_type = \
                                  self._post_process_request(req, *resp)
                        # Give the session a chance to persist changes
                        req.session.save()
                        req.display(template, content_type or 'text/html')
                    else:  # Genshi
                        template, data, content_type = \
                                  self._post_process_request(req, *resp)
                        if 'hdfdump' in req.args:
                            req.perm.require('TRAC_ADMIN')
                            # debugging helper - no need to render first
                            out = StringIO()
                            pprint(data, out)
                            req.send(out.getvalue(), 'text/plain')
                        else:
                            output = chrome.render_template(
                                req, template, data, content_type)
                            # Give the session a chance to persist changes
                            req.session.save()
                            req.send(output, content_type or 'text/html')
                else:
                    self._post_process_request(req)
            except RequestDone:
                raise
            except:
                # post-process the request in case of errors
                err = sys.exc_info()
                try:
                    self._post_process_request(req)
                except RequestDone:
                    raise
                except Exception, e:
                    self.log.error(
                        "Exception caught while post-processing"
                        " request: %s", exception_to_unicode(e,
                                                             traceback=True))
                raise err[0], err[1], err[2]
Esempio n. 15
0
    def process_request(self, req):
        panels, providers = self._get_panels(req)
        if not panels:
            raise HTTPNotFound(_('No administration panels available'))

        def _panel_order(p1, p2):
            if p1[::2] == ('general', 'basics'):
                return -1
            elif p2[::2] == ('general', 'basics'):
                return 1
            elif p1[0] == 'general':
                if p2[0] == 'general':
                    return cmp(p1[1:], p2[1:])
                return -1
            elif p2[0] == 'general':
                if p1[0] == 'general':
                    return cmp(p1[1:], p2[1:])
                return 1
            return cmp(p1, p2)
        panels.sort(_panel_order)

        cat_id = req.args.get('cat_id') or panels[0][0]
        panel_id = req.args.get('panel_id')
        path_info = req.args.get('path_info')
        if not panel_id:
            try:
                panel_id = filter(
                            lambda panel: panel[0] == cat_id, panels)[0][2]
            except IndexError:
                raise HTTPNotFound(_('Unknown administration panel'))

        provider = providers.get((cat_id, panel_id), None)
        if not provider:
            raise HTTPNotFound(_('Unknown administration panel'))

        if hasattr(provider, 'render_admin_panel'):
            template, data = provider.render_admin_panel(req, cat_id, panel_id,
                                                         path_info)

        else: # support for legacy WebAdmin panels
            data = {}
            cstmpl, ct = provider.process_admin_request(req, cat_id, panel_id,
                                                        path_info)
            if isinstance(cstmpl, basestring):
                output = req.hdf.render(cstmpl)
            else:
                output = cstmpl.render()

            title = 'Untitled'
            for panel in panels:
                if (panel[0], panel[2]) == (cat_id, panel_id):
                    title = panel[3]

            data.update({'page_title': title, 'page_body': HTML(output)})
            template = 'admin_legacy.html'

        data.update({
            'active_cat': cat_id, 'active_panel': panel_id,
            'panel_href': partial(req.href, 'admin', cat_id, panel_id),
            'panels': [{
                'category': {'id': panel[0], 'label': panel[1]},
                'panel': {'id': panel[2], 'label': panel[3]}
            } for panel in panels]
        })

        add_stylesheet(req, 'common/css/admin.css')
        return template, data, None
Esempio n. 16
0
    def process_request(self, req):
        path_info = req.path_info[10:]

        if not path_info:
            raise TracError('No ticket specified')

        #list of tickets to generate the depgraph for
        tkt_ids = []
        milestone = None
        split_path = path_info.split('/', 2)

        #Urls to generate the depgraph for a ticket is /depgraph/ticketnum
        #Urls to generate the depgraph for a milestone is /depgraph/milestone/milestone_name
        if split_path[0] == 'milestone':
            #we need to query the list of tickets in the milestone
            milestone = split_path[1]
            query = Query(self.env,
                          constraints={'milestone': [milestone]},
                          max=0)
            tkt_ids = [fields['id'] for fields in query.execute()]
        else:
            #the list is a single ticket
            tkt_ids = [int(split_path[0])]

        #the summary argument defines whether we place the ticket id or
        #it's summary in the node's label
        label_summary = 0
        if 'summary' in req.args:
            label_summary = int(req.args.get('summary'))

        g = self._build_graph(req, tkt_ids, label_summary=label_summary)
        if path_info.endswith('/depgraph.png') or 'format' in req.args:
            format = req.args.get('format')
            if format == 'text':
                #in case g.__str__ returns unicode, we need to convert it in ascii
                req.send(
                    to_unicode(g).encode('ascii', 'replace'), 'text/plain')
            elif format == 'debug':
                import pprint
                req.send(
                    pprint.pformat(
                        [TicketLinks(self.env, tkt_id) for tkt_id in tkt_ids]),
                    'text/plain')
            elif format is not None:
                req.send(g.render(self.dot_path, format), 'text/plain')

            if self.use_gs:
                ps = g.render(self.dot_path, 'ps2')
                gs = subprocess.Popen([
                    self.gs_path, '-q', '-dTextAlphaBits=4',
                    '-dGraphicsAlphaBits=4', '-sDEVICE=png16m',
                    '-sOutputFile=%stdout%', '-'
                ],
                                      stdin=subprocess.PIPE,
                                      stdout=subprocess.PIPE,
                                      stderr=subprocess.PIPE)
                img, err = gs.communicate(ps)
                if err:
                    self.log.debug('MasterTickets: Error from gs: %s', err)
            else:
                img = g.render(self.dot_path)
            req.send(img, 'image/png')
        else:
            data = {}

            #add a context link to enable/disable labels in nodes
            if label_summary:
                add_ctxtnav(req, 'Without labels',
                            req.href(req.path_info, summary=0))
            else:
                add_ctxtnav(req, 'With labels',
                            req.href(req.path_info, summary=1))

            if milestone is None:
                tkt = Ticket(self.env, tkt_ids[0])
                data['tkt'] = tkt
                add_ctxtnav(req, 'Back to Ticket #%s' % tkt.id,
                            req.href.ticket(tkt.id))
            else:
                add_ctxtnav(req, 'Back to Milestone %s' % milestone,
                            req.href.milestone(milestone))
            data['milestone'] = milestone
            data['graph'] = g
            data['graph_render'] = partial(g.render, self.dot_path)
            data['use_gs'] = self.use_gs

            return 'depgraph.html', data, None
    def process_request(self, req):
        realm = req.args['realm']
        id = req.args['id']

        #Urls to generate the depgraph for a ticket is /depgraph/ticketnum
        #Urls to generate the depgraph for a milestone is /depgraph/milestone/milestone_name

        #List of tickets to generate the depgraph for
        tkt_ids = []
        if realm == 'milestone':
            #we need to query the list of tickets in the milestone
            query = Query(self.env, constraints={'milestone': [id]}, max=0)
            tkt_ids = [fields['id'] for fields in query.execute(req)]
        else:
            #the list is a single ticket
            tkt_ids = [int(id)]

        #the summary argument defines whether we place the ticket id or
        #its summary in the node's label
        label_summary = 0
        if 'summary' in req.args:
            label_summary = int(req.args.get('summary'))

        g = self._build_graph(req, tkt_ids, label_summary=label_summary)
        if req.path_info.endswith('/depgraph.png') or 'format' in req.args:
            format = req.args.get('format')
            if format == 'text':
                #in case g.__str__ returns unicode, we need to convert it in ascii
                req.send(to_unicode(g).encode('ascii', 'replace'), 'text/plain')
            elif format == 'debug':
                import pprint

                req.send(
                    pprint.pformat(
                        [TicketLinks(self.env, tkt_id) for tkt_id in tkt_ids]
                    ),
                    'text/plain')
            elif format is not None:
                if format in self.acceptable_formats:
                    req.send(g.render(self.dot_path, format), 'text/plain')
                else:
                    raise TracError(_("The %(format)s format is not allowed.", format=format))

            if self.use_gs:
                ps = g.render(self.dot_path, 'ps2')
                gs = subprocess.Popen(
                    [self.gs_path, '-q', '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4', '-sDEVICE=png16m',
                     '-sOutputFile=%stdout%', '-'],
                    stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                img, err = gs.communicate(ps)
                if err:
                    self.log.debug('MasterTickets: Error from gs: %s', err)
            else:
                img = g.render(self.dot_path)
            req.send(img, 'image/png')
        else:
            data = {}

            #add a context link to enable/disable labels in nodes
            if label_summary:
                add_ctxtnav(req, 'Without labels', req.href(req.path_info, summary=0))
            else:
                add_ctxtnav(req, 'With labels', req.href(req.path_info, summary=1))

            if realm == 'milestone':
                add_ctxtnav(req, 'Back to Milestone: %s' % id, req.href.milestone(id))
                data['milestone'] = id
            else:
                data['ticket'] = id
                add_ctxtnav(req, 'Back to Ticket #%s' % id, req.href.ticket(id))
            data['graph'] = g
            data['graph_render'] = partial(g.render, self.dot_path)
            data['use_gs'] = self.use_gs

            return 'depgraph.html', data, None
Esempio n. 18
0
    def process_request(self, req):
        panels, providers = self._get_panels(req)
        if not panels:
            raise HTTPNotFound(_('No administration panels available'))

        def _panel_order(p1, p2):
            if p1[::2] == ('general', 'basics'):
                return -1
            elif p2[::2] == ('general', 'basics'):
                return 1
            elif p1[0] == 'general':
                if p2[0] == 'general':
                    return cmp(p1[1:], p2[1:])
                return -1
            elif p2[0] == 'general':
                if p1[0] == 'general':
                    return cmp(p1[1:], p2[1:])
                return 1
            return cmp(p1, p2)

        panels.sort(_panel_order)

        cat_id = req.args.get('cat_id') or panels[0][0]
        panel_id = req.args.get('panel_id')
        path_info = req.args.get('path_info')
        if not panel_id:
            try:
                panel_id = filter(lambda panel: panel[0] == cat_id,
                                  panels)[0][2]
            except IndexError:
                raise HTTPNotFound(_('Unknown administration panel'))

        provider = providers.get((cat_id, panel_id), None)
        if not provider:
            raise HTTPNotFound(_('Unknown administration panel'))

        if hasattr(provider, 'render_admin_panel'):
            template, data = provider.render_admin_panel(
                req, cat_id, panel_id, path_info)

        else:  # support for legacy WebAdmin panels
            data = {}
            cstmpl, ct = provider.process_admin_request(
                req, cat_id, panel_id, path_info)
            if isinstance(cstmpl, basestring):
                output = req.hdf.render(cstmpl)
            else:
                output = cstmpl.render()

            title = 'Untitled'
            for panel in panels:
                if (panel[0], panel[2]) == (cat_id, panel_id):
                    title = panel[3]

            data.update({'page_title': title, 'page_body': HTML(output)})
            template = 'admin_legacy.html'

        data.update({
            'active_cat':
            cat_id,
            'active_panel':
            panel_id,
            'panel_href':
            partial(req.href, 'admin', cat_id, panel_id),
            'panels': [{
                'category': {
                    'id': panel[0],
                    'label': panel[1]
                },
                'panel': {
                    'id': panel[2],
                    'label': panel[3]
                }
            } for panel in panels]
        })

        add_stylesheet(req, 'common/css/admin.css')
        return template, data, None
Esempio n. 19
0
    def populate_data(self, req, data):
        d = self._default_context_data.copy()
        d['trac'] = {
            'version': VERSION,
            'homepage': 'http://trac.edgewall.org/', # FIXME: use setup data
            'systeminfo': self.env.systeminfo,
        }
        
        href = req and req.href
        abs_href = req and req.abs_href or self.env.abs_href
        admin_href = None
        if self.env.project_admin_trac_url == '.':
            admin_href = href
        elif self.env.project_admin_trac_url:
            admin_href = Href(self.env.project_admin_trac_url)
            
        d['project'] = {
            'name': self.env.project_name,
            'descr': self.env.project_description,
            'url': self.env.project_url,
            'admin': self.env.project_admin,
            'admin_href': admin_href,
            'admin_trac_url': self.env.project_admin_trac_url,
        }
        d['chrome'] = {
            'footer': Markup(self.env.project_footer)
        }
        if req:
            d['chrome'].update(req.chrome)
        else:
            d['chrome'].update({
                'htdocs_location': self.htdocs_location,
                'logo': self.get_logo_data(self.env.abs_href),
            })

        show_email_addresses = (self.show_email_addresses or not req or \
                                'EMAIL_VIEW' in req.perm)
        tzinfo = None
        if req:
            tzinfo = req.tz

        def dateinfo(date):
            return tag.span(pretty_timedelta(date),
                            title=format_datetime(date))

        def get_rel_url(resource, **kwargs):
            return get_resource_url(self.env, resource, href, **kwargs)

        def get_abs_url(resource, **kwargs):
            return get_resource_url(self.env, resource, abs_href, **kwargs)

        d.update({
            'context': req and Context.from_request(req) or None,
            'url_of': get_rel_url,
            'abs_url_of': get_abs_url,
            'name_of': partial(get_resource_name, self.env),
            'shortname_of': partial(get_resource_shortname, self.env),
            'summary_of': partial(get_resource_summary, self.env),
            'req': req,
            'abs_href': abs_href,
            'href': href,
            'perm': req and req.perm,
            'authname': req and req.authname or '<trac>',
            'show_email_addresses': show_email_addresses,
            'show_ip_addresses': self.show_ip_addresses,
            'format_author': partial(self.format_author, req),
            'format_emails': self.format_emails,

            # Date/time formatting
            'dateinfo': dateinfo,
            'format_datetime': partial(format_datetime, tzinfo=tzinfo),
            'format_date': partial(format_date, tzinfo=tzinfo),
            'format_time': partial(format_time, tzinfo=tzinfo),
            'fromtimestamp': partial(datetime.datetime.fromtimestamp,
                                     tz=tzinfo),

            # Wiki-formatting functions
            'wiki_to': partial(format_to, self.env),
            'wiki_to_html': partial(format_to_html, self.env),
            'wiki_to_oneliner': partial(format_to_oneliner, self.env),
        })

        # Finally merge in the page-specific data
        d.update(data)
        return d
Esempio n. 20
0
    def expand_macro(self, formatter, name, content):
        env = formatter.env
        req = formatter.req
        if not 'VOTE_VIEW' in req.perm:
            return
        # Simplify function calls.
        format_author = partial(Chrome(self.env).format_author, req)
        if not content:
            args = []
            compact = None
            kw = {}
            top = 5
        else:
            args, kw = parse_args(content)
            compact = 'compact' in args and True
            top = as_int(kw.get('top'), 5, min=0)

        if name == 'LastVoted':
            lst = tag.ul()
            for i in self.get_votes(req, top=top):
                resource = Resource(i[0], i[1])
                # Anotate who and when.
                voted = (
                    'by %s at %s' %
                    (format_author(i[3]), format_datetime(to_datetime(i[4]))))
                lst(
                    tag.li(
                        tag.a(get_resource_description(
                            env, resource, compact and 'compact' or 'default'),
                              href=get_resource_url(env, resource,
                                                    formatter.href),
                              title=(compact and '%+i %s' % (i[2], voted)
                                     or None)),
                        (not compact and Markup(' %s %s' %
                                                (tag.b('%+i' % i[2]), voted))
                         or '')))
            return lst

        elif name == 'TopVoted':
            realm = kw.get('realm')
            lst = tag.ul()
            for i in self.get_top_voted(req, realm=realm, top=top):
                if 'up-only' in args and i[2] < 1:
                    break
                resource = Resource(i[0], i[1])
                lst(
                    tag.li(
                        tag.a(get_resource_description(
                            env, resource, compact and 'compact' or 'default'),
                              href=get_resource_url(env, resource,
                                                    formatter.href),
                              title=(compact and '%+i' % i[2] or None)),
                        (not compact and ' (%+i)' % i[2] or '')))
            return lst

        elif name == 'VoteList':
            lst = tag.ul()
            resource = resource_from_path(env, req.path_info)
            for i in self.get_votes(req, resource, top=top):
                vote = ('at %s' % format_datetime(to_datetime(i[4])))
                lst(
                    tag.li(compact and format_author(i[3]) or Markup(
                        u'%s by %s %s' %
                        (tag.b('%+i' % i[2]), tag(format_author(i[3])), vote)),
                           title=(compact and '%+i %s' % (i[2], vote)
                                  or None)))
            return lst
Esempio n. 21
0
    def dispatch(self, req):
        """Find a registered handler that matches the request and let it process
        it.
        
        In addition, this method initializes the HDF data set and adds the web
        site chrome.
        """
        self.log.debug('Dispatching %r', req)
        chrome = Chrome(self.env)

        # Setup request callbacks for lazily-evaluated properties
        req.callbacks.update({
            'authname': self.authenticate,
            'chrome': chrome.prepare_request,
            'hdf': self._get_hdf,
            'perm': self._get_perm,
            'session': self._get_session,
            'tz': self._get_timezone,
            'form_token': self._get_form_token
        })

        try:
            try:
                # Select the component that should handle the request
                chosen_handler = None
                try:
                    for handler in self.handlers:
                        if handler.match_request(req):
                            chosen_handler = handler
                            break
                    if not chosen_handler:
                        if not req.path_info or req.path_info == '/':
                            chosen_handler = self.default_handler
                    # pre-process any incoming request, whether a handler
                    # was found or not
                    chosen_handler = self._pre_process_request(req,
                                                               chosen_handler)
                except TracError, e:
                    raise HTTPInternalError(e)
                if not chosen_handler:
                    if req.path_info.endswith('/'):
                        # Strip trailing / and redirect
                        target = req.path_info.rstrip('/').encode('utf-8')
                        if req.query_string:
                            target += '?' + req.query_string
                        req.redirect(req.href + target, permanent=True)
                    raise HTTPNotFound('No handler matched request to %s',
                                       req.path_info)

                req.callbacks['chrome'] = partial(chrome.prepare_request,
                                                  handler=chosen_handler)

                # Protect against CSRF attacks: we validate the form token for
                # all POST requests with a content-type corresponding to form
                # submissions
                if req.method == 'POST':
                    ctype = req.get_header('Content-Type')
                    if ctype:
                        ctype, options = cgi.parse_header(ctype)
                    if ctype in ('application/x-www-form-urlencoded',
                                 'multipart/form-data') and \
                            req.args.get('__FORM_TOKEN') != req.form_token:
                        raise HTTPBadRequest('Missing or invalid form token. '
                                             'Do you have cookies enabled?')

                # Process the request and render the template
                resp = chosen_handler.process_request(req)
                if resp:
                    if len(resp) == 2: # Clearsilver
                        chrome.populate_hdf(req)
                        template, content_type = \
                                  self._post_process_request(req, *resp)
                        # Give the session a chance to persist changes
                        req.session.save()
                        req.display(template, content_type or 'text/html')
                    else: # Genshi
                        template, data, content_type = \
                                  self._post_process_request(req, *resp)
                        if 'hdfdump' in req.args:
                            req.perm.require('TRAC_ADMIN')
                            # debugging helper - no need to render first
                            from pprint import pprint
                            out = StringIO()
                            pprint(data, out)
                            req.send(out.getvalue(), 'text/plain')
                        else:
                            output = chrome.render_template(req, template,
                                                            data, content_type)
                            # Give the session a chance to persist changes
                            req.session.save()
                            req.send(output, content_type or 'text/html')
                else:
                    self._post_process_request(req)
            except RequestDone:
                raise
            except:
                # post-process the request in case of errors
                err = sys.exc_info()
                try:
                    self._post_process_request(req)
                except RequestDone:
                    raise
                except Exception, e:
                    self.log.error("Exception caught while post-processing"
                                   " request: %s",
                                   exception_to_unicode(e, traceback=True))
                raise err[0], err[1], err[2]
    def process_request(self, req):
        offset = req.args.get("offset",0)
        page = req.args.get('page', 1)
        try:
            offset = int(offset)
        except:
            raise TracError(_('Invalid offset used: %(offset)s', offset=offset))        
        
        try:
            page = int(page)
        except:
            raise TracError(_('Invalid page used: %(page)s', page=page))
                
        offset = (page - 1) * self.limit
        
        add_stylesheet(req, 'mailinglist/css/mailinglist.css')
        add_javascript(req, 'mailinglist/mailinglist.js')
            
        mailinglists = [m for m in Mailinglist.select(self.env)
                        if "MAILINGLIST_VIEW" in req.perm(m.resource)]

        data = {"mailinglists": mailinglists,
                "offset": offset,
                "limit": self.limit}

        if req.method == 'POST':

            if 'subscribe' in req.args:
                subscribe = True
                unsubscribe = False
                mailinglist_email = req.args.get('subscribe')
            elif 'unsubscribe' in req.args:
                subscribe = False
                unsubscribe = True
                mailinglist_email = req.args.get('unsubscribe')
            else:
                # at the moment we only post subscription info to
                # mailing list page - so if there is none in req.args we 
                # can just redirect to mailing list page
                req.redirect(req.href.mailinglist())

            # get mailing list object and check permissions
            mailinglist = Mailinglist.select_by_address(self.env,
                                                    mailinglist_email, localpart=True)
            req.perm(mailinglist.resource).require("MAILINGLIST_VIEW")

            if subscribe:
                mailinglist.subscribe(user=req.authname)
                # subscribe does not return a value to indicate if it 
                # was successful, so we have to explicitly check
                if mailinglist.is_subscribed(req.authname):
                    add_notice(req, _('You have been subscribed to %s.' % mailinglist.name))
                else:
                    add_notice(req, _('Unable to subscribe to %s.' % mailinglist.name))
            elif unsubscribe:
                mailinglist.unsubscribe(user=req.authname)
                # unsubscribe does not return a value to indicate if it 
                # was successful, so we have to explicitly check
                if not mailinglist.is_subscribed(req.authname):
                    add_notice(req, _('You have been unsubscribed from %s.' % mailinglist.name))
                else:
                    add_notice(req, _('Unable to unsubscribe from %s.' % mailinglist.name))

            if req.path_info.endswith('/mailinglist'):
                 # overview mailing list page
                req.redirect(req.href.mailinglist())
            elif 'conversationid' in req.args:
                # individual mailing list conversation log
                req.redirect(req.href.mailinglist(mailinglist_email, req.args['conversationid']))
            else:
                # individual mailing list homepage
                req.redirect(req.href.mailinglist(mailinglist_email))

        #for mailinglist in mailinglists:
        #    add_ctxtnav(req,
        #                _("List: %s") % mailinglist.name,
        #                req.href.mailinglist(mailinglist.emailaddress))
		
        if 'messageid' in req.args:
            message = MailinglistMessage(self.env, req.args['messageid'])
            # leaks the subject of the email in the error, wonder if
            # that's a problem...
            req.perm(message.resource).require("MAILINGLIST_VIEW")
            if req.args.get('format') == "raw":
                req.send_header('Content-Disposition', 'attachment')
                req.send_response(200)
                content = message.raw.bytes
                req.send_header('Content-Type', 'application/mbox')
                req.send_header('Content-Length', len(content))
                req.end_headers()
                if req.method != 'HEAD':
                    req.write(content)
                return

            context = Context.from_request(req, message.resource)
            
            data['message'] = message
            data['attachments'] = AttachmentModule(self.env).attachment_data(context)

            add_link(req, 'up', get_resource_url(self.env, message.conversation.resource, req.href,
                                                 offset=data['offset']),
                     _("Back to conversation"))

            prevnext_nav(req, _("Newer message"), _("Older message"), 
                         _("Back to conversation"))

            raw_href = get_resource_url(self.env, message.resource,
                                        req.href, format='raw')
            add_link(req, 'alternate', raw_href, _('mbox'), "application/mbox")

            if 'MAILINGLIST_ADMIN' in req.perm:
                add_ctxtnav(req, tag.a(tag.i(class_="fa fa-cog"), ' Manage List',
                href=req.href.admin('mailinglist', 'lists', message.conversation.mailinglist.emailaddress),
                title='Manage and subscribe users to the %s mailing list' % message.conversation.mailinglist.name))

            return 'mailinglist_message.html', data, None
            
        if 'conversationid' in req.args:
            conversation = MailinglistConversation(self.env, req.args['conversationid'])
            # also leaks the subject of the first email in the error message
            req.perm(conversation.resource).require("MAILINGLIST_VIEW")
            data['conversation'] = conversation
            data['attachmentselect'] = partial(Attachment.select, self.env)
            
            results = Paginator(conversation.messages(), page - 1, self.limit)
            if results.has_next_page:
                next_href = get_resource_url(self.env, conversation.resource, req.href, page=page + 1) 
                add_link(req, 'next', next_href, _('Next Page'))

            if results.has_previous_page:
                prev_href = get_resource_url(self.env, conversation.resource, req.href, page=page - 1) 
                add_link(req, 'prev', prev_href, _('Previous Page'))
            
            shown_pages = results.get_shown_pages()
            pagedata = [{'href': get_resource_url(self.env,
                                                  conversation.resource,
                                                  req.href, page=page),
                         'class': None, 'string': str(page),
                         'title': _('Page %(num)d', num=page)}
                        for page in shown_pages]
            results.shown_pages = pagedata
            results.current_page = {'href': None, 'class': 'current',
                                    'string': str(results.page + 1),
                                    'title': None}
            data['paginator'] = results
            add_link(req, 'up', get_resource_url(self.env, conversation.mailinglist.resource, req.href,
                                                 offset=data['offset']),
                     _("List of conversations"))

            prevnext_nav(req, _("Newer conversation"), _("Older conversation"), 
                         _("Back to list of conversations"))

            if 'MAILINGLIST_ADMIN' in req.perm:
                add_ctxtnav(req, tag.a(tag.i(class_="fa fa-cog"), ' Manage List',
                href=req.href.admin('mailinglist', 'lists', conversation.mailinglist.emailaddress),
                title='Manage and subscribe users to the %s mailing list' % conversation.mailinglist.name))


            # Check if user is already subscribed to mailing list 
            # and add the appropriate subscribe / unsubscribe ribbon option
            if conversation.mailinglist.is_subscribed(req.authname):
                add_ctxtnav(req, tag.form(tag.input(tag.a(tag.i(class_='fa fa-eye-slash'),
                ' Unsubscribe', title='Unsubscribe from the %s mailing list' % conversation.mailinglist.name, id='subscribe-link'),
                name='unsubscribe', value=conversation.mailinglist.emailaddress, class_='hidden'),
                method_='post', action='', id='subscribe-form', class_='hidden'))
            else:
                add_ctxtnav(req, tag.form(tag.input(tag.a(tag.i(class_='fa fa-eye'),
                ' Subscribe', title='Subscribe to the %s mailing list' % conversation.mailinglist.name, id='subscribe-link'),
                name='subscribe', value=conversation.mailinglist.emailaddress, class_='hidden'),
                method_='post', action='', id='subscribe-form', class_='hidden'))

            return 'mailinglist_conversation.html', data, None

        elif 'listname' in req.args:
            mailinglist = Mailinglist.select_by_address(self.env,
                                                        req.args['listname'], localpart=True)
            # leaks the name of the mailinglist
            req.perm(mailinglist.resource).require("MAILINGLIST_VIEW")

            data['mailinglist'] = mailinglist

            results = Paginator(mailinglist.conversations(),
                            page - 1,
                            self.limit)

            if results.has_next_page:
                next_href = get_resource_url(self.env, mailinglist.resource, req.href, page=page + 1) 
                add_link(req, 'next', next_href, _('Next Page'))

            if results.has_previous_page:
                prev_href = get_resource_url(self.env, mailinglist.resource, req.href, page=page - 1) 
                add_link(req, 'prev', prev_href, _('Previous Page'))

            shown_pages = results.get_shown_pages()
            pagedata = [{'href': get_resource_url(self.env,
                                                  mailinglist.resource,
                                                  req.href, page=page),
                         'class': None, 'string': str(page),
                         'title': _('Page %(num)d', num=page)}
                        for page in shown_pages]
            results.shown_pages = pagedata
            results.current_page = {'href': None, 'class': 'current',
                                    'string': str(results.page + 1),
                                    'title': None}
            data['paginator'] = results

            if data['offset'] + data['limit'] < mailinglist.count_conversations():
                add_link(req, 'next',
                         get_resource_url(self.env, mailinglist.resource, req.href,
                                          offset=data['offset']+data['limit']),
                         _("Older conversations"))

            if offset > 0:
                add_link(req, 'prev',
                         get_resource_url(self.env, mailinglist.resource, req.href,
                                          offset=data['offset']-data['limit']),
                         _("Newer conversations"))

            add_link(req, 'up', req.href.mailinglist(), _("List of mailinglists"))

            prevnext_nav(req, _("Newer conversations"), _("Older conversations"), ("Back to Mailinglists"))

            if 'MAILINGLIST_ADMIN' in req.perm:
                add_ctxtnav(req, tag.a(tag.i(class_="fa fa-cog"), ' Manage List',
                href=req.href.admin('mailinglist', 'lists', mailinglist.emailaddress),
                title='Manage and subscribe users to the %s mailing list' % mailinglist.name))

            # Check if user is already subscribed to mailing list 
            # and add the appropriate subscribe / unsubscribe ribbon option
            if mailinglist.is_subscribed(req.authname):
                add_ctxtnav(req, tag.form(tag.input(tag.a(tag.i(class_='fa fa-eye-slash'),
                ' Unsubscribe', title='Unsubscribe from the %s mailing list' % mailinglist.name, id='subscribe-link'),
                name='unsubscribe', value=mailinglist.emailaddress, class_='hidden'),
                method_='post', action='', id='subscribe-form', class_='hidden'))
            else:
                add_ctxtnav(req, tag.form(tag.input(tag.a(tag.i(class_='fa fa-eye'),
                ' Subscribe', title='Subscribe to the %s mailing list' % mailinglist.name, id='subscribe-link'),
                name='subscribe', value=mailinglist.emailaddress, class_='hidden'),
                method_='post', action='', id='subscribe-form', class_='hidden'))

            return 'mailinglist_conversations.html', data, None

        else:
            return 'mailinglist_list.html', data, None