Example #1
0
    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:
            message = tag(
                tag.p(_('Unable to send email due to identity crisis.')),
                # convert explicitly to `Fragment` to avoid breaking message
                # when passing `LazyProxy` object to `Fragment`
                tag.p(to_fragment(tag_(
                    "Neither %(from_)s nor %(reply_to)s are specified in the "
                    "configuration.",
                    from_=tag.strong("[notification] smtp_from"),
                    reply_to=tag.strong("[notification] smtp_replyto")))))
            raise TracError(message, _("SMTP Notification Error"))

        Notify.notify(self, resid)
Example #2
0
    def _format_reminder(self,
                         req,
                         ticket,
                         id,
                         time,
                         author,
                         origin,
                         description,
                         delete_button=True):
        now = to_datetime(None)
        time = to_datetime(time)
        if now >= time:
            when = tag(tag.strong("Right now"), " (pending)")
        else:
            when = tag("In ", tag.strong(pretty_timedelta(time)), " (",
                       format_date(time), ")")

        if description:
            context = Context.from_request(req, ticket.resource)
            desc = tag.div(format_to_oneliner(self.env, context, description),
                           class_="description")
        else:
            desc = tag()

        return tag(
            self._reminder_delete_form(req, id) if delete_button else None,
            when, " - added by ",
            tag.em(Chrome(self.env).authorinfo(req, author)), " ",
            tag.span(pretty_timedelta(origin),
                     title=format_datetime(
                         origin, req.session.get('datefmt', 'iso8601'),
                         req.tz)), " ago.", desc)
Example #3
0
    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:
            message = tag(
                tag.p(_('Unable to send email due to identity crisis.')),
                # convert explicitly to `Fragment` to avoid breaking message
                # when passing `LazyProxy` object to `Fragment`
                tag.p(to_fragment(tag_(
                    "Neither %(from_)s nor %(reply_to)s are specified in the "
                    "configuration.",
                    from_=tag.strong("[notification] smtp_from"),
                    reply_to=tag.strong("[notification] smtp_replyto")))))
            raise TracError(message, _("SMTP Notification Error"))

        Notify.notify(self, resid)
Example #4
0
def moreless(text, length):
    """Turns `text` into HTML code where everything behind `length` can be uncovered using a ''show more'' link
       and later covered again with a ''show less'' link."""
    try:
        if len(text) <= length:
            return tag(text)
    except:
        return tag(text)
    return tag(tag.span(text[:length]),tag.a(' [', tag.strong(Markup('&hellip;')), ']', class_="more"),
        tag.span(text[length:],class_="moretext"),tag.a(' [', tag.strong('-'), ']', class_="less"))
Example #5
0
def moreless(text, length):
    """Turns `text` into HTML code where everything behind `length` can be uncovered using a ''show more'' link
       and later covered again with a ''show less'' link."""
    try:
        if len(text) <= length:
            return tag(text)
    except:
        return tag(text)
    return tag(tag.span(text[:length]),
               tag.a(' [', tag.strong(Markup('&hellip;')), ']', class_="more"),
               tag.span(text[length:], class_="moretext"),
               tag.a(' [', tag.strong('-'), ']', class_="less"))
Example #6
0
 def generate_prefix(prefix):
     intertrac = intertracs[prefix]
     if isinstance(intertrac, basestring):
         yield tag.tr(tag.td(tag.strong(prefix)),
                      tag.td(tag_("Alias for %(name)s",
                                  name=tag.strong(intertrac))))
     else:
         url = intertrac.get('url', '')
         if url:
             title = intertrac.get('title', url)
             yield tag.tr(tag.td(tag.a(tag.strong(prefix),
                                       href=url + '/timeline')),
                          tag.td(tag.a(title, href=url)))
Example #7
0
 def generate_prefix(prefix):
     intertrac = intertracs[prefix]
     if isinstance(intertrac, basestring):
         yield tag.tr(tag.td(tag.strong(prefix)),
                      tag.td('Alias for ', tag.strong(intertrac)))
     else:
         url = intertrac.get('url', '')
         if url:
             title = intertrac.get('title', url)
             yield tag.tr(
                 tag.td(
                     tag.a(tag.strong(prefix), href=url + '/timeline')),
                 tag.td(tag.a(title, href=url)))
Example #8
0
    def _format_reminder(self, req, ticket, id, time, author, origin, description, delete_button=True):
        now = to_datetime(None)
        time = to_datetime(time)
        if now >= time:
            when = tag(tag.strong("Right now"), " (pending)")
        else:
            when = tag("In ", tag.strong(pretty_timedelta(time)), " (", format_date(time), ")")

        if description:
            context = Context.from_request(req, ticket.resource)
            desc = tag.div(format_to_oneliner(self.env, context, description), class_="description")
        else:
            desc = tag()

        return tag(self._reminder_delete_form(req, id) if delete_button else None, when, " - added by ", tag.em(Chrome(self.env).authorinfo(req, author)), " ", tag.span(pretty_timedelta(origin), title=format_datetime(origin, req.session.get('datefmt', 'iso8601'), req.tz)), " ago.", desc)
Example #9
0
 def render_group(group):
     return tag.ul(
         tag.li(isinstance(elt, tuple) and 
                tag(tag.strong(elt[0]), render_group(elt[1])) or
                tag.a(wiki.format_page_name(elt),
                      href=formatter.href.wiki(elt)))
         for elt in group)
Example #10
0
    def _validate(self, req, page):
        valid = True

        # Validate page size
        if len(req.args.get('text', '')) > self.max_size:
            add_warning(
                req,
                _(
                    'The wiki page is too long (must be less '
                    'than %(num)s characters)',
                    num=self.max_size))
            valid = False

        # Give the manipulators a pass at post-processing the page
        for manipulator in self.page_manipulators:
            for field, message in manipulator.validate_wiki_page(req, page):
                valid = False
                if field:
                    add_warning(
                        req,
                        tag_(
                            "The Wiki page field %(field)s"
                            " is invalid: %(message)s",
                            field=tag.strong(field),
                            message=message))
                else:
                    add_warning(
                        req,
                        tag_("Invalid Wiki page: %(message)s",
                             message=message))
        return valid
Example #11
0
    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.code(ep.__class__.__name__),
                       kinds=', '.join('"%s"' % ep_kinds[f] for f in
                                       current_filters & ep_filters)),
                  tag.strong(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))))
Example #12
0
 def format_change(field,oldvalue,newvalue):
     """Formats tickets changes."""
     fieldtag = tag.strong(field)
     if field == 'cc':
         oldvalues = set(oldvalue and oldvalue.split(', ') or [])
         newvalues = set(newvalue and newvalue.split(', ') or [])
         added   = newvalues.difference(oldvalues)
         removed = oldvalues.difference(newvalues)
         strng = fieldtag
         if added:
             strng += tag(" ", tag.em(', '.join(added)),
                          _(" added"))
         if removed:
             if added:
                 strng += tag(', ')
             strng += tag(" ", tag.em(', '.join(removed)),
                          _(" removed"))
         return strng
     elif field == 'description':
         return fieldtag + tag(_(" modified"), " (", tag.a(_("diff"),
             href=req.href('ticket',id,action='diff',
             version=self.commentnum)), ")")
     elif field == 'comment':
         self.commentnum = oldvalue
         self.comment    = newvalue
         return tag("")
     elif not oldvalue:
         return fieldtag + tag(" ", tag.em(newvalue), _(" added"))
     elif not newvalue:
         return fieldtag + tag(" ", tag.em(oldvalue), _(" deleted"))
     else:
         return fieldtag + tag(_(" changed from "), tag.em(oldvalue),
                               _(" to "), tag.em(newvalue))
Example #13
0
 def render_group(group):
     return tag.ul(
         tag.li(tag(tag.strong(elt[0].strip('/')), render_group(elt[1]))
                if isinstance(elt, tuple) else
                tag.a(wiki.format_page_name(omitprefix(elt)),
                      href=formatter.href.wiki(elt)))
         for elt in group)
Example #14
0
    def _render_source(self, context, stream, annotations, marks=None):
        from trac.web.chrome import add_warning
        annotators, labels, titles = {}, {}, {}
        for annotator in self.annotators:
            atype, alabel, atitle = annotator.get_annotation_type()
            if atype in annotations:
                labels[atype] = alabel
                titles[atype] = atitle
                annotators[atype] = annotator
        annotations = [a for a in annotations if a in annotators]

        if isinstance(stream, list):
            stream = HTMLParser(StringIO(u'\n'.join(stream)))
        elif isinstance(stream, unicode):
            text = stream
            def linesplitter():
                for line in text.splitlines(True):
                    yield TEXT, line, (None, -1, -1)
            stream = linesplitter()

        annotator_datas = []
        for a in annotations:
            annotator = annotators[a]
            try:
                data = (annotator, annotator.get_annotation_data(context))
            except TracError, e:
                self.log.warning("Can't use annotator '%s': %s", a, e.message)
                add_warning(context.req, tag.strong(
                    tag_("Can't use %(annotator)s annotator: %(error)s",
                         annotator=tag.em(a), error=tag.pre(e.message))))
                data = (None, None)
            annotator_datas.append(data)
Example #15
0
    def _render_source(self, context, stream, annotations, marks=None):
        from trac.web.chrome import add_warning
        annotators, labels, titles = {}, {}, {}
        for annotator in self.annotators:
            atype, alabel, atitle = annotator.get_annotation_type()
            if atype in annotations:
                labels[atype] = alabel
                titles[atype] = atitle
                annotators[atype] = annotator
        annotations = [a for a in annotations if a in annotators]

        if isinstance(stream, list):
            stream = HTMLParser(StringIO(u'\n'.join(stream)))
        elif isinstance(stream, unicode):
            text = stream
            def linesplitter():
                for line in text.splitlines(True):
                    yield TEXT, line, (None, -1, -1)
            stream = linesplitter()

        annotator_datas = []
        for a in annotations:
            annotator = annotators[a]
            try:
                data = (annotator, annotator.get_annotation_data(context))
            except TracError, e:
                self.log.warning("Can't use annotator '%s': %s", a, e.message)
                add_warning(context.req, tag.strong(
                    tag_("Can't use %(annotator)s annotator: %(error)s",
                         annotator=tag.em(a), error=tag.pre(e.message))))
                data = (None, None)
            annotator_datas.append(data)
Example #16
0
    def filter_stream(self, req, method, filename, stream, data):
        """Return a filtered Genshi event stream, or the original unfiltered
        stream if no match.

        `req` is the current request object, `method` is the Genshi render
        method (xml, xhtml or text), `filename` is the filename of the template
        to be rendered, `stream` is the event stream and `data` is the data for
        the current template.

        See the Genshi documentation for more information.
        """
        if filename == 'ticket.html':
            ticket = data['ticket']
            if ticket.exists:
                if req.perm.has_permission('SENSITIVE_VIEW'):
                    qry = DBSession().query(CustomerRequest)
                    if not qry.get(ticket.values.get('customerrequest')).active:
                        div = tag.div(
                            tag.div(
                                tag.strong(u'Heads up! '),
                                tag.span(u'This ticket is assigned to an inactive customer request.',),
                                class_="alert alert-info"),
                            id='inactive_cr_ticket')
                        return stream | Transformer("//div[@id='ticket']").before(div)
        return stream
Example #17
0
    def process_request(self, req):
        if req.path_info == '/mindmap/status':
            db = self.env.get_db_cnx()
            cursor = db.cursor()
            try:
                cursor.execute('SELECT hash,content FROM mindmapcache')
                content = tag.html(
                    tag.body(
                        tag.dd([[
                            tag.dt(tag.a(k, href=req.href.mindmap(k + '.mm'))),
                            tag.dd(tag.pre(v))
                        ] for k, v in cursor.fetchall()])))
            except Exception, e:
                content = tag.html(
                    tag.body(tag.strong("DB Error: " + unicode(e))))
            html = content.generate().render("xhtml")
            req.send_response(200)
            req.send_header('Cache-control', 'must-revalidate')
            req.send_header('Content-Type', 'text/html;charset=utf-8')
            req.send_header('Content-Length', len(html))
            req.end_headers()

            if req.method != 'HEAD':
                req.write(html)
            raise RequestDone
Example #18
0
 def _render_property(self, name, mode, context, props):
     repos, revs = props[name]
     def link(rev):
         chgset = repos.get_changeset(rev)
         return tag.a(rev, class_="changeset",
                      title=shorten_line(chgset.message),
                      href=context.href.changeset(rev, repos.reponame))
     if name == 'Parents' and len(revs) == 2: # merge
         new = context.resource.id
         parent_links = [
                 (link(rev), ' (',
                  tag.a('diff', title=_("Diff against this parent "
                        "(show the changes merged from the other parents)"),
                        href=context.href.changeset(new, repos.reponame, 
                                                    old=rev)), ')')
                        for rev in revs]
         return tag([(parent, ', ') for parent in parent_links[:-1]],
                    parent_links[-1], tag.br(),
                    tag.span(tag_("Note: this is a %(merge)s changeset, "
                                  "the changes displayed below correspond "
                                  "to the merge itself.",
                                  merge=tag.strong('merge')),
                             class_='hint'), tag.br(), 
                    # TODO: only keep chunks present in both parents 
                    #       (conflicts) or in none (extra changes)
                    # tag.span('No changes means the merge was clean.',
                    #         class_='hint'), tag.br(), 
                    tag.span(tag_("Use the %(diff)s links above to see all "
                                  "the changes relative to each parent.",
                                  diff=tag.tt('(diff)')),
                             class_='hint'))
     return tag([tag(link(rev), ', ') for rev in revs[:-1]],
                link(revs[-1]))
Example #19
0
 def render_group(group):
     return tag.ul(
         tag.li(tag(tag.strong(elt[0].strip('/')), render_group(elt[1]))
                if isinstance(elt, tuple) else
                tag.a(wiki.format_page_name(omitprefix(elt)),
                      href=formatter.href.wiki(elt)))
         for elt in group)
Example #20
0
 def expand_macro(self, formatter, name, content, args=None):
     hint = '|| yyyy-mm-ddThh:mm:ss || yyyy-mm-ddThh:mm:ss || message'
     pattern = "\s*||(.*)||(.*)||(.*)".replace('|', '\|')
     pattern = re.compile(pattern)
     try:
         if content == None:
             return tag.div('ShowWhen Macro is not supported. Use WikiProcessor-style instead.', \
                            class_="system-message")
         now = datetime.now(utc)
         for line in content.split('\n'):
             matched = pattern.match(line)
             if matched:
                 result = matched.groups()
                 by, to, text = result
                 by, to = parse_date(by, None,
                                     hint), parse_date(to, None, hint)
                 self.env.log.debug('parsed time range: %s / %s' % (by, to))
                 if by <= now and now <= to:
                     return format_to_html(self.env, formatter.context,
                                           text)
         return None
     except Exception, e:
         return tag.div(tag.strong(e.title),
                        ': ' + e.message,
                        class_="system-message")
Example #21
0
 def format_change(field, oldvalue, newvalue):
     """Formats tickets changes."""
     fieldtag = tag.strong(field)
     if field == "cc":
         oldvalues = set(oldvalue and oldvalue.split(", ") or [])
         newvalues = set(newvalue and newvalue.split(", ") or [])
         added = newvalues.difference(oldvalues)
         removed = oldvalues.difference(newvalues)
         strng = fieldtag
         if added:
             strng += tag(" ", tag.em(", ".join(added)), " added")
         if removed:
             if added:
                 strng += tag(", ")
             strng += tag(" ", tag.em(", ".join(removed)), " removed")
         return strng
     elif field == "description":
         return fieldtag + tag(
             " modified (",
             tag.a("diff", href=href("ticket", id, action="diff", version=self.commentnum)),
             ")",
         )
     elif field == "comment":
         self.commentnum = oldvalue
         self.comment = newvalue
         return tag("")
     elif not oldvalue:
         return fieldtag + tag(" ", tag.em(newvalue), " added")
     elif not newvalue:
         return fieldtag + tag(" ", tag.em(oldvalue), " deleted")
     else:
         return fieldtag + tag(" changed from ", tag.em(oldvalue), " to ", tag.em(newvalue))
Example #22
0
    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.code(ep.__class__.__name__),
                       kinds=', '.join('"%s"' % ep_kinds[f] for f in
                                       current_filters & ep_filters)),
                  tag.strong(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))))
Example #23
0
 def mozillate(fmt, match, fullmatch):
     expr = match[1:-1]
     if match[0] == '*':
         return tag.strong(expr)
     elif match[0] == '/':
         return tag.em(expr)
     else:
         return tag.span(expr, class_='underline')
Example #24
0
class MacroListMacro(WikiMacroBase):
    _domain = 'messages'
    _description = cleandoc_(
    """Display a list of all installed Wiki macros, including documentation if
    available.
    
    Optionally, the name of a specific macro can be provided as an argument. In
    that case, only the documentation for that macro will be rendered.
    
    Note that this macro will not be able to display the documentation of
    macros if the `PythonOptimize` option is enabled for mod_python!
    """)

    def expand_macro(self, formatter, name, content):
        from trac.wiki.formatter import system_message

        content = content.strip() if content else ''
        name_filter = content.strip('*')

        def get_macro_descr():
            for macro_provider in formatter.wiki.macro_providers:
                names = list(macro_provider.get_macros() or [])
                if name_filter and not any(name.startswith(name_filter)
                                           for name in names):
                    continue
                try:
                    name_descriptions = [
                        (name, macro_provider.get_macro_description(name))
                        for name in names]
                except Exception, e:
                    yield system_message(
                        _("Error: Can't get description for macro %(name)s",
                          name=names[0]), e), names
                else:
                    for descr, pairs in groupby(name_descriptions,
                                                key=lambda p: p[1]):
                        if descr:
                            if isinstance(descr, (tuple, list)):
                                descr = dgettext(descr[0], descr[1])
                            else:
                                descr = to_unicode(descr) or ''
                            if content == '*':
                                descr = format_to_oneliner(
                                    self.env, formatter.context, descr,
                                    shorten=True)
                            else:
                                descr = format_to_html(
                                    self.env, formatter.context, descr)
                        yield descr, [name for name, descr in pairs]

        return tag.div(class_='trac-macrolist')(
            (tag.h3(tag.code('[[', names[0], ']]'), id='%s-macro' % names[0]),
             len(names) > 1 and tag.p(tag.strong(_("Aliases:")),
                                      [tag.code(' [[', alias, ']]')
                                       for alias in names[1:]]) or None,
             description or tag.em(_("Sorry, no documentation found")))
            for description, names in sorted(get_macro_descr(),
                                             key=lambda item: item[1][0]))
Example #25
0
    def _render_source(self, context, stream, annotations):
        from trac.web.chrome import add_warning
        annotators, labels, titles = {}, {}, {}
        for annotator in self.annotators:
            atype, alabel, atitle = annotator.get_annotation_type()
            if atype in annotations:
                labels[atype] = alabel
                titles[atype] = atitle
                annotators[atype] = annotator
        annotations = [a for a in annotations if a in annotators]

        if isinstance(stream, list):
            stream = HTMLParser(StringIO(u'\n'.join(stream)))
        elif isinstance(stream, unicode):
            text = stream

            def linesplitter():
                for line in text.splitlines(True):
                    yield TEXT, line, (None, -1, -1)

            stream = linesplitter()

        annotator_datas = []
        for a in annotations:
            annotator = annotators[a]
            try:
                data = (annotator, annotator.get_annotation_data(context))
            except TracError as e:
                self.log.warning("Can't use annotator '%s': %s", a, e.message)
                add_warning(
                    context.req,
                    tag.strong(
                        tag_("Can't use %(annotator)s annotator: %(error)s",
                             annotator=tag.em(a),
                             error=tag.pre(e.message))))
                data = (None, None)
            annotator_datas.append(data)

        def _head_row():
            return tag.tr([
                tag.th(labels[a], class_=a, title=titles[a])
                for a in annotations
            ] + [tag.th(u'\xa0', class_='content')])

        def _body_rows():
            for idx, line in enumerate(_group_lines(stream)):
                row = tag.tr()
                for annotator, data in annotator_datas:
                    if annotator:
                        annotator.annotate_row(context, row, idx + 1, line,
                                               data)
                    else:
                        row.append(tag.td())
                row.append(tag.td(line))
                yield row

        return tag.table(class_='code')(tag.thead(_head_row()),
                                        tag.tbody(_body_rows()))
Example #26
0
 def test_find_element_with_tag(self):
     frag = tag(tag.p('Paragraph with a ',
                tag.a('link', href='http://www.edgewall.org'),
                ' and some ', tag.strong('strong text')))
     self.assertIsNotNone(find_element(frag, tag='p'))
     self.assertIsNotNone(find_element(frag, tag='a'))
     self.assertIsNotNone(find_element(frag, tag='strong'))
     self.assertIsNone(find_element(frag, tag='input'))
     self.assertIsNone(find_element(frag, tag='textarea'))
Example #27
0
File: api.py Project: pkdevbox/trac
    def _render_source(self, context, stream, annotations):
        from trac.web.chrome import add_warning

        annotators, labels, titles = {}, {}, {}
        for annotator in self.annotators:
            atype, alabel, atitle = annotator.get_annotation_type()
            if atype in annotations:
                labels[atype] = alabel
                titles[atype] = atitle
                annotators[atype] = annotator
        annotations = [a for a in annotations if a in annotators]

        if isinstance(stream, list):
            stream = HTMLParser(StringIO(u"\n".join(stream)))
        elif isinstance(stream, unicode):
            text = stream

            def linesplitter():
                for line in text.splitlines(True):
                    yield TEXT, line, (None, -1, -1)

            stream = linesplitter()

        annotator_datas = []
        for a in annotations:
            annotator = annotators[a]
            try:
                data = (annotator, annotator.get_annotation_data(context))
            except TracError as e:
                self.log.warning("Can't use annotator '%s': %s", a, e)
                add_warning(
                    context.req,
                    tag.strong(
                        tag_("Can't use %(annotator)s annotator: %(error)s", annotator=tag.em(a), error=tag.pre(e))
                    ),
                )
                data = None, None
            annotator_datas.append(data)

        def _head_row():
            return tag.tr(
                [tag.th(labels[a], class_=a, title=titles[a]) for a in annotations]
                + [tag.th(u"\xa0", class_="content")]
            )

        def _body_rows():
            for idx, line in enumerate(_group_lines(stream)):
                row = tag.tr()
                for annotator, data in annotator_datas:
                    if annotator:
                        annotator.annotate_row(context, row, idx + 1, line, data)
                    else:
                        row.append(tag.td())
                row.append(tag.td(line))
                yield row

        return tag.table(class_="code")(tag.thead(_head_row()), tag.tbody(_body_rows()))
Example #28
0
    def _expand_view_topic(self, formatter, name, content):
        self.log.debug("Rendering ViewTopic macro...")

        # Check permission
        if not formatter.perm.has_permission('DISCUSSION_VIEW'):
            return

        # Determine topic subject
        page_name = formatter.req.path_info[6:] or 'WikiStart'
        subject = content or page_name

        # Create request context.
        context = Context.from_request(formatter.req)
        context.realm = 'discussion-wiki'

        # Get database access.
        db = self.env.get_db_cnx()
        context.cursor = db.cursor()

        # Get API component.
        api = self.env[DiscussionApi]

        # Get topic by subject
        try:
            id = int(subject)
            topic = api.get_topic(context, id)
        except:
            topic = api.get_topic_by_subject(context, subject)
        self.log.debug('subject: %s' % (subject,))
        self.log.debug('topic: %s' % (topic,))

        # Prepare request and resource object.
        if topic:
            context.req.args['topic'] = topic['id']
            context.resource = Resource('discussion', 'topic/%s' % (topic['id']
              ,))

        # Process discussion request.
        template, data = api.process_discussion(context)

        # Return rendered template.
        data['discussion']['mode'] = 'message-list'
        data['discussion']['page_name'] = page_name
        if context.redirect_url:
            # Generate HTML elements for redirection.
            href = context.req.href(context.redirect_url[0]) + \
              context.redirect_url[1]
            self.log.debug("Redirecting to %s" % (href))
            return tag.div(tag.strong('Redirect: '),
              ' This page redirects to ', tag.a(href, href = href),
              tag.script("window.location = '" + context.req.href('discussion',
              'redirect', redirect_url = href) + "'", language = "JavaScript"),
              class_ = "system-message")
        else:
            # Render template.
            return to_unicode(Chrome(self.env).render_template(formatter.req,
              template, data, 'text/html', True))
Example #29
0
 def test_find_element_with_tag(self):
     frag = tag(tag.p('Paragraph with a ',
                tag.a('link', href='http://www.edgewall.org'),
                ' and some ', tag.strong('strong text')))
     self.assertIsNotNone(find_element(frag, tag='p'))
     self.assertIsNotNone(find_element(frag, tag='a'))
     self.assertIsNotNone(find_element(frag, tag='strong'))
     self.assertIsNone(find_element(frag, tag='input'))
     self.assertIsNone(find_element(frag, tag='textarea'))
Example #30
0
def get_powered_by_sign():
    return tag.p("Powered by ",
                 tag.a(tag.strong("IttecoTracPlugin %s" % __version__),
                       href="http://tracplugin.itteco.com/"),
                 tag.br(),
                 tag(
                     "By ",
                     tag.a("Itteco Software", href="http://www.itteco.com"),
                 ),
                 class_="left")
Example #31
0
  def expand_macro(self, formatter, name, content, args):

    title = 'Color Scheme'
    classes = 'colormacro' 

    if args and 'title' in args:
      title = args['title']

    if args and 'class' in args:
      classes  += ' ' + args['class']


    tbody = []
    have_comment = False
    colors = self._parse_arguments(content)

    for color in colors:
      if len(color['title']) > 0:
        have_comment = True
      ## Create row
      tbody.append(
        [
          tag.td()(tag.strong(color['title'])),
          tag.td(
              style='background-color:' + color['orig']
            )(
              tag.div(style='color: black')(color['hex']),
              tag.div(style='color: white')(color['hex'])
          ),
          tag.td(
              style='background-color:' + color['orig']
            )(
              tag.div(style='color: black')(color['rgbp']),
              tag.div(style='color: white')(color['rgbp'])
          ),
        ]
      )
      ## end for loop

    if len(tbody) > 0:
      colcount = len(tbody[0])
      if not have_comment:
        colcount -= 1
      
      table = tag.table(class_=classes)
      table()(tag.thead()(tag.th(colspan='%d' % colcount)(title)))
      ## Attach row in table.
      if have_comment:
        table()(tag.tbody(class_='colorlist')([tag.tr(row) for row in tbody]))
      else:
        table()(tag.tbody(class_='colorlist')([tag.tr(row[1:]) for row in tbody]))

      return table;
    else:
      return tag.div(class_='colormacro')('Nothing to display')
Example #32
0
 def _error_div(self, msg):
     """Display msg in an error box, using Trac style."""
     if isinstance(msg, str):
         msg = to_unicode(msg)
     self.log.error(msg)
     if isinstance(msg, unicode):
         msg = tag.pre(escape(msg))
     return tag.div(
             tag.strong(_("Graphviz macro processor has detected an error. "
                          "Please fix the problem before continuing.")),
             msg, class_="system-message")
Example #33
0
    def expand_macro(self, formatter, name, content):
        """Print redirect notice after edit."""

        target = extract_url(self.env, formatter.context, content)
        if not target:
            target = formatter.context.req.href.wiki(content)

        return tag.div(tag.strong('This page redirects to: '),
                       tag.a(content, href=target),
                       class_='system-message',
                       id='notice')
Example #34
0
 def _error_div(self, msg):
     """Display msg in an error box, using Trac style."""
     if isinstance(msg, str):
         msg = to_unicode(msg)
     self.log.error(msg)
     if isinstance(msg, unicode):
         msg = tag.pre(escape(msg))
     return tag.div(
             tag.strong(_("Canviz macro processor has detected an error. "
                          "Please fix the problem before continuing.")),
             msg, class_="system-message")
Example #35
0
 def render_property_diff(self, name, old_context, old_props,
                          new_context, new_props, options):
     old, new = old_props[name], new_props[name]
     # Render as diff only if multiline (see #3002)
     if '\n' not in old and '\n' not in new:
         return None
     unidiff = '--- \n+++ \n' + \
               '\n'.join(unified_diff(old.splitlines(), new.splitlines(),
                                      options.get('contextlines', 3)))
     return tag.li('Property ', tag.strong(name),
                   Mimeview(self.env).render(old_context, 'text/x-diff',
                                             unidiff))
Example #36
0
    def expand_macro(self, formatter, name, content):
        """Print redirect notice after edit."""

        target = extract_url(self.env, formatter.context, content)
        if not target:
          target = formatter.context.req.href.wiki(content)

        return tag.div(
                  tag.strong('This page redirects to: '),
                  tag.a(content, href=target),
                  class_ = 'system-message',
                  id = 'notice'
               )
Example #37
0
    def expand_macro(self, formatter, name, content):
        from trac.wiki.formatter import system_message

        content = content.strip() if content else ''
        name_filter = content.strip('*')

        def get_macro_descr():
            for macro_provider in formatter.wiki.macro_providers:
                names = list(macro_provider.get_macros() or [])
                if name_filter and not any(
                        name.startswith(name_filter) for name in names):
                    continue
                try:
                    name_descriptions = [
                        (name, macro_provider.get_macro_description(name))
                        for name in names
                    ]
                except Exception as e:
                    yield system_message(
                        _("Error: Can't get description for macro %(name)s",
                          name=names[0]), e), names
                else:
                    for descr, pairs in groupby(name_descriptions,
                                                key=lambda p: p[1]):
                        if descr:
                            if isinstance(descr, (tuple, list)):
                                descr = dgettext(descr[0],
                                                 to_unicode(descr[1])) \
                                        if descr[1] else ''
                            else:
                                descr = to_unicode(descr) or ''
                            if content == '*':
                                descr = format_to_oneliner(self.env,
                                                           formatter.context,
                                                           descr,
                                                           shorten=True)
                            else:
                                descr = format_to_html(self.env,
                                                       formatter.context,
                                                       descr)
                        yield descr, [name for name, descr in pairs]

        return tag.div(class_='trac-macrolist')(
            (tag.h3(tag.code('[[', names[0], ']]'), id='%s-macro' % names[0]),
             len(names) > 1 and tag.p(
                 tag.strong(_("Aliases:")),
                 [tag.code(' [[', alias, ']]')
                  for alias in names[1:]]) or None,
             description or tag.em(_("Sorry, no documentation found")))
            for description, names in sorted(get_macro_descr(),
                                             key=lambda item: item[1][0]))
Example #38
0
def render_tag_changes(old_tags, new_tags):
    old_tags = split_into_tags(old_tags or '')
    new_tags = split_into_tags(new_tags or '')
    added = sorted(new_tags - old_tags)
    added = added and \
            tagn_("%(tags)s added", "%(tags)s added",
                  len(added), tags=builder.em(', '.join(added)))
    removed = sorted(old_tags - new_tags)
    removed = removed and \
              tagn_("%(tags)s removed", "%(tags)s removed",
                    len(removed), tags=builder.em(', '.join(removed)))
    # TRANSLATOR: How to delimit added and removed tags.
    delim = added and removed and _("; ")
    return builder(builder.strong(_("Tags")), ' ', added, delim, removed)
Example #39
0
def render_tag_changes(old_tags, new_tags):
        old_tags = split_into_tags(old_tags or '')
        new_tags = split_into_tags(new_tags or '')
        added = sorted(new_tags - old_tags)
        added = added and \
                tagn_("%(tags)s added", "%(tags)s added",
                      len(added), tags=builder.em(', '.join(added)))
        removed = sorted(old_tags - new_tags)
        removed = removed and \
                  tagn_("%(tags)s removed", "%(tags)s removed",
                        len(removed), tags=builder.em(', '.join(removed)))
        # TRANSLATOR: How to delimit added and removed tags.
        delim = added and removed and _("; ")
        return builder(builder.strong(_("Tags")), ' ', added,
                       delim, removed)
Example #40
0
 def _do_switch(self, env, req, form):
     data = {}
     data['page_title'] = get_resource_description(env, form.resource,
                                                   href=req.href)
     data['title'] = get_resource_shortname(env, form.resource)
     data['siblings'] = []
     for sibling in form.siblings:
         form_id = tag.strong(tag.a(_("Form %(form_id)s",
                                      form_id=sibling[0]),
                                      href=req.href.form(sibling[0])))
         if sibling[1] == '':
             data['siblings'].append(form_id)
         else:
             # TRANSLATOR: Form list entry for form select page
             data['siblings'].append(tag_(
                           "%(form_id)s (subcontext = '%(subcontext)s')",
                           form_id=form_id, subcontext = sibling[1]))
     add_stylesheet(req, 'tracforms/tracforms.css')
     return 'switch.html', data, None
Example #41
0
 def format_change(field, oldvalue, newvalue):
     """Formats tickets changes."""
     fieldtag = tag.strong(field)
     if field == 'cc':
         oldvalues = set(oldvalue and oldvalue.split(', ')
                         or [])
         newvalues = set(newvalue and newvalue.split(', ')
                         or [])
         added = newvalues.difference(oldvalues)
         removed = oldvalues.difference(newvalues)
         strng = fieldtag
         if added:
             strng += tag(" ", tag.em(', '.join(added)),
                          " added")
         if removed:
             if added:
                 strng += tag(', ')
             strng += tag(" ", tag.em(', '.join(removed)),
                          " removed")
         return strng
     elif field == 'description':
         return fieldtag + tag(
             " modified (",
             tag.a("diff",
                   href=href('ticket',
                             id,
                             action='diff',
                             version=self.commentnum)), ")")
     elif field == 'comment':
         self.commentnum = oldvalue
         self.comment = newvalue
         return tag("")
     elif not oldvalue:
         return fieldtag + tag(" ", tag.em(newvalue),
                               " added")
     elif not newvalue:
         return fieldtag + tag(" ", tag.em(oldvalue),
                               " deleted")
     else:
         return fieldtag + tag(" changed from ",
                               tag.em(oldvalue), " to ",
                               tag.em(newvalue))
Example #42
0
 def filter_stream(self, req, method, filename, stream, data):
     if 'modifiedfiles' in data:
         numconflictingtickets = self.__process_ticket_request(req, True)
         #Display a warning message if there are conflicting tickets
         if numconflictingtickets > 0:
             if numconflictingtickets == 1:
                 text = " There is one ticket in conflict!"
             else:
                 text = " There are %s tickets in conflict!" % str(numconflictingtickets)
             stream |= Transformer("//div[@id='changelog']").before(tag.p(tag.strong("Warning:"), text, style='background: #def; border: 2px solid #00d; padding: 3px;'))
         
         #Display the link to this ticket's modifiedfiles page
         stream |= Transformer("//div[@id='changelog']").before(
                    tag.p(
                          'Have a look at the ',
                          tag.a("list of modified files", href="../modifiedfiles/" + str(data["modifiedfiles"])),
                          ' related to this ticket.'
                          )
                    )
     return stream
Example #43
0
def require_secret(macro, environ, *secrets):
    """Macro for hiding text that can be shown by submitting a secret.

    You can provide several secrets as arguments. If ANY of the secret
    was submitted by the user, the content is shown.

    Requires the following keys in the environ:

    ``submitted_secrets``
       A set of secrets for this scenario which were submitted by the user.
    """
    show_content = any(x in environ['submitted_secrets'] for x in secrets)

    if show_content:
        return macro.parsed_body()
    else:
        dragons = tag.strong(_('Here be dragons.'))
        text = _('This content is hidden, '
                 'you need to submit a specific secret in order to show it.')
        return tag.div(tag.p(dragons, ' ', text), class_='require_secret')
Example #44
0
def require_secret(macro, environ, *secrets):
    """Macro for hiding text that can be shown by submitting a secret.

    You can provide several secrets as arguments. If ANY of the secret
    was submitted by the user, the content is shown.

    Requires the following keys in the environ:

    ``submitted_secrets``
       A set of secrets for this scenario which were submitted by the user.
    """
    show_content = any(x in environ['submitted_secrets'] for x in secrets)

    if show_content:
        return macro.parsed_body()
    else:
        dragons = tag.strong(_('Here be dragons.'))
        text = _('This content is hidden, '
                  'you need to submit a specific secret in order to show it.')
        return tag.div(tag.p(dragons, ' ', text), class_='require_secret')
Example #45
0
 def expand_macro(self, formatter, name, content, args=None):
     hint = '|| yyyy-mm-ddThh:mm:ss || yyyy-mm-ddThh:mm:ss || message'
     pattern = "\s*||(.*)||(.*)||(.*)".replace('|', '\|')
     pattern = re.compile(pattern)
     try:
         if content == None:
             return tag.div('ShowWhen Macro is not supported. Use WikiProcessor-style instead.', \
                            class_="system-message")
         now = datetime.now(utc)
         for line in content.split('\n'):
             matched = pattern.match(line)
             if matched:
                 result = matched.groups()
                 by, to, text = result
                 by, to = parse_date(by, None, hint), parse_date(to, None, hint)
                 self.env.log.debug('parsed time range: %s / %s' % (by, to))
                 if by <= now and now <= to:
                     return format_to_html(self.env, formatter.context, text)
         return None
     except Exception, e:
         return tag.div(tag.strong(e.title), ': ' + e.message, class_="system-message")
Example #46
0
    def process_request(self, req):
        if req.path_info == '/mindmap/status':
          db = self.env.get_db_cnx()
          cursor = db.cursor()
          try:
              cursor.execute('SELECT hash,content FROM mindmapcache')
              content = tag.html(tag.body(tag.dd(
                  [ [tag.dt(tag.a(k,href=req.href.mindmap(k + '.mm'))),tag.dd(tag.pre(v))] for k,v in cursor.fetchall()]
                )))
          except Exception, e:
              content = tag.html(tag.body(tag.strong("DB Error: " + unicode(e))))
          html = content.generate().render("xhtml")
          req.send_response(200)
          req.send_header('Cache-control', 'must-revalidate')
          req.send_header('Content-Type', 'text/html;charset=utf-8')
          req.send_header('Content-Length', len(html))
          req.end_headers()

          if req.method != 'HEAD':
             req.write(html)
          raise RequestDone
Example #47
0
 def _generate_attachmentflags_fieldset(self,
                                        readonly=True,
                                        current_flags=None,
                                        form=False):
     fields = Fragment()
     for flag in self.known_flags:
         flagid = 'flag_' + flag
         if current_flags and flag in current_flags:
             date = datetime.datetime.fromtimestamp(
                 current_flags[flag]["updated_on"], utc)
             text = tag.span(
                 tag.strong(flag), " set by ",
                 tag.em(current_flags[flag]["updated_by"]), ", ",
                 tag.span(pretty_timedelta(date),
                          title=format_datetime(date)), " ago")
             if readonly == True:
                 fields += tag.input(text, \
                                     type='checkbox', id=flagid, \
                                     name=flagid, checked="checked",
                                     disabled="true") + tag.br()
             else:
                 fields += tag.input(text, \
                                     type='checkbox', id=flagid, \
                                     name=flagid, checked="checked") + tag.br()
         else:
             if readonly == True:
                 fields += tag.input(flag, \
                                     type='checkbox', id=flagid, \
                                     name=flagid, disabled="true") + tag.br()
             else:
                 fields += tag.input(flag, \
                                     type='checkbox', id=flagid, \
                                     name=flagid) + tag.br()
     if form and not readonly:
         return tag.form(tag.fieldset(
             tag.legend("Attachment Flags") + fields,
             tag.input(type="hidden", name="action", value="update_flags"),
             tag.input(type="submit", value="Update flags")),
                         method="POST")
     return tag.fieldset(tag.legend("Attachment Flags") + fields)
Example #48
0
    def create_wiki_page(self, name=None, content=None, comment=None):
        """Creates a wiki page, with a random unique CamelCase name if none
        is provided, random content if none is provided and a random comment
        if none is provided.  Returns the name of the wiki page.
        """
        if name is None:
            name = random_unique_camel()
        if content is None:
            content = random_page()
        self.go_to_wiki(name)
        tc.find("The page %s does not exist." % tag.strong(name))

        self.edit_wiki_page(name, content, comment)

        # verify the event shows up in the timeline
        self.go_to_timeline()
        tc.formvalue('prefs', 'wiki', True)
        tc.submit()
        tc.find(name + ".*created")

        self.go_to_wiki(name)

        return name
Example #49
0
    def create_wiki_page(self, name=None, content=None, comment=None):
        """Creates a wiki page, with a random unique CamelCase name if none
        is provided, random content if none is provided and a random comment
        if none is provided.  Returns the name of the wiki page.
        """
        if name is None:
            name = random_unique_camel()
        if content is None:
            content = random_page()
        self.go_to_wiki(name)
        tc.find("The page %s does not exist." % tag.strong(name))

        self.edit_wiki_page(name, content, comment)

        # verify the event shows up in the timeline
        self.go_to_timeline()
        tc.formvalue('prefs', 'wiki', True)
        tc.submit()
        tc.find(name + ".*created")

        self.go_to_wiki(name)

        return name
Example #50
0
    def _validate(self, req, page):
        valid = True

        # Validate page size
        if len(req.args.get('text', '')) > self.max_size:
            add_warning(req, _("The wiki page is too long (must be less "
                               "than %(num)s characters)",
                               num=self.max_size))
            valid = False

        # Give the manipulators a pass at post-processing the page
        for manipulator in self.page_manipulators:
            for field, message in manipulator.validate_wiki_page(req, page):
                valid = False
                if field:
                    add_warning(req, tag_("The Wiki page field %(field)s"
                                          " is invalid: %(message)s",
                                          field=tag.strong(field),
                                          message=message))
                else:
                    add_warning(req, tag_("Invalid Wiki page: %(message)s",
                                          message=message))
        return valid
Example #51
0
    def _post_process_request_history(self, req, data):
        history = []
        page_histories = data.get('history', [])
        resource = data['resource']
        tags_histories = tag_changes(self.env, resource)

        for page_history in page_histories:
            while tags_histories and \
                    tags_histories[0][0] >= page_history['date']:
                tags_history = tags_histories.pop(0)
                date = tags_history[0]
                author = tags_history[1]
                old_tags = split_into_tags(tags_history[2] or '')
                new_tags = split_into_tags(tags_history[3] or '')
                added = sorted(new_tags - old_tags)
                added = added and \
                        tagn_("%(tags)s added", "%(tags)s added",
                              len(added), tags=tag.em(', '.join(added)))
                removed = sorted(old_tags - new_tags)
                removed = removed and \
                          tagn_("%(tags)s removed", "%(tags)s removed",
                                len(removed), tags=tag.em(', '.join(removed)))
                # TRANSLATOR: How to delimit added and removed tags.
                delim = added and removed and _("; ")
                comment = tag(tag.strong(_("Tags")), ' ', added, delim,
                              removed)
                url = req.href(resource.realm, resource.id,
                               version=page_history['version'],
                               tags_version=to_utimestamp(date))
                history.append({'version': '*', 'url': url, 'date': date,
                                'author': author, 'comment': comment,
                                'ipnr': ''})
            history.append(page_history)

        data.update(dict(history=history,
                         wiki_to_oneliner=self._wiki_to_oneliner))
Example #52
0
    def _do_save(self, req, attachment):
        req.perm(attachment.resource).require('ATTACHMENT_CREATE')
        parent_resource = attachment.resource.parent

        if 'cancel' in req.args:
            req.redirect(get_resource_url(self.env, parent_resource, req.href))

        upload = req.args.getfirst('attachment')
        if not hasattr(upload, 'filename') or not upload.filename:
            raise TracError(_("No file uploaded"))
        if hasattr(upload.file, 'fileno'):
            size = os.fstat(upload.file.fileno())[6]
        else:
            upload.file.seek(0, 2)  # seek to end of file
            size = upload.file.tell()
            upload.file.seek(0)
        if size == 0:
            raise TracError(_("Can't upload empty file"))

        # Maximum attachment size (in bytes)
        max_size = self.max_size
        if 0 <= max_size < size:
            raise TracError(
                _("Maximum attachment size: %(num)s",
                  num=pretty_size(max_size)), _("Upload failed"))

        filename = _normalized_filename(upload.filename)
        if not filename:
            raise TracError(_("No file uploaded"))
        # Now the filename is known, update the attachment resource
        attachment.filename = filename
        attachment.description = req.args.get('description', '')
        attachment.author = get_reporter_id(req, 'author')
        attachment.ipnr = req.remote_addr

        # Validate attachment
        valid = True
        for manipulator in self.manipulators:
            for field, message in manipulator.validate_attachment(
                    req, attachment):
                valid = False
                if field:
                    add_warning(
                        req,
                        tag_(
                            "Attachment field %(field)s is invalid: "
                            "%(message)s",
                            field=tag.strong(field),
                            message=message))
                else:
                    add_warning(
                        req,
                        tag_("Invalid attachment: %(message)s",
                             message=message))
        if not valid:
            # Display the attach form with pre-existing data
            # NOTE: Local file path not known, file field cannot be repopulated
            add_warning(req, _('Note: File must be selected again.'))
            data = self._render_form(req, attachment)
            data['is_replace'] = req.args.get('replace')
            return data

        if req.args.get('replace'):
            try:
                old_attachment = Attachment(self.env,
                                            attachment.resource(id=filename))
                if not (req.authname and req.authname != 'anonymous'
                        and old_attachment.author == req.authname) \
                   and 'ATTACHMENT_DELETE' \
                                        not in req.perm(attachment.resource):
                    raise PermissionError(msg=_(
                        "You don't have permission to "
                        "replace the attachment %(name)s. You can only "
                        "replace your own attachments. Replacing other's "
                        "attachments requires ATTACHMENT_DELETE permission.",
                        name=filename))
                if (not attachment.description.strip()
                        and old_attachment.description):
                    attachment.description = old_attachment.description
                old_attachment.delete()
            except TracError:
                pass  # don't worry if there's nothing to replace
        attachment.insert(filename, upload.file, size)

        req.redirect(
            get_resource_url(self.env, attachment.resource(id=None), req.href))
Example #53
0
 def expand_macro(self, formatter, name, content, args=None):
     t = datetime.now(utc)
     return tag.strong(format_datetime(t, '%c'))
Example #54
0
def enter_secret(macro, environ, *secrets):
    """Macro for entering a secret. Takes a several secrets as args.

    Requires the following keys in the environ:
    
    ``user``
       An instance of :class:`django.contrib.auth.models.User`. Will be used
       to generate a security token of a secret that is only valid for this
       user.

    ``enter_secret_target``
       An url for the action attribute of the form element. Submitting the
       form will generate a POST request with the following data:

       ``secret``
          The secret which was entered by the user

       ``secret_token``
          Occurs several times, one time for each secret that is valid for
          this form. It is a security token that is build by generating
          a HMAC with ``settings.SECRET_KEY`` as key. The message is the
          user id and the valid secret divided by a colon.

    ``all_secrets``
       A list of strings containing all available secrets for this scenario.
    
    ``submitted_secrets``
       A list of strings containing all secrets submitted by the user for
       this scenario.

    ``secret_token_function``
       A function that calculates the secret's security token. Takes an user
       and a secret.

    ``csrf_token``
       Django's CSRF token. Use :func:`django.middleware.csrf.get_token` to
       get it.
    """
    target = environ['enter_secret_target']
    user = environ['user']
    
    # If all secrets are already submitted, change css class
    solved = all(secret in environ['submitted_secrets'] for secret in secrets)
    css_class = 'enter_secret secret_solved' if solved else 'enter_secret'
    secret_div = tag.div(macro.parsed_body(), class_=css_class)
    
    if not solved:
        # If there are no secrets in the arguments, we will accept all secrets
        if not secrets:
            secrets = environ['all_secrets']
        
        form = tag.form(method='post', action=target)
        
        for secret in secrets:
            secret_token = environ['secret_token_function'](user, secret)
            form.append(tag.input(name='secret_token', value=secret_token,
                                  type='hidden'))
    
        form.append(tag.input(type='hidden', name='csrfmiddlewaretoken',
                              value=environ['csrf_token']))

        p = tag.p(tag.strong(_('Enter secret:')), ' ')
        p.append(tag.input(name='secret', type='text'))
        p.append(tag.input(type='submit', name='enter_secret', value=_('Submit')))
        form.append(p)
        secret_div.append(form)

    form_submitted_secrets = [secret for secret in secrets
                         if secret in environ['submitted_secrets']]
    if form_submitted_secrets:
        submitted_div = tag.div(tag.p(_('Already submitted secrets:')),
                                _class='submitted_secrets')
        secret_list = tag.ul()
        for secret in form_submitted_secrets:
            secret_list.append(tag.li(secret))
        submitted_div.append(secret_list)
        secret_div.append(submitted_div)

    return secret_div
Example #55
0
    def runTest(self):
        """Test for simple wiki rename"""
        pagename = self._tester.create_wiki_page()
        attachment = self._tester.attach_file_to_wiki(pagename)
        base_url = self._tester.url
        page_url = base_url + "/wiki/" + pagename

        def click_rename():
            tc.formvalue('rename', 'action', 'rename')
            tc.submit()
            tc.url(page_url + r'\?action=rename')
            tc.find("New name:")

        tc.go(page_url)
        tc.find("Rename page")
        click_rename()
        # attempt to give an empty new name
        tc.formvalue('rename-form', 'new_name', '')
        tc.submit('submit')
        tc.url(page_url)
        tc.find("A new name is mandatory for a rename")
        # attempt to rename the page to an invalid page name
        tc.formvalue('rename-form', 'new_name', '../WikiStart')
        tc.submit('submit')
        tc.url(page_url)
        tc.find("The new name is invalid")
        # attempt to rename the page to the current page name
        tc.formvalue('rename-form', 'new_name', pagename)
        tc.submit('submit')
        tc.url(page_url)
        tc.find("The new name must be different from the old name")
        # attempt to rename the page to an existing page name
        tc.formvalue('rename-form', 'new_name', 'WikiStart')
        tc.submit('submit')
        tc.url(page_url)
        tc.find("The page WikiStart already exists")
        # correct rename to new page name (old page replaced by a redirection)
        tc.go(page_url)
        click_rename()
        newpagename = pagename + 'Renamed'
        tc.formvalue('rename-form', 'new_name', newpagename)
        tc.formvalue('rename-form', 'redirect', True)
        tc.submit('submit')
        # check redirection page
        tc.url(page_url)
        tc.find("See.*/wiki/" + newpagename)
        tc.find("The page %s has been renamed to %s." %
                (pagename, newpagename))
        tc.find("The page %s has been recreated with a redirect to %s." %
                (pagename, newpagename))
        # check whether attachment exists on the new page but not on old page
        tc.go(base_url + '/attachment/wiki/' + newpagename + '/' + attachment)
        tc.notfind("Error: Invalid Attachment")
        tc.go(base_url + '/attachment/wiki/' + pagename + '/' + attachment)
        tc.find("Error: Invalid Attachment")
        # rename again to another new page name (this time, no redirection)
        tc.go(page_url)
        click_rename()
        newpagename = pagename + 'RenamedAgain'
        tc.formvalue('rename-form', 'new_name', newpagename)
        tc.formvalue('rename-form', 'redirect', False)
        tc.submit('submit')
        tc.url(base_url + "/wiki/" + newpagename)
        tc.find("The page %s has been renamed to %s." %
                (pagename, newpagename))
        # this time, the original page is gone
        tc.go(page_url)
        tc.url(page_url)
        tc.find("The page %s does not exist" % tag.strong(pagename))