From a7d186fd9127db566ec2ad0a66aaeabe2d569004 Mon Sep 17 00:00:00 2001 From: "Paul S. Owen" Date: Sat, 26 Oct 2002 12:34:39 +0000 Subject: Preliminary 'freeze' on permissions system awaiting developer feedback, testing, etc. Caching of non-dynmaic config and acl option elements. git-svn-id: file:///svn/phpbb/trunk@2969 89ea8834-ac86-4346-8a33-228a782c2dd0 --- phpBB/includes/functions.php | 112 ++++++++------------- phpBB/includes/functions_admin.php | 194 ++++++++++++++++++++++++++++++++++--- phpBB/includes/session.php | 123 ++--------------------- 3 files changed, 226 insertions(+), 203 deletions(-) (limited to 'phpBB') diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 06e901842d..9aa3cd8800 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -19,55 +19,6 @@ * ***************************************************************************/ -function get_db_stat($mode) -{ - global $db; - - switch( $mode ) - { - case 'usercount': - $sql = "SELECT COUNT(user_id) - 1 AS total - FROM " . USERS_TABLE; - break; - - case 'newestuser': - $sql = "SELECT user_id, username - FROM " . USERS_TABLE . " - WHERE user_id <> " . ANONYMOUS . " - ORDER BY user_id DESC - LIMIT 1"; - break; - - case 'postcount': - case 'topiccount': - $sql = "SELECT SUM(forum_topics) AS topic_total, SUM(forum_posts) AS post_total - FROM " . FORUMS_TABLE; - break; - } - - $result = $db->sql_query($sql); - - $row = $db->sql_fetchrow($result); - - switch ( $mode ) - { - case 'usercount': - return $row['total']; - break; - case 'newestuser': - return $row; - break; - case 'postcount': - return $row['post_total']; - break; - case 'topiccount': - return $row['topic_total']; - break; - } - - return false; -} - function sql_quote($msg) { return str_replace("'", "''", $msg); @@ -126,18 +77,22 @@ function get_forum_branch($forum_id, $type='all', $order='descending', $include_ // Obtain list of moderators of each forum // First users, then groups ... broken into two queries +// We could cache this ... certainly into a DB table. Would +// better allow the admin to decide which moderators are +// displayed(?) function get_moderators(&$forum_moderators, $forum_id = false) { - global $SID, $db, $phpEx; + global $SID, $db, $acl_options, $phpEx; - $forum_sql = ( $forum_id ) ? 'AND au.forum_id = ' . $forum_id : ''; + $forum_sql = ( $forum_id ) ? 'AND m.forum_id = ' . $forum_id : ''; $sql = "SELECT au.forum_id, u.user_id, u.username - FROM " . ACL_USERS_TABLE . " au, " . ACL_OPTIONS_TABLE . " ao, " . USERS_TABLE . " u - WHERE ao.auth_value = 'm_global' - $forum_sql - AND au.auth_option_id = ao.auth_option_id - AND u.user_id = au.user_id"; + FROM " . ACL_OPTIONS_TABLE . " o, " . ACL_USERS_TABLE . " au, " . USERS_TABLE . " u + WHERE au.auth_option_id = o.auth_option_id + AND au.user_id = u.user_id + AND o.auth_value = 'm_' + AND au.auth_allow_deny = 1 + $forum_sql"; $result = $db->sql_query($sql); while ( $row = $db->sql_fetchrow($result) ) @@ -145,12 +100,14 @@ function get_moderators(&$forum_moderators, $forum_id = false) $forum_moderators[$row['forum_id']][] = '' . $row['username'] . ''; } - $sql = "SELECT au.forum_id, g.group_id, g.group_name - FROM " . ACL_GROUPS_TABLE . " au, " . ACL_OPTIONS_TABLE . " ao, " . GROUPS_TABLE . " g - WHERE ao.auth_value = 'm_global' - $forum_sql - AND au.auth_option_id = ao.auth_option_id - AND g.group_id = au.group_id"; + $sql = "SELECT ag.forum_id, g.group_name, g.group_id + FROM " . ACL_OPTIONS_TABLE . " o, " . ACL_GROUPS_TABLE . " ag, " . GROUPS_TABLE . " g + WHERE ag.auth_option_id = o.auth_option_id + AND ag.group_id = g.group_id + AND o.auth_value = 'm_' + AND ag.auth_allow_deny = 1 + AND g.group_type <> " . GROUP_HIDDEN . " + $forum_sql"; $result = $db->sql_query($sql); while ( $row = $db->sql_fetchrow($result) ) @@ -611,8 +568,10 @@ function message_die($msg_code, $msg_text = '', $msg_title = '') case ERROR: $db->sql_close(); - echo 'phpBB 2 :: General Error' . "\n"; - echo '

phpBB2 :: General Error


' . $msg_text . '


Contact the site administrator to report this failure

'; + echo '' . $msg_title . '
» ' . $msg_title . '   

' . $msg_text . '

'; break; } @@ -628,9 +587,17 @@ function msg_handler($errno, $msg_text, $errfile, $errline) switch ( $errno ) { case E_WARNING: +// if (defined('DEBUG')) +// { +// echo "PHP Warning on line $errline in $errfile :: $msg_text"; +// } break; case E_NOTICE: +// if (defined('DEBUG_EXTRA')) +// { +// echo "PHP Notice on line $errline in $errfile :: $msg_text"; +// } break; case E_USER_ERROR: @@ -639,8 +606,12 @@ function msg_handler($errno, $msg_text, $errfile, $errline) $db->sql_close(); } - echo '' . $msg_title . '' . "\n"; - echo '
' . $msg_title . '
' . $msg_text . '
'; + echo '' . $msg_title . ''; + echo '
phpBB LogoGeneral Error      


' . $msg_text . '
Please notify the board administrator or webmaster : ' . $board_config['board_email'] . '

'; + exit; break; @@ -649,14 +620,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) if ( !defined('HEADER_INC') ) { - if ( empty($user->data) ) - { - echo '' . $user->lang['Information'] . '' . "\n"; - echo '
' . $user->lang['Information'] . '
' . $msg_text . '
'; - $db->sql_close(); - exit; - } - else if ( defined('IN_ADMIN') ) + if ( defined('IN_ADMIN') ) { page_header('', '', false); } diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 4995db0a4f..0c42e528c8 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -395,15 +395,96 @@ function split_sql_file($sql, $delimiter) return $output; } +// Rebuild board_config array in cache file +function config_config($config = false) +{ + global $db, $phpbb_root_path, $phpEx; + + if ( !$config ) + { + $config = array(); + + $sql = "SELECT * + FROM " . CONFIG_TABLE . " + WHERE is_dynamic <> 1"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $config[$row['config_name']] = $row['config_value']; + } + } + + $cache_str = "\$board_config = array(\n"; + foreach ($config as $config_name => $config_value) + { + $cache_str .= "\t'$config_name' => " . ( ( is_numeric($config_value) ) ? $config_value : '"' . addslashes($config_value) . '"' ) . ",\n"; + } + $cache_str .= ");"; + + config_cache_write('\$board_config = array\(.*?\);', $cache_str); + + return $config; +} + +// Update config cache file +function config_cache_write($match, $data) +{ + global $phpbb_root_path, $phpEx, $user; + + if (!is_writeable($phpbb_root_path . 'config_cache.'.$phpEx)) + { + trigger_error($user->lang['Cache_writeable']); + } + + if (!($fp = @fopen($phpbb_root_path . 'config_cache.'.$phpEx, 'r+'))) + { + trigger_error('Failed opening config_cache. Please ensure the file exists', E_USER_ERROR); + } + + $config_file = fread($fp, filesize($phpbb_root_path . 'config_cache.'.$phpEx)); + + fseek($fp, 0); + @flock($fp, LOCK_EX); + if (!fwrite($fp, preg_replace('#' . $match . '#s', $data, $config_file))) + { + trigger_error('Could not write out config data to cache', E_USER_ERROR); + } + @flock($fp, LOCK_UN); + fclose($fp); + + return; +} + // Extension of auth class for changing permissions class auth_admin extends auth { - // Note that the set/delete methods are basically the same - // so if possible they should be merged + // Set a user or group ACL record function acl_set($mode, &$forum_id, &$ug_id, &$auth) { global $db; + // Set any flags as required + foreach ($auth as $auth_value => $allow) + { + $flag = substr($auth_value, 0, strpos($auth_value, '_') + 1); + if ( empty($auth[$flag]) ) + { + $auth[$flag] = $allow; + } + } + + $sql = "SELECT auth_option_id, auth_value + FROM " . ACL_OPTIONS_TABLE; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $option_ids[$row['auth_value']] = $row['auth_option_id']; + } + $db->sql_freeresult($result); + + // One or more forums if ( !is_array($forum_id) ) { $forum_id = array($forum_id); @@ -426,8 +507,10 @@ class auth_admin extends auth foreach ( $forum_id as $forum) { - foreach ( $auth as $auth_option_id => $allow ) + foreach ( $auth as $auth_value => $allow ) { + $auth_option_id = $option_ids[$auth_value]; + if ( !empty($cur_auth[$forum]) ) { $sql_ary[] = ( !isset($cur_auth[$forum][$auth_option_id]) ) ? "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_allow_deny) VALUES ($ug_id, $forum, $auth_option_id, $allow)" : ( ( $cur_auth[$forum][$auth_option_id] != $allow ) ? "UPDATE " . $table . " SET auth_allow_deny = $allow WHERE $id_field = $ug_id AND forum_id = $forum AND auth_option_id = $auth_option_id" : '' ); @@ -459,7 +542,7 @@ class auth_admin extends auth global $db; $auth_sql = ''; - if ( $auth_ids ) + if ($auth_ids) { for($i = 0; $i < count($auth_ids); $i++) { @@ -480,34 +563,113 @@ class auth_admin extends auth $this->acl_clear_prefetch(); } - function acl_clear_prefetch() + function acl_clear_prefetch($user_id = false) { global $db; + $where_sql = ( $user_id ) ? "WHERE user_id = $user_id" : ''; + $sql = "UPDATE " . USERS_TABLE . " - SET user_permissions = ''"; + SET user_permissions = '' + $where_sql"; $db->sql_query($sql); return; } - function acl_add_option($options) + function acl_add_option($new_options) { global $db; - if ( !is_array($options) ) + if (!is_array($new_options)) { - message_die(ERROR, 'Incorrect parameter for acl_add_option'); + trigger_error('Incorrect parameter for acl_add_option', E_USER_ERROR); } - // If we go with the | GLOBAL | FORUM | setup the array - // needs to be a hash setup appropriately. We then need - // to insert each new option with an appropriate global - // or local id - // - // If we stay with the current | FORUM | setup the array - // need not be a hash. Each entry would simply be inserted + $options = array(); + + $sql = "SELECT auth_value, is_global, is_local + FROM " . ACL_OPTIONS_TABLE . " + ORDER BY is_global, is_local, auth_value"; + $result = $db->sql_query($sql); + + while ( $row = $db->sql_fetchrow($result) ) + { + if ( isset($row['is_global']) ) + { + $options['global'][] = $row['auth_value']; + } + if ( isset($row['is_local']) ) + { + $options['local'][] = $row['auth_value']; + } + } + $db->sql_freeresult($result); + + if (!is_array($options)) + { + trigger_error('Incorrect parameter for acl_add_option', E_USER_ERROR); + } + + // Here we need to insert new options ... this requires + // discovering whether an options is global, local or both + // and whether we need to add an option type flag (x_) + foreach ($new_options as $type => $option_ary) + { + foreach ($option_ary as $option_value) + { + $options[$type][] = $option_value; + } + } + + acl_cache_options($options); + } + + function acl_cache_options($options = false) + { + global $db; + + $options = array(); + + if ( !$options ) + { + $sql = "SELECT auth_value, is_global, is_local + FROM " . ACL_OPTIONS_TABLE . " + ORDER BY is_global, is_local, auth_value"; + $result = $db->sql_query($sql); + + $global = $local = 0; + while ( $row = $db->sql_fetchrow($result) ) + { + if ( !empty($row['is_global']) ) + { + $options['global'][$row['auth_value']] = $global++; + } + if ( !empty($row['is_local']) ) + { + $options['local'][$row['auth_value']] = $local++; + } + } + $db->sql_freeresult($result); + } + + // Re-cache options + $cache_str = "\$acl_options = array(\n"; + foreach ($options as $type => $options_ary) + { + $cache_str .= "\t'$type' => array(\n"; + foreach ($options_ary as $option_value => $option_id) + { + $cache_str .= "\t\t'$option_value' => " . $option_id . ",\n"; + } + $cache_str .= "\t),\n"; + } + $cache_str .= ");"; + + config_cache_write('\$acl_options = array\(.*?\);', $cache_str); + $this->acl_clear_prefetch(); + return $options; } } diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index 18bd69f4ea..0a17b59a55 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -468,7 +468,7 @@ class auth var $acl = array(); var $acl_options = array(); - function acl(&$userdata, $forum_id = false, $options_in = false, $options_or = false) + function acl(&$userdata, $forum_id = false) { global $db, $acl_options; @@ -478,87 +478,7 @@ class auth { // $mtime = explode(' ', microtime()); // $starttime = $mtime[1] + $mtime[0]; -/* - $in_sql = "'a_', 'f_list'"; - $or_sql = ''; - - if ( is_array($options_in) ) - { - foreach ( $options_in as $option ) - { - $in_sql .= ", '$option'"; - } - } - if ( is_array($options_or) ) - { - foreach ( $options_or as $option ) - { - $or_sql .= " OR auth_value LIKE '$option%'"; - } - } - -// $mtime = explode(' ', microtime()); -// $starttime = $mtime[1] + $mtime[0]; - - // The possible alternative here is to store the options in a file - // (perhaps with the other config data) and do away with this query. - $sql = "SELECT auth_option_id, auth_value - FROM " . ACL_OPTIONS_TABLE . " - WHERE auth_value IN ($in_sql) $or_sql"; - $result = $db->sql_query($sql); - - while ( $row = $db->sql_fetchrow($result) ) - { - $this->options[$row['auth_value']] = $row['auth_option_id']; - } - $db->sql_freeresult($result); - -// $mtime = explode(' ', microtime()); -// echo $mtime[1] + $mtime[0] - $starttime . " :: "; - - // This is preliminary and can no doubt be improved. The 12 in - // the chunk_split relates to the current 96bits (12 bytes) per forum - if ( !empty($userdata['user_permissions']) ) - { - $permissions = explode("\r\n", chunk_split($userdata['user_permissions'], 12)); - - foreach ( $permissions as $data ) - { - $temp = explode("\r\n", chunk_split($data, 1)); - - $forum_id = bindec(str_pad(decbin(ord(array_shift($temp))), 8, 0, STR_PAD_LEFT) . str_pad(decbin(ord(array_shift($temp))), 8, 0, STR_PAD_LEFT)); - - foreach ( $temp as $char ) - { - $this->acl[$forum_id] .= str_pad(decbin(ord($char)), 8, 0, STR_PAD_LEFT); - } - } - } - else - { - $this->acl_cache($userdata); - } - -/* - $sql = "SELECT auth_value, global_id, local_id - FROM " . ACL_OPTIONS_TABLE . " - WHERE auth_value IN ($in_sql) $or_sql"; - $result = $db->sql_query($sql); - - while ( $row = $db->sql_fetchrow($result) ) - { - if ( isset($row['global_id']) ) - { - $this->options['global'][$row['auth_value']] = $row['global_id']; - } - if ( isset($row['local_id']) ) - { - $this->options['local'][$row['auth_value']] = $row['local_id']; - } - } - $db->sql_freeresult($result); -*/ if ( empty($userdata['user_permissions']) ) { $this->acl_cache($userdata); @@ -579,7 +499,7 @@ class auth array_pop($forums); foreach ( $forums as $forum ) { - $forum_id = bindec(str_pad(decbin(ord(substr($forum, 0, 1))), 8, 0, STR_PAD_LEFT) . str_pad(decbin(ord(substr($forum, 1, 1))), 8, 0, STR_PAD_LEFT)); + $forum_id = bindec(decbin(ord(substr($forum, 0, 1))) . str_pad(decbin(ord(substr($forum, 1, 1))), 8, 0, STR_PAD_LEFT)); for($i = 2; $i < $local_chars; $i++) { @@ -599,12 +519,7 @@ class auth function acl_get($option, $forum_id = 0) { static $acl_cache; -/* - if ( !isset($acl_cache[$forum_id][$option]) && !$this->founder ) - { - $acl_cache[$forum_id][$option] = substr($this->acl[$forum_id], $this->options[$option], 1); - } -*/ + if ( !isset($acl_cache[$forum_id][$option]) && !$this->founder ) { if ( isset($this->acl_options['global'][$option]) ) @@ -655,31 +570,6 @@ class auth if ( is_array($acl_db) ) { sort($acl_db); -/* foreach ( $acl_db as $row ) - { - if ( $row['auth_allow_deny'] != ACL_INHERIT && $this->acl[$row['forum_id']][$row['auth_value']] !== ACL_DENY ) - { - $this->acl[$row['forum_id']][$row['auth_option_id']] = intval($row['auth_allow_deny']); - } - } - unset($acl_db); - - foreach ( $this->acl as $forum_id => $auth_ary ) - { - $holding = array(); - for($i = 0; $i < 80; $i++) - { - $holding[] = ( isset($this->acl[$forum_id][$i]) ) ? $this->acl[$forum_id][$i] : 0; - } - - $bitstring = explode("\r\n", chunk_split(str_pad(decbin($forum_id), 16, 0, STR_PAD_LEFT) . implode('', $holding), 8)); - array_pop($bitstring); - foreach ( $bitstring as $byte ) - { - $userdata['user_permissions'] .= chr(bindec($byte)); - } - } - unset($holding);*/ foreach ( $acl_db as $row ) { @@ -698,6 +588,7 @@ class auth foreach ( $this->acl as $forum_id => $auth_ary ) { $holding = array(); + $option_set = array(); if ( !$forum_id ) { @@ -722,6 +613,12 @@ class auth if ( $allow ) { $holding[$this->acl_options[$ary_key][$option]] = 1; + + $option_key = substr($option, 0, strpos($option, '_') + 1); + if ( empty($holding[$this->acl_options[$ary_key][$option_key]]) ) + { + $holding[$this->acl_options[$ary_key][$option_key]] = 1; + } } } -- cgit v1.2.1