def notify(self, resid, subject, author=None): self.subject = subject config = self.config['notification'] if not config.getbool('smtp_enabled'): return from_email, from_name = '', '' if author and config.getbool('smtp_from_author'): from_email = self.get_smtp_address(author) if from_email: from_name = self.name_map.get(author, '') if not from_name: mo = self.longaddr_re.search(author) if mo: from_name = mo.group(1) if not from_email: from_email = config.get('smtp_from') from_name = config.get('smtp_from_name') or self.env.project_name self.replyto_email = config.get('smtp_replyto') self.from_email = from_email or self.replyto_email self.from_name = from_name if not self.from_email and not self.replyto_email: raise TracError(tag( tag.p(_('Unable to send email due to identity crisis.')), tag.p(_('Neither %(from_)s nor %(reply_to)s are specified ' 'in the configuration.', from_=tag.b('notification.from'), reply_to=tag.b('notification.reply_to')))), _('SMTP Notification Error')) Notify.notify(self, resid)
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 save(self, req): if req.args and req.args.has_key('action') \ and req.args['action'] == 'save': for key in SESSION_KEYS.values(): if req.args.has_key(key): if key == 'wiki.href': wiki_href = req.args[key] if wiki_href == '': req.session[key] = '' continue validated = WikiSystem(self.env).has_page(wiki_href) if validated: req.session[key] = req.args[key] else: add_warning(req, Markup(tag.span(Markup(_( "%(page)s is not a valid Wiki page", page=tag.b(wiki_href) ))))) elif key == 'tickets.href': ticket_href = req.args[key] if ticket_href == '': req.session[key] = '' continue reports = self.get_report_list() self.log.info('reports: %s' % reports) if ticket_href in ('report', 'query') \ or as_int(ticket_href, 0) in reports: req.session[key] = req.args[key] else: add_warning(req, Markup(tag.span(Markup(_( "%(report)s is not a valid report", report=tag.b(ticket_href) ))))) else: req.session[key] = req.args[key]
def validate_registration(self, req): acctmgr = AccountManager(self.env) username = acctmgr.handle_username_casing( req.args.get('username', '').strip()) if not username: raise RegistrationError(N_("Username cannot be empty.")) # Always exclude some special characters, i.e. # ':' can't be used in HtPasswdStore # '[' and ']' can't be used in SvnServePasswordStore blacklist = acctmgr.username_char_blacklist if containsAny(username, blacklist): pretty_blacklist = '' for c in blacklist: if pretty_blacklist == '': pretty_blacklist = tag(' \'', tag.b(c), '\'') else: pretty_blacklist = tag(pretty_blacklist, ', \'', tag.b(c), '\'') raise RegistrationError(N_( "The username must not contain any of these characters: %s"), tag.b(pretty_blacklist) ) # All upper-cased names are reserved for permission action names. if username.isupper(): raise RegistrationError(N_( "A username with only upper-cased characters is not allowed.") ) # Prohibit some user names, that are important for Trac and therefor # reserved, even if not in the permission store for some reason. if username.lower() in ['anonymous', 'authenticated']: raise RegistrationError(N_("Username %s is not allowed."), tag.b(username) ) # NOTE: A user may exist in a password store but not in the permission # store. I.e. this happens, when the user (from the password store) # never logged in into Trac. So we have to perform this test here # and cannot just check for the user being in the permission store. # And better obfuscate whether an existing user or group name # was responsible for rejection of this user name. for store_user in acctmgr.get_users(): # Do it carefully by disregarding case. if store_user.lower() == username.lower(): raise RegistrationError(N_( "Another account or group already exists, who's name " "differs from %s only by case or is identical."), tag.b(username) ) # Password consistency checks follow. password = req.args.get('password') if not password: raise RegistrationError(N_("Password cannot be empty.")) elif password != req.args.get('password_confirm'): raise RegistrationError(N_("The passwords must match."))
def generate_prefix(prefix): intertrac = intertracs[prefix] if isinstance(intertrac, basestring): yield tag.tr(tag.td(tag.b(prefix)), tag.td("Alias for ", tag.b(intertrac))) else: url = intertrac.get("url", "") if url: title = intertrac.get("title", url) yield tag.tr(tag.td(tag.a(tag.b(prefix), href=url + "/timeline")), tag.td(tag.a(title, href=url)))
def process_request(self, req): acctmgr = self.acctmgr if req.authname != 'anonymous': req.redirect(req.href.prefs('account')) action = req.args.get('action') name = req.args.get('name', '').strip() username = acctmgr.handle_username_casing(req.args.get('username', '').strip()) data = { '_dgettext': dgettext, 'acctmgr': dict(name=name, username=username), 'ignore_auth_case': self.config.getbool('trac', 'ignore_auth_case') } verify_enabled = is_enabled(self.env, EmailVerificationModule) and \ EmailVerificationModule(self.env).verify_email data['verify_account_enabled'] = verify_enabled if req.method == 'POST' and action == 'create': try: # Check request and prime account on success. acctmgr.validate_account(req, True) except RegistrationError, e: # Attempt deferred translation. message = gettext(e.message) # Check for (matching number of) message arguments before # attempting string substitution. if e.msg_args and \ len(e.msg_args) == len(re.findall('%s', message)): message = message % e.msg_args chrome.add_warning(req, Markup(message)) else: if self.require_approval: set_user_attribute(self.env, username, 'approval', N_('pending')) # Notify admin user about registration pending for review. acctmgr._notify('registration_approval_required', username) chrome.add_notice(req, Markup(tag.span(Markup(_( "Your username has been registered successfully, but " "your account requires administrative approval. " "Please proceed according to local policy.")))) ) if verify_enabled: chrome.add_notice(req, Markup(tag.span(Markup(_( """Your username has been successfully registered but your account still requires activation. Please login as user %(user)s, and follow the instructions.""", user=tag.b(username))))) ) req.redirect(req.href.login()) chrome.add_notice(req, Markup(tag.span(Markup(_( """Registration has been finished successfully. You may log in as user %(user)s now.""", user=tag.b(username))))) ) req.redirect(req.href.login())
def generate_prefix(prefix): intertrac = intertracs[prefix] if isinstance(intertrac, basestring): yield tag.tr(tag.td(tag.b(prefix)), tag.td('Alias for ', tag.b(intertrac))) else: url = intertrac.get('url', '') if url: title = intertrac.get('title', url) yield tag.tr(tag.td(tag.a(tag.b(prefix), href=url + '/timeline')), tag.td(tag.a(title, href=url)))
def handle_repo_paths(self, req): repopath = req.args.get('q') if not repopath.startswith('/'): repopath = '/%s' % repopath repos = self.env.get_repository(req.authname) def get_node_entries(path): # Should probably try to cache these searches, # although only meant for admins if not path.startswith('/'): path = '/%s' % path fallback = posixpath.dirname(path) try: node = repos.get_node(str(path), repos.youngest_rev) except (TracError, NoSuchNode): node = repos.get_node(fallback, repos.youngest_rev) node_entries = list(node.get_entries()) entries = [] for entry in node_entries: path = entry.path if not path.startswith('/'): path = '/%s' % path if path.startswith(repopath): # Only return those that we're interested in entries.append(entry) entries.sort(key=attrgetter('path')) return entries entries = get_node_entries(repopath) if not entries: req.write(tag.center( tag.em(_("No matches found on repository for "), tag.b(repopath)) )) raise RequestDone while len(entries) <= 1: # If returning only one entry, return a file no matter how deep if entries[0].kind == 'dir': entries = get_node_entries(entries[0].path) elif entries[0].kind == 'file': break req.write('<ul>') for entry in entries: path = entry.path if not path.startswith('/'): path = '/%s' % path req.write(tag.li(tag.b(repopath), tag(path.split(repopath)[1]))) req.write('</ul>') raise RequestDone
def _info_formatter(self, formatter, match, fullmatch): infotype = fullmatch.group('infotype').lower() body = format_to_oneliner(formatter.env, formatter.context, fullmatch.group('notes'), False) return tag.div(tag.blockquote(tag.b(infotype.capitalize() + ': ') + body,class_=infotype.upper()), class_=infotype.upper())
def _provider_failure(self, exc, req, ep, current_filters, all_filters): """Raise a TracError exception explaining the failure of a provider. At the same time, the message will contain a link to the timeline without the filters corresponding to the guilty event provider `ep`. """ self.log.error('Timeline event provider failed: %s', exception_to_unicode(exc, traceback=True)) ep_kinds = dict((f[0], f[1]) for f in ep.get_timeline_filters(req) or []) ep_filters = set(ep_kinds.keys()) current_filters = set(current_filters) other_filters = set(current_filters) - ep_filters if not other_filters: other_filters = set(all_filters) - ep_filters args = [(a, req.args.get(a)) for a in ('from', 'format', 'max', 'daysback')] href = req.href.timeline(args + [(f, 'on') for f in other_filters]) # TRANSLATOR: ...want to see the 'other kinds of events' from... (link) other_events = tag.a(_('other kinds of events'), href=href) raise TracError(tag( tag.p(tag_("Event provider %(name)s failed for filters " "%(kinds)s: ", name=tag.tt(ep.__class__.__name__), kinds=', '.join('"%s"' % ep_kinds[f] for f in current_filters & ep_filters)), tag.b(exception_to_unicode(exc)), class_='message'), tag.p(tag_("You may want to see the %(other_events)s from the " "Timeline or notify your Trac administrator about the " "error (detailed information was written to the log).", other_events=other_events))))
def expand_macro(self, formatter, name, content): req = formatter.req query_string = "" argv, kwargs = parse_args(content, strict=False) if "order" not in kwargs: kwargs["order"] = "id" if "max" not in kwargs: kwargs["max"] = "0" # unlimited by default query_string = "&".join(["%s=%s" % item for item in kwargs.iteritems()]) query = Query.from_string(self.env, query_string) tickets = query.execute(req) tickets = [t for t in tickets if "TICKET_VIEW" in req.perm("ticket", t["id"])] ticket_ids = [t["id"] for t in tickets] # locate the tickets geoticket = GeoTicket(self.env) locations = geoticket.locate_tickets(ticket_ids, req) if not locations: return tag.div(tag.b("MapTickets: "), "No locations found for ", tag.i(content)) data = dict(locations=Markup(simplejson.dumps(locations)), query_href=query.get_href(req), query_string=content) # set an id for the map map_id = req.environ.setdefault("MapTicketsId", 0) + 1 req.environ["MapTicketsId"] = map_id data["map_id"] = "tickets-map-%d" % map_id return Chrome(self.env).render_template(req, "map_tickets.html", data, None, fragment=True)
def _do_account(self, req): assert(req.authname and req.authname != 'anonymous') action = req.args.get('action') delete_enabled = self.acctmgr.supports('delete_user') and \ self.acctmgr.allow_delete_account data = {'delete_enabled': delete_enabled, 'delete_msg_confirm': _( "Are you sure you want to delete your account?"), } force_change_password = req.session.get('force_change_passwd', False) if req.method == 'POST': if action == 'save': data.update(self._do_change_password(req)) if force_change_password: del(req.session['force_change_passwd']) req.session.save() chrome.add_notice(req, Markup(tag.span(tag_( "Thank you for taking the time to update your password." )))) force_change_password = False elif action == 'delete' and delete_enabled: data.update(self._do_delete(req)) else: data.update({'error': 'Invalid action'}) if force_change_password: chrome.add_warning(req, Markup(tag.span(_( "You are required to change password because of a recent " "password change request. "), tag.b(_("Please change your password now."))))) return data
def render_registration_fields(self, req, data): """Add a hidden text input field to the registration form, and a visible one with mandatory input as well, if token is configured. """ if self.reg_basic_token: # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('basic_token', '') # TRANSLATOR: Hint for visible bot trap registration input field. hint = tag.p(Markup(_( """Apologies for the inconvenience, but please use the Sugarlabs Wiki, find the page referring to find the gold in the pot, and insert here the four words on the second line, or send mail to systems mailing list.""", token=tag.b(self.reg_basic_token))), class_='hint') insert = tag( tag.label(_("Parole:"), tag.input(type='text', name='basic_token', size=20, class_='textwidget', value=old_value)), hint ) else: insert = None # TRANSLATOR: Registration form hint for hidden bot trap input field. insert = tag(insert, tag.input(type='hidden', name='sentinel', title=_("Better do not fill this field.")) ) return insert, data
def _do_account(self, req): if not req.authname or req.authname == 'anonymous': req.redirect(req.href.wiki()) action = req.args.get('action') delete_enabled = AccountManager(self.env).supports('delete_user') data = {'delete_enabled': delete_enabled} force_change_password = req.session.get('force_change_passwd', False) if req.method == 'POST': if action == 'save': data.update(self._do_change_password(req)) if force_change_password: del(req.session['force_change_passwd']) req.session.save() chrome.add_notice(req, Markup(tag( "Thank you for taking the time to update your password." ))) force_change_password = False elif action == 'delete' and delete_enabled: data.update(self._do_delete(req)) else: data.update({'error': 'Invalid action'}) if force_change_password: chrome.add_warning(req, Markup(tag( "You are required to change password because of a recent " "password change request. ", tag.b("Please change your password now.")))) return data
def render_registration_fields(self, req, data): """Add a hidden text input field to the registration form, and a visible one with mandatory input as well, if token is configured. """ if self.reg_basic_token: # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('basic_token', '') # TRANSLATOR: Hint for visible bot trap registration input field. hint = tag.p(Markup(_( """Please type [%(token)s] as verification token, exactly replicating everything within the braces.""", token=tag.b(self.reg_basic_token))), class_='hint') insert = tag( tag.label(_("Parole:"), tag.input(type='text', name='basic_token', size=20, class_='textwidget', value=old_value)), hint ) else: insert = None # TRANSLATOR: Registration form hint for hidden bot trap input field. insert = tag(insert, tag.input(type='hidden', name='sentinel', title=_("Better do not fill this field.")) ) return insert, data
def validate_registration(self, req): if req.authname and req.authname != 'anonymous': return username = AccountManager(self.env).handle_username_casing( req.args.get('username', '').strip()) # NOTE: We can't use 'get_user_permissions(username)' here # as this always returns a list - even if the user doesn't exist. # In this case the permissions of "anonymous" are returned. # # Also note that we can't simply compare the result of # 'get_user_permissions(username)' to some known set of permission, # i.e. "get_user_permissions('authenticated') as this is always # false when 'username' is the name of an existing permission group. # # And again obfuscate whether an existing user or group name # was responsible for rejection of this username. for (perm_user, perm_action) in \ perm.PermissionSystem(self.env).get_all_permissions(): if perm_user.lower() == username.lower(): raise RegistrationError(N_( "Another account or group already exists, who's name " "differs from %s only by case or is identical."), tag.b(username) )
def generate_home(self, req): model = ZoteroModelProvider(self.env) title = tag.h1( 'Tops' ) authors_top = model.count_by_author_top() authors = [] for creatorID, firstName, lastName in authors_top: authors.append(tag.a( lastName + ' ' + firstName, href = req.href.zotero('qjump', author = creatorID) ) ) authors.append(tag.span(' | ')) authors = tag.tr(tag.th( tag.b('Authors:'), tag.td( authors, tag.a('more...', href = req.href.zotero('cloud', t = 'author' ) ) ), valign="top", style="text-align: right; width: 15%;")) publisher_top = model.count_by_publisher_top() publisher = [] for p in publisher_top: publisher.append(tag.a( p, href = req.href.zotero('qjump', publisher = p) ) ) publisher.append(tag.br()) publisher = tag.tr(tag.th( tag.b('Publishers:'), tag.td(publisher, tag.a('more...', href = req.href.zotero('cloud', t = 'publisher' ))), valign="top", style="text-align: right; width: 15%;")) year_top = model.count_by_year_top() years = [] for y in year_top: years.append(tag.a( y, href = req.href.zotero('qjump', year = y) ) ) years.append(tag.span(' | ')) years = tag.tr(tag.th( tag.b('Years:'), tag.td(years, tag.a('more...', href = req.href.zotero('cloud', t = 'year' ))), valign="top", style="text-align: right; width: 15%;")) # For recently add recent_ids = model.get_recents() recents_title = tag.div( tag.br(), tag.br(),tag.h1('Recent Changes')) recents = render_refs_box(self, req, recent_ids ) home = tag.div( title, tag.table(authors, years, publisher, border="0", cellpadding="2", cellspacing="2"), recents_title, recents) return home
def expand_macro(self, formatter, name, args): if not args: return Markup() config = None if name == self.CONFIG_KEY: lines = args.splitlines() if not lines or not lines[0].startswith('#!'): return Markup() config = self._parse_config([i.strip() for i in lines[0][2:].split(',')]) else: config = self.CONFIG[name] if not config: return Markup() def to_html(text): if not text: return '' return Markup('<br>'.join([format_to_oneliner(self.env, formatter.context, line) \ for line in text.splitlines()])) def has_keys(dict, keys): for key in keys: if dict.has_key(key): return True return False rows = self.parse_doc(args) if not rows: return Markup() seen = [] for desc, keys in config: if [row for row in rows if has_keys(row, keys)]: seen.append(desc) thead = tag.thead() for desc, keys in config: if not desc in seen: continue thead(tag.td(tag.b(desc))) tbody = tag.tbody() for row in rows: trow = tag.tr() for desc, keys in config: if not desc in seen: continue tcol = tag.td() for key in keys: if row.has_key(key): tcol(to_html(row[key])) trow(tcol) tbody(trow) return tag.table([thead, tbody], class_='wiki')
def notify(self, resid, subject): self.subject = subject if not self.config.getbool('notification', 'smtp_enabled'): return self.from_email = self.config['notification'].get('smtp_from') self.from_name = self.config['notification'].get('smtp_from_name') self.replyto_email = self.config['notification'].get('smtp_replyto') self.from_email = self.from_email or self.replyto_email if not self.from_email and not self.replyto_email: raise TracError(tag( tag.p(_('Unable to send email due to identity crisis.')), tag.p(_('Neither %(from_)s nor %(reply_to)s are specified ' 'in the configuration.', from_=tag.b('notification.from'), reply_to=tag.b('notification.reply_to')))), _('SMTP Notification Error')) Notify.notify(self, resid)
def validate(self, relation): rls = RelationsSystem(self.env) existing_relations = rls._select_relations(resource_type=relation.type, destination=relation.destination) if existing_relations: raise ValidationError( tag_("Another resource is already related to %(destination)s " "with %(relation)s relation.", destination=tag.em(relation.destination), relation=tag.b(self.render_relation_type(relation.type))) )
def handle_locales(self, req): query = req.args.get('q') if not query: req.write(tag.center(tag.em(_('No matches')))) raise RequestDone matches = [AVAILABLE_LOCALES[l] for l in AVAILABLE_LOCALES.keys() if l.lower().startswith(query.lower())] if not matches: req.write(tag.center(tag.em(_("No matches found for locale "), tag.b(query)))) raise RequestDone req.write('<ul>') for loc, eng_name, disp_name in matches: req.write(tag.li(tag.b(loc), tag.br, tag.em(disp_name), tag.br, tag.em(eng_name), realvalue=loc)) req.write('</ul>') raise RequestDone
def render_timeline_event(self, context, field, event): #self.log.debug("Monit: render_timeline_event() called") evt, srv, monit = event[3] if field == 'url': return context.href.monit('event', evt['id']) elif field == 'title': return tag(tag.em('New ', srv_types.get(evt['type'], ''), ' event')) elif field == 'description': if srv and monit: markup = tag.div('Event on ', tag.b(monit['localhostname']), ' for service ', tag.b(srv['name']), '(type %s) ' % srv_types.get(evt['type'], ''), tag.em(evt['message'])) self.log.debug("Monit markup for Timeline -> %s" % str(markup)) elif srv: markup = tag.div('Event on ', tag.b('unknown'), ' for service ', tag.b(srv['name']), '(type %s) ' % srv_types.get(evt['type'], ''), tag.em(evt['message'])) else: markup = tag.div('Event on ', tag.b('unknown'), ' for service ', tag.b('unknown'), '(type unknown)', tag.em(evt['message'])) self.log.debug("Monit markup for Timeline -> %s" % str(markup)) return markup
def process_request(self, req): repos = self.env.get_repository(req.authname) if req.get_header('X-Requested-With') == 'XMLHttpRequest': dirname, prefix = posixpath.split(req.args.get('q')) prefix = prefix.lower() node = repos.get_node(dirname) def kind_order(entry): def name_order(entry): return embedded_numbers(entry.name) return entry.isfile, name_order(entry) elem = tag.ul( [tag.li(is_dir and tag.b(path) or path) for e in sorted(node.get_entries(), key=kind_order) for is_dir, path in [(e.isdir, '/' + e.path.lstrip('/'))] if e.name.lower().startswith(prefix)] ) xhtml = elem.generate().render('xhtml') req.send_header('Content-Length', len(xhtml)) req.write(xhtml) return # -- retrieve arguments new_path = req.args.get('new_path') new_rev = req.args.get('new_rev') old_path = req.args.get('old_path') old_rev = req.args.get('old_rev') # -- normalize new_path = repos.normalize_path(new_path) if not new_path.startswith('/'): new_path = '/' + new_path new_rev = repos.normalize_rev(new_rev) old_path = repos.normalize_path(old_path) if not old_path.startswith('/'): old_path = '/' + old_path old_rev = repos.normalize_rev(old_rev) repos.authz.assert_permission_for_changeset(new_rev) repos.authz.assert_permission_for_changeset(old_rev) # -- prepare rendering data = {'new_path': new_path, 'new_rev': new_rev, 'old_path': old_path, 'old_rev': old_rev} add_script(req, 'common/js/suggest.js') return 'diff_form.html', data, None
def notify(self, resid, subject): self.subject = subject if not self.config.getbool('notification', 'smtp_enabled'): return self.smtp_server = self.config['notification'].get('smtp_server') self.smtp_port = self.config['notification'].getint('smtp_port') self.from_email = self.config['notification'].get('smtp_from') self.from_name = self.config['notification'].get('smtp_from_name') self.replyto_email = self.config['notification'].get('smtp_replyto') self.from_email = self.from_email or self.replyto_email if not self.from_email and not self.replyto_email: raise TracError(tag(tag.p('Unable to send email due to identity ' 'crisis.'), tag.p('Neither ', tag.b('notification.from'), ' nor ', tag.b('notification.reply_to'), 'are specified in the configuration.')), 'SMTP Notification Error') # Authentication info (optional) self.user_name = self.config['notification'].get('smtp_user') self.password = self.config['notification'].get('smtp_password') Notify.notify(self, resid)
def expand_macro(self, formatter, name, text, args): proxy_support = urllib2.ProxyHandler({"https" : proxy_url}) opener = urllib2.build_opener(proxy_support) urllib2.install_opener(opener) url = 'https://inventaris.onroerenderfgoed.be/erfgoed/node?query=%s' % (urllib2.quote(text)) req = urllib2.Request(url) req.add_header('Accept', 'application/json') r = urllib2.urlopen(req) data = json.load(r) titel = tag.div(tag.b("Uw zoekopdracht: " + Markup.escape(text))) res = tag.em("Resultaten %d - %d van %d" % \ (data['startIndex'], data['startIndex'] -1 + data['itemsPerPage'], data['totalResults'])) def make_listitem(item): def filter_html_link(link): return link['type'] == 'text/html' url = filter(filter_html_link,item['links'])[0]['href'] link = tag.a(item['omschrijving'] + ' (' + item['id'] + ')',href=url) return tag.li(link) lijst = tag.ul(map(make_listitem,data['items'])) return titel + res + lijst
def validate_registration(self, req): acctmgr = AccountManager(self.env) username = acctmgr.handle_username_casing( req.args.get('username', '').strip()) if self.username_regexp != "" and \ not re.match(self.username_regexp.strip(), username): raise RegistrationError(N_( "Username %s doesn't match local naming policy."), tag.b(username) ) email = req.args.get('email', '').strip() if acctmgr.verify_email and is_enabled(self.env, EmailCheck) and \ is_enabled(self.env, EmailVerificationModule): if self.email_regexp.strip() != "" and \ not re.match(self.email_regexp.strip(), email): raise RegistrationError(N_( "The email address specified appears to be invalid. " "Please specify a valid email address.") )
def validate_registration(self, req): if req.perm.has_permission('ACCTMGR_USER_ADMIN'): return username = AccountManager(self.env).handle_username_casing( req.args.get('username', '').strip()) # NOTE: We can't use 'get_user_permissions(username)' here # as this always returns a list - even if the user doesn't exist. # In this case the permissions of "anonymous" are returned. # # Also note that we can't simply compare the result of # 'get_user_permissions(username)' to some known set of permission, # i.e. "get_user_permissions('authenticated') as this is always # false when 'username' is the name of an existing permission group. # # And again obfuscate whether an existing user or group name # was responsible for rejection of this username. for (perm_user, perm_action) in \ perm.PermissionSystem(self.env).get_all_permissions(): if perm_user.lower() == username.lower(): raise RegistrationError( N_("Another account or group already exists, who's name " "differs from %s only by case or is identical."), tag.b(username))
def process_request(self, req): if req.authname != 'anonymous': req.redirect(req.href.prefs('account')) action = req.args.get('action') data = {'acctmgr' : { 'username' : None, 'name' : None, 'email' : None, }, '_dgettext': dgettext, } data['verify_account_enabled'] = is_enabled( self.env, EmailVerificationModule) and self.acctmgr.verify_email if req.method == 'POST' and action == 'create': try: _create_user(req, self.env) except TracError, e: data['registration_error'] = e.message data['acctmgr'] = getattr(e, 'acctmgr', '') else: chrome.add_notice(req, Markup(tag.span(Markup(_( """Registration has been finished successfully. You may login as user %(user)s now.""", user=tag.b(req.args.get('username'))))))) req.redirect(req.href.login())
def expand_macro(self, formatter, name, arguments): self.ref = formatter self.tz_info = formatter.req.tz self.thistime = datetime.datetime.now(self.tz_info) # Parse arguments from macro invocation args, kwargs = parse_args(arguments, strict=False) # Find out whether use http param, current or macro param year/month http_param_year = formatter.req.args.get('year', '') http_param_month = formatter.req.args.get('month', '') if http_param_year == "": # not clicked on a prev or next button if len(args) >= 1 and args[0] <> "*": # year given in macro parameters year = int(args[0]) else: # use current year year = self.thistime.year else: # year in http params (clicked by user) overrides everything year = int(http_param_year) if http_param_month == "": # not clicked on a prev or next button if len(args) >= 2 and args[1] <> "*": # month given in macro parameters month = int(args[1]) else: # use current month month = self.thistime.month else: # month in http params (clicked by user) overrides everything month = int(http_param_month) showbuttons = True if len(args) >= 3 or kwargs.has_key('nav'): try: showbuttons = kwargs['nav'] in ["True", "true", "yes", "1"] except KeyError: showbuttons = args[2] in ["True", "true", "yes", "1"] wiki_page_format = "%Y-%m-%d" if len(args) >= 4 and args[3] != "*" or kwargs.has_key('wiki'): try: wiki_page_format = str(kwargs['wiki']) except KeyError: wiki_page_format = str(args[3]) show_t_open_dates = True if len(args) >= 5 or kwargs.has_key('cdate'): try: show_t_open_dates = kwargs['cdate'] in \ ["True", "true", "yes", "1"] except KeyError: show_t_open_dates = args[4] in ["True", "true", "yes", "1"] # template name tried to create new pages # optional, default (empty page) is used, if name is invalid wiki_page_template = "" if len(args) >= 6 or kwargs.has_key('base'): try: wiki_page_template = kwargs['base'] except KeyError: wiki_page_template = args[5] # TracQuery support for ticket selection query_args = "id!=0" if len(args) >= 7 or kwargs.has_key('query'): # prefer query arguments provided by kwargs try: query_args = kwargs['query'] except KeyError: query_args = args[6] self.tickets = self._ticket_query(formatter, query_args) # compress long ticket lists list_condense = 0 if len(args) >= 8 or kwargs.has_key('short'): # prefer query arguments provided by kwargs try: list_condense = int(kwargs['short']) except KeyError: list_condense = int(args[7]) # control calendar display width cal_width = "100%;" if len(args) >= 9 or kwargs.has_key('width'): # prefer query arguments provided by kwargs try: cal_width = kwargs['width'] except KeyError: cal_width = args[8] # Can use this to change the day the week starts on, # but this is a system-wide setting. calendar.setfirstweekday(calendar.MONDAY) cal = calendar.monthcalendar(year, month) curr_day = None if year == self.thistime.year and month == self.thistime.month: curr_day = self.thistime.day # Compile regex pattern before use for better performance pattern_del = '(?:<span .*?>)|(?:</span>)' pattern_del += '|(?:<p>)|(?:<p .*?>)|(?:</p>)' pattern_del += '|(?:</table>)|(?:<td.*?\n)|(?:<tr.*?</tr>)' self.end_RE = re.compile('(?:</a>)') self.del_RE = re.compile(pattern_del) self.item_RE = re.compile('(?:<img .*?>)') self.open_RE = re.compile('(?:<a .*?>)') self.tab_RE = re.compile('(?:<table .*?>)') # for prev/next navigation links prevMonth = month - 1 nextMonth = month + 1 nextYear = prevYear = year # check for year change (KISS version) if prevMonth == 0: prevMonth = 12 prevYear -= 1 if nextMonth == 13: nextMonth = 1 nextYear += 1 # for fast-forward/-rewind navigation links ffYear = frYear = year if month < 4: frMonth = month + 9 frYear -= 1 else: frMonth = month - 3 if month > 9: ffMonth = month - 9 ffYear += 1 else: ffMonth = month + 3 # Finally building the output # Prepending inline CSS definitions styles = """ \ <!-- table.wikiTicketCalendar th { font-weight: bold; } table.wikiTicketCalendar th.workday { width: 17%; } table.wikiTicketCalendar th.weekend { width: 7%; } table.wikiTicketCalendar caption { font-size: 120%; white-space: nowrap; } table.wikiTicketCalendar caption a { display: inline; margin: 0; border: 0; padding: 0; background-color: transparent; color: #b00; text-decoration: none; } table.wikiTicketCalendar caption a.prev { padding-right: 5px; font: bold; } table.wikiTicketCalendar caption a.next { padding-left: 5px; font: bold; } table.wikiTicketCalendar caption a:hover { background-color: #eee; } table.wikiTicketCalendar td.today { background: #fbfbfb; border-color: #444444; color: #444; border-style: solid; border-width: 1px; } table.wikiTicketCalendar td.day { background: #e5e5e5; border-color: #444444; color: #333; border-style: solid; border-width: 1px; } table.wikiTicketCalendar td.fill { background: #eee; border-color: #ccc; border-style: solid; border-width: 1px; } table.wikiTicketCalendar div.milestone { font-size: 9px; background: #f7f7f0; border: 1px solid #d7d7d7; border-bottom-color: #999; text-align: left; } table.wikiTicketCalendar a.day { width: 2em; height: 100%; margin: 0; border: 0px; padding: 0; color: #333; text-decoration: none; } table.wikiTicketCalendar a.day_haspage { width: 2em; height: 100%; margin: 0; border: 0px; padding: 0; color: #b00 !important; text-decoration: none; } table.wikiTicketCalendar a.day:hover { border-color: #eee; background-color: #eee; color: #000; } table.wikiTicketCalendar div.open, span.open { font-size: 9px; color: #000000; } table.wikiTicketCalendar div.closed, span.closed { font-size: 9px; color: #777777; text-decoration: line-through; } table.wikiTicketCalendar div.opendate_open, span.opendate_open { font-size: 9px; color: #000077; } table.wikiTicketCalendar div.opendate_closed, span.opendate_closed { font-size: 9px; color: #000077; text-decoration: line-through; } table.wikiTicketCalendar div.condense { background-color: #e5e5e5; } table.wikiTicketCalendar div.opendate_condense { background-color: #cdcdfa; } /* pure CSS style tooltip */ a.tip { position: relative; cursor: help; } a.tip span { display: none; } a.tip:hover span { display: block; z-index: 1; font-size: 0.75em; text-decoration: none; /* big left move because of z-index render bug in IE<8 */ position: absolute; top: 0.8em; left: 6em; border: 1px solid #000; background-color: #fff; padding: 5px; } --> """ # create inline style definition as Genshi fragment styles = tag.style(Markup(styles)) styles(type='text/css') # Build caption and optional navigation links buff = tag.caption() if showbuttons is True: # calendar navigation buttons nx = 'next' pv = 'prev' nav_pvY = self._mknav(' <<', pv, month, year - 1) nav_frM = self._mknav(' < ', pv, frMonth, frYear) nav_pvM = self._mknav(' « ', pv, prevMonth, prevYear) nav_nxM = self._mknav(' » ', nx, nextMonth, nextYear) nav_ffM = self._mknav(' > ', nx, ffMonth, ffYear) nav_nxY = self._mknav(' >>', nx, month, year + 1) # add buttons for going to previous months and year buff(nav_pvY, nav_frM, nav_pvM) # The caption will always be there. buff( tag.strong( to_unicode(format_date(self._mkdatetime(year, month), '%B %Y')))) if showbuttons is True: # add buttons for going to next months and year buff(nav_nxM, nav_ffM, nav_nxY) buff = tag.table(buff) width = ":".join(['min-width', cal_width]) buff(class_='wikiTicketCalendar', style=width) heading = tag.tr() heading(align='center') for day in calendar.weekheader(2).split()[:-2]: col = tag.th(day) col(class_='workday', scope='col') heading(col) for day in calendar.weekheader(2).split()[-2:]: col = tag.th(day) col(class_='weekend', scope='col') heading(col) heading = buff(tag.thead(heading)) # Building main calendar table body buff = tag.tbody() for row in cal: line = tag.tr() line(align='right') for day in row: if not day: cell = tag.td('') cell(class_='fill') line(cell) else: # check for wikipage with name specified in # 'wiki_page_format' wiki = format_date(self._mkdatetime(year, month, day), wiki_page_format) url = self.env.href.wiki(wiki) if WikiSystem(self.env).has_page(wiki): a_class = "day_haspage" title = "Go to page %s" % wiki else: a_class = "day" url += "?action=edit" # adding template name, if specified if wiki_page_template != "": url += "&template=" + wiki_page_template title = "Create page %s" % wiki if day == curr_day: td_class = 'today' else: td_class = 'day' cell = tag.a(tag.b(day), href=url) cell(class_=a_class, title_=title) cell = tag.td(cell) cell(class_=td_class, valign='top') day_dt = self._mkdatetime(year, month, day) if uts: day_ts = to_utimestamp(day_dt) day_ts_eod = day_ts + 86399999999 else: day_ts = to_timestamp(day_dt) day_ts_eod = day_ts + 86399 # check for milestone(s) on that day db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( """ SELECT name FROM milestone WHERE due >= %s and due <= %s """, (day_ts, day_ts_eod)) while (1): row = cursor.fetchone() if row is None: cell(tag.br()) break else: name = to_unicode(row[0]) url = self.env.href.milestone(name) milestone = '* ' + name milestone = tag.div(tag.a(milestone, href=url)) milestone(class_='milestone') cell(milestone) match = [] match_od = [] ticket_heap = tag('') ticket_list = tag.div('') ticket_list(align='left', class_='condense') # get tickets with due date set to day for t in self.tickets: due = t.get(self.due_field_name) if due is None or due in ['', '--']: continue else: if self.due_field_fmt == 'ts': if not isinstance(due, datetime.datetime): continue else: if uts: due_ts = to_utimestamp(due) else: due_ts = to_timestamp(due) if due_ts < day_ts or \ due_ts > day_ts_eod: continue else: duedate = format_date(day_dt, self.due_field_fmt) if not due == duedate: continue id = t.get('id') ticket, short = self._gen_ticket_entry(t) ticket_heap(ticket) if not id in match: if len(match) == 0: ticket_list(short) else: ticket_list(', ', short) match.append(id) # optionally get tickets created on day if show_t_open_dates is True: ticket_od_list = tag.div('') ticket_od_list(align='left', class_='opendate_condense') for t in self.tickets: if uts: ticket_ts = to_utimestamp(t.get('time')) else: ticket_ts = to_timestamp(t.get('time')) if ticket_ts < day_ts or ticket_ts > day_ts_eod: continue a_class = 'opendate_' id = t.get('id') ticket, short = self._gen_ticket_entry(t, a_class) ticket_heap(ticket) if not id in match: if len(match_od) == 0: ticket_od_list(short) else: ticket_od_list(', ', short) match_od.append(id) matches = len(match) + len(match_od) if list_condense > 0 and matches >= list_condense: if len(match_od) > 0: if len(match) > 0: ticket_list(', ') ticket_list = tag(ticket_list, ticket_od_list) line(cell(ticket_list)) else: line(cell(ticket_heap)) buff(line) buff = tag.div(heading(buff)) if cal_width.startswith('+') is True: width = ":".join(['width', cal_width]) buff(class_='wikiTicketCalendar', style=width) else: buff(class_='wikiTicketCalendar') # Finally prepend prepared CSS styles buff = tag(styles, buff) return buff
def _create_user(req, env, check_permissions=True): acctmgr = AccountManager(env) username = acctmgr.handle_username_casing(req.args.get('username').strip()) name = req.args.get('name') email = req.args.get('email').strip() account = { 'username': username, 'name': name, 'email': email, } error = TracError('') error.account = account if not username: error.message = _("Username cannot be empty.") raise error # Prohibit some user names that are important for Trac and therefor # reserved, even if they're not in the permission store for some reason. if username in ['authenticated', 'anonymous']: error.message = _("Username %s is not allowed.") % username raise error # NOTE: A user may exist in the password store but not in the permission # store. I.e. this happens, when the user (from the password store) # never logged in into Trac. So we have to perform this test here # and cannot just check for the user being in the permission store. # And obfuscate whether an existing user or group name # was responsible for rejection of this user name. if acctmgr.has_user(username): error.message = _( "Another account or group named %s already exists.") % username raise error # Check whether there is also a user or a group with that name. if check_permissions: # NOTE: We can't use 'get_user_permissions(username)' here # as this always returns a list - even if the user doesn't exist. # In this case the permissions of "anonymous" are returned. # # Also note that we can't simply compare the result of # 'get_user_permissions(username)' to some known set of permission, # i.e. "get_user_permissions('authenticated') as this is always # false when 'username' is the name of an existing permission group. # # And again obfuscate whether an existing user or group name # was responsible for rejection of this username. for (perm_user, perm_action) in \ perm.PermissionSystem(env).get_all_permissions(): if perm_user == username: error.message = _( "Another account or group named %s already exists.") \ % username raise error # Always exclude some special characters, i.e. # ':' can't be used in HtPasswdStore # '[' and ']' can't be used in SvnServePasswordStore blacklist = acctmgr.username_char_blacklist if containsAny(username, blacklist): pretty_blacklist = '' for c in blacklist: if pretty_blacklist == '': pretty_blacklist = tag(' \'', tag.b(c), '\'') else: pretty_blacklist = tag(pretty_blacklist, ', \'', tag.b(c), '\'') error.message = tag( _("The username must not contain any of these characters:"), pretty_blacklist) raise error # Validation of username passed. password = req.args.get('password') if not password: error.message = _("Password cannot be empty.") raise error if password != req.args.get('password_confirm'): error.message = _("The passwords must match.") raise error # Validation of password passed. if if_enabled(EmailVerificationModule) and acctmgr.verify_email: if not email: error.message = _("You must specify a valid email address.") raise error elif not re.match('^[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', email, re.IGNORECASE): error.message = _("""The email address specified appears to be invalid. Please specify a valid email address. """) raise error elif acctmgr.has_email(email): error.message = _("""The email address specified is already in use. Please specify a different one. """) raise error # Validation of email address passed. acctmgr.set_password(username, password) # INSERT new sid, needed as foreign key in some db schemata later on, # at least for PostgreSQL. db = env.get_db_cnx() cursor = db.cursor() cursor.execute( """ SELECT COUNT(*) FROM session WHERE sid=%s """, (username, )) exists = cursor.fetchone() if not exists: cursor.execute( """ INSERT INTO session (sid,authenticated,last_visit) VALUES (%s,0,0) """, (username, )) for attribute in ('name', 'email'): value = req.args.get(attribute) if not value: continue set_user_attribute(env, username, attribute, value)
def expand_macro(self, formatter, name, arguments): self.ref = formatter self.tz_info = formatter.req.tz self.thistime = datetime.datetime.now(self.tz_info) # Add CSS stylesheet add_stylesheet(self.ref.req, 'wikiticketcalendar/css/wikiticketcalendar.css') # Parse arguments from macro invocation args, kwargs = parse_args(arguments, strict=False) # Find out whether use http param, current or macro param year/month http_param_year = formatter.req.args.get('year','') http_param_month = formatter.req.args.get('month','') if http_param_year == "": # not clicked on a prev or next button if len(args) >= 1 and args[0] <> "*": # year given in macro parameters year = int(args[0]) else: # use current year year = self.thistime.year else: # year in http params (clicked by user) overrides everything year = int(http_param_year) if http_param_month == "": # not clicked on a prev or next button if len(args) >= 2 and args[1] <> "*": # month given in macro parameters month = int(args[1]) else: # use current month month = self.thistime.month else: # month in http params (clicked by user) overrides everything month = int(http_param_month) showbuttons = True if len(args) >= 3 or kwargs.has_key('nav'): try: showbuttons = kwargs['nav'] in ["True", "true", "yes", "1"] except KeyError: showbuttons = args[2] in ["True", "true", "yes", "1"] wiki_page_format = "%Y-%m-%d" if len(args) >= 4 and args[3] != "*" or kwargs.has_key('wiki'): try: wiki_page_format = str(kwargs['wiki']) except KeyError: wiki_page_format = str(args[3]) show_t_open_dates = True if len(args) >= 5 or kwargs.has_key('cdate'): try: show_t_open_dates = kwargs['cdate'] in \ ["True", "true", "yes", "1"] except KeyError: show_t_open_dates = args[4] in ["True", "true", "yes", "1"] # template name tried to create new pages # optional, default (empty page) is used, if name is invalid wiki_page_template = "" if len(args) >= 6 or kwargs.has_key('base'): try: wiki_page_template = kwargs['base'] except KeyError: wiki_page_template = args[5] # TracQuery support for ticket selection query_args = "id!=0" if len(args) >= 7 or kwargs.has_key('query'): # prefer query arguments provided by kwargs try: query_args = kwargs['query'] except KeyError: query_args = args[6] self.tickets = self._ticket_query(formatter, query_args) # compress long ticket lists list_condense = 0 if len(args) >= 8 or kwargs.has_key('short'): # prefer query arguments provided by kwargs try: list_condense = int(kwargs['short']) except KeyError: list_condense = int(args[7]) # control calendar display width cal_width = "100%;" if len(args) >= 9 or kwargs.has_key('width'): # prefer query arguments provided by kwargs try: cal_width = kwargs['width'] except KeyError: cal_width = args[8] # Can use this to change the day the week starts on, # but this is a system-wide setting. calendar.setfirstweekday(calendar.MONDAY) cal = calendar.monthcalendar(year, month) curr_day = None if year == self.thistime.year and month == self.thistime.month: curr_day = self.thistime.day # Compile regex pattern before use for better performance pattern_del = '(?:<span .*?>)|(?:</span>)' pattern_del += '|(?:<p>)|(?:<p .*?>)|(?:</p>)' pattern_del += '|(?:</table>)|(?:<td.*?\n)|(?:<tr.*?</tr>)' self.end_RE = re.compile('(?:</a>)') self.del_RE = re.compile(pattern_del) self.item_RE = re.compile('(?:<img .*?>)') self.open_RE = re.compile('(?:<a .*?>)') self.tab_RE = re.compile('(?:<table .*?>)') # for prev/next navigation links prevMonth = month - 1 nextMonth = month + 1 nextYear = prevYear = year # check for year change (KISS version) if prevMonth == 0: prevMonth = 12 prevYear -= 1 if nextMonth == 13: nextMonth = 1 nextYear += 1 # for fast-forward/-rewind navigation links ffYear = frYear = year if month < 4: frMonth = month + 9 frYear -= 1 else: frMonth = month - 3 if month > 9: ffMonth = month - 9 ffYear += 1 else: ffMonth = month + 3 # Finally building the output # Begin with caption and optional navigation links buff = tag.caption() if showbuttons is True: # calendar navigation buttons nx = 'next' pv = 'prev' nav_pvY = self._mknav(' <<', pv, month, year-1) nav_frM = self._mknav(' < ', pv, frMonth, frYear) nav_pvM = self._mknav(' « ', pv, prevMonth, prevYear) nav_nxM = self._mknav(' » ', nx, nextMonth, nextYear) nav_ffM = self._mknav(' > ', nx, ffMonth, ffYear) nav_nxY = self._mknav(' >>', nx, month, year+1) # add buttons for going to previous months and year buff(nav_pvY, nav_frM, nav_pvM) # The caption will always be there. buff(tag.strong(to_unicode(format_date(self._mkdatetime( year, month), '%B %Y')))) if showbuttons is True: # add buttons for going to next months and year buff(nav_nxM, nav_ffM, nav_nxY) buff = tag.table(buff) width=":".join(['min-width', cal_width]) buff(class_='wikiTicketCalendar', style=width) heading = tag.tr() heading(align='center') for day in calendar.weekheader(2).split()[:-2]: col = tag.th(day) col(class_='workday', scope='col') heading(col) for day in calendar.weekheader(2).split()[-2:]: col = tag.th(day) col(class_='weekend', scope='col') heading(col) heading = buff(tag.thead(heading)) # Building main calendar table body buff = tag.tbody() for row in cal: line = tag.tr() line(align='right') for day in row: if not day: cell = tag.td('') cell(class_='fill') line(cell) else: # check for wikipage with name specified in # 'wiki_page_format' wiki = format_date(self._mkdatetime(year, month, day), wiki_page_format) url = self.env.href.wiki(wiki) if WikiSystem(self.env).has_page(wiki): a_class = "day_haspage" title = _("Go to page %s") % wiki else: a_class = "day" url += "?action=edit" # adding template name, if specified if wiki_page_template != "": url += "&template=" + wiki_page_template title = _("Create page %s") % wiki if day == curr_day: td_class = 'today' else: td_class = 'day' cell = tag.a(tag.b(day), href=url) cell(class_=a_class, title_=title) cell = tag.td(cell) cell(class_=td_class, valign='top') day_dt = self._mkdatetime(year, month, day) day_ts = to_utimestamp(day_dt) day_ts_eod = day_ts + 86399999999 # check for milestone(s) on that day db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute(""" SELECT name FROM milestone WHERE due >= %s and due <= %s """, (day_ts, day_ts_eod)) while (1): row = cursor.fetchone() if row is None: cell(tag.br()) break else: name = to_unicode(row[0]) url = self.env.href.milestone(name) milestone = '* ' + name milestone = tag.div(tag.a(milestone, href=url)) milestone(class_='milestone') cell(milestone) match = [] match_od = [] ticket_heap = tag('') ticket_list = tag.div('') ticket_list(align='left', class_='condense') # get tickets with due date set to day for t in self.tickets: due = t.get(self.due_field_name) if due is None or due in ['', '--']: continue else: if self.due_field_fmt == 'ts': if not isinstance(due, datetime.datetime): continue due_ts = to_utimestamp(due) if due_ts < day_ts or \ due_ts > day_ts_eod: continue else: duedate = format_date(day_dt, self.due_field_fmt) if not due == duedate: continue id = t.get('id') ticket, short = self._gen_ticket_entry(t) ticket_heap(ticket) if not id in match: if len(match) == 0: ticket_list(short) else: ticket_list(', ', short) match.append(id) # optionally get tickets created on day if show_t_open_dates is True: ticket_od_list = tag.div('') ticket_od_list(align='left', class_='opendate_condense') for t in self.tickets: ticket_ts = to_utimestamp(t.get('time')) if ticket_ts < day_ts or ticket_ts > day_ts_eod: continue a_class = 'opendate_' id = t.get('id') ticket, short = self._gen_ticket_entry(t, a_class) ticket_heap(ticket) if not id in match: if len(match_od) == 0: ticket_od_list(short) else: ticket_od_list(', ', short) match_od.append(id) matches = len(match) + len(match_od) if list_condense > 0 and matches >= list_condense: if len(match_od) > 0: if len(match) > 0: ticket_list(', ') ticket_list = tag(ticket_list, ticket_od_list) line(cell(ticket_list)) else: line(cell(ticket_heap)) buff(line) buff = tag.div(heading(buff)) if cal_width.startswith('+') is True: width=":".join(['width', cal_width]) buff(class_='wikiTicketCalendar', style=width) else: buff(class_='wikiTicketCalendar') return buff
def test_exception_with_fragment_as_argument(self): e1 = Exception(tag(tag.b('the message'))) e2 = HTTPInternalError(e1) self.assertEqual('500 Internal Server Error (<b>the message</b>)', unicode(e2))
def __call__(self,obj,depth=0,dontRender=False): from genshi.builder import tag if depth>self.maxDepth: raise RuntimeError("Maximum nesting depth %d exceeded"%self.maxDepth) kw=self.padding.copy() if depth>0: kw.update(width='100%') # was [1:] to omit leading woo./wooExtra., but that is not desirable head=tag.b('.'.join(obj.__class__.__module__.split('.')[0:])+'.'+obj.__class__.__name__) head=tag.a(head,href=woo.document.makeObjectUrl(obj),title=_ensureUnicode(obj.__class__.__doc__)) ret=tag.table(tag.th(head,colspan=3,align='left'),frame='box',rules='all',**kw) # get all attribute traits first traits=obj._getAllTraits() for trait in traits: if trait.hidden or (self.hideNoGui and trait.noGui) or trait.noDump or (trait.hideIf and eval(trait.hideIf,globals(),{'self':obj})): continue # start new group (additional line) if trait.startGroup: ret.append(tag.tr(tag.td(tag.i(u'▸ %s'%_ensureUnicode(trait.startGroup)),colspan=3))) attr=getattr(obj,trait.name) if self.showDoc: tr=tag.tr(tag.td(_ensureUnicode(trait.doc))) else: try: tr=tag.tr(tag.td(tag.a(trait.name,href=woo.document.makeObjectUrl(obj,trait.name),title=_ensureUnicode(trait.doc)))) except UnicodeEncodeError: print 'ERROR: UnicodeEncodeError while formatting the attribute ',obj.__class__.__name__+'.'+trait.name print 'ERROR: the docstring is',trait.doc raise # tr=tag.tr(tag.td(trait.name if not self.showDoc else trait.doc.decode('utf-8'))) # nested object if isinstance(attr,woo.core.Object): tr.append([tag.td(self(attr,depth+1),align='justify'),tag.td()]) # sequence of objects (no units here) elif hasattr(attr,'__len__') and len(attr)>0 and isinstance(attr[0],woo.core.Object): tr.append(tag.td(tag.ol([tag.li(self(o,depth+1)) for o in attr]))) else: # !! make deepcopy so that the original object is not modified !! import copy attr=copy.deepcopy(attr) if not trait.multiUnit: # the easier case if not trait.prefUnit: unit=u'−' else: unit=_ensureUnicode(trait.prefUnit[0][0]) # create new list, where entries are multiplied by the multiplier if type(attr)==list: attr=[a*trait.prefUnit[0][1] for a in attr] else: attr=attr*trait.prefUnit[0][1] else: # multiple units unit=[] wasList=isinstance(attr,list) if not wasList: attr=[attr] # handle uniformly for i in range(len(attr)): attr[i]=[attr[i][j]*trait.prefUnit[j][1] for j in range(len(attr[i]))] for pu in trait.prefUnit: unit.append(_ensureUnicode(pu[0])) if not wasList: attr=attr[0] unit=', '.join(unit) # sequence type, or something similar if hasattr(attr,'__len__') and not isinstance(attr,str): if len(attr)>0: tr.append(tag.td(self.htmlSeq(attr,insideTable=False),align='right')) else: tr.append(tag.td(tag.i('[empty]'),align='right')) else: tr.append(tag.td(float2str(attr) if isinstance(attr,float) else str(attr),align='right')) if unit: tr.append(tag.td(unit,align='right')) ret.append(tr) if depth>0 or dontRender: return ret return ret.generate().render('xhtml',encoding='ascii')+b'\n'
def render_fdx_subset(self,fdx,start_with_scene,end_with_scene,mode,formatter): theoutput = tag.div(class_="scrippet"+mode) # self.log.debug("FDX: %s START: %d END %d" % (fdx,start_with_scene,end_with_scene)) fdx_obj = self._get_src(self.env, formatter.req, *fdx) fd_doc = cElementTree.fromstring(fdx_obj.getStream().read()) renderParagraphs = False for fd_content in fd_doc.findall("Content"): for fd_paragraph in fd_content.findall("Paragraph"): ptype = fd_paragraph.get('Type') if ptype == "Action": ptype = "action" elif ptype == "Character": ptype = "character" elif ptype == "Dialogue": ptype = "dialogue" elif ptype == "Parenthetical": ptype = "parenthetical" elif ptype == "Shot": ptype = "shot" elif ptype == "Scene Heading": if int(fd_paragraph.get('Number')) == start_with_scene: renderParagraphs = True if int(fd_paragraph.get('Number')) == end_with_scene: renderParagraphs = False ptype = "sceneheader" elif ptype == "Transition": ptype = "transition" elif ptype == "Teaser/Act One": ptype = "header" elif ptype == "New Act": ptype = "header" elif ptype == "End Of Act": ptype = "header" else: ptype = "action" #UNHANDLED FOR THE MOMENT #Show/Ep. Title ptext = [] for fd_text in fd_paragraph.findall("Text"): text_style = fd_text.get('Style') if fd_text.text != None: if "FADE IN:" in fd_text.text.upper(): fd_text.text = fd_text.text.upper() if ptype in ["character","transition","sceneheader","header","shot"]: fd_text.text = fd_text.text.upper() #clean smart quotes fd_text.text = fd_text.text.replace(u"\u201c", "\"").replace(u"\u201d", "\"") #strip double curly quotes fd_text.text = fd_text.text.replace(u"\u2018", "'").replace(u"\u2019", "'").replace(u"\u02BC", "'") #strip single curly quotes ptext.append({"style":text_style,"text":fd_text.text}) content = [] for block in ptext: if block["style"] == "Italic": content.append(tag.i(block["text"])) elif block["style"] == "Underline": content.append(tag.u(block["text"])) elif block["style"] == "Bold": content.append(tag.b(block["text"])) elif block["style"] == "Bold+Underline": content.append(tag.b(tag.u(block["text"]))) else: content.append(block["text"]) if renderParagraphs: theoutput.append(tag.p(content,class_=ptype+mode)) return theoutput
try: # Establish binding with the authenticated user's credentials self.ldap.simple_bind_s(dn, old) self.log.warn('Ldap change password dn. %s' % dn) # Update password self.ldap.passwd_s(dn, old, p1) except ldap.LDAPError, e: data['accountldap_message'] = \ tag.center(u'There was an error changing your password.', tag.b(u' Please make sure the old password you' ' entered was correct.'), style='color:chocolate') self.log.warn('Ldap change password. %s' % e) return template, data, None data['accountldap_message'] = \ tag.center(tag.b(u'Your LDAP password has been updated successfully.'), style='color:green') return template, data, None # #---------------------------------------------- ITemplateProvider interface # def get_htdocs_dirs(self): return [] def get_templates_dirs(self): from pkg_resources import resource_filename return [resource_filename(__name__, 'templates')] # #----------------------------------------------------------- helper methods
def _do_acct_details(self, req): username = req.args.get('user') if not username: # Accessing user account details without username is not useful, # so we revert such request immediately. add_warning(req, Markup(tag.span(tag_( "Please choose account by username from list to proceed." )))) req.redirect(req.href.admin('accounts', 'users')) acctmgr = self.acctmgr guard = self.guard if req.args.get('update'): req.redirect(req.href.admin('accounts', 'users', user=username)) elif req.args.get('delete') or req.args.get('release'): # delete failed login attempts, evaluating attempts count if guard.failed_count(username, reset=True) > 0: add_notice(req, Markup(tag.span(Markup(_( "Failed login attempts for user %(user)s deleted", user=tag.b(username) ))))) elif req.args.get('list'): req.redirect(req.href.admin('accounts', 'users')) data = {'_': _, 'user': username, } stores = StoreOrder(stores=acctmgr.stores, list=acctmgr.password_store) user_store = acctmgr.find_user_store(username) if not user_store is None: data['user_store'] = user_store.__class__.__name__ data['store_order_num'] = stores[user_store] data['ignore_auth_case'] = \ self.config.getbool('trac', 'ignore_auth_case') for username_, name, email in self.env.get_known_users(): if username_ == username: data['name'] = name if email: data['email'] = email break ts_seen = acctmgr.last_seen(username) if ts_seen is not None: data['last_visit'] = format_datetime(ts_seen[0][1], tzinfo=req.tz) attempts = [] attempts_count = guard.failed_count(username, reset = None) if attempts_count > 0: for attempt in guard.get_failed_log(username): t = format_datetime(to_datetime( attempt['time']), tzinfo=req.tz) attempts.append({'ipnr': attempt['ipnr'], 'time': t}) data['attempts'] = attempts data['attempts_count'] = attempts_count data['pretty_lock_time'] = guard.pretty_lock_time(username, next=True) data['lock_count'] = guard.lock_count(username) if guard.user_locked(username) is True: data['user_locked'] = True data['release_time'] = guard.pretty_release_time(req, username) if is_enabled(self.env, EmailVerificationModule) and \ acctmgr.verify_email is True: data['verification'] = 'enabled' data['email_verified'] = acctmgr.email_verified(username, email) self.log.debug('AcctMgr:admin:_do_acct_details for user \"' + \ username + '\", email \"' + str(email) + '\": ' + \ str(data['email_verified'])) add_stylesheet(req, 'acct_mgr/acct_mgr.css') data['url'] = req.href.admin('accounts', 'users', user=username) return 'account_details.html', data
def render(self, context, mimetype, content, filename=None, url=None): add_stylesheet(context.req, 'scrippets/css/scrippets-full.css') if hasattr(content, 'read'): content = content.read() mode = "-full" theoutput = tag.div(class_="scrippet" + mode) fd_doc = cElementTree.fromstring(content) for fd_content in fd_doc.findall("Content"): for fd_paragraph in fd_content.findall("Paragraph"): ptype = fd_paragraph.get('Type') if ptype == "Action": ptype = "action" elif ptype == "Character": ptype = "character" elif ptype == "Dialogue": ptype = "dialogue" elif ptype == "Parenthetical": ptype = "parenthetical" elif ptype == "Scene Heading": ptype = "sceneheader" elif ptype == "Shot": ptype = "shot" elif ptype == "Transition": ptype = "transition" elif ptype == "Teaser/Act One": ptype = "header" elif ptype == "New Act": ptype = "header" elif ptype == "End Of Act": ptype = "header" else: ptype = "action" #UNHANDLED FOR THE MOMENT #Show/Ep. Title ptext = [] for fd_text in fd_paragraph.findall("Text"): text_style = fd_text.get('Style') if fd_text.text != None: if "FADE IN:" in fd_text.text.upper(): fd_text.text = fd_text.text.upper() if ptype in [ "character", "transition", "sceneheader", "header", "shot" ]: fd_text.text = fd_text.text.upper() #clean smart quotes fd_text.text = fd_text.text.replace( u"\u201c", "\"").replace(u"\u201d", "\"") #strip double curly quotes fd_text.text = fd_text.text.replace( u"\u2018", "'").replace(u"\u2019", "'").replace( u"\u02BC", "'") #strip single curly quotes ptext.append({ "style": text_style, "text": fd_text.text }) content = [] for block in ptext: if block["style"] == "Italic": content.append(tag.i(block["text"])) elif block["style"] == "Underline": content.append(tag.u(block["text"])) elif block["style"] == "Bold": content.append(tag.b(block["text"])) elif block["style"] == "Bold+Underline": content.append(tag.b(tag.u(block["text"]))) else: content.append(block["text"]) theoutput += tag.p(content, class_=ptype + mode) for fd_titlepage in fd_doc.findall("TitlePage"): for fd_content in fd_titlepage.findall("Content"): for fd_paragraph in fd_content.findall("Paragraph"): ptype = fd_paragraph.get('Type') for fd_text in fd_paragraph.findall("Text"): text_style = fd_text.get('Style') if fd_text.text != None: self.log.debug("SCRIPPET: " + fd_text.text) return "%s" % theoutput
def _do_acct_details(self, req): username = req.args.get('user') if not username: # Accessing user account details without username is not useful, # so we revert such request immediately. add_warning( req, Markup( tag.span( tag_( "Please choose account by username from list to proceed." )))) req.redirect(req.href.admin('accounts', 'users')) acctmgr = self.acctmgr guard = self.guard if req.args.get('update'): req.redirect(req.href.admin('accounts', 'users', user=username)) elif req.args.get('delete') or req.args.get('release'): # delete failed login attempts, evaluating attempts count if guard.failed_count(username, reset=True) > 0: add_notice( req, Markup( tag.span( Markup( _("Failed login attempts for user %(user)s deleted", user=tag.b(username)))))) elif req.args.get('list'): req.redirect(req.href.admin('accounts', 'users')) data = { '_dgettext': dgettext, 'user': username, } stores = StoreOrder(stores=acctmgr.stores, list=acctmgr.password_store) user_store = acctmgr.find_user_store(username) if not user_store is None: data['user_store'] = user_store.__class__.__name__ data['store_order_num'] = stores[user_store] data['ignore_auth_case'] = \ self.config.getbool('trac', 'ignore_auth_case') for username_, name, email in self.env.get_known_users(): if username_ == username: data['name'] = name if email: data['email'] = email break ts_seen = last_seen(self.env, username) if ts_seen is not None: data['last_visit'] = format_datetime(ts_seen[0][1], tzinfo=req.tz) attempts = [] attempts_count = guard.failed_count(username, reset=None) if attempts_count > 0: for attempt in guard.get_failed_log(username): t = format_datetime(to_datetime(attempt['time']), tzinfo=req.tz) attempts.append({'ipnr': attempt['ipnr'], 'time': t}) data['attempts'] = attempts data['attempts_count'] = attempts_count data['pretty_lock_time'] = guard.pretty_lock_time(username, next=True) data['lock_count'] = guard.lock_count(username) if guard.user_locked(username) is True: data['user_locked'] = True data['release_time'] = guard.pretty_release_time(req, username) if is_enabled(self.env, EmailVerificationModule) and \ acctmgr.verify_email is True: data['verification'] = 'enabled' data['email_verified'] = email_verified(self.env, username, email) self.log.debug('AcctMgr:admin:_do_acct_details for user \"' + \ username + '\", email \"' + str(email) + '\": ' + \ str(data['email_verified'])) add_stylesheet(req, 'acct_mgr/acct_mgr.css') data['url'] = req.href.admin('accounts', 'users', user=username) return 'account_details.html', data
def expand_macro(self, formatter, name, args): t = datetime.now(utc) return tag.b(format_datetime(t, '%c'))
dn = '%s=%s,%s,%s' % (self.userFilter, req.authname, self.userdn, self.basedn) try: self.log.warn('Ldap change password dn. %s' % dn) self.ldap.passwd_s(dn, old, p1) except ldap.LDAPError, e: data['accountldap_message'] = tag.center( u'Se produjo un error durante el cambio de contraseña.', tag. b(u' Por favor, comprueba que la contraseña antigua es la correcta.' ), style='color:chocolate') self.log.warn('Ldap change password. %s' % e) return template, data, None data['accountldap_message'] = tag.center( tag.b(u'La contraseña se ha cambiado correctamente.'), style='color:green') return template, data, None # #---------------------------------------------- ITemplateProvider interface # def get_htdocs_dirs(self): return [] def get_templates_dirs(self): from pkg_resources import resource_filename return [resource_filename(__name__, 'templates')] # #----------------------------------------------------------- helper methods
def process_request(self, req): acctmgr = self.acctmgr if req.authname != 'anonymous': req.redirect(req.href.prefs('account')) action = req.args.get('action') name = req.args.get('name', '').strip() username = acctmgr.handle_username_casing( req.args.get('username', '').strip()) data = { '_dgettext': dgettext, 'acctmgr': dict(name=name, username=username), 'ignore_auth_case': self.config.getbool('trac', 'ignore_auth_case') } verify_enabled = is_enabled(self.env, EmailVerificationModule) and \ EmailVerificationModule(self.env).verify_email data['verify_account_enabled'] = verify_enabled if req.method == 'POST' and action == 'create': try: # Check request and prime account on success. acctmgr.validate_account(req, True) except RegistrationError, e: # Attempt deferred translation. message = gettext(e.message) # Check for (matching number of) message arguments before # attempting string substitution. if e.msg_args and \ len(e.msg_args) == len(re.findall('%s', message)): message = message % e.msg_args chrome.add_warning(req, Markup(message)) else: if self.require_approval: set_user_attribute(self.env, username, 'approval', N_('pending')) # Notify admin user about registration pending for review. acctmgr._notify('registration_approval_required', username) chrome.add_notice( req, Markup( tag.span( Markup( _("Your username has been registered successfully, but " "your account requires administrative approval. " "Please proceed according to local policy." ))))) if verify_enabled: chrome.add_notice( req, Markup( tag.span( Markup( _("""Your username has been successfully registered but your account still requires activation. Please login as user %(user)s, and follow the instructions.""", user=tag.b(username)))))) req.redirect(req.href.login()) chrome.add_notice( req, Markup( tag.span( Markup( _("""Registration has been finished successfully. You may log in as user %(user)s now.""", user=tag.b(username)))))) req.redirect(req.href.login())
def test_tracerror_with_fragment_as_argument(self): e1 = TracError(tag(tag.b('the message'))) e2 = HTTPInternalError(e1) self.assertEqual('500 Trac Error (<b>the message</b>)', unicode(e2))
def validate_registration(self, req): if req.path_info == '/prefs': return acctmgr = AccountManager(self.env) username = acctmgr.handle_username_casing( req.args.get('username', '').strip()) if not username: raise RegistrationError(N_("Username cannot be empty.")) # Always exclude some special characters, i.e. # ':' can't be used in HtPasswdStore # '[' and ']' can't be used in SvnServePasswordStore blacklist = acctmgr.username_char_blacklist if containsAny(username, blacklist): pretty_blacklist = '' for c in blacklist: if pretty_blacklist == '': pretty_blacklist = tag(' \'', tag.b(c), '\'') else: pretty_blacklist = tag(pretty_blacklist, ', \'', tag.b(c), '\'') raise RegistrationError(N_( "The username must not contain any of these characters: %s"), tag.b(pretty_blacklist) ) # All upper-cased names are reserved for permission action names. if username.isupper(): raise RegistrationError(N_( "A username with only upper-cased characters is not allowed.") ) # Prohibit some user names, that are important for Trac and therefor # reserved, even if not in the permission store for some reason. if username.lower() in ['anonymous', 'authenticated']: raise RegistrationError(N_("Username %s is not allowed."), tag.b(username) ) # NOTE: A user may exist in a password store but not in the permission # store. I.e. this happens, when the user (from the password store) # never logged in into Trac. So we have to perform this test here # and cannot just check for the user being in the permission store. # And better obfuscate whether an existing user or group name # was responsible for rejection of this user name. for store_user in acctmgr.get_users(): # Do it carefully by disregarding case. if store_user.lower() == username.lower(): raise RegistrationError(N_( "Another account or group already exists, who's name " "differs from %s only by case or is identical."), tag.b(username) ) # Password consistency checks follow. password = req.args.get('password') if not password: raise RegistrationError(N_("Password cannot be empty.")) elif password != req.args.get('password_confirm'): raise RegistrationError(N_("The passwords must match."))
def test_error_with_error_with_fragment(self): v1 = ValueError(tag('invalid literal for int(): ', tag.b('blah'))) rv = to_fragment(ValueError(v1)) self.assertEqual(Fragment, type(rv)) self.assertEqual('invalid literal for int(): <b>blah</b>', unicode(rv))
def _boldstar_formatter(self,formatter,match,fullmatch): return tag.b(fullmatch.group('text'))
def __call__(self,obj,depth=0,dontRender=False): from genshi.builder import tag if depth>self.maxDepth: raise RuntimeError("Maximum nesting depth %d exceeded"%self.maxDepth) kw=self.padding.copy() if depth>0: kw.update(width='100%') # was [1:] to omit leading woo./wooExtra., but that is not desirable objInExtra=obj.__class__.__module__.startswith('wooExtra.') if self.hideWooExtra and objInExtra: head=tag.span(tag.b(obj.__class__.__name__),title=_ensureUnicode(obj.__class__.__doc__)) else: head=tag.b('.'.join(obj.__class__.__module__.split('.')[0:])+'.'+obj.__class__.__name__) head=tag.a(head,href=woo.document.makeObjectUrl(obj),title=_ensureUnicode(obj.__class__.__doc__)) ret=tag.table(tag.th(head,colspan=3,align='left'),frame='box',rules='all',**kw) # get all attribute traits first traits=obj._getAllTraits() for trait in traits: if trait.hidden or (self.hideNoGui and trait.noGui) or trait.noDump or (trait.hideIf and eval(trait.hideIf,globals(),{'self':obj})): continue # start new group (additional line) if trait.startGroup: ret.append(tag.tr(tag.td(tag.i(u'▸ %s'%_ensureUnicode(trait.startGroup)),colspan=3))) attr=getattr(obj,trait.name) if self.showDoc: tr=tag.tr(tag.td(_ensureUnicode(trait.doc))) else: try: if self.hideWooExtra and objInExtra: label=tag.span(tag.b(trait.name),title=_ensureUnicode(trait.doc)) else: label=tag.a(trait.name,href=woo.document.makeObjectUrl(obj,trait.name),title=_ensureUnicode(trait.doc)) tr=tag.tr(tag.td(label)) except UnicodeEncodeError: print('ERROR: UnicodeEncodeError while formatting the attribute ',obj.__class__.__name__+'.'+trait.name) print('ERROR: the docstring is',trait.doc) raise # tr=tag.tr(tag.td(trait.name if not self.showDoc else trait.doc.decode('utf-8'))) # nested object if isinstance(attr,woo.core.Object): tr.append([tag.td(self(attr,depth+1),align='justify'),tag.td()]) # sequence of objects (no units here) elif hasattr(attr,'__len__') and len(attr)>0 and isinstance(attr[0],woo.core.Object): tr.append(tag.td(tag.ol([tag.li(self(o,depth+1)) for o in attr]))) else: # !! make deepcopy so that the original object is not modified !! import copy attr=copy.deepcopy(attr) if not trait.multiUnit: # the easier case if not trait.prefUnit: unit=u'−' else: unit=_ensureUnicode(trait.prefUnit[0][0]) # create new list, where entries are multiplied by the multiplier if type(attr)==list: attr=[a*trait.prefUnit[0][1] for a in attr] else: attr=attr*trait.prefUnit[0][1] else: # multiple units unit=[] wasList=isinstance(attr,list) if not wasList: attr=[attr] # handle uniformly for i in range(len(attr)): attr[i]=[attr[i][j]*trait.prefUnit[j][1] for j in range(len(attr[i]))] for pu in trait.prefUnit: unit.append(_ensureUnicode(pu[0])) if not wasList: attr=attr[0] unit=', '.join(unit) # sequence type, or something similar if hasattr(attr,'__len__') and not isinstance(attr,(str,unicode,bytes)): if len(attr)>0: tr.append(tag.td(self.htmlSeq(attr,insideTable=False),align='right')) else: tr.append(tag.td(tag.i('[empty]'),align='right')) else: tr.append(tag.td(float2str(attr) if isinstance(attr,float) else str(attr),align='right')) if unit: tr.append(tag.td(unit,align='right')) ret.append(tr) if depth>0 or dontRender: return ret r1=ret.generate().render('xhtml',encoding='ascii') if isinstance(r1,bytes): r1=r1.decode('ascii') return r1+u'\n'
def greeting2(self, arg): return tag.b('Hello, %s!' % arg)
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 content(self, req, ticket): return tag.b('hello world')