PageRenderTime 53ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/acp/auth.php

https://bitbucket.org/jablonski/yebood
PHP | 1285 lines | 929 code | 200 blank | 156 comment | 180 complexity | 56a0e7bf222f375263397ed168e92b8d MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. /**
  3. *
  4. * @package phpBB3
  5. * @version $Id$
  6. * @copyright (c) 2005 phpBB Group
  7. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  8. *
  9. */
  10. /**
  11. * @ignore
  12. */
  13. if (!defined('IN_PHPBB'))
  14. {
  15. exit;
  16. }
  17. /**
  18. * ACP Permission/Auth class
  19. * @package phpBB3
  20. */
  21. class auth_admin extends auth
  22. {
  23. /**
  24. * Init auth settings
  25. */
  26. function auth_admin()
  27. {
  28. global $db, $cache;
  29. if (($this->acl_options = $cache->get('_acl_options')) === false)
  30. {
  31. $sql = 'SELECT auth_option_id, auth_option, is_global, is_local
  32. FROM ' . ACL_OPTIONS_TABLE . '
  33. ORDER BY auth_option_id';
  34. $result = $db->sql_query($sql);
  35. $global = $local = 0;
  36. $this->acl_options = array();
  37. while ($row = $db->sql_fetchrow($result))
  38. {
  39. if ($row['is_global'])
  40. {
  41. $this->acl_options['global'][$row['auth_option']] = $global++;
  42. }
  43. if ($row['is_local'])
  44. {
  45. $this->acl_options['local'][$row['auth_option']] = $local++;
  46. }
  47. $this->acl_options['id'][$row['auth_option']] = (int) $row['auth_option_id'];
  48. $this->acl_options['option'][(int) $row['auth_option_id']] = $row['auth_option'];
  49. }
  50. $db->sql_freeresult($result);
  51. $cache->put('_acl_options', $this->acl_options);
  52. }
  53. }
  54. /**
  55. * Get permission mask
  56. * This function only supports getting permissions of one type (for example a_)
  57. *
  58. * @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
  59. * @param mixed $user_id user ids to search for (a user_id or a group_id has to be specified at least)
  60. * @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)
  61. * @param mixed $forum_id forum_ids to search for. Defining a forum id also means getting local settings
  62. * @param string $auth_option the auth_option defines the permission setting to look for (a_ for example)
  63. * @param local|global $scope the scope defines the permission scope. If local, a forum_id is additionally required
  64. * @param ACL_NEVER|ACL_NO|ACL_YES $acl_fill defines the mode those permissions not set are getting filled with
  65. */
  66. function get_mask($mode, $user_id = false, $group_id = false, $forum_id = false, $auth_option = false, $scope = false, $acl_fill = ACL_NEVER)
  67. {
  68. global $db, $user;
  69. $hold_ary = array();
  70. $view_user_mask = ($mode == 'view' && $group_id === false) ? true : false;
  71. if ($auth_option === false || $scope === false)
  72. {
  73. return array();
  74. }
  75. $acl_user_function = ($mode == 'set') ? 'acl_user_raw_data' : 'acl_raw_data';
  76. if (!$view_user_mask)
  77. {
  78. if ($forum_id !== false)
  79. {
  80. $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);
  81. }
  82. else
  83. {
  84. $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);
  85. }
  86. }
  87. // Make sure hold_ary is filled with every setting (prevents missing forums/users/groups)
  88. $ug_id = ($group_id !== false) ? ((!is_array($group_id)) ? array($group_id) : $group_id) : ((!is_array($user_id)) ? array($user_id) : $user_id);
  89. $forum_ids = ($forum_id !== false) ? ((!is_array($forum_id)) ? array($forum_id) : $forum_id) : (($scope == 'global') ? array(0) : array());
  90. // Only those options we need
  91. $compare_options = array_diff(preg_replace('/^((?!' . $auth_option . ').+)|(' . $auth_option . ')$/', '', array_keys($this->acl_options[$scope])), array(''));
  92. // If forum_ids is false and the scope is local we actually want to have all forums within the array
  93. if ($scope == 'local' && !sizeof($forum_ids))
  94. {
  95. $sql = 'SELECT forum_id
  96. FROM ' . FORUMS_TABLE;
  97. $result = $db->sql_query($sql, 120);
  98. while ($row = $db->sql_fetchrow($result))
  99. {
  100. $forum_ids[] = (int) $row['forum_id'];
  101. }
  102. $db->sql_freeresult($result);
  103. }
  104. if ($view_user_mask)
  105. {
  106. $auth2 = null;
  107. $sql = 'SELECT user_id, user_permissions, user_type
  108. FROM ' . USERS_TABLE . '
  109. WHERE ' . $db->sql_in_set('user_id', $ug_id);
  110. $result = $db->sql_query($sql);
  111. while ($userdata = $db->sql_fetchrow($result))
  112. {
  113. if ($user->data['user_id'] != $userdata['user_id'])
  114. {
  115. $auth2 = new auth();
  116. $auth2->acl($userdata);
  117. }
  118. else
  119. {
  120. global $auth;
  121. $auth2 = &$auth;
  122. }
  123. $hold_ary[$userdata['user_id']] = array();
  124. foreach ($forum_ids as $f_id)
  125. {
  126. $hold_ary[$userdata['user_id']][$f_id] = array();
  127. foreach ($compare_options as $option)
  128. {
  129. $hold_ary[$userdata['user_id']][$f_id][$option] = $auth2->acl_get($option, $f_id);
  130. }
  131. }
  132. }
  133. $db->sql_freeresult($result);
  134. unset($userdata);
  135. unset($auth2);
  136. }
  137. foreach ($ug_id as $_id)
  138. {
  139. if (!isset($hold_ary[$_id]))
  140. {
  141. $hold_ary[$_id] = array();
  142. }
  143. foreach ($forum_ids as $f_id)
  144. {
  145. if (!isset($hold_ary[$_id][$f_id]))
  146. {
  147. $hold_ary[$_id][$f_id] = array();
  148. }
  149. }
  150. }
  151. // Now, we need to fill the gaps with $acl_fill. ;)
  152. // Now switch back to keys
  153. if (sizeof($compare_options))
  154. {
  155. $compare_options = array_combine($compare_options, array_fill(1, sizeof($compare_options), $acl_fill));
  156. }
  157. // Defining the user-function here to save some memory
  158. $return_acl_fill = create_function('$value', 'return ' . $acl_fill . ';');
  159. // Actually fill the gaps
  160. if (sizeof($hold_ary))
  161. {
  162. foreach ($hold_ary as $ug_id => $row)
  163. {
  164. foreach ($row as $id => $options)
  165. {
  166. // Do not include the global auth_option
  167. unset($options[$auth_option]);
  168. // Not a "fine" solution, but at all it's a 1-dimensional
  169. // array_diff_key function filling the resulting array values with zeros
  170. // The differences get merged into $hold_ary (all permissions having $acl_fill set)
  171. $hold_ary[$ug_id][$id] = array_merge($options,
  172. array_map($return_acl_fill,
  173. array_flip(
  174. array_diff(
  175. array_keys($compare_options), array_keys($options)
  176. )
  177. )
  178. )
  179. );
  180. }
  181. }
  182. }
  183. else
  184. {
  185. $hold_ary[($group_id !== false) ? $group_id : $user_id][(int) $forum_id] = $compare_options;
  186. }
  187. return $hold_ary;
  188. }
  189. /**
  190. * Get permission mask for roles
  191. * This function only supports getting masks for one role
  192. */
  193. function get_role_mask($role_id)
  194. {
  195. global $db;
  196. $hold_ary = array();
  197. // Get users having this role set...
  198. $sql = 'SELECT user_id, forum_id
  199. FROM ' . ACL_USERS_TABLE . '
  200. WHERE auth_role_id = ' . $role_id . '
  201. ORDER BY forum_id';
  202. $result = $db->sql_query($sql);
  203. while ($row = $db->sql_fetchrow($result))
  204. {
  205. $hold_ary[$row['forum_id']]['users'][] = $row['user_id'];
  206. }
  207. $db->sql_freeresult($result);
  208. // Now grab groups...
  209. $sql = 'SELECT group_id, forum_id
  210. FROM ' . ACL_GROUPS_TABLE . '
  211. WHERE auth_role_id = ' . $role_id . '
  212. ORDER BY forum_id';
  213. $result = $db->sql_query($sql);
  214. while ($row = $db->sql_fetchrow($result))
  215. {
  216. $hold_ary[$row['forum_id']]['groups'][] = $row['group_id'];
  217. }
  218. $db->sql_freeresult($result);
  219. return $hold_ary;
  220. }
  221. /**
  222. * Display permission mask (assign to template)
  223. */
  224. function display_mask($mode, $permission_type, &$hold_ary, $user_mode = 'user', $local = false, $group_display = true)
  225. {
  226. global $template, $user, $db, $phpbb_root_path, $phpEx;
  227. // Define names for template loops, might be able to be set
  228. $tpl_pmask = 'p_mask';
  229. $tpl_fmask = 'f_mask';
  230. $tpl_category = 'category';
  231. $tpl_mask = 'mask';
  232. $l_acl_type = (isset($user->lang['ACL_TYPE_' . (($local) ? 'LOCAL' : 'GLOBAL') . '_' . strtoupper($permission_type)])) ? $user->lang['ACL_TYPE_' . (($local) ? 'LOCAL' : 'GLOBAL') . '_' . strtoupper($permission_type)] : 'ACL_TYPE_' . (($local) ? 'LOCAL' : 'GLOBAL') . '_' . strtoupper($permission_type);
  233. // Allow trace for viewing permissions and in user mode
  234. $show_trace = ($mode == 'view' && $user_mode == 'user') ? true : false;
  235. // Get names
  236. if ($user_mode == 'user')
  237. {
  238. $sql = 'SELECT user_id as ug_id, username as ug_name
  239. FROM ' . USERS_TABLE . '
  240. WHERE ' . $db->sql_in_set('user_id', array_keys($hold_ary)) . '
  241. ORDER BY username_clean ASC';
  242. }
  243. else
  244. {
  245. $sql = 'SELECT group_id as ug_id, group_name as ug_name, group_type
  246. FROM ' . GROUPS_TABLE . '
  247. WHERE ' . $db->sql_in_set('group_id', array_keys($hold_ary)) . '
  248. ORDER BY group_type DESC, group_name ASC';
  249. }
  250. $result = $db->sql_query($sql);
  251. $ug_names_ary = array();
  252. while ($row = $db->sql_fetchrow($result))
  253. {
  254. $ug_names_ary[$row['ug_id']] = ($user_mode == 'user') ? $row['ug_name'] : (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['ug_name']] : $row['ug_name']);
  255. }
  256. $db->sql_freeresult($result);
  257. // Get used forums
  258. $forum_ids = array();
  259. foreach ($hold_ary as $ug_id => $row)
  260. {
  261. $forum_ids = array_merge($forum_ids, array_keys($row));
  262. }
  263. $forum_ids = array_unique($forum_ids);
  264. $forum_names_ary = array();
  265. if ($local)
  266. {
  267. $forum_names_ary = make_forum_select(false, false, true, false, false, false, true);
  268. // Remove the disabled ones, since we do not create an option field here...
  269. foreach ($forum_names_ary as $key => $value)
  270. {
  271. if (!$value['disabled'])
  272. {
  273. continue;
  274. }
  275. unset($forum_names_ary[$key]);
  276. }
  277. }
  278. else
  279. {
  280. $forum_names_ary[0] = $l_acl_type;
  281. }
  282. // Get available roles
  283. $sql = 'SELECT *
  284. FROM ' . ACL_ROLES_TABLE . "
  285. WHERE role_type = '" . $db->sql_escape($permission_type) . "'
  286. ORDER BY role_order ASC";
  287. $result = $db->sql_query($sql);
  288. $roles = array();
  289. while ($row = $db->sql_fetchrow($result))
  290. {
  291. $roles[$row['role_id']] = $row;
  292. }
  293. $db->sql_freeresult($result);
  294. $cur_roles = $this->acl_role_data($user_mode, $permission_type, array_keys($hold_ary));
  295. // Build js roles array (role data assignments)
  296. $s_role_js_array = '';
  297. if (sizeof($roles))
  298. {
  299. $s_role_js_array = array();
  300. // Make sure every role (even if empty) has its array defined
  301. foreach ($roles as $_role_id => $null)
  302. {
  303. $s_role_js_array[$_role_id] = "\n" . 'role_options[' . $_role_id . '] = new Array();' . "\n";
  304. }
  305. $sql = 'SELECT r.role_id, o.auth_option, r.auth_setting
  306. FROM ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' o
  307. WHERE o.auth_option_id = r.auth_option_id
  308. AND ' . $db->sql_in_set('r.role_id', array_keys($roles));
  309. $result = $db->sql_query($sql);
  310. while ($row = $db->sql_fetchrow($result))
  311. {
  312. $flag = substr($row['auth_option'], 0, strpos($row['auth_option'], '_') + 1);
  313. if ($flag == $row['auth_option'])
  314. {
  315. continue;
  316. }
  317. $s_role_js_array[$row['role_id']] .= 'role_options[' . $row['role_id'] . '][\'' . addslashes($row['auth_option']) . '\'] = ' . $row['auth_setting'] . '; ';
  318. }
  319. $db->sql_freeresult($result);
  320. $s_role_js_array = implode('', $s_role_js_array);
  321. }
  322. $template->assign_var('S_ROLE_JS_ARRAY', $s_role_js_array);
  323. unset($s_role_js_array);
  324. // Now obtain memberships
  325. $user_groups_default = $user_groups_custom = array();
  326. if ($user_mode == 'user' && $group_display)
  327. {
  328. $sql = 'SELECT group_id, group_name, group_type
  329. FROM ' . GROUPS_TABLE . '
  330. ORDER BY group_type DESC, group_name ASC';
  331. $result = $db->sql_query($sql);
  332. $groups = array();
  333. while ($row = $db->sql_fetchrow($result))
  334. {
  335. $groups[$row['group_id']] = $row;
  336. }
  337. $db->sql_freeresult($result);
  338. $memberships = group_memberships(false, array_keys($hold_ary), false);
  339. // User is not a member of any group? Bad admin, bad bad admin...
  340. if ($memberships)
  341. {
  342. foreach ($memberships as $row)
  343. {
  344. if ($groups[$row['group_id']]['group_type'] == GROUP_SPECIAL)
  345. {
  346. $user_groups_default[$row['user_id']][] = $user->lang['G_' . $groups[$row['group_id']]['group_name']];
  347. }
  348. else
  349. {
  350. $user_groups_custom[$row['user_id']][] = $groups[$row['group_id']]['group_name'];
  351. }
  352. }
  353. }
  354. unset($memberships, $groups);
  355. }
  356. // If we only have one forum id to display or being in local mode and more than one user/group to display,
  357. // we switch the complete interface to group by user/usergroup instead of grouping by forum
  358. // To achieve this, we need to switch the array a bit
  359. if (sizeof($forum_ids) == 1 || ($local && sizeof($ug_names_ary) > 1))
  360. {
  361. $hold_ary_temp = $hold_ary;
  362. $hold_ary = array();
  363. foreach ($hold_ary_temp as $ug_id => $row)
  364. {
  365. foreach ($forum_names_ary as $forum_id => $forum_row)
  366. {
  367. if (isset($row[$forum_id]))
  368. {
  369. $hold_ary[$forum_id][$ug_id] = $row[$forum_id];
  370. }
  371. }
  372. }
  373. unset($hold_ary_temp);
  374. foreach ($hold_ary as $forum_id => $forum_array)
  375. {
  376. $content_array = $categories = array();
  377. $this->build_permission_array($hold_ary[$forum_id], $content_array, $categories, array_keys($ug_names_ary));
  378. $template->assign_block_vars($tpl_pmask, array(
  379. 'NAME' => ($forum_id == 0) ? $forum_names_ary[0] : $forum_names_ary[$forum_id]['forum_name'],
  380. 'PADDING' => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'],
  381. 'CATEGORIES' => implode('</th><th>', $categories),
  382. 'L_ACL_TYPE' => $l_acl_type,
  383. 'S_LOCAL' => ($local) ? true : false,
  384. 'S_GLOBAL' => (!$local) ? true : false,
  385. 'S_NUM_CATS' => sizeof($categories),
  386. 'S_VIEW' => ($mode == 'view') ? true : false,
  387. 'S_NUM_OBJECTS' => sizeof($content_array),
  388. 'S_USER_MODE' => ($user_mode == 'user') ? true : false,
  389. 'S_GROUP_MODE' => ($user_mode == 'group') ? true : false)
  390. );
  391. @reset($content_array);
  392. while (list($ug_id, $ug_array) = each($content_array))
  393. {
  394. // Build role dropdown options
  395. $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0;
  396. $s_role_options = '';
  397. @reset($roles);
  398. while (list($role_id, $role_row) = each($roles))
  399. {
  400. $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']);
  401. $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name'];
  402. $title = ($role_description) ? ' title="' . $role_description . '"' : '';
  403. $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>';
  404. }
  405. if ($s_role_options)
  406. {
  407. $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;
  408. }
  409. if (!$current_role_id && $mode != 'view')
  410. {
  411. $s_custom_permissions = false;
  412. foreach ($ug_array as $key => $value)
  413. {
  414. if ($value['S_NEVER'] || $value['S_YES'])
  415. {
  416. $s_custom_permissions = true;
  417. break;
  418. }
  419. }
  420. }
  421. else
  422. {
  423. $s_custom_permissions = false;
  424. }
  425. $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array(
  426. 'NAME' => $ug_names_ary[$ug_id],
  427. 'S_ROLE_OPTIONS' => $s_role_options,
  428. 'UG_ID' => $ug_id,
  429. 'S_CUSTOM' => $s_custom_permissions,
  430. 'FORUM_ID' => $forum_id)
  431. );
  432. $this->assign_cat_array($ug_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, $show_trace, ($mode == 'view'));
  433. unset($content_array[$ug_id]);
  434. }
  435. unset($hold_ary[$forum_id]);
  436. }
  437. }
  438. else
  439. {
  440. foreach ($ug_names_ary as $ug_id => $ug_name)
  441. {
  442. if (!isset($hold_ary[$ug_id]))
  443. {
  444. continue;
  445. }
  446. $content_array = $categories = array();
  447. $this->build_permission_array($hold_ary[$ug_id], $content_array, $categories, array_keys($forum_names_ary));
  448. $template->assign_block_vars($tpl_pmask, array(
  449. 'NAME' => $ug_name,
  450. 'CATEGORIES' => implode('</th><th>', $categories),
  451. 'USER_GROUPS_DEFAULT' => ($user_mode == 'user' && isset($user_groups_default[$ug_id]) && sizeof($user_groups_default[$ug_id])) ? implode(', ', $user_groups_default[$ug_id]) : '',
  452. 'USER_GROUPS_CUSTOM' => ($user_mode == 'user' && isset($user_groups_custom[$ug_id]) && sizeof($user_groups_custom[$ug_id])) ? implode(', ', $user_groups_custom[$ug_id]) : '',
  453. 'L_ACL_TYPE' => $l_acl_type,
  454. 'S_LOCAL' => ($local) ? true : false,
  455. 'S_GLOBAL' => (!$local) ? true : false,
  456. 'S_NUM_CATS' => sizeof($categories),
  457. 'S_VIEW' => ($mode == 'view') ? true : false,
  458. 'S_NUM_OBJECTS' => sizeof($content_array),
  459. 'S_USER_MODE' => ($user_mode == 'user') ? true : false,
  460. 'S_GROUP_MODE' => ($user_mode == 'group') ? true : false)
  461. );
  462. @reset($content_array);
  463. while (list($forum_id, $forum_array) = each($content_array))
  464. {
  465. // Build role dropdown options
  466. $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0;
  467. $s_role_options = '';
  468. @reset($roles);
  469. while (list($role_id, $role_row) = each($roles))
  470. {
  471. $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']);
  472. $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name'];
  473. $title = ($role_description) ? ' title="' . $role_description . '"' : '';
  474. $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>';
  475. }
  476. if ($s_role_options)
  477. {
  478. $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;
  479. }
  480. if (!$current_role_id && $mode != 'view')
  481. {
  482. $s_custom_permissions = false;
  483. foreach ($forum_array as $key => $value)
  484. {
  485. if ($value['S_NEVER'] || $value['S_YES'])
  486. {
  487. $s_custom_permissions = true;
  488. break;
  489. }
  490. }
  491. }
  492. else
  493. {
  494. $s_custom_permissions = false;
  495. }
  496. $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array(
  497. 'NAME' => ($forum_id == 0) ? $forum_names_ary[0] : $forum_names_ary[$forum_id]['forum_name'],
  498. 'PADDING' => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'],
  499. 'S_ROLE_OPTIONS' => $s_role_options,
  500. 'S_CUSTOM' => $s_custom_permissions,
  501. 'UG_ID' => $ug_id,
  502. 'FORUM_ID' => $forum_id)
  503. );
  504. $this->assign_cat_array($forum_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, $show_trace, ($mode == 'view'));
  505. }
  506. unset($hold_ary[$ug_id], $ug_names_ary[$ug_id]);
  507. }
  508. }
  509. }
  510. /**
  511. * Display permission mask for roles
  512. */
  513. function display_role_mask(&$hold_ary)
  514. {
  515. global $db, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx;
  516. if (!sizeof($hold_ary))
  517. {
  518. return;
  519. }
  520. // Get forum names
  521. $sql = 'SELECT forum_id, forum_name
  522. FROM ' . FORUMS_TABLE . '
  523. WHERE ' . $db->sql_in_set('forum_id', array_keys($hold_ary)) . '
  524. ORDER BY left_id';
  525. $result = $db->sql_query($sql);
  526. // If the role is used globally, then reflect that
  527. $forum_names = (isset($hold_ary[0])) ? array(0 => '') : array();
  528. while ($row = $db->sql_fetchrow($result))
  529. {
  530. $forum_names[$row['forum_id']] = $row['forum_name'];
  531. }
  532. $db->sql_freeresult($result);
  533. foreach ($forum_names as $forum_id => $forum_name)
  534. {
  535. $auth_ary = $hold_ary[$forum_id];
  536. $template->assign_block_vars('role_mask', array(
  537. 'NAME' => ($forum_id == 0) ? $user->lang['GLOBAL_MASK'] : $forum_name,
  538. 'FORUM_ID' => $forum_id)
  539. );
  540. if (isset($auth_ary['users']) && sizeof($auth_ary['users']))
  541. {
  542. $sql = 'SELECT user_id, username
  543. FROM ' . USERS_TABLE . '
  544. WHERE ' . $db->sql_in_set('user_id', $auth_ary['users']) . '
  545. ORDER BY username_clean ASC';
  546. $result = $db->sql_query($sql);
  547. while ($row = $db->sql_fetchrow($result))
  548. {
  549. $template->assign_block_vars('role_mask.users', array(
  550. 'USER_ID' => $row['user_id'],
  551. 'USERNAME' => $row['username'],
  552. 'U_PROFILE' => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=viewprofile&amp;u={$row['user_id']}"))
  553. );
  554. }
  555. $db->sql_freeresult($result);
  556. }
  557. if (isset($auth_ary['groups']) && sizeof($auth_ary['groups']))
  558. {
  559. $sql = 'SELECT group_id, group_name, group_type
  560. FROM ' . GROUPS_TABLE . '
  561. WHERE ' . $db->sql_in_set('group_id', $auth_ary['groups']) . '
  562. ORDER BY group_type ASC, group_name';
  563. $result = $db->sql_query($sql);
  564. while ($row = $db->sql_fetchrow($result))
  565. {
  566. $template->assign_block_vars('role_mask.groups', array(
  567. 'GROUP_ID' => $row['group_id'],
  568. 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'],
  569. 'U_PROFILE' => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=group&amp;g={$row['group_id']}"))
  570. );
  571. }
  572. $db->sql_freeresult($result);
  573. }
  574. }
  575. }
  576. /**
  577. * NOTE: this function is not in use atm
  578. * Add a new option to the list ... $options is a hash of form ->
  579. * $options = array(
  580. * 'local' => array('option1', 'option2', ...),
  581. * 'global' => array('optionA', 'optionB', ...)
  582. * );
  583. */
  584. function acl_add_option($options)
  585. {
  586. global $db, $cache;
  587. if (!is_array($options))
  588. {
  589. return false;
  590. }
  591. $cur_options = array();
  592. // Determine current options
  593. $sql = 'SELECT auth_option, is_global, is_local
  594. FROM ' . ACL_OPTIONS_TABLE . '
  595. ORDER BY auth_option_id';
  596. $result = $db->sql_query($sql);
  597. while ($row = $db->sql_fetchrow($result))
  598. {
  599. $cur_options[$row['auth_option']] = ($row['is_global'] && $row['is_local']) ? 'both' : (($row['is_global']) ? 'global' : 'local');
  600. }
  601. $db->sql_freeresult($result);
  602. // Here we need to insert new options ... this requires discovering whether
  603. // an options is global, local or both and whether we need to add an permission
  604. // set flag (x_)
  605. $new_options = array('local' => array(), 'global' => array());
  606. foreach ($options as $type => $option_ary)
  607. {
  608. $option_ary = array_unique($option_ary);
  609. foreach ($option_ary as $option_value)
  610. {
  611. $new_options[$type][] = $option_value;
  612. $flag = substr($option_value, 0, strpos($option_value, '_') + 1);
  613. if (!in_array($flag, $new_options[$type]))
  614. {
  615. $new_options[$type][] = $flag;
  616. }
  617. }
  618. }
  619. unset($options);
  620. $options = array();
  621. $options['local'] = array_diff($new_options['local'], $new_options['global']);
  622. $options['global'] = array_diff($new_options['global'], $new_options['local']);
  623. $options['both'] = array_intersect($new_options['local'], $new_options['global']);
  624. // Now check which options to add/update
  625. $add_options = $update_options = array();
  626. // First local ones...
  627. foreach ($options as $type => $option_ary)
  628. {
  629. foreach ($option_ary as $option)
  630. {
  631. if (!isset($cur_options[$option]))
  632. {
  633. $add_options[] = array(
  634. 'auth_option' => (string) $option,
  635. 'is_global' => ($type == 'global' || $type == 'both') ? 1 : 0,
  636. 'is_local' => ($type == 'local' || $type == 'both') ? 1 : 0
  637. );
  638. continue;
  639. }
  640. // Else, update existing entry if it is changed...
  641. if ($type === $cur_options[$option])
  642. {
  643. continue;
  644. }
  645. // New type is always both:
  646. // If is now both, we set both.
  647. // If it was global the new one is local and we need to set it to both
  648. // If it was local the new one is global and we need to set it to both
  649. $update_options[] = $option;
  650. }
  651. }
  652. if (!empty($add_options))
  653. {
  654. $db->sql_multi_insert(ACL_OPTIONS_TABLE, $add_options);
  655. }
  656. if (!empty($update_options))
  657. {
  658. $sql = 'UPDATE ' . ACL_OPTIONS_TABLE . '
  659. SET is_global = 1, is_local = 1
  660. WHERE ' . $db->sql_in_set('auth_option', $update_options);
  661. $db->sql_query($sql);
  662. }
  663. $cache->destroy('_acl_options');
  664. $this->acl_clear_prefetch();
  665. // Because we just changed the options and also purged the options cache, we instantly update/regenerate it for later calls to succeed.
  666. $this->acl_options = array();
  667. $this->auth_admin();
  668. return true;
  669. }
  670. /**
  671. * Set a user or group ACL record
  672. */
  673. function acl_set($ug_type, $forum_id, $ug_id, $auth, $role_id = 0, $clear_prefetch = true)
  674. {
  675. global $db;
  676. // One or more forums
  677. if (!is_array($forum_id))
  678. {
  679. $forum_id = array($forum_id);
  680. }
  681. // One or more users
  682. if (!is_array($ug_id))
  683. {
  684. $ug_id = array($ug_id);
  685. }
  686. $ug_id_sql = $db->sql_in_set($ug_type . '_id', array_map('intval', $ug_id));
  687. $forum_sql = $db->sql_in_set('forum_id', array_map('intval', $forum_id));
  688. // Instead of updating, inserting, removing we just remove all current settings and re-set everything...
  689. $table = ($ug_type == 'user') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE;
  690. $id_field = $ug_type . '_id';
  691. // Get any flags as required
  692. reset($auth);
  693. $flag = key($auth);
  694. $flag = substr($flag, 0, strpos($flag, '_') + 1);
  695. // This ID (the any-flag) is set if one or more permissions are true...
  696. $any_option_id = (int) $this->acl_options['id'][$flag];
  697. // Remove any-flag from auth ary
  698. if (isset($auth[$flag]))
  699. {
  700. unset($auth[$flag]);
  701. }
  702. // Remove current auth options...
  703. $auth_option_ids = array((int)$any_option_id);
  704. foreach ($auth as $auth_option => $auth_setting)
  705. {
  706. $auth_option_ids[] = (int) $this->acl_options['id'][$auth_option];
  707. }
  708. $sql = "DELETE FROM $table
  709. WHERE $forum_sql
  710. AND $ug_id_sql
  711. AND " . $db->sql_in_set('auth_option_id', $auth_option_ids);
  712. $db->sql_query($sql);
  713. // Remove those having a role assigned... the correct type of course...
  714. $sql = 'SELECT role_id
  715. FROM ' . ACL_ROLES_TABLE . "
  716. WHERE role_type = '" . $db->sql_escape($flag) . "'";
  717. $result = $db->sql_query($sql);
  718. $role_ids = array();
  719. while ($row = $db->sql_fetchrow($result))
  720. {
  721. $role_ids[] = $row['role_id'];
  722. }
  723. $db->sql_freeresult($result);
  724. if (sizeof($role_ids))
  725. {
  726. $sql = "DELETE FROM $table
  727. WHERE $forum_sql
  728. AND $ug_id_sql
  729. AND auth_option_id = 0
  730. AND " . $db->sql_in_set('auth_role_id', $role_ids);
  731. $db->sql_query($sql);
  732. }
  733. // Ok, include the any-flag if one or more auth options are set to yes...
  734. foreach ($auth as $auth_option => $setting)
  735. {
  736. if ($setting == ACL_YES && (!isset($auth[$flag]) || $auth[$flag] == ACL_NEVER))
  737. {
  738. $auth[$flag] = ACL_YES;
  739. }
  740. }
  741. $sql_ary = array();
  742. foreach ($forum_id as $forum)
  743. {
  744. $forum = (int) $forum;
  745. if ($role_id)
  746. {
  747. foreach ($ug_id as $id)
  748. {
  749. $sql_ary[] = array(
  750. $id_field => (int) $id,
  751. 'forum_id' => (int) $forum,
  752. 'auth_option_id' => 0,
  753. 'auth_setting' => 0,
  754. 'auth_role_id' => (int) $role_id,
  755. );
  756. }
  757. }
  758. else
  759. {
  760. foreach ($auth as $auth_option => $setting)
  761. {
  762. $auth_option_id = (int) $this->acl_options['id'][$auth_option];
  763. if ($setting != ACL_NO)
  764. {
  765. foreach ($ug_id as $id)
  766. {
  767. $sql_ary[] = array(
  768. $id_field => (int) $id,
  769. 'forum_id' => (int) $forum,
  770. 'auth_option_id' => (int) $auth_option_id,
  771. 'auth_setting' => (int) $setting
  772. );
  773. }
  774. }
  775. }
  776. }
  777. }
  778. $db->sql_multi_insert($table, $sql_ary);
  779. if ($clear_prefetch)
  780. {
  781. $this->acl_clear_prefetch();
  782. }
  783. }
  784. /**
  785. * Set a role-specific ACL record
  786. */
  787. function acl_set_role($role_id, $auth)
  788. {
  789. global $db;
  790. // Get any-flag as required
  791. reset($auth);
  792. $flag = key($auth);
  793. $flag = substr($flag, 0, strpos($flag, '_') + 1);
  794. // Remove any-flag from auth ary
  795. if (isset($auth[$flag]))
  796. {
  797. unset($auth[$flag]);
  798. }
  799. // Re-set any flag...
  800. foreach ($auth as $auth_option => $setting)
  801. {
  802. if ($setting == ACL_YES && (!isset($auth[$flag]) || $auth[$flag] == ACL_NEVER))
  803. {
  804. $auth[$flag] = ACL_YES;
  805. }
  806. }
  807. $sql_ary = array();
  808. foreach ($auth as $auth_option => $setting)
  809. {
  810. $auth_option_id = (int) $this->acl_options['id'][$auth_option];
  811. if ($setting != ACL_NO)
  812. {
  813. $sql_ary[] = array(
  814. 'role_id' => (int) $role_id,
  815. 'auth_option_id' => (int) $auth_option_id,
  816. 'auth_setting' => (int) $setting
  817. );
  818. }
  819. }
  820. // If no data is there, we set the any-flag to ACL_NEVER...
  821. if (!sizeof($sql_ary))
  822. {
  823. $sql_ary[] = array(
  824. 'role_id' => (int) $role_id,
  825. 'auth_option_id' => (int) $this->acl_options['id'][$flag],
  826. 'auth_setting' => ACL_NEVER
  827. );
  828. }
  829. // Remove current auth options...
  830. $sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . '
  831. WHERE role_id = ' . $role_id;
  832. $db->sql_query($sql);
  833. // Now insert the new values
  834. $db->sql_multi_insert(ACL_ROLES_DATA_TABLE, $sql_ary);
  835. $this->acl_clear_prefetch();
  836. }
  837. /**
  838. * Remove local permission
  839. */
  840. function acl_delete($mode, $ug_id = false, $forum_id = false, $permission_type = false)
  841. {
  842. global $db;
  843. if ($ug_id === false && $forum_id === false)
  844. {
  845. return;
  846. }
  847. $option_id_ary = array();
  848. $table = ($mode == 'user') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE;
  849. $id_field = $mode . '_id';
  850. $where_sql = array();
  851. if ($forum_id !== false)
  852. {
  853. $where_sql[] = (!is_array($forum_id)) ? 'forum_id = ' . (int) $forum_id : $db->sql_in_set('forum_id', array_map('intval', $forum_id));
  854. }
  855. if ($ug_id !== false)
  856. {
  857. $where_sql[] = (!is_array($ug_id)) ? $id_field . ' = ' . (int) $ug_id : $db->sql_in_set($id_field, array_map('intval', $ug_id));
  858. }
  859. // There seem to be auth options involved, therefore we need to go through the list and make sure we capture roles correctly
  860. if ($permission_type !== false)
  861. {
  862. // Get permission type
  863. $sql = 'SELECT auth_option, auth_option_id
  864. FROM ' . ACL_OPTIONS_TABLE . "
  865. WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char);
  866. $result = $db->sql_query($sql);
  867. $auth_id_ary = array();
  868. while ($row = $db->sql_fetchrow($result))
  869. {
  870. $option_id_ary[] = $row['auth_option_id'];
  871. $auth_id_ary[$row['auth_option']] = ACL_NO;
  872. }
  873. $db->sql_freeresult($result);
  874. // First of all, lets grab the items having roles with the specified auth options assigned
  875. $sql = "SELECT auth_role_id, $id_field, forum_id
  876. FROM $table, " . ACL_ROLES_TABLE . " r
  877. WHERE auth_role_id <> 0
  878. AND auth_role_id = r.role_id
  879. AND r.role_type = '{$permission_type}'
  880. AND " . implode(' AND ', $where_sql) . '
  881. ORDER BY auth_role_id';
  882. $result = $db->sql_query($sql);
  883. $cur_role_auth = array();
  884. while ($row = $db->sql_fetchrow($result))
  885. {
  886. $cur_role_auth[$row['auth_role_id']][$row['forum_id']][] = $row[$id_field];
  887. }
  888. $db->sql_freeresult($result);
  889. // Get role data for resetting data
  890. if (sizeof($cur_role_auth))
  891. {
  892. $sql = 'SELECT ao.auth_option, rd.role_id, rd.auth_setting
  893. FROM ' . ACL_OPTIONS_TABLE . ' ao, ' . ACL_ROLES_DATA_TABLE . ' rd
  894. WHERE ao.auth_option_id = rd.auth_option_id
  895. AND ' . $db->sql_in_set('rd.role_id', array_keys($cur_role_auth));
  896. $result = $db->sql_query($sql);
  897. $auth_settings = array();
  898. while ($row = $db->sql_fetchrow($result))
  899. {
  900. // We need to fill all auth_options, else setting it will fail...
  901. if (!isset($auth_settings[$row['role_id']]))
  902. {
  903. $auth_settings[$row['role_id']] = $auth_id_ary;
  904. }
  905. $auth_settings[$row['role_id']][$row['auth_option']] = $row['auth_setting'];
  906. }
  907. $db->sql_freeresult($result);
  908. // Set the options
  909. foreach ($cur_role_auth as $role_id => $auth_row)
  910. {
  911. foreach ($auth_row as $f_id => $ug_row)
  912. {
  913. $this->acl_set($mode, $f_id, $ug_row, $auth_settings[$role_id], 0, false);
  914. }
  915. }
  916. }
  917. }
  918. // Now, normally remove permissions...
  919. if ($permission_type !== false)
  920. {
  921. $where_sql[] = $db->sql_in_set('auth_option_id', array_map('intval', $option_id_ary));
  922. }
  923. $sql = "DELETE FROM $table
  924. WHERE " . implode(' AND ', $where_sql);
  925. $db->sql_query($sql);
  926. $this->acl_clear_prefetch();
  927. }
  928. /**
  929. * Assign category to template
  930. * used by display_mask()
  931. */
  932. function assign_cat_array(&$category_array, $tpl_cat, $tpl_mask, $ug_id, $forum_id, $show_trace = false, $s_view)
  933. {
  934. global $template, $user, $phpbb_admin_path, $phpEx;
  935. @reset($category_array);
  936. while (list($cat, $cat_array) = each($category_array))
  937. {
  938. $template->assign_block_vars($tpl_cat, array(
  939. 'S_YES' => ($cat_array['S_YES'] && !$cat_array['S_NEVER'] && !$cat_array['S_NO']) ? true : false,
  940. 'S_NEVER' => ($cat_array['S_NEVER'] && !$cat_array['S_YES'] && !$cat_array['S_NO']) ? true : false,
  941. 'S_NO' => ($cat_array['S_NO'] && !$cat_array['S_NEVER'] && !$cat_array['S_YES']) ? true : false,
  942. 'CAT_NAME' => $user->lang['permission_cat'][$cat])
  943. );
  944. /* Sort permissions by name (more naturaly and user friendly than sorting by a primary key)
  945. * Commented out due to it's memory consumption and time needed
  946. *
  947. $key_array = array_intersect(array_keys($user->lang), array_map(create_function('$a', 'return "acl_" . $a;'), array_keys($cat_array['permissions'])));
  948. $values_array = $cat_array['permissions'];
  949. $cat_array['permissions'] = array();
  950. foreach ($key_array as $key)
  951. {
  952. $key = str_replace('acl_', '', $key);
  953. $cat_array['permissions'][$key] = $values_array[$key];
  954. }
  955. unset($key_array, $values_array);
  956. */
  957. @reset($cat_array['permissions']);
  958. while (list($permission, $allowed) = each($cat_array['permissions']))
  959. {
  960. if ($s_view)
  961. {
  962. $template->assign_block_vars($tpl_cat . '.' . $tpl_mask, array(
  963. 'S_YES' => ($allowed == ACL_YES) ? true : false,
  964. 'S_NEVER' => ($allowed == ACL_NEVER) ? true : false,
  965. 'UG_ID' => $ug_id,
  966. 'FORUM_ID' => $forum_id,
  967. 'FIELD_NAME' => $permission,
  968. 'S_FIELD_NAME' => 'setting[' . $ug_id . '][' . $forum_id . '][' . $permission . ']',
  969. '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") : '',
  970. 'UA_TRACE' => ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission", false) : '',
  971. 'PERMISSION' => $user->lang['acl_' . $permission]['lang'])
  972. );
  973. }
  974. else
  975. {
  976. $template->assign_block_vars($tpl_cat . '.' . $tpl_mask, array(
  977. 'S_YES' => ($allowed == ACL_YES) ? true : false,
  978. 'S_NEVER' => ($allowed == ACL_NEVER) ? true : false,
  979. 'S_NO' => ($allowed == ACL_NO) ? true : false,
  980. 'UG_ID' => $ug_id,
  981. 'FORUM_ID' => $forum_id,
  982. 'FIELD_NAME' => $permission,
  983. 'S_FIELD_NAME' => 'setting[' . $ug_id . '][' . $forum_id . '][' . $permission . ']',
  984. '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") : '',
  985. 'UA_TRACE' => ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission", false) : '',
  986. 'PERMISSION' => $user->lang['acl_' . $permission]['lang'])
  987. );
  988. }
  989. }
  990. }
  991. }
  992. /**
  993. * Building content array from permission rows with explicit key ordering
  994. * used by display_mask()
  995. */
  996. function build_permission_array(&$permission_row, &$content_array, &$categories, $key_sort_array)
  997. {
  998. global $user;
  999. foreach ($key_sort_array as $forum_id)
  1000. {
  1001. if (!isset($permission_row[$forum_id]))
  1002. {
  1003. continue;
  1004. }
  1005. $permissions = $permission_row[$forum_id];
  1006. ksort($permissions);
  1007. @reset($permissions);
  1008. while (list($permission, $auth_setting) = each($permissions))
  1009. {
  1010. if (!isset($user->lang['acl_' . $permission]))
  1011. {
  1012. $user->lang['acl_' . $permission] = array(
  1013. 'cat' => 'misc',
  1014. 'lang' => '{ acl_' . $permission . ' }'
  1015. );
  1016. }
  1017. $cat = $user->lang['acl_' . $permission]['cat'];
  1018. // Build our categories array
  1019. if (!isset($categories[$cat]))
  1020. {
  1021. $categories[$cat] = $user->lang['permission_cat'][$cat];
  1022. }
  1023. // Build our content array
  1024. if (!isset($content_array[$forum_id]))
  1025. {
  1026. $content_array[$forum_id] = array();
  1027. }
  1028. if (!isset($content_array[$forum_id][$cat]))
  1029. {
  1030. $content_array[$forum_id][$cat] = array(
  1031. 'S_YES' => false,
  1032. 'S_NEVER' => false,
  1033. 'S_NO' => false,
  1034. 'permissions' => array(),
  1035. );
  1036. }
  1037. $content_array[$forum_id][$cat]['S_YES'] |= ($auth_setting == ACL_YES) ? true : false;
  1038. $content_array[$forum_id][$cat]['S_NEVER'] |= ($auth_setting == ACL_NEVER) ? true : false;
  1039. $content_array[$forum_id][$cat]['S_NO'] |= ($auth_setting == ACL_NO) ? true : false;
  1040. $content_array[$forum_id][$cat]['permissions'][$permission] = $auth_setting;
  1041. }
  1042. }
  1043. }
  1044. /**
  1045. * Use permissions from another user. This transferes a permission set from one user to another.
  1046. * The other user is always able to revert back to his permission set.
  1047. * This function does not check for lower/higher permissions, it is possible for the user to gain
  1048. * "more" permissions by this.
  1049. * Admin permissions will not be copied.
  1050. */
  1051. function ghost_permissions($from_user_id, $to_user_id)
  1052. {
  1053. global $db;
  1054. if ($to_user_id == ANONYMOUS)
  1055. {
  1056. return false;
  1057. }
  1058. $hold_ary = $this->acl_raw_data_single_user($from_user_id);
  1059. // Key 0 in $hold_ary are global options, all others are forum_ids
  1060. // We disallow copying admin permissions
  1061. foreach ($this->acl_options['global'] as $opt => $id)
  1062. {
  1063. if (strpos($opt, 'a_') === 0)
  1064. {
  1065. $hold_ary[0][$this->acl_options['id'][$opt]] = ACL_NEVER;
  1066. }
  1067. }
  1068. // Force a_switchperm to be allowed
  1069. $hold_ary[0][$this->acl_options['id']['a_switchperm']] = ACL_YES;
  1070. $user_permissions = $this->build_bitstring($hold_ary);
  1071. if (!$user_permissions)
  1072. {
  1073. return false;
  1074. }
  1075. $sql = 'UPDATE ' . USERS_TABLE . "
  1076. SET user_permissions = '" . $db->sql_escape($user_permissions) . "',
  1077. user_perm_from = $from_user_id
  1078. WHERE user_id = " . $to_user_id;
  1079. $db->sql_query($sql);
  1080. return true;
  1081. }
  1082. }
  1083. ?>