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)
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)
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)
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)
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)
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
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)
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
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
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
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]
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
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
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
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
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 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