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
def do_modify(self): 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) 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) 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: return redirect(url_for_item(**self.fqname.split)) help = CONTENTTYPES_HELP_DOCS[self.contenttype] if isinstance(help, tuple): help = self.doc_link(*help) return render_template( self.modify_template, fqname=self.fqname, item_name=self.name, item=self, rows_meta=str(ROWS_META), cols=str(COLS), form=form, search_form=None, help=help, meta=item._meta_info(), )
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
def do_modify(self): 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) 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) 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: return redirect(url_for_item(**self.fqname.split)) help = CONTENTTYPES_HELP_DOCS[self.contenttype] if isinstance(help, tuple): help = self.doc_link(*help) return render_template(self.modify_template, fqname=self.fqname, item_name=self.name, item=self, rows_meta=str(ROWS_META), cols=str(COLS), form=form, search_form=None, help=help, meta=item._meta_info(), )
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
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)
def get_editor_info(meta, external=False): 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 = '{0}[{1}]'.format(hostname, addr) css = 'editor host' else: name = text = addr title = '[{0}]'.format(addr) css = 'editor ip' userid = meta.get(USERID) if userid: u = user.User(userid) name = u.name text = name aliasname = u.aliasname if not aliasname: aliasname = name if title: # we already have some address info title = "{0} @ {1}".format(aliasname, title) else: title = aliasname 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) result = dict(name=name, text=text, css=css, title=title) if uri: result['uri'] = uri if email: result['email'] = email return result
def handle_wikilocal_links(self, elem, input, page): if input.path: # this can be a relative path, make it absolute: path = input.path path = self.absolute_path(path, page.path) item_name = unicode(path) if not flaskg.storage.has_item(item_name): 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) link = Iri(url, query=query, fragment=input.fragment) elem.set(self._tag_xlink_href, link)
def handle_wikilocal_links(self, elem, input, page): if input.path: # this can be a relative path, make it absolute: path = input.path 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) link = Iri(url, query=query, fragment=input.fragment) elem.set(self._tag_xlink_href, link)
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_USERPROFILES) return wiki_href, display_name, title, exists
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, item_name = split_interwiki(interwiki_item_name) err = not is_known_wiki(wiki_name) href = url_for_item(item_name, wiki_name=wiki_name) if is_local_wiki(wiki_name): exists = self.storage.has_item(item_name) wiki_name = '' # means "this wiki" for the theme code else: exists = True # we can't detect existance of remote items breadcrumbs.append((wiki_name, item_name, href, exists, err)) return breadcrumbs
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)
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
def userhome(self): """ Assemble arguments used to build user homepage link :rtype: tuple :returns: arguments of user homepage link in tuple (wiki_href, aliasname, title, exists) """ user = self.user name = user.name aliasname = user.aliasname if not aliasname: aliasname = name wikiname, itemname = getInterwikiHome(name) title = "{0} @ {1}".format(aliasname, 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) return wiki_href, aliasname, title, exists
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
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)
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')
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, )