Beispiel #1
0
    def test_url_for_item(self):
        before_wiki()
        revid = 'cdc431e0fc624d6fb8372152dcb66457'

        tests = [
            (('SomePage', '', '', '', CURRENT, 'frontend.show_item', False),
             '/SomePage'),
            # Method signature to understand the tuple parameters
            # (item_name, wiki_name='', namespace='', rev=CURRENT, endpoint='frontend.show_item', _external=False):
            (('SomePage', '', '', '', CURRENT, 'frontend.show_item', True),
             'http://*****:*****@itemid/SomeItemID'),
            (('SomePage', 'non-existent', '', 'ns1', CURRENT,
              'frontend.show_item', False), '/non-existent/ns1/SomePage'),
        ]

        for (item_name, wiki_name, field, namespace, rev, endpoint,
             _external), url in tests:
            assert url_for_item(item_name, wiki_name, field, namespace, rev,
                                endpoint, _external) == url
Beispiel #2
0
def get_editor_info(meta, external=False):
    """
    Create a dict of formatted user info.

    :rtype: dict
    :returns: dict of formatted user info such as name, ip addr, email,...
    """
    addr = meta.get(ADDRESS)
    hostname = meta.get(HOSTNAME)
    text = _('anonymous')  # link text
    title = ''  # link title
    css = 'editor'  # link/span css class
    name = None  # author name
    uri = None  # author homepage uri
    email = None  # pure email address of author
    if app.cfg.show_hosts and addr:
        # only tell ip / hostname if show_hosts is True
        if hostname:
            text = hostname[:15]  # 15 = len(ipaddr)
            name = title = u'{0}[{1}]'.format(hostname, addr)
            css = 'editor host'
        else:
            name = text = addr
            title = u'[{0}]'.format(addr)
            css = 'editor ip'

    userid = meta.get(USERID)
    if userid:
        u = user.User(userid)
        name = u.name0
        text = name
        display_name = u.display_name or name
        if title:
            # we already have some address info
            title = u"{0} @ {1}".format(display_name, title)
        else:
            title = display_name
        if u.mailto_author and u.email:
            email = u.email
            css = 'editor mail'
        else:
            homewiki = app.cfg.user_homewiki
            if is_local_wiki(homewiki):
                css = 'editor homepage local'
            else:
                css = 'editor homepage interwiki'
            uri = url_for_item(name,
                               wiki_name=homewiki,
                               _external=external,
                               namespace=NAMESPACE_USERS)

    result = dict(name=name, text=text, css=css, title=title)
    if uri:
        result['uri'] = uri
    if email:
        result['email'] = email
    return result
Beispiel #3
0
    def split_navilink(self, text):
        """
        Split navibar links into pagename, link to page

        Admin or user might want to use shorter navibar items by using
        the [[page|title]] or [[url|title]] syntax.

        Supported syntax:
            * PageName
            * WikiName:PageName
            * wiki:WikiName:PageName
            * url
            * all targets as seen above with title: [[target|title]]

        :param text: the text used in config or user preferences
        :rtype: tuple
        :returns: pagename or url, link to page or url
        """
        title = None
        wiki_local = ''  # means local wiki

        # Handle [[pagename|title]] or [[url|title]] formats
        if text.startswith('[[') and text.endswith(']]'):
            text = text[2:-2]
            try:
                target, title = text.split('|', 1)
                target = target.strip()
                title = title.strip()
            except (ValueError, TypeError):
                # Just use the text as is.
                target = text.strip()
        else:
            target = text

        if wikiutil.is_URL(target):
            if not title:
                title = target
            return target, title, wiki_local

        # remove wiki: url prefix
        if target.startswith("wiki:"):
            target = target[5:]

        wiki_name, namespace, field, item_name = split_interwiki(target)
        if wiki_name == 'Self':
            wiki_name = ''
        href = url_for_item(item_name,
                            namespace=namespace,
                            wiki_name=wiki_name,
                            field=field)
        if not title:
            title = shorten_fqname(CompositeName(namespace, field, item_name))
        return href, title, wiki_name
Beispiel #4
0
 def handle_wiki_links(self, elem, input):
     wiki_name = 'Self'
     if input.authority and input.authority.host:
         wn = unicode(input.authority.host)
         if is_known_wiki(wn):
             # interwiki link
             elem.set(moin_page.class_, 'moin-interwiki')
             wiki_name = wn
     item_name = unicode(input.path[1:])
     endpoint, rev, query = self._get_do_rev(input.query)
     url = url_for_item(item_name, wiki_name=wiki_name, rev=rev, endpoint=endpoint)
     link = Iri(url, query=query, fragment=input.fragment)
     elem.set(self._tag_xlink_href, link)
Beispiel #5
0
 def handle_wikilocal_links(self, elem, input, page):
     if input.path:
         # this can be a relative path, make it absolute:
         path = input.path
         if page:
             path = self.absolute_path(path, page.path)
         item_name = unicode(path)
         if not flaskg.storage.has_item(item_name):
             # XXX these index accesses slow down the link converter quite a bit
             elem.set(moin_page.class_, 'moin-nonexistent')
     else:
         item_name = unicode(page.path[1:])
     endpoint, rev, query = self._get_do_rev(input.query)
     url = url_for_item(item_name, rev=rev, endpoint=endpoint)
     if not page:
         url = url[1:]
     link = Iri(url, query=query, fragment=input.fragment)
     elem.set(self._tag_xlink_href, link)
Beispiel #6
0
    def userhome(self):
        """
        Assemble arguments used to build user homepage link

        :rtype: tuple
        :returns: arguments of user homepage link in tuple (wiki_href, display_name, title, exists)
        """
        user = self.user
        name = user.name0
        display_name = user.display_name or name
        wikiname, itemname = getInterwikiHome(name)
        title = u"{0} @ {1}".format(display_name, wikiname)
        # link to (interwiki) user homepage
        if is_local_wiki(wikiname):
            exists = self.storage.has_item(itemname)
        else:
            # We cannot check if wiki pages exists in remote wikis
            exists = True
        wiki_href = url_for_item(itemname,
                                 wiki_name=wikiname,
                                 namespace=NAMESPACE_USERS)
        return wiki_href, display_name, title, exists
Beispiel #7
0
    def __init__(self, app, fqname, revs, **kwargs):
        self.app = app
        self.fqname = fqname
        self.revs = revs
        self.action = kwargs.get('action', None)
        self.content = kwargs.get('content', None)
        self.meta = kwargs.get('meta', None)
        self.comment = kwargs.get('comment', None)
        self.wiki_name = self.app.cfg.interwikiname

        if self.action == ACTION_SAVE:
            self.action = ACTION_CREATE if len(
                self.revs) == 1 else ACTION_MODIFY

        if self.action == ACTION_TRASH:
            self.meta = self.revs[0].meta

        kw = dict(fqname=unicode(fqname),
                  wiki_name=self.wiki_name,
                  user_name=flaskg.user.name0,
                  item_url=url_for_item(self.fqname))
        self.notification_sentence = L_(MESSAGES[self.action], **kw)
Beispiel #8
0
    def path_breadcrumbs(self):
        """
        Assemble the path breadcrumbs (a.k.a.: trail)

        :rtype: list
        :returns: path breadcrumbs items in tuple (wiki_name, item_name, url, exists, err)
        """
        user = self.user
        breadcrumbs = []
        trail = user.get_trail()
        for interwiki_item_name in trail:
            wiki_name, namespace, field, item_name = split_interwiki(
                interwiki_item_name)
            fqname = CompositeName(namespace, field, item_name)
            err = not is_known_wiki(wiki_name)
            href = url_for_item(wiki_name=wiki_name, **fqname.split)
            if is_local_wiki(wiki_name):
                exists = bool(self.storage.get_item(**fqname.query))
                wiki_name = ''  # means "this wiki" for the theme code
            else:
                exists = True  # we can't detect existance of remote items
            if item_name:
                breadcrumbs.append((wiki_name, fqname, href, exists, err))
        return breadcrumbs
Beispiel #9
0
def atom(item_name):
    # Currently atom feeds behave in the fol. way
    # - Text diffs are shown in a side-by-side fashion
    # - The current binary item is fully rendered in the feed
    # - Image(binary)'s diff is shown using PIL
    # - First item is always rendered fully
    # - Revision meta(id, size and comment) is shown for parent and current revision
    query = Term(WIKINAME, app.cfg.interwikiname)
    if item_name:
        query = And([
            query,
            Term(NAME_EXACT, item_name),
        ])
    revs = list(
        flaskg.storage.search(query,
                              idx_name=LATEST_REVS,
                              sortedby=[MTIME],
                              reverse=True,
                              limit=1))
    if revs:
        rev = revs[0]
        cid = cache_key(usage="atom", revid=rev.revid, item_name=item_name)
        content = app.cache.get(cid)
    else:
        content = None
        cid = None
    if content is None:
        if not item_name:
            title = u"{0}".format(app.cfg.sitename)
        else:
            title = u"{0} - {1}".format(app.cfg.sitename, item_name)
        feed = AtomFeed(title=title,
                        feed_url=request.url,
                        url=request.host_url)
        query = Term(WIKINAME, app.cfg.interwikiname)
        if item_name:
            query = And([
                query,
                Term(NAME_EXACT, item_name),
            ])
        history = flaskg.storage.search(query,
                                        idx_name=ALL_REVS,
                                        sortedby=[MTIME],
                                        reverse=True,
                                        limit=100)
        for rev in history:
            name = rev.name
            item = rev.item
            this_revid = rev.meta[REVID]
            previous_revid = rev.meta.get(PARENTID)
            this_rev = rev
            try:
                hl_item = Item.create(name, rev_id=this_revid)
                if previous_revid is not None:
                    # HTML diff for subsequent revisions
                    previous_rev = item[previous_revid]
                    content = hl_item.content._render_data_diff_atom(
                        previous_rev, this_rev)
                else:
                    # full html rendering for new items
                    content = render_template(
                        'atom.html',
                        get='first_revision',
                        rev=this_rev,
                        content=Markup(hl_item.content._render_data()),
                        revision=this_revid)
                content_type = 'html'
            except Exception as e:
                logging.exception("content rendering crashed")
                content = _(u'MoinMoin feels unhappy.')
                content_type = 'text'
            author = get_editor_info(rev.meta, external=True)
            rev_comment = rev.meta.get(COMMENT, '')
            if rev_comment:
                # Trim down extremely long revision comment
                if len(rev_comment) > 80:
                    content = render_template('atom.html',
                                              get='comment_cont_merge',
                                              comment=rev_comment[79:],
                                              content=Markup(content))
                    rev_comment = u"{0}...".format(rev_comment[:79])
                feed_title = u"{0} - {1}".format(author.get(NAME, ''),
                                                 rev_comment)
            else:
                feed_title = u"{0}".format(author.get(NAME, ''))
            if not item_name:
                feed_title = u"{0} - {1}".format(name, feed_title)
            feed.add(
                title=feed_title,
                title_type='text',
                summary=content,
                summary_type=content_type,
                author=author,
                url=url_for_item(name, rev=this_revid, _external=True),
                updated=datetime.fromtimestamp(rev.meta[MTIME]),
            )
        content = feed.to_string()
        # Hack to add XSLT stylesheet declaration since AtomFeed doesn't allow this
        content = content.split("\n")
        content.insert(1, render_template('atom.html', get='xml'))
        content = "\n".join(content)
        if cid is not None:
            app.cache.set(cid, content)
    return Response(content, content_type='application/atom+xml')
Beispiel #10
0
 def do_modify(self):
     if isinstance(self.content, NonExistentContent) and not flaskg.user.may.create(self.name):
         abort(403, description=' ' + _('You do not have permission to create the item named "{name}".'.format(name=self.name)))
     method = request.method
     if method in ['GET', 'HEAD']:
         if isinstance(self.content, NonExistentContent):
             return render_template('modify_select_contenttype.html',
                                    fqname=self.fqname,
                                    item_name=self.name,
                                    itemtype=self.itemtype,
                                    group_names=content_registry.group_names,
                                    groups=content_registry.groups,
                                   )
         item = self
         if isinstance(self.rev, DummyRev):
             template_name = request.values.get(TEMPLATE)
             if template_name is None:
                 return self._do_modify_show_templates()
             elif template_name:
                 item = Item.create(template_name)
                 form = self.ModifyForm.from_item(item)
                 # replace template name with new item name and remove TEMPLATE tag
                 form['meta_form']['name'] = self.names[0]
                 form['meta_form']['tags'].remove(TEMPLATE)
             else:
                 # template_name == u'' when user chooses "create item from scratch"
                 form = self.ModifyForm.from_item(item)
         else:
             form = self.ModifyForm.from_item(item)
     elif method == 'POST':
         # XXX workaround for *Draw items
         if isinstance(self.content, Draw):
             try:
                 self.content.handle_post()
             except AccessDenied:
                 abort(403)
             else:
                 # *Draw Applets POSTs more than once, redirecting would
                 # break them
                 return "OK"
         form = self.ModifyForm.from_request(request)
         meta, data, contenttype_guessed, comment = form._dump(self)
         if contenttype_guessed:
             m = re.search('charset=(.+?)($|;)', contenttype_guessed)
             if m:
                 data = unicode(data, m.group(1))
         state = dict(fqname=self.fqname, itemid=meta.get(ITEMID), meta=meta)
         if form.validate(state):
             contenttype_qs = request.values.get('contenttype')
             try:
                 self.modify(meta, data, comment, contenttype_guessed, **{CONTENTTYPE: contenttype_qs})
             except AccessDenied:
                 abort(403)
             else:
                 if isinstance(self.rev.data, file):
                     self.rev.data.close()
                 return redirect(url_for_item(**self.fqname.split))
     help = CONTENTTYPES_HELP_DOCS[self.contenttype]
     if isinstance(help, tuple):
         help = self.doc_link(*help)
     if flaskg.user.valid and EDIT_ROWS in flaskg.user.profile._meta:
         edit_rows = str(flaskg.user.profile._meta[EDIT_ROWS])
     else:
         edit_rows = str(flaskg.user.profile._defaults[EDIT_ROWS])
     if isinstance(self.rev.data, file):
         self.rev.data.close()
     return render_template('modify.html',
                            fqname=self.fqname,
                            item_name=self.name,
                            item=self,
                            rows_meta=str(ROWS_META),
                            cols=str(COLS),
                            form=form,
                            search_form=None,
                            help=help,
                            edit_rows=edit_rows,
                           )