import os
import urllib
import urlparse

from quixote import redirect, get_request, get_response, get_publisher
from quixote.directory import Directory

import lasso

from qommon.admin.menu import html_top, command_icon
from qommon import get_cfg
from qommon.form import *
from qommon.misc import http_get_page, get_abs_path

from larpe import site_authentication
from larpe import errors
from larpe import misc
from larpe.hosts import Host
from larpe.admin.liberty_utils import *
#from larpe.filter import filter_misc
from larpe.admin.apache import write_apache2_vhosts
from larpe.admin.forms_prefill import FormsDirectory
from larpe.Defaults import OUTPUT_FILTER_BASE

def check_basic_configuration(form):
    get_publisher().reload_cfg()
    # Check reversed_hostname and reversed_directory
    reversed_hostname = form.get_widget('reversed_hostname').parse()
    reversed_directory = form.get_widget('reversed_directory').parse()
    if reversed_hostname == get_publisher().cfg['proxy_hostname'] and not reversed_directory:
        form.set_error('reversed_hostname',
            _('You must either choose a different hostname from Larpe or specify a reversed directory'))

def convert_label_to_name(label):
    '''Build host name from host label'''
    name = label.lower()
    invalid_characters = [' ', "'"]
    for char in invalid_characters:
        name = name.replace(char, '_')
    return name

class DictWidget(Widget):
    def render_content [html] (self):
        self.render_br = False
        if self.value['enabled'] is True:
            htmltag('input', xml_end=True, type='checkbox', name=self.name + '_enabled', checked='checked')
        else:
            htmltag('input', xml_end=True, type='checkbox', name=self.name + '_enabled')
        ' ' + self.name + ' &nbsp;'
        htmltag('input', xml_end=True, type='text', name=self.name, value=self.value['value'], size='35', **self.attrs)

    def _parse(self, request):
        enabled = request.form.get(self.name + '_enabled')
        value = request.form.get(self.name)
        self.value = { 'enabled': enabled, 'value': value }


class ConfigurationAssistant(Directory):
    _q_exports = ['start', 'check_new_address', 'modify_site_address_and_name',
                  'authentication_and_logout_adresses', 'check_auto_detected_configuration',
                  'credentials', 'send_authentication_request', 'check_authentication',
                  'see_authentication_response', 'see_response_html_page',
                  'see_bad_response_html_page', 'authentication_success_criteria',
                  'modify_authentication_request', 'auth_request_post_parameters',
                  'auth_request_http_headers', 'sso_init_link', 'metadatas',
                  'check_full_configuration', 'advanced_options']

    def __init__(self, host):
        self.host = host

    def html_top [html] (self, title):
        html_top('hosts', title)
        '<h2>%s</h2>' % title

    def start [html] (self):
        # Check the global domain name has been previously set
        get_publisher().reload_cfg()
        if not get_cfg('domain_names') or not get_cfg('domain_names')[0]:
            get_response().breadcrumb.append(('start', _('Basic configuration')))
            self.html_top(_('Need domain name configuration'))
            return htmltext(_('''Before configuring hosts, you must
<a href="../../../settings/domain_names">setup a global domain name</a> in
%(settings)s menu.''') % { 'settings': _('Settings') })

        form = self.form_start()

        if form.get_widget('cancel').parse():
            return redirect('../..')

        connection_failure = None
        if form.is_submitted() and not form.has_errors():
            try:
                self.submit_start_form(form)
            except Exception, e:
                connection_failure = e
            else:
                if form.get_widget('terminate').parse():
                    return redirect('..')
                return redirect('check_new_address')

        get_response().breadcrumb.append(('start', _('Basic configuration')))
        self.html_top(_('Step 1 - Basic configuration'))

        if connection_failure:
            '<div class="errornotice">%s</div>' % connection_failure

        form.render()

    def form_start(self):
        form = Form(enctype='multipart/form-data')
        form.add(UrlWidget, 'orig_site', title = _('Original site root address'), required = True,
                size = 50, value = self.host.orig_site,
                hint = _('If your site address is http://test.org/index.php, put http://test.org/ here'))
        get_publisher().reload_cfg()
        if get_cfg('proxy', {}).get('enabled'):
            form.add(CheckboxWidget, 'use_proxy', title = _('Use a proxy'),
                    hint = _("Uncheck it if Larpe doesn't need to use the proxy to connect to this site"),
                    value = self.host.use_proxy)
        else:
            form.add(HtmlWidget, htmltext('<p>%s</p>' % \
                _('''If Larpe needs to use a proxy to connect to this site, you must first configure
 it in <a href="../../../settings/proxy">global proxy parameters</a>.''')))
        form.add_submit('cancel', _('Cancel'))
        form.add_submit('submit', _('Next'))
        form.add_submit('terminate', _('Terminate'))
        return form

    def submit_start_form(self, form):
        fields = ['orig_site']
        use_proxy = get_cfg('proxy', {}).get('enabled')
        if use_proxy:
            fields += ['use_proxy']
        for f in fields:
            setattr(self.host, f, form.get_widget(f).parse())

        # If no proxy is setup yet, set use_proxy to False for new hosts in case a proxy is later configured
        if not use_proxy:
            self.host.use_proxy = False

        # Remove what is after the last '/'
        #self.host.orig_site = '/'.join(self.host.orig_site.split('/')[:-1])

        html_page = self.get_data_after_redirects(self.host.orig_site)

        if not self.host.label:
            # Look for html title in original site index page
            regexp = re.compile("""<title.*?>(.*?)</title>""", re.DOTALL | re.IGNORECASE)
            title = regexp.findall(html_page)
            if title:
                self.host.label = title[0]
            else:
                self.host.label = 'Untitled'
            # If another site already uses this site title, add trailings "_" until we find an available name
            existing_label = True
            while existing_label is True:
                for any_host in Host.select():
                    if any_host.id != self.host.id and self.host.label == any_host.label:
                        self.host.label += '_'
                        break
                else:
                    existing_label = False

            # Fill host.name attribute
            self.host.name = convert_label_to_name(self.host.label)

        if not self.host.scheme:
            # Get tokens from orig site url
            orig_scheme, rest = urllib.splittype(self.host.orig_site)
            orig_host, rest = urllib.splithost(rest)

            get_publisher().reload_cfg()
            # Set url scheme (HTTP or HTTPS)
            # TODO: Handle the option "Both"
            if get_cfg('sites_url_scheme'):
                self.host.scheme = get_cfg('sites_url_scheme')
            else:
                self.host.scheme = orig_scheme

        if not self.host.reversed_hostname:
            # Build a new domain name
            short_name = orig_host.split('.')[0]
            if short_name == 'www':
                short_name = orig_host.split('.')[1]
            self.host.reversed_hostname = '%s.%s' % (short_name, get_cfg('domain_names')[0])
            # If another site already uses this domain name, add some trailing "_" until we find an available name
            existing_domain = True
            while existing_domain is True:
                for any_host in Host.select():
                    if any_host.id != self.host.id and self.host.reversed_hostname == any_host.reversed_hostname:
                        self.host.reversed_hostname += '-'
                        break
                else:
                    existing_domain = False
            self.host.reversed_directory = None

        if not self.host.new_url:
            # New url for this host
            self.host.new_url = '%s://%s%s/' % (self.host.scheme, self.host.reversed_hostname, get_request().environ['SCRIPT_NAME'])
            # FIXME: Check if the new domain name already exists

            # New url for this host
            #        self.host.new_url = '%s://%s%s/' % (self.host.scheme, self.host.reversed_hostname, get_request().environ['SCRIPT_NAME'])
            #        if self.host.reversed_directory is not None:
            #            self.host.new_url += '%s/' % self.host.reversed_directory

        self.host.store()
        write_apache2_vhosts()

    # XXX: Should use the FancyURLopener class instead when it supports proxies
    def get_data_after_redirects(self, start_url):
        if not start_url:
            return ''
        status = 302
        location = None
        while status // 100 == 3:
            if location is None:
                url = start_url
            elif location.startswith('http'):
                # Location is an absolute path
                url = location
            else:
                # Location is a relative path
                url = urlparse.urljoin(start_url, location)
            response, status, data, auth_headers = http_get_page(url, use_proxy=self.host.use_proxy)
            location = response.getheader('Location', None)
        return data

    def create_dirs(self):
        # Hack : sites must use the configuration which is stored in main Larpe directory,
        # but they need to have a directory named with their hostname, which will contain the
        # main domain name for Larpe so they know where is the main configuration
        hostname_dir = get_abs_path(os.path.join('..', self.host.reversed_hostname))
        if not os.path.exists(hostname_dir):
            os.mkdir(hostname_dir)
        # Load the configuration from the main directory
        get_publisher().reload_cfg()
        # Write it in the site directory
        get_publisher().write_cfg(hostname_dir)

        # Storage directories
        if not self.host.reversed_directory:
            reversed_dir = 'default'
        else:
            reversed_dir = self.host.reversed_directory
        self.host.site_dir = \
            os.path.join(get_publisher().app_dir, 'sp', self.host.reversed_hostname, reversed_dir)
        user_dir = os.path.join(self.host.site_dir, 'users')
        token_dir = os.path.join(self.host.site_dir, 'tokens')
        filter_dir = os.path.join(self.host.site_dir, 'filters')
        for dir in (self.host.site_dir, user_dir, token_dir, filter_dir):
            if not os.path.isdir(dir):
                os.makedirs(dir)

    def generate_ssl_keys(self):
        # Generate SSL keys
        private_key_path = os.path.join(self.host.site_dir, 'private_key.pem')
        public_key_path = os.path.join(self.host.site_dir, 'public_key.pem')
        if not os.path.isfile(private_key_path) or not os.path.isfile(public_key_path):
            set_provider_keys(private_key_path, public_key_path)
        self.host.private_key = private_key_path
        self.host.public_key = public_key_path

    def generate_metadatas(self):
        metadata_cfg = {}

        # Organization name
        self.host.organization_name = self.host.label
        metadata_cfg['organization_name'] = self.host.organization_name

        # Base URL
        base_url = '%s://%s%s/liberty/%s/liberty' % (self.host.scheme,
                                                     self.host.reversed_hostname,
                                                     get_request().environ['SCRIPT_NAME'],
                                                     self.host.name)
        metadata_cfg['base_url'] = base_url
        self.host.base_url = base_url

        if lasso.SAML2_SUPPORT:
            saml2_base_url = '%s://%s%s/liberty/%s/saml' % (self.host.scheme,
                                                         self.host.reversed_hostname,
                                                         get_request().environ['SCRIPT_NAME'],
                                                         self.host.name)
            metadata_cfg['saml2_base_url'] = saml2_base_url
            self.host.saml2_base_url = saml2_base_url

        # Provider Id
        provider_id = '%s/metadata' % base_url
        metadata_cfg['provider_id'] = provider_id
        self.host.provider_id = provider_id

        if lasso.SAML2_SUPPORT:
            saml2_provider_id = '%s/metadata' % saml2_base_url
            metadata_cfg['saml2_provider_id'] = saml2_provider_id
            self.host.saml2_provider_id = saml2_provider_id

        # Read public key
        public_key = ''
        if self.host.public_key is not None and os.path.exists(self.host.public_key):
            metadata_cfg['signing_public_key'] = open(self.host.public_key).read()

        # Write metadatas
        metadata_path = os.path.join(self.host.site_dir, 'metadata.xml')
        open(metadata_path, 'w').write(get_metadata(metadata_cfg))
        self.host.metadata = metadata_path

        if lasso.SAML2_SUPPORT:
            saml2_metadata_path = os.path.join(self.host.site_dir, 'saml2_metadata.xml')
            open(saml2_metadata_path, 'w').write(get_saml2_metadata(metadata_cfg))
            self.host.saml2_metadata = saml2_metadata_path

    def check_new_address [html] (self):
        form = Form(enctype='multipart/form-data')
        form.add_submit('cancel', _('Previous'))
        form.add_submit('submit', _('Next'))
        form.add_submit('terminate', _('Terminate'))

        if form.get_widget('cancel').parse():
            return redirect('start')

        if form.is_submitted():
            self.create_dirs()
            if self.host.private_key is None:
                self.generate_ssl_keys()
            self.generate_metadatas()
            self.host.store()

            if form.get_widget('terminate').parse():
                return redirect('..')
            return redirect('authentication_and_logout_adresses')

        get_response().breadcrumb.append(('check_new_address', _('Check site address and name')))
        self.html_top(_('Step 2 - Check the new site address works'))

        '<h3>%s</h3>' % _('DNS configuration')

        '<p>%s</p>' % _('''Before opening the following link, ensure you have configured your DNS
for this address. If you don't have a DNS server and you just want to test Larpe, add this
domain name in the file "/etc/hosts".''')

        '<p>%s</p>' % _('''Then you can open this link in a new window or tab and see if your site
is displayed. If it's ok, you can click the "%(next)s" button. Otherwise, click the "%(previous)s"
button and check your settings.''') % {'next': _('Next'), 'previous': _('Previous')}

        '<h3>%s</h3>' % _('Site adress and name')

        '<p>%s' % _('The new address of this site is ')
        '<a href="%s">%s</a><br/>' % (self.host.new_url, self.host.new_url)
        '%s</p>' % _('The name of this site is "%s".') % self.host.label
        '<p>%s</p>' % htmltext(_('''You can also <a href="modify_site_address_and_name">
modify the address or the name of this site</a>'''))

        form.render()

    def modify_site_address_and_name [html] (self):
        form = self.form_modify_site_address_and_name()

        if form.get_widget('cancel').parse():
            return redirect('check_new_address')

        if form.is_submitted() and not form.has_errors():
            label = form.get_widget('label').parse()
            name = convert_label_to_name(label)
            for any_host in Host.select():
                if any_host.id != self.host.id and name == any_host.name:
                    form.set_error('label', _('An host with the same name already exists'))
                    break

        if form.is_submitted() and not form.has_errors():
            self.submit_modify_site_address_and_name_form(form)
            return redirect('check_new_address')

        get_response().breadcrumb.append(('modify_site_address_and_name', _('Modify site address and name')))
        self.html_top(_('Modify site address and name'))

        form.render()

    def form_modify_site_address_and_name(self):
        form = Form(enctype='multipart/form-data')
        form.add(UrlWidget, 'new_url', title = _('Address'), required = True,
                size = 50, value = self.host.new_url)
        form.add(StringWidget, 'label', title = _('Name'), required = True,
                size = 50, value = self.host.label)
        form.add_submit('submit', _('Submit'))
        form.add_submit('cancel', _('Cancel'))
        return form

    def submit_modify_site_address_and_name_form(self, form):
        fields = ['new_url', 'label']
        for f in fields:
            setattr(self.host, f, form.get_widget(f).parse())

        # Split url to retrieve components
        tokens = urlparse.urlparse(self.host.new_url)
        self.host.scheme = tokens[0]
        self.host.reversed_hostname = tokens[1]
        self.host.reversed_directory = tokens[2]
        if self.host.reversed_directory.startswith('/'):
            self.host.reversed_directory = self.host.reversed_directory[1:]

        # Fill host.name attribute
        self.host.name = convert_label_to_name(self.host.label)

        self.host.store()
        write_apache2_vhosts()

    def authentication_and_logout_adresses [html] (self):
        form = self.form_authentication_and_logout_adresses()

        if form.get_widget('cancel').parse():
            return redirect('check_new_address')

        if form.is_submitted() and not form.has_errors():
            self.submit_authentication_and_logout_adresses_form(form)
            if form.get_widget('terminate').parse():
                return redirect('..')
            return redirect('check_auto_detected_configuration')

        get_response().breadcrumb.append(('authentication_and_logout_adresses', _('Authentication and logout')))
        self.html_top(_('Step 3 - Configure authentication and logout pages'))

        form.render()

    def form_authentication_and_logout_adresses(self):
        form = Form(enctype='multipart/form-data')
        form.add(ValidUrlWidget, 'auth_url', title = _('Authentication form page address'),
                hint = _('Address of a page on the site which contains the authentication form'),
                required = True, size = 50, value = self.host.auth_url)
        form.add(ValidUrlWidget, 'logout_url', title = _('Logout address'), required = False,
                hint = _('Address of the logout link on the site'),
                size = 50, value = self.host.logout_url)
        form.add_submit('cancel', _('Previous'))
        form.add_submit('submit', _('Next'))
        form.add_submit('terminate', _('Terminate'))
        return form

    def submit_authentication_and_logout_adresses_form(self, form):
        fields = ['auth_url', 'logout_url']
        for f in fields:
            setattr(self.host, f, form.get_widget(f).parse())
        self.host.auth_form_url = self.host.auth_url

        if not self.host.http_headers:
            self.host.http_headers = {
                'Content-Type': { 'enabled': True, 'value': 'application/x-www-form-urlencoded', 'immutable': False },
                'X-Forwarded-For': { 'enabled': True, 'value': _('(computed automatically)'), 'immutable': True },
                'X-Forwarded-Host': { 'enabled': True, 'value': self.host.reversed_hostname, 'immutable': False },
            }

        self.auto_detect_configuration()
        self.host.store()
        write_apache2_vhosts()

    def check_auto_detected_configuration [html] (self):
        form = Form(enctype='multipart/form-data')
        form.add_submit('cancel', _('Previous'))
        form.add_submit('submit', _('Next'))
        form.add_submit('terminate', _('Terminate'))

        if form.get_widget('cancel').parse():
            return redirect('authentication_and_logout_adresses')

        if form.is_submitted():
            if form.get_widget('terminate').parse():
                return redirect('..')
            return redirect('credentials')

        get_response().breadcrumb.append(('check_auto_detected_configuration', _('Auto detected configuration')))
        self.html_top(_('Step 4 - Check automatically detected configuration for the authentication form'))

        host_attrs = (
            ('auth_check_url', _('Address where the authentication form must be sent')),
            ('login_field_name', _('Name of the login field')),
            ('password_field_name', _('Name of the password field')),
        )

        html_fields = ''
        success = True
        for attr, name in host_attrs:
            color = 'black'
            if attr in ('auth_check_url', 'login_field_name', 'password_field_name') and \
                    not getattr(self.host, str(attr)):
                color = 'red'
                success = False
            html_fields += '<div style="margin-bottom: 0.1em; font-weight: bold; color: %s;">%s</div>' % (color, name)
            html_fields += '<div style="margin-left: 1em; margin-bottom: 0.3em; color: %s;">%s</div>' % \
                (color, getattr(self.host, str(attr)))
            if getattr(self.host, str(attr)) == '':
                html_fields += '<br />'

        '<p>'
        if success:
            htmltext(_('''\
The following authentication form parameters have been detected. If they look right, you can go to the next step.
If you think they are wrong, go back and check your settings then try again.
'''))
        else:
            htmltext(_('''\
The following authentication form parameters in red haven't been correctly detected. Go back and check
your settings then try again.
'''))
        '</p>'

        html_fields
        form.render()

    def credentials [html] (self):
        form = self.form_credentials()

        if form.get_widget('cancel').parse():
            return redirect('check_auto_detected_configuration')

        if form.is_submitted() and not form.has_errors():
            self.submit_credentials_form(form)
            if form.get_widget('terminate').parse():
                return redirect('..')
            return redirect('send_authentication_request')

        get_response().breadcrumb.append(('credentials', _('Credentials')))
        self.html_top(_('Step 5 - Fill in a valid username/password for this site'))

        form.render()

    def form_credentials(self):
        form = Form(enctype='multipart/form-data')
        form.add(StringWidget, 'username', title = _('Username'), required = True,
                size = 30, value = self.host.valid_username)
        form.add(PasswordWidget, 'password', title = _('Password'), required = True,
                size = 30, value = self.host.valid_password)
        for name, values in self.host.select_fields.iteritems():
            options = []
            if values:
                for value in values:
                    options.append(value)
                form.add(SingleSelectWidget, name, title = name.capitalize(),
                    value = values[0], options = options)
        form.add_submit('cancel', _('Previous'))
        form.add_submit('submit', _('Next'))
        form.add_submit('terminate', _('Terminate'))
        return form

    def submit_credentials_form(self, form):
        self.host.valid_username = form.get_widget('username').parse()
        self.host.valid_password = form.get_widget('password').parse()
        self.host.valid_select = {}
        for name, values in self.host.select_fields.iteritems():
            if form.get_widget(name):
                self.host.valid_select[name] = form.get_widget(name).parse()

        self.host.store()

    def send_authentication_request(self):
        site_auth = site_authentication.get_site_authentication(self.host)

        # Request with good credentials
        self.host.auth_request_status, self.host.auth_request_data = site_auth.local_auth_check_dispatch(
            self.host.valid_username, self.host.valid_password, self.host.valid_select)
        self.host.auth_request_success, self.host.auth_request_return_content = \
            site_auth.check_auth(self.host.auth_request_status, self.host.auth_request_data)

        # Request with bad credentials
        self.host.auth_bad_request_status, self.host.auth_bad_request_data = site_auth.local_auth_check_dispatch(
            'this_is_a_bad_login', 'this_is_a_bad_password', {})
        self.host.auth_bad_request_success, self.host.auth_bad_request_return_content = \
            site_auth.check_auth(self.host.auth_bad_request_status, self.host.auth_bad_request_data)

        self.host.store()

        return redirect('check_authentication')

    def check_authentication [html] (self):
        form = Form(enctype='multipart/form-data')
        form.add_submit('cancel', _('Previous'))
        form.add_submit('submit', _('Next'))
        form.add_submit('terminate', _('Terminate'))

        if form.get_widget('cancel').parse():
            return redirect('credentials')

        if form.is_submitted():
            if form.get_widget('terminate').parse():
                return redirect('..')
            return redirect('sso_init_link')

        get_response().breadcrumb.append(('check_authentication', _('Check authentication')))
        self.html_top(_('Step 6 - Check the authentication process'))

        if self.host.auth_request_success:
            good_cred_status = 'Success <span style="color: green">[OK]</span>'
        else:
            good_cred_status = 'Failed <span style="color: red">[KO]</span'

        if not self.host.auth_bad_request_success:
            bad_cred_status = 'Failed <span style="color: green">[OK]</span>'
        else:
            bad_cred_status = 'Success <span style="color: red">[KO]</span>'

        '<p>Results of authentication requests :</p>\n'
        '<ul>\n'
        '\t<li>With good credentials : %s</li>' % good_cred_status
        '\t<li>With bad credentials : %s</li>' % bad_cred_status
        '</ul>\n'

        if self.host.auth_request_success and not self.host.auth_bad_request_success :
            '<p>%s</p>\n' % _('Authentication succeeded ! You can go to the next step.')
        else:
            '<p>%s</p>\n' % _('Authentication has failed. To resolve this problem, you can :')
            '<ul>\n'
            '\t<li><a href="send_authentication_request">%s</a></li>\n' % \
                _('Try authentication again')
            '\t<li><a href="see_authentication_response">%s</a></li>\n' % \
                _('See the response of the authentication requests')
            '\t<li><a href="modify_authentication_request">%s</a></li>\n' % \
                _('Modify the parameters of the authentication requests')
            '\t<li><a href="authentication_success_criteria">%s</a></li>\n' % \
                _('Change the way Larpe detects the authentication is successful or not')
            '\t<li>%s</li>\n' % _('Go back and change your username and/or password')
            '</ul>\n'

        form.render()

    def see_authentication_response [html] (self):
        get_response().breadcrumb.append(('see_authentication_response', _('Authentication response')))
        self.html_top(_('Authentication response'))

        '<h3>%s</h3>' % _('Response of the request with good credentials')

        '<div style="margin-bottom: 0.1em; font-weight: bold; color: black;">%s</div>' % \
            str(_('HTTP status code'))
        '<div style="margin-left: 1em; margin-bottom: 0.3em; color: black;">%s (%s)</div>' % \
            (self.host.auth_request_status, status_reasons[self.host.auth_request_status])

        '<dl>'
        '<dt><a href="see_bad_response_html_page">%s</a></dt>' % _('See HTML page')
        '</dl>'

        '<h3>%s</h3>' % _('Response of the request with bad credentials')

        '<div style="margin-bottom: 0.1em; font-weight: bold; color: black;">%s</div>' % \
            str(_('HTTP status code'))
        '<div style="margin-left: 1em; margin-bottom: 0.3em; color: black;">%s (%s)</div>' % \
            (self.host.auth_bad_request_status, status_reasons[self.host.auth_bad_request_status])

        '<dl>'
        '<dt><a href="see_response_html_page">%s</a></dt>' % _('See HTML page')
        '</dl>'

        '<div class="buttons"><a href="check_authentication"><input type="button" value="%s" /></a></div><br />' % _('Back')

    def see_response_html_page (self):
        return self.host.auth_request_data

    def see_bad_response_html_page (self):
        return self.host.auth_bad_request_data

    def authentication_success_criteria [html] (self):
        form = self.form_authentication_success_criteria()

        if form.get_widget('cancel').parse():
            return redirect('check_authentication')

        if form.is_submitted() and not form.has_errors():
            self.submit_authentication_success_criteria_form(form)
            return redirect('check_authentication')

        get_response().breadcrumb.append(('authentication_success_criteria', _('Authentication success criteria')))
        self.html_top(_('Authentication success criteria'))

        form.render()

    def form_authentication_success_criteria(self):
        form = Form(enctype='multipart/form-data')
        form.add(RadiobuttonsWidget, 'auth_system', title = _('Authentication system of the original site'),
                options=[
                    ('password', _('Check the existence of a password field'), 'password'),
                    ('match_text', _('Match some text to detect an authentication failure'), 'match_text'),
                ],
                sort=False,
                delim=htmltext('<br />'),
                value = self.host.auth_system)
        form.add(RegexStringWidget, 'auth_match_text', title = _('Text to match in case of authentication failure'),
                required = False, size = 50, value = self.host.auth_match_text)
        form.add_submit('submit', _('Submit'))
        form.add_submit('cancel', _('Cancel'))
        return form

    def submit_authentication_success_criteria_form(self, form):
        for f in ('auth_system', 'auth_match_text'):
            value = form.get_widget(f).parse()
            setattr(self.host, f, value)

        self.host.store()

    def modify_authentication_request [html] (self):
        get_response().breadcrumb.append(('modify_authentication_request', _('Authentication request')))
        self.html_top(_('Modify the parameters of the authentication requests'))

        '<dl>'
        '<dt><a href="auth_request_post_parameters">%s</a></dt> <dd>%s</dd>' % (
                _('Modify POST parameters'), _('Configure the form attributes that will be sent within the authentication POST requests'))
        '<dt><a href="auth_request_http_headers">%s</a></dt> <dd>%s</dd>' % (
                _('Modify HTTP headers'), _('Configure the HTTP headers of the authentication requests made by Larpe'))
        '</dl>'
        '<div class="buttons"><a href="check_authentication"><input type="button" value="%s" /></a></div><br />' % _('Back')

    def auth_request_post_parameters [html] (self):
        form = self.form_auth_request_post_parameters()

        if form.get_widget('cancel').parse():
            return redirect('modify_authentication_request')

        if form.is_submitted() and not form.has_errors():
            self.submit_auth_request_post_parameters_form(form)
            return redirect('modify_authentication_request')

        get_response().breadcrumb.append(('auth_request_post_parameters', _('POST parameters')))
        self.html_top(_('Configure POST parameters'))

        '<p>%s</p>' % _('''Here are the detected form fields that will be sent as parameters of the
authentication POST request. You can desactivate some or all of them, or change their value.''')

        form.render()

    def form_auth_request_post_parameters(self):
        form = Form(enctype='multipart/form-data')
        for name, value in self.host.post_parameters.iteritems():
            if value['immutable']:
                form.add(DictWidget, name, value, disabled = 'disabled')
            else:
                form.add(DictWidget, name, value)
        form.add_submit('submit', _('Submit'))
        form.add_submit('cancel', _('Cancel'))
        return form

    def submit_auth_request_post_parameters_form(self, form):
        for name, old_value in self.host.post_parameters.iteritems():
            value = form.get_widget(name).parse()
            if value['enabled'] == 'on':
                old_value['enabled'] = True
            else:
                old_value['enabled'] = False
            if old_value['immutable'] is False:
                old_value['value'] = value['value']
            self.host.post_parameters[name] = old_value
        self.host.store()

    def auth_request_http_headers [html] (self):
        form = self.form_auth_request_http_headers()

        if form.get_widget('cancel').parse():
            return redirect('modify_authentication_request')

        if form.is_submitted() and not form.has_errors():
            self.submit_auth_request_http_headers_form(form)
            return redirect('modify_authentication_request')

        get_response().breadcrumb.append(('auth_request_http_headers', _('HTTP headers')))
        self.html_top(_('Configure HTTP headers'))

        '<p>%s</p>' % _('''Here are the HTTP headers that will be sent within the authentication
POST request. You can desactivate some or all of them, or change their value.''')

        form.render()

    def form_auth_request_http_headers(self):
        form = Form(enctype='multipart/form-data')
        for name, value in self.host.http_headers.iteritems():
            if value['immutable']:
                form.add(DictWidget, name, value, disabled = 'disabled')
            else:
                form.add(DictWidget, name, value)
        form.add(HtmlWidget, htmltext('<p>%s</p>' % \
            _('The headers "Host", "Accept-Encoding" and "Content-Length" will also automatically be sent.')))
        if get_cfg('proxy', {}).get('enabled') and self.host.use_proxy:
            form.add(HtmlWidget, htmltext('<p>%s</p>' % \
                _('''As Larpe uses a proxy for this site, the headers "Proxy-Authorization",
"Proxy-Connection" and "Keep-Alive" will be sent as well.''')))
        form.add_submit('submit', _('Submit'))
        form.add_submit('cancel', _('Cancel'))
        return form

    def submit_auth_request_http_headers_form(self, form):
        for name, old_value in self.host.http_headers.iteritems():
            value = form.get_widget(name).parse()
            if value['enabled'] == 'on':
                old_value['enabled'] = True
            else:
                old_value['enabled'] = False
            if old_value['immutable'] is False:
                old_value['value'] = value['value']
            self.host.http_headers[name] = old_value
        self.host.store()

    def generate_apache_filter(self):
        # Set Python filter path for Apache configuration
        python_path = os.path.join(self.host.site_dir, 'filters')
        if python_path not in self.host.apache_python_paths:
            self.host.apache_python_paths.append(python_path)

        # Write Python filter
        python_file = open(os.path.join(self.host.site_dir, 'filters', 'output_replace_form.py'), 'w')
        python_file.write(open(OUTPUT_FILTER_BASE).read())
        python_file.write('''\
def filter_page(filter, page):
    current_form = re.compile('<form [^>]*?action="%(auth_form_action)s".*?>.*?</form>', re.DOTALL)
    return current_form.sub('<form method="post" action="/liberty/%(name)s/login"><input type="submit" value="Connexion" /></form>', page)
''' % { 'auth_form_action': self.host.auth_form_action, 'name': self.host.name })
        python_file.close()

        # Set Python filter for Apache configuration
        if not 'output_replace_form' in self.host.apache_output_python_filters:
            self.host.apache_output_python_filters.append('output_replace_form')

    def sso_init_link [html] (self):
        form = self.form_sso_init_link()

        if form.get_widget('cancel').parse():
            return redirect('check_authentication')

        if form.is_submitted() and not form.has_errors():
            self.submit_sso_init_link_form(form)
            if form.get_widget('terminate').parse():
                return redirect('..')
            return redirect('metadatas')

        get_response().breadcrumb.append(('sso_init_link', _('SSO initiation')))
        self.html_top(_('Step 7 - Configure how a Single Sign On can be initiated'))

        '<p>%s\n' % _('Most sites use one of the following 2 ways to allow users to initialise an authentication :')
        '\t<ol>\n'
        '\t\t<li>%s</li>\n' % \
            _('''The site has a single authentication page. It redirects users to this page when
they click a "Login" button or try to access a page which require users to be authenticated.''')
        '\t\t<li>%s</li>\n' % \
            _('''The site includes an authentication form in most or all of his pages. Users can
authenticate on any of these pages, and don't need to be redirected to a separate authentication page.''')
        '\t</ol>\n'
        '</p>\n'

        '<p>%s</p>' % _('Select the way your site works :')

        form.render()

    def form_sso_init_link(self):
        form = Form(enctype='multipart/form-data')
        form.add(RadiobuttonsWidget, 'auth_form_places',
                options=[
                    ('form_once', _('The site has a single authentication page'), 'form_once'),
                    ('form_everywhere', _('The site includes an authentication form in most or all pages'), 'form_everywhere'),
                ],
                sort=False, required = True, delim=htmltext('<br />'), value = self.host.auth_form_places)
        form.add_submit('cancel', _('Previous'))
        form.add_submit('submit', _('Next'))
        form.add_submit('terminate', _('Terminate'))
        return form

    def submit_sso_init_link_form(self, form):
        fields = [ 'auth_form_places', ]
        for f in fields:
            setattr(self.host, f, form.get_widget(f).parse())
        self.host.auth_form_url = self.host.auth_url

        if self.host.auth_form_places == 'form_everywhere' and self.host.auth_form_action:
            self.generate_apache_filter()
        else:
            if 'output_replace_form' in self.host.apache_output_python_filters:
                self.host.apache_output_python_filters.remove('output_replace_form')

        self.host.store()
        write_apache2_vhosts()

    def metadatas [html] (self):
        form = Form(enctype='multipart/form-data')
        form.add_submit('cancel', _('Previous'))
        form.add_submit('submit', _('Next'))
        form.add_submit('terminate', _('Terminate'))

        if form.get_widget('cancel').parse():
            return redirect('sso_init_link')

        if form.is_submitted():
            if form.get_widget('terminate').parse():
                return redirect('..')
            return redirect('advanced_options')

        get_response().breadcrumb.append(('metadatas', _('Metadatas')))
        self.html_top(_('Step 8 - Metadatas of %(site_name)s' % {'site_name': self.host.name}))

        '<p>%s</p>' % \
            _('''Download the metadatas and the public key for this site and
upload them on your identity provider in order to use Liberty Alliance features.''')

        '<dl>'
        if hasattr(self.host, str('base_url')):
            if lasso.SAML2_SUPPORT:
                saml2_metadata_url = '%s/metadata.xml' % self.host.saml2_base_url
                '<dt><a href="%s">%s</a></dt> <dd>%s</dd>' % (
                            saml2_metadata_url,
                            _('SAML 2.0 Metadata'),
                            _('Download SAML 2.0 metadata file'))
            metadata_url = '%s/metadata.xml' % self.host.base_url
            '<dt><a href="%s">%s</a></dt> <dd>%s</dd>' % (
                        metadata_url,
                        _('ID-FF 1.2 Metadata'),
                        _('Download ID-FF 1.2 metadata file'))
        else:
            '<p>%s</p>' % _('No metadata has been generated for this host.')

        if hasattr(self.host, str('base_url')) and self.host.public_key and os.path.exists(self.host.public_key):
            public_key_url = '%s/public_key' % self.host.base_url
            '<dt><a href="%s">%s</a></dt> <dd>%s</dd>' % (
                        public_key_url,
                        _('Public key'),
                        _('Download SSL Public Key file'))
        else:
            '<p>%s</p>' % _('No public key has been generated for this host.')
        '</dl>'

        form.render()

    def advanced_options [html] (self):
        form = self.form_advanced_options()

        if form.get_widget('cancel').parse():
            return redirect('metadatas')

        if not form.is_submitted() or form.has_errors():
            get_response().breadcrumb.append(('advanced_options', _('Advanced options')))
            self.html_top(_('Step 9 - Advanced options'))

            '<p>%s</p>' % _('Configure advanced options to setup the last details of your site.')
            '<p>%s</p>' % _('''If you don't know what to configure here, just click %(next)s and
come here later if needed.''') % {'next': _('Next')}

            form.render()
        else:
            self.submit_advanced_options_form(form)
            if form.get_widget('terminate').parse():
                return redirect('..')
            return redirect('check_full_configuration')

    def form_advanced_options(self):
        form = Form(enctype='multipart/form-data')
        form.add(CheckboxWidget, 'redirect_root_to_login',
                title=_('Redirect the root URL of the site to the login page.'),
                value = self.host.redirect_root_to_login)
        form.add(UrlOrAbsPathWidget, 'return_url', title = _('Return address'),
                hint = _('Where the user will be redirected after a successful authentication'),
                required = False, size = 50, value = self.host.return_url)
        form.add(UrlOrAbsPathWidget, 'root_url', title = _('Error address'),
                hint = _('Where the user will be redirected after a disconnection or an error'),
                required = False, size = 50, value = self.host.root_url)
        form.add(UrlOrAbsPathWidget, 'initiate_sso_url', title = _('URL which must initiate the SSO'),
                hint = _('''Address which must initiate the SSO. If empty, defaults to the previously
specified "%s"''') % _('Authentication form page address'),
                required = False, size = 50, value = self.host.initiate_sso_url)
        form.add(CheckboxWidget, 'proxy-html', title = _('Apache HTML proxy'),
                hint = _('''Converts urls in the HTML pages according to the host new domain name.
Disabled by default because it makes some sites not work correctly.'''),
                value = 'proxy-html' in self.host.apache_output_filters)

        form.add_submit('cancel', _('Previous'))
        form.add_submit('submit', _('Next'))
        form.add_submit('terminate', _('Terminate'))
        return form

    def submit_advanced_options_form(self, form):
        old_redirect_root_to_login = self.host.redirect_root_to_login

        for f in ('redirect_root_to_login', 'return_url', 'root_url', 'initiate_sso_url'):
            value = form.get_widget(f).parse()
            setattr(self.host, f, value)

        f = 'proxy-html'
        value = form.get_widget(f).parse()
        if value is True and f not in self.host.apache_output_filters:
            self.host.apache_output_filters.append(f)
        if value is False and f in self.host.apache_output_filters:
            self.host.apache_output_filters.remove(f)

        self.host.store()

        if self.host.initiate_sso_url or self.host.redirect_root_to_login is not old_redirect_root_to_login:
            write_apache2_vhosts()

    def check_full_configuration [html] (self):
        form = Form(enctype='multipart/form-data')
        form.add_submit('cancel', _('Previous'))
        form.add_submit('submit', _('Finish'))

        if form.get_widget('cancel').parse():
            return redirect('advanced_options')

        if form.is_submitted():
            return redirect('../..')

        get_response().breadcrumb.append(('check_full_configuration', _('Check everything works')))
        self.html_top(_('Step 10 - Check everything works'))

        '<p>%s</p>' % \
            _('''Now you can fully test your site, start from the home page, initiate a
Single Sign On, federate your identities and do a Single Logout.''')

        '<p>%s' % _('The address of your site is : ')
        '<a href="%s">%s</a>' % (self.host.new_url, self.host.new_url)
        '</p>'

        '<p>%s</p>' % \
            _('''If everything works, click the "%(finish)s" button, otherwise you can go
back and check your settings.''') % { 'finish': _('Finish') }

        form.render()

    def auto_detect_configuration(self):
        # Reset previous detected values
        self.host.auth_form = None
        self.host.auth_check_url = None
        self.host.login_field_name = None
        self.host.password_field_name = None
        if not self.host.post_parameters:
            self.host.post_parameters = {}

        self.parse_page(self.host.auth_form_url)

    def parse_page(self, page_url):
        # Get the authentication page
        try:
            response, status, page, auth_header = http_get_page(page_url, use_proxy=self.host.use_proxy)
        except Exception, msg:
            print msg
            return

        if page is None:
            return
            #raise FormError, ('auth_check_url', '%s : %s' % (_('Failed to get page'), self.host.auth_form_url))

        # Default authentication mode
        self.host.auth_mode = 'form'

        self.host.site_authentication_plugin = site_authentication.guess_site_authentication_class(page)
        self.parse_frames(page)
        self.parse_forms(page)
        if self.host.auth_form is not None:
            self.parse_form_action()
            input_fields = self.parse_input_fields()
            self.parse_login_field(input_fields)
            self.parse_password_field()
            self.parse_select_fields()
            self.parse_other_fields()

    def parse_frames(self, page):
        '''If there are frames, parse them recursively'''
        regexp = re.compile("""<frame.*?src=["'](.*?)["'][^>]*?>""", re.DOTALL | re.IGNORECASE)
        found_frames = regexp.findall(page)
        if found_frames:
            for frame_url in found_frames:
                if frame_url.startswith('http'):
                    frame_full_url = frame_url
                else:
                    page_url_tokens = page_url.split('/')
                    page_url_tokens[-1] = frame_url
                    frame_full_url = '/'.join(page_url_tokens)
                self.parse_page(frame_full_url)

    def parse_forms(self, page):
        '''Search for an authentication form'''
        # Get all forms
        regexp = re.compile("""<form.*?</form>""", re.DOTALL | re.IGNORECASE)
        found_forms = regexp.findall(page)
        if not found_forms:
            return
            #raise FormError, ('auth_check_url', '%s : %s' % (_('Failed to find any form'), self.host.auth_form_url))

        # Get the first form with a password field
        for found_form in found_forms:
            regexp = re.compile("""<input[^>]*?type=["']?password["']?[^>]*?>""", re.DOTALL | re.IGNORECASE)
            if regexp.search(found_form) is not None:
                self.host.auth_form = found_form
                break

    def parse_form_action(self):
        '''Get the action url of the form'''
        regexp = re.compile("""<form.*?action=["']?(.*?)["']?[\s>].*?>""", re.DOTALL | re.IGNORECASE)
        self.host.auth_form_action = regexp.findall(self.host.auth_form)[0]
        # FIXME: Find a Python module which unescapes html entities
        self.host.auth_check_url = self.host.auth_form_action.replace('&amp;', '&')
        if not self.host.auth_check_url.startswith('http'):
            if self.host.auth_check_url.startswith('/'):
                if self.host.orig_site.startswith('https'):
                    orig_site_root = 'https://%s' % urllib.splithost(self.host.orig_site[6:])[0]
                else:
                    orig_site_root = 'http://%s' % urllib.splithost(self.host.orig_site[5:])[0]
                self.host.auth_check_url = orig_site_root + self.host.auth_check_url
            else:
                auth_form_url_tokens = self.host.auth_form_url.split('/')
                auth_form_url_tokens[-1] = self.host.auth_check_url
                self.host.auth_check_url = '/'.join(auth_form_url_tokens)

    def parse_input_fields(self):
        '''Get all input fields'''
        regexp = re.compile("""<input[^>]*?>""", re.DOTALL | re.IGNORECASE)
        return regexp.findall(self.host.auth_form)

    def parse_login_field(self, input_fields):
        '''Get login field name'''
        try:
            regexp = re.compile("""<input[^>]*?type=["']?text["']?[^>]*?>""", re.DOTALL | re.IGNORECASE)
            text_fields = regexp.findall(self.host.auth_form)
            login_field = ''
            if text_fields:
                login_field = text_fields[0]
            else:
                for field in input_fields:
                    if re.search("""type=["']?""", field, re.DOTALL | re.IGNORECASE) is None:
                        login_field = field
                        break
            regexp = re.compile("""name=["']?(.*?)["']?[\s/>]""", re.DOTALL | re.IGNORECASE)
            self.host.login_field_name = regexp.findall(login_field)[0]
            if not self.host.post_parameters.has_key(self.host.login_field_name):
                self.host.post_parameters[self.host.login_field_name] = \
                    { 'enabled': True, 'value': _('(filled by users)'), 'immutable': True }
                self.host.store()
        except IndexError, e:
            self.host.login_field_name = None
            print 'Error handling login field : %s' % e

    def parse_password_field(self):
        '''Get password field name'''
        try:
            regexp = re.compile("""<input[^>]*?type=["']?password["']?[^>]*?>""", re.DOTALL | re.IGNORECASE)
            password_field = regexp.findall(self.host.auth_form)[0]
            regexp = re.compile("""name=["']?(.*?)["']?[\s/>]""", re.DOTALL | re.IGNORECASE)
            self.host.password_field_name = regexp.findall(password_field)[0]
            if not self.host.post_parameters.has_key(self.host.password_field_name):
                self.host.post_parameters[self.host.password_field_name] = \
                    { 'enabled': True, 'value': _('(filled by users)'), 'immutable': True }
        except IndexError, e:
            self.host.password_field_name = None
            print 'Error handling password field : %s' % e

    def parse_select_fields(self):
        '''Add select fields to host attributes'''
        # First added for Imuse (Rennes)
        regexp = re.compile("""<select.*?</select>""", re.DOTALL | re.IGNORECASE)
        self.host.select_fields = {}
        for field in regexp.findall(self.host.auth_form):
            try:
                regexp = re.compile("""name=["']?(.*?)["']?[\s/>]""", re.DOTALL | re.IGNORECASE)
                name = regexp.findall(field)[0]
                regexp = re.compile("""<option[^>]*?>.*?</option>""", re.DOTALL | re.IGNORECASE)
                options = regexp.findall(field)
                values = []
                for option in options:
                    regexp = re.compile("""<option[^>]*?>(.*?)</option>""", re.DOTALL | re.IGNORECASE)
                    option_label = regexp.findall(option)
                    regexp = re.compile("""value=["']?(.*?)["']?[\s/>]""", re.DOTALL | re.IGNORECASE)
                    option_value = regexp.findall(option)
                    if option_label:
                        if not option_value:
                            option_value = option_label
                        values.append((option_value[0], option_label[0]))
                    else:
                        print >> sys.stderr, 'W: Could not parse select options'
                self.host.select_fields[name] = values
                if not self.host.post_parameters.has_key(name):
                    self.host.post_parameters[name] = \
                        { 'enabled': True, 'value': _('(filled by users)'), 'immutable': True }
            except IndexError, e:
                continue

    def parse_other_fields(self):
        '''Get the default value of all other fields'''
        self.host.other_fields = {}

        # Get hidden fields
        regexp = re.compile("""<input[^>]*?type=["']?hidden["']?[^>]*?>""", re.DOTALL | re.IGNORECASE)
        other_fields = regexp.findall(self.host.auth_form)

        # Only get first submit field
        regexp = re.compile("""<input[^>]*?type=["']?submit["']?[^>]*?>""", re.DOTALL | re.IGNORECASE)
        found = regexp.findall(self.host.auth_form)
        if found:
            if other_fields:
                other_fields.append(found[0])
            else:
                other_fields = found[0]

        for field in other_fields:
            try:
                regexp = re.compile("""name=["']?(.*?)["']?[\s/>]""", re.DOTALL | re.IGNORECASE)
                name = regexp.findall(field)[0]
                regexp = re.compile("""value=["'](.*?)["'][\s/>]""", re.DOTALL | re.IGNORECASE)
                value = regexp.findall(field)[0]
                self.host.other_fields[name] = value
                if not self.host.post_parameters.has_key(name):
                    self.host.post_parameters[name] = { 'enabled': True, 'value': value, 'immutable': False }
            except IndexError, e:
                continue


class HostPage(Directory):
    _q_exports = ['', 'delete']

    def __init__(self, host_id):
        self.host = Host.get(host_id)
        get_response().breadcrumb.append((host_id + '/', self.host.label))

    def _q_lookup(self, component):
        if component == 'configuration_assistant':
            return ConfigurationAssistant(self.host)
        elif component == 'forms_prefill':
            return FormsDirectory(self.host)

    def _q_index [html] (self):
        get_publisher().reload_cfg()
        html_top('hosts', title = self.host.label)

        '<h2>%s</h2>' % _('Configuration assistant')

        '<dl>'

        '<dt><a href="configuration_assistant/start">%s</a></dt> <dd>%s</dd>' % (
                _('Address of the original site'), _('Configure the root address of the site'))

        '<dt><a href="configuration_assistant/check_new_address">%s</a></dt> <dd>%s</dd>' % (
                _('New address and name'), _('Configure the new address and name of this site'))

        '<dt><a href="configuration_assistant/authentication_and_logout_adresses">%s</a></dt> <dd>%s</dd>' % (
                _('Authentication and logout addresses'), _('Configure the authentication and logout addresses of the original site'))

        '<dt><a href="configuration_assistant/check_auto_detected_configuration">%s</a></dt> <dd>%s</dd>' % (
                _('Check auto detected configuration'), _('Check the automatically detected configuration is right'))

        '<dt><a href="configuration_assistant/credentials">%s</a></dt> <dd>%s</dd>' % (
                _('Credentials'), _('Configure some valid credentials to authenticate on the original site'))

        '<dt><a href="configuration_assistant/send_authentication_request">%s</a></dt> <dd>%s</dd>' % (
                _('Retry authentication'), _('Retry sending an authentication request to the site to check if your new parameters work well'))

        '<dt><a href="configuration_assistant/see_authentication_response">%s</a></dt> <dd>%s</dd>' % (
                _('Check authentication response'), _('Check the response from the latest authentication request'))

        '<dt><a href="configuration_assistant/authentication_success_criteria">%s</a></dt> <dd>%s</dd>' % (
                _('Configure authentication success criteria'), _('Specify how Larpe knows if the authentication has succeeded or not'))

        '<dt><a href="configuration_assistant/modify_authentication_request">%s</a></dt> <dd>%s</dd>' % (
                _('Modify authentication request'), _('Modify POST fields or HTTP headers of the authentication request'))

        '<dt><a href="configuration_assistant/sso_init_link">%s</a></dt> <dd>%s</dd>' % (
                _('Configure how a Single Sign On can be initiated'), _('Configure how a Single Sign On can be initiated'))

        '<dt><a href="configuration_assistant/metadatas">%s</a></dt> <dd>%s</dd>' % (
                _('Metadatas and key'), _('Download SAML 2.0 or ID-FF metadatas and SSL public key'))

        '<dt><a href="configuration_assistant/advanced_options">%s</a></dt> <dd>%s</dd>' % (
                _('Adavanced options'), _('Configure advanced options to setup the last details of your site'))

        '</dl>'

        '<h2>%s</h2>' % _('Form prefilling with ID-WSF')

        '<dl>'
        '<dt><a href="forms_prefill/">%s</a></dt> <dd>%s</dd>' % (
                _('Forms'), _('Configure the forms to prefill'))
        '</dl>'

    def delete [html] (self):
        form = Form(enctype='multipart/form-data')
        form.widgets.append(HtmlWidget('<p>%s</p>' % _(
                        'You are about to irrevocably delete this host.')))
        form.add_submit('submit', _('Submit'))
        form.add_submit('cancel', _('Cancel'))
        if form.get_widget('cancel').parse():
            return redirect('..')
        if not form.is_submitted() or form.has_errors():
            get_response().breadcrumb.append(('delete', _('Delete')))
            html_top('hosts', title = _('Delete Host'))
            '<h2>%s : %s</h2>' % (_('Delete Host'), self.host.label)
            form.render()
        else:
            self.host.remove_self()
            write_apache2_vhosts()
            return redirect('..')


class HostsDirectory(Directory):
    _q_exports = ['', 'new']

    def _q_index [html] (self):
        get_response().breadcrumb.append(('hosts/', _('Hosts')))
        html_top('hosts', title = _('Hosts'))
        """<ul id="nav-hosts-admin">
          <li><a href="new">%s</a></li>
        </ul>""" % _('New Host')

        '<ul class="biglist">'

        for host in Host.select(lambda x: x.name != 'larpe', order_by = 'label'):
            if not host.name:
                continue
            if not hasattr(host, str('scheme')):
                host.scheme = str('http')
            '<li>'
            '<strong class="label">%s</strong>' % host.label
            if hasattr(host, str('new_url')) and host.new_url:
                url = host.new_url
            else:
                # Compat with older Larpe versions
                url = '%s://%s%s/' % (host.scheme, host.reversed_hostname, get_request().environ['SCRIPT_NAME'])
                if host.reversed_directory is not None:
                    url += '%s/' % host.reversed_directory
            '<br /><a href="%s">%s</a>' % (url, url)
            '<p class="commands">'
            command_icon('%s/' % host.id, 'edit')
            command_icon('%s/delete' % host.id, 'remove')
            '</p></li>'
        '</ul>'

    def new [html] (self):
        if not os.path.isdir(os.path.join(get_publisher().app_dir, str('idp'))):
            html_top('hosts', title = _('New Host'))
            html = '<h2>%s</h2>' % _('New Host')
            html += 'You must <a href="%s/admin/settings/liberty_idp/">' % misc.get_root_url()
            html += 'configure an Identity Provider</a> first<br /><br />'
            html += '<a href="."><input type="button" value="%s" /></a>' % _('Back')
            return html

        get_response().breadcrumb.append(('hosts/', _('Hosts')))
        get_response().breadcrumb.append(('new', _('New')) )
        host = Host()
        host.store()
        return redirect('%s/configuration_assistant/start' % host.id)

    def _q_lookup(self, component):
        get_response().breadcrumb.append(('hosts/', _('Hosts')))
        return HostPage(component)

