diff --git a/modules/webaccess/lib/access_control_variables.py.wml b/modules/webaccess/lib/access_control_variables.py.wml
new file mode 100644
index 000000000..614b1224a
--- /dev/null
+++ b/modules/webaccess/lib/access_control_variables.py.wml
@@ -0,0 +1,38 @@
+## $Id$
+## CDSware Access Control Variables in mod_python.
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002 CERN.
+##
+## The CDSware is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 2 of the
+## License, or (at your option) any later version.
+##
+## The CDSware is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+"""CDSware Access Control Variables. """
+
+<protect> ## okay, rest of the Python code goes below #######
+
+__version__ = "$Id$"
+
+# VALUES TO BE EXPORTED
+# CURRENTLY USED BY THE FILES access_control_engine.py access_control_admin.py webaccessadmin_lib.py
+
+# name of the role giving superadmin rights
+SUPERADMINROLE      = 'superadmin'
+# name of the action allowing roles to access the web administrator interface
+WEBACCESSACTION     = 'accesswebadmin'
+# name of the action allowing roles to delegate the rights to other roles
+# ex: libraryadmin to delegate libraryworker
+DELEGATEADDUSERROLE = 'delegate_adduserrole'
+
+</protect>
diff --git a/modules/webaccess/lib/webaccessadmin_lib.py b/modules/webaccess/lib/webaccessadmin_lib.py
new file mode 100644
index 000000000..723c49136
--- /dev/null
+++ b/modules/webaccess/lib/webaccessadmin_lib.py
@@ -0,0 +1,2537 @@
+## $Id$
+## Administrator interface for WebAccess
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002 CERN.
+##
+## The CDSware is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 2 of the
+## License, or (at your option) any later version.
+##
+## The CDSware is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.  
+##
+## You should have received a copy of the GNU General Public License
+## along with CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+## read config variables:
+#include "config.wml"
+#include "configbis.wml"
+
+<protect>## $Id$</protect>
+<protect>## DO NOT EDIT THIS FILE!  IT WAS AUTOMATICALLY GENERATED FROM CDSware WML SOURCES.</protect>
+"""CDSware WebAccess Administrator Interface."""
+
+__lastupdated__ = """<: print `date +"%d %b %Y %H:%M:%S %Z"`; :>"""
+
+## fill config variables:
+pylibdir = "<LIBDIR>/python"
+
+try:
+    import sys
+    sys.path.append('%s' % pylibdir)
+    import cdsware.access_control_engine as acce
+    import cdsware.access_control_admin as acca
+    reload(acce)
+    reload(acca)
+    import cgi
+    import re
+    
+    from cdsware.dbquery import run_sql
+    from cdsware.access_control_variables import SUPERADMINROLE, WEBACCESSACTION, DELEGATEADDUSERROLE
+    from cdsware.config import *
+    from cdsware.webpage import page, pageheaderonly, pagefooteronly
+    from cdsware.webuser import getUid, get_email
+    from mod_python import apache
+except ImportError, e:
+    print "Error: %s" % e
+    import sys
+    sys.exit(1)
+
+__version__ = "$Id$"
+
+
+def index(req, title='', body='', subtitle='', authorized=0):
+    """main function to show pages for webaccessadmin.
+
+    1. if user not logged in and administrator, show the mustlogin page
+
+    2. if used without body argument, show the startpage
+
+    3. show admin page with title, body, subtitle and navtrail.
+
+    authorized - if 1, don't check if the user is allowed to be webadmin """
+    
+    # navtrail_previous_links="""<a class=navtrail href=<WEBURL>/hacking/>Hacking CDSware</a> &gt;
+    # <a class=navtrail href=<WEBURL>/hacking/webaccess/index.html>WebAccess Internals</a> &gt;
+    # <a class=navtrail href=<WEBURL>/admin/webaccess/>Access Control Admin</a> &gt; """
+    navtrail_previous_links = """<a class=navtrail href="<WEBURL>/admin/">Admin Area</a> &gt; <a class=navtrail href="<WEBURL>/admin/webaccess/">WebAccess Admin</a> """
+    
+    if body and not authorized: navtrail_previous_links += '&gt; <a class=navtrail href=<WEBURL>/admin/webaccess/webaccessadmin.py>Manage WebAccess</a>'
+    
+    id_user = getUid(req)
+
+    if not authorized and not is_adminuser(req): return mustloginpage(req)
+    
+    elif not body:
+        title = 'Manage WebAccess'
+        body = startpage()
+    elif type(body) != str: body = addadminbox(subtitle, datalist=body)
+
+    return page(title=title,
+                uid=id_user,
+                body=body,
+                navtrail=navtrail_previous_links,
+                lastupdated=__lastupdated__)                
+
+
+def mustloginpage(req):
+    """show a page asking the user to login."""
+    
+    # navtrail_previous_links="""<a class=navtrail href=<WEBURL>/hacking/>Hacking CDSware</a> &gt;
+    # <a class=navtrail href=<WEBURL>/hacking/webaccess/index.html>WebAccess Internals</a> &gt;
+    # <a class=navtrail href=<WEBURL>/admin/webaccess/>Access Control Admin Area</a>"""
+    navtrail_previous_links = """<a class=navtrail href="<WEBURL>/admin/">Admin Area</a> &gt; <a class=navtrail href="<WEBURL>/admin/webaccess/">WebAccess Admin</a> &gt; """
+
+    return page(title='Authorization failure',
+                uid=getUid(req),
+                body=adderrorbox('try to login first',
+                                 datalist=["""You are not a user authorized to perform admin tasks, try to
+                                 <a href="http://cdsdev.cern.ch:8000/DEMODEV/youraccount.py/login">login</a>."""]),
+                navtrail=navtrail_previous_links,
+                lastupdated=__lastupdated__)                
+
+    
+def is_adminuser(req):
+    """check if user is a registered administrator. """
+
+    id_user = getUid(req)
+    return acce.acc_authorize_action(id_user, WEBACCESSACTION)
+     
+
+def perform_rolearea(req):
+    """create the role area menu page."""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    header = ['id', 'name', 'description', 'users', 'authorizations / actions', 'role', '']
+    roles = acca.acc_getAllRoles()
+
+    roles2 = []
+    for (id, name, desc) in roles:
+        if len(desc) > 30: desc = desc[:30] + '...'
+        roles2.append([id, name, desc])
+        for col in [(('add', 'adduserrole'),
+                     ('remove', 'deleteuserrole')),
+                    (('add', 'addauthorization'),
+                     ('modify', 'modifyauthorizations'),
+                     ('remove', 'deleteroleaction')),
+                    (('delete', 'deleterole'), ),
+                    (('show details', 'showroledetails'), )]:
+            roles2[-1].append('<a href="%s?id_role=%s">%s</a>' % (col[0][1], id, col[0][0]))
+            for (str, function) in col[1:]:
+                roles2[-1][-1] += ' / <a href="%s?id_role=%s">%s</a>' % (function, id, str)
+
+    output  = """
+    <dl>
+     <dt>Users:</dt>
+     <dd>add or remove users from the access to a role and its priviliges.</dd>
+     <dt>Authorizations/Actions:</dt>
+     <dd>these terms means almost the same, but an authorization is a <br>
+         connection between a role and an action (possibly) containing arguments.</dd>
+     <dt>Roles:</dt>
+     <dd>see all the information attached to a role and decide if you want to<br>delete it.</dd>
+    </dl>
+    """
+    
+    output += tupletotable(header=header, tuple=roles2)
+
+    extra = """
+    <dl>
+     <dt><a href="addrole">Add new role</a></dt>
+     <dd>go here to add a new role.</dd>
+     <dt><a href="addaction">Add new action</a></dt>
+     <dd>go here to add a new action.</dd>
+    </dl>
+    """
+
+    return index(req=req,
+                 title='Role Administration',
+                 subtitle='administration with roles as access point',
+                 body=[output, extra])
+
+
+def perform_actionarea(req):
+    """create the action area menu page."""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    header = ['id', 'name', 'authorizations/roles', 'action', '']
+    actions = acca.acc_getAllActions()
+
+    actions2 = []
+    roles2 = []
+    for (id, name, dontcare) in actions:
+        actions2.append([id, name])
+        for col in [(('add', 'addauthorization'),
+                     ('modify', 'modifyauthorizations'),
+                     ('remove', 'deleteroleaction')),
+                    (('delete', 'deleteaction'), ),
+                    (('show details', 'showactiondetails'), )]:
+            actions2[-1].append('<a href="%s?id_action=%s&amp;reverse=1">%s</a>' % (col[0][1], id, col[0][0]))
+            for (str, function) in col[1:]:
+                actions2[-1][-1] += ' / <a href="%s?id_action=%s&amp;reverse=1">%s</a>' % (function, id, str)
+
+    output  = """
+    <dl>
+     <dt>Authorizations/Roles:</dt>
+     <dd>these terms means almost the same, but an authorization is a <br>
+         connection between a role and an action (possibly) containing arguments.</dd>
+     <dt>Actions:</dt>
+     <dd>see all the information attached to an action and decide if you want to<br>delete it.</dd>
+    </dl>
+    """
+    
+    output += tupletotable(header=header, tuple=actions2)
+
+    extra = """
+    <dl>
+     <dt><a href="addrole">Add new role</a>
+     <dd>go here to add a new role.
+     <dt><a href="addaction">Add new action</a>
+     <dd>go here to add a new action.
+    </dl>
+    """
+
+    return index(req=req,
+                 title='Action Administration',
+                 subtitle='administration with actions as access point',
+                 body=[output, extra])
+
+
+def perform_userarea(req, email_user_pattern=''):
+    """create area to show info about users. """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    subtitle = 'step 1 - search for users'
+
+    output = """
+    <p>
+     search for users to display. 
+    </p> """
+
+    # remove letters not allowed in an email
+    email_user_pattern = cleanstring_email(email_user_pattern)
+        
+    text  = ' <span class="adminlabel">1. search pattern </span>\n'
+    text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, )
+
+    output += createhiddenform(action="userarea",
+                               text=text,
+                               button="search for users")
+
+    if email_user_pattern:
+        users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id LIMIT 26""" % (email_user_pattern, ))
+
+        if not users1:
+            output += '<p>no matching users</p>'
+        else: 
+            subtitle = 'step 2 - select what to do with user'
+
+            users = []
+            for (id, email) in users1[:25]:
+                users.append([id, email])
+                for col in [(('add', 'addroleuser'),
+                             ('remove', 'deleteuserrole')),
+                            (('show details', 'showuserdetails'), )]:
+                    users[-1].append('<a href="%s?email_user_pattern=%s&amp;id_user=%s">%s</a>' % (col[0][1], email_user_pattern, id, col[0][0]))
+                    for (str, function) in col[1:]:
+                        users[-1][-1] += ' / <a href="%s?email_user_pattern=%s&amp;id_user=%s&amp;reverse=1">%s</a>' % (function, email_user_pattern, id, str)
+    
+            output += '<p>found <strong>%s</strong> matching users</p>' % (len(users1), )
+            output += tupletotable(header=['id', 'email', 'roles', ''], tuple=users)
+
+            if len(users1) > 25:
+                output += '<p><strong>only showing the first 25 users, narrow your search...</strong></p>'
+
+    return index(req=req,
+                 title='User Administration',
+                 subtitle=subtitle,
+                 body=[output])
+
+
+def perform_resetarea(req):
+    """create the reset area menu page."""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    output = """
+    <dl>
+     <dt><a href="resetdefaultsettings">Reset to Default Authorizations</a>
+     <dd>Remove all changes that has been done to the roles and <br>
+     add only the default authorization settings.
+     <dt><a href="adddefaultsettings">Add Default Authorizations</a>
+     <dd>Keep all changes and add the default authorization settings.
+    </dl>
+    """
+
+    return index(req=req,
+                 title='Reset Authorizations',
+                 subtitle='reseting to or adding default authorizations',
+                 body=[output])
+
+
+def perform_resetdefaultsettings(req, superusers=[], confirm=0):
+    """delete all roles, actions and authorizations presently in the database
+    and add only the default roles.
+    only selected users will be added to superadmin, rest is blank """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    # cleaning input
+    if type(superusers) == str: superusers = [superusers]
+
+    # remove not valid e-mails
+    for email in superusers:
+        if not check_email(email): superusers.remove(email)
+    
+    # instructions
+    output  = """
+    <p>
+     before you reset the settings, we need some users<br>
+     to connect to <strong>%s</strong>.<br>
+     enter as many e-mail adresses you want and press <strong>reset</strong>.<br>
+     <strong>confirm reset settings</strong> when you have added enough e-mails.<br>
+     <strong><SUPPORTEMAIL></strong> is added as default.
+    </p>""" % (SUPERADMINROLE, )
+
+    # add more superusers
+    output += """
+    <p>enter user e-mail addresses: </p>
+    <form action="resetdefaultsettings" method="POST">"""
+
+    for email in superusers:
+        output += '      <input type="hidden" name="superusers" value="%s" />' % (email, )
+
+    output += """
+     <span class="adminlabel">e-mail</span>
+     <input class="admin_wvar" type="text" name="superusers" />
+     <input class="adminbutton" type="submit" value="add e-mail" />
+    </form>"""
+
+
+    if superusers:
+        # remove emails
+        output += """
+        <form action="resetdefaultsettings" method="POST">
+         have you entered wrong data? 
+         <input class="adminbutton" type="submit" value="remove all e-mails" />
+        </form>
+        """
+        
+        # superusers confirm table
+        start = '<form action="resetdefaultsettings" method="POST">'
+    
+        extra  = ' <input type="hidden" name="confirm" value="1" />'
+        for email in superusers:
+            extra += '<input type="hidden" name="superusers" value="%s" />' % (email, )
+        extra += ' <input class="adminbutton" type="submit" value="confirm to reset settings" />'
+    
+        end    = '</form>'
+    
+        output += '<p><strong>reset default settings</strong> with the users below? </p>'
+        output += tupletotable(header=['e-mail address'],
+                               tuple=superusers,
+                               start=start,
+                               extracolumn=extra,
+                               end=end)
+        
+        if confirm in [1, "1"]:
+            res = acca.acc_reset_default_settings(superusers)
+            if res:
+                  output += '<p>successfully reset default settings</p>'
+            else:
+                  output += '<p>sorry, could not reset default settings</p>'
+    
+    return index(req=req,
+                 title='Reset Default Settings',
+                 subtitle='reset settings',
+                 body=[output])
+
+
+def perform_adddefaultsettings(req, superusers=[], confirm=0):
+    """add the default settings, and keep everything else.
+    probably nothing will be deleted, except if there has been made changes to the defaults."""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    # cleaning input
+    if type(superusers) == str: superusers = [superusers]
+    
+    # remove not valid e-mails
+    for email in superusers:
+        if not check_email(email): superusers.remove(email)
+    
+    # instructions
+    output  = """
+    <p>
+     before you add the settings, we need some users<br>
+     to connect to <strong>%s</strong>.<br>
+     enter as many e-mail adresses you want and press <strong>add</strong>.<br>
+     <strong>confirm add settings</strong> when you have added enough e-mails.<br>
+     <strong><SUPPORTEMAIL></strong> is added as default.
+    </p>""" % (SUPERADMINROLE, )
+
+    # add more superusers
+    output += """
+    <p>enter user e-mail addresses: </p>
+    <form action="adddefaultsettings" method="POST">"""
+
+    for email in superusers:
+        output += '      <input type="hidden" name="superusers" value="%s" />' % (email, )
+
+    output += """
+     <span class="adminlabel">e-mail</span>
+     <input class="admin_wvar" type="text" name="superusers" />
+     <input class="adminbutton" type="submit" value="add e-mail" />
+    </form>
+    """
+
+    if superusers:
+        # remove emails
+        output += """
+        <form action="adddefaultsettings" method="POST">
+         have you entered wrong data? 
+         <input class="adminbutton" type="submit" value="remove all e-mails" />
+        </form>
+        """
+        
+        # superusers confirm table
+        start = '<form action="adddefaultsettings" method="POST">'
+    
+        extra  = ' <input type="hidden" name="confirm" value="1" />'
+        for email in superusers:
+            extra += '<input type="hidden" name="superusers" value="%s" />' % (email, )
+        extra += ' <input class="adminbutton" type="submit" value="confirm to add settings" />'
+    
+        end    = '</form>'
+    
+        output += '<p><strong>add default settings</strong> with the users below? </p>'
+        output += tupletotable(header=['e-mail address'],
+                               tuple=superusers,
+                               start=start,
+                               extracolumn=extra,
+                               end=end)
+
+        if confirm in [1, "1"]:
+            res = acca.acc_add_default_settings(superusers)
+            if res:
+                  output += '<p>successfully added default settings</p>'
+            else:
+                  output += '<p>sorry, could not add default settings</p>'
+    
+    return index(req=req,
+                 title='Add Default Settings',
+                 subtitle='add settings',
+                 body=[output])
+
+
+def perform_delegate_startarea(req):
+    """start area for lower level delegation of rights."""
+
+    subtitle = 'select what to do'
+
+    output = ''
+    
+    if is_adminuser(req):
+        output += """
+        <p>
+         You are also allowed to be in the <a href="../webaccessadmin.py">Main Admin Area</a> which gives you<br>
+         the access to the full functionality of WebAccess.
+        </p>
+        """
+
+    output += """
+    <dl>
+     <dt><a href="delegate_adduserrole">Add users to roles</a>
+     <dd>add users to the roles you have delegation rights to.
+     <dt><a href="delegate_deleteuserrole">Remove users from roles</a>
+     <dd>remove users from the roles you have delegation rights to.
+    </dl>
+    """
+        
+    return index(req=req,
+                 title='Delegate Rights - start area',
+                 subtitle=subtitle, 
+                 body=[output],
+                 authorized=1)
+
+
+def perform_delegate_adduserrole(req, id_role=0, email_user_pattern='', id_user=0, confirm=0):
+    """let a lower level web admin add users to a limited set of roles.
+
+    id_role - the role to connect to a user
+
+    id_user - the user to connect to a role
+
+    confirm - make the connection happen """
+
+    # finding the allowed roles for this user
+    id_admin = getUid(req)
+    id_action = acca.acc_getActionId(name_action=DELEGATEADDUSERROLE) 
+    actions = acca.acc_findPossibleActionsUser(id_user=id_admin, id_action=id_action)
+
+    allowed_roles = []
+    for (id, arglistid, name_role_help) in actions[1:]:
+        id_role_help = acca.acc_getRoleId(name_role=name_role_help)
+        if id_role_help and [id_role_help, name_role_help, ''] not in allowed_roles:
+            allowed_roles.append([id_role_help, name_role_help, ''])
+        
+    output = ''
+
+    if not allowed_roles:
+        subtitle = 'no delegation rights'
+        output += """
+        <p>
+         You do not have the delegation rights over any roles.<br>
+         If you think you should have such rights, contact a WebAccess Administrator.
+        </p>"""
+    else:
+        subtitle = 'step 1 - select role'
+
+        output += """
+        <p>
+         Lower level delegation of access rights to roles.<br>
+         An administrator with all rights have to give you these rights.
+        </p>"""
+
+        email_out = acca.acc_getUserEmail(id_user=id_user)
+        name_role = acca.acc_getRoleName(id_role=id_role)
+
+        output += createroleselect(id_role=id_role, step=1, name='id_role',
+                                   action='delegate_adduserrole', roles=allowed_roles)
+
+        if str(id_role) != '0':
+            subtitle = 'step 2 - search for users'
+
+            # remove letters not allowed in an email
+            email_user_pattern = cleanstring_email(email_user_pattern)
+                
+            text  = ' <span class="adminlabel">2. search pattern </span>\n'
+            text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, )
+    
+            output += createhiddenform(action="delegate_adduserrole",
+                                       text=text,
+                                       button="search for users",
+                                       id_role=id_role)
+    
+            # pattern is entered
+            if email_user_pattern:
+                # users with matching email-address
+                users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id """ % (email_user_pattern, ))
+                # users that are connected
+                users2 = run_sql("""SELECT DISTINCT u.id, u.email
+                FROM user u LEFT JOIN user_accROLE ur ON u.id = ur.id_user
+                WHERE ur.id_accROLE = '%s' AND u.email RLIKE '%s'
+                ORDER BY u.id """ % (id_role, email_user_pattern))
+    
+                # no users that match the pattern
+                if not (users1 or users2):
+                    output += 'no qualified users, try new search'
+                # show matching users
+                else:
+                    subtitle = 'step 3 - select a user'
+                    
+                    users = []
+                    extrausers = []
+                    for (id, email) in users1:
+                        if (id, email) not in users2: users.append([id,email,''])
+                    for (id, email) in users2:
+                        extrausers.append([-id, email,''])
+    
+                    output += createuserselect(id_user=id_user,
+                                               action="delegate_adduserrole",
+                                               step=3,
+                                               users=users,
+                                               extrausers=extrausers,
+                                               button="add this user",
+                                               id_role=id_role,
+                                               email_user_pattern=email_user_pattern)
+    
+                    try: id_user = int(id_user)
+                    except ValueError: pass
+                    # user selected already connected to role
+                    if id_user < 0:
+                        output += '<p>users in brackets are already attached to the role, try another one</p>'
+                    # a user is selected
+                    elif email_out:
+                        subtitle = "step 4 - confirm to add user"
+    
+                        output += createhiddenform(action="delegate_adduserrole",
+                                                   text='add user <strong>%s</strong> to role <strong>%s</strong>?' % (email_out, name_role),
+                                                   id_role=id_role,
+                                                   email_user_pattern=email_user_pattern,
+                                                   id_user=id_user,
+                                                   confirm=1)
+    
+                        # it is confirmed that this user should be added
+                        if confirm:
+                            # add user
+                            result = acca.acc_addUserRole(id_user=id_user, id_role=id_role)
+            
+                            if result and result[2]: 
+                                subtitle = 'step 5 - confirm user added'
+                                output  += '<p>confirm: user <strong>%s</strong> added to role <strong>%s</strong>.</p>' % (email_out, name_role)
+                            else:
+                                subtitle = 'step 5 - user could not be added'
+                                output += '<p>sorry, but user could not be added.</p>'
+                
+    return index(req=req,
+                 title='Delegate Rights - add users to roles',
+                 subtitle=subtitle, 
+                 body=[output],
+                 authorized=1)
+
+
+def perform_delegate_deleteuserrole(req, id_role=0, id_user=0, confirm=0):
+    """let a lower level web admin remove users from a limited set of roles.
+
+    id_role - the role to connect to a user
+
+    id_user - the user to connect to a role
+
+    confirm - make the connection happen """
+
+    subtitle = 'in progress...'
+
+    output = '<p>in progress...</p>'
+
+    # finding the allowed roles for this user
+    id_admin = getUid(req)
+    id_action = acca.acc_getActionId(name_action=DELEGATEADDUSERROLE)
+    actions = acca.acc_findPossibleActionsUser(id_user=id_admin, id_action=id_action)
+
+    output = ''
+
+    if not actions:
+        subtitle = 'no delegation rights'
+        output += """
+        <p>
+         You do not have the delegation rights over any roles.<br>
+         If you think you should have such rights, contact a WebAccess Administrator.
+        </p>"""
+    else:
+        subtitle = 'step 1 - select role'
+
+        output += """
+        <p>
+         Lower level delegation of access rights to roles.<br>
+         An administrator with all rights have to give you these rights.
+        </p>"""
+
+        email_out = acca.acc_getUserEmail(id_user=id_user)
+        name_role = acca.acc_getRoleName(id_role=id_role)
+
+        allowed_roles = []
+        for (id, arglistid, name_role_help) in actions[1:]:
+            id_role_help = acca.acc_getRoleId(name_role=name_role_help)
+            if id_role_help and [id_role_help, name_role_help, ''] not in allowed_roles:
+                allowed_roles.append([id_role_help, name_role_help, ''])
+        
+        output += createroleselect(id_role=id_role, step=1,
+                                   action='delegate_deleteuserrole', roles=allowed_roles)
+
+        if str(id_role) != '0':
+            subtitle = 'step 2 - select user'
+            
+            users = acca.acc_getRoleUsers(id_role)
+
+            output += createuserselect(id_user=id_user, step=2,
+                                       action='delegate_deleteuserrole', users=users,
+                                       id_role=id_role)
+
+            if str(id_user) != '0':
+                subtitle = 'step 3 - confirm delete of user'
+                email_user = acca.acc_getUserEmail(id_user=id_user)
+                
+                output += createhiddenform(action="delegate_deleteuserrole",
+                                           text='delete user %s from %s?'
+                                           % (headerstrong(user=id_user), headerstrong(role=id_role)),
+                                           id_role=id_role,
+                                           id_user=id_user,
+                                           confirm=1)
+        
+                if confirm:
+                    res = acca.acc_deleteUserRole(id_user=id_user, id_role=id_role)
+                    if res:
+                        subtitle = 'step 4 - confirm user deleted from role'
+                        output += '<p>confirm: deleted user <strong>%s</strong> from role <strong>%s</strong>.</p>' % (email_user, name_role)
+                    else:
+                        subtitle = 'step 4 - user could not be deleted'
+                        output += 'sorry, but user could not be deleted<br>user is probably already deleted.'
+
+    return index(req=req,
+                 title='Delegate Rights - remove users from roles',
+                 subtitle=subtitle, 
+                 body=[output],
+                 authorized=1)
+
+
+def perform_addaction(req, name_action='', arguments='', optional='no', description='put description here.', confirm=0):
+    """form to add a new action with these values:
+
+    name_action - name of the new action
+
+      arguments - allowedkeywords, separated by whitespace
+
+    description - optional description of the action"""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    name_action = cleanstring(name_action)
+    arguments = cleanstring(arguments, comma=1)
+
+    title = 'Add Action'
+    subtitle = 'step 1 - give values to the requested fields'
+
+    output  = """
+    <form action="addaction" method="POST">
+     <span class="adminlabel">action name </span>
+     <input class="admin_wvar" type="text" name="name_action" value="%s" /> <br> 
+     <span class="adminlabel">arguments </span>
+     <input class="admin_wvar" type="text" name="arguments" value="%s" /> 
+     <small>keywords for arguments, separate with comma, no whitespace.</small> <br>
+     <span class="adminlabel">optional arguments</span>
+     <select name="optional" class="admin_w200">
+      <option value="no" selected="selected">no, not allowed</option>
+      <option value="yes" %s>yes, allowed</option>
+     </select><br>
+     <span class="adminlabel">description </span>
+     <textarea class="admin_wvar" rows="6" cols="30" name="description">%s</textarea> 
+     <input class="adminbutton" type="submit" value="add action" />
+    </form>
+    """ % (name_action, arguments, optional == 'yes' and 'selected="selected"' or '', description)
+
+    if name_action:
+        # description must be changed before it is submitted
+        if description == 'put description here.': internaldesc = ''
+        else: internaldesc = description
+        
+        if arguments:
+            subtitle = 'step 2 - confirm to add action with %s arguments' % (optional == 'yes' and 'optional' or '', )
+            arguments = arguments.replace(' ', '')
+            text  = 'add action with: <br>\n'
+            text += 'name: <strong>%s</strong><br>\n' % (name_action, )
+            if internaldesc:
+                text += 'description: <strong>%s</strong><br>\n' % (description, )
+            text += '%sarguments: <strong>%s</strong><br>' % (optional == 'yes' and 'optional ' or '', arguments)
+            text += 'optional: <strong>%s</strong>?' % (optional, )
+        
+        else:
+            optional = 'no'
+            subtitle = 'step 2 - confirm to add action without arguments'
+            text = 'add action <strong>%s</strong> without arguments' % (name_action, )
+            if internaldesc: text += '<br>\nand description: <strong>%s</strong>?\n' % (description, )
+            else: text += '?\n'
+            
+        output += createhiddenform(action="addaction",
+                                   text=text,
+                                   name_action=name_action,
+                                   arguments=arguments,
+                                   optional=optional, 
+                                   description=description,
+                                   confirm=1)
+
+        if confirm not in ["0", 0]:
+            arguments = arguments.split(',')
+            result = acca.acc_addAction(name_action,
+                                        internaldesc,
+                                        optional,
+                                        *arguments)
+
+            if result:
+                subtitle = 'step 3 - action added'
+                output += '<p>action added:</p>'
+                output += tupletotable(header=['id', 'action name', 'description', 'allowedkeywords', 'optional'],
+                                      tuple=[result])
+            else:
+                subtitle = 'step 3 - action could not be added'
+                output += '<p>sorry, could not add action, <br>action with the same name probably exists.</p>'
+                
+            extra = """
+            <dl>
+             <dt><a href="addauthorization?id_action=%s&amp;reverse=1">Add authorization</a></dt>
+             <dd>start adding new authorizations to this action.</dd>
+            </dl> """ % (acca.acc_getActionId(name_action=name_action, ))
+
+    try: body = [output, extra]
+    except NameError: body = [output]
+
+    return index(req=req,
+                 title=title,
+                 body=body,
+                 subtitle=subtitle)
+
+
+def perform_deleteaction(req, id_action="0", confirm=0):
+    """show all roles connected, and ask for confirmation.
+
+    id_action - id of action to delete """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    title='Delete Action'
+    subtitle='step 1 - select action to delete'
+    name_action = acca.acc_getActionName(id_action=id_action)
+
+    output = createactionselect(id_action=id_action,
+                                action="deleteaction",
+                                step=1,
+                                actions=acca.acc_getAllActions(),
+                                button="delete action")
+
+    if id_action != "0":
+        subtitle = 'step 2 - confirm the delete'
+
+        output += actiondetails(id_action=id_action)
+
+        if acca.acc_getActionRoles(id_action=id_action):
+            output += createhiddenform(action="deleteroleaction",
+                                       text="""rather delete only connection between this action
+                                       and a selected role?""",
+                                       id_action=id_action,
+                                       reverse=1,
+                                       button='go there')
+        
+        output += createhiddenform(action="deleteaction",
+                                   text=' delete action <strong>%s</strong> and all connections?' % (name_action, ),
+                                   confirm=1,
+                                   id_action=id_action)
+        
+    if confirm:
+        subtitle = 'step 3 - confirm delete of action'
+        res = acca.acc_deleteAction(id_action=id_action)
+        if res:
+            output += '<p>confirm: action <strong>%s</strong> deleted.<br>\n' % (name_action, )
+            output += '%s entries deleted all in all.</p>\n' % (res, )
+        else:
+            output += '<p>sorry, action could not be deleted.</p>\n'
+    
+    return index(req=req,
+                 title=title,
+                 subtitle=subtitle,
+                 body=[output])
+
+
+def perform_showactiondetails(req, id_action):
+    """show the details of an action. """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    if id_action not in [0, '0']:
+        output = actiondetails(id_action=id_action)
+
+        extra = """
+        <dl>
+         <dt><a href="addauthorization?id_action=%s&amp;reverse=1">Add new authorization</a></dt>
+         <dd>add an authorization.</dd>
+         <dt><a href="modifyauthorizations?id_action=%s&amp;reverse=1">Modify authorizations</a></dt>
+         <dd>modify existing authorizations.</dd>
+        </dl>
+        """ % (id_action, id_action)
+        body = [output, extra]
+        
+    else:
+        body = ['<p>no details to show</p>']
+
+    return index(req=req,
+                 title='Show Action Details',
+                 subtitle='show action details',
+                 body=body)
+
+
+def actiondetails(id_action=0):
+    """show details of given action. """
+
+    output = ''
+
+    if id_action not in [0, '0']:
+        name_action = acca.acc_getActionName(id_action=id_action)
+
+        output += '<p>action details:</p>'
+        output += tupletotable(header=['id', 'name', 'description', 'allowedkeywords', 'optional'],
+                               tuple=[acca.acc_getActionDetails(id_action=id_action)])
+    
+        roleshlp = acca.acc_getActionRoles(id_action=id_action)
+        if roleshlp: 
+            roles = []
+            for (id, name, dontcare) in roleshlp:
+                roles.append([id, name,
+                              '<a href="simpleauthorization?id_role=%s&amp;id_action=%s">show authorization details</a>'
+                              % (id, id_action),
+                              '<a href="simpleroleusers?id_role=%s">show connected users</a>' % (id, )])
+            roletable = tupletotable(header=['id', 'name', '', ''], tuple=roles)
+            
+            output += '<p>roles connected to %s:</p>\n' % (headerstrong(action=name_action, query=0), )
+            output += roletable
+    
+        else:
+            output += '<p>no roles connected to %s.</p>\n' % (headerstrong(action=name_action, query=0), )
+
+    else:
+        output += '<p>no details to show</p>'
+    
+    return output
+
+
+def perform_addrole(req, name_role='', description='put description here.', confirm=0):
+    """form to add a new role with these values:
+    
+      name_role - name of the new role
+
+    description - optional description of the role """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    name_role = cleanstring(name_role)
+
+    title='Add Role'
+    subtitle = 'step 1 - give values to the requested fields'
+
+    output = """
+    <form action="addrole" method="POST">
+     <span class="adminlabel">role name </span>
+     <input class="admin_wvar" type="text" name="name_role" value="%s" /> <br>
+     <span class="adminlabel">description </span>
+     <textarea class="admin_wvar" rows="6" cols="30" name="description">%s</textarea>
+     <input class="adminbutton" type="submit" value="add role" />
+    </form>
+    """ % (name_role, description)
+    
+    if name_role:
+        # description must be changed before submitting
+        subtitle = 'step 2 - confirm to add role'
+        internaldesc = ''
+        if description != 'put description here.':
+            internaldesc = description
+            
+        text = """
+        add role with: <br>\n
+        name: <strong>%s</strong> <br>""" % (name_role, )
+        if internaldesc:
+            text += 'description: <strong>%s</strong>?\n' % (description, )
+            
+        output += createhiddenform(action="addrole",
+                                   text=text,
+                                   name_role=name_role,
+                                   description=description,
+                                   confirm=1)
+        
+        if confirm not in ["0", 0]:
+            result = acca.acc_addRole(name_role=name_role,
+                                      description=internaldesc)
+            
+            if result:
+                subtitle = 'step 3 - role added'
+                output += '<p>role added: </p>'
+                output += tupletotable(header=['id', 'action name', 'description', 'allowedkeywords'],
+                                       tuple=[result])
+            else:
+                subtitle = 'step 3 - role could not be added'
+                output += '<p>sorry, could not add role, <br>role with the same name probably exists.</p>'
+
+            extra = """
+            <dl>
+             <dt><a href="addauthorization?id_role=%s">Add authorization</a></dt>
+             <dd>start adding new authorizations to this role.</dd>
+            </dl> """ % (acca.acc_getRoleId(name_role=name_role), )
+
+    try: body = [output, extra]
+    except NameError: body = [output]
+
+    return index(req=req,
+                 title=title,
+                 body=body,
+                 subtitle=subtitle)
+
+
+def perform_deleterole(req, id_role="0", confirm=0):
+    """select a role and show all connected information,
+
+      users - users that can access the role.
+
+    actions - actions with possible authorizations."""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    title = 'Delete role'
+    subtitle = 'step 1 - select role to delete'
+    name_role = id_role
+
+    name_role = acca.acc_getRoleName(id_role=id_role)
+    output = createroleselect(id_role=id_role,
+                              action="deleterole",
+                              step=1,
+                              roles=acca.acc_getAllRoles(),
+                              button="delete role")
+
+    if id_role != "0":
+        subtitle = 'step 2 - confirm delete of role'
+
+        output += roledetails(id_role=id_role)
+
+        output += createhiddenform(action="deleterole",
+                                   text='delete role <strong>%s</strong> and all connections?' % (name_role, ),
+                                   id_role=id_role,
+                                   confirm=1)
+
+        if confirm:
+            res = acca.acc_deleteRole(id_role=id_role)
+            subtitle = 'step 3 - confirm role deleted'
+            if res:
+                output += "<p>confirm: role <strong>%s</strong> deleted.<br>" % (name_role, )
+                output += "<strong>%s</strong> entries were removed.</p>" % (res, )
+            else:
+                output += "<p>sorry, the role could not be deleted.</p>"
+
+    return index(req=req,
+                 title=title,
+                 subtitle=subtitle,                 
+                 body=[output])
+
+
+def perform_showroledetails(req, id_role):
+    """show the details of a role."""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    if id_role not in [0, '0']:
+        output = roledetails(id_role=id_role)
+            
+        extra = """
+        <dl>
+         <dt><a href="adduserrole?id_role=%s">Connect user</a></dt>
+         <dd>connect a user to the role.</dd>
+         <dt><a href="addauthorization?id_role=%s">Add new authorization</a></dt>
+         <dd>add an authorization.</dd>
+         <dt><a href="modifyauthorizations?id_role=%s">Modify authorizations</a></dt>
+         <dd>modify existing authorizations.</dd>
+        </dl>
+        """ % (id_role, id_role, id_role)
+        body = [output, extra]
+    
+    else:
+        body = ['<p>no details to show</p>']
+    
+    return index(req=req,
+                 title='Show Role Details',
+                 subtitle='show role details',
+                 body=body)
+
+
+def roledetails(id_role=0):
+    """create the string to show details about a role. """
+
+    name_role = acca.acc_getRoleName(id_role=id_role)
+
+    usershlp = acca.acc_getRoleUsers(id_role)
+    users = []
+    for (id, email, dontcare) in usershlp:
+        users.append([id, email, '<a href="showuserdetails?id_user=%s">show user details</a>' % (id, )])
+    usertable = tupletotable(header=['id', 'email'], tuple=users)
+    
+    actionshlp = acca.acc_getRoleActions(id_role)
+    actions = []
+    for (id, name, dontcare) in actionshlp:
+        actions.append([id, name,
+                        '<a href="showactiondetails?id_role=%s&amp;id_action=%s">show action details</a>' % (id_role, id),
+                        '<a href="simpleauthorization?id_role=%s&amp;id_action=%s">show authorization details</a>' % (id_role, id)])
+        
+    actiontable = tupletotable(header=['id', 'name', '', ''], tuple=actions)
+
+    # show role details
+    details  = '<p>role details:</p>'
+    details += tupletotable(header=['id', 'name', 'description'],
+                            tuple=[acca.acc_getRoleDetails(id_role=id_role)])
+
+    # show connected users
+    details += '<p>users connected to %s:</p>' % (headerstrong(role=name_role, query=0), )
+    if users: 
+        details += usertable
+    else:
+        details += '<p>no users connected.</p>'
+    # show connected authorizations
+    details += '<p>authorizations for %s:</p>' % (headerstrong(role=name_role, query=0), )
+    if actions: 
+        details += actiontable
+    else:
+        details += '<p>no authorizations connected</p>'
+
+    return details 
+
+
+
+def perform_adduserrole(req, id_role='0', email_user_pattern='', id_user='0', confirm=0):
+    """create connection between user and role.
+
+               id_role - id of the role to add user to
+
+    email_user_pattern - search for users using this pattern
+
+               id_user - id of user to add to the role. """
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    email_out = acca.acc_getUserEmail(id_user=id_user)
+    name_role = acca.acc_getRoleName(id_role=id_role)
+    
+    title = 'Add user to role '
+    subtitle = 'step 1 - select a role'
+
+    output = createroleselect(id_role=id_role,
+                              action="adduserrole",
+                              step=1,
+                              roles=acca.acc_getAllRoles())
+
+    # role is selected
+    if id_role != "0":
+        title += name_role
+        
+        subtitle = 'step 2 - search for users'
+
+        # remove letters not allowed in an email
+        email_user_pattern = cleanstring_email(email_user_pattern)
+            
+        text  = ' <span class="adminlabel">2. search pattern </span>\n'
+        text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, )
+
+        output += createhiddenform(action="adduserrole",
+                                   text=text,
+                                   button="search for users",
+                                   id_role=id_role)
+
+        # pattern is entered
+        if email_user_pattern:
+            # users with matching email-address
+            users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id """ % (email_user_pattern, ))
+            # users that are connected
+            users2 = run_sql("""SELECT DISTINCT u.id, u.email
+            FROM user u LEFT JOIN user_accROLE ur ON u.id = ur.id_user
+            WHERE ur.id_accROLE = '%s' AND u.email RLIKE '%s'
+            ORDER BY u.id """ % (id_role, email_user_pattern))
+
+            # no users that match the pattern
+            if not (users1 or users2):
+                output += 'no qualified users, try new search'
+            # show matching users
+            else:
+                subtitle = 'step 3 - select a user'
+                
+                users = []
+                extrausers = []
+                for (id, email) in users1:
+                    if (id, email) not in users2: users.append([id,email,''])
+                for (id, email) in users2:
+                    extrausers.append([-id, email,''])
+
+                output += createuserselect(id_user=id_user,
+                                           action="adduserrole",
+                                           step=3,
+                                           users=users,
+                                           extrausers=extrausers,
+                                           button="add this user",
+                                           id_role=id_role,
+                                           email_user_pattern=email_user_pattern)
+
+                try: id_user = int(id_user)
+                except ValueError: pass
+                # user selected already connected to role
+                if id_user < 0:
+                    output += '<p>users in brackets are already attached to the role, try another one</p>'
+                # a user is selected
+                elif email_out:
+                    subtitle = "step 4 - confirm to add user"
+
+                    output += createhiddenform(action="adduserrole",
+                                               text='add user <strong>%s</strong> to role <strong>%s</strong>?' % (email_out, name_role),
+                                               id_role=id_role,
+                                               email_user_pattern=email_user_pattern,
+                                               id_user=id_user,
+                                               confirm=1)
+
+                    # it is confirmed that this user should be added
+                    if confirm:
+                        # add user
+                        result = acca.acc_addUserRole(id_user=id_user, id_role=id_role)
+        
+                        if result and result[2]: 
+                            subtitle = 'step 5 - confirm user added'
+                            output  += '<p>confirm: user <strong>%s</strong> added to role <strong>%s</strong>.</p>' % (email_out, name_role)
+                        else:
+                            subtitle = 'step 5 - user could not be added'
+                            output += '<p>sorry, but user could not be added.</p>'
+            
+    extra = """
+    <dl>
+     <dt><a href="addrole">Add new role</a></dt>
+     <dd>go here to add a new role.</dd>
+    </dl>
+    """
+
+    return index(req=req,
+                 title=title,
+                 subtitle=subtitle,
+                 body=[output, extra])
+
+
+def perform_addroleuser(req, email_user_pattern='', id_user='0', id_role='0', confirm=0):
+    """delete connection between role and user.
+
+    id_role - id of role to disconnect
+
+    id_user - id of user to disconnect. """
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    email_out = acca.acc_getUserEmail(id_user=id_user)
+    name_role = acca.acc_getRoleName(id_role=id_role)
+
+    title = 'Connect user to roles'
+    subtitle = 'step 1 - search for users'
+
+    # clean email search string
+    email_user_pattern = cleanstring_email(email_user_pattern)
+        
+    text  = ' <span class="adminlabel">1. search pattern </span>\n'
+    text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, )
+
+    output = createhiddenform(action='addroleuser',
+                               text=text,
+                               button='search for users',
+                               id_role=id_role)
+    
+    if email_user_pattern:
+        subtitle = 'step 2 - select user'
+
+        users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id """ % (email_user_pattern, ))
+        users = []
+        for (id, email) in users1: users.append([id, email, ''])
+
+        if not users:
+            output += '<p>no qualified users, try new search</p>'
+        else:
+            output += createuserselect(id_user=id_user,
+                                       action='addroleuser',
+                                       step=2,
+                                       users=users,
+                                       button='select user',
+                                       email_user_pattern=email_user_pattern)
+
+            if int(id_user):
+                subtitle = 'step 3 - select role'
+
+                # roles the user is connected to
+                role_ids = acca.acc_getUserRoles(id_user=id_user)
+                # all the roles
+                all_roles = acca.acc_getAllRoles()
+
+                # sort the roles in connected and not connected roles
+                con_roles = []
+                not_roles = []
+                for (id, name, description) in all_roles:
+                    if (id, ) in role_ids: con_roles.append([-id, name, description])
+                    else: not_roles.append([id, name, description])
+
+                # create roleselect
+                output += createroleselect(id_role=id_role,
+                                           action='addroleuser',
+                                           step=3,
+                                           roles=not_roles,
+                                           extraroles=con_roles,
+                                           button='add this role',
+                                           email_user_pattern=email_user_pattern,
+                                           id_user=id_user)
+
+                if int(id_role) < 0:
+                    output += '<p>roles in brackets are already connected to the user, try another one<p>'
+                elif int(id_role):
+                    subtitle = 'step 4 - confirm to add role to user'
+
+                    output += createhiddenform(action='addroleuser',
+                                               text='add role <strong>%s</strong> to user <strong>%s</strong>?' % (name_role, email_out),
+                                               email_user_pattern=email_user_pattern,
+                                               id_user=id_user,
+                                               id_role=id_role,
+                                               confirm=1)
+
+                    if confirm:
+                        # add role
+                        result = acca.acc_addUserRole(id_user=id_user, id_role=id_role)
+
+                        if result and result[2]:
+                            subtitle = 'step 5 - confirm role added'
+                            output  += '<p>confirm: role <strong>%s</strong> added to user <strong>%s</strong>.</p>' % (name_role, email_out)
+                        else:
+                            subtitle = 'step 5 - role could not be added'
+                            output += '<p>sorry, but role could not be added</p>'
+
+    extra = """
+    <dl>
+     <dt><a href="addrole">Add new role</a></dt>
+     <dd>go here to add a new role.</dd>
+    </dl>
+    """
+
+    return index(req=req,
+                 title=title,
+                 subtitle=subtitle,
+                 body=[output, extra])
+
+
+def perform_deleteuserrole(req, id_role='0', id_user='0', reverse=0, confirm=0):
+    """delete connection between role and user.
+
+    id_role - id of role to disconnect
+
+    id_user - id of user to disconnect. """
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    title = 'Delete user from role'
+    email_user = acca.acc_getUserEmail(id_user=id_user)
+    name_role = acca.acc_getRoleName(id_role=id_role)
+
+    output = ''
+
+    if reverse in [0, '0']: 
+        subtitle='step 1 - select the role'
+        output += createroleselect(id_role=id_role,
+                                   action="deleteuserrole",
+                                   step=1,
+                                   roles=acca.acc_getAllRoles())
+            
+        if id_role != "0":
+            subtitle = 'step 2 - select the user'
+            output += createuserselect(id_user=id_user,
+                                       action="deleteuserrole",
+                                       step=2,
+                                       users=acca.acc_getRoleUsers(id_role=id_role),
+                                       id_role=id_role)
+
+    else:
+        # show only users connected to a role
+        users = run_sql("""SELECT DISTINCT(u.id), u.email, u.note
+        FROM user u LEFT JOIN user_accROLE ur
+        ON u.id = ur.id_user
+        WHERE ur.id_accROLE != 'NULL' AND u.email != ''
+        ORDER BY id """)
+
+        has_roles = 1
+        
+        # check if the user is connected to any roles
+        for (id, email, note) in users:
+            if str(id) == str(id_user): break
+        else:
+            subtitle = 'step 1 - user not connected'
+            output += '<p>no need to remove roles from this user,<br>user <strong>%s</strong> is not connected to any roles.</p>' % (email_user, )
+            has_roles, id_user = 0, '0' # stop the rest of the output below...
+            
+        
+        if has_roles:
+            output += createuserselect(id_user=id_user,
+                                      action="deleteuserrole",
+                                      step=1,
+                                      users=users,
+                                      reverse=reverse)
+        
+            if id_user != "0":
+                subtitle = 'step 2 - select the user'
+    
+                role_ids = acca.acc_getUserRoles(id_user=id_user)
+                all_roles = run_sql("""SELECT id, name, description FROM accROLE ORDER BY id """)
+                roles = []
+                for (id, name, desc) in all_roles:
+                    if (id, ) in role_ids: roles.append([id, name, desc])
+                
+                output += createroleselect(id_role=id_role,
+                                           action="deleteuserrole",
+                                           step=2,
+                                           roles=roles,
+                                           id_user=id_user,
+                                           reverse=reverse)
+    
+    if id_role != '0' and id_user != '0':
+        subtitle = 'step 3 - confirm delete of user'
+        output += createhiddenform(action="deleteuserrole",
+                                   text='<span class="adminlabel">3. confirm</span> delete user %s from %s?' % (headerstrong(user=id_user), headerstrong(role=id_role)),
+                                   id_role=id_role,
+                                   id_user=id_user,
+                                   reverse=reverse,
+                                   confirm=1)
+
+        if confirm:
+            res = acca.acc_deleteUserRole(id_user=id_user, id_role=id_role)
+            if res:
+                subtitle = 'step 4 - confirm delete of user'
+                output += '<p>confirm: deleted user <strong>%s</strong> from role <strong>%s</strong>.</p>' % (email_user, name_role)
+            else:
+                subtitle = 'step 4 - user could not be deleted'
+                output += 'sorry, but user could not be deleted<br>user is probably already deleted.'
+            
+    return index(req=req,
+                 title=title,
+                 subtitle=subtitle,
+                 body=[output])
+
+
+def perform_showuserdetails(req, id_user=0):
+    """show the details of a user. """
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    if id_user not in [0, '0']:
+        output = userdetails(id_user=id_user)
+
+        extra = """
+        <dl>
+         <dt><a href="addroleuser?id_user=%s">Connect role</a></dt>
+         <dd>connect a role to the user.</dd>
+        </dl>
+        """ % (id_user, )
+
+        body = [output, extra]
+    else:
+        body = ['<p>no details to show</p>']
+
+    return index(req=req,
+                 title='Show User Details',
+                 subtitle='show user details',
+                 body=body)
+
+
+def userdetails(id_user=0):
+    """create the string to show details about a user. """
+
+    # find necessary details
+    email_user = acca.acc_getUserEmail(id_user=id_user)
+
+    userroles = acca.acc_getUserRoles(id_user=id_user)
+    conn_roles = []
+
+    # find connected roles
+    for (id, name, desc) in acca.acc_getAllRoles():
+        if (id, ) in userroles:
+            conn_roles.append([id, name, desc])
+            conn_roles[-1].append('<a href="showroledetails?id_role=%s">show details</a>' % (id, ))
+
+    if conn_roles: 
+        # print details
+        details  = '<p>roles connected to user <strong>%s</strong></p>' % (email_user, )
+        details += tupletotable(header=['id', 'name', 'description', ''], tuple=conn_roles)
+    else:
+        details  = '<p>no roles connected to user <strong>%s</strong>.</p>' % (email_user, )
+
+    return details
+
+def perform_addauthorization(req, id_role="0", id_action="0", optional=0, reverse="0", confirm=0, **keywords):
+    """ form to add new connection between user and role:
+
+      id_role - role to connect 
+
+    id_action - action to connect
+
+      reverse - role or action first? """
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    # values that might get used
+    name_role = acca.acc_getRoleName(id_role=id_role) or id_role
+    name_action = acca.acc_getActionName(id_action=id_action) or id_action
+    optional = optional == 'on' and 1 or int(optional)
+    
+    extra = """
+    <dl>
+     <dt><a href="addrole">Add new role</a></dt>
+     <dd>go here to add a new role.</dd>
+     <dt><a href="addaction">Add new action</a></dt>
+     <dd>go here to add a new action.</dd>
+    </dl>
+    """
+
+    # create the page according to which step the user is on
+    # role -> action -> arguments
+    if reverse in ["0", 0]:
+        subtitle = 'step 1 - select role'
+        output = createroleselect(id_role=id_role,
+                                  action="addauthorization",
+                                  step=1,
+                                  roles=acca.acc_getAllRoles(),
+                                  reverse=reverse)
+        if id_role != "0":
+            subtitle = 'step 2 - select action'
+            rolacts = acca.acc_getRoleActions(id_role)
+            allhelp = acca.acc_getAllActions()
+            allacts = []
+            for r in allhelp:
+                if r not in rolacts: allacts.append(r)
+            output += createactionselect(id_action=id_action,
+                                         action="addauthorization",
+                                         step=2,
+                                         actions=rolacts,
+                                         extraactions=allacts,
+                                         id_role=id_role,
+                                         reverse=reverse)
+    # action -> role -> arguments
+    else:
+        subtitle = 'step 1 - select action'
+        output = createactionselect(id_action=id_action,
+                                    action="addauthorization",
+                                    step=1,
+                                    actions=acca.acc_getAllActions(),
+                                    reverse=reverse)
+        if id_action != "0":
+            subtitle = 'step 2 - select role'
+            actroles = acca.acc_getActionRoles(id_action)
+            allhelp = acca.acc_getAllRoles()
+            allroles = []
+            for r in allhelp:
+                if r not in actroles: allroles.append(r)
+            output += createroleselect(id_role=id_role,
+                                       action="addauthorization",
+                                       step=2,
+                                       roles=actroles,
+                                       extraroles=allroles,
+                                       id_action=id_action,
+                                       reverse=reverse)
+
+    # ready for step 3 no matter which direction we took to get here
+    if id_action != "0" and id_role != "0":
+        subtitle = 'step 3 - enter values for the keywords\n'
+
+        output += """
+        <form action="addauthorization" method="POST">
+         <input type="hidden" name="id_role" value="%s">
+         <input type="hidden" name="id_action" value="%s">
+         <input type="hidden" name="reverse" value="%s">
+        """  % (id_role, id_action, reverse)
+         
+        res_keys = acca.acc_getActionKeywords(id_action=id_action)
+
+        if not res_keys:
+            output += """
+             <input type="hidden" name="confirm" value="1">
+              create connection between %s?
+             <input class="adminbutton" type="submit" value="confirm">
+            </form>
+            """ % (headerstrong(role=name_role, action=name_action, query=0), )
+
+                   
+        else:
+            optionalargs = acca.acc_getActionIsOptional(id_action=id_action)
+
+            output += '<span class="adminlabel">3. arguments</span><br>'
+            if optionalargs:
+                output += """
+                <p>
+                 <input type="checkbox" name="optional" %s />
+                 create connection without the need for arguments
+                </p>
+                """ % (optional and 'checked="checked"' or '', )
+                
+            allkeys = 1
+            for key in res_keys:
+                output += '<span class="adminlabel">%s </span>\n <input class="admin_wvar" type="text" name="%s"' % (key, key)
+                try:
+                    val = keywords[key] = cleanstring_argumentvalue(keywords[key])
+                    if val: output += 'value="%s" ' % (val, )
+                    else: allkeys = 0
+                except KeyError: allkeys = 0
+                output += ' /> <br>\n'
+            output = output[:-5] + ' <input class="adminbutton" type="submit" value="create entry -->" />\n'
+            output += '</form>\n'
+
+            # ask for confirmation
+            if allkeys not in ["0", 0] or optional:
+                keys = keywords.keys()
+                keys.reverse()
+                subtitle = 'step 4 - confirm add of authorization\n'
+
+                text = """
+                create connection between <br>
+                %s <br>
+                """ % (headerstrong(role=name_role, action=name_action, query=0), )
+
+                if optional:
+                    text += 'withouth arguments'
+                    keywords = {}
+                else:
+                    for key in keys:
+                        text += '<strong>%s</strong>: %s \n' % (key, keywords[key])
+                
+                output += createhiddenform(action="addauthorization",
+                                           text=text,
+                                           id_role=id_role,
+                                           id_action=id_action,
+                                           reverse=reverse,
+                                           confirm=1,
+                                           optional=optional,
+                                           **keywords)
+
+        # show existing authorizations
+        res = acca.acc_findPossibleActions(id_role, id_action)
+        output += '<p>existing authorizations:</p>'
+        if res:
+            output += tupletotable(header=res[0], tuple=res[1:])
+            # shortcut to modifying authorizations
+            extra += """
+            <dl>
+             <dt><a href="modifyauthorizations?id_role=%s&amp;id_action=%s&amp;reverse=%s">Modify authorizations</a></dt>
+             <dd>modify the existing authorizations.<dd>
+            </dl> """ % (id_role, id_action, reverse)
+
+        else:   output += '<p>no details to show</p>'
+
+
+    # user confirmed to add entries
+    if confirm: 
+        subtitle = 'step 5 - confirm authorization added'
+        res1 = acca.acc_addRoleActionArguments_names(name_role=name_role,
+                                                     name_action=name_action,
+                                                     arglistid=-1,
+                                                     optional=optional,
+                                                     **keywords)
+        # newentries = ''
+    
+        if res1:
+            res2 = acca.acc_findPossibleActions(id_role, id_action)
+            arg = res1[0][3] # the arglistid
+            new = [res2[0]]
+            for row in res2[1:]:
+                if row[0] == arg: new.append(row)
+    
+            newauths = tupletotable(header=new[0], tuple=new[1:])
+            newentries = tupletotable(header=['role id', 'action id', 'argument id', '#'], tuple=res1)
+
+            st = 'style="vertical-align: top"'
+            output += """
+            <p>new authorization and entries:</p>
+            <table><tr>
+             <td class="admintd" %s>%s</td>
+             <td class="admintd" %s>%s</td>
+            </tr></table> """ % (st, newauths, st, newentries)
+
+        else: output += '<p>sorry, authorization could not be added,<br>it probably already exists</p>'
+
+    # trying to put extra link on the right side
+    try: body = [output, extra]
+    except NameError: body = [output]
+
+    return index(req=req,
+                 title = 'Create entry for new authorization',
+                 subtitle=subtitle,
+                 body=body) 
+
+
+def perform_deleteroleaction(req, id_role="0", id_action="0", reverse=0, confirm=0):
+    """delete all connections between a role and an action.
+
+      id_role - id of the role
+
+    id_action - id of the action
+
+      reverse - 0: ask for role first
+                1: ask for action first"""
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    title = 'Remove action from role '
+    
+    if reverse in ["0", 0]:
+        # select role -> action
+        subtitle = 'step 1 - select a role'
+        output  = createroleselect(id_role=id_role,
+                                   action="deleteroleaction",
+                                   step=1,
+                                   roles=acca.acc_getAllRoles(),
+                                   reverse=reverse)
+        
+        if id_role != "0":
+            rolacts = acca.acc_getRoleActions(id_role=id_role)
+            subtitle = 'step 2 - select the action'
+            output += createactionselect(id_action=id_action,
+                                         action="deleteroleaction",
+                                         step=2,
+                                         actions=rolacts,
+                                         reverse=reverse,
+                                         id_role=id_role,
+                                         button="remove connection and all authorizations")
+    else:
+        # select action -> role
+        subtitle = 'step 1 - select an action'
+        output = createactionselect(id_action=id_action,
+                                    action="deleteroleaction",
+                                    step=1,
+                                    actions=acca.acc_getAllActions(),
+                                    reverse=reverse)
+        
+        if id_action != "0":
+            actroles = acca.acc_getActionRoles(id_action=id_action)
+            subtitle = 'step 2 - select the role'
+            output += createroleselect(id_role=id_role,
+                                       action="deleteroleaction",
+                                       step=2,
+                                       roles=actroles,
+                                       button="remove connection and all authorizations", 
+                                       id_action=id_action,
+                                       reverse=reverse)
+
+    if id_action != "0" and id_role != "0":
+        subtitle = 'step 3 - confirm remove of action'
+        # ask for confirmation
+
+        res = acca.acc_findPossibleActions(id_role, id_action)
+
+        if res:
+            output += '<p>authorizations that also will be deleted:</p>'
+            output += tupletotable(header=res[0], tuple=res[1:])
+
+            output += createhiddenform(action="deleteroleaction",
+                                       text='remove action %s from %s' % (headerstrong(action=id_action), headerstrong(role=id_role)),
+                                       confirm=1,
+                                       id_role=id_role,
+                                       id_action=id_action,
+                                       reverse=reverse)
+        else:
+            output += 'no authorizations'
+
+        # confirmation is given
+        if confirm: 
+            subtitle = 'step 4 - confirm remove of action '
+            res = acca.acc_deleteRoleAction(id_role=id_role, id_action=id_action)
+            if res:
+                output += '<p>confirm: removed %s from %s<br>' % (headerstrong(action=id_action), headerstrong(role=id_role))
+                output += '<strong>%s</strong> entries were removed.</p>' % (res, )
+            else:
+                output += '<p>sorry, no entries could be removed.</p>'
+    
+    return index(req=req,
+                 title=title,
+                 subtitle=subtitle,
+                 body=[output])
+        
+
+def perform_modifyauthorizations(req, id_role="0", id_action="0", reverse=0, confirm=0, errortext='', sel='', authids=[]):
+    """given ids of a role and an action, show all possible action combinations
+    with checkboxes and allow user to access other functions.    
+
+      id_role - id of the role
+
+    id_action - id of the action
+
+      reverse - 0: ask for role first
+                1: ask for action first
+
+          sel - which button and modification that is selected
+    
+    errortext - text to print when no connection exist between role and action
+    
+      authids - ids of checked checkboxes """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    name_role = acca.acc_getRoleName(id_role)
+    name_action = acca.acc_getActionName(id_action)
+
+    extra = """
+    <dl>
+     <dt><a href="addrole">Add new role</a></dt>
+     <dd>go here to add a new role.</dd>
+     <dt><a href="addaction">Add new action</a></dt>
+     <dd>go here to add a new action.</dd>
+    </dl>
+    """
+
+    if reverse in ["0", 0]:
+        # role -> action
+        subtitle = 'step 1 - select the role'
+        output  = createroleselect(id_role=id_role,
+                                   action="modifyauthorizations",
+                                   step=1,
+                                   roles=acca.acc_getAllRoles(),
+                                   reverse=reverse)
+
+        if id_role != "0":
+            rolacts = acca.acc_getRoleActions(id_role=id_role)
+            subtitle = 'step 2 - select the action'
+            output += createactionselect(id_action=id_action,
+                                         action="modifyauthorizations",
+                                         step=2,
+                                         actions=rolacts,
+                                         id_role=id_role,
+                                         reverse=reverse)
+    else:
+        # action -> role
+        subtitle = 'step 1 - select the action'
+        output = createactionselect(id_action=id_action,
+                                    action="modifyauthorizations",
+                                    step=1,
+                                    actions=acca.acc_getAllActions(),
+                                    reverse=reverse)
+        if id_action != "0":
+            actroles = acca.acc_getActionRoles(id_action=id_action)
+            subtitle = 'step 2 - select the role'
+            output += createroleselect(id_role=id_role,
+                                       action="modifyauthorizations",
+                                       step=2,
+                                       roles=actroles,
+                                       id_action=id_action,
+                                       reverse=reverse)
+
+    if errortext: output += '<p>%s</p>' % (errortext, )
+
+    if id_role != "0" and id_action != "0":
+        # shortcut to modifying authorizations
+        extra += """
+        <dl>
+         <dt><a href="addauthorization?id_role=%s&amp;id_action=%s&amp;reverse=%s">Add authorizations</a></dt>
+         <dd>Add and authorization to the existing.</dd>
+        </dl> """ % (id_role, id_action, reverse)
+
+        # back to the main area
+        if type(authids) is not list: authids = [authids]
+        subtitle = 'step 3 - select groups and modification'
+
+        # get info 
+        res = acca.acc_findPossibleActions(id_role, id_action)
+
+        # clean the authids
+        hiddenids = []
+        if sel in ['delete selected']:
+            hiddenids = authids[:]
+        elif sel in ['split groups', 'merge groups']:
+            for authid in authids:
+                arghlp = res[int(authid)][0]
+                if authid not in hiddenids and arghlp not in [-1, '-1', 0, '0']: hiddenids.append(authid)
+            authids = hiddenids[:]
+        
+        if confirm:
+            # do selected modification and output with new authorizations
+            if sel == 'split groups':
+                res = splitgroups(id_role, id_action, authids)
+            elif sel == 'merge groups':
+                res = mergegroups(id_role, id_action, authids)
+            elif sel == 'delete selected':
+                res = deleteselected(id_role, id_action, authids)
+            authids = []
+            res = acca.acc_findPossibleActions(id_role, id_action)
+            output += 'authorizations after <strong>%s</strong>.<br>\n' % (sel, )
+
+        elif sel and authids:
+            output += 'confirm choice of authorizations and modification.<br>\n'
+        else:
+            output += 'select authorizations and perform modification.<br>\n'
+            
+        if not res:
+            errortext='all connections deleted, try different '
+            if reverse in ["0", 0]:
+                return perform_modifyauthorizations(req=req, id_role=id_role, errortext=errortext + 'action.')
+            else:
+                return perform_modifyauthorizations(req=req, id_action=id_action, reverse=reverse, errortext=errortext + 'role.')
+        
+        # display 
+        output += modifyauthorizationsmenu(id_role, id_action, header=res[0], tuple=res[1:], checked=authids, reverse=reverse)
+        
+        if sel and authids:
+            # form with hidden authids
+            output += '<form action="%s" method="POST">\n' % ('modifyauthorizations', )
+
+            for hiddenid in hiddenids: 
+                output += '<input type="hidden" name="authids" value="%s" />\n' % (hiddenid, )
+
+            # choose what to do
+            if sel == 'split groups':
+                output += '<p>split groups containing:</p>'
+            elif sel == 'merge groups':               
+                output += '<p>merge groups containing:</p>'
+            elif sel == 'delete selected':            
+                output += '<p>delete selected entries:</p>'
+
+            extracolumn  = '<input type="checkbox" name="confirm" value="1" />\n'
+            extracolumn += '<input class="adminbutton" type="submit" value="confirm" />\n'
+
+            # show the entries here...
+            output += tupletotable_onlyselected(header=res[0],
+                                                tuple=res[1:],
+                                                selected=hiddenids,
+                                                extracolumn=extracolumn)
+            
+            output += '<input type="hidden" name="id_role" value="%s" />\n' % (id_role, )
+            output += '<input type="hidden" name="id_action" value="%s" />\n' % (id_action, )
+            output += '<input type="hidden" name="sel" value="%s" />\n' % (sel, )
+            output += '<input type="hidden" name="reverse" value="%s" />\n' % (reverse, )
+            output += '</form>'
+
+        # tried to perform modification without something selected
+        elif sel and not authids and not confirm: 
+            output += '<p>no valid groups selected</p>'
+
+    # trying to put extra link on the right side
+    try: body = [output, extra]
+    except NameError: body = [output]
+
+    # Display the page
+    return index(req=req,
+                 title='Modify Authorizations',
+                 subtitle=subtitle,
+                 body=body)
+
+
+def modifyauthorizationsmenu(id_role, id_action, tuple=[], header=[], checked=[], reverse=0):
+    """create table with header and checkboxes, used for multiple choice.
+    makes use of tupletotable to add the actual table
+
+      id_role - selected role, hidden value in the form
+
+    id_action - selected action, hidden value in the form
+
+        tuple - all rows to be put in the table (with checkboxes)
+
+       header - column headers, empty strings added at start and end
+
+      checked - ids of rows to be checked """
+
+    if not tuple:
+        return 'no authorisations...'
+
+    argnum = len(acca.acc_getActionKeywords(id_action=id_action))
+    
+    tuple2 = []
+    for t in tuple: tuple2.append(t[:])
+    
+    tuple2 = addcheckboxes(datalist=tuple2, name='authids', startindex=1, checked=checked)
+
+    hidden  = '<input type="hidden" name="id_role" value="%s" /> \n' % (id_role, )
+    hidden += '<input type="hidden" name="id_action" value="%s" /> \n' % (id_action, )
+    hidden += '<input type="hidden" name="reverse" value="%s" /> \n' % (reverse, )
+
+    
+    button = '<input type="submit" class="adminbutton" value="delete selected" name="sel" />\n'
+    if argnum > 1: 
+        button += '<input type="submit" class="adminbutton" value="split groups" name="sel" />\n'
+        button += '<input type="submit" class="adminbutton" value="merge groups" name="sel" />\n'
+    
+    hdrstr = ''
+    for h in [''] + header + ['']: hdrstr += '  <th class="adminheader">%s</th>\n' % (h, )
+    if hdrstr: hdrstr = ' <tr>\n%s\n </tr>\n' % (hdrstr, )
+    
+    output  = '<form action="modifyauthorizations" method="POST">\n'
+    output += '<table class="admin_wvar_nomargin"> \n'
+    output += hdrstr
+    output += '<tr><td>%s</td></tr>\n' % (hidden, )
+
+    output += '<tr>'
+    for data in tuple2[0]: output += '<td class="admintd">%s</td>\n' % (data,)
+    output += '<td rowspan="%s" style="vertical-align: bottom">\n%s\n</td>\n' % (len(tuple2), button)
+
+    output += '</tr>\n'
+    for row in tuple2[1:]:
+        output += ' <tr>\n'
+        for data in row: output += '<td class="admintd">%s</td>\n' % (data,)
+        output += ' </tr>\n'
+
+    output += '</table>\n</form>\n'
+
+    return output
+
+
+def splitgroups(id_role=0, id_action=0, authids=[]):
+    """get all the old ones, gather up the arglistids find a list of
+    arglistidgroups to be split, unique get all actions in groups outside
+    of the old ones, (old arglistid is allowed).
+    
+    show them like in showselect. """
+
+    if not id_role or not id_action or not authids:
+        return 0
+    
+    # find all the actions
+    datalist = acca.acc_findPossibleActions(id_role, id_action)
+
+    if type(authids) is str: authids = [authids]
+    for i in range(len(authids)): authids[i] = int(authids[i])
+    
+    # argumentlistids of groups to be split
+    splitgrps = []
+    for authid in authids:
+        hlp = datalist[authid][0]
+        if hlp not in splitgrps and authid in range(1,len(datalist)):
+            splitgrps.append(hlp)
+
+    # split groups and return success or failure
+    result = 1
+    for splitgroup in splitgrps:
+        result = 1 and acca.acc_splitArgumentGroup(id_role, id_action, splitgroup)
+
+    return result
+
+
+def mergegroups(id_role=0, id_action=0, authids=[]):
+    """get all the old ones, gather up the argauthids find a list
+    of arglistidgroups to be split, unique get all actions in groups
+    outside of the old ones, (old arglistid is allowed).
+
+    show them like in showselect."""
+
+    if not id_role or not id_action or not authids:
+        return 0
+    
+    datalist = acca.acc_findPossibleActions(id_role, id_action)
+
+    if type(authids) is str: authids = [authids]
+    for i in range(len(authids)): authids[i] = int(authids[i])
+    
+    # argumentlistids of groups to be merged
+    mergegroups = []
+    for authid in authids:
+        hlp = datalist[authid][0]
+        if hlp not in mergegroups and authid in range(1, len(datalist)):
+            mergegroups.append(hlp)
+
+    # merge groups and return success or failure
+    if acca.acc_mergeArgumentGroups(id_role, id_action, mergegroups):
+        return 1
+    else:
+        return 0
+
+
+
+def deleteselected(id_role=0, id_action=0,  authids=[]):
+    """delete checked authorizations/possible actions, ids in authids.
+
+    id_role - role to delete from
+
+    id_action - action to delete from
+
+    authids - listids for which possible actions to delete."""
+    
+    if not id_role or not id_action or not authids:
+        return 0
+
+    if type(authids) in [str, int]: authids = [authids]
+    for i in range(len(authids)): authids[i] = int(authids[i])
+    
+    result = acca.acc_deletePossibleActions(id_role=id_role,
+                                            id_action=id_action,
+                                            authids=authids)
+
+    return result
+
+
+def addadminbox(header='', datalist=[], cls="admin_wvar"):
+    """used to create table around main data on a page, row based.
+
+      header - header on top of the table
+
+    datalist - list of the data to be added row by row
+
+         cls - possible to select wich css-class to format the look of the table."""
+
+    try: per = str(100 // len(datalist)) + '%'
+    except ZeroDivisionError: per = 1
+
+    output  = '<table class="%s" ' % (cls, ) + 'width="100%">\n'
+    output += """
+     <thead>
+      <tr>
+       <th class="adminheaderleft" colspan="%s">%s</th>
+      </tr>
+     </thead>
+     <tbody>
+    """ % (len(datalist), header)
+    for row in [datalist]:
+        output += '      <tr>\n'
+        for data in row:
+            output += """
+            <td style="vertical-align: top; margin-top: 5px; width: %s;">
+             %s 
+            </td>
+            """ % (per, data)
+        output += '      </tr>\n'
+    output += """
+     </tbody>
+    </table>
+    """
+
+    return output
+
+
+def addadminbox(header='', datalist=[], cls="admin_wvar"):
+    """used to create table around main data on a page, row based.
+
+      header - header on top of the table
+
+    datalist - list of the data to be added row by row
+
+         cls - possible to select wich css-class to format the look of the table."""
+
+    if len(datalist) == 1: per = 100
+    else: per = 75
+    
+    output  = '<table class="%s" ' % (cls, ) + 'width="100%">\n'
+    output += """
+     <thead>
+      <tr>
+       <th class="adminheaderleft" colspan="%s">%s</th>
+      </tr>
+     </thead>
+     <tbody>
+    """ % (len(datalist), header)
+
+    output += '      <tr>\n'
+
+    output += """
+    <td style="vertical-align: top; margin-top: 5px; width: %s;">
+     %s 
+    </td>
+    """ % (per, datalist[0])
+
+    if len(datalist) > 1:
+        output += """
+        <td style="vertical-align: top; margin-top: 5px; width: %s;">
+         %s 
+        </td>
+        """ % ('25%', datalist[1])
+        
+    output += '      </tr>\n'
+    
+    output += """
+     </tbody>
+    </table>
+    """
+
+    return output
+
+
+def adderrorbox(header='', datalist=[]):
+    """used to create table around main data on a page, row based"""
+
+    try: perc= str(100 // len(datalist)) + '%'
+    except ZeroDivisionError: perc= 1
+
+    output  = '<table class="errorbox" width="100%">'
+    output += '<thead><tr><th class="errorboxheader" colspan="%s">%s</th></tr></thead>' % (len(datalist), header)
+    output += '<tbody>'
+    for row in [datalist]:
+        output += '<tr>'
+        for data in row:
+            output += '<td style="vertical-align: top; margin-top: 5px; width: %s;">' % (perc, )
+            output += data
+            output += '</td>'
+        output += '</tr>'
+    output += '</tbody></table>'
+
+    return output
+
+
+def tupletotable(header=[], tuple=[], start='', end='', extracolumn=''):
+    """create html table for a tuple.
+
+         header - optional header for the columns
+     
+          tuple - create table of this
+     
+          start - text to be added in the beginning, most likely beginning of a form
+     
+            end - text to be added in the end, mot likely end of a form.
+     
+    extracolumn - mainly used to put in a button. """
+    
+    tblstr = ''
+    for h in header + ['']:
+        tblstr += '  <th class="adminheader">%s</th>\n' % (h, )
+    if tblstr: tblstr = ' <tr>\n%s\n </tr>\n' % (tblstr, )
+    
+    tblstr = start + '<table class="admin_wvar_nomargin">\n' + tblstr
+
+    # extra column
+    try: 
+        extra = '<tr>'
+        row = tuple[0]
+        if type(row) not in [int, long, str, dict]:
+            for data in row: extra += '<td class="admintd">%s</td>\n' % (data,)
+        else:
+            extra += '  <td class="admintd">%s</td>\n' % (row, )
+        extra += '<td rowspan="%s" style="vertical-align: bottom">\n%s\n</td>\n</tr>\n' % (len(tuple), extracolumn)
+    except IndexError:
+        extra = ''
+    tblstr += extra
+
+    
+    for row in tuple[1:]:
+        tblstr += ' <tr>\n'
+        if type(row) not in [int, long, str, dict]:
+            for data in row: tblstr += '<td class="admintd">%s</td>\n' % (data,)
+        else:
+            tblstr += '  <td class="admintd">%s</td>\n' % (row, )
+        tblstr += ' </tr> \n'
+
+    tblstr += '</table> \n '
+    tblstr += end
+    
+    return tblstr
+
+
+def tupletotable_onlyselected(header=[], tuple=[], selected=[], start='', end='', extracolumn=''):
+    """create html table for a tuple.
+
+        header - optional header for the columns
+
+         tuple - create table of this
+
+      selected - indexes of selected rows in the tuple
+
+         start - put this in the beginning
+
+           end - put this in the beginning
+
+   extracolumn - mainly used to put in a button"""
+
+    tuple2 = []
+
+    for index in selected:
+        tuple2.append(tuple[int(index)-1])
+
+    return tupletotable(header=header,
+                        tuple=tuple2,
+                        start=start,
+                        end=end,
+                        extracolumn=extracolumn)
+
+
+def addcheckboxes(datalist=[], name='authids', startindex=1, checked=[]):
+    """adds checkboxes in front of the listdata.
+
+      datalist - add checkboxes in front of this list
+
+          name - name of all the checkboxes, values will be associated with this name
+
+    startindex - usually 1 because of the header
+
+       checked - values of checkboxes to be pre-checked """
+    
+    if not type(checked) is list: checked = [checked]
+    for row in datalist:
+        if 1 or row[0] not in [-1, "-1", 0, "0"]: # always box, check another place
+            chkstr = str(startindex) in checked and 'checked="checked"' or ''
+            row.insert(0, '<input type="checkbox" name="%s" value="%s" %s />' % (name, startindex, chkstr))
+        else:
+            row.insert(0, '')
+        startindex += 1
+    return datalist
+
+
+def headeritalic(**ids):
+    """transform keyword=value pairs to string with value in italics.
+
+    **ids - a dictionary of pairs to create string from """
+    
+    output = ''
+    value = ''
+    table = ''
+
+    for key in ids.keys():
+        if key in ['User', 'user']:
+            value, table = 'email', 'user'
+        elif key in ['Role', 'role']:
+            value, table = 'name', 'accROLE'
+        elif key in ['Action', 'action']:
+            value, table = 'name', 'accACTION'
+        else:
+            if output: output += ' and '
+            output += ' %s <i>%s</i>' % (key, ids[key])
+            continue
+                
+        res = run_sql("""SELECT %s FROM %s WHERE id = %s""" % (value, table, ids[key]))
+        
+        if res:
+            if output: output += ' and '
+            output += ' %s <i>%s</i>' % (key, res[0][0])
+
+    return output
+
+
+def headerstrong(query=1, **ids):
+    """transform keyword=value pairs to string with value in strong text.
+
+    **ids - a dictionary of pairs to create string from
+    
+    query - 1 -> try to find names to ids of role, user and action.
+            0 -> do not try to find names, use the value passed on """
+
+    output = ''
+    value = ''
+    table = ''
+
+    for key in ids.keys():
+        if key in ['User', 'user']:
+            value, table = 'email', 'user'
+        elif key in ['Role', 'role']:
+            value, table = 'name', 'accROLE'
+        elif key in ['Action', 'action']:
+            value, table = 'name', 'accACTION'
+        else:
+            if output: output += ' and '
+            output += ' %s <strong>%s</strong>' % (key, ids[key])
+            continue
+
+        if query:
+            res = run_sql("""SELECT %s FROM %s WHERE id = %s""" % (value, table, ids[key]))
+            if res:
+                if output: output += ' and '
+                output += ' %s <strong>%s</strong>' % (key, res[0][0])
+        else:
+            if output: output += ' and '
+            output += ' %s <strong>%s</strong>' % (key, ids[key])
+
+    return output
+
+
+def startpage():
+    """create the menu for the startpage"""
+    
+    body = """
+    <table class="admin_wvar" width="100%s" summary="">
+     <thead>
+      <tr>
+       <th class="adminheaderleft" colspan="2">Selection for Admin <i>%s</i></th>
+      </tr>
+     </thead>
+     <tbody>
+      <tr>
+       <td style="vertical-align: top; margin-top: 5px; width: 50%s;">
+        <dl>
+         <dt><a href="webaccessadmin.py/rolearea">Role Area</a>
+         <dd>Main area to configure administration rights and authorization rules.
+         <dt><a href="webaccessadmin.py/actionarea">Action Area</a>
+         <dd>Configure administration rights with the actions as starting point.
+         <dt><a href="webaccessadmin.py/userarea">User Area</a>
+         <dd>Configure administration rights with the users as starting point.
+         <dt><a href="webaccessadmin.py/resetarea">Reset Area</a>
+         <dd>Reset roles, actions and authorizations.
+        </dl>
+       </td>
+       <td style="vertical-align: top; margin-top: 5px; width: 50%s;"> </td>
+      </tr>
+     </tbody>
+    </table>""" % ('%', SUPERADMINROLE, '%', '%')
+
+    return body
+
+
+def perform_simpleauthorization(req, id_role=0, id_action=0):
+    """show a page with simple overview of authorizations between a
+    connected role and action. """
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    res = acca.acc_findPossibleActions(id_role, id_action)
+    if res:
+        extra = createhiddenform(action='modifyauthorizations',
+                                 button='modify authorizations',
+                                 id_role=id_role,
+                                 id_action=id_action)
+        
+        output  = '<p>authorizations for %s:</p>' % (headerstrong(action=id_action, role=id_role), )
+        output += tupletotable(header=res[0], tuple=res[1:], extracolumn=extra)
+    else:
+        output = 'no details to show'
+
+    return index(req=req,
+                 title='Simple authorization details',
+                 subtitle='simple authorization details', 
+                 body=[output])
+
+
+def perform_simpleroleusers(req, id_role=0):
+    """show a page with simple overview of a role and connected users. """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    res = acca.acc_getRoleUsers(id_role=id_role)
+    if res:
+        users = []
+        for (id, name, dontcare) in res: users.append([id, name, '<a href="showuserdetails?id_user=%s">show user details</a>'
+                                                       % (id, )])
+        output  = '<p>users connected to %s:</p>' % (headerstrong(role=id_role), )
+        output += tupletotable(header=['id', 'name', ''], tuple=users)
+    else:
+        output = 'no users connected'
+
+    return index(req=req,
+                 title='Simple user details',
+                 subtitle='simple user details', 
+                 body=[output])
+               
+
+def createhiddenform(action="", text="", button="confirm", cnfrm='', **hidden):
+    """create select with hidden values and submit button
+
+      action - name of the action to perform on submit
+
+        text - additional text, can also be used to add non hidden input
+
+      button - value/caption on the submit button
+
+       cnfrm - if given, must check checkbox to confirm
+
+    **hidden - dictionary with name=value pairs for hidden input """
+    
+    output  = '<form action="%s" method="POST">\n' % (action, )
+    output += '<table>\n<tr><td>'
+    output += text
+    if cnfrm:
+        output += ' <input type="checkbox" name="confirm" value="1" />' 
+    for key in hidden.keys():
+        output += ' <input type="hidden" name="%s" value="%s" />\n' % (key, hidden[key])
+    output += '</td><td style="vertical-align: bottom">'
+    output += ' <input class="adminbutton" type="submit" value="%s" />\n' % (button, )
+    output += '</td></tr></table>'
+    output += '</form>\n'
+
+    return output
+
+
+def createselect(id_input="0", label="", step=0, name="",
+                 action="", list=[], extralist=[],
+                 button="", **hidden):
+    """create form with select and hidden values
+
+           id - the one to choose as selected if exists
+
+        label - label shown to the left of the select
+
+         name - the name of the select on which to reference it
+
+         list - primary list to select from
+
+    extralist - list of options to be put in paranthesis
+
+       button - the value/text to be put on the button
+
+     **hidden - name=value pairs to be put as hidden in the form. """
+
+    step = step and '%s. ' % step or ''
+    
+    output  = '<form action="%s" method="POST">\n' % (action, )
+    output += ' <span class="adminlabel">%s</span>\n' % (step + label, )
+    output += ' <select name="%s" class="admin_w200">\n' % (name, )
+    if not list and not extralist:
+        output += '  <option value="0">no %ss to select from</option>\n' % (label.split()[-1], )
+    else:
+        output += '  <option value="0">%s</option>\n' % (label, )
+        for (id, email, dontcare) in list:
+            if str(id) == id_input: output += '  <option value="%s" selected="selected">%s</option>\n' % (id, email)
+            else: output += '  <option value="%s">%s</option>\n' % (id, email)
+        for (id, email, dontcare) in extralist:
+            if str(id) == id_input: output += '  <option value="%s" selected="selected">(%s)</option>\n' % (id, email)
+            else: output += '  <option value="%s">(%s)</option>\n' % (id, email)
+    output += ' </select>\n'
+    for key in hidden.keys():
+        output += ' <input type="hidden" name="%s" value="%s" />\n' % (key, hidden[key])
+    output += ' <input class="adminbutton" type="submit" value="%s" />\n' % (button, )
+    output += '</form>\n'
+
+    return output
+
+
+def createactionselect(id_action="0", label="select action", step=0, name="id_action",
+                       action="", actions=[], extraactions=[],
+                       button="select action", **hidden):
+    """create a select for roles in a form. see createselect."""
+
+    return createselect(id_input=id_action, label=label, step=step, name=name,
+                        action=action, list=actions, extralist=extraactions,
+                        button=button, **hidden)
+
+
+def createroleselect(id_role="0", label="select role", step=0, name="id_role",
+                     action="", roles=[], extraroles=[],
+                     button="select role", **hidden):
+    """create a select for roles in a form. see createselect."""
+
+    return createselect(id_input=id_role, label=label, step=step, name=name,
+                        action=action, list=roles, extralist=extraroles,
+                        button=button, **hidden)
+
+
+def createuserselect(id_user="0", label="select user", step=0, name="id_user",
+                     action="", users=[], extrausers=[],
+                     button="select user", **hidden):
+    """create a select for users in a form.see createselect."""
+    
+    return createselect(id_input=id_user, label=label, step=step, name=name,
+                        action=action, list=users, extralist=extrausers,
+                        button=button, **hidden)
+
+
+def cleanstring(str='', comma=0):
+    """clean all the strings before submitting to access control admin.
+    remove characters not letter, number or underscore, also remove leading
+    underscores and numbers. return cleaned string.
+
+      str - string to be cleaned
+
+    comma - 1 -> allow the comma to divide multiple arguments
+            0 -> wash commas as well """
+
+    # remove not allowed characters
+    str = re.sub(r'[^a-zA-Z0-9_,]', '', str)
+
+    # split string on commas
+    items = str.split(',')
+    str = ''
+    for item in items:
+        if not item: continue
+        if comma and str: str += ','
+        # create valid variable names
+        str += re.sub(r'^([0-9_])*', '', item)
+
+    return str
+
+
+def cleanstring_argumentvalue(str=''):
+    """clean the value of an argument before submitting it.
+    allowed characters: a-z A-Z 0-9 _ and space 
+
+      str - string to be cleaned """
+
+    # remove not allowed characters
+    str = re.sub(r'[^a-zA-Z0-9_ .]', '', str)
+    # trim leading and ending spaces
+    str = re.sub(r'^ *| *$', '', str)
+
+    return str
+
+
+def cleanstring_email(str=''):
+    """clean the string and return a valid email address.
+    
+      str - string to be cleaned """
+
+    # remove not allowed characters
+    str = re.sub(r'[^a-zA-Z0-9_.@]', '', str)
+
+    return str
+
+
+def check_email(str=''):
+    """control that submitted emails are correct.
+    this little check is not very good, but better than nothing. """
+
+    r = re.compile(r'(.)+\@(.)+\.(.)+')
+    return r.match(str) and 1 or 0
diff --git a/modules/webaccess/lib/webaccessadmin_lib.py.wml b/modules/webaccess/lib/webaccessadmin_lib.py.wml
new file mode 100644
index 000000000..723c49136
--- /dev/null
+++ b/modules/webaccess/lib/webaccessadmin_lib.py.wml
@@ -0,0 +1,2537 @@
+## $Id$
+## Administrator interface for WebAccess
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002 CERN.
+##
+## The CDSware is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 2 of the
+## License, or (at your option) any later version.
+##
+## The CDSware is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.  
+##
+## You should have received a copy of the GNU General Public License
+## along with CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+## read config variables:
+#include "config.wml"
+#include "configbis.wml"
+
+<protect>## $Id$</protect>
+<protect>## DO NOT EDIT THIS FILE!  IT WAS AUTOMATICALLY GENERATED FROM CDSware WML SOURCES.</protect>
+"""CDSware WebAccess Administrator Interface."""
+
+__lastupdated__ = """<: print `date +"%d %b %Y %H:%M:%S %Z"`; :>"""
+
+## fill config variables:
+pylibdir = "<LIBDIR>/python"
+
+try:
+    import sys
+    sys.path.append('%s' % pylibdir)
+    import cdsware.access_control_engine as acce
+    import cdsware.access_control_admin as acca
+    reload(acce)
+    reload(acca)
+    import cgi
+    import re
+    
+    from cdsware.dbquery import run_sql
+    from cdsware.access_control_variables import SUPERADMINROLE, WEBACCESSACTION, DELEGATEADDUSERROLE
+    from cdsware.config import *
+    from cdsware.webpage import page, pageheaderonly, pagefooteronly
+    from cdsware.webuser import getUid, get_email
+    from mod_python import apache
+except ImportError, e:
+    print "Error: %s" % e
+    import sys
+    sys.exit(1)
+
+__version__ = "$Id$"
+
+
+def index(req, title='', body='', subtitle='', authorized=0):
+    """main function to show pages for webaccessadmin.
+
+    1. if user not logged in and administrator, show the mustlogin page
+
+    2. if used without body argument, show the startpage
+
+    3. show admin page with title, body, subtitle and navtrail.
+
+    authorized - if 1, don't check if the user is allowed to be webadmin """
+    
+    # navtrail_previous_links="""<a class=navtrail href=<WEBURL>/hacking/>Hacking CDSware</a> &gt;
+    # <a class=navtrail href=<WEBURL>/hacking/webaccess/index.html>WebAccess Internals</a> &gt;
+    # <a class=navtrail href=<WEBURL>/admin/webaccess/>Access Control Admin</a> &gt; """
+    navtrail_previous_links = """<a class=navtrail href="<WEBURL>/admin/">Admin Area</a> &gt; <a class=navtrail href="<WEBURL>/admin/webaccess/">WebAccess Admin</a> """
+    
+    if body and not authorized: navtrail_previous_links += '&gt; <a class=navtrail href=<WEBURL>/admin/webaccess/webaccessadmin.py>Manage WebAccess</a>'
+    
+    id_user = getUid(req)
+
+    if not authorized and not is_adminuser(req): return mustloginpage(req)
+    
+    elif not body:
+        title = 'Manage WebAccess'
+        body = startpage()
+    elif type(body) != str: body = addadminbox(subtitle, datalist=body)
+
+    return page(title=title,
+                uid=id_user,
+                body=body,
+                navtrail=navtrail_previous_links,
+                lastupdated=__lastupdated__)                
+
+
+def mustloginpage(req):
+    """show a page asking the user to login."""
+    
+    # navtrail_previous_links="""<a class=navtrail href=<WEBURL>/hacking/>Hacking CDSware</a> &gt;
+    # <a class=navtrail href=<WEBURL>/hacking/webaccess/index.html>WebAccess Internals</a> &gt;
+    # <a class=navtrail href=<WEBURL>/admin/webaccess/>Access Control Admin Area</a>"""
+    navtrail_previous_links = """<a class=navtrail href="<WEBURL>/admin/">Admin Area</a> &gt; <a class=navtrail href="<WEBURL>/admin/webaccess/">WebAccess Admin</a> &gt; """
+
+    return page(title='Authorization failure',
+                uid=getUid(req),
+                body=adderrorbox('try to login first',
+                                 datalist=["""You are not a user authorized to perform admin tasks, try to
+                                 <a href="http://cdsdev.cern.ch:8000/DEMODEV/youraccount.py/login">login</a>."""]),
+                navtrail=navtrail_previous_links,
+                lastupdated=__lastupdated__)                
+
+    
+def is_adminuser(req):
+    """check if user is a registered administrator. """
+
+    id_user = getUid(req)
+    return acce.acc_authorize_action(id_user, WEBACCESSACTION)
+     
+
+def perform_rolearea(req):
+    """create the role area menu page."""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    header = ['id', 'name', 'description', 'users', 'authorizations / actions', 'role', '']
+    roles = acca.acc_getAllRoles()
+
+    roles2 = []
+    for (id, name, desc) in roles:
+        if len(desc) > 30: desc = desc[:30] + '...'
+        roles2.append([id, name, desc])
+        for col in [(('add', 'adduserrole'),
+                     ('remove', 'deleteuserrole')),
+                    (('add', 'addauthorization'),
+                     ('modify', 'modifyauthorizations'),
+                     ('remove', 'deleteroleaction')),
+                    (('delete', 'deleterole'), ),
+                    (('show details', 'showroledetails'), )]:
+            roles2[-1].append('<a href="%s?id_role=%s">%s</a>' % (col[0][1], id, col[0][0]))
+            for (str, function) in col[1:]:
+                roles2[-1][-1] += ' / <a href="%s?id_role=%s">%s</a>' % (function, id, str)
+
+    output  = """
+    <dl>
+     <dt>Users:</dt>
+     <dd>add or remove users from the access to a role and its priviliges.</dd>
+     <dt>Authorizations/Actions:</dt>
+     <dd>these terms means almost the same, but an authorization is a <br>
+         connection between a role and an action (possibly) containing arguments.</dd>
+     <dt>Roles:</dt>
+     <dd>see all the information attached to a role and decide if you want to<br>delete it.</dd>
+    </dl>
+    """
+    
+    output += tupletotable(header=header, tuple=roles2)
+
+    extra = """
+    <dl>
+     <dt><a href="addrole">Add new role</a></dt>
+     <dd>go here to add a new role.</dd>
+     <dt><a href="addaction">Add new action</a></dt>
+     <dd>go here to add a new action.</dd>
+    </dl>
+    """
+
+    return index(req=req,
+                 title='Role Administration',
+                 subtitle='administration with roles as access point',
+                 body=[output, extra])
+
+
+def perform_actionarea(req):
+    """create the action area menu page."""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    header = ['id', 'name', 'authorizations/roles', 'action', '']
+    actions = acca.acc_getAllActions()
+
+    actions2 = []
+    roles2 = []
+    for (id, name, dontcare) in actions:
+        actions2.append([id, name])
+        for col in [(('add', 'addauthorization'),
+                     ('modify', 'modifyauthorizations'),
+                     ('remove', 'deleteroleaction')),
+                    (('delete', 'deleteaction'), ),
+                    (('show details', 'showactiondetails'), )]:
+            actions2[-1].append('<a href="%s?id_action=%s&amp;reverse=1">%s</a>' % (col[0][1], id, col[0][0]))
+            for (str, function) in col[1:]:
+                actions2[-1][-1] += ' / <a href="%s?id_action=%s&amp;reverse=1">%s</a>' % (function, id, str)
+
+    output  = """
+    <dl>
+     <dt>Authorizations/Roles:</dt>
+     <dd>these terms means almost the same, but an authorization is a <br>
+         connection between a role and an action (possibly) containing arguments.</dd>
+     <dt>Actions:</dt>
+     <dd>see all the information attached to an action and decide if you want to<br>delete it.</dd>
+    </dl>
+    """
+    
+    output += tupletotable(header=header, tuple=actions2)
+
+    extra = """
+    <dl>
+     <dt><a href="addrole">Add new role</a>
+     <dd>go here to add a new role.
+     <dt><a href="addaction">Add new action</a>
+     <dd>go here to add a new action.
+    </dl>
+    """
+
+    return index(req=req,
+                 title='Action Administration',
+                 subtitle='administration with actions as access point',
+                 body=[output, extra])
+
+
+def perform_userarea(req, email_user_pattern=''):
+    """create area to show info about users. """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    subtitle = 'step 1 - search for users'
+
+    output = """
+    <p>
+     search for users to display. 
+    </p> """
+
+    # remove letters not allowed in an email
+    email_user_pattern = cleanstring_email(email_user_pattern)
+        
+    text  = ' <span class="adminlabel">1. search pattern </span>\n'
+    text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, )
+
+    output += createhiddenform(action="userarea",
+                               text=text,
+                               button="search for users")
+
+    if email_user_pattern:
+        users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id LIMIT 26""" % (email_user_pattern, ))
+
+        if not users1:
+            output += '<p>no matching users</p>'
+        else: 
+            subtitle = 'step 2 - select what to do with user'
+
+            users = []
+            for (id, email) in users1[:25]:
+                users.append([id, email])
+                for col in [(('add', 'addroleuser'),
+                             ('remove', 'deleteuserrole')),
+                            (('show details', 'showuserdetails'), )]:
+                    users[-1].append('<a href="%s?email_user_pattern=%s&amp;id_user=%s">%s</a>' % (col[0][1], email_user_pattern, id, col[0][0]))
+                    for (str, function) in col[1:]:
+                        users[-1][-1] += ' / <a href="%s?email_user_pattern=%s&amp;id_user=%s&amp;reverse=1">%s</a>' % (function, email_user_pattern, id, str)
+    
+            output += '<p>found <strong>%s</strong> matching users</p>' % (len(users1), )
+            output += tupletotable(header=['id', 'email', 'roles', ''], tuple=users)
+
+            if len(users1) > 25:
+                output += '<p><strong>only showing the first 25 users, narrow your search...</strong></p>'
+
+    return index(req=req,
+                 title='User Administration',
+                 subtitle=subtitle,
+                 body=[output])
+
+
+def perform_resetarea(req):
+    """create the reset area menu page."""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    output = """
+    <dl>
+     <dt><a href="resetdefaultsettings">Reset to Default Authorizations</a>
+     <dd>Remove all changes that has been done to the roles and <br>
+     add only the default authorization settings.
+     <dt><a href="adddefaultsettings">Add Default Authorizations</a>
+     <dd>Keep all changes and add the default authorization settings.
+    </dl>
+    """
+
+    return index(req=req,
+                 title='Reset Authorizations',
+                 subtitle='reseting to or adding default authorizations',
+                 body=[output])
+
+
+def perform_resetdefaultsettings(req, superusers=[], confirm=0):
+    """delete all roles, actions and authorizations presently in the database
+    and add only the default roles.
+    only selected users will be added to superadmin, rest is blank """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    # cleaning input
+    if type(superusers) == str: superusers = [superusers]
+
+    # remove not valid e-mails
+    for email in superusers:
+        if not check_email(email): superusers.remove(email)
+    
+    # instructions
+    output  = """
+    <p>
+     before you reset the settings, we need some users<br>
+     to connect to <strong>%s</strong>.<br>
+     enter as many e-mail adresses you want and press <strong>reset</strong>.<br>
+     <strong>confirm reset settings</strong> when you have added enough e-mails.<br>
+     <strong><SUPPORTEMAIL></strong> is added as default.
+    </p>""" % (SUPERADMINROLE, )
+
+    # add more superusers
+    output += """
+    <p>enter user e-mail addresses: </p>
+    <form action="resetdefaultsettings" method="POST">"""
+
+    for email in superusers:
+        output += '      <input type="hidden" name="superusers" value="%s" />' % (email, )
+
+    output += """
+     <span class="adminlabel">e-mail</span>
+     <input class="admin_wvar" type="text" name="superusers" />
+     <input class="adminbutton" type="submit" value="add e-mail" />
+    </form>"""
+
+
+    if superusers:
+        # remove emails
+        output += """
+        <form action="resetdefaultsettings" method="POST">
+         have you entered wrong data? 
+         <input class="adminbutton" type="submit" value="remove all e-mails" />
+        </form>
+        """
+        
+        # superusers confirm table
+        start = '<form action="resetdefaultsettings" method="POST">'
+    
+        extra  = ' <input type="hidden" name="confirm" value="1" />'
+        for email in superusers:
+            extra += '<input type="hidden" name="superusers" value="%s" />' % (email, )
+        extra += ' <input class="adminbutton" type="submit" value="confirm to reset settings" />'
+    
+        end    = '</form>'
+    
+        output += '<p><strong>reset default settings</strong> with the users below? </p>'
+        output += tupletotable(header=['e-mail address'],
+                               tuple=superusers,
+                               start=start,
+                               extracolumn=extra,
+                               end=end)
+        
+        if confirm in [1, "1"]:
+            res = acca.acc_reset_default_settings(superusers)
+            if res:
+                  output += '<p>successfully reset default settings</p>'
+            else:
+                  output += '<p>sorry, could not reset default settings</p>'
+    
+    return index(req=req,
+                 title='Reset Default Settings',
+                 subtitle='reset settings',
+                 body=[output])
+
+
+def perform_adddefaultsettings(req, superusers=[], confirm=0):
+    """add the default settings, and keep everything else.
+    probably nothing will be deleted, except if there has been made changes to the defaults."""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    # cleaning input
+    if type(superusers) == str: superusers = [superusers]
+    
+    # remove not valid e-mails
+    for email in superusers:
+        if not check_email(email): superusers.remove(email)
+    
+    # instructions
+    output  = """
+    <p>
+     before you add the settings, we need some users<br>
+     to connect to <strong>%s</strong>.<br>
+     enter as many e-mail adresses you want and press <strong>add</strong>.<br>
+     <strong>confirm add settings</strong> when you have added enough e-mails.<br>
+     <strong><SUPPORTEMAIL></strong> is added as default.
+    </p>""" % (SUPERADMINROLE, )
+
+    # add more superusers
+    output += """
+    <p>enter user e-mail addresses: </p>
+    <form action="adddefaultsettings" method="POST">"""
+
+    for email in superusers:
+        output += '      <input type="hidden" name="superusers" value="%s" />' % (email, )
+
+    output += """
+     <span class="adminlabel">e-mail</span>
+     <input class="admin_wvar" type="text" name="superusers" />
+     <input class="adminbutton" type="submit" value="add e-mail" />
+    </form>
+    """
+
+    if superusers:
+        # remove emails
+        output += """
+        <form action="adddefaultsettings" method="POST">
+         have you entered wrong data? 
+         <input class="adminbutton" type="submit" value="remove all e-mails" />
+        </form>
+        """
+        
+        # superusers confirm table
+        start = '<form action="adddefaultsettings" method="POST">'
+    
+        extra  = ' <input type="hidden" name="confirm" value="1" />'
+        for email in superusers:
+            extra += '<input type="hidden" name="superusers" value="%s" />' % (email, )
+        extra += ' <input class="adminbutton" type="submit" value="confirm to add settings" />'
+    
+        end    = '</form>'
+    
+        output += '<p><strong>add default settings</strong> with the users below? </p>'
+        output += tupletotable(header=['e-mail address'],
+                               tuple=superusers,
+                               start=start,
+                               extracolumn=extra,
+                               end=end)
+
+        if confirm in [1, "1"]:
+            res = acca.acc_add_default_settings(superusers)
+            if res:
+                  output += '<p>successfully added default settings</p>'
+            else:
+                  output += '<p>sorry, could not add default settings</p>'
+    
+    return index(req=req,
+                 title='Add Default Settings',
+                 subtitle='add settings',
+                 body=[output])
+
+
+def perform_delegate_startarea(req):
+    """start area for lower level delegation of rights."""
+
+    subtitle = 'select what to do'
+
+    output = ''
+    
+    if is_adminuser(req):
+        output += """
+        <p>
+         You are also allowed to be in the <a href="../webaccessadmin.py">Main Admin Area</a> which gives you<br>
+         the access to the full functionality of WebAccess.
+        </p>
+        """
+
+    output += """
+    <dl>
+     <dt><a href="delegate_adduserrole">Add users to roles</a>
+     <dd>add users to the roles you have delegation rights to.
+     <dt><a href="delegate_deleteuserrole">Remove users from roles</a>
+     <dd>remove users from the roles you have delegation rights to.
+    </dl>
+    """
+        
+    return index(req=req,
+                 title='Delegate Rights - start area',
+                 subtitle=subtitle, 
+                 body=[output],
+                 authorized=1)
+
+
+def perform_delegate_adduserrole(req, id_role=0, email_user_pattern='', id_user=0, confirm=0):
+    """let a lower level web admin add users to a limited set of roles.
+
+    id_role - the role to connect to a user
+
+    id_user - the user to connect to a role
+
+    confirm - make the connection happen """
+
+    # finding the allowed roles for this user
+    id_admin = getUid(req)
+    id_action = acca.acc_getActionId(name_action=DELEGATEADDUSERROLE) 
+    actions = acca.acc_findPossibleActionsUser(id_user=id_admin, id_action=id_action)
+
+    allowed_roles = []
+    for (id, arglistid, name_role_help) in actions[1:]:
+        id_role_help = acca.acc_getRoleId(name_role=name_role_help)
+        if id_role_help and [id_role_help, name_role_help, ''] not in allowed_roles:
+            allowed_roles.append([id_role_help, name_role_help, ''])
+        
+    output = ''
+
+    if not allowed_roles:
+        subtitle = 'no delegation rights'
+        output += """
+        <p>
+         You do not have the delegation rights over any roles.<br>
+         If you think you should have such rights, contact a WebAccess Administrator.
+        </p>"""
+    else:
+        subtitle = 'step 1 - select role'
+
+        output += """
+        <p>
+         Lower level delegation of access rights to roles.<br>
+         An administrator with all rights have to give you these rights.
+        </p>"""
+
+        email_out = acca.acc_getUserEmail(id_user=id_user)
+        name_role = acca.acc_getRoleName(id_role=id_role)
+
+        output += createroleselect(id_role=id_role, step=1, name='id_role',
+                                   action='delegate_adduserrole', roles=allowed_roles)
+
+        if str(id_role) != '0':
+            subtitle = 'step 2 - search for users'
+
+            # remove letters not allowed in an email
+            email_user_pattern = cleanstring_email(email_user_pattern)
+                
+            text  = ' <span class="adminlabel">2. search pattern </span>\n'
+            text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, )
+    
+            output += createhiddenform(action="delegate_adduserrole",
+                                       text=text,
+                                       button="search for users",
+                                       id_role=id_role)
+    
+            # pattern is entered
+            if email_user_pattern:
+                # users with matching email-address
+                users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id """ % (email_user_pattern, ))
+                # users that are connected
+                users2 = run_sql("""SELECT DISTINCT u.id, u.email
+                FROM user u LEFT JOIN user_accROLE ur ON u.id = ur.id_user
+                WHERE ur.id_accROLE = '%s' AND u.email RLIKE '%s'
+                ORDER BY u.id """ % (id_role, email_user_pattern))
+    
+                # no users that match the pattern
+                if not (users1 or users2):
+                    output += 'no qualified users, try new search'
+                # show matching users
+                else:
+                    subtitle = 'step 3 - select a user'
+                    
+                    users = []
+                    extrausers = []
+                    for (id, email) in users1:
+                        if (id, email) not in users2: users.append([id,email,''])
+                    for (id, email) in users2:
+                        extrausers.append([-id, email,''])
+    
+                    output += createuserselect(id_user=id_user,
+                                               action="delegate_adduserrole",
+                                               step=3,
+                                               users=users,
+                                               extrausers=extrausers,
+                                               button="add this user",
+                                               id_role=id_role,
+                                               email_user_pattern=email_user_pattern)
+    
+                    try: id_user = int(id_user)
+                    except ValueError: pass
+                    # user selected already connected to role
+                    if id_user < 0:
+                        output += '<p>users in brackets are already attached to the role, try another one</p>'
+                    # a user is selected
+                    elif email_out:
+                        subtitle = "step 4 - confirm to add user"
+    
+                        output += createhiddenform(action="delegate_adduserrole",
+                                                   text='add user <strong>%s</strong> to role <strong>%s</strong>?' % (email_out, name_role),
+                                                   id_role=id_role,
+                                                   email_user_pattern=email_user_pattern,
+                                                   id_user=id_user,
+                                                   confirm=1)
+    
+                        # it is confirmed that this user should be added
+                        if confirm:
+                            # add user
+                            result = acca.acc_addUserRole(id_user=id_user, id_role=id_role)
+            
+                            if result and result[2]: 
+                                subtitle = 'step 5 - confirm user added'
+                                output  += '<p>confirm: user <strong>%s</strong> added to role <strong>%s</strong>.</p>' % (email_out, name_role)
+                            else:
+                                subtitle = 'step 5 - user could not be added'
+                                output += '<p>sorry, but user could not be added.</p>'
+                
+    return index(req=req,
+                 title='Delegate Rights - add users to roles',
+                 subtitle=subtitle, 
+                 body=[output],
+                 authorized=1)
+
+
+def perform_delegate_deleteuserrole(req, id_role=0, id_user=0, confirm=0):
+    """let a lower level web admin remove users from a limited set of roles.
+
+    id_role - the role to connect to a user
+
+    id_user - the user to connect to a role
+
+    confirm - make the connection happen """
+
+    subtitle = 'in progress...'
+
+    output = '<p>in progress...</p>'
+
+    # finding the allowed roles for this user
+    id_admin = getUid(req)
+    id_action = acca.acc_getActionId(name_action=DELEGATEADDUSERROLE)
+    actions = acca.acc_findPossibleActionsUser(id_user=id_admin, id_action=id_action)
+
+    output = ''
+
+    if not actions:
+        subtitle = 'no delegation rights'
+        output += """
+        <p>
+         You do not have the delegation rights over any roles.<br>
+         If you think you should have such rights, contact a WebAccess Administrator.
+        </p>"""
+    else:
+        subtitle = 'step 1 - select role'
+
+        output += """
+        <p>
+         Lower level delegation of access rights to roles.<br>
+         An administrator with all rights have to give you these rights.
+        </p>"""
+
+        email_out = acca.acc_getUserEmail(id_user=id_user)
+        name_role = acca.acc_getRoleName(id_role=id_role)
+
+        allowed_roles = []
+        for (id, arglistid, name_role_help) in actions[1:]:
+            id_role_help = acca.acc_getRoleId(name_role=name_role_help)
+            if id_role_help and [id_role_help, name_role_help, ''] not in allowed_roles:
+                allowed_roles.append([id_role_help, name_role_help, ''])
+        
+        output += createroleselect(id_role=id_role, step=1,
+                                   action='delegate_deleteuserrole', roles=allowed_roles)
+
+        if str(id_role) != '0':
+            subtitle = 'step 2 - select user'
+            
+            users = acca.acc_getRoleUsers(id_role)
+
+            output += createuserselect(id_user=id_user, step=2,
+                                       action='delegate_deleteuserrole', users=users,
+                                       id_role=id_role)
+
+            if str(id_user) != '0':
+                subtitle = 'step 3 - confirm delete of user'
+                email_user = acca.acc_getUserEmail(id_user=id_user)
+                
+                output += createhiddenform(action="delegate_deleteuserrole",
+                                           text='delete user %s from %s?'
+                                           % (headerstrong(user=id_user), headerstrong(role=id_role)),
+                                           id_role=id_role,
+                                           id_user=id_user,
+                                           confirm=1)
+        
+                if confirm:
+                    res = acca.acc_deleteUserRole(id_user=id_user, id_role=id_role)
+                    if res:
+                        subtitle = 'step 4 - confirm user deleted from role'
+                        output += '<p>confirm: deleted user <strong>%s</strong> from role <strong>%s</strong>.</p>' % (email_user, name_role)
+                    else:
+                        subtitle = 'step 4 - user could not be deleted'
+                        output += 'sorry, but user could not be deleted<br>user is probably already deleted.'
+
+    return index(req=req,
+                 title='Delegate Rights - remove users from roles',
+                 subtitle=subtitle, 
+                 body=[output],
+                 authorized=1)
+
+
+def perform_addaction(req, name_action='', arguments='', optional='no', description='put description here.', confirm=0):
+    """form to add a new action with these values:
+
+    name_action - name of the new action
+
+      arguments - allowedkeywords, separated by whitespace
+
+    description - optional description of the action"""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    name_action = cleanstring(name_action)
+    arguments = cleanstring(arguments, comma=1)
+
+    title = 'Add Action'
+    subtitle = 'step 1 - give values to the requested fields'
+
+    output  = """
+    <form action="addaction" method="POST">
+     <span class="adminlabel">action name </span>
+     <input class="admin_wvar" type="text" name="name_action" value="%s" /> <br> 
+     <span class="adminlabel">arguments </span>
+     <input class="admin_wvar" type="text" name="arguments" value="%s" /> 
+     <small>keywords for arguments, separate with comma, no whitespace.</small> <br>
+     <span class="adminlabel">optional arguments</span>
+     <select name="optional" class="admin_w200">
+      <option value="no" selected="selected">no, not allowed</option>
+      <option value="yes" %s>yes, allowed</option>
+     </select><br>
+     <span class="adminlabel">description </span>
+     <textarea class="admin_wvar" rows="6" cols="30" name="description">%s</textarea> 
+     <input class="adminbutton" type="submit" value="add action" />
+    </form>
+    """ % (name_action, arguments, optional == 'yes' and 'selected="selected"' or '', description)
+
+    if name_action:
+        # description must be changed before it is submitted
+        if description == 'put description here.': internaldesc = ''
+        else: internaldesc = description
+        
+        if arguments:
+            subtitle = 'step 2 - confirm to add action with %s arguments' % (optional == 'yes' and 'optional' or '', )
+            arguments = arguments.replace(' ', '')
+            text  = 'add action with: <br>\n'
+            text += 'name: <strong>%s</strong><br>\n' % (name_action, )
+            if internaldesc:
+                text += 'description: <strong>%s</strong><br>\n' % (description, )
+            text += '%sarguments: <strong>%s</strong><br>' % (optional == 'yes' and 'optional ' or '', arguments)
+            text += 'optional: <strong>%s</strong>?' % (optional, )
+        
+        else:
+            optional = 'no'
+            subtitle = 'step 2 - confirm to add action without arguments'
+            text = 'add action <strong>%s</strong> without arguments' % (name_action, )
+            if internaldesc: text += '<br>\nand description: <strong>%s</strong>?\n' % (description, )
+            else: text += '?\n'
+            
+        output += createhiddenform(action="addaction",
+                                   text=text,
+                                   name_action=name_action,
+                                   arguments=arguments,
+                                   optional=optional, 
+                                   description=description,
+                                   confirm=1)
+
+        if confirm not in ["0", 0]:
+            arguments = arguments.split(',')
+            result = acca.acc_addAction(name_action,
+                                        internaldesc,
+                                        optional,
+                                        *arguments)
+
+            if result:
+                subtitle = 'step 3 - action added'
+                output += '<p>action added:</p>'
+                output += tupletotable(header=['id', 'action name', 'description', 'allowedkeywords', 'optional'],
+                                      tuple=[result])
+            else:
+                subtitle = 'step 3 - action could not be added'
+                output += '<p>sorry, could not add action, <br>action with the same name probably exists.</p>'
+                
+            extra = """
+            <dl>
+             <dt><a href="addauthorization?id_action=%s&amp;reverse=1">Add authorization</a></dt>
+             <dd>start adding new authorizations to this action.</dd>
+            </dl> """ % (acca.acc_getActionId(name_action=name_action, ))
+
+    try: body = [output, extra]
+    except NameError: body = [output]
+
+    return index(req=req,
+                 title=title,
+                 body=body,
+                 subtitle=subtitle)
+
+
+def perform_deleteaction(req, id_action="0", confirm=0):
+    """show all roles connected, and ask for confirmation.
+
+    id_action - id of action to delete """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    title='Delete Action'
+    subtitle='step 1 - select action to delete'
+    name_action = acca.acc_getActionName(id_action=id_action)
+
+    output = createactionselect(id_action=id_action,
+                                action="deleteaction",
+                                step=1,
+                                actions=acca.acc_getAllActions(),
+                                button="delete action")
+
+    if id_action != "0":
+        subtitle = 'step 2 - confirm the delete'
+
+        output += actiondetails(id_action=id_action)
+
+        if acca.acc_getActionRoles(id_action=id_action):
+            output += createhiddenform(action="deleteroleaction",
+                                       text="""rather delete only connection between this action
+                                       and a selected role?""",
+                                       id_action=id_action,
+                                       reverse=1,
+                                       button='go there')
+        
+        output += createhiddenform(action="deleteaction",
+                                   text=' delete action <strong>%s</strong> and all connections?' % (name_action, ),
+                                   confirm=1,
+                                   id_action=id_action)
+        
+    if confirm:
+        subtitle = 'step 3 - confirm delete of action'
+        res = acca.acc_deleteAction(id_action=id_action)
+        if res:
+            output += '<p>confirm: action <strong>%s</strong> deleted.<br>\n' % (name_action, )
+            output += '%s entries deleted all in all.</p>\n' % (res, )
+        else:
+            output += '<p>sorry, action could not be deleted.</p>\n'
+    
+    return index(req=req,
+                 title=title,
+                 subtitle=subtitle,
+                 body=[output])
+
+
+def perform_showactiondetails(req, id_action):
+    """show the details of an action. """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    if id_action not in [0, '0']:
+        output = actiondetails(id_action=id_action)
+
+        extra = """
+        <dl>
+         <dt><a href="addauthorization?id_action=%s&amp;reverse=1">Add new authorization</a></dt>
+         <dd>add an authorization.</dd>
+         <dt><a href="modifyauthorizations?id_action=%s&amp;reverse=1">Modify authorizations</a></dt>
+         <dd>modify existing authorizations.</dd>
+        </dl>
+        """ % (id_action, id_action)
+        body = [output, extra]
+        
+    else:
+        body = ['<p>no details to show</p>']
+
+    return index(req=req,
+                 title='Show Action Details',
+                 subtitle='show action details',
+                 body=body)
+
+
+def actiondetails(id_action=0):
+    """show details of given action. """
+
+    output = ''
+
+    if id_action not in [0, '0']:
+        name_action = acca.acc_getActionName(id_action=id_action)
+
+        output += '<p>action details:</p>'
+        output += tupletotable(header=['id', 'name', 'description', 'allowedkeywords', 'optional'],
+                               tuple=[acca.acc_getActionDetails(id_action=id_action)])
+    
+        roleshlp = acca.acc_getActionRoles(id_action=id_action)
+        if roleshlp: 
+            roles = []
+            for (id, name, dontcare) in roleshlp:
+                roles.append([id, name,
+                              '<a href="simpleauthorization?id_role=%s&amp;id_action=%s">show authorization details</a>'
+                              % (id, id_action),
+                              '<a href="simpleroleusers?id_role=%s">show connected users</a>' % (id, )])
+            roletable = tupletotable(header=['id', 'name', '', ''], tuple=roles)
+            
+            output += '<p>roles connected to %s:</p>\n' % (headerstrong(action=name_action, query=0), )
+            output += roletable
+    
+        else:
+            output += '<p>no roles connected to %s.</p>\n' % (headerstrong(action=name_action, query=0), )
+
+    else:
+        output += '<p>no details to show</p>'
+    
+    return output
+
+
+def perform_addrole(req, name_role='', description='put description here.', confirm=0):
+    """form to add a new role with these values:
+    
+      name_role - name of the new role
+
+    description - optional description of the role """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    name_role = cleanstring(name_role)
+
+    title='Add Role'
+    subtitle = 'step 1 - give values to the requested fields'
+
+    output = """
+    <form action="addrole" method="POST">
+     <span class="adminlabel">role name </span>
+     <input class="admin_wvar" type="text" name="name_role" value="%s" /> <br>
+     <span class="adminlabel">description </span>
+     <textarea class="admin_wvar" rows="6" cols="30" name="description">%s</textarea>
+     <input class="adminbutton" type="submit" value="add role" />
+    </form>
+    """ % (name_role, description)
+    
+    if name_role:
+        # description must be changed before submitting
+        subtitle = 'step 2 - confirm to add role'
+        internaldesc = ''
+        if description != 'put description here.':
+            internaldesc = description
+            
+        text = """
+        add role with: <br>\n
+        name: <strong>%s</strong> <br>""" % (name_role, )
+        if internaldesc:
+            text += 'description: <strong>%s</strong>?\n' % (description, )
+            
+        output += createhiddenform(action="addrole",
+                                   text=text,
+                                   name_role=name_role,
+                                   description=description,
+                                   confirm=1)
+        
+        if confirm not in ["0", 0]:
+            result = acca.acc_addRole(name_role=name_role,
+                                      description=internaldesc)
+            
+            if result:
+                subtitle = 'step 3 - role added'
+                output += '<p>role added: </p>'
+                output += tupletotable(header=['id', 'action name', 'description', 'allowedkeywords'],
+                                       tuple=[result])
+            else:
+                subtitle = 'step 3 - role could not be added'
+                output += '<p>sorry, could not add role, <br>role with the same name probably exists.</p>'
+
+            extra = """
+            <dl>
+             <dt><a href="addauthorization?id_role=%s">Add authorization</a></dt>
+             <dd>start adding new authorizations to this role.</dd>
+            </dl> """ % (acca.acc_getRoleId(name_role=name_role), )
+
+    try: body = [output, extra]
+    except NameError: body = [output]
+
+    return index(req=req,
+                 title=title,
+                 body=body,
+                 subtitle=subtitle)
+
+
+def perform_deleterole(req, id_role="0", confirm=0):
+    """select a role and show all connected information,
+
+      users - users that can access the role.
+
+    actions - actions with possible authorizations."""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    title = 'Delete role'
+    subtitle = 'step 1 - select role to delete'
+    name_role = id_role
+
+    name_role = acca.acc_getRoleName(id_role=id_role)
+    output = createroleselect(id_role=id_role,
+                              action="deleterole",
+                              step=1,
+                              roles=acca.acc_getAllRoles(),
+                              button="delete role")
+
+    if id_role != "0":
+        subtitle = 'step 2 - confirm delete of role'
+
+        output += roledetails(id_role=id_role)
+
+        output += createhiddenform(action="deleterole",
+                                   text='delete role <strong>%s</strong> and all connections?' % (name_role, ),
+                                   id_role=id_role,
+                                   confirm=1)
+
+        if confirm:
+            res = acca.acc_deleteRole(id_role=id_role)
+            subtitle = 'step 3 - confirm role deleted'
+            if res:
+                output += "<p>confirm: role <strong>%s</strong> deleted.<br>" % (name_role, )
+                output += "<strong>%s</strong> entries were removed.</p>" % (res, )
+            else:
+                output += "<p>sorry, the role could not be deleted.</p>"
+
+    return index(req=req,
+                 title=title,
+                 subtitle=subtitle,                 
+                 body=[output])
+
+
+def perform_showroledetails(req, id_role):
+    """show the details of a role."""
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    if id_role not in [0, '0']:
+        output = roledetails(id_role=id_role)
+            
+        extra = """
+        <dl>
+         <dt><a href="adduserrole?id_role=%s">Connect user</a></dt>
+         <dd>connect a user to the role.</dd>
+         <dt><a href="addauthorization?id_role=%s">Add new authorization</a></dt>
+         <dd>add an authorization.</dd>
+         <dt><a href="modifyauthorizations?id_role=%s">Modify authorizations</a></dt>
+         <dd>modify existing authorizations.</dd>
+        </dl>
+        """ % (id_role, id_role, id_role)
+        body = [output, extra]
+    
+    else:
+        body = ['<p>no details to show</p>']
+    
+    return index(req=req,
+                 title='Show Role Details',
+                 subtitle='show role details',
+                 body=body)
+
+
+def roledetails(id_role=0):
+    """create the string to show details about a role. """
+
+    name_role = acca.acc_getRoleName(id_role=id_role)
+
+    usershlp = acca.acc_getRoleUsers(id_role)
+    users = []
+    for (id, email, dontcare) in usershlp:
+        users.append([id, email, '<a href="showuserdetails?id_user=%s">show user details</a>' % (id, )])
+    usertable = tupletotable(header=['id', 'email'], tuple=users)
+    
+    actionshlp = acca.acc_getRoleActions(id_role)
+    actions = []
+    for (id, name, dontcare) in actionshlp:
+        actions.append([id, name,
+                        '<a href="showactiondetails?id_role=%s&amp;id_action=%s">show action details</a>' % (id_role, id),
+                        '<a href="simpleauthorization?id_role=%s&amp;id_action=%s">show authorization details</a>' % (id_role, id)])
+        
+    actiontable = tupletotable(header=['id', 'name', '', ''], tuple=actions)
+
+    # show role details
+    details  = '<p>role details:</p>'
+    details += tupletotable(header=['id', 'name', 'description'],
+                            tuple=[acca.acc_getRoleDetails(id_role=id_role)])
+
+    # show connected users
+    details += '<p>users connected to %s:</p>' % (headerstrong(role=name_role, query=0), )
+    if users: 
+        details += usertable
+    else:
+        details += '<p>no users connected.</p>'
+    # show connected authorizations
+    details += '<p>authorizations for %s:</p>' % (headerstrong(role=name_role, query=0), )
+    if actions: 
+        details += actiontable
+    else:
+        details += '<p>no authorizations connected</p>'
+
+    return details 
+
+
+
+def perform_adduserrole(req, id_role='0', email_user_pattern='', id_user='0', confirm=0):
+    """create connection between user and role.
+
+               id_role - id of the role to add user to
+
+    email_user_pattern - search for users using this pattern
+
+               id_user - id of user to add to the role. """
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    email_out = acca.acc_getUserEmail(id_user=id_user)
+    name_role = acca.acc_getRoleName(id_role=id_role)
+    
+    title = 'Add user to role '
+    subtitle = 'step 1 - select a role'
+
+    output = createroleselect(id_role=id_role,
+                              action="adduserrole",
+                              step=1,
+                              roles=acca.acc_getAllRoles())
+
+    # role is selected
+    if id_role != "0":
+        title += name_role
+        
+        subtitle = 'step 2 - search for users'
+
+        # remove letters not allowed in an email
+        email_user_pattern = cleanstring_email(email_user_pattern)
+            
+        text  = ' <span class="adminlabel">2. search pattern </span>\n'
+        text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, )
+
+        output += createhiddenform(action="adduserrole",
+                                   text=text,
+                                   button="search for users",
+                                   id_role=id_role)
+
+        # pattern is entered
+        if email_user_pattern:
+            # users with matching email-address
+            users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id """ % (email_user_pattern, ))
+            # users that are connected
+            users2 = run_sql("""SELECT DISTINCT u.id, u.email
+            FROM user u LEFT JOIN user_accROLE ur ON u.id = ur.id_user
+            WHERE ur.id_accROLE = '%s' AND u.email RLIKE '%s'
+            ORDER BY u.id """ % (id_role, email_user_pattern))
+
+            # no users that match the pattern
+            if not (users1 or users2):
+                output += 'no qualified users, try new search'
+            # show matching users
+            else:
+                subtitle = 'step 3 - select a user'
+                
+                users = []
+                extrausers = []
+                for (id, email) in users1:
+                    if (id, email) not in users2: users.append([id,email,''])
+                for (id, email) in users2:
+                    extrausers.append([-id, email,''])
+
+                output += createuserselect(id_user=id_user,
+                                           action="adduserrole",
+                                           step=3,
+                                           users=users,
+                                           extrausers=extrausers,
+                                           button="add this user",
+                                           id_role=id_role,
+                                           email_user_pattern=email_user_pattern)
+
+                try: id_user = int(id_user)
+                except ValueError: pass
+                # user selected already connected to role
+                if id_user < 0:
+                    output += '<p>users in brackets are already attached to the role, try another one</p>'
+                # a user is selected
+                elif email_out:
+                    subtitle = "step 4 - confirm to add user"
+
+                    output += createhiddenform(action="adduserrole",
+                                               text='add user <strong>%s</strong> to role <strong>%s</strong>?' % (email_out, name_role),
+                                               id_role=id_role,
+                                               email_user_pattern=email_user_pattern,
+                                               id_user=id_user,
+                                               confirm=1)
+
+                    # it is confirmed that this user should be added
+                    if confirm:
+                        # add user
+                        result = acca.acc_addUserRole(id_user=id_user, id_role=id_role)
+        
+                        if result and result[2]: 
+                            subtitle = 'step 5 - confirm user added'
+                            output  += '<p>confirm: user <strong>%s</strong> added to role <strong>%s</strong>.</p>' % (email_out, name_role)
+                        else:
+                            subtitle = 'step 5 - user could not be added'
+                            output += '<p>sorry, but user could not be added.</p>'
+            
+    extra = """
+    <dl>
+     <dt><a href="addrole">Add new role</a></dt>
+     <dd>go here to add a new role.</dd>
+    </dl>
+    """
+
+    return index(req=req,
+                 title=title,
+                 subtitle=subtitle,
+                 body=[output, extra])
+
+
+def perform_addroleuser(req, email_user_pattern='', id_user='0', id_role='0', confirm=0):
+    """delete connection between role and user.
+
+    id_role - id of role to disconnect
+
+    id_user - id of user to disconnect. """
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    email_out = acca.acc_getUserEmail(id_user=id_user)
+    name_role = acca.acc_getRoleName(id_role=id_role)
+
+    title = 'Connect user to roles'
+    subtitle = 'step 1 - search for users'
+
+    # clean email search string
+    email_user_pattern = cleanstring_email(email_user_pattern)
+        
+    text  = ' <span class="adminlabel">1. search pattern </span>\n'
+    text += ' <input class="admin_wvar" type="text" name="email_user_pattern" value="%s" />\n' % (email_user_pattern, )
+
+    output = createhiddenform(action='addroleuser',
+                               text=text,
+                               button='search for users',
+                               id_role=id_role)
+    
+    if email_user_pattern:
+        subtitle = 'step 2 - select user'
+
+        users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE '%s' ORDER BY id """ % (email_user_pattern, ))
+        users = []
+        for (id, email) in users1: users.append([id, email, ''])
+
+        if not users:
+            output += '<p>no qualified users, try new search</p>'
+        else:
+            output += createuserselect(id_user=id_user,
+                                       action='addroleuser',
+                                       step=2,
+                                       users=users,
+                                       button='select user',
+                                       email_user_pattern=email_user_pattern)
+
+            if int(id_user):
+                subtitle = 'step 3 - select role'
+
+                # roles the user is connected to
+                role_ids = acca.acc_getUserRoles(id_user=id_user)
+                # all the roles
+                all_roles = acca.acc_getAllRoles()
+
+                # sort the roles in connected and not connected roles
+                con_roles = []
+                not_roles = []
+                for (id, name, description) in all_roles:
+                    if (id, ) in role_ids: con_roles.append([-id, name, description])
+                    else: not_roles.append([id, name, description])
+
+                # create roleselect
+                output += createroleselect(id_role=id_role,
+                                           action='addroleuser',
+                                           step=3,
+                                           roles=not_roles,
+                                           extraroles=con_roles,
+                                           button='add this role',
+                                           email_user_pattern=email_user_pattern,
+                                           id_user=id_user)
+
+                if int(id_role) < 0:
+                    output += '<p>roles in brackets are already connected to the user, try another one<p>'
+                elif int(id_role):
+                    subtitle = 'step 4 - confirm to add role to user'
+
+                    output += createhiddenform(action='addroleuser',
+                                               text='add role <strong>%s</strong> to user <strong>%s</strong>?' % (name_role, email_out),
+                                               email_user_pattern=email_user_pattern,
+                                               id_user=id_user,
+                                               id_role=id_role,
+                                               confirm=1)
+
+                    if confirm:
+                        # add role
+                        result = acca.acc_addUserRole(id_user=id_user, id_role=id_role)
+
+                        if result and result[2]:
+                            subtitle = 'step 5 - confirm role added'
+                            output  += '<p>confirm: role <strong>%s</strong> added to user <strong>%s</strong>.</p>' % (name_role, email_out)
+                        else:
+                            subtitle = 'step 5 - role could not be added'
+                            output += '<p>sorry, but role could not be added</p>'
+
+    extra = """
+    <dl>
+     <dt><a href="addrole">Add new role</a></dt>
+     <dd>go here to add a new role.</dd>
+    </dl>
+    """
+
+    return index(req=req,
+                 title=title,
+                 subtitle=subtitle,
+                 body=[output, extra])
+
+
+def perform_deleteuserrole(req, id_role='0', id_user='0', reverse=0, confirm=0):
+    """delete connection between role and user.
+
+    id_role - id of role to disconnect
+
+    id_user - id of user to disconnect. """
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    title = 'Delete user from role'
+    email_user = acca.acc_getUserEmail(id_user=id_user)
+    name_role = acca.acc_getRoleName(id_role=id_role)
+
+    output = ''
+
+    if reverse in [0, '0']: 
+        subtitle='step 1 - select the role'
+        output += createroleselect(id_role=id_role,
+                                   action="deleteuserrole",
+                                   step=1,
+                                   roles=acca.acc_getAllRoles())
+            
+        if id_role != "0":
+            subtitle = 'step 2 - select the user'
+            output += createuserselect(id_user=id_user,
+                                       action="deleteuserrole",
+                                       step=2,
+                                       users=acca.acc_getRoleUsers(id_role=id_role),
+                                       id_role=id_role)
+
+    else:
+        # show only users connected to a role
+        users = run_sql("""SELECT DISTINCT(u.id), u.email, u.note
+        FROM user u LEFT JOIN user_accROLE ur
+        ON u.id = ur.id_user
+        WHERE ur.id_accROLE != 'NULL' AND u.email != ''
+        ORDER BY id """)
+
+        has_roles = 1
+        
+        # check if the user is connected to any roles
+        for (id, email, note) in users:
+            if str(id) == str(id_user): break
+        else:
+            subtitle = 'step 1 - user not connected'
+            output += '<p>no need to remove roles from this user,<br>user <strong>%s</strong> is not connected to any roles.</p>' % (email_user, )
+            has_roles, id_user = 0, '0' # stop the rest of the output below...
+            
+        
+        if has_roles:
+            output += createuserselect(id_user=id_user,
+                                      action="deleteuserrole",
+                                      step=1,
+                                      users=users,
+                                      reverse=reverse)
+        
+            if id_user != "0":
+                subtitle = 'step 2 - select the user'
+    
+                role_ids = acca.acc_getUserRoles(id_user=id_user)
+                all_roles = run_sql("""SELECT id, name, description FROM accROLE ORDER BY id """)
+                roles = []
+                for (id, name, desc) in all_roles:
+                    if (id, ) in role_ids: roles.append([id, name, desc])
+                
+                output += createroleselect(id_role=id_role,
+                                           action="deleteuserrole",
+                                           step=2,
+                                           roles=roles,
+                                           id_user=id_user,
+                                           reverse=reverse)
+    
+    if id_role != '0' and id_user != '0':
+        subtitle = 'step 3 - confirm delete of user'
+        output += createhiddenform(action="deleteuserrole",
+                                   text='<span class="adminlabel">3. confirm</span> delete user %s from %s?' % (headerstrong(user=id_user), headerstrong(role=id_role)),
+                                   id_role=id_role,
+                                   id_user=id_user,
+                                   reverse=reverse,
+                                   confirm=1)
+
+        if confirm:
+            res = acca.acc_deleteUserRole(id_user=id_user, id_role=id_role)
+            if res:
+                subtitle = 'step 4 - confirm delete of user'
+                output += '<p>confirm: deleted user <strong>%s</strong> from role <strong>%s</strong>.</p>' % (email_user, name_role)
+            else:
+                subtitle = 'step 4 - user could not be deleted'
+                output += 'sorry, but user could not be deleted<br>user is probably already deleted.'
+            
+    return index(req=req,
+                 title=title,
+                 subtitle=subtitle,
+                 body=[output])
+
+
+def perform_showuserdetails(req, id_user=0):
+    """show the details of a user. """
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    if id_user not in [0, '0']:
+        output = userdetails(id_user=id_user)
+
+        extra = """
+        <dl>
+         <dt><a href="addroleuser?id_user=%s">Connect role</a></dt>
+         <dd>connect a role to the user.</dd>
+        </dl>
+        """ % (id_user, )
+
+        body = [output, extra]
+    else:
+        body = ['<p>no details to show</p>']
+
+    return index(req=req,
+                 title='Show User Details',
+                 subtitle='show user details',
+                 body=body)
+
+
+def userdetails(id_user=0):
+    """create the string to show details about a user. """
+
+    # find necessary details
+    email_user = acca.acc_getUserEmail(id_user=id_user)
+
+    userroles = acca.acc_getUserRoles(id_user=id_user)
+    conn_roles = []
+
+    # find connected roles
+    for (id, name, desc) in acca.acc_getAllRoles():
+        if (id, ) in userroles:
+            conn_roles.append([id, name, desc])
+            conn_roles[-1].append('<a href="showroledetails?id_role=%s">show details</a>' % (id, ))
+
+    if conn_roles: 
+        # print details
+        details  = '<p>roles connected to user <strong>%s</strong></p>' % (email_user, )
+        details += tupletotable(header=['id', 'name', 'description', ''], tuple=conn_roles)
+    else:
+        details  = '<p>no roles connected to user <strong>%s</strong>.</p>' % (email_user, )
+
+    return details
+
+def perform_addauthorization(req, id_role="0", id_action="0", optional=0, reverse="0", confirm=0, **keywords):
+    """ form to add new connection between user and role:
+
+      id_role - role to connect 
+
+    id_action - action to connect
+
+      reverse - role or action first? """
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    # values that might get used
+    name_role = acca.acc_getRoleName(id_role=id_role) or id_role
+    name_action = acca.acc_getActionName(id_action=id_action) or id_action
+    optional = optional == 'on' and 1 or int(optional)
+    
+    extra = """
+    <dl>
+     <dt><a href="addrole">Add new role</a></dt>
+     <dd>go here to add a new role.</dd>
+     <dt><a href="addaction">Add new action</a></dt>
+     <dd>go here to add a new action.</dd>
+    </dl>
+    """
+
+    # create the page according to which step the user is on
+    # role -> action -> arguments
+    if reverse in ["0", 0]:
+        subtitle = 'step 1 - select role'
+        output = createroleselect(id_role=id_role,
+                                  action="addauthorization",
+                                  step=1,
+                                  roles=acca.acc_getAllRoles(),
+                                  reverse=reverse)
+        if id_role != "0":
+            subtitle = 'step 2 - select action'
+            rolacts = acca.acc_getRoleActions(id_role)
+            allhelp = acca.acc_getAllActions()
+            allacts = []
+            for r in allhelp:
+                if r not in rolacts: allacts.append(r)
+            output += createactionselect(id_action=id_action,
+                                         action="addauthorization",
+                                         step=2,
+                                         actions=rolacts,
+                                         extraactions=allacts,
+                                         id_role=id_role,
+                                         reverse=reverse)
+    # action -> role -> arguments
+    else:
+        subtitle = 'step 1 - select action'
+        output = createactionselect(id_action=id_action,
+                                    action="addauthorization",
+                                    step=1,
+                                    actions=acca.acc_getAllActions(),
+                                    reverse=reverse)
+        if id_action != "0":
+            subtitle = 'step 2 - select role'
+            actroles = acca.acc_getActionRoles(id_action)
+            allhelp = acca.acc_getAllRoles()
+            allroles = []
+            for r in allhelp:
+                if r not in actroles: allroles.append(r)
+            output += createroleselect(id_role=id_role,
+                                       action="addauthorization",
+                                       step=2,
+                                       roles=actroles,
+                                       extraroles=allroles,
+                                       id_action=id_action,
+                                       reverse=reverse)
+
+    # ready for step 3 no matter which direction we took to get here
+    if id_action != "0" and id_role != "0":
+        subtitle = 'step 3 - enter values for the keywords\n'
+
+        output += """
+        <form action="addauthorization" method="POST">
+         <input type="hidden" name="id_role" value="%s">
+         <input type="hidden" name="id_action" value="%s">
+         <input type="hidden" name="reverse" value="%s">
+        """  % (id_role, id_action, reverse)
+         
+        res_keys = acca.acc_getActionKeywords(id_action=id_action)
+
+        if not res_keys:
+            output += """
+             <input type="hidden" name="confirm" value="1">
+              create connection between %s?
+             <input class="adminbutton" type="submit" value="confirm">
+            </form>
+            """ % (headerstrong(role=name_role, action=name_action, query=0), )
+
+                   
+        else:
+            optionalargs = acca.acc_getActionIsOptional(id_action=id_action)
+
+            output += '<span class="adminlabel">3. arguments</span><br>'
+            if optionalargs:
+                output += """
+                <p>
+                 <input type="checkbox" name="optional" %s />
+                 create connection without the need for arguments
+                </p>
+                """ % (optional and 'checked="checked"' or '', )
+                
+            allkeys = 1
+            for key in res_keys:
+                output += '<span class="adminlabel">%s </span>\n <input class="admin_wvar" type="text" name="%s"' % (key, key)
+                try:
+                    val = keywords[key] = cleanstring_argumentvalue(keywords[key])
+                    if val: output += 'value="%s" ' % (val, )
+                    else: allkeys = 0
+                except KeyError: allkeys = 0
+                output += ' /> <br>\n'
+            output = output[:-5] + ' <input class="adminbutton" type="submit" value="create entry -->" />\n'
+            output += '</form>\n'
+
+            # ask for confirmation
+            if allkeys not in ["0", 0] or optional:
+                keys = keywords.keys()
+                keys.reverse()
+                subtitle = 'step 4 - confirm add of authorization\n'
+
+                text = """
+                create connection between <br>
+                %s <br>
+                """ % (headerstrong(role=name_role, action=name_action, query=0), )
+
+                if optional:
+                    text += 'withouth arguments'
+                    keywords = {}
+                else:
+                    for key in keys:
+                        text += '<strong>%s</strong>: %s \n' % (key, keywords[key])
+                
+                output += createhiddenform(action="addauthorization",
+                                           text=text,
+                                           id_role=id_role,
+                                           id_action=id_action,
+                                           reverse=reverse,
+                                           confirm=1,
+                                           optional=optional,
+                                           **keywords)
+
+        # show existing authorizations
+        res = acca.acc_findPossibleActions(id_role, id_action)
+        output += '<p>existing authorizations:</p>'
+        if res:
+            output += tupletotable(header=res[0], tuple=res[1:])
+            # shortcut to modifying authorizations
+            extra += """
+            <dl>
+             <dt><a href="modifyauthorizations?id_role=%s&amp;id_action=%s&amp;reverse=%s">Modify authorizations</a></dt>
+             <dd>modify the existing authorizations.<dd>
+            </dl> """ % (id_role, id_action, reverse)
+
+        else:   output += '<p>no details to show</p>'
+
+
+    # user confirmed to add entries
+    if confirm: 
+        subtitle = 'step 5 - confirm authorization added'
+        res1 = acca.acc_addRoleActionArguments_names(name_role=name_role,
+                                                     name_action=name_action,
+                                                     arglistid=-1,
+                                                     optional=optional,
+                                                     **keywords)
+        # newentries = ''
+    
+        if res1:
+            res2 = acca.acc_findPossibleActions(id_role, id_action)
+            arg = res1[0][3] # the arglistid
+            new = [res2[0]]
+            for row in res2[1:]:
+                if row[0] == arg: new.append(row)
+    
+            newauths = tupletotable(header=new[0], tuple=new[1:])
+            newentries = tupletotable(header=['role id', 'action id', 'argument id', '#'], tuple=res1)
+
+            st = 'style="vertical-align: top"'
+            output += """
+            <p>new authorization and entries:</p>
+            <table><tr>
+             <td class="admintd" %s>%s</td>
+             <td class="admintd" %s>%s</td>
+            </tr></table> """ % (st, newauths, st, newentries)
+
+        else: output += '<p>sorry, authorization could not be added,<br>it probably already exists</p>'
+
+    # trying to put extra link on the right side
+    try: body = [output, extra]
+    except NameError: body = [output]
+
+    return index(req=req,
+                 title = 'Create entry for new authorization',
+                 subtitle=subtitle,
+                 body=body) 
+
+
+def perform_deleteroleaction(req, id_role="0", id_action="0", reverse=0, confirm=0):
+    """delete all connections between a role and an action.
+
+      id_role - id of the role
+
+    id_action - id of the action
+
+      reverse - 0: ask for role first
+                1: ask for action first"""
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    title = 'Remove action from role '
+    
+    if reverse in ["0", 0]:
+        # select role -> action
+        subtitle = 'step 1 - select a role'
+        output  = createroleselect(id_role=id_role,
+                                   action="deleteroleaction",
+                                   step=1,
+                                   roles=acca.acc_getAllRoles(),
+                                   reverse=reverse)
+        
+        if id_role != "0":
+            rolacts = acca.acc_getRoleActions(id_role=id_role)
+            subtitle = 'step 2 - select the action'
+            output += createactionselect(id_action=id_action,
+                                         action="deleteroleaction",
+                                         step=2,
+                                         actions=rolacts,
+                                         reverse=reverse,
+                                         id_role=id_role,
+                                         button="remove connection and all authorizations")
+    else:
+        # select action -> role
+        subtitle = 'step 1 - select an action'
+        output = createactionselect(id_action=id_action,
+                                    action="deleteroleaction",
+                                    step=1,
+                                    actions=acca.acc_getAllActions(),
+                                    reverse=reverse)
+        
+        if id_action != "0":
+            actroles = acca.acc_getActionRoles(id_action=id_action)
+            subtitle = 'step 2 - select the role'
+            output += createroleselect(id_role=id_role,
+                                       action="deleteroleaction",
+                                       step=2,
+                                       roles=actroles,
+                                       button="remove connection and all authorizations", 
+                                       id_action=id_action,
+                                       reverse=reverse)
+
+    if id_action != "0" and id_role != "0":
+        subtitle = 'step 3 - confirm remove of action'
+        # ask for confirmation
+
+        res = acca.acc_findPossibleActions(id_role, id_action)
+
+        if res:
+            output += '<p>authorizations that also will be deleted:</p>'
+            output += tupletotable(header=res[0], tuple=res[1:])
+
+            output += createhiddenform(action="deleteroleaction",
+                                       text='remove action %s from %s' % (headerstrong(action=id_action), headerstrong(role=id_role)),
+                                       confirm=1,
+                                       id_role=id_role,
+                                       id_action=id_action,
+                                       reverse=reverse)
+        else:
+            output += 'no authorizations'
+
+        # confirmation is given
+        if confirm: 
+            subtitle = 'step 4 - confirm remove of action '
+            res = acca.acc_deleteRoleAction(id_role=id_role, id_action=id_action)
+            if res:
+                output += '<p>confirm: removed %s from %s<br>' % (headerstrong(action=id_action), headerstrong(role=id_role))
+                output += '<strong>%s</strong> entries were removed.</p>' % (res, )
+            else:
+                output += '<p>sorry, no entries could be removed.</p>'
+    
+    return index(req=req,
+                 title=title,
+                 subtitle=subtitle,
+                 body=[output])
+        
+
+def perform_modifyauthorizations(req, id_role="0", id_action="0", reverse=0, confirm=0, errortext='', sel='', authids=[]):
+    """given ids of a role and an action, show all possible action combinations
+    with checkboxes and allow user to access other functions.    
+
+      id_role - id of the role
+
+    id_action - id of the action
+
+      reverse - 0: ask for role first
+                1: ask for action first
+
+          sel - which button and modification that is selected
+    
+    errortext - text to print when no connection exist between role and action
+    
+      authids - ids of checked checkboxes """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    name_role = acca.acc_getRoleName(id_role)
+    name_action = acca.acc_getActionName(id_action)
+
+    extra = """
+    <dl>
+     <dt><a href="addrole">Add new role</a></dt>
+     <dd>go here to add a new role.</dd>
+     <dt><a href="addaction">Add new action</a></dt>
+     <dd>go here to add a new action.</dd>
+    </dl>
+    """
+
+    if reverse in ["0", 0]:
+        # role -> action
+        subtitle = 'step 1 - select the role'
+        output  = createroleselect(id_role=id_role,
+                                   action="modifyauthorizations",
+                                   step=1,
+                                   roles=acca.acc_getAllRoles(),
+                                   reverse=reverse)
+
+        if id_role != "0":
+            rolacts = acca.acc_getRoleActions(id_role=id_role)
+            subtitle = 'step 2 - select the action'
+            output += createactionselect(id_action=id_action,
+                                         action="modifyauthorizations",
+                                         step=2,
+                                         actions=rolacts,
+                                         id_role=id_role,
+                                         reverse=reverse)
+    else:
+        # action -> role
+        subtitle = 'step 1 - select the action'
+        output = createactionselect(id_action=id_action,
+                                    action="modifyauthorizations",
+                                    step=1,
+                                    actions=acca.acc_getAllActions(),
+                                    reverse=reverse)
+        if id_action != "0":
+            actroles = acca.acc_getActionRoles(id_action=id_action)
+            subtitle = 'step 2 - select the role'
+            output += createroleselect(id_role=id_role,
+                                       action="modifyauthorizations",
+                                       step=2,
+                                       roles=actroles,
+                                       id_action=id_action,
+                                       reverse=reverse)
+
+    if errortext: output += '<p>%s</p>' % (errortext, )
+
+    if id_role != "0" and id_action != "0":
+        # shortcut to modifying authorizations
+        extra += """
+        <dl>
+         <dt><a href="addauthorization?id_role=%s&amp;id_action=%s&amp;reverse=%s">Add authorizations</a></dt>
+         <dd>Add and authorization to the existing.</dd>
+        </dl> """ % (id_role, id_action, reverse)
+
+        # back to the main area
+        if type(authids) is not list: authids = [authids]
+        subtitle = 'step 3 - select groups and modification'
+
+        # get info 
+        res = acca.acc_findPossibleActions(id_role, id_action)
+
+        # clean the authids
+        hiddenids = []
+        if sel in ['delete selected']:
+            hiddenids = authids[:]
+        elif sel in ['split groups', 'merge groups']:
+            for authid in authids:
+                arghlp = res[int(authid)][0]
+                if authid not in hiddenids and arghlp not in [-1, '-1', 0, '0']: hiddenids.append(authid)
+            authids = hiddenids[:]
+        
+        if confirm:
+            # do selected modification and output with new authorizations
+            if sel == 'split groups':
+                res = splitgroups(id_role, id_action, authids)
+            elif sel == 'merge groups':
+                res = mergegroups(id_role, id_action, authids)
+            elif sel == 'delete selected':
+                res = deleteselected(id_role, id_action, authids)
+            authids = []
+            res = acca.acc_findPossibleActions(id_role, id_action)
+            output += 'authorizations after <strong>%s</strong>.<br>\n' % (sel, )
+
+        elif sel and authids:
+            output += 'confirm choice of authorizations and modification.<br>\n'
+        else:
+            output += 'select authorizations and perform modification.<br>\n'
+            
+        if not res:
+            errortext='all connections deleted, try different '
+            if reverse in ["0", 0]:
+                return perform_modifyauthorizations(req=req, id_role=id_role, errortext=errortext + 'action.')
+            else:
+                return perform_modifyauthorizations(req=req, id_action=id_action, reverse=reverse, errortext=errortext + 'role.')
+        
+        # display 
+        output += modifyauthorizationsmenu(id_role, id_action, header=res[0], tuple=res[1:], checked=authids, reverse=reverse)
+        
+        if sel and authids:
+            # form with hidden authids
+            output += '<form action="%s" method="POST">\n' % ('modifyauthorizations', )
+
+            for hiddenid in hiddenids: 
+                output += '<input type="hidden" name="authids" value="%s" />\n' % (hiddenid, )
+
+            # choose what to do
+            if sel == 'split groups':
+                output += '<p>split groups containing:</p>'
+            elif sel == 'merge groups':               
+                output += '<p>merge groups containing:</p>'
+            elif sel == 'delete selected':            
+                output += '<p>delete selected entries:</p>'
+
+            extracolumn  = '<input type="checkbox" name="confirm" value="1" />\n'
+            extracolumn += '<input class="adminbutton" type="submit" value="confirm" />\n'
+
+            # show the entries here...
+            output += tupletotable_onlyselected(header=res[0],
+                                                tuple=res[1:],
+                                                selected=hiddenids,
+                                                extracolumn=extracolumn)
+            
+            output += '<input type="hidden" name="id_role" value="%s" />\n' % (id_role, )
+            output += '<input type="hidden" name="id_action" value="%s" />\n' % (id_action, )
+            output += '<input type="hidden" name="sel" value="%s" />\n' % (sel, )
+            output += '<input type="hidden" name="reverse" value="%s" />\n' % (reverse, )
+            output += '</form>'
+
+        # tried to perform modification without something selected
+        elif sel and not authids and not confirm: 
+            output += '<p>no valid groups selected</p>'
+
+    # trying to put extra link on the right side
+    try: body = [output, extra]
+    except NameError: body = [output]
+
+    # Display the page
+    return index(req=req,
+                 title='Modify Authorizations',
+                 subtitle=subtitle,
+                 body=body)
+
+
+def modifyauthorizationsmenu(id_role, id_action, tuple=[], header=[], checked=[], reverse=0):
+    """create table with header and checkboxes, used for multiple choice.
+    makes use of tupletotable to add the actual table
+
+      id_role - selected role, hidden value in the form
+
+    id_action - selected action, hidden value in the form
+
+        tuple - all rows to be put in the table (with checkboxes)
+
+       header - column headers, empty strings added at start and end
+
+      checked - ids of rows to be checked """
+
+    if not tuple:
+        return 'no authorisations...'
+
+    argnum = len(acca.acc_getActionKeywords(id_action=id_action))
+    
+    tuple2 = []
+    for t in tuple: tuple2.append(t[:])
+    
+    tuple2 = addcheckboxes(datalist=tuple2, name='authids', startindex=1, checked=checked)
+
+    hidden  = '<input type="hidden" name="id_role" value="%s" /> \n' % (id_role, )
+    hidden += '<input type="hidden" name="id_action" value="%s" /> \n' % (id_action, )
+    hidden += '<input type="hidden" name="reverse" value="%s" /> \n' % (reverse, )
+
+    
+    button = '<input type="submit" class="adminbutton" value="delete selected" name="sel" />\n'
+    if argnum > 1: 
+        button += '<input type="submit" class="adminbutton" value="split groups" name="sel" />\n'
+        button += '<input type="submit" class="adminbutton" value="merge groups" name="sel" />\n'
+    
+    hdrstr = ''
+    for h in [''] + header + ['']: hdrstr += '  <th class="adminheader">%s</th>\n' % (h, )
+    if hdrstr: hdrstr = ' <tr>\n%s\n </tr>\n' % (hdrstr, )
+    
+    output  = '<form action="modifyauthorizations" method="POST">\n'
+    output += '<table class="admin_wvar_nomargin"> \n'
+    output += hdrstr
+    output += '<tr><td>%s</td></tr>\n' % (hidden, )
+
+    output += '<tr>'
+    for data in tuple2[0]: output += '<td class="admintd">%s</td>\n' % (data,)
+    output += '<td rowspan="%s" style="vertical-align: bottom">\n%s\n</td>\n' % (len(tuple2), button)
+
+    output += '</tr>\n'
+    for row in tuple2[1:]:
+        output += ' <tr>\n'
+        for data in row: output += '<td class="admintd">%s</td>\n' % (data,)
+        output += ' </tr>\n'
+
+    output += '</table>\n</form>\n'
+
+    return output
+
+
+def splitgroups(id_role=0, id_action=0, authids=[]):
+    """get all the old ones, gather up the arglistids find a list of
+    arglistidgroups to be split, unique get all actions in groups outside
+    of the old ones, (old arglistid is allowed).
+    
+    show them like in showselect. """
+
+    if not id_role or not id_action or not authids:
+        return 0
+    
+    # find all the actions
+    datalist = acca.acc_findPossibleActions(id_role, id_action)
+
+    if type(authids) is str: authids = [authids]
+    for i in range(len(authids)): authids[i] = int(authids[i])
+    
+    # argumentlistids of groups to be split
+    splitgrps = []
+    for authid in authids:
+        hlp = datalist[authid][0]
+        if hlp not in splitgrps and authid in range(1,len(datalist)):
+            splitgrps.append(hlp)
+
+    # split groups and return success or failure
+    result = 1
+    for splitgroup in splitgrps:
+        result = 1 and acca.acc_splitArgumentGroup(id_role, id_action, splitgroup)
+
+    return result
+
+
+def mergegroups(id_role=0, id_action=0, authids=[]):
+    """get all the old ones, gather up the argauthids find a list
+    of arglistidgroups to be split, unique get all actions in groups
+    outside of the old ones, (old arglistid is allowed).
+
+    show them like in showselect."""
+
+    if not id_role or not id_action or not authids:
+        return 0
+    
+    datalist = acca.acc_findPossibleActions(id_role, id_action)
+
+    if type(authids) is str: authids = [authids]
+    for i in range(len(authids)): authids[i] = int(authids[i])
+    
+    # argumentlistids of groups to be merged
+    mergegroups = []
+    for authid in authids:
+        hlp = datalist[authid][0]
+        if hlp not in mergegroups and authid in range(1, len(datalist)):
+            mergegroups.append(hlp)
+
+    # merge groups and return success or failure
+    if acca.acc_mergeArgumentGroups(id_role, id_action, mergegroups):
+        return 1
+    else:
+        return 0
+
+
+
+def deleteselected(id_role=0, id_action=0,  authids=[]):
+    """delete checked authorizations/possible actions, ids in authids.
+
+    id_role - role to delete from
+
+    id_action - action to delete from
+
+    authids - listids for which possible actions to delete."""
+    
+    if not id_role or not id_action or not authids:
+        return 0
+
+    if type(authids) in [str, int]: authids = [authids]
+    for i in range(len(authids)): authids[i] = int(authids[i])
+    
+    result = acca.acc_deletePossibleActions(id_role=id_role,
+                                            id_action=id_action,
+                                            authids=authids)
+
+    return result
+
+
+def addadminbox(header='', datalist=[], cls="admin_wvar"):
+    """used to create table around main data on a page, row based.
+
+      header - header on top of the table
+
+    datalist - list of the data to be added row by row
+
+         cls - possible to select wich css-class to format the look of the table."""
+
+    try: per = str(100 // len(datalist)) + '%'
+    except ZeroDivisionError: per = 1
+
+    output  = '<table class="%s" ' % (cls, ) + 'width="100%">\n'
+    output += """
+     <thead>
+      <tr>
+       <th class="adminheaderleft" colspan="%s">%s</th>
+      </tr>
+     </thead>
+     <tbody>
+    """ % (len(datalist), header)
+    for row in [datalist]:
+        output += '      <tr>\n'
+        for data in row:
+            output += """
+            <td style="vertical-align: top; margin-top: 5px; width: %s;">
+             %s 
+            </td>
+            """ % (per, data)
+        output += '      </tr>\n'
+    output += """
+     </tbody>
+    </table>
+    """
+
+    return output
+
+
+def addadminbox(header='', datalist=[], cls="admin_wvar"):
+    """used to create table around main data on a page, row based.
+
+      header - header on top of the table
+
+    datalist - list of the data to be added row by row
+
+         cls - possible to select wich css-class to format the look of the table."""
+
+    if len(datalist) == 1: per = 100
+    else: per = 75
+    
+    output  = '<table class="%s" ' % (cls, ) + 'width="100%">\n'
+    output += """
+     <thead>
+      <tr>
+       <th class="adminheaderleft" colspan="%s">%s</th>
+      </tr>
+     </thead>
+     <tbody>
+    """ % (len(datalist), header)
+
+    output += '      <tr>\n'
+
+    output += """
+    <td style="vertical-align: top; margin-top: 5px; width: %s;">
+     %s 
+    </td>
+    """ % (per, datalist[0])
+
+    if len(datalist) > 1:
+        output += """
+        <td style="vertical-align: top; margin-top: 5px; width: %s;">
+         %s 
+        </td>
+        """ % ('25%', datalist[1])
+        
+    output += '      </tr>\n'
+    
+    output += """
+     </tbody>
+    </table>
+    """
+
+    return output
+
+
+def adderrorbox(header='', datalist=[]):
+    """used to create table around main data on a page, row based"""
+
+    try: perc= str(100 // len(datalist)) + '%'
+    except ZeroDivisionError: perc= 1
+
+    output  = '<table class="errorbox" width="100%">'
+    output += '<thead><tr><th class="errorboxheader" colspan="%s">%s</th></tr></thead>' % (len(datalist), header)
+    output += '<tbody>'
+    for row in [datalist]:
+        output += '<tr>'
+        for data in row:
+            output += '<td style="vertical-align: top; margin-top: 5px; width: %s;">' % (perc, )
+            output += data
+            output += '</td>'
+        output += '</tr>'
+    output += '</tbody></table>'
+
+    return output
+
+
+def tupletotable(header=[], tuple=[], start='', end='', extracolumn=''):
+    """create html table for a tuple.
+
+         header - optional header for the columns
+     
+          tuple - create table of this
+     
+          start - text to be added in the beginning, most likely beginning of a form
+     
+            end - text to be added in the end, mot likely end of a form.
+     
+    extracolumn - mainly used to put in a button. """
+    
+    tblstr = ''
+    for h in header + ['']:
+        tblstr += '  <th class="adminheader">%s</th>\n' % (h, )
+    if tblstr: tblstr = ' <tr>\n%s\n </tr>\n' % (tblstr, )
+    
+    tblstr = start + '<table class="admin_wvar_nomargin">\n' + tblstr
+
+    # extra column
+    try: 
+        extra = '<tr>'
+        row = tuple[0]
+        if type(row) not in [int, long, str, dict]:
+            for data in row: extra += '<td class="admintd">%s</td>\n' % (data,)
+        else:
+            extra += '  <td class="admintd">%s</td>\n' % (row, )
+        extra += '<td rowspan="%s" style="vertical-align: bottom">\n%s\n</td>\n</tr>\n' % (len(tuple), extracolumn)
+    except IndexError:
+        extra = ''
+    tblstr += extra
+
+    
+    for row in tuple[1:]:
+        tblstr += ' <tr>\n'
+        if type(row) not in [int, long, str, dict]:
+            for data in row: tblstr += '<td class="admintd">%s</td>\n' % (data,)
+        else:
+            tblstr += '  <td class="admintd">%s</td>\n' % (row, )
+        tblstr += ' </tr> \n'
+
+    tblstr += '</table> \n '
+    tblstr += end
+    
+    return tblstr
+
+
+def tupletotable_onlyselected(header=[], tuple=[], selected=[], start='', end='', extracolumn=''):
+    """create html table for a tuple.
+
+        header - optional header for the columns
+
+         tuple - create table of this
+
+      selected - indexes of selected rows in the tuple
+
+         start - put this in the beginning
+
+           end - put this in the beginning
+
+   extracolumn - mainly used to put in a button"""
+
+    tuple2 = []
+
+    for index in selected:
+        tuple2.append(tuple[int(index)-1])
+
+    return tupletotable(header=header,
+                        tuple=tuple2,
+                        start=start,
+                        end=end,
+                        extracolumn=extracolumn)
+
+
+def addcheckboxes(datalist=[], name='authids', startindex=1, checked=[]):
+    """adds checkboxes in front of the listdata.
+
+      datalist - add checkboxes in front of this list
+
+          name - name of all the checkboxes, values will be associated with this name
+
+    startindex - usually 1 because of the header
+
+       checked - values of checkboxes to be pre-checked """
+    
+    if not type(checked) is list: checked = [checked]
+    for row in datalist:
+        if 1 or row[0] not in [-1, "-1", 0, "0"]: # always box, check another place
+            chkstr = str(startindex) in checked and 'checked="checked"' or ''
+            row.insert(0, '<input type="checkbox" name="%s" value="%s" %s />' % (name, startindex, chkstr))
+        else:
+            row.insert(0, '')
+        startindex += 1
+    return datalist
+
+
+def headeritalic(**ids):
+    """transform keyword=value pairs to string with value in italics.
+
+    **ids - a dictionary of pairs to create string from """
+    
+    output = ''
+    value = ''
+    table = ''
+
+    for key in ids.keys():
+        if key in ['User', 'user']:
+            value, table = 'email', 'user'
+        elif key in ['Role', 'role']:
+            value, table = 'name', 'accROLE'
+        elif key in ['Action', 'action']:
+            value, table = 'name', 'accACTION'
+        else:
+            if output: output += ' and '
+            output += ' %s <i>%s</i>' % (key, ids[key])
+            continue
+                
+        res = run_sql("""SELECT %s FROM %s WHERE id = %s""" % (value, table, ids[key]))
+        
+        if res:
+            if output: output += ' and '
+            output += ' %s <i>%s</i>' % (key, res[0][0])
+
+    return output
+
+
+def headerstrong(query=1, **ids):
+    """transform keyword=value pairs to string with value in strong text.
+
+    **ids - a dictionary of pairs to create string from
+    
+    query - 1 -> try to find names to ids of role, user and action.
+            0 -> do not try to find names, use the value passed on """
+
+    output = ''
+    value = ''
+    table = ''
+
+    for key in ids.keys():
+        if key in ['User', 'user']:
+            value, table = 'email', 'user'
+        elif key in ['Role', 'role']:
+            value, table = 'name', 'accROLE'
+        elif key in ['Action', 'action']:
+            value, table = 'name', 'accACTION'
+        else:
+            if output: output += ' and '
+            output += ' %s <strong>%s</strong>' % (key, ids[key])
+            continue
+
+        if query:
+            res = run_sql("""SELECT %s FROM %s WHERE id = %s""" % (value, table, ids[key]))
+            if res:
+                if output: output += ' and '
+                output += ' %s <strong>%s</strong>' % (key, res[0][0])
+        else:
+            if output: output += ' and '
+            output += ' %s <strong>%s</strong>' % (key, ids[key])
+
+    return output
+
+
+def startpage():
+    """create the menu for the startpage"""
+    
+    body = """
+    <table class="admin_wvar" width="100%s" summary="">
+     <thead>
+      <tr>
+       <th class="adminheaderleft" colspan="2">Selection for Admin <i>%s</i></th>
+      </tr>
+     </thead>
+     <tbody>
+      <tr>
+       <td style="vertical-align: top; margin-top: 5px; width: 50%s;">
+        <dl>
+         <dt><a href="webaccessadmin.py/rolearea">Role Area</a>
+         <dd>Main area to configure administration rights and authorization rules.
+         <dt><a href="webaccessadmin.py/actionarea">Action Area</a>
+         <dd>Configure administration rights with the actions as starting point.
+         <dt><a href="webaccessadmin.py/userarea">User Area</a>
+         <dd>Configure administration rights with the users as starting point.
+         <dt><a href="webaccessadmin.py/resetarea">Reset Area</a>
+         <dd>Reset roles, actions and authorizations.
+        </dl>
+       </td>
+       <td style="vertical-align: top; margin-top: 5px; width: 50%s;"> </td>
+      </tr>
+     </tbody>
+    </table>""" % ('%', SUPERADMINROLE, '%', '%')
+
+    return body
+
+
+def perform_simpleauthorization(req, id_role=0, id_action=0):
+    """show a page with simple overview of authorizations between a
+    connected role and action. """
+    
+    if not is_adminuser(req): return mustloginpage(req)
+
+    res = acca.acc_findPossibleActions(id_role, id_action)
+    if res:
+        extra = createhiddenform(action='modifyauthorizations',
+                                 button='modify authorizations',
+                                 id_role=id_role,
+                                 id_action=id_action)
+        
+        output  = '<p>authorizations for %s:</p>' % (headerstrong(action=id_action, role=id_role), )
+        output += tupletotable(header=res[0], tuple=res[1:], extracolumn=extra)
+    else:
+        output = 'no details to show'
+
+    return index(req=req,
+                 title='Simple authorization details',
+                 subtitle='simple authorization details', 
+                 body=[output])
+
+
+def perform_simpleroleusers(req, id_role=0):
+    """show a page with simple overview of a role and connected users. """
+
+    if not is_adminuser(req): return mustloginpage(req)
+
+    res = acca.acc_getRoleUsers(id_role=id_role)
+    if res:
+        users = []
+        for (id, name, dontcare) in res: users.append([id, name, '<a href="showuserdetails?id_user=%s">show user details</a>'
+                                                       % (id, )])
+        output  = '<p>users connected to %s:</p>' % (headerstrong(role=id_role), )
+        output += tupletotable(header=['id', 'name', ''], tuple=users)
+    else:
+        output = 'no users connected'
+
+    return index(req=req,
+                 title='Simple user details',
+                 subtitle='simple user details', 
+                 body=[output])
+               
+
+def createhiddenform(action="", text="", button="confirm", cnfrm='', **hidden):
+    """create select with hidden values and submit button
+
+      action - name of the action to perform on submit
+
+        text - additional text, can also be used to add non hidden input
+
+      button - value/caption on the submit button
+
+       cnfrm - if given, must check checkbox to confirm
+
+    **hidden - dictionary with name=value pairs for hidden input """
+    
+    output  = '<form action="%s" method="POST">\n' % (action, )
+    output += '<table>\n<tr><td>'
+    output += text
+    if cnfrm:
+        output += ' <input type="checkbox" name="confirm" value="1" />' 
+    for key in hidden.keys():
+        output += ' <input type="hidden" name="%s" value="%s" />\n' % (key, hidden[key])
+    output += '</td><td style="vertical-align: bottom">'
+    output += ' <input class="adminbutton" type="submit" value="%s" />\n' % (button, )
+    output += '</td></tr></table>'
+    output += '</form>\n'
+
+    return output
+
+
+def createselect(id_input="0", label="", step=0, name="",
+                 action="", list=[], extralist=[],
+                 button="", **hidden):
+    """create form with select and hidden values
+
+           id - the one to choose as selected if exists
+
+        label - label shown to the left of the select
+
+         name - the name of the select on which to reference it
+
+         list - primary list to select from
+
+    extralist - list of options to be put in paranthesis
+
+       button - the value/text to be put on the button
+
+     **hidden - name=value pairs to be put as hidden in the form. """
+
+    step = step and '%s. ' % step or ''
+    
+    output  = '<form action="%s" method="POST">\n' % (action, )
+    output += ' <span class="adminlabel">%s</span>\n' % (step + label, )
+    output += ' <select name="%s" class="admin_w200">\n' % (name, )
+    if not list and not extralist:
+        output += '  <option value="0">no %ss to select from</option>\n' % (label.split()[-1], )
+    else:
+        output += '  <option value="0">%s</option>\n' % (label, )
+        for (id, email, dontcare) in list:
+            if str(id) == id_input: output += '  <option value="%s" selected="selected">%s</option>\n' % (id, email)
+            else: output += '  <option value="%s">%s</option>\n' % (id, email)
+        for (id, email, dontcare) in extralist:
+            if str(id) == id_input: output += '  <option value="%s" selected="selected">(%s)</option>\n' % (id, email)
+            else: output += '  <option value="%s">(%s)</option>\n' % (id, email)
+    output += ' </select>\n'
+    for key in hidden.keys():
+        output += ' <input type="hidden" name="%s" value="%s" />\n' % (key, hidden[key])
+    output += ' <input class="adminbutton" type="submit" value="%s" />\n' % (button, )
+    output += '</form>\n'
+
+    return output
+
+
+def createactionselect(id_action="0", label="select action", step=0, name="id_action",
+                       action="", actions=[], extraactions=[],
+                       button="select action", **hidden):
+    """create a select for roles in a form. see createselect."""
+
+    return createselect(id_input=id_action, label=label, step=step, name=name,
+                        action=action, list=actions, extralist=extraactions,
+                        button=button, **hidden)
+
+
+def createroleselect(id_role="0", label="select role", step=0, name="id_role",
+                     action="", roles=[], extraroles=[],
+                     button="select role", **hidden):
+    """create a select for roles in a form. see createselect."""
+
+    return createselect(id_input=id_role, label=label, step=step, name=name,
+                        action=action, list=roles, extralist=extraroles,
+                        button=button, **hidden)
+
+
+def createuserselect(id_user="0", label="select user", step=0, name="id_user",
+                     action="", users=[], extrausers=[],
+                     button="select user", **hidden):
+    """create a select for users in a form.see createselect."""
+    
+    return createselect(id_input=id_user, label=label, step=step, name=name,
+                        action=action, list=users, extralist=extrausers,
+                        button=button, **hidden)
+
+
+def cleanstring(str='', comma=0):
+    """clean all the strings before submitting to access control admin.
+    remove characters not letter, number or underscore, also remove leading
+    underscores and numbers. return cleaned string.
+
+      str - string to be cleaned
+
+    comma - 1 -> allow the comma to divide multiple arguments
+            0 -> wash commas as well """
+
+    # remove not allowed characters
+    str = re.sub(r'[^a-zA-Z0-9_,]', '', str)
+
+    # split string on commas
+    items = str.split(',')
+    str = ''
+    for item in items:
+        if not item: continue
+        if comma and str: str += ','
+        # create valid variable names
+        str += re.sub(r'^([0-9_])*', '', item)
+
+    return str
+
+
+def cleanstring_argumentvalue(str=''):
+    """clean the value of an argument before submitting it.
+    allowed characters: a-z A-Z 0-9 _ and space 
+
+      str - string to be cleaned """
+
+    # remove not allowed characters
+    str = re.sub(r'[^a-zA-Z0-9_ .]', '', str)
+    # trim leading and ending spaces
+    str = re.sub(r'^ *| *$', '', str)
+
+    return str
+
+
+def cleanstring_email(str=''):
+    """clean the string and return a valid email address.
+    
+      str - string to be cleaned """
+
+    # remove not allowed characters
+    str = re.sub(r'[^a-zA-Z0-9_.@]', '', str)
+
+    return str
+
+
+def check_email(str=''):
+    """control that submitted emails are correct.
+    this little check is not very good, but better than nothing. """
+
+    r = re.compile(r'(.)+\@(.)+\.(.)+')
+    return r.match(str) and 1 or 0