Exemplo n.º 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
Exemplo n.º 2
0
 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(),
     )
Exemplo n.º 3
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
Exemplo n.º 4
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
Exemplo n.º 5
0
 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(),
                           )
Exemplo n.º 6
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
Exemplo n.º 7
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)
Exemplo n.º 8
0
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
Exemplo n.º 9
0
 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)
Exemplo n.º 10
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
Exemplo n.º 11
0
 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)
Exemplo n.º 12
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_USERPROFILES)
        return wiki_href, display_name, title, exists
Exemplo n.º 13
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_USERPROFILES)
        return wiki_href, display_name, title, exists
Exemplo n.º 14
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, 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
Exemplo n.º 15
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)
Exemplo n.º 16
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
Exemplo n.º 17
0
    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
Exemplo n.º 18
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
Exemplo n.º 19
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)
Exemplo n.º 20
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')
Exemplo n.º 21
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,
     )