Index: t3lib/config_default.php
===================================================================
--- t3lib/config_default.php	(revision 3243)
+++ t3lib/config_default.php	(working copy)
@@ -186,7 +186,8 @@
 			'ShortcutMenu::delete'       => 'typo3/classes/class.shortcutmenu.php:ShortcutMenu->deleteAjaxShortcut',
 			'ShortcutMenu::create'       => 'typo3/classes/class.shortcutmenu.php:ShortcutMenu->createAjaxShortcut',
 			'ModuleMenu::saveMenuState'  => 'typo3/classes/class.modulemenu.php:ModuleMenu->saveMenuState',
-			'ModuleMenu::render'         => 'typo3/classes/class.modulemenu.php:ModuleMenu->renderAjax'
+			'ModuleMenu::render'         => 'typo3/classes/class.modulemenu.php:ModuleMenu->renderAjax',
+			'SC_mod_web_perm_ajax::dispatch' => 'typo3/mod/web/perm/class.sc_mod_web_perm_ajax.php:SC_mod_web_perm_ajax->dispatch'
 		),
 	),
 	'FE' => Array(			// Configuration for the TypoScript frontend (FE). Nothing here relates to the administration backend!
Index: typo3/mod/web/perm/class.sc_mod_web_perm_ajax.php
===================================================================
--- typo3/mod/web/perm/class.sc_mod_web_perm_ajax.php	(revision 0)
+++ typo3/mod/web/perm/class.sc_mod_web_perm_ajax.php	(revision 0)
@@ -0,0 +1,392 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2007 - 2008 mehrwert (typo3@mehrwert.de)
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project 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 GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script 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.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/**
+ * [CLASS/FUNCTION INDEX of SCRIPT]
+ *
+ *
+ *
+ *   66: class SC_mod_web_perm_ajax
+ *
+ *              SECTION: Init method for this class
+ *   97:     public function __construct()
+ *
+ *              SECTION: Main dispatcher method
+ *  143:     public function dispatch($params = array(), TYPO3AJAX &$ajaxObj = null)
+ *
+ *              SECTION: Helpers for this script
+ *  259:     private function renderUserSelector($page, $ownerUid, $username = '')
+ *  302:     private function renderGroupSelector($page, $groupUid, $groupname = '')
+ *  350:     private function renderOwnername($page, $ownerUid, $username)
+ *  363:     private function renderGroupname($page, $groupUid, $groupname)
+ *  375:     private function renderToggleEditLock($page, $editlockstate)
+ *  389:     private function renderPermissions($int, $pageId = 0, $who = 'user')
+ *
+ * TOTAL FUNCTIONS: 8
+ * (This index is automatically created/updated by the extension "extdeveval")
+ *
+ */
+
+$GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_mod_web_perm.xml');
+
+/**
+ * This class extends the permissions module in the TYPO3 Backend to provide
+ * convenient methods of editing of page permissions (including page ownership
+ * (user and group)) via new TYPO3AJAX facility
+ *
+ * @author		Andreas Kundoch <typo3@mehrwert.de>
+ * @version		$Id$
+ * @package		TYPO3
+ * @subpackage	core
+ * @license		GPL
+ * @since		TYPO3_4-2
+ */
+class SC_mod_web_perm_ajax {
+
+	private $conf = array();	// The local configuration array
+	private $backPath = '../../../';	// TYPO3 Back Path
+
+	/********************************************
+	 *
+	 * Init method for this class
+	 *
+	 ********************************************/
+
+	/**
+	 * The constructor of this class
+	 *
+	 * @return	Void
+	 */
+	public function __construct() {
+
+			// Configuration, variable assignment
+		$this->conf['page']          = t3lib_div::_POST('page');
+		$this->conf['who']           = t3lib_div::_POST('who');
+		$this->conf['mode']          = t3lib_div::_POST('mode');
+		$this->conf['bits']          = intval(t3lib_div::_POST('bits'));
+		$this->conf['permissions']   = intval(t3lib_div::_POST('permissions'));
+		$this->conf['action']	     = t3lib_div::_POST('action');
+		$this->conf['ownerUid']      = intval(t3lib_div::_POST('ownerUid'));
+		$this->conf['username']      = t3lib_div::_POST('username');
+		$this->conf['groupUid']      = intval(t3lib_div::_POST('groupUid'));
+		$this->conf['groupname']     = t3lib_div::_POST('groupname');
+		$this->conf['editLockState'] = intval(t3lib_div::_POST('editLockState'));
+
+			// User: Replace some parts of the posted values
+		$this->conf['owner_data']	      = urldecode(t3lib_div::_POST('owner_data'));
+		$this->conf['owner_data']         = str_replace('new_page_owner=', '', $this->conf['owner_data']);
+		$this->conf['owner_data']         = str_replace('%3B', ';', $this->conf['owner_data']);
+		$temp_owner_data                  = explode(';', $this->conf['owner_data']);
+		$this->conf['new_owner_uid']      = intval($temp_owner_data[0]);
+		$this->conf['new_owner_username'] = htmlspecialchars($temp_owner_data[1]);
+
+			// Group: Replace some parts of the posted values
+		$this->conf['group_data']         = urldecode(t3lib_div::_POST('group_data'));
+		$this->conf['group_data']         = str_replace('new_page_group=', '', $this->conf['group_data']);
+		$this->conf['group_data']         = str_replace('%3B', ';', $this->conf['group_data']);
+		$temp_group_data                  = explode(';', $this->conf['group_data']);
+		$this->conf['new_group_uid']      = intval($temp_group_data[0]);
+		$this->conf['new_group_username'] = htmlspecialchars($temp_group_data[1]);
+
+	}
+
+	/********************************************
+	 *
+	 * Main dispatcher method
+	 *
+	 ********************************************/
+
+	/**
+	 * The main dispatcher function. Collect data and prepare HTML output.
+	 *
+	 * @param	array		$params: array of parameters from the AJAX interface, currently unused
+	 * @param	TYPO3AJAX		$ajaxObj: object of type TYPO3AJAX
+	 * @return	Void
+	 */
+	public function dispatch($params = array(), TYPO3AJAX &$ajaxObj = null) {
+		$content = '';
+
+			// Basic test for required value
+		if ($this->conf['page'] > 0) {
+
+				// Init TCE for execution of update
+			$tce = t3lib_div::makeInstance('t3lib_TCEmain');
+			$tce->stripslashes_values = 1;
+
+				// Determine the scripts to execute
+			switch ($this->conf['action']) {
+
+					// Return the select to change the owner (BE user) of the page
+				case 'show_change_owner_selector':
+					$content = $this->renderUserSelector($this->conf['page'], $this->conf['ownerUid'], $this->conf['username']);
+					break;
+
+					// Change the owner and return the new owner HTML snippet
+				case 'change_owner':
+					if (is_int($this->conf['new_owner_uid'])) {
+							// Prepare data to change
+						$data = array();
+						$data['pages'][$this->conf['page']]['perms_userid'] = $this->conf['new_owner_uid'];
+
+							// Execute TCE Update
+						$tce->start($data, array());
+						$tce->process_datamap();
+						$content = $this->renderOwnername($this->conf['page'], $this->conf['new_owner_uid'], $this->conf['new_owner_username']);
+					} else {
+						$ajaxObj->setError('An error occured: No page owner uid specified.');
+					}
+					break;
+
+					// Return the select to change the group (BE group) of the page
+				case 'show_change_group_selector':
+					$content = $this->renderGroupSelector($this->conf['page'], $this->conf['groupUid'], $this->conf['groupname']);
+					break;
+
+					// Change the group and return the new group HTML snippet
+				case 'change_group':
+					if (is_int($this->conf['new_group_uid'])) {
+
+							// Prepare data to change
+						$data = array();
+						$data['pages'][$this->conf['page']]['perms_groupid'] = $this->conf['new_group_uid'];
+
+							// Execute TCE Update
+						$tce->start($data, array());
+						$tce->process_datamap();
+
+						$content = $this->renderGroupname($this->conf['page'], $this->conf['new_group_uid'], $this->conf['new_group_username']);
+					} else {
+						$ajaxObj->setError('An error occured: No page group uid specified.');
+					}
+					break;
+
+					// Change the group and return the new group HTML snippet
+				case 'toggle_edit_lock':
+
+						// Prepare data to change
+					$data = array();
+					$data['pages'][$this->conf['page']]['editlock'] = ($this->conf['editLockState'] === 1 ? 0 : 1);
+
+						// Execute TCE Update
+					$tce->start($data, array());
+					$tce->process_datamap();
+
+					$content = $this->renderToggleEditLock($this->conf['page'], $data['pages'][$this->conf['page']]['editlock']);
+					break;
+
+					// The script defaults to change permissions
+				default:
+					if ($this->conf['mode'] == 'delete') {
+						$this->conf['permissions'] = intval($this->conf['permissions'] - $this->conf['bits']);
+					} else {
+						$this->conf['permissions'] = intval($this->conf['permissions'] + $this->conf['bits']);
+					}
+
+						// Prepare data to change
+					$data = array();
+					$data['pages'][$this->conf['page']]['perms_'.$this->conf['who']] = $this->conf['permissions'];
+
+						// Execute TCE Update
+					$tce->start($data, array());
+					$tce->process_datamap();
+
+					$content = $this->renderPermissions($this->conf['permissions'], $this->conf['page'], $this->conf['who']);
+			}
+		} else {
+			$ajaxObj->setError('This script cannot be called directly.');
+		}
+		$ajaxObj->addContent($this->conf['page'].'_'.$this->conf['who'], $content);
+	}
+
+	/********************************************
+	 *
+	 * Helpers for this script
+	 *
+	 ********************************************/
+
+	/**
+	 * Generate the user selector element
+	 *
+	 * @param	Integer		$page: The page id to change the user for
+	 * @param	Integer		$ownerUid: The page owner uid
+	 * @param	String		$username: The username to display
+	 * @return	String		The html select element
+	 */
+	private function renderUserSelector($page, $ownerUid, $username = '') {
+
+			// Get usernames
+		$beUsers = t3lib_BEfunc::getUserNames();
+
+			// Init groupArray
+		$groups = array();
+
+		if (!$GLOBALS['BE_USER']->isAdmin()) {
+			$beUsers = t3lib_BEfunc::blindUserNames($beUsers, $groups, 1);
+		}
+
+			// Owner selector:
+		$options = '';
+
+			// Loop through the users
+		foreach ($beUsers as $uid => $row) {
+			$selected = ($uid == $ownerUid	? ' selected="selected"' : '');
+			$options .= '<option value="'.$uid.';'.htmlspecialchars($row['username']).'"'.$selected.'>'.htmlspecialchars($row['username']).'</option>';
+		}
+
+		$elementId = 'o_'.$page;
+		$options = '<option value="0"></option>'.$options;
+		$selector = '<select name="new_page_owner" id="new_page_owner">'.$options.'</select>';
+		$saveButton = '<a onclick="WebPermissions.changeOwner('.$page.', '.$ownerUid.', \''.$elementId.'\');"><img'.t3lib_iconWorks::skinImg($this->backPath, 'gfx/savedok.gif', 'width="21" height="16"').' border="0" title="Change owner" align="top" alt="" /></a>';
+		$cancelButton = '<a onclick="WebPermissions.restoreOwner('.$page.', '.$ownerUid.', \''.($username == '' ? '<span class=not_set>[not set]</span>' : htmlspecialchars($username)).'\', \''.$elementId.'\');"><img'.t3lib_iconWorks::skinImg($this->backPath, 'gfx/closedok.gif', 'width="21" height="16"').' border="0" title="Cancel" align="top" alt="" /></a>';
+		$ret = $selector.$saveButton.$cancelButton;
+		return $ret;
+	}
+
+	/**
+	 * Generate the group selector element
+	 *
+	 * @param	Integer		$page: The page id to change the user for
+	 * @param	Integer		$groupUid: The page group uid
+	 * @param	String		$username: The username to display
+	 * @return	String		The html select element
+	 */
+	private function renderGroupSelector($page, $groupUid, $groupname = '') {
+
+			// Get usernames
+		$beGroups = t3lib_BEfunc::getListGroupNames('title,uid');
+		$beGroupKeys = array_keys($beGroups);
+		$beGroupsO = $beGroups = t3lib_BEfunc::getGroupNames();
+		if (!$GLOBALS['BE_USER']->isAdmin()) {
+			$beGroups = t3lib_BEfunc::blindGroupNames($beGroupsO, $beGroupKeys, 1);
+		}
+
+			// Group selector:
+		$options = '';
+
+			// flag: is set if the page-groupid equals one from the group-list
+		$userset = 0;
+
+			// Loop through the groups
+		foreach ($beGroups as $uid => $row) {
+			if ($uid == $groupUid) {
+				$userset = 1;
+				$selected = ' selected="selected"';
+			} else {
+				$selected = '';
+			}
+			$options .= '<option value="'.$uid.';'.htmlspecialchars($row['title']).'"'.$selected.'>'.htmlspecialchars($row['title']).'</option>';
+		}
+
+			// If the group was not set AND there is a group for the page
+		if (!$userset && $groupUid) {
+			$options = '<option value="'.$groupUid.'" selected="selected">'.htmlspecialchars($beGroupsO[$groupUid]['title']).'</option>'.$options;
+		}
+
+		$elementId = 'g_'.$page;
+		$options = '<option value="0"></option>'.$options;
+		$selector = '<select name="new_page_group" id="new_page_group">'.$options.'</select>';
+		$saveButton = '<a onclick="WebPermissions.changeGroup('.$page.', '.$groupUid.', \''.$elementId.'\');"><img'.t3lib_iconWorks::skinImg($this->backPath, 'gfx/savedok.gif', 'width="21" height="16"').' border="0" title="Change group" align="top" alt="" /></a>';
+		$cancelButton = '<a onclick="WebPermissions.restoreGroup('.$page.', '.$groupUid.', \''.($groupname == '' ? '<span class=not_set>[not set]</span>' : htmlspecialchars($groupname)).'\', \''.$elementId.'\');"><img'.t3lib_iconWorks::skinImg($this->backPath, 'gfx/closedok.gif', 'width="21" height="16"').' border="0" title="Cancel" align="top" alt="" /></a>';
+		$ret = $selector.$saveButton.$cancelButton;
+		return $ret;
+	}
+
+
+	/**
+	 * Print the string with the new owner of a page record
+	 *
+	 * @param	Integer		$page: The TYPO3 page id
+	 * @param	Integer		$ownerUid: The new page user uid
+	 * @param	String		$username: The TYPO3 BE username (used to display in the element)
+	 * @return	String		The new group wrapped in HTML
+	 */
+	public function renderOwnername($page, $ownerUid, $username) {
+		$elementId = 'o_'.$page;
+		$ret = '<span id="'.$elementId.'"><a class="ug_selector" onclick="WebPermissions.showChangeOwnerSelector('.$page.', '.$ownerUid.', \''.$elementId.'\', \''.htmlspecialchars($username).'\');">'.($username == '' ? '<span class=not_set>[not set]</span>' : htmlspecialchars(t3lib_div::fixed_lgd_cs($username, 20))).'</a></span>';
+		return $ret;
+	}
+
+
+	/**
+	 * Print the string with the new group of a page record
+	 *
+	 * @param	Integer		$page: The TYPO3 page id
+	 * @param	Integer		$groupUid: The new page group uid
+	 * @param	String		$groupname: The TYPO3 BE groupname (used to display in the element)
+	 * @return	String		The new group wrapped in HTML
+	 */
+	public function renderGroupname($page, $groupUid, $groupname) {
+		$elementId = 'g_'.$page;
+		$ret = '<span id="'.$elementId.'"><a class="ug_selector" onclick="WebPermissions.showChangeGroupSelector('.$page.', '.$groupUid.', \''.$elementId.'\', \''.htmlspecialchars($groupname).'\');">'.($groupname == '' ? '<span class=not_set>[not set]</span>' : htmlspecialchars(t3lib_div::fixed_lgd_cs($groupname, 20))).'</a></span>';
+		return $ret;
+	}
+
+
+	/**
+	 * Print the string with the new edit lock state of a page record
+	 *
+	 * @param	Integer		$page: The TYPO3 page id
+	 * @param	String		$editlockstate: The state of the TYPO3 page (locked, unlocked)
+	 * @return	String		The new edit lock string wrapped in HTML
+	 */
+	private function renderToggleEditLock($page, $editLockState) {
+		if ($editLockState === 1) {
+			$ret = '<a class="editlock" onclick="WebPermissions.toggleEditLock('.$page.', 1);"><img'.t3lib_iconWorks::skinImg($this->backPath,'gfx/recordlock_warning2.gif','width="22" height="16"').' title="The page and all content is locked for editing by all non-Admin users." alt="" /></a>';
+		} else {
+			$ret = '<a class="editlock" onclick="WebPermissions.toggleEditLock('.$page.', 0);" title="Enable the &raquo;Admin-only&laquo; edit lock for this page">[+]</a>';
+		}
+		return $ret;
+	}
+
+
+	/**
+	 * Print a set of permissions. Also used in index.php
+	 *
+	 * @param	integer		Permission integer (bits)
+	 * @param	Integer		$page: The TYPO3 page id
+	 * @param	String		$who: The scope (user, group or everybody)
+	 * @return	string		HTML marked up x/* indications.
+	 */
+	public function renderPermissions($int, $pageId = 0, $who = 'user') {
+		global $LANG;
+		$str = '';
+
+		$permissions = array(1,16,2,4,8);
+		foreach ($permissions as $permission) {
+			if ($int&$permission) {
+				$str .= '<span class="perm-allowed"><a title="'.$LANG->getLL($permission,1).'" class="perm-allowed" onclick="WebPermissions.setPermissions('.$pageId.', '.$permission.', \'delete\', \''.$who.'\', '.$int.');">*</a></span>';
+			} else {
+				$str .= '<span class="perm-denied"><a title="'.$LANG->getLL($permission,1).'" class="perm-denied" onclick="WebPermissions.setPermissions('.$pageId.', '.$permission.', \'add\', \''.$who.'\', '.$int.');">x</a></span>';
+			}
+		}
+		return '<span id="'.$pageId.'_'.$who.'">'.$str.'</span>';
+	}
+
+}
+
+// Include extension?
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/web/perm/class.sc_mod_web_perm_ajax.php']) {
+	include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/web/perm/class.sc_mod_web_perm_ajax.php']);
+}
+
+?>
Index: typo3/mod/web/perm/index.php
===================================================================
--- typo3/mod/web/perm/index.php	(revision 3243)
+++ typo3/mod/web/perm/index.php	(working copy)
@@ -38,23 +38,24 @@
  *
  *
  *
- *   89: class SC_mod_web_perm_index
- *  123:     function init()
- *  183:     function menuConfig()
- *  214:     function main()
- *  288:     function printContent()
+ *   90: class SC_mod_web_perm_index
+ *  194:     public function init()
+ *  246:     public function menuConfig()
+ *  277:     public function main()
+ *  344:     public function printContent()
+ *  354:     private function getButtons()
  *
  *              SECTION: Listing and Form rendering
- *  315:     function doEdit()
- *  452:     function notEdit()
+ *  398:     public function doEdit()
+ *  545:     public function notEdit()
  *
  *              SECTION: Helper functions
- *  647:     function printCheckBox($checkName,$num)
- *  658:     function printPerms($int)
- *  676:     function groupPerms($row,$firstGroup)
- *  693:     function getRecursiveSelect($id,$perms_clause)
+ *  739:     public function printCheckBox($checkName, $num)
+ *  752:     public function printPerms($int, $pageId = 0, $who = 'user')
+ *  772:     public function groupPerms($row, $firstGroup)
+ *  789:     public function getRecursiveSelect($id,$perms_clause)
  *
- * TOTAL FUNCTIONS: 10
+ * TOTAL FUNCTIONS: 11
  * (This index is automatically created/updated by the extension "extdeveval")
  *
  */
@@ -63,6 +64,7 @@
 require('conf.php');
 require($BACK_PATH.'init.php');
 require($BACK_PATH.'template.php');
+require('class.sc_mod_web_perm_ajax.php');
 $LANG->includeLLFile('EXT:lang/locallang_mod_web_perm.xml');
 require_once (PATH_t3lib.'class.t3lib_pagetree.php');
 require_once (PATH_t3lib.'class.t3lib_page.php');
@@ -76,59 +78,127 @@
 
 
 /**
+ * Module: Permission setting
+ *
  * Script Class for the Web > Access module
  * This module lets you view and change permissions for pages.
  *
- * variables:
- * $this->depth 	: 	intval 1-3: decides the depth of the list
- * $this->mode		:	'perms' / '': decides if we view a user-overview or the permissions.
+ * Variables:
+ * $this->MOD_SETTINGS['depth']: intval 1-3: decides the depth of the list
+ * $this->MOD_SETTINGS['mode']: 'perms' / '': decides if we view a user-overview or the permissions.
  *
  * @author	Kasper Skaarhoj <kasperYYYY@typo3.com>
- * @package TYPO3
- * @subpackage core
+ * @author	Andreas Kundoch <typo3@mehrwert.de>
+ * @package	TYPO3
+ * @subpackage	core
+ * @version	$Id$
  */
 class SC_mod_web_perm_index {
 
-		// External, static:
-	var $getLevels = 10;			// Number of levels to enable recursive settings for
+	/**
+	 * Number of levels to enable recursive settings for
+	 * @var integer
+	 */
+	public $getLevels = 10;
 
-		// Internal, static:
-	var $MCONF=array();			// Module config
+	/**
+	 * Module config
+	 * Internal static
+	 * @var array
+	 */
+	private $MCONF = array();
 
 	/**
 	 * Document Template Object
-	 *
-	 * @var mediumDoc
+	 * @var template
 	 */
-	var $doc;
-	var $content;				// Content accumulation
+	public $doc;
 
-	var $MOD_MENU=array();		// Module menu
-	var $MOD_SETTINGS=array();	// Module settings, cleansed.
+	/**
+	 * Content accumulation
+	 * @var string
+	 */
+	public $content;
 
-	var $perms_clause;			// Page select permissions
-	var $pageinfo;				// Current page record
+	/**
+	 * Module menu
+	 * @var array
+	 */
+	public $MOD_MENU = array();
 
-	var $color;					// Background color 1
-	var $color2;				// Background color 2
-	var $color3;				// Background color 3
+	/**
+	 * Module settings, cleansed.
+	 * @var aray
+	 */
+	public $MOD_SETTINGS = array();
 
-	var $editingAllowed;		// Set internally if the current user either OWNS the page OR is admin user!
+	/**
+	 * Page select permissions
+	 * @var string
+	 */
+	public $perms_clause;
 
-		// Internal, static: GPvars:
-	var $id;					// Page id.
-	var $edit;					// If set, editing of the page permissions will occur (showing the editing screen). Notice: This value is evaluated against permissions and so it will change internally!
-	var $return_id;				// ID to return to after editing.
-	var $lastEdited;			// Id of the page which was just edited.
+	/**
+	 * Current page record
+	 * @var array
+	 */
+	public $pageinfo;
 
+	/**
+	 *  Background color 1
+	 * @var string
+	 */
+	public $color;
 
 	/**
+	 * Background color 2
+	 * @var string
+	 */
+	public $color2;
+
+	/**
+	 * Background color 3
+	 * @var string
+	 */
+	public $color3;
+
+	/**
+	 * Set internally if the current user either OWNS the page OR is admin user!
+	 * @var boolean
+	 */
+	public $editingAllowed;
+
+	/**
+	 * Internal, static: GPvars: Page id.
+	 * @var integer
+	 */
+	public $id;
+
+	/**
+	 * If set, editing of the page permissions will occur (showing the editing screen). Notice:
+	 * This value is evaluated against permissions and so it will change internally!
+	 * @var boolean
+	 */
+	public $edit;
+
+	/**
+	 * ID to return to after editing.
+	 * @var integer
+	 */
+	public $return_id;
+
+	/**
+	 * Id of the page which was just edited.
+	 * @var integer
+	 */
+	public $lastEdited;
+
+	/**
 	 * Initialization of the class
 	 *
 	 * @return	void
 	 */
-	function init()	{
-		global $BE_USER,$BACK_PATH;
+	public function init() {
 
 			// Setting GPvars:
 		$this->id = intval(t3lib_div::_GP('id'));
@@ -140,40 +210,31 @@
 		$this->MCONF = $GLOBALS['MCONF'];
 
 			// Page select clause:
-		$this->perms_clause = $BE_USER->getPagePermsClause(1);
+		$this->perms_clause = $GLOBALS['BE_USER']->getPagePermsClause(1);
 
 			// Initializing document template object:
 		$this->doc = t3lib_div::makeInstance('template');
-		$this->doc->backPath = $BACK_PATH;
+		$this->doc->backPath = $GLOBALS['BACK_PATH'];
 		$this->doc->docType = 'xhtml_trans';
 		$this->doc->setModuleTemplate('templates/perm.html');
-		
-		$this->doc->form='<form action="'.$BACK_PATH.'tce_db.php" method="post" name="editform">';
-		$this->doc->JScode = '<script type="text/javascript" src="'.$BACK_PATH.'../t3lib/jsfunc.updateform.js"></script>';
-		$this->doc->JScode.= $this->doc->wrapScriptTags('
-			function checkChange(checknames, varname)	{	//
-				var res = 0;
-				for (var a=1; a<=5; a++)	{
-					if (document.editform[checknames+"["+a+"]"].checked)	{
-						res|=Math.pow(2,a-1);
-					}
-				}
-				document.editform[varname].value = res | (checknames=="check[perms_user]"?1:0) ;
-				setCheck (checknames,varname);
-			}
-			function setCheck(checknames, varname)	{ 	//
-				if (document.editform[varname])	{
-					var res = document.editform[varname].value;
-					for (var a=1; a<=5; a++)	{
-						document.editform[checknames+"["+a+"]"].checked = (res & Math.pow(2,a-1));
-					}
-				}
-			}
-			function jumpToUrl(URL)	{	//
-				window.location.href = URL;
-			}
-		');
+		$this->doc->form = '<form action="'.$GLOBALS['BACK_PATH'].'tce_db.php" method="post" name="editform">';
+		$this->doc->loadJavascriptLib('../t3lib/jsfunc.updateform.js');
+		$this->doc->loadJavascriptLib('contrib/prototype/prototype.js');
+		$this->doc->loadJavascriptLib(TYPO3_MOD_PATH . 'perm.js');
 
+		// Adding special styles to the permissions indicators and selecot boxes
+ 		$this->doc->inDocStyles .= "
+ 			A.perm-allowed, A.perm-denied { padding: 2px 3px 1px 3px; border: 0; cursor: pointer; }
+			A.perm-allowed:hover, A.perm-denied:hover { padding: 1px 2px 0 2px; border: 1px solid red; cursor: pointer; }
+			A.perm-allowed:hover { color: green; }
+			A.perm-denied:hover { color: red; }
+			A IMG { cursor: pointer; }
+			.ug_selector, .ug_selector A { text-decoration: underline; cursor: pointer; }
+			.not_set, .not_set A, .editlock, .editlock A { text-decoration: none; cursor: pointer; color: #CCC; }
+			.not_set:hover, .not_set A:hover, .editlock:hover, .editlock A:hover { text-decoration: none; cursor: pointer; color: #000; font-weight: bold; }
+			.not_set { color: #000; font-style: italic; }
+		";
+
 			// Setting up the context sensitive menu:
 		$this->doc->getContextMenuCode();
 
@@ -186,7 +247,7 @@
 	 *
 	 * @return	void
 	 */
-	function menuConfig()	{
+	public function menuConfig() {
 		global $LANG;
 
 			// MENU-ITEMS:
@@ -217,17 +278,17 @@
 	 *
 	 * @return	void
 	 */
-	function main()	{
-		global $BE_USER,$LANG;
-		
+	public function main() {
+		global $BE_USER, $LANG;
+
 			// Access check...
 			// The page will show only if there is a valid page and if this page may be viewed by the user
-		$this->pageinfo = t3lib_BEfunc::readPageAccess($this->id,$this->perms_clause);
-		$access = is_array($this->pageinfo) ? 1 : 0;
+		$this->pageinfo = t3lib_BEfunc::readPageAccess($this->id, $this->perms_clause);
+		$access = is_array($this->pageinfo);
 
 			// Checking access:
-		if (($this->id && $access) || ($BE_USER->user['admin'] && !$this->id))	{
-			if ($BE_USER->user['admin'] && !$this->id)	{
+		if (($this->id && $access) || ($BE_USER->isAdmin() && !$this->id)) {
+			if ($BE_USER->isAdmin() && !$this->id)	{
 				$this->pageinfo=array('title' => '[root-level]','uid'=>0,'pid'=>0);
 			}
 
@@ -245,38 +306,36 @@
 			}
 
 				// Draw the HTML page header.
-			$this->content.=$this->doc->header($LANG->getLL('permissions').($this->edit?': '.$LANG->getLL('Edit'):''));
+			$this->content.=$this->doc->header($LANG->getLL('permissions') . ($this->edit ? ': '.$LANG->getLL('Edit') : ''));
 			$this->content.=$this->doc->spacer(5);
 
 			$vContent = $this->doc->getVersionSelector($this->id,1);
-			if ($vContent)	{
-				$this->content.=$this->doc->section('',$vContent);
+			if ($vContent) {
+				$this->content .= $this->doc->section('',$vContent);
 			}
 
 				// Main function, branching out:
-			if (!$this->edit)	{
+			if (!$this->edit) {
 				$this->notEdit();
 			} else {
 				$this->doEdit();
 			}
-			
+
 			$docHeaderButtons = $this->getButtons();
 
 			$markers['CSH'] = $this->docHeaderButtons['csh'];
 			$markers['FUNC_MENU'] = t3lib_BEfunc::getFuncMenu($this->id, 'SET[mode]', $this->MOD_SETTINGS['mode'], $this->MOD_MENU['mode']);
 			$markers['CONTENT'] = $this->content;
-			
+
 				// Build the <body> for the module
 			$this->content = $this->doc->startPage($LANG->getLL('permissions'));
 			$this->content.= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
-			$this->content.= $this->doc->endPage();
-			$this->content = $this->doc->insertStylesAndJS($this->content);
 		} else {
 				// If no access or if ID == zero
 			$this->content.=$this->doc->startPage($LANG->getLL('permissions'));
 			$this->content.=$this->doc->header($LANG->getLL('permissions'));
-			$this->content = $this->doc->insertStylesAndJS($this->content);
 		}
+		$this->content.= $this->doc->endPage();
 	}
 
 	/**
@@ -284,7 +343,7 @@
 	 *
 	 * @return	void
 	 */
-	function printContent()	{
+	public function printContent() {
 		$this->content = $this->doc->insertStylesAndJS($this->content);
 		echo $this->content;
 	}
@@ -292,11 +351,10 @@
 	/**
 	 * Create the panel of buttons for submitting the form or otherwise perform operations.
 	 *
-	 * @return	array	all available buttons as an assoc. array
+	 * @return	array		all available buttons as an assoc. array
 	 */
-	private function getButtons()	{
-		global $TCA, $LANG, $BACK_PATH, $BE_USER;
-		
+	private function getButtons() {
+
 		$buttons = array(
 			'csh' => '',
 			'view' => '',
@@ -305,22 +363,22 @@
 		);
 			// CSH
 		$buttons['csh'] = t3lib_BEfunc::cshItem('_MOD_web_info', '', $GLOBALS['BACK_PATH']);
-		
+
 			// View page
-		$buttons['view'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::viewOnClick($this->pageinfo['uid'], $BACK_PATH, t3lib_BEfunc::BEgetRootLine($this->pageinfo['uid']))) . '">' .
-				'<img' . t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/zoom.gif') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showPage', 1) . '" hspace="3" alt="" />' .
+		$buttons['view'] = '<a href="#" onclick="' . htmlspecialchars(t3lib_BEfunc::viewonclick($this->pageinfo['uid'], $GLOBALS['BACK_PATH'], t3lib_BEfunc::BEgetRootLine($this->pageinfo['uid']))) . '">' .
+				'<img' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'], 'gfx/zoom.gif') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showPage', 1) . '" hspace="3" alt="" />' .
 				'</a>';
 
 			// Shortcut
-		if ($BE_USER->mayMakeShortcut())	{
+		if ($GLOBALS['BE_USER']->mayMakeShortcut())	{
 			$buttons['shortcut'] = $this->doc->makeShortcutIcon('id, edit_record, pointer, new_unique_uid, search_field, search_levels, showLimit', implode(',', array_keys($this->MOD_MENU)), $this->MCONF['name']);
 		}
-		
+
 			// If access to Web>List for user, then link to that module.
-		if ($BE_USER->check('modules','web_list'))	{
-			$href = $BACK_PATH . 'db_list.php?id=' . $this->pageinfo['uid'] . '&returnUrl=' . rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'));
+		if ($GLOBALS['BE_USER']->check('modules','web_list'))	{
+			$href = $GLOBALS['BACK_PATH'] . 'db_list.php?id=' . $this->pageinfo['uid'] . '&returnUrl=' . rawurlencode(t3lib_div::getIndpEnv('REQUEST_URI'));
 			$buttons['record_list'] = '<a href="' . htmlspecialchars($href) . '">' .
-					'<img' . t3lib_iconWorks::skinImg($BACK_PATH, 'gfx/list.gif') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showList', 1) . '" alt="" />' .
+					'<img' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'], 'gfx/list.gif') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.php:labels.showList', 1) . '" alt="" />' .
 					'</a>';
 		}
 		return $buttons;
@@ -345,7 +403,7 @@
 	 *
 	 * @return	void
 	 */
-	function doEdit()	{
+	public function doEdit() {
 		global $BE_USER,$LANG;
 
 		if ($BE_USER->workspace!=0)	{
@@ -355,24 +413,30 @@
 		}
 
 			// Get usernames and groupnames
-		$be_group_Array=t3lib_BEfunc::getListGroupNames('title,uid');
-		$groupArray=array_keys($be_group_Array);
+		$beGroupArray = t3lib_BEfunc::getListGroupNames('title,uid');
+		$beGroupKeys = array_keys($beGroupArray);
 
-		$be_user_Array = t3lib_BEfunc::getUserNames();
-		if (!$GLOBALS['BE_USER']->isAdmin())		$be_user_Array = t3lib_BEfunc::blindUserNames($be_user_Array,$groupArray,1);
-		$be_group_Array_o = $be_group_Array = t3lib_BEfunc::getGroupNames();
-		if (!$GLOBALS['BE_USER']->isAdmin())		$be_group_Array = t3lib_BEfunc::blindGroupNames($be_group_Array_o,$groupArray,1);
-		$firstGroup = $groupArray[0] ? $be_group_Array[$groupArray[0]] : '';	// data of the first group, the user is member of
+		$beUserArray = t3lib_BEfunc::getUserNames();
+		if (!$GLOBALS['BE_USER']->isAdmin()) {
+			$beUserArray = t3lib_BEfunc::blindUserNames($beUserArray,$beGroupKeys,1);
+		}
+		$beGroupArray_o = $beGroupArray = t3lib_BEfunc::getGroupNames();
+		if (!$GLOBALS['BE_USER']->isAdmin()) {
+			$beGroupArray = t3lib_BEfunc::blindGroupNames($beGroupArray_o,$beGroupKeys,1);
+		}
+		$firstGroup = $beGroupKeys[0] ? $beGroupArray[$beGroupKeys[0]] : '';	// data of the first group, the user is member of
 
 
 			// Owner selector:
 		$options='';
 		$userset=0;	// flag: is set if the page-userid equals one from the user-list
-		foreach($be_user_Array as $uid => $row)	{
+		foreach($beUserArray as $uid => $row)	{
 			if ($uid==$this->pageinfo['perms_userid'])	{
 				$userset = 1;
 				$selected=' selected="selected"';
-			} else {$selected='';}
+			} else {
+				$selected='';
+			}
 			$options.='
 				<option value="'.$uid.'"'.$selected.'>'.htmlspecialchars($row['username']).'</option>';
 		}
@@ -389,18 +453,20 @@
 			// Group selector:
 		$options='';
 		$userset=0;
-		foreach($be_group_Array as $uid => $row)	{
+		foreach($beGroupArray as $uid => $row)	{
 			if ($uid==$this->pageinfo['perms_groupid'])	{
 				$userset = 1;
 				$selected=' selected="selected"';
-			} else {$selected='';}
+			} else {
+				$selected='';
+			}
 			$options.='
 				<option value="'.$uid.'"'.$selected.'>'.htmlspecialchars($row['title']).'</option>';
 		}
 		if (!$userset && $this->pageinfo['perms_groupid'])	{	// If the group was not set AND there is a group for the page
 			$options='
 				<option value="'.$this->pageinfo['perms_groupid'].'" selected="selected">'.
-						htmlspecialchars($be_group_Array_o[$this->pageinfo['perms_groupid']]['title']).
+						htmlspecialchars($beGroupArray_o[$this->pageinfo['perms_groupid']]['title']).
 						'</option>'.
 						$options;
 		}
@@ -488,15 +554,19 @@
 	 *
 	 * @return	void
 	 */
-	function notEdit()	{
+	public function notEdit() {
 		global $BE_USER,$LANG,$BACK_PATH;
 
 			// Get usernames and groupnames: The arrays we get in return contains only 1) users which are members of the groups of the current user, 2) groups that the current user is member of
-		$groupArray = $BE_USER->userGroupsUID;
-		$be_user_Array = t3lib_BEfunc::getUserNames();
-		if (!$GLOBALS['BE_USER']->isAdmin())		$be_user_Array = t3lib_BEfunc::blindUserNames($be_user_Array,$groupArray,0);
-		$be_group_Array = t3lib_BEfunc::getGroupNames();
-		if (!$GLOBALS['BE_USER']->isAdmin())		$be_group_Array = t3lib_BEfunc::blindGroupNames($be_group_Array,$groupArray,0);
+		$beGroupKeys = $BE_USER->userGroupsUID;
+		$beUserArray = t3lib_BEfunc::getUserNames();
+		if (!$GLOBALS['BE_USER']->isAdmin()) {
+			$beUserArray = t3lib_BEfunc::blindUserNames($beUserArray,$beGroupKeys,0);
+		}
+		$beGroupArray = t3lib_BEfunc::getGroupNames();
+		if (!$GLOBALS['BE_USER']->isAdmin()) {
+			$beGroupArray = t3lib_BEfunc::blindGroupNames($beGroupArray,$beGroupKeys,0);
+		}
 
 			// Length of strings:
 		$tLen= ($this->MOD_SETTINGS['mode']=='perms' ? 20 : 30);
@@ -525,14 +595,14 @@
 
 			// Creating top icon; the current page
 		$HTML=t3lib_iconWorks::getIconImage('pages',$this->pageinfo,$BACK_PATH,'align="top"');
-		$tree->tree[]=Array('row'=>$this->pageinfo,'HTML'=>$HTML);
+		$tree->tree[] = array('row'=>$this->pageinfo,'HTML'=>$HTML);
 
 			// Create the tree from $this->id:
 		$tree->getTree($this->id,$this->MOD_SETTINGS['depth'],'');
 
 			// Make header of table:
 		$code='';
-		if ($this->MOD_SETTINGS['mode']=='perms')	{
+		if ($this->MOD_SETTINGS['mode']=='perms') {
 			$code.='
 				<tr>
 					<td class="bgColor2" colspan="2">&nbsp;</td>
@@ -558,29 +628,34 @@
 		}
 
 			// Traverse tree:
-		foreach($tree->tree as $data)	{
+		foreach ($tree->tree as $data) {
 			$cells = array();
+			$pageId = $data['row']['uid'];
 
 				// Background colors:
-			if ($this->lastEdited==$data['row']['uid'])	{$bgCol = ' class="bgColor-20"';} else {$bgCol = '';}
+			$bgCol = ($this->lastEdited == $pageId ? ' class="bgColor-20"' : '');
 			$lE_bgCol = $bgCol;
 
 				// User/Group names:
-			$userN = $be_user_Array[$data['row']['perms_userid']] ? $be_user_Array[$data['row']['perms_userid']]['username'] : ($data['row']['perms_userid'] ? '<i>['.$data['row']['perms_userid'].']!</i>' : '');
-			$groupN = $be_group_Array[$data['row']['perms_groupid']] ? $be_group_Array[$data['row']['perms_groupid']]['title']  : ($data['row']['perms_groupid'] ? '<i>['.$data['row']['perms_groupid'].']!</i>' : '');
-			$groupN = t3lib_div::fixed_lgd_cs($groupN,20);
+			$userName = $beUserArray[$data['row']['perms_userid']] ? $beUserArray[$data['row']['perms_userid']]['username'] : ($data['row']['perms_userid'] ? '<i>['.$data['row']['perms_userid'].']!</i>' : '');
+			$userName = SC_mod_web_perm_ajax::renderOwnername($pageId, $data['row']['perms_userid'], htmlspecialchars(t3lib_div::fixed_lgd_cs($userName, 20)));
 
+			$groupName = $beGroupArray[$data['row']['perms_groupid']] ? $beGroupArray[$data['row']['perms_groupid']]['title']  : ($data['row']['perms_groupid'] ? '<i>['.$data['row']['perms_groupid'].']!</i>' : '');
+			$groupName = SC_mod_web_perm_ajax::renderGroupname($pageId, $data['row']['perms_groupid'], htmlspecialchars(t3lib_div::fixed_lgd_cs($groupName, 20)));
+
+
 				// Seeing if editing of permissions are allowed for that page:
-			$editPermsAllowed=($data['row']['perms_userid']==$BE_USER->user['uid'] || $BE_USER->isAdmin());
+			$editPermsAllowed = ($data['row']['perms_userid'] == $BE_USER->user['uid'] || $BE_USER->isAdmin());
 
+
 				// First column:
 			$cellAttrib = ($data['row']['_CSSCLASS'] ? ' class="'.$data['row']['_CSSCLASS'].'"' : '');
 			$cells[]='
 					<td align="left" nowrap="nowrap"'.($cellAttrib ? $cellAttrib : $bgCol).'>'.$data['HTML'].htmlspecialchars(t3lib_div::fixed_lgd($data['row']['title'],$tLen)).'&nbsp;</td>';
 
 				// "Edit permissions" -icon
-			if ($editPermsAllowed && $data['row']['uid'])	{
-				$aHref = 'index.php?mode='.$this->MOD_SETTINGS['mode'].'&depth='.$this->MOD_SETTINGS['depth'].'&id='.($data['row']['_ORIG_uid'] ? $data['row']['_ORIG_uid'] : $data['row']['uid']).'&return_id='.$this->id.'&edit=1';
+			if ($editPermsAllowed && $pageId) {
+				$aHref = 'index.php?mode='.$this->MOD_SETTINGS['mode'].'&depth='.$this->MOD_SETTINGS['depth'].'&id='.($data['row']['_ORIG_uid'] ? $data['row']['_ORIG_uid'] : $pageId).'&return_id='.$this->id.'&edit=1';
 				$cells[]='
 					<td'.$bgCol.'><a href="'.htmlspecialchars($aHref).'"><img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/edit2.gif','width="11" height="12"').' border="0" title="'.$LANG->getLL('ch_permissions',1).'" align="top" alt="" /></a></td>';
 			} else {
@@ -589,37 +664,38 @@
 			}
 
 				// Rest of columns (depending on mode)
-			if ($this->MOD_SETTINGS['mode']=='perms')	{
+			if ($this->MOD_SETTINGS['mode'] == 'perms') {
 				$cells[]='
 					<td'.$bgCol.'><img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/line.gif','width="5" height="16"').' alt="" /></td>
-					<td'.$bgCol.' nowrap="nowrap">'.($data['row']['uid']?$this->printPerms($data['row']['perms_user']).' '.$userN:'').'</td>
+					<td'.$bgCol.' nowrap="nowrap">'.($pageId ? SC_mod_web_perm_ajax::renderPermissions($data['row']['perms_user'], $pageId, 'user').' '.$userName : '').'</td>
 
 					<td'.$bgCol.'><img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/line.gif','width="5" height="16"').' alt="" /></td>
-					<td'.$bgCol.' nowrap="nowrap">'.($data['row']['uid']?$this->printPerms($data['row']['perms_group']).' '.$groupN:'').'</td>
+					<td'.$bgCol.' nowrap="nowrap">'.($pageId ? SC_mod_web_perm_ajax::renderPermissions($data['row']['perms_group'], $pageId, 'group').' '.$groupName : '').'</td>
 
 					<td'.$bgCol.'><img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/line.gif','width="5" height="16"').' alt="" /></td>
-					<td'.$bgCol.' nowrap="nowrap">'.($data['row']['uid']?' '.$this->printPerms($data['row']['perms_everybody']):'').'</td>
+					<td'.$bgCol.' nowrap="nowrap">'.($pageId ? ' '.SC_mod_web_perm_ajax::renderPermissions($data['row']['perms_everybody'], $pageId, 'everybody') : '').'</td>
 
 					<td'.$bgCol.'><img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/line.gif','width="5" height="16"').' alt="" /></td>
-					<td'.$bgCol.' nowrap="nowrap">'.($data['row']['editlock']?'<img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/recordlock_warning2.gif','width="22" height="16"').' title="'.$LANG->getLL('EditLock_descr',1).'" alt="" />':'').'</td>
+					<td'.$bgCol.' nowrap="nowrap">'.($data['row']['editlock']?'<span id="el_'.$pageId.'" class="editlock"><a class="editlock" onclick="WebPermissions.toggleEditLock(\''.$pageId.'\', \'1\');"><img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/recordlock_warning2.gif','width="22" height="16"').' title="'.$LANG->getLL('EditLock_descr',1).'" alt="Edit Lock" /></a></span>' : ( $pageId === 0 ? '' : '<span id="el_'.$pageId.'" class="editlock"><a class="editlock" onclick="WebPermissions.toggleEditLock(\''.$pageId.'\', \'0\');" title="Enable the &raquo;Admin-only&laquo; edit lock for this page">[+]</a></span>')).'</td>
 				';
 			} else {
 				$cells[]='
 					<td'.$bgCol.'><img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/line.gif','width="5" height="16"').' alt="" /></td>';
 
-				if ($BE_USER->user['uid']==$data['row']['perms_userid'])	{$bgCol = ' class="bgColor-20"';} else {$bgCol = $lE_bgCol;}
-// FIXME $owner undefined
+				$bgCol = ($BE_USER->user['uid'] == $data['row']['perms_userid'] ? ' class="bgColor-20"' : $lE_bgCol);
+
+				// FIXME $owner undefined
 				$cells[]='
-					<td'.$bgCol.' nowrap="nowrap" align="center">'.($data['row']['uid']?$owner.$this->printPerms($BE_USER->calcPerms($data['row'])):'').'</td>
+					<td'.$bgCol.' nowrap="nowrap" align="center">'.($pageId ? $owner.SC_mod_web_perm_ajax::renderPermissions($BE_USER->calcPerms($data['row']), $pageId, 'user') : '').'</td>
 					'.(!$BE_USER->isAdmin()?'
 					<td'.$bgCol.'><img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/line.gif','width="5" height="16"').' alt="" /></td>
-					<td'.$bgCol.' nowrap="nowrap">'.($data['row']['editlock']?'<img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/recordlock_warning2.gif','width="22" height="16"').' title="'.$LANG->getLL('EditLock_descr',1).'" alt="" />':'').'</td>
+					<td'.$bgCol.' nowrap="nowrap">'.($data['row']['editlock']?'<img'.t3lib_iconWorks::skinImg($BACK_PATH,'gfx/recordlock_warning2.gif','width="22" height="16"').' title="'.$LANG->getLL('EditLock_descr',1).'" alt="" />' : '').'</td>
 					':'');
 				$bgCol = $lE_bgCol;
 			}
 
 				// Compile table row:
-			$code.='
+			$code .= '
 				<tr>
 					'.implode('
 					',$cells).'
@@ -627,7 +703,7 @@
 		}
 
 			// Wrap rows in table tags:
-		$code='<table border="0" cellspacing="0" cellpadding="0" id="typo3-permissionList">'.$code.'</table>';
+		$code = '<table border="0" cellspacing="0" cellpadding="0" id="typo3-permissionList" width="98%">'.$code.'</table>';
 
 			// Adding the content as a section:
 		$this->content.=$this->doc->section('',$code);
@@ -663,13 +739,6 @@
 
 
 
-
-
-
-
-
-
-
 	/*****************************
 	 *
 	 * Helper functions
@@ -683,28 +752,12 @@
 	 * @param	integer		Checkbox number index
 	 * @return	string		HTML checkbox
 	 */
-	function printCheckBox($checkName,$num)	{
-		$onClick = 'checkChange(\'check['.$checkName.']\', \'data[pages]['.$GLOBALS['SOBE']->id.']['.$checkName.']\')';
-		return '<input type="checkbox" name="check['.$checkName.']['.$num.']" onclick="'.htmlspecialchars($onClick).'" /><br />';
+	public function printCheckBox($checkName, $num) {
+		$onclick = 'checkChange(\'check['.$checkName.']\', \'data[pages]['.$GLOBALS['SOBE']->id.']['.$checkName.']\')';
+		return '<input type="checkbox" name="check['.$checkName.']['.$num.']" onclick="'.htmlspecialchars($onclick).'" /><br />';
 	}
 
-	/**
-	 * Print a set of permissions
-	 *
-	 * @param	integer		Permission integer (bits)
-	 * @return	string		HTML marked up x/* indications.
-	 */
-	function printPerms($int)	{
-		$str='';
-		$str.= (($int&1)?'*':'<span class="perm-denied">x</span>');
-		$str.= (($int&16)?'*':'<span class="perm-denied">x</span>');
-		$str.= (($int&2)?'*':'<span class="perm-denied">x</span>');
-		$str.= (($int&4)?'*':'<span class="perm-denied">x</span>');
-		$str.= (($int&8)?'*':'<span class="perm-denied">x</span>');
 
-		return '<span class="perm-allowed">'.$str.'</span>';
-	}
-
 	/**
 	 * Returns the permissions for a group based of the perms_groupid of $row. If the $row[perms_groupid] equals the $firstGroup[uid] then the function returns perms_everybody OR'ed with perms_group, else just perms_everybody
 	 *
@@ -712,11 +765,11 @@
 	 * @param	array		First group data
 	 * @return	integer		Integer: Combined permissions.
 	 */
-	function groupPerms($row,$firstGroup)	{
+	public function groupPerms($row, $firstGroup) {
 		if (is_array($row))	{
-			$out=intval($row['perms_everybody']);
+			$out = intval($row['perms_everybody']);
 			if ($row['perms_groupid'] && $firstGroup['uid']==$row['perms_groupid'])	{
-				$out|= intval($row['perms_group']);
+				$out |= intval($row['perms_group']);
 			}
 			return $out;
 		}
@@ -729,7 +782,7 @@
 	 * @param	string		Select clause
 	 * @return	string		Select form element for recursive levels (if any levels are found)
 	 */
-	function getRecursiveSelect($id,$perms_clause)	{
+	public function getRecursiveSelect($id,$perms_clause) {
 
 			// Initialize tree object:
 		$tree = t3lib_div::makeInstance('t3lib_pageTree');
@@ -742,7 +795,7 @@
 		$tree->getTree($id,$this->getLevels,'');
 
 			// If there are a hierarchy of page ids, then...
-		if ($GLOBALS['BE_USER']->user['uid'] && count($tree->orig_ids_hierarchy))	{
+		if ($GLOBALS['BE_USER']->user['uid'] && count($tree->orig_ids_hierarchy)) {
 
 				// Init:
 			$label_recur = $GLOBALS['LANG']->getLL('recursive');
@@ -773,7 +826,6 @@
 					<select name="mirror[pages]['.$id.']">
 						'.$opts.'
 					</select>
-
 				<br /><br />';
 		} else {
 			$theRecursiveSelect = '';
@@ -809,4 +861,5 @@
 if ($TYPO3_CONF_VARS['BE']['compressionLevel'])	{
 	new gzip_encode($TYPO3_CONF_VARS['BE']['compressionLevel']);
 }
+
 ?>
Index: typo3/mod/web/perm/perm.js
===================================================================
--- typo3/mod/web/perm/perm.js	(revision 0)
+++ typo3/mod/web/perm/perm.js	(revision 0)
@@ -0,0 +1,121 @@
+/***************************************************************
+*
+*  Javascript functions regarding the permissions module
+*  Relies on the javascript library "prototype"
+*
+*  Copyright notice
+*
+*  (c) 2007-2008	Andreas Beutel <typo3@mehrwert.de>
+*  (c) 2007	Benjamin Mack <www.xnos.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project 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 GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script 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.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/**
+ * @author		Andreas Kundoch <typo3@mehrwert.de>
+ * @author		Benjamin Mack <www.xnos.org>
+ * @package		TYPO3
+ * @subpackage	core
+ * @version 	$Id: index.php 3074 2008-02-05 16:46:59Z patrickbroens $
+ */
+
+// TYPO3 code extracted from index.php
+function checkChange(checknames, varname) {
+	var res = 0;
+	for (var a=1; a<=5; a++)	{
+		if (document.editform[checknames+'['+a+']'].checked) {
+			res|=Math.pow(2,a-1);
+		}
+	}
+	document.editform[varname].value = res | (checknames == 'check[perms_user]' ? 1 : 0);
+	setCheck(checknames, varname);
+}
+
+function setCheck(checknames, varname) {
+	if (document.editform[varname])	{
+		var res = document.editform[varname].value;
+		for (var a=1; a<=5; a++) {
+			document.editform[checknames+'['+a+']'].checked = (res & Math.pow(2,a-1));
+		}
+	}
+}
+
+function jumpToUrl(URL)	{ window.location.href = URL; }
+
+// Methods for AJAX permission manipulation
+var WebPermissions = {
+
+    thisScript: '../../../ajax.php',
+	ajaxID: 'SC_mod_web_perm_ajax::dispatch',
+
+		// set the permission bits through an ajax call
+	setPermissions: function(page, bits, mode, who, permissions) {
+		new Ajax.Updater($(page + '_' + who), this.thisScript, {
+			parameters: { ajaxID: this.ajaxID, page: page, permissions: permissions, mode: mode, who: who, bits: bits }
+		});
+	},
+
+		// load the selector for selecting the owner of a page by executing an ajax call
+	showChangeOwnerSelector: function(page, ownerUid, elementID, username) {
+		new Ajax.Updater($(elementID), this.thisScript, {
+			parameters: { ajaxID: this.ajaxID, action: 'show_change_owner_selector', page: page, ownerUid: ownerUid, username: username }
+		});
+	},
+
+		// Set the new owner of a page by executing an ajax call
+	changeOwner: function(page, ownerUid, elementID) {
+		new Ajax.Updater($(elementID), this.thisScript, {
+			parameters: { ajaxID: this.ajaxID, action: 'change_owner', page: page, ownerUid: ownerUid, owner_data: $('new_page_owner').serialize(true) }
+		});
+	},
+
+		// Update the HTML view and show the original owner
+	restoreOwner: function(page, ownerUid, username, elementID) {
+		var idName = 'o_' + page;
+		$(elementID).innerHTML = '<a class="ug_selector" onclick="WebPermissions.showChangeOwnerSelector(' + page + ', ' + ownerUid + ', \'' + idName + '\', \'' + username + '\');">' + username + '</a>';
+	},
+
+		// Load the selector by executing an ajax call
+	showChangeGroupSelector: function(page, groupUid, elementID, groupname) {
+		new Ajax.Updater($(elementID), this.thisScript, {
+			parameters: { ajaxID: this.ajaxID, action: 'show_change_group_selector', page: page, groupUid: groupUid, groupname: groupname }
+		});
+	},
+
+		// Set the new group by executing an ajax call
+	changeGroup: function(page, groupUid, elementID) {
+		new Ajax.Updater($(elementID), this.thisScript, {
+			parameters: { ajaxID: this.ajaxID, action: 'change_group', page: page, groupUid: groupUid, group_data: $('new_page_group').serialize(true) }
+		});
+	},
+
+		// Update the HTML view and show the original group
+	restoreGroup: function(page, groupUid, groupname, elementID) {
+		var idName = 'g_' + page;
+		$(elementID).innerHTML = '<a class="ug_selector" onclick="WebPermissions.showChangeGroupSelector(' + page + ', ' + groupUid + ', \'' + idName + '\', \'' + groupname + '\');">' + groupname + '</a>';
+	},
+
+		// set or remove the edit lock by executing an ajax call
+	toggleEditLock: function(page, editLockState) {
+		new Ajax.Updater($('el_' + page), this.thisScript, {
+			parameters: { ajaxID: this.ajaxID, action: 'toggle_edit_lock', page: page, editLockState: editLockState }
+		});
+	}
+};
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 3243)
+++ ChangeLog	(working copy)
@@ -1,3 +1,7 @@
+2008-02-21  Benjamin Mack  <mack@xnos.org>
+
+	* Added feature "Extended BE Module "Web/Permissions" with AJAX possibilites (Thanks to Andreas Kundoch)
+
 2008-02-21  Ingo Renner  <ingo@typo3.org>
 
 	* !!! modified the interface for toolbarItems so that the reference to the backend Object in the constructor is optional, this was necessary to have AJAX response methods in the same class as the code that generates the toolbar item itself
