def _update(self, portal):
        t = '%(info)s folder: <a href="%(url)s/manage_main">%(text)s</a>'
        pt_start = '<metal:block metal:define-macro="page" metal:extend-macro="here/standard_template_macro">'
        old_meta_slot = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" ?/>'
        meta_slot_start = '<metal:block fill-slot="meta">'
        meta_slot = '''
<metal:block fill-slot="meta">
    <meta tal:define="description here/description;
                      content python:here.html2text(description);"
          tal:condition="content"
          tal:attributes="content content" name="description" />
    <meta tal:condition="here/keywords"
          tal:attributes="content here/keywords" name="keywords" />
    <meta tal:attributes="content here/contributor" name="author" />
    <meta tal:attributes="content here/gl_get_selected_language"
          name="dc.language" />
    <meta tal:attributes="content string:${here/title} | ${here/site_title}"
          name="title" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</metal:block>
'''

        self.log.debug(physical_path(portal))
        for folder in list_folders_with_custom_index(portal):
            tal = folder.index.read()
            if re.search(meta_slot_start, tal) is not None:
                self.log.info(
                    t % {
                        'info': 'already has meta slot',
                        'url': folder.absolute_url(),
                        'text': physical_path(folder)
                    })
                continue

            if re.search('^' + pt_start, tal) is None and re.search(
                    old_meta_slot, tal) is None:
                self.log.info(
                    t % {
                        'info':
                        'not using standard template macro and no old meta slot',
                        'url': folder.absolute_url(),
                        'text': physical_path(folder)
                    })
                continue

            self.log.info(
                t % {
                    'info': 'matched',
                    'url': folder.absolute_url(),
                    'text': physical_path(folder)
                })

            if re.search(old_meta_slot, tal) is not None:
                # replace only first occurance, remove the others
                tal = re.sub(old_meta_slot, meta_slot, tal, count=1)
                tal = re.sub(old_meta_slot, '', tal)
            elif re.search('^' + pt_start, tal) is not None:
                tal = re.sub(pt_start, '%s\n%s' % (pt_start, meta_slot), tal)
            folder.index.write(tal)
        return True
    def _update(self, portal):
        start = '<span tal:replace="structure here/standard_html_header" ?/>'
        end = '<span tal:replace="structure here/standard_html_footer" ?/>'

        replace_start = '<metal:block metal:define-macro="page" metal:extend-macro="here/standard_template_macro">\n\n<metal:block metal:fill-slot="body">'
        replace_end = "</metal:block>\n\n</metal:block>"

        self.log.debug(physical_path(portal))
        for folder in list_folders_with_custom_index(portal):
            folder.index.expand = 0

            tal = folder.index.read()
            tal = tal.strip()

            if re.search("^" + start, tal) is None:
                assert re.search(end + "$", tal) is None
                continue
            assert re.search(end + "$", tal) is not None

            t = 'matched folder: <a href="%(url)s/manage_main">%(text)s</a>'
            self.log.info(t % {"url": folder.absolute_url(), "text": physical_path(folder)})

            tal = re.sub(start, replace_start, tal)
            tal = re.sub(end, replace_end, tal)

            folder.index.write(tal)
        return True
    def _update(self, portal):
        self.log.debug(physical_path(portal))

        t = 'folder index: <a href="%(url)s/manage_main">%(text)s</a>'
        for folder in list_folders_with_custom_index(portal):
            self.log.info(t % {'url': folder.absolute_url(),
                               'text': physical_path(folder)})

        return True
    def _update(self, portal):
        t = '%(info)s folder: <a href="%(url)s/manage_main">%(text)s</a>'

        old_macro_start = '<metal:block use-macro="here/folder_listing/macros/content">'
        new_macro_start = '<metal:block use-macro="python:here.getFormsTool().getForm(\'folder_listing\').macros[\'listing\']">'

        self.log.debug(physical_path(portal))
        for folder in list_folders_with_custom_index(portal):
            tal = folder.index.read()
            if tal.find(new_macro_start) != -1:
                self.log.info(
                    t % {
                        'info': 'already uses new folder listing macro',
                        'url': folder.absolute_url(),
                        'text': physical_path(folder)
                    })
                continue

            if tal.find(old_macro_start) == -1:
                self.log.info(
                    t % {
                        'info': 'not using folder listing macro',
                        'url': folder.absolute_url(),
                        'text': physical_path(folder)
                    })
                continue

            self.log.info(
                t % {
                    'info': 'replacing folder listing macro',
                    'url': folder.absolute_url(),
                    'text': physical_path(folder)
                })

            tal = tal.replace(old_macro_start, new_macro_start)
            folder.index.write(tal)

        custom_folder_index = portal.portal_forms._getOb('folder_index',
                                                         default=None)
        if custom_folder_index is None:
            return True

        tal = custom_folder_index.read()
        if tal.find(new_macro_start) != -1:
            self.log.info('folder index already uses new folder listing macro')
            return True

        if tal.find(old_macro_start) == -1:
            self.log.info('folder index not using folder listing macro')
            return True

        self.log.info('folder index replacing folder listing macro')
        tal = tal.replace(old_macro_start, new_macro_start)
        custom_folder_index.write(tal)
        return True
    def _update(self, portal):
        self.log.debug(physical_path(portal))

        t = 'folder index: <a href="%(url)s/manage_main">%(text)s</a>'
        for folder in list_folders_with_custom_index(portal):
            self.log.info(t % {
                'url': folder.absolute_url(),
                'text': physical_path(folder)
            })

        return True
    def _update(self, portal):
        t = '%(info)s folder: <a href="%(url)s/manage_main">%(text)s</a>'
        pt_start = '<metal:block metal:define-macro="page" metal:extend-macro="here/standard_template_macro">'
        old_meta_slot = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" ?/>'
        meta_slot_start = '<metal:block fill-slot="meta">'
        meta_slot = '''
<metal:block fill-slot="meta">
    <meta tal:define="description here/description;
                      content python:here.html2text(description);"
          tal:condition="content"
          tal:attributes="content content" name="description" />
    <meta tal:condition="here/keywords"
          tal:attributes="content here/keywords" name="keywords" />
    <meta tal:attributes="content here/contributor" name="author" />
    <meta tal:attributes="content here/gl_get_selected_language"
          name="dc.language" />
    <meta tal:attributes="content string:${here/title} | ${here/site_title}"
          name="title" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</metal:block>
'''

        self.log.debug(physical_path(portal))
        for folder in list_folders_with_custom_index(portal):
            tal = folder.index.read()
            if re.search(meta_slot_start, tal) is not None:
                self.log.info(t % {'info': 'already has meta slot',
                                   'url': folder.absolute_url(),
                                   'text': physical_path(folder)})
                continue

            if re.search('^' + pt_start, tal) is None and re.search(old_meta_slot, tal) is None:
                self.log.info(t % {'info': 'not using standard template macro and no old meta slot',
                                    'url': folder.absolute_url(),
                                    'text': physical_path(folder)})
                continue

            self.log.info(t % {'info': 'matched',
                               'url': folder.absolute_url(),
                               'text': physical_path(folder)})

            if re.search(old_meta_slot, tal) is not None:
                # replace only first occurance, remove the others
                tal = re.sub(old_meta_slot, meta_slot, tal, count=1)
                tal = re.sub(old_meta_slot, '', tal)
            elif re.search('^' + pt_start, tal) is not None:
                tal = re.sub(pt_start, '%s\n%s' % (pt_start, meta_slot), tal)
            folder.index.write(tal)
        return True
    def _update(self, portal):
        t = '%(info)s folder: <a href="%(url)s/manage_main">%(text)s</a>'

        old_macro_start = '<metal:block use-macro="here/folder_listing/macros/content">'
        new_macro_start = '<metal:block use-macro="python:here.getFormsTool().getForm(\'folder_listing\').macros[\'listing\']">'

        self.log.debug(physical_path(portal))
        for folder in list_folders_with_custom_index(portal):
            tal = folder.index.read()
            if tal.find(new_macro_start) != -1:
                self.log.info(t % {'info': 'already uses new folder listing macro',
                                   'url': folder.absolute_url(),
                                   'text': physical_path(folder)})
                continue

            if tal.find(old_macro_start) == -1:
                self.log.info(t % {'info': 'not using folder listing macro',
                                   'url': folder.absolute_url(),
                                   'text': physical_path(folder)})
                continue

            self.log.info(t % {'info': 'replacing folder listing macro',
                               'url': folder.absolute_url(),
                               'text': physical_path(folder)})

            tal = tal.replace(old_macro_start, new_macro_start)
            folder.index.write(tal)

        custom_folder_index = portal.portal_forms._getOb('folder_index', default=None)
        if custom_folder_index is None:
            return True

        tal = custom_folder_index.read()
        if tal.find(new_macro_start) != -1:
            self.log.info('folder index already uses new folder listing macro')
            return True

        if tal.find(old_macro_start) == -1:
            self.log.info('folder index not using folder listing macro')
            return True

        self.log.info('folder index replacing folder listing macro')
        tal = tal.replace(old_macro_start, new_macro_start)
        custom_folder_index.write(tal)
        return True
    def _update(self, portal):
        t = '%(info)s folder: <a href="%(url)s/manage_main">%(text)s</a>'

        self.log.debug(physical_path(portal))
        for folder in list_folders_with_custom_index(portal):
            tal = folder.index.read()

            tal, strs = add_onerror_to_portlets_in_tal(tal)
            if strs == []:
                self.log.info(t % {'info': 'no match',
                                   'url': folder.absolute_url(),
                                   'text': physical_path(folder)})
            else:
                self.log.info(t % {'info': ','.join(strs) + ' portlet(s)',
                                   'url': folder.absolute_url(),
                                   'text': physical_path(folder)})
                folder.index.write(tal)
        return True
    def _update(self, portal):
        t = '%(info)s folder: <a href="%(url)s/manage_main">%(text)s</a>'

        self.log.debug(physical_path(portal))
        for folder in list_folders_with_custom_index(portal):
            tal = folder.index.read()

            tal, strs = add_onerror_to_portlets_in_tal(tal)
            if strs == []:
                self.log.info(
                    t % {
                        'info': 'no match',
                        'url': folder.absolute_url(),
                        'text': physical_path(folder)
                    })
            else:
                self.log.info(
                    t % {
                        'info': ','.join(strs) + ' portlet(s)',
                        'url': folder.absolute_url(),
                        'text': physical_path(folder)
                    })
                folder.index.write(tal)
        return True