Fixed a bug in the Group Editor that didn't let you add groups to other groups unless your $_TABLES['groups'] happened to be called "groups" (bug #0000998)
3 /* Reminder: always indent with 4 spaces (no tabs). */
4 // +---------------------------------------------------------------------------+
6 // +---------------------------------------------------------------------------+
9 // | Geeklog group administration page. |
10 // +---------------------------------------------------------------------------+
11 // | Copyright (C) 2000-2009 by the following authors: |
13 // | Authors: Tony Bibbs - tony AT tonybibbs DOT com |
14 // | Mark Limburg - mlimburg AT users DOT sourceforge DOT net |
15 // | Jason Whittenburg - jwhitten AT securitygeeks DOT com |
16 // | Dirk Haun - dirk AT haun-online DOT de |
17 // +---------------------------------------------------------------------------+
19 // | This program is free software; you can redistribute it and/or |
20 // | modify it under the terms of the GNU General Public License |
21 // | as published by the Free Software Foundation; either version 2 |
22 // | of the License, or (at your option) any later version. |
24 // | This program is distributed in the hope that it will be useful, |
25 // | but WITHOUT ANY WARRANTY; without even the implied warranty of |
26 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
27 // | GNU General Public License for more details. |
29 // | You should have received a copy of the GNU General Public License |
30 // | along with this program; if not, write to the Free Software Foundation, |
31 // | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
33 // +---------------------------------------------------------------------------+
36 * This file is the Geeklog Group administration page
38 * @author Tony Bibbs, tony AT tonybibbs DOT com
43 * Geeklog common function library
45 require_once '../lib-common.php';
48 * Security check to ensure user even belongs on this page
50 require_once 'auth.inc.php';
52 // Uncomment the line below if you need to debug the HTTP variables being passed
53 // to the script. This will sometimes cause errors but it will allow you to see
54 // the data being passed in a POST operation
55 // echo COM_debug($_POST);
59 // Make sure user has rights to access this page
60 if (!SEC_hasRights('group.edit')) {
61 $display .= COM_siteHeader('menu', $MESSAGE[30])
62 . COM_showMessageText($MESSAGE[29], $MESSAGE[30])
64 COM_accessLog("User {$_USER['username']} tried to illegally access the group administration screen.");
70 * Shows the group editor form
72 * @param string $grp_id ID of group to edit
73 * @return string HTML for group editor
76 function editgroup($grp_id = '')
78 global $_TABLES, $_CONF, $_USER, $LANG_ACCESS, $LANG_ADMIN, $MESSAGE,
81 require_once $_CONF['path_system'] . 'lib-admin.php';
85 $thisUsersGroups = SEC_getUserGroups();
86 if (! empty($grp_id) &&
88 !in_array($grp_id, $thisUsersGroups) &&
89 !SEC_groupIsRemoteUserAndHaveAccess($grp_id, $thisUsersGroups)) {
90 $retval .= COM_startBlock($LANG_ACCESS['groupeditor'], '',
91 COM_getBlockTemplate('_msg_block', 'header'));
92 if (!SEC_inGroup('Root') && (DB_getItem($_TABLES['groups'],
93 'grp_name', "grp_id = $grp_id") == 'Root')) {
94 $retval .= $LANG_ACCESS['canteditroot'];
95 COM_accessLog("User {$_USER['username']} tried to edit the Root group with insufficient privileges.");
97 $retval .= $LANG_ACCESS['canteditgroup'];
99 $retval .= COM_endBlock(COM_getBlockTemplate('_msg_block', 'footer'));
104 $group_templates = new Template($_CONF['path_layout'] . 'admin/group');
105 $group_templates->set_file('editor', 'groupeditor.thtml');
106 $group_templates->set_var('site_url', $_CONF['site_url']);
107 $group_templates->set_var('site_admin_url', $_CONF['site_admin_url']);
108 $group_templates->set_var('layout_url', $_CONF['layout_url']);
109 $group_templates->set_var('lang_save', $LANG_ADMIN['save']);
110 $group_templates->set_var('lang_cancel', $LANG_ADMIN['cancel']);
111 $group_templates->set_var('lang_admingroup', $LANG28[49]);
112 $group_templates->set_var('lang_admingrp_msg', $LANG28[50]);
113 $group_templates->set_var('xhtml', XHTML);
115 if (isset($_REQUEST['chk_showall']) && ($_REQUEST['chk_showall'] == 1)) {
118 $group_templates->set_var('show_all', $showall);
120 if (! empty($grp_id)) {
121 $result = DB_query("SELECT grp_id,grp_name,grp_descr,grp_gl_core FROM {$_TABLES['groups']} WHERE grp_id ='$grp_id'");
122 $A = DB_fetchArray($result);
123 if ($A['grp_gl_core'] > 0) {
124 $group_templates->set_var('chk_adminuse', 'checked="checked"');
127 // new group, so it's obviously not a core group
128 $A['grp_gl_core'] = 0;
131 $token = SEC_createToken();
132 $retval .= COM_startBlock($LANG_ACCESS['groupeditor'], '',
133 COM_getBlockTemplate('_admin_block', 'header'));
134 $retval .= SEC_getTokenExpiryNotice($token);
136 if (! empty($grp_id)) {
137 // Groups tied to Geeklog's functionality shouldn't be deleted
138 if ($A['grp_gl_core'] != 1) {
139 $delbutton = '<input type="submit" value="' . $LANG_ADMIN['delete']
140 . '" name="mode"%s' . XHTML . '>';
141 $jsconfirm = ' onclick="return confirm(\'' . $MESSAGE[76] . '\');"';
142 $group_templates->set_var('delete_option',
143 sprintf($delbutton, $jsconfirm));
144 $group_templates->set_var('delete_option_no_confirmation',
145 sprintf($delbutton, ''));
146 $group_templates->set_var('group_core', 0);
148 $group_templates->set_var('group_core', 1);
150 $group_templates->set_var('group_id', $A['grp_id']);
152 $group_templates->set_var('group_core', 0);
155 $group_templates->set_var('lang_groupname', $LANG_ACCESS['groupname']);
157 if ($A['grp_gl_core'] != 1) {
158 $group_templates->set_var('groupname_inputtype', 'text');
159 $group_templates->set_var('groupname_static', '');
161 $group_templates->set_var('groupname_inputtype', 'hidden');
162 $group_templates->set_var('groupname_static', $A['grp_name']);
164 if (isset ($A['grp_name'])) {
165 $group_templates->set_var('group_name', $A['grp_name']);
167 $group_templates->set_var('group_name', '');
170 $group_templates->set_var('lang_description', $LANG_ACCESS['description']);
171 if (isset ($A['grp_descr'])) {
172 $group_templates->set_var('group_description', $A['grp_descr']);
174 $group_templates->set_var('group_description', '');
176 $group_templates->set_var('lang_securitygroups', $LANG_ACCESS['securitygroups']);
179 if (! empty($grp_id)) {
180 $tmp = DB_query("SELECT ug_main_grp_id FROM {$_TABLES['group_assignments']} WHERE ug_grp_id = $grp_id");
181 $num_groups = DB_numRows($tmp);
182 for ($x = 0; $x < $num_groups; $x++) {
183 $G = DB_fetchArray($tmp);
185 $selected .= ' ' . $G['ug_main_grp_id'];
187 $selected .= $G['ug_main_grp_id'];
193 if ($A['grp_gl_core'] == 1) {
194 $group_templates->set_var('lang_securitygroupmsg',
195 $LANG_ACCESS['coregroupmsg']);
196 $group_templates->set_var('hide_adminoption',
197 ' style="display:none;"');
200 if (! empty($selected)) {
201 $inclause = str_replace(' ', ',', $selected);
202 $result = DB_query("SELECT COUNT(*) AS count FROM {$_TABLES['groups']} WHERE grp_id <> $grp_id AND grp_id IN ($inclause)");
203 list($count) = DB_fetchArray($result);
206 // this group doesn't belong to anything...give a friendly message
207 $groupoptions = '<p class="pluginRow1">'
208 . $LANG_ACCESS['nogroupsforcoregroup'] . '</p>';
211 $group_templates->set_var('lang_securitygroupmsg',
212 $LANG_ACCESS['groupmsg']);
213 $group_templates->set_var('hide_adminoption', '');
216 COM_errorLog("SELECTED: $selected");
219 if (empty($groupoptions)) {
220 // make sure to list only those groups of which the Group Admin
222 $whereGroups = '(grp_id IN (' . implode (',', $thisUsersGroups) . '))';
225 array('text' => $LANG28[86], 'field' => ($A['grp_gl_core'] == 1 ? 'disabled-checkbox' : 'checkbox'), 'sort' => false),
226 array('text' => $LANG_ACCESS['groupname'], 'field' => 'grp_name', 'sort' => true),
227 array('text' => $LANG_ACCESS['description'], 'field' => 'grp_descr', 'sort' => true)
230 $defsort_arr = array('field' => 'grp_name', 'direction' => 'asc');
232 $form_url = $_CONF['site_admin_url']
233 . '/group.php?mode=edit&grp_id=' . $grp_id;
234 $text_arr = array('has_menu' => false,
235 'title' => '', 'instructions' => '',
236 'icon' => '', 'form_url' => $form_url,
239 if ($A['grp_gl_core'] == 1) {
240 $inclause = str_replace(' ', ',', $selected);
241 $sql = "SELECT grp_id, grp_name, grp_descr FROM {$_TABLES['groups']} WHERE grp_id <> $grp_id AND grp_id IN ($inclause)";
244 if (! empty($grp_id)) {
245 $xsql = " AND (grp_id <> $grp_id)";
247 $sql = "SELECT grp_id, grp_name, grp_descr FROM {$_TABLES['groups']} WHERE (grp_name <> 'Root')" . $xsql . ' AND ' . $whereGroups;
249 $query_arr = array('table' => 'groups',
251 'query_fields' => array('grp_name'),
252 'default_filter' => '',
256 $groupoptions = ADMIN_list('groups', 'ADMIN_getListField_groups',
257 $header_arr, $text_arr, $query_arr,
258 $defsort_arr, '', explode(' ', $selected));
260 $group_templates->set_var('group_options', $groupoptions);
261 $group_templates->set_var('lang_rights', $LANG_ACCESS['rights']);
263 if ($A['grp_gl_core'] == 1) {
264 $group_templates->set_var('lang_rightsmsg', $LANG_ACCESS['corerightsdescr']);
266 $group_templates->set_var('lang_rightsmsg', $LANG_ACCESS['rightsdescr']);
269 $group_templates->set_var('rights_options',
270 printrights($grp_id, $A['grp_gl_core']));
271 $group_templates->set_var('gltoken_name', CSRF_TOKEN);
272 $group_templates->set_var('gltoken', $token);
273 $group_templates->parse('output','editor');
274 $retval .= $group_templates->finish($group_templates->get_var('output'));
275 $retval .= COM_endBlock (COM_getBlockTemplate ('_admin_block', 'footer'));
282 * Get the indirect features for a group, i.e. a list of all the features
283 * that this group inherited from other groups.
285 * @param int $grp_id ID of group
286 * @return string comma-separated list of feature names
289 function getIndirectFeatures ($grp_id)
294 $tocheck = array ($grp_id);
297 $grp = array_pop ($tocheck);
299 $result = DB_query ("SELECT ug_main_grp_id FROM {$_TABLES['group_assignments']} WHERE ug_grp_id = $grp AND ug_uid IS NULL");
300 $numrows = DB_numRows ($result);
304 for ($j = 0; $j < $numrows; $j++) {
305 $A = DB_fetchArray ($result);
306 if (!in_array ($A['ug_main_grp_id'], $checked) &&
307 !in_array ($A['ug_main_grp_id'], $tocheck)) {
308 $tocheck[] = $A['ug_main_grp_id'];
312 while (count($tocheck) > 0);
314 // get features for all groups in $checked
315 $glist = join (',', $checked);
316 $result = DB_query("SELECT DISTINCT ft_name FROM {$_TABLES['access']},{$_TABLES['features']} WHERE ft_id = acc_ft_id AND acc_grp_id IN ($glist)");
317 $nrows = DB_numRows ($result);
320 for ($j = 1; $j <= $nrows; $j++) {
321 $A = DB_fetchArray ($result);
322 $retval .= $A['ft_name'];
332 * Prints the features a group has access. Please follow the comments in the
333 * code closely if you need to modify this function. Also right is synonymous
336 * @param mixed $grp_id ID to print rights for
337 * @param boolean $core indicates if group is a core Geeklog group
338 * @return string HTML for rights
341 function printrights($grp_id = '', $core = 0)
343 global $_TABLES, $_USER, $LANG_ACCESS, $VERBOSE;
346 // this gets a bit complicated so bear with the comments
348 // get a list of all the features that the current user (i.e. Group Admin)
349 // has access to, so we only include these features in the list below
350 if (!SEC_inGroup('Root')) {
351 $GroupAdminFeatures = SEC_getUserPermissions ();
352 $availableFeatures = explode (',', $GroupAdminFeatures);
353 $GroupAdminFeatures = "'" . implode ("','", $availableFeatures) . "'";
354 $ftWhere = ' WHERE ft_name IN (' . $GroupAdminFeatures . ')';
359 // now query for all available features
360 $features = DB_query ("SELECT ft_id,ft_name,ft_descr FROM {$_TABLES['features']}{$ftWhere} ORDER BY ft_name");
361 $nfeatures = DB_numRows($features);
363 $grpftarray = array ();
364 if (!empty($grp_id)) {
365 // now get all the feature this group gets directly
366 $directfeatures = DB_query("SELECT acc_ft_id,ft_name FROM {$_TABLES['access']},{$_TABLES['features']} WHERE ft_id = acc_ft_id AND acc_grp_id = $grp_id",1);
368 // now in many cases the features will be given to this user indirectly
369 // via membership to another group. These are not editable and must,
370 // instead, be removed from that group directly
371 $indirectfeatures = getIndirectFeatures ($grp_id);
372 $indirectfeatures = explode (',', $indirectfeatures);
374 // Build an array of indirect features
375 for ($i = 0; $i < count($indirectfeatures); $i++) {
376 $grpftarray[current($indirectfeatures)] = 'indirect';
377 next($indirectfeatures);
380 // Build an arrray of direct features
381 $grpftarray1 = array ();
382 $ndirect = DB_numRows($directfeatures);
383 for ($i = 0; $i < $ndirect; $i++) {
384 $A = DB_fetchArray($directfeatures);
385 $grpftarray1[$A['ft_name']] = 'direct';
388 // Now merge the two arrays
389 $grpftarray = array_merge ($grpftarray, $grpftarray1);
391 // this is for debugging purposes
392 for ($i = 1; $i < count($grpftarray); $i++) {
393 COM_errorLog("element $i is feature " . key($grpftarray) . " and is " . current($grpftarray),1);
399 // OK, now loop through and print all the features giving edit rights
400 // to only the ones that are direct features
403 for ($i = 0; $i < $nfeatures; $i++) {
404 $A = DB_fetchArray($features);
406 if ((empty($grpftarray[$A['ft_name']]) OR ($grpftarray[$A['ft_name']] == 'direct')) AND ($core != 1)) {
407 if (($ftcount > 0) && ($ftcount % 3 == 0)) {
408 $retval .= '</tr>' . LB . '<tr>';
410 $pluginRow = sprintf('pluginRow%d', ($ftcount % 2) + 1);
413 $retval .= '<td class="' . $pluginRow . '">'
414 . '<input type="checkbox" name="features[]" value="'
416 if (!empty($grpftarray[$A['ft_name']])) {
417 if ($grpftarray[$A['ft_name']] == 'direct') {
418 $retval .= ' checked="checked"';
421 $retval .= XHTML . '><span title="' . $A['ft_descr'] . '">'
422 . $A['ft_name'] . '</span></td>';
424 // either this is an indirect right OR this is a core feature
425 if ((($core == 1) AND (isset($grpftarray[$A['ft_name']]) AND (($grpftarray[$A['ft_name']] == 'indirect') OR ($grpftarray[$A['ft_name']] == 'direct')))) OR ($core != 1)) {
426 if (($ftcount > 0) && ($ftcount % 3 == 0)) {
427 $retval .= '</tr>' . LB . '<tr>';
429 $pluginRow = sprintf('pluginRow%d', ($ftcount % 2) + 1);
432 $retval .= '<td class="' . $pluginRow . '">'
433 . '<input type="checkbox" checked="checked" '
434 . 'disabled="disabled"' . XHTML . '>'
435 . '<input type="hidden" name="features[]" value="'
436 . $A['ft_id'] . '"' . XHTML . '>'
437 . '(<i title="' . $A['ft_descr'] . '">' . $A['ft_name']
443 // This group doesn't have rights to any features
444 $retval .= '<td colspan="3" class="pluginRow1">'
445 . $LANG_ACCESS['grouphasnorights'] . '</td>';
448 $retval .= '</tr>' . LB;
454 * Save a group to the database
456 * @param string $grp_id ID of group to save
457 * @param string $grp_name Group Name
458 * @param string $grp_descr Description of group
459 * @param boolean $grp_admin Flag that indicates this is an admin use group
460 * @param boolean $grp_gl_core Flag that indicates if this is a core Geeklog group
461 * @param array $features Features the group has access to
462 * @param array $groups Groups this group will belong to
463 * @return string HTML refresh or error message
466 function savegroup($grp_id, $grp_name, $grp_descr, $grp_admin, $grp_gl_core, $features, $groups)
468 global $_CONF, $_TABLES, $_USER, $LANG_ACCESS, $VERBOSE;
471 if (!empty($grp_name) && !empty($grp_descr)) {
472 $GroupAdminGroups = SEC_getUserGroups();
473 if (!empty ($grp_id) &&
475 !in_array ($grp_id, $GroupAdminGroups) &&
476 !SEC_groupIsRemoteUserAndHaveAccess($grp_id, $GroupAdminGroups)) {
477 COM_accessLog ("User {$_USER['username']} tried to edit group '$grp_name' ($grp_id) with insufficient privileges.");
479 return COM_refresh ($_CONF['site_admin_url'] . '/group.php');
482 if ($grp_gl_core == 1 AND !is_array ($features)) {
483 COM_errorLog ("Sorry, no valid features were passed to this core group ($grp_id) and saving could cause problem...bailing.");
485 return COM_refresh ($_CONF['site_admin_url'] . '/group.php');
488 // group names have to be unique, so check if this one exists already
489 $g_id = DB_getItem ($_TABLES['groups'], 'grp_id',
490 "grp_name = '$grp_name'");
492 if (empty ($grp_id) || ($grp_id != $g_id)) {
493 // there already is a group with that name - complain
494 $retval .= COM_siteHeader ('menu', $LANG_ACCESS['groupeditor']);
495 $retval .= COM_startBlock ($LANG_ACCESS['groupexists'], '',
496 COM_getBlockTemplate ('_msg_block', 'header'));
497 $retval .= $LANG_ACCESS['groupexistsmsg'];
498 $retval .= COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'));
499 $retval .= editgroup ($grp_id);
500 $retval .= COM_siteFooter ();
506 $grp_descr = COM_stripslashes ($grp_descr);
507 $grp_descr = addslashes ($grp_descr);
509 if (empty ($grp_id)) {
510 DB_save ($_TABLES['groups'], 'grp_name,grp_descr,grp_gl_core',
511 "'$grp_name','$grp_descr',$grp_gl_core");
512 $grp_id = DB_getItem ($_TABLES['groups'], 'grp_id',
513 "grp_name = '$grp_name'");
516 DB_save ($_TABLES['groups'],
517 'grp_id,grp_name,grp_descr,grp_gl_core',
518 "$grp_id,'$grp_name','$grp_descr',$grp_gl_core");
522 if (empty($grp_id) || ($grp_id < 1)) {
523 // "this shouldn't happen"
524 COM_errorLog("Internal error: invalid group id");
525 $retval .= COM_siteHeader('menu', $LANG_ACCESS['groupeditor']);
526 $retval .= COM_showMessage(95);
527 $retval .= COM_siteFooter();
532 // Use the field grp_gl_core to indicate if this is non-core GL Group is an Admin related group
533 if (($grp_gl_core != 1) AND ($grp_id > 1)) {
534 if ($grp_admin == 1) {
535 DB_query("UPDATE {$_TABLES['groups']} SET grp_gl_core=2 WHERE grp_id=$grp_id");
537 DB_query("UPDATE {$_TABLES['groups']} SET grp_gl_core=0 WHERE grp_id=$grp_id");
541 // now save the features
542 DB_delete($_TABLES['access'], 'acc_grp_id', $grp_id);
543 $num_features = count($features);
544 if (SEC_inGroup('Root')) {
545 foreach ($features as $f) {
546 DB_query ("INSERT INTO {$_TABLES['access']} (acc_ft_id,acc_grp_id) VALUES ($f,$grp_id)");
549 $GroupAdminFeatures = SEC_getUserPermissions();
550 $availableFeatures = explode(',', $GroupAdminFeatures);
551 foreach ($features as $f) {
552 if (in_array($f, $availableFeatures)) {
553 DB_query("INSERT INTO {$_TABLES['access']} (acc_ft_id,acc_grp_id) VALUES ($f,$grp_id)");
558 COM_errorLog('groups = ' . $groups);
559 COM_errorLog("deleting all group_assignments for group $grp_id/$grp_name",1);
562 DB_delete($_TABLES['group_assignments'], 'ug_grp_id', $grp_id);
563 if (! empty($groups)) {
564 foreach ($groups as $g) {
565 if (in_array($g, $GroupAdminGroups)) {
566 if ($VERBOSE) COM_errorLog("adding group_assignment $g for $grp_name",1);
567 $sql = "INSERT INTO {$_TABLES['group_assignments']} (ug_main_grp_id, ug_grp_id) VALUES ($g,$grp_id)";
573 // Make sure Root group belongs to any new group
574 if (DB_getItem ($_TABLES['group_assignments'], 'COUNT(*)',
575 "ug_main_grp_id = $grp_id AND ug_grp_id = 1") == 0) {
576 DB_query("INSERT INTO {$_TABLES['group_assignments']} (ug_main_grp_id, ug_grp_id) VALUES ($grp_id, 1)");
579 // make sure this Group Admin belongs to the new group
580 if (!SEC_inGroup ('Root')) {
581 if (DB_count ($_TABLES['group_assignments'], 'ug_uid',
582 "(ug_uid = {$_USER['uid']}) AND (ug_main_grp_id = $grp_id)") == 0) {
583 DB_query ("INSERT INTO {$_TABLES['group_assignments']} (ug_main_grp_id, ug_uid) VALUES ($grp_id,{$_USER['uid']})");
588 PLG_groupChanged ($grp_id, 'new');
590 PLG_groupChanged ($grp_id, 'edit');
592 if (isset($_REQUEST['chk_showall']) && ($_REQUEST['chk_showall'] == 1)) {
593 echo COM_refresh($_CONF['site_admin_url'] . '/group.php?msg=49&chk_showall=1');
595 echo COM_refresh($_CONF['site_admin_url'] . '/group.php?msg=49');
598 $retval .= COM_siteHeader ('menu', $LANG_ACCESS['groupeditor']);
599 $retval .= COM_startBlock ($LANG_ACCESS['missingfields'], '',
600 COM_getBlockTemplate ('_msg_block', 'header'));
601 $retval .= $LANG_ACCESS['missingfieldsmsg'];
602 $retval .= COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'));
603 $retval .= editgroup ($grp_id);
604 $retval .= COM_siteFooter ();
611 * Get a list (actually an array) of all groups this group belongs to.
613 * @param int $basegroup id of group
614 * @return array array of all groups $basegroup belongs to
617 function getGroupList($basegroup)
621 $to_check = array ();
622 array_push ($to_check, $basegroup);
626 while (count($to_check) > 0) {
627 $thisgroup = array_pop ($to_check);
628 if ($thisgroup > 0) {
629 $result = DB_query ("SELECT ug_grp_id FROM {$_TABLES['group_assignments']} WHERE ug_main_grp_id = $thisgroup");
630 $numGroups = DB_numRows ($result);
631 for ($i = 0; $i < $numGroups; $i++) {
632 $A = DB_fetchArray ($result);
633 if (!in_array ($A['ug_grp_id'], $checked)) {
634 if (!in_array ($A['ug_grp_id'], $to_check)) {
635 array_push ($to_check, $A['ug_grp_id']);
639 $checked[] = $thisgroup;
647 * Display a list of all users in a given group.
649 * @param int $grp_id group id
650 * @return string HTML for user listing
653 function listusers ($grp_id)
655 global $_CONF, $_TABLES, $LANG28, $LANG_ACCESS, $LANG_ADMIN, $_IMAGE_TYPE;
657 require_once $_CONF['path_system'] . 'lib-admin.php';
661 $thisUsersGroups = SEC_getUserGroups ();
662 if (!empty ($grp_id) &&
664 !in_array ($grp_id, $thisUsersGroups) &&
665 !SEC_groupIsRemoteUserAndHaveAccess( $grp_id, $thisUsersGroups)) {
666 $retval .= COM_startBlock ($LANG_ACCESS['usergroupadmin'], '',
667 COM_getBlockTemplate ('_msg_block', 'header'));
668 $retval .= $LANG_ACCESS['cantlistgroup'];
669 $retval .= COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'));
674 if ($_CONF['lastlogin']) {
675 $login_text = $LANG28[41];
676 $login_field = 'lastlogin';
678 $login_text = $LANG28[40];
679 $login_field = 'regdate';
682 $header_arr = array (
683 array('text' => $LANG_ADMIN['edit'], 'field' => 'edit', 'sort' => false),
684 array('text' => $LANG28[37], 'field' => 'uid', 'sort' => true),
685 array('text' => $LANG28[3], 'field' => 'username', 'sort' => true),
686 array('text' => $LANG28[4], 'field' => 'fullname', 'sort' => true),
687 array('text' => $login_text, 'field' => $login_field, 'sort' => true),
688 array('text' => $LANG28[7], 'field' => 'email', 'sort' => true)
691 $defsort_arr = array ('field' => 'username',
695 $form_url = $_CONF['site_admin_url'] . '/group.php?mode=listusers&grp_id='.$grp_id;
696 if (isset($_REQUEST['chk_showall']) && ($_REQUEST['chk_showall'] == 1)) {
697 $form_url .= '&chk_showall=1';
700 $groupname = DB_getItem ($_TABLES['groups'], 'grp_name',
701 "grp_id = '$grp_id'");
702 $headline = sprintf ($LANG_ACCESS['usersingroup'], $groupname);
704 $url = $_CONF['site_admin_url'] . '/group.php';
705 if (isset($_REQUEST['chk_showall']) && ($_REQUEST['chk_showall'] == 1)) {
706 $url .= '?chk_showall=1';
710 'text' => $LANG28[38]),
711 array('url' => $_CONF['site_admin_url'],
712 'text' => $LANG_ADMIN['admin_home']));
714 $retval .= COM_startBlock($headline, '',
715 COM_getBlockTemplate('_admin_block', 'header'));
717 $retval .= ADMIN_createMenu(
720 $_CONF['layout_url'] . '/images/icons/group.' . $_IMAGE_TYPE
724 'has_extras' => true,
725 'form_url' => $form_url,
730 $select_userinfo = '';
731 if ($_CONF['lastlogin']) {
732 $join_userinfo = "LEFT JOIN {$_TABLES['userinfo']} ON {$_TABLES['users']}.uid={$_TABLES['userinfo']}.uid ";
733 $select_userinfo = ",lastlogin ";
736 $groups = getGroupList ($grp_id);
737 $groupList = implode (',', $groups);
739 $sql = "SELECT DISTINCT {$_TABLES['users']}.uid,username,fullname,email,photo,regdate$select_userinfo "
740 ."FROM {$_TABLES['group_assignments']},{$_TABLES['users']} $join_userinfo "
741 ."WHERE {$_TABLES['users']}.uid > 1 "
742 ."AND {$_TABLES['users']}.uid = {$_TABLES['group_assignments']}.ug_uid "
743 ."AND ({$_TABLES['group_assignments']}.ug_main_grp_id IN ({$groupList}))";
745 $query_arr = array ('table' => 'users',
747 'query_fields' => array('username', 'email', 'fullname'),
748 'default_filter' => "AND {$_TABLES['users']}.uid > 1"
751 $retval .= ADMIN_list('user', 'ADMIN_getListField_users', $header_arr,
752 $text_arr, $query_arr, $defsort_arr);
753 $retval .= COM_endBlock(COM_getBlockTemplate('_admin_block', 'footer'));
759 * Display a list of (all) groups
761 * @param boolean $show_all_groups include admin groups if true
762 * @return string HTML of the group list
765 function listgroups($show_all_groups = false)
767 global $_CONF, $_TABLES, $LANG_ADMIN, $LANG_ACCESS, $LANG28, $_IMAGE_TYPE;
769 require_once $_CONF['path_system'] . 'lib-admin.php';
773 $header_arr = array( // display 'text' and use table field 'field'
774 array('text' => $LANG_ADMIN['edit'], 'field' => 'edit', 'sort' => false),
775 array('text' => $LANG_ACCESS['groupname'], 'field' => 'grp_name', 'sort' => true),
776 array('text' => $LANG_ACCESS['description'], 'field' => 'grp_descr', 'sort' => true),
777 array('text' => $LANG_ACCESS['coregroup'], 'field' => 'grp_gl_core', 'sort' => true),
778 array('text' => $LANG_ACCESS['listusers'], 'field' => 'list', 'sort' => false)
781 $defsort_arr = array('field' => 'grp_name', 'direction' => 'asc');
783 $form_url = $_CONF['site_admin_url'] . '/group.php';
784 if ($show_all_groups) {
785 $form_url .= '?chk_showall=1';
789 array('url' => $_CONF['site_admin_url'] . '/group.php?mode=edit',
790 'text' => $LANG_ADMIN['create_new']),
791 array('url' => $_CONF['site_admin_url'],
792 'text' => $LANG_ADMIN['admin_home'])
795 $retval .= COM_startBlock($LANG_ACCESS['groupmanager'], '',
796 COM_getBlockTemplate('_admin_block', 'header'));
798 $retval .= ADMIN_createMenu(
800 $LANG_ACCESS['newgroupmsg'],
801 $_CONF['layout_url'] . '/images/icons/group.' . $_IMAGE_TYPE
805 'has_extras' => true,
806 'form_url' => $form_url
809 $filter = '<span style="padding-right:20px;">';
812 if ($show_all_groups) {
813 $checked = ' checked="checked"';
816 if (SEC_inGroup('Root')) {
819 $thisUsersGroups = SEC_getUserGroups ();
820 $grpFilter = 'AND (grp_id IN (' . implode (',', $thisUsersGroups) . '))';
823 if ($show_all_groups) {
824 $filter .= '<label for="chk_showall"><input id="chk_showall" type="checkbox" name="chk_showall" value="1" checked="checked"' . XHTML . '>';
827 'sql' => "SELECT * FROM {$_TABLES['groups']} WHERE 1=1",
828 'query_fields' => array('grp_name', 'grp_descr'),
829 'default_filter' => $grpFilter);
831 $filter .= '<label for="chk_showall"><input id="chk_showall" type="checkbox" name="chk_showall" value="1"' . $checked . XHTML . '>';
834 'sql' => "SELECT * FROM {$_TABLES['groups']} WHERE (grp_gl_core = 0 OR grp_name IN ('All Users','Logged-in Users'))",
835 'query_fields' => array('grp_name', 'grp_descr'),
836 'default_filter' => $grpFilter);
838 $filter .= $LANG28[48] . '</label></span>';
840 $retval .= ADMIN_list('groups', 'ADMIN_getListField_groups', $header_arr,
841 $text_arr, $query_arr, $defsort_arr, $filter);
842 $retval .= COM_endBlock(COM_getBlockTemplate('_admin_block', 'footer'));
848 * Get list of users in a given group
850 * Effectively, this function is used twice: To get a list of all users currently
851 * in the given group and to get all list of all users NOT in that group.
853 * @param int $group_id group id
854 * @param boolean $allusers true: return users not in the group
855 * @return string option list containing uids and user names
858 function grp_selectUsers($group_id, $allusers = false)
860 global $_TABLES, $_USER;
864 // Get a list of users in the Root Group and the selected group
865 $sql = "SELECT DISTINCT uid FROM {$_TABLES['users']} LEFT JOIN {$_TABLES['group_assignments']} ";
866 $sql .= "ON {$_TABLES['group_assignments']}.ug_uid = uid WHERE uid > 1 AND ";
867 $sql .= "({$_TABLES['group_assignments']}.ug_main_grp_id = 1 OR {$_TABLES['group_assignments']}.ug_main_grp_id = $group_id)";
868 $result = DB_query ($sql);
869 $filteredusers = array();
870 while ($A = DB_fetchArray($result)) {
871 $filteredusers[] = $A['uid'];
874 $groups = getGroupList ($group_id);
875 $grouplist = '(' . implode (',', $groups) . ')';
876 $sql = "SELECT DISTINCT uid,username FROM {$_TABLES['users']} LEFT JOIN {$_TABLES['group_assignments']} ";
877 $sql .= "ON {$_TABLES['group_assignments']}.ug_uid = uid WHERE uid > 1 AND ";
878 $sql .= "{$_TABLES['group_assignments']}.ug_main_grp_id ";
882 $sql .= "IN {$grouplist} ";
883 // Filter out the users that will be in the selected group
885 $filteredusers = implode(',',$filteredusers);
886 $sql .= " AND uid NOT IN ($filteredusers) ";
888 $sql .= "ORDER BY username";
889 $result = DB_query ($sql);
890 $numUsers = DB_numRows ($result);
891 for ($i = 0; $i < $numUsers; $i++) {
892 list($uid, $username) = DB_fetchArray ($result);
893 $retval .= '<option value="' . $uid . '">' . $username . '</option>';
900 * Allow easy addition/removal of users to/from a group
902 * @param int $group Group ID
903 * @return string HTML form
906 function editusers($group)
908 global $_CONF, $_TABLES, $_USER, $LANG_ACCESS, $LANG_ADMIN, $LANG28,
911 require_once $_CONF['path_system'] . 'lib-admin.php';
915 $grp_name = DB_getItem($_TABLES['groups'], 'grp_name', "grp_id = $group");
917 $thisUsersGroups = SEC_getUserGroups();
918 $groupName = DB_getItem($_TABLES['groups'], 'grp_name', "grp_id='$group'");
919 if ((!empty($group) && ($group > 0) &&
920 !in_array($group, $thisUsersGroups) &&
921 !SEC_groupIsRemoteUserAndHaveAccess($group, $thisUsersGroups))
922 || (($grp_name == 'All Users') ||
923 ($grp_name == 'Logged-in Users'))) {
924 $retval .= COM_startBlock($LANG_ACCESS['usergroupadmin'], '',
925 COM_getBlockTemplate('_msg_block', 'header'));
926 if (!SEC_inGroup('Root') && ($grp_name == 'Root')) {
927 $retval .= $LANG_ACCESS['canteditroot'];
928 COM_accessLog("User {$_USER['username']} tried to edit the Root group with insufficient privileges.");
930 $retval .= $LANG_ACCESS['canteditgroup'];
932 $retval .= COM_endBlock(COM_getBlockTemplate('_msg_block', 'footer'));
937 $group_listing_url = $_CONF['site_admin_url'] . '/group.php';
939 if (isset($_REQUEST['chk_showall']) && ($_REQUEST['chk_showall'] == 1)) {
940 $group_listing_url .= '?chk_showall=1';
945 array('url' => $group_listing_url,
946 'text' => $LANG28[38]),
947 array('url' => $_CONF['site_admin_url'],
948 'text' => $LANG_ADMIN['admin_home'])
951 $retval .= COM_startBlock($LANG_ACCESS['usergroupadmin'] . " - $groupName",
952 '', COM_getBlockTemplate('_admin_block', 'header'));
954 $retval .= ADMIN_createMenu($menu_arr, $LANG_ACCESS['editgroupmsg'],
955 $_CONF['layout_url'] . '/images/icons/group.' . $_IMAGE_TYPE);
957 $groupmembers = new Template($_CONF['path_layout'] . 'admin/group');
958 $groupmembers->set_file(array('groupmembers'=>'groupmembers.thtml'));
959 $groupmembers->set_var('site_url', $_CONF['site_url']);
960 $groupmembers->set_var('site_admin_url', $_CONF['site_admin_url']);
961 $groupmembers->set_var('group_listing_url', $group_listing_url);
962 $groupmembers->set_var('layout_url', $_CONF['layout_url']);
963 $groupmembers->set_var('phpself', $_CONF['site_admin_url'] . '/group.php');
964 $groupmembers->set_var('lang_adminhome', $LANG_ACCESS['adminhome']);
965 $groupmembers->set_var('lang_instructions', $LANG_ACCESS['editgroupmsg']);
966 $groupmembers->set_var('LANG_sitemembers',$LANG_ACCESS['availmembers']);
967 $groupmembers->set_var('LANG_grpmembers',$LANG_ACCESS['groupmembers']);
968 $groupmembers->set_var('sitemembers', grp_selectUsers($group, true));
969 $groupmembers->set_var('group_list', grp_selectUsers($group));
970 $groupmembers->set_var('LANG_add',$LANG_ACCESS['add']);
971 $groupmembers->set_var('LANG_remove',$LANG_ACCESS['remove']);
972 $groupmembers->set_var('lang_save', $LANG_ADMIN['save']);
973 $groupmembers->set_var('lang_cancel', $LANG_ADMIN['cancel']);
974 $groupmembers->set_var('lang_grouplist', $LANG28[38]);
975 $groupmembers->set_var('show_all', $showall);
976 $groupmembers->set_var('group_id',$group);
977 $groupmembers->set_var('xhtml', XHTML);
978 $groupmembers->set_var('gltoken_name', CSRF_TOKEN);
979 $groupmembers->set_var('gltoken', SEC_createToken());
980 $groupmembers->parse('output', 'groupmembers');
981 $retval .= $groupmembers->finish($groupmembers->get_var('output'));
983 $retval .= COM_endBlock(COM_getBlockTemplate('_admin_block', 'footer'));
989 * Save changes from the form to add/remove users to/from groups
991 * @param int $groupid id of the group being changed
992 * @param string $groupmembers list of group members
993 * @return string HTML redirect
996 function savegroupusers($groupid, $groupmembers)
998 global $_CONF, $_TABLES;
1002 // Delete all the current buddy records for this user and add all the selected ones
1003 $sql = "DELETE FROM {$_TABLES['group_assignments']} WHERE ug_main_grp_id={$groupid} AND ug_uid IS NOT NULL";
1005 $adduser = explode('|', $groupmembers);
1006 for ($i = 0; $i < count($adduser); $i++) {
1007 $adduser[$i] = COM_applyFilter($adduser[$i], true);
1008 DB_query("INSERT INTO {$_TABLES['group_assignments']} (ug_main_grp_id, ug_uid) VALUES ('$groupid', '$adduser[$i]')");
1011 if (isset($_REQUEST['chk_showall']) && ($_REQUEST['chk_showall'] == 1)) {
1012 $retval = COM_refresh($_CONF['site_admin_url'] . '/group.php?msg=49&chk_showall=1');
1014 $retval = COM_refresh($_CONF['site_admin_url'] . '/group.php?msg=49');
1023 * @param int $grp_id id of group to delete
1024 * @return string HTML redirect
1027 function deleteGroup ($grp_id)
1029 global $_CONF, $_TABLES, $_USER;
1031 if (!SEC_inGroup ('Root') && (DB_getItem ($_TABLES['groups'], 'grp_name',
1032 "grp_id = $grp_id") == 'Root')) {
1033 COM_accessLog ("User {$_USER['username']} tried to delete the Root group with insufficient privileges.");
1035 return COM_refresh ($_CONF['site_admin_url'] . '/group.php');
1038 $GroupAdminGroups = SEC_getUserGroups ();
1039 if (!in_array ($grp_id, $GroupAdminGroups) && !SEC_groupIsRemoteUserAndHaveAccess($grp_id, $GroupAdminGroups)) {
1040 COM_accessLog ("User {$_USER['username']} tried to delete group $grp_id with insufficient privileges.");
1042 return COM_refresh ($_CONF['site_admin_url'] . '/group.php');
1045 DB_delete ($_TABLES['access'], 'acc_grp_id', $grp_id);
1046 DB_delete ($_TABLES['group_assignments'], 'ug_grp_id', $grp_id);
1047 DB_delete ($_TABLES['group_assignments'], 'ug_main_grp_id', $grp_id);
1048 DB_delete ($_TABLES['groups'], 'grp_id', $grp_id);
1050 PLG_groupChanged ($grp_id, 'delete');
1051 if (isset($_REQUEST['chk_showall']) && ($_REQUEST['chk_showall'] == 1)) {
1052 return COM_refresh($_CONF['site_admin_url'] . '/group.php?msg=50&chk_showall=1');
1054 return COM_refresh($_CONF['site_admin_url'] . '/group.php?msg=50');
1060 if (isset($_REQUEST['mode'])) {
1061 $mode = $_REQUEST['mode'];
1064 if (($mode == $LANG_ADMIN['delete']) && !empty ($LANG_ADMIN['delete'])) {
1065 $grp_id = COM_applyFilter ($_REQUEST['grp_id'], true);
1066 if (!isset ($grp_id) || empty ($grp_id) || ($grp_id == 0)) {
1067 COM_errorLog ('Attempted to delete group grp_id=' . $grp_id);
1068 $display .= COM_refresh ($_CONF['site_admin_url'] . '/group.php');
1069 } elseif (SEC_checkToken()) {
1070 $display .= deleteGroup ($grp_id);
1072 COM_accessLog("User {$_USER['username']} tried to illegally delete group $grp_id and failed CSRF checks.");
1073 echo COM_refresh($_CONF['site_admin_url'] . '/index.php');
1075 } elseif (($mode == $LANG_ADMIN['save']) && !empty($LANG_ADMIN['save']) && SEC_checkToken()) {
1076 $grp_gl_core = COM_applyFilter($_POST['grp_gl_core'], true);
1078 if (isset($_POST['chk_grpadmin'])) {
1079 $chk_grpadmin = COM_applyFilter($_POST['chk_grpadmin']);
1081 $features = array();
1082 if (isset($_POST['features'])) {
1083 $features = $_POST['features'];
1086 if (isset($_POST['groups'])) {
1087 $groups = $_POST['groups'];
1089 $display .= savegroup(COM_applyFilter($_POST['grp_id'], true),
1090 COM_applyFilter($_POST['grp_name']),
1091 $_POST['grp_descr'], $chk_grpadmin, $grp_gl_core,
1092 $features, $groups);
1093 } elseif (($mode == 'savegroupusers') && SEC_checkToken()) {
1094 $grp_id = COM_applyFilter($_REQUEST['grp_id'], true);
1095 $display .= savegroupusers($grp_id, $_POST['groupmembers']);
1096 } elseif ($mode == 'edit') {
1098 if (isset ($_REQUEST['grp_id'])) {
1099 $grp_id = COM_applyFilter ($_REQUEST['grp_id'], true);
1101 $display .= COM_siteHeader ('menu', $LANG_ACCESS['groupeditor']);
1102 $display .= editgroup ($grp_id);
1103 $display .= COM_siteFooter ();
1104 } elseif ($mode == 'listusers') {
1105 $grp_id = COM_applyFilter ($_REQUEST['grp_id'], true);
1106 $display .= COM_siteHeader ('menu', $LANG_ACCESS['groupmembers']);
1107 $display .= listusers ($grp_id);
1108 $display .= COM_siteFooter ();
1109 } elseif ($mode == 'editusers') {
1110 $grp_id = COM_applyFilter ($_REQUEST['grp_id'], true);
1111 $display .= COM_siteHeader ('menu', $LANG_ACCESS['usergroupadmin']);
1112 $display .= editusers ($grp_id);
1113 $display .= COM_siteFooter ();
1114 } else { // 'cancel' or no mode at all
1115 $show_all_groups = false;
1116 if (isset($_POST['q'])) {
1117 // check $_POST only, as $_GET['chk_showall'] may also be set
1118 if (isset($_POST['chk_showall']) && ($_POST['chk_showall'] == 1)) {
1119 $show_all_groups = true;
1121 } elseif (isset($_REQUEST['chk_showall']) &&
1122 ($_REQUEST['chk_showall'] == 1)) {
1123 $show_all_groups = true;
1125 $display .= COM_siteHeader('menu', $LANG28[38]);
1126 $display .= COM_showMessageFromParameter();
1127 $display .= listgroups($show_all_groups);
1128 $display .= COM_siteFooter();
1131 COM_output($display);