Commits

Jean-Christian Denis committed e6db669

Fixes a CSRF on users deletion.
Cleaned code on users manager, fixes #1200

  • Participants
  • Parent commits cbc4839

Comments (0)

Files changed (12)

File admin/blog_pref.php

 				'<h4>'.sprintf($user_url_p,html::escapeHTML($k)).
 				' ('.html::escapeHTML(dcUtils::getUserCN(
 					$k, $v['name'], $v['firstname'], $v['displayname']
-				)).')';
-				
-				if (!$v['super'] && $core->auth->isSuperAdmin()) {
-					echo
-					' - <a href="permissions.php?blog_id[]='.$blog_id.'&amp;user_id[]='.$k.'">'
-					.__('Change permissions').'</a>';
-				}
-				
-				echo '</h4>';
+				)).')</h4>';
 				
 				echo '<ul>';
 				if ($v['super']) {
 					}
 				}
 				echo '</ul>';
+				
+				if (!$v['super'] && $core->auth->isSuperAdmin()) {
+					echo 
+					'<form action="users_actions.php" method="post">'.
+					'<p><input type="submit" value="'.__('Change permissions').'" />'.
+					form::hidden(array('redir'),'blog_pref.php?id='.$k).
+					form::hidden(array('action'),'perms').
+					form::hidden(array('users[]'),$k).
+					form::hidden(array('blogs[]'),$blog_id).
+					$core->formNonce().
+					'</p>'.
+					'</form>';
+				}
 			}
 		}
 	}

File admin/dispatcher.php

-<?php
-# -- BEGIN LICENSE BLOCK ---------------------------------------
-#
-# This file is part of Dotclear 2.
-#
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
-# Licensed under the GPL version 2.0 license.
-# See LICENSE file or
-# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
-#
-# -- END LICENSE BLOCK -----------------------------------------
-
-# Delete users
-if (!empty($_REQUEST['dispatch_action']))
-{
-	if ($_REQUEST['dispatch_action'] == 'deleteuser')
-	{
-		if (!empty($_REQUEST['user_id'])) {
-			$delete_users = $_REQUEST['user_id'];
-		}
-		
-		include dirname(__FILE__).'/users.php';
-		exit;
-	}
-	elseif ($_REQUEST['dispatch_action'] == 'setpermissions')
-	{
-		include dirname(__FILE__).'/permissions_blog.php';
-		exit;
-	}
-}
-
-echo '<p>What the hell are you doing here?</p>';
-exit;
-?>

File admin/js/_permissions.js

-jQuery.fn.updatePermissionsForm = function() {
-	return this.each(function() {
-		var perms = {};
-		var re = /^perm\[(.+?)\]\[(.+?)\]$/;
-		var e,prop;
-		
-		// Building a nice object of form elements
-		for (var i=0; i<this.elements.length; i++) {
-			e = this.elements[i];
-			
-			if (e.name == undefined) {
-				continue;
-			}
-			prop = e.name.match(re);
-			if (!prop) {
-				continue;
-			}
-			if (perms[prop[1]] == undefined) {
-				perms[prop[1]] = {};
-			}
-			perms[prop[1]][prop[2]] = e;
-		}
-		
-		// Update elements status
-		var E;
-		for (blog in perms) {
-			for (perm in perms[blog]) {
-				E = perms[blog][perm];
-				E.onclick = function() {};
-				
-				if (perm == 'admin' && !E.disabled) {
-					perms[blog]['usage'].disabled = E.checked;
-					perms[blog]['publish'].disabled = E.checked;
-					perms[blog]['delete'].disabled = E.checked;
-					perms[blog]['contentadmin'].disabled = E.checked;
-					perms[blog]['categories'].disabled = E.checked;
-					perms[blog]['media'].disabled = E.checked;
-					perms[blog]['media_admin'].disabled = E.checked;
-					E.onclick = function() { $(this.form).updatePermissionsForm(); };
-				} else if (perm == 'contentadmin' && !E.disabled) {
-					perms[blog]['usage'].disabled = E.checked;
-					perms[blog]['publish'].disabled = E.checked;
-					perms[blog]['delete'].disabled = E.checked;
-					E.onclick = function() { $(this.form).updatePermissionsForm(); };
-				} else if (perm == 'media_admin' && !E.disabled) {
-					perms[blog]['media'].disabled = E.checked;
-					E.onclick = function() { $(this.form).updatePermissionsForm(); };
-				}
-			}
-		}
-	});
-};
-
-$(function() {
-	$('#permissions-form').updatePermissionsForm();
-});

File admin/js/_permissions_blog.js

-$(function() {
-	$('.checkboxes-helpers').each(function() {
-		dotclear.checkboxesHelpers(this);
-	});
-});

File admin/js/_users.js

 		dotclear.checkboxesHelpers(this);
 	});
 	$('#form-users').submit(function() {
-		var action = $(this).find('select[name="dispatch_action"]').val();
+		var action = $(this).find('select[name="action"]').val();
 		var user_ids = new Array();
 		var nb_posts = new Array();
 		var i;
 		var msg_cannot_delete = false;
 		
-		$(this).find('input[name="user_id[]"]').each(function() {
+		$(this).find('input[name="users[]"]').each(function() {
 			user_ids.push(this);
 		});
 		$(this).find('input[name="nb_post[]"]').each(function() {
 		}
 		
 		if (action == 'deleteuser') {
-			return window.confirm(dotclear.msg.confirm_delete_user.replace('%s',$('input[name="user_id[]"]:checked').size()));
+			return window.confirm(dotclear.msg.confirm_delete_user.replace('%s',$('input[name="users[]"]:checked').size()));
 		}
 		
 		return true;

File admin/js/_users_actions.js

+jQuery.fn.updatePermissionsForm = function() {
+	return this.each(function() {
+		var perms = {};
+		var re = /^perm\[(.+?)\]\[(.+?)\]$/;
+		var e,prop;
+		
+		// Building a nice object of form elements
+		for (var i=0; i<this.elements.length; i++) {
+			e = this.elements[i];
+			
+			if (e.name == undefined) {
+				continue;
+			}
+			prop = e.name.match(re);
+			if (!prop) {
+				continue;
+			}
+			if (perms[prop[1]] == undefined) {
+				perms[prop[1]] = {};
+			}
+			perms[prop[1]][prop[2]] = e;
+		}
+		
+		// Update elements status
+		var E;
+		for (blog in perms) {
+			for (perm in perms[blog]) {
+				E = perms[blog][perm];
+				E.onclick = function() {};
+				
+				if (perm == 'admin' && !E.disabled) {
+					perms[blog]['usage'].disabled = E.checked;
+					perms[blog]['publish'].disabled = E.checked;
+					perms[blog]['delete'].disabled = E.checked;
+					perms[blog]['contentadmin'].disabled = E.checked;
+					perms[blog]['categories'].disabled = E.checked;
+					perms[blog]['media'].disabled = E.checked;
+					perms[blog]['media_admin'].disabled = E.checked;
+					E.onclick = function() { $(this.form).updatePermissionsForm(); };
+				} else if (perm == 'contentadmin' && !E.disabled) {
+					perms[blog]['usage'].disabled = E.checked;
+					perms[blog]['publish'].disabled = E.checked;
+					perms[blog]['delete'].disabled = E.checked;
+					E.onclick = function() { $(this.form).updatePermissionsForm(); };
+				} else if (perm == 'media_admin' && !E.disabled) {
+					perms[blog]['media'].disabled = E.checked;
+					E.onclick = function() { $(this.form).updatePermissionsForm(); };
+				}
+			}
+		}
+	});
+};
+
+$(function() {
+	$('.checkboxes-helpers').each(function() {
+		dotclear.checkboxesHelpers(this);
+	});
+	$('#permissions-form').updatePermissionsForm();
+});

File admin/permissions.php

-<?php
-# -- BEGIN LICENSE BLOCK ---------------------------------------
-#
-# This file is part of Dotclear 2.
-#
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
-# Licensed under the GPL version 2.0 license.
-# See LICENSE file or
-# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
-#
-# -- END LICENSE BLOCK -----------------------------------------
-
-require dirname(__FILE__).'/../inc/admin/prepend.php';
-
-dcPage::checkSuper();
-
-$changes = false;
-$blogs = array();
-$users = array();
-
-# Check users
-if (!empty($_REQUEST['user_id']) && is_array($_REQUEST['user_id']))
-{
-	foreach ($_REQUEST['user_id'] as $u)
-	{
-		if ($core->userExists($u)) {
-			$users[] = $u;
-		}
-	}
-}
-
-# Check blogs
-if (!empty($_REQUEST['blog_id']) && is_array($_REQUEST['blog_id']))
-{
-	foreach ($_REQUEST['blog_id'] as $b)
-	{
-		if ($core->blogExists($b)) {
-			$blogs[] = $b;
-		}
-	}
-}
-
-# Update permissions
-if (!empty($_POST['upd_perm']) && !empty($users) && !empty($blogs))
-{
-	$redir = 'permissions.php?upd=1';
-	
-	try
-	{
-		if (empty($_POST['your_pwd']) || !$core->auth->checkPassword(crypt::hmac(DC_MASTER_KEY,$_POST['your_pwd']))) {
-			throw new Exception(__('Password verification failed'));
-		}
-		
-		foreach ($users as $u)
-		{
-			foreach ($blogs as $b)
-			{
-				$set_perms = array();
-				
-				if (!empty($_POST['perm'][$b]))
-				{
-					foreach ($_POST['perm'][$b] as $perm_id => $v)
-					{
-						if ($v) {
-							$set_perms[$perm_id] = true;
-						}
-					}
-				}
-				
-				$core->setUserBlogPermissions($u, $b, $set_perms, true);
-			}
-			
-			$redir .= '&user_id[]='.$u;
-		}
-		
-		foreach ($blogs as $b) {
-			$redir .= '&blog_id[]='.$b;
-		}
-		http::redirect($redir);
-	}
-	catch (Exception $e)
-	{
-		$core->error->add($e->getMessage());
-	}
-}
-
-
-
-if (empty($blogs) || empty($users)) {
-	$core->error->add(__('No blog or user given.'));
-}
-
-
-/* DISPLAY
--------------------------------------------------------- */
-dcPage::open(__('permissions'),
-	dcPage::jsLoad('js/_permissions.js')
-);
-
-echo '<h2><a href="users.php">'.__('Users').'</a> &rsaquo; <span class="page-title">'.__('Permissions').'</span></h2>';
-
-if (!empty($_GET['upd'])) {
-		echo '<p class="message">'.__('The permissions have been successfully updated.').'</p>';
-}
-
-if (!empty($blogs) && !empty($users))
-{
-	$perm_form = '';
-	
-	if (count($users) == 1) {
-			$user_perm = $core->getUserPermissions($users[0]);	
-	}
-	
-	foreach ($users as $u) {
-		$user_list[] = '<a href="user.php?id='.$u.'">'.$u.'</a>';
-	}
-	
-	echo '<p>'.sprintf(__('You are about to change permissions on the following blogs for users %s.'),
-	implode(', ',$user_list));
-	
-	echo '<form id="permissions-form" action="permissions.php" method="post">';
-	
-	foreach ($blogs as $b)
-	{
-		echo '<h3><a href="blog.php?id='.html::escapeHTML($b).'">'.html::escapeHTML($b).'</a>'.
-		form::hidden(array('blog_id[]'),$b).'</h3>';
-		
-		foreach ($core->auth->getPermissionsTypes() as $perm_id => $perm)
-		{
-			$checked = false;
-			
-			if (count($users) == 1) {
-				$checked = isset($user_perm[$b]['p'][$perm_id]) && $user_perm[$b]['p'][$perm_id];
-			}
-			
-			echo
-			'<p><label for="perm'.html::escapeHTML($b).html::escapeHTML($perm_id).'" class="classic">'.
-			form::checkbox(array('perm['.html::escapeHTML($b).']['.html::escapeHTML($perm_id).']','perm'.html::escapeHTML($b).html::escapeHTML($perm_id)),
-			1,$checked).' '.
-			__($perm).'</label></p>';
-		}
-	}
-	
-	echo
-	'<fieldset><legend>'.__('Validate permissions').'</legend>'.
-	'<p><label for="your_pwd">'.__('Your password:').
-	form::password('your_pwd',20,255).'</label></p>'.
-	'</fieldset>'.
-	'<p><input type="submit" accesskey="s" value="'.__('Save').'" />'.
-	$core->formNonce();
-	
-	foreach ($users as $u) {
-		echo form::hidden(array('user_id[]'),$u);
-	}
-	
-	echo	form::hidden('upd_perm',1).'</p></form>';
-}
-
-dcPage::close();
-?>

File admin/permissions_blog.php

-<?php
-# -- BEGIN LICENSE BLOCK ---------------------------------------
-#
-# This file is part of Dotclear 2.
-#
-# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
-# Licensed under the GPL version 2.0 license.
-# See LICENSE file or
-# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
-#
-# -- END LICENSE BLOCK -----------------------------------------
-
-require dirname(__FILE__).'/../inc/admin/prepend.php';
-
-dcPage::checkSuper();
-
-# Filters
-$sortby_combo = array(
-__('Blog ID') => 'B.blog_id',
-__('Blog name') => 'blog_name'
-);
-
-$order_combo = array(
-__('Descending') => 'desc',
-__('Ascending') => 'asc'
-);
-
-$q = !empty($_GET['q']) ? $_GET['q'] : '';
-$sortby = !empty($_GET['sortby']) ? $_GET['sortby'] : 'blog_id';
-$order = !empty($_GET['order']) ? $_GET['order'] : 'asc';
-
-
-# Check users
-if (!empty($_REQUEST['user_id']) && is_array($_REQUEST['user_id']))
-{
-	foreach ($_REQUEST['user_id'] as $u)
-	{
-		if ($core->userExists($u)) {
-			$users[] = $u;
-		}
-	}
-}
-
-if (empty($users))
-{
-	$core->error->add(__('No blog or user given.'));
-}
-else
-{
-	$page = !empty($_GET['page']) ? $_GET['page'] : 1;
-	$nb_per_page =  30;
-	
-	if (!empty($_GET['nb']) && (integer) $_GET['nb'] > 0) {
-		$nb_per_page = $_GET['nb'];
-	}
-	
-	$show_filters = false;
-	
-	# - Search filter
-	if ($q) {
-		$params['q'] = $q;
-		$show_filters = true;
-	}
-	
-	# - Sortby and order filter
-	if ($sortby !== '' && in_array($sortby,$sortby_combo)) {
-		if ($order !== '' && in_array($order,$order_combo)) {
-			$params['order'] = $sortby.' '.$order;
-			$show_filters = true;
-		}
-	}
-	
-	$params['limit'] = array((($page-1)*$nb_per_page),$nb_per_page);
-	
-	try {
-		$rs = $core->getBlogs($params);
-		$counter = $core->getBlogs($params,1);
-		$nb_blog = $counter->f(0);
-	} catch (Exception $e) {
-		$core->error->add($e->getMessage());
-	}
-}
-
-/* DISPLAY
--------------------------------------------------------- */
-$starting_script = dcPage::jsLoad('js/_permissions_blog.js');
-if (!$show_filters) {
-	$starting_script .= dcPage::jsLoad('js/filter-controls.js');
-}
-dcPage::open(__('choose a blog'),$starting_script);
-
-echo '<h2><a href="users.php">'.__('Users').'</a> &rsaquo; <span class="page-title">'.__('Choose a blog').'</span></h2>';
-
-if (!$core->error->flag())
-{
-	$hidden_fields = '';
-	foreach ($users as $u) {
-		$hidden_fields .= form::hidden(array('user_id[]'),$u);
-	}
-	
-	if (!$show_filters) {
-		echo '<p><a id="filter-control" class="form-control" href="#">'.__('Filters').'</a></p>';
-	}
-	
-	echo
-	'<form action="permissions_blog.php" method="get" id="filters-form">'.
-	'<fieldset class="two-cols"><legend>'.__('Filters').'</legend>'.
-	
-	'<div class="col">'.
-	'<p><label for="sortby">'.__('Order by:').' '.
-	form::combo('sortby',$sortby_combo,html::escapeHTML($sortby)).
-	'</label> '.
-	'<label for="order">'.__('Sort:').' '.
-	form::combo('order',$order_combo,html::escapeHTML($order)).
-	'</label></p>'.
-	'</div>'.
-	
-	'<div class="col">'.
-	'<p><label for="q">'.__('Search:').' '.
-	form::field('q',20,255,html::escapeHTML($q)).
-	'</label></p>'.
-	'<p><label for="nb" class="classic">'.	form::field('nb',3,3,$nb_per_page).' '.
-	__('Entries per page').'</label> '.
-	'<input type="submit" value="'.__('Apply filters').'" />'.
-	$hidden_fields.'</p>'.
-	'</div>'.
-	
-	'<br class="clear" />'. //Opera sucks
-	'</fieldset>'.
-	'</form>';
-	
-	echo
-	'<p>'.
-	sprintf(__('Choose one or more blogs to which you want to give permissions to users %s.'),
-	'<strong>'.implode(', ',$users).'</strong>').'</p>';
-	
-	# Show blogs
-	if ($nb_blog == 0)
-	{
-		echo '<p><strong>'.__('No blog').'</strong></p>';
-	}
-	else
-	{
-		$pager = new pager($page,$nb_blog,$nb_per_page,10);
-		$pager->var_page = 'page';
-		
-		echo '<p>'.__('Page(s)').' : '.$pager->getLinks().'</p>';
-		
-		echo
-		'<form action="permissions.php" method="post" id="form-blogs">'.
-		'<table class="clear"><tr>'.
-		'<th colspan="2">'.__('Blog ID').'</th>'.
-		'<th>'.__('Blog name').'</th>'.
-		'<th class="nowrap">'.__('Entries').'</th>'.
-		'<th class="nowrap">'.__('Status').'</th>'.
-		'</tr>';
-		
-		while ($rs->fetch()) {
-			echo blogLine($rs);
-		}
-		
-		echo
-		'</table>'.
-		
-		'<p class="checkboxes-helpers"></p>'.
-		
-		'<p><input type="submit" value="'.__('Set permissions').'" />'.
-		$hidden_fields.
-		$core->formNonce().'</p>'.
-		'</form>';
-		
-		echo '<p>'.__('Page(s)').' : '.$pager->getLinks().'</p>';
-	}
-}
-
-dcPage::close();
-
-function blogLine($rs)
-{
-	global $core;
-	
-	$img_status = $rs->blog_status == 1 ? 'check-on' : 'check-off';
-	$txt_status = $GLOBALS['core']->getBlogStatus($rs->blog_status);
-	$img_status = sprintf('<img src="images/%1$s.png" alt="%2$s" title="%2$s" />',$img_status,$txt_status);
-	
-	return
-	'<tr class="line">'.
-	'<td class="nowrap">'.
-	form::checkbox(array('blog_id[]'),$rs->blog_id,'','','',false,'title="'.__('select').' '.$rs->blog_id.'"').'</td>'.
-	'<td class="nowrap">'.$rs->blog_id.'</td>'.
-	'<td class="maximal">'.html::escapeHTML($rs->blog_name).'</td>'.
-	'<td class="nowrap">'.$core->countBlogPosts($rs->blog_id).'</td>'.
-	'<td class="status">'.$img_status.'</td>'.
-	'</tr>';
-}
-?>

File admin/user.php

 
 if ($user_id)
 {
-	echo '<div class="clear fieldset"><h3>'.__('Permissions').'</h3>';
+	echo '<div class="clear fieldset"><h3>'.__('Permissions').'</h3>'.
+	'<form action="users_actions.php" method="post">'.
+	'<p><input type="submit" value="'.__('Add new permissions').'" />'.
+	form::hidden(array('redir'),'user.php?id='.$user_id).
+	form::hidden(array('action'),'blogs').
+	form::hidden(array('users[]'),$user_id).
+	$core->formNonce().
+	'</p>'.
+	'</form>';
 	
 	$permissions = $core->getUserPermissions($user_id);
 	$perm_types = $core->auth->getPermissionsTypes();
 		{
 			if (count($v['p']) > 0)
 			{
-				echo '<h4><a href="blog.php?id='.html::escapeHTML($k).'">'.
-				html::escapeHTML($v['name']).'</a> ('.html::escapeHTML($k).') - '.
-				'<a href="permissions.php?blog_id[]='.$k.'&amp;user_id[]='.$user_id.'">'
-				.__('Change permissions').'</a></h4>';
+				echo 
+				'<form action="users_actions.php" method="post">'.
+				'<h4><a href="blog.php?id='.html::escapeHTML($k).'">'.
+				html::escapeHTML($v['name']).'</a> ('.html::escapeHTML($k).')</h4>';
 				
 				echo '<ul>';
 				foreach ($v['p'] as $p => $V) {
 						echo '<li>'.__($perm_types[$p]).'</li>';
 					}
 				}
-				echo '</ul>';
+				echo '</ul>'.
+				'<p><input type="submit" value="'.__('Change permissions').'" />'.
+				form::hidden(array('redir'),'user.php?id='.$user_id).
+				form::hidden(array('action'),'perms').
+				form::hidden(array('users[]'),$user_id).
+				form::hidden(array('blogs[]'),$k).
+				$core->formNonce().
+				'</p>'.
+				'</form>';
 			}
 		}
 	}
 	
-	echo
-	'<p><a href="permissions_blog.php?user_id[]='.$user_id.'">'.
-	__('Add new permissions').'</a></p>'.
-	'</div>';
+	echo '</div>';
 }
 
 dcPage::helpBlock('core_user');

File admin/users.php

 
 dcPage::checkSuper();
 
-# Delete users
-if (!empty($delete_users))
-{
-	foreach ($delete_users as $u)
-	{
-		try
-		{
-			# --BEHAVIOR-- adminBeforeUserDelete
-			$core->callBehavior('adminBeforeUserDelete',$u);
-			if ($u != $core->auth->userID()) {
-				$core->delUser($u);
-			}
-		}
-		catch (Exception $e)
-		{
-			$core->error->add($e->getMessage());
-		}
-	}
-	if (!$core->error->flag()) {
-		http::redirect('users.php?del=1');
-	}
-}
-
-
 # Creating filter combo boxes
 $sortby_combo = array(
-__('Username') => 'U.user_id',
+__('Username') => 'user_id',
 __('Last Name') => 'user_name',
 __('First Name') => 'user_firstname',
 __('Display name') => 'user_displayname',
 
 # Actions combo box
 $combo_action = array(
-	__('Set permissions') => 'setpermissions',
+	__('Set permissions') => 'blogs',
 	__('Delete') => 'deleteuser'
 );
 
 if ($sortby !== '' && in_array($sortby,$sortby_combo)) {
 	if ($order !== '' && in_array($order,$order_combo)) {
 		$params['order'] = $sortby.' '.$order;
+	} else {
+		$order='asc';
+	}
+	
+	if ($sortby != 'user_id' || $order != 'asc') {
 		$show_filters = true;
 	}
+} else {
+	$sortby = 'user_id';
+	$order = 'asc';
 }
 
+# Get users
 try {
 	$rs = $core->getUsers($params);
 	$counter = $core->getUsers($params,1);
 	$starting_script .= dcPage::jsLoad('js/filter-controls.js');
 }
 
-dcPage::open(__('users'),$starting_script);
+dcPage::open(__('Users'),$starting_script);
 
 if (!$core->error->flag())
 {
 	if (!empty($_GET['del'])) {
 		echo '<p class="message">'.__('User has been successfully removed.').'</p>';
 	}
+	if (!empty($_GET['upd'])) {
+			echo '<p class="message">'.__('The permissions have been successfully updated.').'</p>';
+	}
 	
 	echo 
 	'<h2 class="post-title">'.__('Users').'</h2>'.
 	
 	# Show users
 	$user_list->display($page,$nb_per_page,
-	'<form action="dispatcher.php" method="get" id="form-users">'.
+	'<form action="users_actions.php" method="post" id="form-users">'.
 	
 	'%s'.
 	
 	'<div class="two-cols">'.
 	'<p class="col checkboxes-helpers"></p>'.
 	
-	'<p class="col right"><label for="dispatch_action" class="classic">'.
+	'<p class="col right"><label for="action" class="classic">'.
 	__('Selected users action:').' '.
-	form::combo('dispatch_action',$combo_action).
+	form::combo('action',$combo_action).
 	'</label> '.
 	'<input type="submit" value="'.__('ok').'" />'.
+	form::hidden(array('q'),html::escapeHTML($q)).
+	form::hidden(array('sortby'),$sortby).
+	form::hidden(array('order'),$order).
+	form::hidden(array('page'),$page).
+	form::hidden(array('nb'),$nb_per_page).
+	$core->formNonce().
 	'</p>'.
 	'</div>'.
 	'</form>'

File admin/users_actions.php

+<?php
+# -- BEGIN LICENSE BLOCK ---------------------------------------
+#
+# This file is part of Dotclear 2.
+#
+# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
+# Licensed under the GPL version 2.0 license.
+# See LICENSE file or
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+#
+# -- END LICENSE BLOCK -----------------------------------------
+
+require dirname(__FILE__).'/../inc/admin/prepend.php';
+
+dcPage::checkSuper();
+
+$users = array();
+if (!empty($_POST['users']) && is_array($_POST['users']))
+{
+	foreach ($_POST['users'] as $u)
+	{
+		if ($core->userExists($u)) {
+			$users[] = $u;
+		}
+	}
+}
+
+$blogs = array();
+if (!empty($_POST['blogs']) && is_array($_POST['blogs']))
+{
+	foreach ($_POST['blogs'] as $b)
+	{
+		if ($core->blogExists($b)) {
+			$blogs[] = $b;
+		}
+	}
+}
+
+/* Actions
+-------------------------------------------------------- */
+if (!empty($_POST['action']) && !empty($_POST['users']))
+{
+	$action = $_POST['action'];
+	
+	if (isset($_POST['redir']) && strpos($_POST['redir'],'://') === false)
+	{
+		$redir = $_POST['redir'];
+	}
+	else
+	{
+		$redir =
+		'users.php?q='.$_POST['q'].
+		'&sortby='.$_POST['sortby'].
+		'&order='.$_POST['order'].
+		'&page='.$_POST['page'].
+		'&nb='.$_POST['nb'];
+	}
+	
+	if (empty($users)) {
+		$core->error->add(__('No blog or user given.'));
+	}
+	
+	# --BEHAVIOR-- adminUsersActions
+	$core->callBehavior('adminUsersActions',$core,$users,$blogs,$action,$redir);
+	
+	# Delete users
+	if ($action == 'deleteuser' && !empty($users))
+	{
+		foreach ($users as $u)
+		{
+			try
+			{
+				if ($u == $core->auth->userID()) {
+					throw new Exception(__('Not delete yourself.'));
+				}
+				
+				# --BEHAVIOR-- adminBeforeUserDelete
+				$core->callBehavior('adminBeforeUserDelete',$u);
+				
+				$core->delUser($u);
+			}
+			catch (Exception $e)
+			{
+				$core->error->add($e->getMessage());
+			}
+		}
+		if (!$core->error->flag()) {
+			http::redirect($redir.'&del=1');
+		}
+	}
+	
+	# Update users perms
+	if ($action == 'updateperm' && !empty($users) && !empty($blogs))
+	{
+		try
+		{
+			if (empty($_POST['your_pwd']) || !$core->auth->checkPassword(crypt::hmac(DC_MASTER_KEY,$_POST['your_pwd']))) {
+				throw new Exception(__('Password verification failed'));
+			}
+			
+			foreach ($users as $u)
+			{
+				foreach ($blogs as $b)
+				{
+					$set_perms = array();
+					
+					if (!empty($_POST['perm'][$b]))
+					{
+						foreach ($_POST['perm'][$b] as $perm_id => $v)
+						{
+							if ($v) {
+								$set_perms[$perm_id] = true;
+							}
+						}
+					}
+					
+					$core->setUserBlogPermissions($u,$b,$set_perms,true);
+				}
+			}
+		}
+		catch (Exception $e)
+		{
+			$core->error->add($e->getMessage());
+		}
+		if (!$core->error->flag()) {
+			http::redirect($redir.'&upd=1');
+		}
+	}
+}
+
+/* DISPLAY
+-------------------------------------------------------- */
+dcPage::open(
+	__('Users'),
+	dcPage::jsLoad('js/_users_actions.js').
+	# --BEHAVIOR-- adminUsersActionsHeaders
+	$core->callBehavior('adminUsersActionsHeaders')
+);
+
+if (!isset($action)) {
+	dcPage::close();
+	exit;
+}
+
+$hidden_fields = '';
+foreach($users as $u) {
+	$hidden_fields .= form::hidden(array('users[]'),$u);
+}
+
+if (isset($_POST['redir']) && strpos($_POST['redir'],'://') === false)
+{
+	$hidden_fields .= form::hidden(array('redir'),html::escapeURL($_POST['redir']));
+}
+else
+{
+	$hidden_fields .=
+	form::hidden(array('q'),html::escapeHTML($_POST['q'])).
+	form::hidden(array('sortby'),$_POST['sortby']).
+	form::hidden(array('order'),$_POST['order']).
+	form::hidden(array('page'),$_POST['page']).
+	form::hidden(array('nb'),$_POST['nb']);
+}
+
+# --BEHAVIOR-- adminUsersActionsContent
+$core->callBehavior('adminUsersActionsContent',$core,$action,$hidden_fields);
+
+# Blog list where to set permissions
+if (!empty($users) && empty($blogs) && $action == 'blogs')
+{
+	try {
+		$rs = $core->getBlogs();
+		$nb_blog = $rs->count();
+	} catch (Exception $e) { }
+	
+	foreach ($users as $u) {
+		$user_list[] = '<a href="user.php?id='.$u.'">'.$u.'</a>';
+	}
+	
+	echo 
+	'<h2><a href="users.php">'.__('Users').'</a> &rsaquo; <span class="page-title">'.__('Permissions').'</span></h2>'.
+	'<p>'.sprintf(
+		__('Choose one or more blogs to which you want to give permissions to users %s.'),
+		implode(', ',$user_list)
+	).'</p>';
+	
+	if ($nb_blog == 0)
+	{
+		echo '<p><strong>'.__('No blog').'</strong></p>';
+	}
+	else
+	{
+		echo
+		'<form action="users_actions.php" method="post" id="form-blogs">'.
+		'<table class="clear"><tr>'.
+		'<th class="nowrap" colspan="2">'.__('Blog ID').'</th>'.
+		'<th class="nowrap">'.__('Blog name').'</th>'.
+		'<th class="nowrap">'.__('Entries').'</th>'.
+		'<th class="nowrap">'.__('Status').'</th>'.
+		'</tr>';
+		
+		while ($rs->fetch())
+		{
+			$img_status = $rs->blog_status == 1 ? 'check-on' : 'check-off';
+			$txt_status = $core->getBlogStatus($rs->blog_status);
+			$img_status = sprintf('<img src="images/%1$s.png" alt="%2$s" title="%2$s" />',$img_status,$txt_status);
+			
+			echo
+			'<tr class="line">'.
+			'<td class="nowrap">'.
+			form::checkbox(array('blogs[]'),$rs->blog_id,'','','',false,'title="'.__('select').' '.$rs->blog_id.'"').'</td>'.
+			'<td class="nowrap">'.$rs->blog_id.'</td>'.
+			'<td class="maximal">'.html::escapeHTML($rs->blog_name).'</td>'.
+			'<td class="nowrap">'.$core->countBlogPosts($rs->blog_id).'</td>'.
+			'<td class="status">'.$img_status.'</td>'.
+			'</tr>';
+		}
+		
+		echo
+		'</table>'.
+		'<p class="checkboxes-helpers"></p>'.
+		'<p><input type="submit" value="'.__('Set permissions').'" />'.
+		$hidden_fields.
+		form::hidden(array('action'),'perms').
+		$core->formNonce().'</p>'.
+		'</form>';
+	}
+}
+# Permissions list for each selected blogs
+elseif (!empty($blogs) && !empty($users) && $action == 'perms')
+{
+	$user_perm = array();
+	if (count($users) == 1) {
+			$user_perm = $core->getUserPermissions($users[0]);	
+	}
+	
+	foreach ($users as $u) {
+		$user_list[] = '<a href="user.php?id='.$u.'">'.$u.'</a>';
+	}
+	
+	echo 
+	'<h2><a href="users.php">'.__('Users').'</a> &rsaquo; <span class="page-title">'.__('Permissions').'</span></h2>'.
+	'<p>'.sprintf(
+		__('You are about to change permissions on the following blogs for users %s.'),
+		implode(', ',$user_list)
+	).'</p>'.
+	'<form id="permissions-form" action="users_actions.php" method="post">';
+	
+	foreach ($blogs as $b)
+	{
+		echo '<h3><a href="blog.php?id='.html::escapeHTML($b).'">'.html::escapeHTML($b).'</a>'.
+		form::hidden(array('blogs[]'),$b).'</h3>';
+		
+		foreach ($core->auth->getPermissionsTypes() as $perm_id => $perm)
+		{
+			$checked = false;
+			
+			if (count($users) == 1) {
+				$checked = isset($user_perm[$b]['p'][$perm_id]) && $user_perm[$b]['p'][$perm_id];
+			}
+			
+			echo
+			'<p><label for="perm'.html::escapeHTML($b).html::escapeHTML($perm_id).'" class="classic">'.
+			form::checkbox(array('perm['.html::escapeHTML($b).']['.html::escapeHTML($perm_id).']','perm'.html::escapeHTML($b).html::escapeHTML($perm_id)),
+			1,$checked).' '.
+			__($perm).'</label></p>';
+		}
+	}
+	
+	echo
+	'<fieldset><legend>'.__('Validate permissions').'</legend>'.
+	'<p><label for="your_pwd">'.__('Your password:').
+	form::password('your_pwd',20,255).'</label></p>'.
+	'</fieldset>'.
+	'<p><input type="submit" accesskey="s" value="'.__('Save').'" />'.
+	$hidden_fields.
+	form::hidden(array('action'),'updateperm').
+	$core->formNonce().'</p>'.
+	'</form>';
+}
+
+echo '<p><a class="back" href="'.html::escapeURL($redir).'">'.__('back').'</a></p>';
+
+dcPage::close();
+?>

File inc/admin/lib.pager.php

 		return
 		'<tr class="line">'.
 		'<td class="nowrap">'.form::hidden(array('nb_post[]'),(integer) $this->rs->nb_post).
-		form::checkbox(array('user_id[]'),$this->rs->user_id).'</td>'.
+		form::checkbox(array('users[]'),$this->rs->user_id).'</td>'.
 		'<td class="maximal"><a href="user.php?id='.$this->rs->user_id.'">'.
 		$this->rs->user_id.'</a>&nbsp;'.$img_status.'</td>'.
 		'<td class="nowrap">'.$this->rs->user_firstname.'</td>'.