From fac78dd27fd3690d2744994a972366f2b0737690 Mon Sep 17 00:00:00 2001 From: "Paul S. Owen" Date: Tue, 3 Feb 2004 02:26:58 +0000 Subject: [PATCH] Further group work ... nearly there ... still some consistency and other issues. git-svn-id: file:///svn/phpbb/trunk@4780 89ea8834-ac86-4346-8a33-228a782c2dd0 --- phpBB/adm/admin_groups.php | 286 +++++--- phpBB/includes/functions_user.php | 1030 +++++++++++++++-------------- 2 files changed, 736 insertions(+), 580 deletions(-) diff --git a/phpBB/adm/admin_groups.php b/phpBB/adm/admin_groups.php index f88cf83537..ad53feff0a 100644 --- a/phpBB/adm/admin_groups.php +++ b/phpBB/adm/admin_groups.php @@ -12,9 +12,7 @@ // ------------------------------------------------------------- // TODO -// Remove hard-coded text strings -// Hidden/Normal type for "Special Groups" -// Group avatar handling ... +// Avatar gallery ... // Mass user pref setting via group membership if (!empty($setmodules)) @@ -43,18 +41,22 @@ if (!$auth->acl_get('a_group')) } // Check and set some common vars -$update = (isset($_POST['update'])) ? true : false; $mode = request_var('mode', ''); $action = (isset($_POST['add'])) ? 'add' : ((isset($_POST['addusers'])) ? 'addusers' : request_var('action', '')); $group_id = request_var('g', 0); $mark_ary = request_var('mark', 0); $name_ary = request_var('usernames', ''); $leader = request_var('leader', 0); +$default = request_var('default', 0); $start = request_var('start', 0); +$update = (isset($_POST['update'])) ? true : false; +$confirm = (isset($_POST['confirm'])) ? true : false; +$cancel = (isset($_POST['cancel'])) ? true : false; // Clear some vars +$can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && is_writeable($phpbb_root_path . $config['avatar_path']) && $file_uploads) ? true : false; + $group_type = $group_name = $group_desc = $group_colour = $group_rank = $group_avatar = false; -$can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && is_writeable($phpbb_root_path . $config['avatar_path']) && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false; // Grab basic data for group, if group_id is set and exists if ($group_id) @@ -77,42 +79,37 @@ switch ($mode) // Page header adm_page_header($user->lang['MANAGE']); + // Common javascript +?> + + + +lang['NO_GROUP']); - } - - approve_user($group_id, $mark_ary, false, $group_name); - trigger_error($user->lang['USERS_APPROVED']); - break; - - case 'default': - if (!$group_id) - { - trigger_error($user->lang['NO_GROUP']); - } - - set_default_group($group_id, $mark_ary, false, $group_name, $group_colour, $group_rank, false, false); - trigger_error($user->lang['GROUP_DEFS_UPDATED']); - break; - case 'demote': case 'promote': - case 'deleteusers': - case 'delete': if (!$group_id) { trigger_error($user->lang['NO_GROUP']); } - if ($error = group_memberships($action, $group_id, $mark_ary, false, $group_name)) - { - trigger_error($user->lang[$error]); - } + group_user_attributes($action, $group_id, $mark_ary, false, $group_name); switch ($action) { @@ -122,16 +119,94 @@ switch ($mode) case 'promote': $message = 'GROUP_MODS_PROMOTED'; break; - case 'delete': - $message = 'GROUP_DELETED'; - break; - case 'deleteusers': - $message = 'GROUP_USERS_REMOVE'; + case 'approve': + $message = 'USERS_APPROVED'; break; } trigger_error($user->lang[$message]); break; + case 'default': + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP']); + } + + if (!$mark_ary) + { + $start = 0; + do + { + $sql = 'SELECT user_id + FROM ' . USER_GROUP_TABLE . " + WHERE group_id = $group_id + ORDER BY user_id + LIMIT $start, 200"; + $result = $db->sql_query($sql); + + $mark_ary = array(); + if ($row = $db->sql_fetchrow($result)) + { + do + { + $mark_ary[] = $row['user_id']; + } + while ($row = $db->sql_fetchrow($result)); + + group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_colour, $group_rank, $group_avatar, $group_avatar_type, $group_avatar_width, $group_avatar_height); + + $start = (sizeof($user_id_ary) < 200) ? 0 : $start + 200; + } + else + { + $start = 0; + } + $db->sql_freeresult($result); + } + while ($start); + } + else + { + group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_colour, $group_rank, $group_avatar, $group_avatar_type, $group_avatar_width, $group_avatar_height); + } + + trigger_error($user->lang['GROUP_DEFS_UPDATED']); + break; + + case 'deleteusers': + case 'delete': + if (!$cancel && !$confirm) + { + adm_page_confirm($user->lang['CONFIRM'], $user->lang['CONFIRM_OPERATION']); + } + else + { + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP']); + } + + switch ($action) + { + case 'delete': + $error = group_delete($group_id, $group_name); + break; + + case 'deleteusers': + $error = group_user_del($group_id, $mark_ary, false, $group_name); + break; + } + + if ($error) + { + trigger_error($user->lang[$error]); + } + + $message = ($action == 'delete') ? 'GROUP_DELETED' : 'GROUP_USERS_REMOVE'; + trigger_error($user->lang[$message]); + } + break; + case 'addusers': if (!$group_id) { @@ -146,7 +221,7 @@ switch ($mode) $name_ary = array_unique(explode("\n", $name_ary)); // Add user/s to group - if ($error = add_to_group($action, $group_id, false, $name_ary, $leader, $group_colour, $group_rank, $group_avatar, $group_avatar_type)) + if ($error = group_user_add($group_id, false, $name_ary, $group_name, $default, $leader, $group_colour, $group_rank, $group_avatar, $group_avatar_type, $group_avatar_width, $group_avatar_height)) { trigger_error($user->lang[$error]); } @@ -157,15 +232,73 @@ switch ($mode) case 'edit': case 'add': + if ($action == 'edit' && !$group_id) { trigger_error($user->lang['NO_GROUP']); } + $name = request_var('group_name', ''); + $desc = request_var('group_description', ''); + $type = request_var('group_type', 0); + + $colour = request_var('group_colour', ''); + $rank = request_var('group_rank', 0); + + $data['uploadurl'] = request_var('uploadurl', ''); + $data['remotelink'] = request_var('remotelink', ''); + $delete = request_var('delete', ''); + + if (!empty($_FILES['uploadfile']['tmp_name']) || $data['uploadurl'] || $data['remotelink']) + { + $data['width'] = request_var('width', ''); + $data['height'] = request_var('height', ''); + + // Avatar stuff + $var_ary = array( + 'uploadurl' => array('string', true, 5, 255), + 'remotelink' => array('string', true, 5, 255), + 'width' => array('string', true, 1, 3), + 'height' => array('string', true, 1, 3), + ); + + if (!($error = validate_data($data, $var_ary))) + { + $data['user_id'] = "g$group_id"; + + if ((!empty($_FILES['uploadfile']['tmp_name']) || $data['uploadurl']) && $can_upload) + { + list($avatar_type, $avatar, $avatar_width, $avatar_height) = avatar_upload($data, $error); + } + else if ($data['remotelink']) + { + list($avatar_type, $avatar, $avatar_width, $avatar_height) = avatar_remote($data, $error); + } + } + } + else if ($delete) + { + $avatar = ''; + $avatar_type = $avatar_width = $avatar_height = 0; + } + // Did we submit? if ($update) { - if (!($error = create_group($action, $group_id, $group_type, $group_name, $group_description, $group_colour, $group_rank, $group_avatar, $group_avatar_type, $group_avatar_width, $group_avatar_height))) + if (($avatar && $group_avatar != $avatar) || $delete) + { + avatar_delete($group_avatar); + } + + // Only set the rank, colour, etc. if it's changed or if we're adding a new + // group. This prevents existing group members being updated if no changes + // were made. + foreach (array('name', 'desc', 'type', 'rank', 'colour', 'avatar', 'avatar_type', 'avatar_width', 'avatar_height') as $test) + { + ${'group_' . $test} = ($action == 'add' || (isset($$test) && $$test != ${'group_' . $test})) ? $$test : false; + } + + if (!($error = group_create($group_id, $group_type, $group_name, $group_description, $group_colour, $group_rank, $group_avatar, $group_avatar_type, $group_avatar_width, $group_avatar_height))) { $message = ($action == 'edit') ? 'GROUP_UPDATED' : 'GROUP_CREATED'; trigger_error($message); @@ -173,7 +306,7 @@ switch ($mode) } else if (!$group_id) { - $group_name = (!empty($_POST['group_name'])) ? stripslashes(htmlspecialchars($_POST['group_name'])) : ''; + $group_name = request_var('group_name', ''); $group_description = $group_colour = $group_avatar = ''; $group_type = GROUP_FREE; } @@ -399,14 +532,16 @@ function swatch() lang['NO_GROUP']); - } + if ($mode == 'list' || $group_id) + { + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP']); + } ?> @@ -417,7 +552,7 @@ function swatch()
"> - + @@ -562,7 +697,7 @@ function swatch() ?> -
lang['USERNAME']; ?>Defaultlang['DEFAULT']; ?> lang['JOINED']; ?> lang['POSTS']; ?> lang['MARK']; ?>
lang['SELECT_OPTION']; ?>: 'DEFAULT', 'approve' => 'APPROVE', 'demote' => 'DEMOTE', 'promote' => 'PROMOTE', 'deleteusers' => 'DELETE') as $option => $lang) { @@ -610,10 +745,9 @@ function swatch() @@ -711,52 +845,6 @@ function swatch()
- - - - @@ -781,7 +869,7 @@ function hidebox(id)

lang['GROUP_SETTINGS_EXPLAIN']; ?>

-
"> +">
diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index dde2f137f6..3018089ac5 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -14,6 +14,94 @@ // // User functions // + +// Obtain user_ids from usernames or vice versa. Returns false on +// success else the error string +function get_username_id_data(&$user_id_ary, &$username_ary) +{ + global $db; + + // Are both arrays already filled? Yep, return else + // are neither array filled? + if ($user_id_ary && $username_ary) + { + return; + } + else if (!$user_id_ary && !$username_ary) + { + return 'NO_USERS'; + } + + $which_ary = ($user_id_ary) ? 'user_id_ary' : 'username_ary'; + + if ($$which_ary && !is_array($$which_ary)) + { + $$which_ary = array($$which_ary); + } + + $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', $$which_ary) : preg_replace('#^[\s]*(.*?)[\s]*$#e', "\"'\" . \$db->sql_escape('\\1') . \"'\"", $$which_ary); + unset($$which_ary); + + // Grab the user id/username records + $sql_where = ($which_ary == 'user_id_ary') ? 'user_id' : 'username'; + $sql = 'SELECT user_id, username + FROM ' . USERS_TABLE . " + WHERE $sql_where IN (" . implode(', ', $sql_in) . ')'; + $result = $db->sql_query($sql); + + if (!($row = $db->sql_fetchrow($result))) + { + return 'NO_USERS'; + } + + $id_ary = $username_ary = array(); + do + { + $username_ary[$row['user_id']] = $row['username']; + $user_id_ary[] = $row['user_id']; + } + while ($row = $db->sql_fetchrow($result)); + $db->sql_freeresult($result); + + return false; +} + +// Updates a username across all relevant tables/fields +function user_update_name($old_name, $new_name) +{ + global $db; + + $update_ary = array( + FORUMS_TABLE => array('forum_last_poster_name'), + MODERATOR_TABLE => array('username'), + POSTS_TABLE => array('poster_username'), + TOPICS_TABLE => array('topic_first_poster_name', 'topic_last_poster_name'), + ); + + foreach ($update_ary as $table => $field_ary) + { + foreach ($field_ary as $field) + { + $sql = "UPDATE $table + SET $field = '$new_name' + WHERE $field = '$old_name'"; + $db->sql_query($sql); + } + } + + $sql = 'UPDATE ' . CONFIG_TABLE . " + SET config_value = '" . $new_name . "' + WHERE config_name = 'newest_username' + AND config_value = '" . $old_name . "'"; + $db->sql_query($sql); +} + +// +// Data validation ... used primarily but not exclusively by +// ucp modules +// + +// "Master" function for validating a range of data types function validate_data($data, $val_ary) { $error = array(); @@ -205,34 +293,9 @@ function validate_email($email) return false; } -function update_username($old_name, $new_name) -{ - global $db; - - $update_ary = array( - FORUMS_TABLE => array('forum_last_poster_name'), - MODERATOR_TABLE => array('username'), - POSTS_TABLE => array('poster_username'), - TOPICS_TABLE => array('topic_first_poster_name', 'topic_last_poster_name'), - ); - - foreach ($update_ary as $table => $field_ary) - { - foreach ($field_ary as $field) - { - $sql = "UPDATE $table - SET $field = '$new_name' - WHERE $field = '$old_name'"; - $db->sql_query($sql); - } - } - - $sql = 'UPDATE ' . CONFIG_TABLE . " - SET config_value = '" . $new_name . "' - WHERE config_name = 'newest_username' - AND config_value = '" . $old_name . "'"; - $db->sql_query($sql); -} +// +// Avatar functions +// function avatar_delete($id) { @@ -275,9 +338,6 @@ function avatar_remote($data, &$error) $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_max_width'], $config['avatar_max_height']); return false; } - - $data['width'] = $width; - $data['height'] = $height; } else if ($data['width'] > $config['avatar_max_width'] || $data['height'] > $config['avatar_max_height']) { @@ -285,11 +345,7 @@ function avatar_remote($data, &$error) return false; } - // Set type - $data['filename'] = $data['remotelink']; - $data['type'] = AVATAR_REMOTE; - - return $data; + return array(AVATAR_REMOTE, $remotelink, $width, $height); } function avatar_upload($data, &$error) @@ -389,11 +445,9 @@ function avatar_upload($data, &$error) // Replace any chars which may cause us problems with _ $bad_chars = array(' ', '/', ':', '*', '?', '"', '<', '>', '|'); - $data['filename'] = $data['user_id'] . '_' . str_replace($bad_chars, '_', $realname) . '.' . $filetype; - $data['width'] = $width; - $data['height'] = $height; + $realfilename = $data['user_id'] . '_' . str_replace($bad_chars, '_', $realname) . '.' . $filetype; - if(!$php_move($filename, $phpbb_root_path . $config['avatar_path'] . '/' . $data['filename'])) + if(!$php_move($filename, $phpbb_root_path . $config['avatar_path'] . '/' . $realfilename)) { @unlink($filename); $error[] = $user->lang['AVATAR_NOT_UPLOADED']; @@ -401,18 +455,15 @@ function avatar_upload($data, &$error) } @unlink($filename); - $filesize = @filesize($phpbb_root_path . $config['avatar_path'] . '/' . $data['filename']); + $filesize = @filesize($phpbb_root_path . $config['avatar_path'] . "/$realfilename"); if (!$filesize || $filesize > $config['avatar_filesize']) { - @unlink($phpbb_root_path . $config['avatar_path'] . '/' . $data['filename']); + @unlink($phpbb_root_path . $config['avatar_path'] . "/$realfilename"); $error[] = sprintf($user->lang['AVATAR_WRONG_FILESIZE'], $config['avatar_filesize']); return false; } - // Set type - $data['type'] = AVATAR_UPLOAD; - - return $data; + return array(AVATAR_UPLOAD, $realfilename, $width, $height); } function avatar_gallery($category, &$error) @@ -457,68 +508,173 @@ function avatar_gallery($category, &$error) return $data; } -// Generates an alphanumeric random string of given length -function gen_rand_string($num_chars) -{ - $chars = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9'); - - list($usec, $sec) = explode(' ', microtime()); - mt_srand($sec * $usec); - - $max_chars = count($chars) - 1; - $rand_str = ''; - for ($i = 0; $i < $num_chars; $i++) - { - $rand_str .= $chars[mt_rand(0, $max_chars)]; - } - - return $rand_str; -} - - // // Usergroup functions // -function add_to_group($action, $group_id, $user_id_ary, $username_ary, $leader, $colour, $rank, $avatar, $avatar_type) +// Add or edit a group. If we're editing a group we only update user +// parameters such as rank, etc. if they are changed +function group_create($group_id, $type, $name, $desc) +{ + global $phpbb_root_path, $config, $db, $user, $file_upload; + + $error = array(); + + // Check data + if (!strlen($name) || strlen($name) > 40) + { + $error[] = (!strlen($name)) ? $user->lang['GROUP_ERR_USERNAME'] : $user->lang['GROUP_ERR_USER_LONG']; + } + + if (strlen($desc) > 255) + { + $error[] = $user->lang['GROUP_ERR_DESC_LONG']; + } + + if (!in_array($type, array(GROUP_OPEN, GROUP_CLOSED, GROUP_HIDDEN, GROUP_SPECIAL, GROUP_FREE))) + { + $error[] = $user->lang['GROUP_ERR_TYPE']; + } + + if (!sizeof($error)) + { + $sql_ary = array( + 'group_name' => (string) $name, + 'group_description' => (string) $desc, + 'group_type' => (int) $type, + ); + + $attribute_ary = array('group_colour' => 'string', 'group_rank' => 'int', 'group_avatar' => 'string', 'group_avatar_type' => 'int', 'group_avatar_width' => 'int', 'group_avatar_height' => 'int'); + + $i = 4; + foreach ($attribute_ary as $attribute => $type) + { + if (func_num_args() > $i && ($value = func_get_arg($i)) !== false) + { + settype($value, $type); + + $sql_ary[$attribute] = $$attribute = $value; + } + $i++; + } + + $sql = ($group_id) ? 'UPDATE ' . GROUPS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE group_id = $group_id" : 'INSERT INTO ' . GROUPS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + + $sql_ary = array(); + foreach ($attribute_ary as $attribute => $type) + { + if (isset($$attribute)) + { + $sql_ary[str_replace('group', 'user', $attribute)] = $$attribute; + } + } + + if (sizeof($sql_ary)) + { + $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE group_id = $group_id"; + $db->sql_query($sql); + } + + if (!function_exists('add_log')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/functions_admin.'.$phpEx); + } + + $log = ($group_id) ? 'LOG_GROUP_UPDATED' : 'LOG_GROUP_CREATED'; + add_log('admin', $log, $name); + } + + return (sizeof($error)) ? $error : false; +} + +function group_delete($group_id, $group_name = false) { global $db; - $which_ary = ($user_id_ary) ? 'user_id_ary' : 'username_ary'; - - if ($$which_ary && !is_array($$which_ary)) + if (!$group_name) { - $$which_ary = array($$which_ary); + $sql = 'SELECT group_name + FROM ' . GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + + if (!extract($db->sql_fetchrow($result))) + { + trigger_error("Could not obtain name of group $group_id", E_USER_ERROR); + } + $db->sql_freeresult($result); } - $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', $$which_ary) : preg_replace('#^[\s]*(.*?)[\s]*$#e', "\"'\" . \$db->sql_escape('\\1') . \"'\"", $$which_ary); - unset($$which_ary); + $batch = 100; + $start = 0; + $end = $start + $batch; - // Grab the user id/username records - $sql_where = ($which_ary == 'user_id_ary') ? 'user_id' : 'username'; - $sql = 'SELECT user_id, username - FROM ' . USERS_TABLE . " - WHERE $sql_where IN (" . implode(', ', $sql_in) . ')'; - $result = $db->sql_query($sql); - - if (!($row = $db->sql_fetchrow($result))) - { - return 'NO_USERS'; - } - - $id_ary = $username_ary = array(); do { - $username_ary[$row['user_id']] = $row['username']; - $id_ary[] = $row['user_id']; + $user_id_ary = $username_ary = array(); + + // Batch query for group members, call group_user_del + $sql = 'SELECT u.user_id, u.username + FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . " u + WHERE ug.group_id = $group_id + AND u.user_id = ug.user_id + BETWEEN $start + AND $end"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $user_id_ary[] = $row['user_id']; + $username_ary[] = $row['username']; + + $start++; + } + while ($row = $db->sql_fetchrow($result)); + + group_user_del($group_id, $user_id_ary, $username_ary, $group_name); + + $end = $start + $batch; + } + else + { + $start = 0; + } + $db->sql_freeresult($result); } - while ($row = $db->sql_fetchrow($result)); - $db->sql_freeresult($result); + while ($start); + + // Delete group + $sql = 'DELETE FROM ' . GROUPS_TABLE . " + WHERE group_id = $group_id"; + $db->sql_query($sql); + + if (!function_exists('add_log')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/functions_admin.'.$phpEx); + } + + add_log('admin', 'LOG_GROUP_DELETE', $group_name); + + return false; +} + +function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $default = false, $leader = false) +{ + global $db, $auth; + + // We need both username and user_id info + get_username_id_data($user_id_ary, $username_ary); // Remove users who are already members of this group $sql = 'SELECT user_id, group_leader FROM ' . USER_GROUP_TABLE . ' - WHERE user_id IN (' . implode(', ', $id_ary) . ") + WHERE user_id IN (' . implode(', ', $user_id_ary) . ") AND group_id = $group_id"; $result = $db->sql_query($sql); @@ -539,7 +695,7 @@ function add_to_group($action, $group_id, $user_id_ary, $username_ary, $leader, $db->sql_freeresult($result); // Do all the users exist in this group? - $add_id_ary = array_diff($id_ary, $add_id_ary); + $add_id_ary = array_diff($user_id_ary, $add_id_ary); unset($id_ary); // If we have no users @@ -577,11 +733,6 @@ function add_to_group($action, $group_id, $user_id_ary, $username_ary, $leader, } break; } - - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_permissions = '' - WHERE user_id IN (" . implode(', ', $add_id_ary) . ')'; - $db->sql_query($sql); } $usernames = array(); @@ -605,20 +756,82 @@ function add_to_group($action, $group_id, $user_id_ary, $username_ary, $leader, $usernames[] = $username_ary[$id]; } } - unset($username_ary); - // Update user settings (color, rank) if applicable - // TODO - // Do not update users who are not approved - if (!empty($_POST['default'])) + if ($default) { - $sql = 'UPDATE ' . USERS_TABLE . " - SET group_id = $group_id, user_colour = '" . $db->sql_escape($color) . "', user_rank = $rank - WHERE user_id IN (" . implode(', ', array_merge($add_id_ary, $update_id_ary)) . ")"; + $attribute_ary = array('group_colour' => 'string', 'group_rank' => 'int', 'group_avatar' => 'string', 'group_avatar_type' => 'int', 'group_avatar_width' => 'int', 'group_avatar_height' => 'int'); + + // Were group attributes passed to the function? If not we need to obtain them + if (func_num_args() > 6) + { + $i = 6; + foreach ($attribute_ary as $attribute => $type) + { + if (func_num_args() > $i && ($value = func_get_arg($i)) !== false) + { + settype($value, $type); + + $sql_ary[$attribute] = $$attribute = $value; + } + $i++; + } + } + else + { + $sql = 'SELECT group_colour, group_rank, group_avatar, group_avatar_type, group_avatar_width, group_avatar_height + FROM ' . GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + + if (!extract($db->sql_fetchrow($result))) + { + trigger_error("Could not obtain group attributes for group_id $group_id", E_USER_ERROR); + } + } + + $sql_set = ''; + foreach ($attribute_ary as $attribute => $type) + { + if (isset($$attribute)) + { + $field = str_replace('group_', 'user_', $attribute); + + switch ($type) + { + case 'int': + $sql_set .= ", $field = " . (int) $$attribute; + break; + case 'double': + $sql_set .= ", $field = " . (double) $$attribute; + break; + case 'string': + $sql_set .= ", $field = '" . (string) $db->sql_escape($$attribute) . "'"; + break; + } + } + } + + $sql = 'UPDATE ' . USERS_TABLE . " + SET group_id = $group_id$sql_set + WHERE user_id IN (" . implode(', ', $user_id_ary) . ')'; $db->sql_query($sql); } - unset($update_id_ary); - unset($add_id_ary); + + // Clear permissions cache of relevant users + $auth->acl_clear_prefetch($user_id_ary); + + if (!$group_name) + { + $sql = 'SELECT group_name + FROM ' . GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + + if (!extract($db->sql_fetchrow($result))) + { + trigger_error("Could not obtain name of group $group_id", E_USER_ERROR); + } + } if (!function_exists('add_log')) { @@ -627,257 +840,8 @@ function add_to_group($action, $group_id, $user_id_ary, $username_ary, $leader, } $log = ($leader) ? 'LOG_MODS_ADDED' : 'LOG_USERS_ADDED'; - add_log('admin', $log, $group_name, implode(', ', $usernames)); - return false; -} - -function create_group($action, $group_id, &$type, &$name, &$desc, &$colour, &$rank, &$avatar) -{ - global $phpbb_root_path, $config, $db, $user; - - $error = array(); - - $can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && is_writeable($phpbb_root_path . $config['avatar_path']) && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false; - - if (isset($type) && $type != GROUP_SPECIAL) - { - $name = request_var('group_name', ''); - $type = request_var('group_type', 0); - } - $desc = request_var('group_description', ''); - $colour2 = request_var('group_colour', ''); - $rank2 = request_var('group_rank', 0); - - $data['uploadurl'] = request_var('uploadurl', ''); - $data['remotelink'] = request_var('remotelink', ''); - $data['width'] = request_var('width', ''); - $data['height'] = request_var('height', ''); - $delete = request_var('delete', ''); - - // Check data - if (!strlen($name) || strlen($name) > 40) - { - $error[] = (!strlen($name)) ? $user->lang['GROUP_ERR_USERNAME'] : $user->lang['GROUP_ERR_USER_LONG']; - } - - if (strlen($desc) > 255) - { - $error[] = $user->lang['GROUP_ERR_DESC_LONG']; - } - - if ($type < GROUP_OPEN || $type > GROUP_FREE) - { - $error[] = $user->lang['GROUP_ERR_TYPE']; - } - - // Avatar stuff - $var_ary = array( - 'uploadurl' => array('string', true, 5, 255), - 'remotelink' => array('string', true, 5, 255), - 'width' => array('string', true, 1, 3), - 'height' => array('string', true, 1, 3), - ); - - $error = validate_data($data, $var_ary); - - if (!sizeof($error)) - { - $data['user_id'] = "g$group_id"; - - if (!empty($_FILES['uploadfile']['tmp_name']) && $can_upload) - { - $data = avatar_upload($data, $error); - } - else if ($data['uploadurl'] && $can_upload) - { - $data = avatar_upload($data, $error); - } - else if ($data['remotelink']) - { - $data = avatar_remote($data, $error); - } - else if ($delete) - { - $data['filename'] = $data['width'] = $data['height'] = ''; - } - - // Update group preferences - $sql_ary = array( - 'group_name' => (string) $name, - 'group_description' => (string) $desc, - 'group_type' => (int) $type, - 'group_rank' => (int) $rank2, - 'group_colour' => (string) $colour2, - 'group_avatar' => (string) $data['filename'], - 'group_avatar_type' => (int) $data['type'], - 'group_avatar_width' => (int) $data['width'], - 'group_avatar_height' => (int) $data['height'], - ); - - $sql = ($action == 'edit' && $group_id) ? 'UPDATE ' . GROUPS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE group_id = $group_id" : 'INSERT INTO ' . GROUPS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); - $db->sql_query($sql); - - if ($group_id && ($colour != $colour2 || $rank != $rank2 || $avatar != $data['filename'])) - { - $sql_ary = array( - 'user_rank' => (string) $rank2, - 'user_colour' => (string) $colour2, - 'user_avatar' => (string) $data['filename'], - 'user_avatar_type' => (int) $data['type'], - 'user_avatar_width' => (int) $data['width'], - 'user_avatar_height'=> (int) $data['height'], - ); - - $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " - WHERE group_id = $group_id"; - $db->sql_query($sql); - - // Delete old avatar if present - if ($avatar != '' && $avatar != $data['filename']) - { - avatar_delete($avatar); - } - } - - if (!function_exists('add_log')) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/functions_admin.'.$phpEx); - } - - $log = ($action == 'edit') ? 'LOG_GROUP_UPDATED' : 'LOG_GROUP_CREATED'; - add_log('admin', $log, $group_name); - } - - $colour = $colour2; - $rank = $rank2; - $avatar = $avatar2; - - return (sizeof($error)) ? $error : false; -} - -// Call with: user_id_ary or username_ary set ... if both false entire group -// will be set default -function set_default_group($id, $user_id_ary, $username_ary, &$name, &$colour, &$rank, $avatar, $avatar_type) -{ - global $db; - - if (is_array($user_id_ary) || is_array($username_ary)) - { - $sql_where = ($user_id_ary) ? 'user_id IN (' . implode(', ', $user_id_ary) . ')' : 'username IN (' . implode(', ', $username_ary) . ')'; - - $sql = 'UPDATE ' . USERS_TABLE . " - SET group_id = $id, user_colour = '$colour', user_rank = $rank - WHERE $sql_where"; - $db->sql_query($sql); - } - else - { - switch (SQL_LAYER) - { - case 'mysql': - case 'mysql4': - // With no subselect we do mysql updates in batches to ward off - // potential issues with large groups - - $start = 0; - do - { - $sql = 'SELECT user_id - FROM ' . USER_GROUP_TABLE . " - WHERE group_id = $id - ORDER BY user_id - LIMIT $start, 200"; - $result = $db->sql_query($sql); - - $user_id_ary = array(); - if ($row = $db->sql_fetchrow($result)) - { - do - { - $user_id_ary[] = $row['user_id']; - } - while ($row = $db->sql_fetchrow($result)); - - $sql = 'UPDATE ' . USERS_TABLE . " - SET group_id = $id, user_colour = '$colour', user_rank = $rank - WHERE user_id IN (" . implode(', ', $user_id_ary) . ')'; - $db->sql_query($sql); - - $start = (sizeof($user_id_ary) < 200) ? 0 : $start + 200; - } - else - { - $start = 0; - } - $db->sql_freeresult($result); - } - while ($start); - break; - - default: - $sql = 'UPDATE ' . USERS_TABLE . " - SET group_id = $id, user_colour = '$colour', user_rank = $rank - WHERE user_id IN ( - SELECT user_id - FROM " . USER_GROUP_TABLE . " - WHERE group_id = $id - )"; - $db->sql_query($sql); - break; - } - } - - if (!function_exists('add_log')) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/functions_admin.'.$phpEx); - } - - add_log('admin', 'LOG_GROUP_DEFAULTS', $name); - - return false; -} - -// Call with: user_id_ary or username_ary set ... if both false entire group -// will be approved -function approve_user($group_id, $user_id_ary, $username_ary, &$group_name) -{ - global $db; - - if (is_array($user_id_ary) || is_array($username_ary)) - { - $sql_where = ($user_id_ary) ? 'user_id IN (' . implode(', ', $user_id_ary) . ')' : 'username IN (' . implode(', ', $username_ary) . ')'; - - $sql = 'SELECT user_id, username - FROM ' . USERS_TABLE . " - WHERE $sql_where"; - } - else - { - $sql = 'SELECT u.user_id, u.username - FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " - WHERE ug.group_id = $group_id - AND u.user_id = ug.user_id"; - } - $result = $db->sql_query($sql); - - $usernames = array(); - while ($row = $db->sql_fetchrow($result)) - { - $username_ary[] = $row['username']; - $user_id_ary[] = $row['user_id']; - } - $db->sql_freeresult($result); - - $sql = 'UPDATE ' . USER_GROUP_TABLE . " - SET user_pending = 0 - WHERE group_id = $group_id - AND user_id IN (" . implode(', ', $user_id_ary) . ')'; - $db->sql_query($sql); - - add_log('admin', 'LOG_GROUP_APPROVE', $group_name, implode(', ', $username_ary)); + add_log('admin', $log, $group_name, implode(', ', $username_ary)); unset($username_ary); unset($user_id_ary); @@ -885,164 +849,228 @@ function approve_user($group_id, $user_id_ary, $username_ary, &$group_name) return false; } -// Setting action to demote true will demote leaders to users -// (if appropriate), deleting leaders removes them from group as with -// normal users -function group_memberships($action, $id, $user_id_ary, $username_ary, &$group_name) +// Remove a user/s from a given group. When we remove users we update their +// default group_id. We do this by examining which "special" groups they belong +// to. The selection is made based on a reasonable priority system +function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_name = false) { - global $db; + global $db, $auth; - // If no user_id or username data is submitted we'll act the entire group - if ($action == 'delete' && !$user_id_ary && !$username_ary) - { - $sql = 'SELECT user_id - FROM ' . USER_GROUP_TABLE . " - WHERE group_id = $id"; - $result = $db->sql_query($sql); + $group_order = array('ADMINISTRATORS', 'SUPER_MODERATORS', 'REGISTERED_COPPA', 'REGISTERED', 'BOTS', 'GUESTS'); - while ($row = $db->sql_fetchrow($result)) - { - $user_id_ary[] = $row['user_id']; - } - $db->sql_freeresult($result); - } + $attribute_ary = array('group_colour' => 'string', 'group_rank' => 'int', 'group_avatar' => 'string', 'group_avatar_type' => 'int', 'group_avatar_width' => 'int', 'group_avatar_height' => 'int'); - $which_ary = ($user_id_ary) ? 'user_id_ary' : 'username_ary'; + // We need both username and user_id info + get_username_id_data($user_id_ary, $username_ary); - if ($$which_ary && !is_array($$which_ary)) - { - $$which_ary = array($$which_ary); - } - - $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', $user_id_ary) : preg_replace('#^[\s]*?(.*?)[\s]*?$#e', "\"'\" . \$db->sql_escape('\\1') . \"'\"", $username_ary); - - $sql_where = ($which_ary == 'user_id_ary') ? 'user_id' : 'username'; - $sql = 'SELECT user_id, username - FROM ' . USERS_TABLE . " - WHERE $sql_where IN (" . implode(', ', $sql_in) . ')'; + $sql = 'SELECT * + FROM ' . GROUPS_TABLE . ' + WHERE group_name IN (' . implode(', ', preg_replace('#^(.*)$#', "'\\1'", $group_order)) . ')'; $result = $db->sql_query($sql); - if (!($row = $db->sql_fetchrow($result))) + $group_order_id = $special_group_data = array(); + while ($row = $db->sql_fetchrow($result)) { - return 'NO_USERS'; + $group_order_id[$row['group_name']] = $row['group_id']; + + $special_group_data[$row['group_id']]['group_colour'] = $row['group_colour']; + $special_group_data[$row['group_id']]['group_rank'] = $row['group_rank']; + $special_group_data[$row['group_id']]['group_avatar'] = $row['group_avatar']; + $special_group_data[$row['group_id']]['group_avatar_type'] = $row['group_avatar_type']; + $special_group_data[$row['group_id']]['group_avatar_width'] = $row['group_avatar_width']; + $special_group_data[$row['group_id']]['group_avatar_height'] = $row['group_avatar_height']; + } + $db->sql_freeresult($result); + + // What special group memberships exist for these users? + $sql = 'SELECT g.group_id, g.group_name, ug.user_id + FROM ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g + WHERE ug.user_id IN (' . implode(', ', $user_id_ary) . ") + AND g.group_id = ug.group_id + AND g.group_id <> $group_id + AND g.group_type = " . GROUP_SPECIAL . ' + ORDER BY ug.user_id, g.group_id'; + $result = $db->sql_query($sql); + + $temp_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + if (!isset($temp_ary[$row['user_id']]) || array_search($row['group_name'], $group_order) < $temp_ary[$row['user_id']]) + { + $temp_ary[$row['user_id']] = $row['group_id']; + } + } + $db->sql_freeresult($result); + + $sql_where_ary = array(); + foreach ($temp_ary as $uid => $gid) + { + $sql_where_ary[$gid][] = $uid; + } + unset($temp_ary); + + foreach ($special_group_data as $gid => $default_data_ary) + { + if ($sql_where = implode(', ', $sql_where_ary[$gid])) + { + $sql_set = ''; + foreach ($special_group_data[$gid] as $attribute => $value) + { + $field = str_replace('group_', 'user_', $attribute); + + switch ($attribute_ary[$attribute]) + { + case 'int': + $sql_set .= ", $field = " . (int) $value; + break; + case 'double': + $sql_set .= ", $field = " . (double) $value; + break; + case 'string': + $sql_set .= ", $field = '" . $db->sql_escape($value) . "'"; + break; + } + } + + // Set new default + $sql = 'UPDATE ' . USERS_TABLE . " + SET group_id = $gid$sql_set + WHERE user_id IN (" . implode(', ', $sql_where_ary[$gid]) . ')'; + $db->sql_query($sql); + } + } + unset($special_group_data); + + $sql = 'DELETE FROM ' . USER_GROUP_TABLE . " + WHERE group_id = $group_id + AND user_id IN (" . implode(', ', $user_id_ary) . ')'; + $db->sql_query($sql); + unset($default_ary); + + // Clear permissions cache of relevant users + $auth->acl_clear_prefetch($user_id_ary); + + if (!$group_name) + { + $sql = 'SELECT group_name + FROM ' . GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + + if (!extract($db->sql_fetchrow($result))) + { + trigger_error("Could not obtain name of group $group_id", E_USER_ERROR); + } } - $id_ary = $username_ary = array(); - do + if (!function_exists('add_log')) { - $username_ary[$row['user_id']] = $row['username']; - $id_ary[] = $row['user_id']; + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/functions_admin.'.$phpEx); } - while ($row = $db->sql_fetchrow($result)); - $db->sql_freeresult($result); + + $log = 'LOG_GROUP_REMOVE'; + + add_log('admin', $log, $group_name, implode(', ', $username_ary)); + + unset($username_ary); + unset($user_id_ary); + + return false; +} + +// This is used to promote (to leader), demote or set as default a member/s +function group_user_attributes($action, $group_id, $user_id_ary = false, $username_ary = false, $group_name = false) +{ + global $db, $auth; + + // We need both username and user_id info + get_username_id_data($user_id_ary, $username_ary); switch ($action) { case 'demote': - $sql = 'UPDATE ' . USER_GROUP_TABLE . ' - SET group_leader = 0 - WHERE user_id IN (' . implode(', ', $id_ary) . ") - AND group_id = $id"; - $db->sql_query($sql); - - $log = 'LOG_GROUP_DEMOTED'; - break; - case 'promote': $sql = 'UPDATE ' . USER_GROUP_TABLE . ' - SET group_leader = 1 - WHERE user_id IN (' . implode(', ', $id_ary) . ") - AND group_id = $id"; + SET group_leader = ' . (($action == 'promote') ? 1 : 0) . " + WHERE group_id = $group_id + AND user_id IN (" . implode(', ', $user_id_ary) . ')'; $db->sql_query($sql); - $log = 'LOG_GROUP_PROMOTED'; + $log = ($action == 'promote') ? 'LOG_GROUP_PROMOTED' : 'LOG_GROUP_DEMOTED'; break; - case 'delete': - case 'deleteusers': - $group_order = array('ADMINISTRATORS', 'SUPER_MODERATORS', 'REGISTERED', 'REGISTERED_COPPA', 'BOTS', 'GUESTS'); + case 'approve': + $sql = 'UPDATE ' . USER_GROUP_TABLE . " + SET user_pending = 0 + WHERE group_id = $group_id + AND user_id IN (" . implode(', ', $user_id_ary) . ')'; + $db->sql_query($sql); - $sql = 'SELECT * - FROM ' . GROUPS_TABLE . ' - WHERE group_name IN (' . implode(', ', preg_replace('#^(.*)$#', "'\\1'", $group_order)) . ')'; - $result = $db->sql_query($sql); + $log = 'LOG_GROUP_APPROVE'; + break; - $group_order_keys = $group_data = array(); - while ($row = $db->sql_fetchrow($result)) + case 'default': + $attribute_ary = array('group_colour' => 'string', 'group_rank' => 'int', 'group_avatar' => 'string', 'group_avatar_type' => 'int', 'group_avatar_width' => 'int', 'group_avatar_height' => 'int'); + + // Were group attributes passed to the function? If not we need + // to obtain them + if (func_num_args() > 5) { - $group_order_keys[$row['group_name']] = $row['group_id']; - - $group_data[$row['group_id']]['color'] = $row['group_colour']; - $group_data[$row['group_id']]['rank'] = $row['group_rank']; - } - $db->sql_freeresult($result); - - $new_group_order = array(); - foreach ($group_order as $group) - { - $new_group_order[$group] = $group_order_keys[$group]; - } - $group_order = $new_group_order; - unset($new_group_order); - unset($group_order_keys); - - $sql = 'SELECT g.group_id, g.group_name, ug.user_id - FROM ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g - WHERE ug.user_id IN (' . implode(', ', $user_id_ary) . ") - AND g.group_id = ug.group_id - AND g.group_id <> $id - AND g.group_type = " . GROUP_SPECIAL . ' - ORDER BY ug.user_id, g.group_id'; - $result = $db->sql_query($sql); - - $default_ary = array(); - while ($row = $db->sql_fetchrow($result)) - { - $default_ary[$row['user_id']][] = $row['group_name']; - } - $db->sql_freeresult($result); - - foreach ($default_ary as $user_id => $group_ary) - { - foreach ($group_order as $group_name => $group_id) + $i = 5; + foreach ($attribute_ary as $attribute => $type) { - if (in_array($group_name, $group_ary)) + if (func_num_args() > $i && ($value = func_get_arg($i)) !== false) { - $default_group_ary[$group_id][] = $user_id; - continue 2; + settype($value, $type); + + $sql_ary[$attribute] = $$attribute = $value; + } + $i++; + } + } + else + { + $sql = 'SELECT group_colour, group_rank, group_avatar, group_avatar_type, group_avatar_width, group_avatar_height + FROM ' . GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + + if (!extract($db->sql_fetchrow($result))) + { + return 'NO_GROUP'; + } + $db->sql_freeresult($result); + } + + $sql_set = ''; + foreach ($attribute_ary as $attribute => $type) + { + if (isset($$attribute)) + { + $field = str_replace('group_', 'user_', $attribute); + + switch ($type) + { + case 'int': + $sql_set .= ", $field = " . (int) $$attribute; + break; + case 'double': + $sql_set .= ", $field = " . (double) $$attribute; + break; + case 'string': + $sql_set .= ", $field = '" . (string) $db->sql_escape($$attribute) . "'"; + break; } } } - foreach ($default_group_ary as $group_id => $new_default_ary) - { - // Set new default - $sql = 'UPDATE ' . USERS_TABLE . " - SET group_id = $group_id, user_colour = '" . $group_data[$group_id]['color'] . "', user_rank = " . $group_data[$group_id]['rank'] . " - WHERE user_id IN (" . implode(', ', $new_default_ary) . ')'; - $db->sql_query($sql); - } - unset($default_group_ary); - - if ($action == 'delete') - { - $sql = 'DELETE FROM ' . GROUPS_TABLE . " - WHERE group_id = $db"; - $db->sql_query($sql); - - $sql = 'DELETE FROM ' . USER_GROUP_TABLE . " - WHERE group_id = $id"; - } - else - { - $sql = 'DELETE FROM ' . USER_GROUP_TABLE . " - WHERE group_id = $id - AND user_id IN (" . implode(', ', array_keys($default_ary)) . ')'; - } + $sql = 'UPDATE ' . USERS_TABLE . " + SET group_id = $group_id$sql_set + WHERE user_id IN (" . implode(', ', $user_id_ary) . ')'; $db->sql_query($sql); - unset($default_ary); - $log = ($action == 'deleteusers') ? 'LOG_GROUP_REMOVE' : 'LOG_GROUP_DELETED'; + $log = 'LOG_GROUP_DEFAULTS'; break; } @@ -1052,8 +1080,48 @@ function group_memberships($action, $id, $user_id_ary, $username_ary, &$group_na include($phpbb_root_path . 'includes/functions_admin.'.$phpEx); } + // Clear permissions cache of relevant users + $auth->acl_clear_prefetch($user_id_ary); + + if (!$group_name) + { + $sql = 'SELECT group_name + FROM ' . GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + + if (!extract($db->sql_fetchrow($result))) + { + trigger_error("Could not obtain name of group $group_id", E_USER_ERROR); + } + } + add_log('admin', $log, $group_name, implode(', ', $username_ary)); + unset($username_ary); + unset($user_id_ary); + + return false; +} + +// Obtain either the members of a specified group or the groups to +// which the specified users are members +function group_memberships($group_id = false, $user_id_ary = false) +{ + global $db; + + if (!$group_id && !$user_id_ary) + { + return true; + } + + if ($group_id) + { + } + else if ($user_id_ary) + { + } + return false; }
lang['GROUP_SETTINGS']; ?>