Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

auth.php

Zuletzt modifiziert: 09.10.2024, 12:52 - Dateigröße: 38.56 KiB


0001  <?php
0002  /**
0003  *
0004  * This file is part of the phpBB Forum Software package.
0005  *
0006  * @copyright (c) phpBB Limited <https://www.phpbb.com>
0007  * @license GNU General Public License, version 2 (GPL-2.0)
0008  *
0009  * For full copyright and license information, please see
0010  * the docs/CREDITS.txt file.
0011  *
0012  */
0013   
0014  /**
0015  * @ignore
0016  */
0017  if (!defined('IN_PHPBB'))
0018  {
0019      exit;
0020  }
0021   
0022  /**
0023  * ACP Permission/Auth class
0024  */
0025  class auth_admin extends \phpbb\auth\auth
0026  {
0027      /**
0028      * Init auth settings
0029      */
0030      function auth_admin()
0031      {
0032          global $db, $cache;
0033   
0034          if (($this->acl_options = $cache->get('_acl_options')) === false)
0035          {
0036              $sql = 'SELECT auth_option_id, auth_option, is_global, is_local
0037                  FROM ' . ACL_OPTIONS_TABLE . '
0038                  ORDER BY auth_option_id';
0039              $result = $db->sql_query($sql);
0040   
0041              $global = $local = 0;
0042              $this->acl_options = array();
0043              while ($row = $db->sql_fetchrow($result))
0044              {
0045                  if ($row['is_global'])
0046                  {
0047                      $this->acl_options['global'][$row['auth_option']] = $global++;
0048                  }
0049   
0050                  if ($row['is_local'])
0051                  {
0052                      $this->acl_options['local'][$row['auth_option']] = $local++;
0053                  }
0054   
0055                  $this->acl_options['id'][$row['auth_option']] = (int) $row['auth_option_id'];
0056                  $this->acl_options['option'][(int) $row['auth_option_id']] = $row['auth_option'];
0057              }
0058              $db->sql_freeresult($result);
0059   
0060              $cache->put('_acl_options', $this->acl_options);
0061          }
0062      }
0063   
0064      /**
0065      * Get permission mask
0066      * This function only supports getting permissions of one type (for example a_)
0067      *
0068      * @param set|view $mode defines the permissions we get, view gets effective permissions (checking user AND group permissions), set only gets the user or group permission set alone
0069      * @param mixed $user_id user ids to search for (a user_id or a group_id has to be specified at least)
0070      * @param mixed $group_id group ids to search for, return group related settings (a user_id or a group_id has to be specified at least)
0071      * @param mixed $forum_id forum_ids to search for. Defining a forum id also means getting local settings
0072      * @param string $auth_option the auth_option defines the permission setting to look for (a_ for example)
0073      * @param local|global $scope the scope defines the permission scope. If local, a forum_id is additionally required
0074      * @param ACL_NEVER|ACL_NO|ACL_YES $acl_fill defines the mode those permissions not set are getting filled with
0075      */
0076      function get_mask($mode, $user_id = false, $group_id = false, $forum_id = false, $auth_option = false, $scope = false, $acl_fill = ACL_NEVER)
0077      {
0078          global $db, $user;
0079   
0080          $hold_ary = array();
0081          $view_user_mask = ($mode == 'view' && $group_id === false) ? true : false;
0082   
0083          if ($auth_option === false || $scope === false)
0084          {
0085              return array();
0086          }
0087   
0088          $acl_user_function = ($mode == 'set') ? 'acl_user_raw_data' : 'acl_raw_data';
0089   
0090          if (!$view_user_mask)
0091          {
0092              if ($forum_id !== false)
0093              {
0094                  $hold_ary = ($group_id !== false) ? $this->acl_group_raw_data($group_id, $auth_option . '%', $forum_id) : $this->$acl_user_function($user_id, $auth_option . '%', $forum_id);
0095              }
0096              else
0097              {
0098                  $hold_ary = ($group_id !== false) ? $this->acl_group_raw_data($group_id, $auth_option . '%', ($scope == 'global') ? 0 : false) : $this->$acl_user_function($user_id, $auth_option . '%', ($scope == 'global') ? 0 : false);
0099              }
0100          }
0101   
0102          // Make sure hold_ary is filled with every setting (prevents missing forums/users/groups)
0103          $ug_id = ($group_id !== false) ? ((!is_array($group_id)) ? array($group_id) : $group_id) : ((!is_array($user_id)) ? array($user_id) : $user_id);
0104          $forum_ids = ($forum_id !== false) ? ((!is_array($forum_id)) ? array($forum_id) : $forum_id) : (($scope == 'global') ? array(0) : array());
0105   
0106          // Only those options we need
0107          $compare_options = array_diff(preg_replace('/^((?!' . $auth_option . ').+)|(' . $auth_option . ')$/', '', array_keys($this->acl_options[$scope])), array(''));
0108   
0109          // If forum_ids is false and the scope is local we actually want to have all forums within the array
0110          if ($scope == 'local' && !sizeof($forum_ids))
0111          {
0112              $sql = 'SELECT forum_id
0113                  FROM ' . FORUMS_TABLE;
0114              $result = $db->sql_query($sql, 120);
0115   
0116              while ($row = $db->sql_fetchrow($result))
0117              {
0118                  $forum_ids[] = (int) $row['forum_id'];
0119              }
0120              $db->sql_freeresult($result);
0121          }
0122   
0123          if ($view_user_mask)
0124          {
0125              $auth2 = null;
0126   
0127              $sql = 'SELECT user_id, user_permissions, user_type
0128                  FROM ' . USERS_TABLE . '
0129                  WHERE ' . $db->sql_in_set('user_id', $ug_id);
0130              $result = $db->sql_query($sql);
0131   
0132              while ($userdata = $db->sql_fetchrow($result))
0133              {
0134                  if ($user->data['user_id'] != $userdata['user_id'])
0135                  {
0136                      $auth2 = new \phpbb\auth\auth();
0137                      $auth2->acl($userdata);
0138                  }
0139                  else
0140                  {
0141                      global $auth;
0142                      $auth2 = &$auth;
0143                  }
0144   
0145                  $hold_ary[$userdata['user_id']] = array();
0146                  foreach ($forum_ids as $f_id)
0147                  {
0148                      $hold_ary[$userdata['user_id']][$f_id] = array();
0149                      foreach ($compare_options as $option)
0150                      {
0151                          $hold_ary[$userdata['user_id']][$f_id][$option] = $auth2->acl_get($option, $f_id);
0152                      }
0153                  }
0154              }
0155              $db->sql_freeresult($result);
0156   
0157              unset($userdata);
0158              unset($auth2);
0159          }
0160   
0161          foreach ($ug_id as $_id)
0162          {
0163              if (!isset($hold_ary[$_id]))
0164              {
0165                  $hold_ary[$_id] = array();
0166              }
0167   
0168              foreach ($forum_ids as $f_id)
0169              {
0170                  if (!isset($hold_ary[$_id][$f_id]))
0171                  {
0172                      $hold_ary[$_id][$f_id] = array();
0173                  }
0174              }
0175          }
0176   
0177          // Now, we need to fill the gaps with $acl_fill. ;)
0178   
0179          // Now switch back to keys
0180          if (sizeof($compare_options))
0181          {
0182              $compare_options = array_combine($compare_options, array_fill(1, sizeof($compare_options), $acl_fill));
0183          }
0184   
0185          // Defining the user-function here to save some memory
0186          $return_acl_fill = function () use ($acl_fill)
0187          {
0188              return $acl_fill;
0189          };
0190   
0191          // Actually fill the gaps
0192          if (sizeof($hold_ary))
0193          {
0194              foreach ($hold_ary as $ug_id => $row)
0195              {
0196                  foreach ($row as $id => $options)
0197                  {
0198                      // Do not include the global auth_option
0199                      unset($options[$auth_option]);
0200   
0201                      // Not a "fine" solution, but at all it's a 1-dimensional
0202                      // array_diff_key function filling the resulting array values with zeros
0203                      // The differences get merged into $hold_ary (all permissions having $acl_fill set)
0204                      $hold_ary[$ug_id][$id] = array_merge($options,
0205   
0206                          array_map($return_acl_fill,
0207                              array_flip(
0208                                  array_diff(
0209                                      array_keys($compare_options), array_keys($options)
0210                                  )
0211                              )
0212                          )
0213                      );
0214                  }
0215              }
0216          }
0217          else
0218          {
0219              $hold_ary[($group_id !== false) ? $group_id : $user_id][(int) $forum_id] = $compare_options;
0220          }
0221   
0222          return $hold_ary;
0223      }
0224   
0225      /**
0226      * Get permission mask for roles
0227      * This function only supports getting masks for one role
0228      */
0229      function get_role_mask($role_id)
0230      {
0231          global $db;
0232   
0233          $hold_ary = array();
0234   
0235          // Get users having this role set...
0236          $sql = 'SELECT user_id, forum_id
0237              FROM ' . ACL_USERS_TABLE . '
0238              WHERE auth_role_id = ' . $role_id . '
0239              ORDER BY forum_id';
0240          $result = $db->sql_query($sql);
0241   
0242          while ($row = $db->sql_fetchrow($result))
0243          {
0244              $hold_ary[$row['forum_id']]['users'][] = $row['user_id'];
0245          }
0246          $db->sql_freeresult($result);
0247   
0248          // Now grab groups...
0249          $sql = 'SELECT group_id, forum_id
0250              FROM ' . ACL_GROUPS_TABLE . '
0251              WHERE auth_role_id = ' . $role_id . '
0252              ORDER BY forum_id';
0253          $result = $db->sql_query($sql);
0254   
0255          while ($row = $db->sql_fetchrow($result))
0256          {
0257              $hold_ary[$row['forum_id']]['groups'][] = $row['group_id'];
0258          }
0259          $db->sql_freeresult($result);
0260   
0261          return $hold_ary;
0262      }
0263   
0264      /**
0265      * Display permission mask (assign to template)
0266      */
0267      function display_mask($mode, $permission_type, &$hold_ary, $user_mode = 'user', $local = false, $group_display = true)
0268      {
0269          global $template, $user, $db, $phpbb_container;
0270   
0271          /* @var $phpbb_permissions \phpbb\permissions */
0272          $phpbb_permissions = $phpbb_container->get('acl.permissions');
0273   
0274          /** @var \phpbb\group\helper $group_helper */
0275          $group_helper = $phpbb_container->get('group_helper');
0276   
0277          // Define names for template loops, might be able to be set
0278          $tpl_pmask = 'p_mask';
0279          $tpl_fmask = 'f_mask';
0280          $tpl_category = 'category';
0281          $tpl_mask = 'mask';
0282   
0283          $l_acl_type = $phpbb_permissions->get_type_lang($permission_type, (($local) ? 'local' : 'global'));
0284   
0285          // Allow trace for viewing permissions and in user mode
0286          $show_trace = ($mode == 'view' && $user_mode == 'user') ? true : false;
0287   
0288          // Get names
0289          if ($user_mode == 'user')
0290          {
0291              $sql = 'SELECT user_id as ug_id, username as ug_name
0292                  FROM ' . USERS_TABLE . '
0293                  WHERE ' . $db->sql_in_set('user_id', array_keys($hold_ary)) . '
0294                  ORDER BY username_clean ASC';
0295          }
0296          else
0297          {
0298              $sql = 'SELECT group_id as ug_id, group_name as ug_name, group_type
0299                  FROM ' . GROUPS_TABLE . '
0300                  WHERE ' . $db->sql_in_set('group_id', array_keys($hold_ary)) . '
0301                  ORDER BY group_type DESC, group_name ASC';
0302          }
0303          $result = $db->sql_query($sql);
0304   
0305          $ug_names_ary = array();
0306          while ($row = $db->sql_fetchrow($result))
0307          {
0308              $ug_names_ary[$row['ug_id']] = ($user_mode == 'user') ? $row['ug_name'] : $group_helper->get_name($row['ug_name']);
0309          }
0310          $db->sql_freeresult($result);
0311   
0312          // Get used forums
0313          $forum_ids = array();
0314          foreach ($hold_ary as $ug_id => $row)
0315          {
0316              $forum_ids = array_merge($forum_ids, array_keys($row));
0317          }
0318          $forum_ids = array_unique($forum_ids);
0319   
0320          $forum_names_ary = array();
0321          if ($local)
0322          {
0323              $forum_names_ary = make_forum_select(false, false, true, false, false, false, true);
0324   
0325              // Remove the disabled ones, since we do not create an option field here...
0326              foreach ($forum_names_ary as $key => $value)
0327              {
0328                  if (!$value['disabled'])
0329                  {
0330                      continue;
0331                  }
0332                  unset($forum_names_ary[$key]);
0333              }
0334          }
0335          else
0336          {
0337              $forum_names_ary[0] = $l_acl_type;
0338          }
0339   
0340          // Get available roles
0341          $sql = 'SELECT *
0342              FROM ' . ACL_ROLES_TABLE . "
0343              WHERE role_type = '" . $db->sql_escape($permission_type) . "'
0344              ORDER BY role_order ASC";
0345          $result = $db->sql_query($sql);
0346   
0347          $roles = array();
0348          while ($row = $db->sql_fetchrow($result))
0349          {
0350              $roles[$row['role_id']] = $row;
0351          }
0352          $db->sql_freeresult($result);
0353   
0354          $cur_roles = $this->acl_role_data($user_mode, $permission_type, array_keys($hold_ary));
0355   
0356          // Build js roles array (role data assignments)
0357          $s_role_js_array = '';
0358   
0359          if (sizeof($roles))
0360          {
0361              $s_role_js_array = array();
0362   
0363              // Make sure every role (even if empty) has its array defined
0364              foreach ($roles as $_role_id => $null)
0365              {
0366                  $s_role_js_array[$_role_id] = "\n" . 'role_options[' . $_role_id . '] = new Array();' . "\n";
0367              }
0368   
0369              $sql = 'SELECT r.role_id, o.auth_option, r.auth_setting
0370                  FROM ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' o
0371                  WHERE o.auth_option_id = r.auth_option_id
0372                      AND ' . $db->sql_in_set('r.role_id', array_keys($roles));
0373              $result = $db->sql_query($sql);
0374   
0375              while ($row = $db->sql_fetchrow($result))
0376              {
0377                  $flag = substr($row['auth_option'], 0, strpos($row['auth_option'], '_') + 1);
0378                  if ($flag == $row['auth_option'])
0379                  {
0380                      continue;
0381                  }
0382   
0383                  $s_role_js_array[$row['role_id']] .= 'role_options[' . $row['role_id'] . '][\'' . addslashes($row['auth_option']) . '\'] = ' . $row['auth_setting'] . '; ';
0384              }
0385              $db->sql_freeresult($result);
0386   
0387              $s_role_js_array = implode('', $s_role_js_array);
0388          }
0389   
0390          $template->assign_var('S_ROLE_JS_ARRAY', $s_role_js_array);
0391          unset($s_role_js_array);
0392   
0393          // Now obtain memberships
0394          $user_groups_default = $user_groups_custom = array();
0395          if ($user_mode == 'user' && $group_display)
0396          {
0397              $sql = 'SELECT group_id, group_name, group_type
0398                  FROM ' . GROUPS_TABLE . '
0399                  ORDER BY group_type DESC, group_name ASC';
0400              $result = $db->sql_query($sql);
0401   
0402              $groups = array();
0403              while ($row = $db->sql_fetchrow($result))
0404              {
0405                  $groups[$row['group_id']] = $row;
0406              }
0407              $db->sql_freeresult($result);
0408   
0409              $memberships = group_memberships(false, array_keys($hold_ary), false);
0410   
0411              // User is not a member of any group? Bad admin, bad bad admin...
0412              if ($memberships)
0413              {
0414                  foreach ($memberships as $row)
0415                  {
0416                      $user_groups_default[$row['user_id']][] = $group_helper->get_name($groups[$row['group_id']]['group_name']);
0417                  }
0418              }
0419              unset($memberships, $groups);
0420          }
0421   
0422          // If we only have one forum id to display or being in local mode and more than one user/group to display,
0423          // we switch the complete interface to group by user/usergroup instead of grouping by forum
0424          // To achieve this, we need to switch the array a bit
0425          if (sizeof($forum_ids) == 1 || ($local && sizeof($ug_names_ary) > 1))
0426          {
0427              $hold_ary_temp = $hold_ary;
0428              $hold_ary = array();
0429              foreach ($hold_ary_temp as $ug_id => $row)
0430              {
0431                  foreach ($forum_names_ary as $forum_id => $forum_row)
0432                  {
0433                      if (isset($row[$forum_id]))
0434                      {
0435                          $hold_ary[$forum_id][$ug_id] = $row[$forum_id];
0436                      }
0437                  }
0438              }
0439              unset($hold_ary_temp);
0440   
0441              foreach ($hold_ary as $forum_id => $forum_array)
0442              {
0443                  $content_array = $categories = array();
0444                  $this->build_permission_array($hold_ary[$forum_id], $content_array, $categories, array_keys($ug_names_ary));
0445   
0446                  $template->assign_block_vars($tpl_pmask, array(
0447                      'NAME'            => ($forum_id == 0) ? $forum_names_ary[0] : $forum_names_ary[$forum_id]['forum_name'],
0448                      'PADDING'        => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'],
0449   
0450                      'CATEGORIES'    => implode('</th><th>', $categories),
0451   
0452                      'L_ACL_TYPE'    => $l_acl_type,
0453   
0454                      'S_LOCAL'        => ($local) ? true : false,
0455                      'S_GLOBAL'        => (!$local) ? true : false,
0456                      'S_NUM_CATS'    => sizeof($categories),
0457                      'S_VIEW'        => ($mode == 'view') ? true : false,
0458                      'S_NUM_OBJECTS'    => sizeof($content_array),
0459                      'S_USER_MODE'    => ($user_mode == 'user') ? true : false,
0460                      'S_GROUP_MODE'    => ($user_mode == 'group') ? true : false)
0461                  );
0462   
0463                  @reset($content_array);
0464                  while (list($ug_id, $ug_array) = each($content_array))
0465                  {
0466                      // Build role dropdown options
0467                      $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0;
0468   
0469                      $role_options = array();
0470   
0471                      $s_role_options = '';
0472                      $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0;
0473   
0474                      @reset($roles);
0475                      while (list($role_id, $role_row) = each($roles))
0476                      {
0477                          $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']);
0478                          $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name'];
0479   
0480                          $title = ($role_description) ? ' title="' . $role_description . '"' : '';
0481                          $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>';
0482   
0483                          $role_options[] = array(
0484                              'ID'    => $role_id,
0485                              'ROLE_NAME'    => $role_name,
0486                              'TITLE'        => $role_description,
0487                              'SELECTED'    => $role_id == $current_role_id,
0488                          );
0489                      }
0490   
0491                      if ($s_role_options)
0492                      {
0493                          $s_role_options = '<option value="0"' . ((!$current_role_id) ? ' selected="selected"' : '') . ' title="' . htmlspecialchars($user->lang['NO_ROLE_ASSIGNED_EXPLAIN']) . '">' . $user->lang['NO_ROLE_ASSIGNED'] . '</option>' . $s_role_options;
0494                      }
0495   
0496                      if (!$current_role_id && $mode != 'view')
0497                      {
0498                          $s_custom_permissions = false;
0499   
0500                          foreach ($ug_array as $key => $value)
0501                          {
0502                              if ($value['S_NEVER'] || $value['S_YES'])
0503                              {
0504                                  $s_custom_permissions = true;
0505                                  break;
0506                              }
0507                          }
0508                      }
0509                      else
0510                      {
0511                          $s_custom_permissions = false;
0512                      }
0513   
0514                      $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array(
0515                          'NAME'                => $ug_names_ary[$ug_id],
0516                          'UG_ID'                => $ug_id,
0517                          'S_ROLE_OPTIONS'    => $s_role_options,
0518                          'S_CUSTOM'            => $s_custom_permissions,
0519                          'FORUM_ID'            => $forum_id,
0520                          'S_ROLE_ID'            => $current_role_id,
0521                      ));
0522   
0523                      $template->assign_block_vars_array($tpl_pmask . '.' . $tpl_fmask . '.role_options', $role_options);
0524   
0525                      $this->assign_cat_array($ug_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, ($mode == 'view'), $show_trace);
0526   
0527                      unset($content_array[$ug_id]);
0528                  }
0529   
0530                  unset($hold_ary[$forum_id]);
0531              }
0532          }
0533          else
0534          {
0535              foreach ($ug_names_ary as $ug_id => $ug_name)
0536              {
0537                  if (!isset($hold_ary[$ug_id]))
0538                  {
0539                      continue;
0540                  }
0541   
0542                  $content_array = $categories = array();
0543                  $this->build_permission_array($hold_ary[$ug_id], $content_array, $categories, array_keys($forum_names_ary));
0544   
0545                  $template->assign_block_vars($tpl_pmask, array(
0546                      'NAME'            => $ug_name,
0547                      'CATEGORIES'    => implode('</th><th>', $categories),
0548   
0549                      'USER_GROUPS_DEFAULT'    => ($user_mode == 'user' && isset($user_groups_default[$ug_id]) && sizeof($user_groups_default[$ug_id])) ? implode($user->lang['COMMA_SEPARATOR'], $user_groups_default[$ug_id]) : '',
0550                      'USER_GROUPS_CUSTOM'    => ($user_mode == 'user' && isset($user_groups_custom[$ug_id]) && sizeof($user_groups_custom[$ug_id])) ? implode($user->lang['COMMA_SEPARATOR'], $user_groups_custom[$ug_id]) : '',
0551                      'L_ACL_TYPE'            => $l_acl_type,
0552   
0553                      'S_LOCAL'        => ($local) ? true : false,
0554                      'S_GLOBAL'        => (!$local) ? true : false,
0555                      'S_NUM_CATS'    => sizeof($categories),
0556                      'S_VIEW'        => ($mode == 'view') ? true : false,
0557                      'S_NUM_OBJECTS'    => sizeof($content_array),
0558                      'S_USER_MODE'    => ($user_mode == 'user') ? true : false,
0559                      'S_GROUP_MODE'    => ($user_mode == 'group') ? true : false)
0560                  );
0561   
0562                  @reset($content_array);
0563                  while (list($forum_id, $forum_array) = each($content_array))
0564                  {
0565                      // Build role dropdown options
0566                      $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0;
0567   
0568                      $role_options = array();
0569   
0570                      $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0;
0571                      $s_role_options = '';
0572   
0573                      @reset($roles);
0574                      while (list($role_id, $role_row) = each($roles))
0575                      {
0576                          $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']);
0577                          $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name'];
0578   
0579                          $title = ($role_description) ? ' title="' . $role_description . '"' : '';
0580                          $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>';
0581   
0582                          $role_options[] = array(
0583                              'ID'    => $role_id,
0584                              'ROLE_NAME'    => $role_name,
0585                              'TITLE'        => $role_description,
0586                              'SELECTED'    => $role_id == $current_role_id,
0587                          );
0588                      }
0589   
0590                      if ($s_role_options)
0591                      {
0592                          $s_role_options = '<option value="0"' . ((!$current_role_id) ? ' selected="selected"' : '') . ' title="' . htmlspecialchars($user->lang['NO_ROLE_ASSIGNED_EXPLAIN']) . '">' . $user->lang['NO_ROLE_ASSIGNED'] . '</option>' . $s_role_options;
0593                      }
0594   
0595                      if (!$current_role_id && $mode != 'view')
0596                      {
0597                          $s_custom_permissions = false;
0598   
0599                          foreach ($forum_array as $key => $value)
0600                          {
0601                              if ($value['S_NEVER'] || $value['S_YES'])
0602                              {
0603                                  $s_custom_permissions = true;
0604                                  break;
0605                              }
0606                          }
0607                      }
0608                      else
0609                      {
0610                          $s_custom_permissions = false;
0611                      }
0612   
0613                      $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array(
0614                          'NAME'                => ($forum_id == 0) ? $forum_names_ary[0] : $forum_names_ary[$forum_id]['forum_name'],
0615                          'PADDING'            => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'],
0616                          'S_CUSTOM'            => $s_custom_permissions,
0617                          'UG_ID'                => $ug_id,
0618                          'S_ROLE_OPTIONS'    => $s_role_options,
0619                          'FORUM_ID'            => $forum_id)
0620                      );
0621   
0622                      $template->assign_block_vars_array($tpl_pmask . '.' . $tpl_fmask . '.role_options', $role_options);
0623   
0624                      $this->assign_cat_array($forum_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, ($mode == 'view'), $show_trace);
0625                  }
0626   
0627                  unset($hold_ary[$ug_id], $ug_names_ary[$ug_id]);
0628              }
0629          }
0630      }
0631   
0632      /**
0633      * Display permission mask for roles
0634      */
0635      function display_role_mask(&$hold_ary)
0636      {
0637          global $db, $template, $user, $phpbb_root_path, $phpEx;
0638          global $phpbb_container;
0639   
0640          if (!sizeof($hold_ary))
0641          {
0642              return;
0643          }
0644   
0645          /** @var \phpbb\group\helper $group_helper */
0646          $group_helper = $phpbb_container->get('group_helper');
0647   
0648          // Get forum names
0649          $sql = 'SELECT forum_id, forum_name
0650              FROM ' . FORUMS_TABLE . '
0651              WHERE ' . $db->sql_in_set('forum_id', array_keys($hold_ary)) . '
0652              ORDER BY left_id';
0653          $result = $db->sql_query($sql);
0654   
0655          // If the role is used globally, then reflect that
0656          $forum_names = (isset($hold_ary[0])) ? array(0 => '') : array();
0657          while ($row = $db->sql_fetchrow($result))
0658          {
0659              $forum_names[$row['forum_id']] = $row['forum_name'];
0660          }
0661          $db->sql_freeresult($result);
0662   
0663          foreach ($forum_names as $forum_id => $forum_name)
0664          {
0665              $auth_ary = $hold_ary[$forum_id];
0666   
0667              $template->assign_block_vars('role_mask', array(
0668                  'NAME'                => ($forum_id == 0) ? $user->lang['GLOBAL_MASK'] : $forum_name,
0669                  'FORUM_ID'            => $forum_id)
0670              );
0671   
0672              if (isset($auth_ary['users']) && sizeof($auth_ary['users']))
0673              {
0674                  $sql = 'SELECT user_id, username
0675                      FROM ' . USERS_TABLE . '
0676                      WHERE ' . $db->sql_in_set('user_id', $auth_ary['users']) . '
0677                      ORDER BY username_clean ASC';
0678                  $result = $db->sql_query($sql);
0679   
0680                  while ($row = $db->sql_fetchrow($result))
0681                  {
0682                      $template->assign_block_vars('role_mask.users', array(
0683                          'USER_ID'        => $row['user_id'],
0684                          'USERNAME'        => get_username_string('username', $row['user_id'], $row['username']),
0685                          'U_PROFILE'        => get_username_string('profile', $row['user_id'], $row['username']),
0686                      ));
0687                  }
0688                  $db->sql_freeresult($result);
0689              }
0690   
0691              if (isset($auth_ary['groups']) && sizeof($auth_ary['groups']))
0692              {
0693                  $sql = 'SELECT group_id, group_name, group_type
0694                      FROM ' . GROUPS_TABLE . '
0695                      WHERE ' . $db->sql_in_set('group_id', $auth_ary['groups']) . '
0696                      ORDER BY group_type ASC, group_name';
0697                  $result = $db->sql_query($sql);
0698   
0699                  while ($row = $db->sql_fetchrow($result))
0700                  {
0701                      $template->assign_block_vars('role_mask.groups', array(
0702                          'GROUP_ID'        => $row['group_id'],
0703                          'GROUP_NAME'    => $group_helper->get_name($row['group_name']),
0704                          'U_PROFILE'        => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=group&amp;g={$row['group_id']}"))
0705                      );
0706                  }
0707                  $db->sql_freeresult($result);
0708              }
0709          }
0710      }
0711   
0712      /**
0713      * NOTE: this function is not in use atm
0714      * Add a new option to the list ... $options is a hash of form ->
0715      * $options = array(
0716      *    'local'        => array('option1', 'option2', ...),
0717      *    'global'    => array('optionA', 'optionB', ...)
0718      * );
0719      */
0720      function acl_add_option($options)
0721      {
0722          global $db, $cache;
0723   
0724          if (!is_array($options))
0725          {
0726              return false;
0727          }
0728   
0729          $cur_options = array();
0730   
0731          // Determine current options
0732          $sql = 'SELECT auth_option, is_global, is_local
0733              FROM ' . ACL_OPTIONS_TABLE . '
0734              ORDER BY auth_option_id';
0735          $result = $db->sql_query($sql);
0736   
0737          while ($row = $db->sql_fetchrow($result))
0738          {
0739              $cur_options[$row['auth_option']] = ($row['is_global'] && $row['is_local']) ? 'both' : (($row['is_global']) ? 'global' : 'local');
0740          }
0741          $db->sql_freeresult($result);
0742   
0743          // Here we need to insert new options ... this requires discovering whether
0744          // an options is global, local or both and whether we need to add an permission
0745          // set flag (x_)
0746          $new_options = array('local' => array(), 'global' => array());
0747   
0748          foreach ($options as $type => $option_ary)
0749          {
0750              $option_ary = array_unique($option_ary);
0751   
0752              foreach ($option_ary as $option_value)
0753              {
0754                  $new_options[$type][] = $option_value;
0755   
0756                  $flag = substr($option_value, 0, strpos($option_value, '_') + 1);
0757   
0758                  if (!in_array($flag, $new_options[$type]))
0759                  {
0760                      $new_options[$type][] = $flag;
0761                  }
0762              }
0763          }
0764          unset($options);
0765   
0766          $options = array();
0767          $options['local'] = array_diff($new_options['local'], $new_options['global']);
0768          $options['global'] = array_diff($new_options['global'], $new_options['local']);
0769          $options['both'] = array_intersect($new_options['local'], $new_options['global']);
0770   
0771          // Now check which options to add/update
0772          $add_options = $update_options = array();
0773   
0774          // First local ones...
0775          foreach ($options as $type => $option_ary)
0776          {
0777              foreach ($option_ary as $option)
0778              {
0779                  if (!isset($cur_options[$option]))
0780                  {
0781                      $add_options[] = array(
0782                          'auth_option'    => (string) $option,
0783                          'is_global'        => ($type == 'global' || $type == 'both') ? 1 : 0,
0784                          'is_local'        => ($type == 'local' || $type == 'both') ? 1 : 0
0785                      );
0786   
0787                      continue;
0788                  }
0789   
0790                  // Else, update existing entry if it is changed...
0791                  if ($type === $cur_options[$option])
0792                  {
0793                      continue;
0794                  }
0795   
0796                  // New type is always both:
0797                  // If is now both, we set both.
0798                  // If it was global the new one is local and we need to set it to both
0799                  // If it was local the new one is global and we need to set it to both
0800                  $update_options[] = $option;
0801              }
0802          }
0803   
0804          if (!empty($add_options))
0805          {
0806              $db->sql_multi_insert(ACL_OPTIONS_TABLE, $add_options);
0807          }
0808   
0809          if (!empty($update_options))
0810          {
0811              $sql = 'UPDATE ' . ACL_OPTIONS_TABLE . '
0812                  SET is_global = 1, is_local = 1
0813                  WHERE ' . $db->sql_in_set('auth_option', $update_options);
0814              $db->sql_query($sql);
0815          }
0816   
0817          $cache->destroy('_acl_options');
0818          $this->acl_clear_prefetch();
0819   
0820          // Because we just changed the options and also purged the options cache, we instantly update/regenerate it for later calls to succeed.
0821          $this->acl_options = array();
0822          $this->auth_admin();
0823   
0824          return true;
0825      }
0826   
0827      /**
0828      * Set a user or group ACL record
0829      */
0830      function acl_set($ug_type, $forum_id, $ug_id, $auth, $role_id = 0, $clear_prefetch = true)
0831      {
0832          global $db;
0833   
0834          // One or more forums
0835          if (!is_array($forum_id))
0836          {
0837              $forum_id = array($forum_id);
0838          }
0839   
0840          // One or more users
0841          if (!is_array($ug_id))
0842          {
0843              $ug_id = array($ug_id);
0844          }
0845   
0846          $ug_id_sql = $db->sql_in_set($ug_type . '_id', array_map('intval', $ug_id));
0847          $forum_sql = $db->sql_in_set('forum_id', array_map('intval', $forum_id));
0848   
0849          // Instead of updating, inserting, removing we just remove all current settings and re-set everything...
0850          $table = ($ug_type == 'user') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE;
0851          $id_field = $ug_type . '_id';
0852   
0853          // Get any flags as required
0854          reset($auth);
0855          $flag = key($auth);
0856          $flag = substr($flag, 0, strpos($flag, '_') + 1);
0857   
0858          // This ID (the any-flag) is set if one or more permissions are true...
0859          $any_option_id = (int) $this->acl_options['id'][$flag];
0860   
0861          // Remove any-flag from auth ary
0862          if (isset($auth[$flag]))
0863          {
0864              unset($auth[$flag]);
0865          }
0866   
0867          // Remove current auth options...
0868          $auth_option_ids = array((int) $any_option_id);
0869          foreach ($auth as $auth_option => $auth_setting)
0870          {
0871              $auth_option_ids[] = (int) $this->acl_options['id'][$auth_option];
0872          }
0873   
0874          $sql = "DELETE FROM $table
0875              WHERE $forum_sql
0876                  AND $ug_id_sql
0877                  AND " . $db->sql_in_set('auth_option_id', $auth_option_ids);
0878          $db->sql_query($sql);
0879   
0880          // Remove those having a role assigned... the correct type of course...
0881          $sql = 'SELECT role_id
0882              FROM ' . ACL_ROLES_TABLE . "
0883              WHERE role_type = '" . $db->sql_escape($flag) . "'";
0884          $result = $db->sql_query($sql);
0885   
0886          $role_ids = array();
0887          while ($row = $db->sql_fetchrow($result))
0888          {
0889              $role_ids[] = $row['role_id'];
0890          }
0891          $db->sql_freeresult($result);
0892   
0893          if (sizeof($role_ids))
0894          {
0895              $sql = "DELETE FROM $table
0896                  WHERE $forum_sql
0897                      AND $ug_id_sql
0898                      AND auth_option_id = 0
0899                      AND " . $db->sql_in_set('auth_role_id', $role_ids);
0900              $db->sql_query($sql);
0901          }
0902   
0903          // Ok, include the any-flag if one or more auth options are set to yes...
0904          foreach ($auth as $auth_option => $setting)
0905          {
0906              if ($setting == ACL_YES && (!isset($auth[$flag]) || $auth[$flag] == ACL_NEVER))
0907              {
0908                  $auth[$flag] = ACL_YES;
0909              }
0910          }
0911   
0912          $sql_ary = array();
0913          foreach ($forum_id as $forum)
0914          {
0915              $forum = (int) $forum;
0916   
0917              if ($role_id)
0918              {
0919                  foreach ($ug_id as $id)
0920                  {
0921                      $sql_ary[] = array(
0922                          $id_field            => (int) $id,
0923                          'forum_id'            => (int) $forum,
0924                          'auth_option_id'    => 0,
0925                          'auth_setting'        => 0,
0926                          'auth_role_id'        => (int) $role_id,
0927                      );
0928                  }
0929              }
0930              else
0931              {
0932                  foreach ($auth as $auth_option => $setting)
0933                  {
0934                      $auth_option_id = (int) $this->acl_options['id'][$auth_option];
0935   
0936                      if ($setting != ACL_NO)
0937                      {
0938                          foreach ($ug_id as $id)
0939                          {
0940                              $sql_ary[] = array(
0941                                  $id_field            => (int) $id,
0942                                  'forum_id'            => (int) $forum,
0943                                  'auth_option_id'    => (int) $auth_option_id,
0944                                  'auth_setting'        => (int) $setting
0945                              );
0946                          }
0947                      }
0948                  }
0949              }
0950          }
0951   
0952          $db->sql_multi_insert($table, $sql_ary);
0953   
0954          if ($clear_prefetch)
0955          {
0956              $this->acl_clear_prefetch();
0957          }
0958      }
0959   
0960      /**
0961      * Set a role-specific ACL record
0962      */
0963      function acl_set_role($role_id, $auth)
0964      {
0965          global $db;
0966   
0967          // Get any-flag as required
0968          reset($auth);
0969          $flag = key($auth);
0970          $flag = substr($flag, 0, strpos($flag, '_') + 1);
0971   
0972          // Remove any-flag from auth ary
0973          if (isset($auth[$flag]))
0974          {
0975              unset($auth[$flag]);
0976          }
0977   
0978          // Re-set any flag...
0979          foreach ($auth as $auth_option => $setting)
0980          {
0981              if ($setting == ACL_YES && (!isset($auth[$flag]) || $auth[$flag] == ACL_NEVER))
0982              {
0983                  $auth[$flag] = ACL_YES;
0984              }
0985          }
0986   
0987          $sql_ary = array();
0988          foreach ($auth as $auth_option => $setting)
0989          {
0990              $auth_option_id = (int) $this->acl_options['id'][$auth_option];
0991   
0992              if ($setting != ACL_NO)
0993              {
0994                  $sql_ary[] = array(
0995                      'role_id'            => (int) $role_id,
0996                      'auth_option_id'    => (int) $auth_option_id,
0997                      'auth_setting'        => (int) $setting
0998                  );
0999              }
1000          }
1001   
1002          // If no data is there, we set the any-flag to ACL_NEVER...
1003          if (!sizeof($sql_ary))
1004          {
1005              $sql_ary[] = array(
1006                  'role_id'            => (int) $role_id,
1007                  'auth_option_id'    => (int) $this->acl_options['id'][$flag],
1008                  'auth_setting'        => ACL_NEVER
1009              );
1010          }
1011   
1012          // Remove current auth options...
1013          $sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . '
1014              WHERE role_id = ' . $role_id;
1015          $db->sql_query($sql);
1016   
1017          // Now insert the new values
1018          $db->sql_multi_insert(ACL_ROLES_DATA_TABLE, $sql_ary);
1019   
1020          $this->acl_clear_prefetch();
1021      }
1022   
1023      /**
1024      * Remove local permission
1025      */
1026      function acl_delete($mode, $ug_id = false, $forum_id = false, $permission_type = false)
1027      {
1028          global $db;
1029   
1030          if ($ug_id === false && $forum_id === false)
1031          {
1032              return;
1033          }
1034   
1035          $option_id_ary = array();
1036          $table = ($mode == 'user') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE;
1037          $id_field = $mode . '_id';
1038   
1039          $where_sql = array();
1040   
1041          if ($forum_id !== false)
1042          {
1043              $where_sql[] = (!is_array($forum_id)) ? 'forum_id = ' . (int) $forum_id : $db->sql_in_set('forum_id', array_map('intval', $forum_id));
1044          }
1045   
1046          if ($ug_id !== false)
1047          {
1048              $where_sql[] = (!is_array($ug_id)) ? $id_field . ' = ' . (int) $ug_id : $db->sql_in_set($id_field, array_map('intval', $ug_id));
1049          }
1050   
1051          // There seem to be auth options involved, therefore we need to go through the list and make sure we capture roles correctly
1052          if ($permission_type !== false)
1053          {
1054              // Get permission type
1055              $sql = 'SELECT auth_option, auth_option_id
1056                  FROM ' . ACL_OPTIONS_TABLE . "
1057                  WHERE auth_option " . $db->sql_like_expression($permission_type . $db->get_any_char());
1058              $result = $db->sql_query($sql);
1059   
1060              $auth_id_ary = array();
1061              while ($row = $db->sql_fetchrow($result))
1062              {
1063                  $option_id_ary[] = $row['auth_option_id'];
1064                  $auth_id_ary[$row['auth_option']] = ACL_NO;
1065              }
1066              $db->sql_freeresult($result);
1067   
1068              // First of all, lets grab the items having roles with the specified auth options assigned
1069              $sql = "SELECT auth_role_id, $id_field, forum_id
1070                  FROM $table" . ACL_ROLES_TABLE . " r
1071                  WHERE auth_role_id <> 0
1072                      AND auth_role_id = r.role_id
1073                      AND r.role_type = '{$permission_type}'
1074                      AND " . implode(' AND ', $where_sql) . '
1075                  ORDER BY auth_role_id';
1076              $result = $db->sql_query($sql);
1077   
1078              $cur_role_auth = array();
1079              while ($row = $db->sql_fetchrow($result))
1080              {
1081                  $cur_role_auth[$row['auth_role_id']][$row['forum_id']][] = $row[$id_field];
1082              }
1083              $db->sql_freeresult($result);
1084   
1085              // Get role data for resetting data
1086              if (sizeof($cur_role_auth))
1087              {
1088                  $sql = 'SELECT ao.auth_option, rd.role_id, rd.auth_setting
1089                      FROM ' . ACL_OPTIONS_TABLE . ' ao, ' . ACL_ROLES_DATA_TABLE . ' rd
1090                      WHERE ao.auth_option_id = rd.auth_option_id
1091                          AND ' . $db->sql_in_set('rd.role_id', array_keys($cur_role_auth));
1092                  $result = $db->sql_query($sql);
1093   
1094                  $auth_settings = array();
1095                  while ($row = $db->sql_fetchrow($result))
1096                  {
1097                      // We need to fill all auth_options, else setting it will fail...
1098                      if (!isset($auth_settings[$row['role_id']]))
1099                      {
1100                          $auth_settings[$row['role_id']] = $auth_id_ary;
1101                      }
1102                      $auth_settings[$row['role_id']][$row['auth_option']] = $row['auth_setting'];
1103                  }
1104                  $db->sql_freeresult($result);
1105   
1106                  // Set the options
1107                  foreach ($cur_role_auth as $role_id => $auth_row)
1108                  {
1109                      foreach ($auth_row as $f_id => $ug_row)
1110                      {
1111                          $this->acl_set($mode, $f_id, $ug_row, $auth_settings[$role_id], 0, false);
1112                      }
1113                  }
1114              }
1115          }
1116   
1117          // Now, normally remove permissions...
1118          if ($permission_type !== false)
1119          {
1120              $where_sql[] = $db->sql_in_set('auth_option_id', array_map('intval', $option_id_ary));
1121          }
1122   
1123          $sql = "DELETE FROM $table
1124              WHERE " . implode(' AND ', $where_sql);
1125          $db->sql_query($sql);
1126   
1127          $this->acl_clear_prefetch();
1128      }
1129   
1130      /**
1131      * Assign category to template
1132      * used by display_mask()
1133      */
1134      function assign_cat_array(&$category_array, $tpl_cat, $tpl_mask, $ug_id, $forum_id, $s_view, $show_trace = false)
1135      {
1136          global $template, $phpbb_admin_path, $phpEx, $phpbb_container;
1137   
1138          /* @var $phpbb_permissions \phpbb\permissions */
1139          $phpbb_permissions = $phpbb_container->get('acl.permissions');
1140   
1141          @reset($category_array);
1142          while (list($cat, $cat_array) = each($category_array))
1143          {
1144              if (!$phpbb_permissions->category_defined($cat))
1145              {
1146                  continue;
1147              }
1148   
1149              $template->assign_block_vars($tpl_cat, array(
1150                  'S_YES'        => ($cat_array['S_YES'] && !$cat_array['S_NEVER'] && !$cat_array['S_NO']) ? true : false,
1151                  'S_NEVER'    => ($cat_array['S_NEVER'] && !$cat_array['S_YES'] && !$cat_array['S_NO']) ? true : false,
1152                  'S_NO'        => ($cat_array['S_NO'] && !$cat_array['S_NEVER'] && !$cat_array['S_YES']) ? true : false,
1153   
1154                  'CAT_NAME'    => $phpbb_permissions->get_category_lang($cat),
1155              ));
1156   
1157              /*    Sort permissions by name (more naturaly and user friendly than sorting by a primary key)
1158              *    Commented out due to it's memory consumption and time needed
1159              *
1160              $key_array = array_intersect(array_keys($user->lang), array_map(create_function('$a', 'return "acl_" . $a;'), array_keys($cat_array['permissions'])));
1161              $values_array = $cat_array['permissions'];
1162   
1163              $cat_array['permissions'] = array();
1164   
1165              foreach ($key_array as $key)
1166              {
1167                  $key = str_replace('acl_', '', $key);
1168                  $cat_array['permissions'][$key] = $values_array[$key];
1169              }
1170              unset($key_array, $values_array);
1171  */
1172              @reset($cat_array['permissions']);
1173              while (list($permission, $allowed) = each($cat_array['permissions']))
1174              {
1175                  if (!$phpbb_permissions->permission_defined($permission))
1176                  {
1177                      continue;
1178                  }
1179   
1180                  if ($s_view)
1181                  {
1182                      $template->assign_block_vars($tpl_cat . '.' . $tpl_mask, array(
1183                          'S_YES'        => ($allowed == ACL_YES) ? true : false,
1184                          'S_NEVER'    => ($allowed == ACL_NEVER) ? true : false,
1185   
1186                          'UG_ID'            => $ug_id,
1187                          'FORUM_ID'        => $forum_id,
1188                          'FIELD_NAME'    => $permission,
1189                          'S_FIELD_NAME'    => 'setting[' . $ug_id . '][' . $forum_id . '][' . $permission . ']',
1190   
1191                          'U_TRACE'        => ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&amp;mode=trace&amp;u=$ug_id&amp;f=$forum_id&amp;auth=$permission") : '',
1192                          'UA_TRACE'        => ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission", false) : '',
1193   
1194                          'PERMISSION'    => $phpbb_permissions->get_permission_lang($permission),
1195                      ));
1196                  }
1197                  else
1198                  {
1199                      $template->assign_block_vars($tpl_cat . '.' . $tpl_mask, array(
1200                          'S_YES'        => ($allowed == ACL_YES) ? true : false,
1201                          'S_NEVER'    => ($allowed == ACL_NEVER) ? true : false,
1202                          'S_NO'        => ($allowed == ACL_NO) ? true : false,
1203   
1204                          'UG_ID'            => $ug_id,
1205                          'FORUM_ID'        => $forum_id,
1206                          'FIELD_NAME'    => $permission,
1207                          'S_FIELD_NAME'    => 'setting[' . $ug_id . '][' . $forum_id . '][' . $permission . ']',
1208   
1209                          'U_TRACE'        => ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&amp;mode=trace&amp;u=$ug_id&amp;f=$forum_id&amp;auth=$permission") : '',
1210                          'UA_TRACE'        => ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission", false) : '',
1211   
1212                          'PERMISSION'    => $phpbb_permissions->get_permission_lang($permission),
1213                      ));
1214                  }
1215              }
1216          }
1217      }
1218   
1219      /**
1220      * Building content array from permission rows with explicit key ordering
1221      * used by display_mask()
1222      */
1223      function build_permission_array(&$permission_row, &$content_array, &$categories, $key_sort_array)
1224      {
1225          global $phpbb_container;
1226   
1227          /* @var $phpbb_permissions \phpbb\permissions */
1228          $phpbb_permissions = $phpbb_container->get('acl.permissions');
1229   
1230          foreach ($key_sort_array as $forum_id)
1231          {
1232              if (!isset($permission_row[$forum_id]))
1233              {
1234                  continue;
1235              }
1236   
1237              $permissions = $permission_row[$forum_id];
1238              ksort($permissions);
1239   
1240              @reset($permissions);
1241              while (list($permission, $auth_setting) = each($permissions))
1242              {
1243                  $cat = $phpbb_permissions->get_permission_category($permission);
1244   
1245                  // Build our categories array
1246                  if (!isset($categories[$cat]))
1247                  {
1248                      $categories[$cat] = $phpbb_permissions->get_category_lang($cat);
1249                  }
1250   
1251                  // Build our content array
1252                  if (!isset($content_array[$forum_id]))
1253                  {
1254                      $content_array[$forum_id] = array();
1255                  }
1256   
1257                  if (!isset($content_array[$forum_id][$cat]))
1258                  {
1259                      $content_array[$forum_id][$cat] = array(
1260                          'S_YES'            => false,
1261                          'S_NEVER'        => false,
1262                          'S_NO'            => false,
1263                          'permissions'    => array(),
1264                      );
1265                  }
1266   
1267                  $content_array[$forum_id][$cat]['S_YES'] |= ($auth_setting == ACL_YES) ? true : false;
1268                  $content_array[$forum_id][$cat]['S_NEVER'] |= ($auth_setting == ACL_NEVER) ? true : false;
1269                  $content_array[$forum_id][$cat]['S_NO'] |= ($auth_setting == ACL_NO) ? true : false;
1270   
1271                  $content_array[$forum_id][$cat]['permissions'][$permission] = $auth_setting;
1272              }
1273          }
1274      }
1275   
1276      /**
1277      * Use permissions from another user. This transferes a permission set from one user to another.
1278      * The other user is always able to revert back to his permission set.
1279      * This function does not check for lower/higher permissions, it is possible for the user to gain
1280      * "more" permissions by this.
1281      * Admin permissions will not be copied.
1282      */
1283      function ghost_permissions($from_user_id, $to_user_id)
1284      {
1285          global $db;
1286   
1287          if ($to_user_id == ANONYMOUS)
1288          {
1289              return false;
1290          }
1291   
1292          $hold_ary = $this->acl_raw_data_single_user($from_user_id);
1293   
1294          // Key 0 in $hold_ary are global options, all others are forum_ids
1295   
1296          // We disallow copying admin permissions
1297          foreach ($this->acl_options['global'] as $opt => $id)
1298          {
1299              if (strpos($opt, 'a_') === 0)
1300              {
1301                  $hold_ary[0][$this->acl_options['id'][$opt]] = ACL_NEVER;
1302              }
1303          }
1304   
1305          // Force a_switchperm to be allowed
1306          $hold_ary[0][$this->acl_options['id']['a_switchperm']] = ACL_YES;
1307   
1308          $user_permissions = $this->build_bitstring($hold_ary);
1309   
1310          if (!$user_permissions)
1311          {
1312              return false;
1313          }
1314   
1315          $sql = 'UPDATE ' . USERS_TABLE . "
1316              SET user_permissions = '" . $db->sql_escape($user_permissions) . "',
1317                  user_perm_from = $from_user_id
1318              WHERE user_id = " . $to_user_id;
1319          $db->sql_query($sql);
1320   
1321          return true;
1322      }
1323  }
1324